nukak
Version:
flexible and efficient ORM, with declarative JSON syntax and smart type-safety
650 lines • 99.3 kB
JavaScript
import { getMeta } from '../entity/index.js';
import { QueryRaw, } from '../type/index.js';
import { buildSortMap, buldQueryWhereAsMap, escapeSqlId, fillOnFields, filterFieldKeys, filterRelationKeys, flatObject, getFieldCallbackValue, getFieldKeys, getKeys, hasKeys, isSelectingRelations, raw, } from '../util/index.js';
import { AbstractDialect } from './abstractDialect.js';
import { SqlQueryContext } from './queryContext.js';
export class AbstractSqlDialect extends AbstractDialect {
escapeIdChar;
beginTransactionCommand;
commitTransactionCommand;
rollbackTransactionCommand;
constructor(namingStrategy, escapeIdChar = '`', beginTransactionCommand = 'START TRANSACTION', commitTransactionCommand = 'COMMIT', rollbackTransactionCommand = 'ROLLBACK') {
super(namingStrategy);
this.escapeIdChar = escapeIdChar;
this.beginTransactionCommand = beginTransactionCommand;
this.commitTransactionCommand = commitTransactionCommand;
this.rollbackTransactionCommand = rollbackTransactionCommand;
}
createContext() {
return new SqlQueryContext(this);
}
addValue(values, value) {
values.push(value ?? null);
return this.placeholder(values.length);
}
placeholder(_index) {
return '?';
}
returningId(entity) {
const meta = getMeta(entity);
const idName = this.resolveColumnName(meta.id, meta.fields[meta.id]);
return `RETURNING ${this.escapeId(idName)} ${this.escapeId('id')}`;
}
search(ctx, entity, q = {}, opts = {}) {
const meta = getMeta(entity);
const tableName = this.resolveTableName(entity, meta);
const prefix = (opts.prefix ?? (opts.autoPrefix || isSelectingRelations(meta, q.$select))) ? tableName : undefined;
opts = { ...opts, prefix };
this.where(ctx, entity, q.$where, opts);
this.sort(ctx, entity, q.$sort, opts);
this.pager(ctx, q);
}
selectFields(ctx, entity, select, opts = {}) {
const meta = getMeta(entity);
const prefix = opts.prefix ? opts.prefix + '.' : '';
const escapedPrefix = this.escapeId(opts.prefix, true, true);
let selectArr;
if (select) {
if (Array.isArray(select)) {
selectArr = select;
}
else {
const selectPositive = getKeys(select).filter((it) => select[it]);
selectArr = selectPositive.length
? selectPositive
: getFieldKeys(meta.fields).filter((it) => !(it in select));
}
selectArr = selectArr.filter((it) => it instanceof QueryRaw || it in meta.fields);
if (opts.prefix && !selectArr.includes(meta.id)) {
selectArr = [meta.id, ...selectArr];
}
}
else {
selectArr = getFieldKeys(meta.fields);
}
if (!selectArr.length) {
ctx.append(escapedPrefix + '*');
return;
}
selectArr.forEach((key, index) => {
if (index > 0)
ctx.append(', ');
if (key instanceof QueryRaw) {
this.getRawValue(ctx, {
value: key,
prefix: opts.prefix,
escapedPrefix,
autoPrefixAlias: opts.autoPrefixAlias,
});
}
else {
const field = meta.fields[key];
const columnName = this.resolveColumnName(key, field);
if (field.virtual) {
this.getRawValue(ctx, {
value: raw(field.virtual.value, key),
prefix: opts.prefix,
escapedPrefix,
autoPrefixAlias: opts.autoPrefixAlias,
});
}
else {
ctx.append(escapedPrefix + this.escapeId(columnName));
}
if (!field.virtual && (columnName !== key || opts.autoPrefixAlias)) {
const aliasStr = (prefix + key);
// Replace dots with underscores for alias to avoid syntax errors
const safeAlias = aliasStr.replace(/\./g, '_');
ctx.append(' ' + this.escapeId(safeAlias, true));
}
}
});
}
select(ctx, entity, select, opts = {}) {
const meta = getMeta(entity);
const tableName = this.resolveTableName(entity, meta);
const prefix = (opts.prefix ?? (opts.autoPrefix || isSelectingRelations(meta, select))) ? tableName : undefined;
ctx.append('SELECT ');
this.selectFields(ctx, entity, select, { prefix });
// Add related fields BEFORE FROM clause
this.selectRelationFields(ctx, entity, select, { prefix });
ctx.append(` FROM ${this.escapeId(tableName)}`);
// Add JOINs AFTER FROM clause
this.selectRelationJoins(ctx, entity, select, { prefix });
}
selectRelationFields(ctx, entity, select, opts = {}) {
if (Array.isArray(select)) {
return;
}
const meta = getMeta(entity);
const tableName = this.resolveTableName(entity, meta);
const relKeys = filterRelationKeys(meta, select);
const isSelectArray = Array.isArray(select);
const prefix = opts.prefix;
for (const relKey of relKeys) {
const relOpts = meta.relations[relKey];
if (relOpts.cardinality === '1m' || relOpts.cardinality === 'mm') {
continue;
}
const isFirstLevel = prefix === tableName;
const joinRelAlias = isFirstLevel ? relKey : prefix ? prefix + '.' + relKey : relKey;
const relEntity = relOpts.entity();
const relSelect = select[relKey];
const relQuery = isSelectArray ? {} : Array.isArray(relSelect) ? { $select: relSelect } : relSelect;
ctx.append(', ');
this.selectFields(ctx, relEntity, relQuery.$select, {
prefix: joinRelAlias,
autoPrefixAlias: true,
});
// Recursively add nested relation fields
this.selectRelationFields(ctx, relEntity, relQuery.$select, {
prefix: joinRelAlias,
});
}
}
selectRelationJoins(ctx, entity, select, opts = {}) {
if (Array.isArray(select)) {
return;
}
const meta = getMeta(entity);
const tableName = this.resolveTableName(entity, meta);
const relKeys = filterRelationKeys(meta, select);
const isSelectArray = Array.isArray(select);
const prefix = opts.prefix;
for (const relKey of relKeys) {
const relOpts = meta.relations[relKey];
if (relOpts.cardinality === '1m' || relOpts.cardinality === 'mm') {
continue;
}
const isFirstLevel = prefix === tableName;
const joinRelAlias = isFirstLevel ? relKey : prefix ? prefix + '.' + relKey : relKey;
const relEntity = relOpts.entity();
const relSelect = select[relKey];
const relQuery = isSelectArray ? {} : Array.isArray(relSelect) ? { $select: relSelect } : relSelect;
const relMeta = getMeta(relEntity);
const relTableName = this.resolveTableName(relEntity, relMeta);
const relEntityName = this.escapeId(relTableName);
const relPath = prefix ? this.escapeId(prefix, true) : this.escapeId(tableName);
const joinType = relQuery.$required ? 'INNER' : 'LEFT';
const joinAlias = this.escapeId(joinRelAlias, true);
ctx.append(` ${joinType} JOIN ${relEntityName} ${joinAlias} ON `);
ctx.append(relOpts.references
.map((it) => {
const foreignColumnName = this.resolveColumnName(it.foreign, relMeta.fields[it.foreign]);
const localColumnName = this.resolveColumnName(it.local, meta.fields[it.local]);
return `${joinAlias}.${this.escapeId(foreignColumnName)} = ${relPath}.${this.escapeId(localColumnName)}`;
})
.join(' AND '));
if (relQuery.$where) {
ctx.append(' AND ');
this.where(ctx, relEntity, relQuery.$where, { prefix: joinRelAlias, clause: false });
}
// Recursively add nested relation JOINs
this.selectRelationJoins(ctx, relEntity, relQuery.$select, {
prefix: joinRelAlias,
});
}
}
where(ctx, entity, where = {}, opts = {}) {
const meta = getMeta(entity);
const { usePrecedence, clause = 'WHERE', softDelete } = opts;
where = buldQueryWhereAsMap(meta, where);
if (meta.softDelete && (softDelete || softDelete === undefined) && !where[meta.softDelete]) {
where[meta.softDelete] = null;
}
const entries = Object.entries(where);
if (!entries.length) {
return;
}
if (clause) {
ctx.append(` ${clause} `);
}
if (usePrecedence) {
ctx.append('(');
}
entries.forEach(([key, val], index) => {
if (index > 0) {
ctx.append(' AND ');
}
this.compare(ctx, entity, key, val, {
...opts,
usePrecedence: entries.length > 1,
});
});
if (usePrecedence) {
ctx.append(')');
}
}
compare(ctx, entity, key, val, opts = {}) {
const meta = getMeta(entity);
if (val instanceof QueryRaw) {
if (key === '$exists' || key === '$nexists') {
ctx.append(key === '$exists' ? 'EXISTS (' : 'NOT EXISTS (');
const tableName = this.resolveTableName(entity, meta);
this.getRawValue(ctx, {
value: val,
prefix: tableName,
escapedPrefix: this.escapeId(tableName, false, true),
});
ctx.append(')');
return;
}
this.getComparisonKey(ctx, entity, key, opts);
ctx.append(' = ');
this.getRawValue(ctx, { value: val });
return;
}
if (key === '$text') {
const search = val;
const fields = search.$fields.map((fKey) => {
const field = meta.fields[fKey];
const columnName = this.resolveColumnName(fKey, field);
return this.escapeId(columnName);
});
ctx.append(`MATCH(${fields.join(', ')}) AGAINST(`);
ctx.addValue(search.$value);
ctx.append(')');
return;
}
if (key === '$and' || key === '$or' || key === '$not' || key === '$nor') {
const negateOperatorMap = {
$not: '$and',
$nor: '$or',
};
const op = negateOperatorMap[key] ?? key;
const negate = key in negateOperatorMap ? 'NOT' : '';
const valArr = val;
const hasManyItems = valArr.length > 1;
if ((opts.usePrecedence || negate) && hasManyItems) {
ctx.append((negate ? negate + ' ' : '') + '(');
}
else if (negate) {
ctx.append(negate + ' ');
}
valArr.forEach((whereEntry, index) => {
if (index > 0) {
ctx.append(op === '$or' ? ' OR ' : ' AND ');
}
if (whereEntry instanceof QueryRaw) {
this.getRawValue(ctx, {
value: whereEntry,
prefix: opts.prefix,
escapedPrefix: this.escapeId(opts.prefix, true, true),
});
}
else {
this.where(ctx, entity, whereEntry, {
prefix: opts.prefix,
usePrecedence: hasManyItems && !Array.isArray(whereEntry) && getKeys(whereEntry).length > 1,
clause: false,
});
}
});
if ((opts.usePrecedence || negate) && hasManyItems) {
ctx.append(')');
}
return;
}
const value = Array.isArray(val) ? { $in: val } : typeof val === 'object' && val !== null ? val : { $eq: val };
const operators = getKeys(value);
if (operators.length > 1) {
ctx.append('(');
}
operators.forEach((op, index) => {
if (index > 0) {
ctx.append(' AND ');
}
this.compareFieldOperator(ctx, entity, key, op, value[op], opts);
});
if (operators.length > 1) {
ctx.append(')');
}
}
compareFieldOperator(ctx, entity, key, op, val, opts = {}) {
switch (op) {
case '$eq':
this.getComparisonKey(ctx, entity, key, opts);
if (val === null) {
ctx.append(' IS NULL');
}
else {
ctx.append(' = ');
ctx.addValue(val);
}
break;
case '$ne':
this.getComparisonKey(ctx, entity, key, opts);
if (val === null) {
ctx.append(' IS NOT NULL');
}
else {
ctx.append(' <> ');
ctx.addValue(val);
}
break;
case '$not':
ctx.append('NOT (');
this.compare(ctx, entity, key, val, opts);
ctx.append(')');
break;
case '$gt':
this.getComparisonKey(ctx, entity, key, opts);
ctx.append(' > ');
ctx.addValue(val);
break;
case '$gte':
this.getComparisonKey(ctx, entity, key, opts);
ctx.append(' >= ');
ctx.addValue(val);
break;
case '$lt':
this.getComparisonKey(ctx, entity, key, opts);
ctx.append(' < ');
ctx.addValue(val);
break;
case '$lte':
this.getComparisonKey(ctx, entity, key, opts);
ctx.append(' <= ');
ctx.addValue(val);
break;
case '$startsWith':
this.getComparisonKey(ctx, entity, key, opts);
ctx.append(' LIKE ');
ctx.addValue(`${val}%`);
break;
case '$istartsWith':
this.getComparisonKey(ctx, entity, key, opts);
ctx.append(' LIKE ');
ctx.addValue(`${val.toLowerCase()}%`);
break;
case '$endsWith':
this.getComparisonKey(ctx, entity, key, opts);
ctx.append(' LIKE ');
ctx.addValue(`%${val}`);
break;
case '$iendsWith':
this.getComparisonKey(ctx, entity, key, opts);
ctx.append(' LIKE ');
ctx.addValue(`%${val.toLowerCase()}`);
break;
case '$includes':
this.getComparisonKey(ctx, entity, key, opts);
ctx.append(' LIKE ');
ctx.addValue(`%${val}%`);
break;
case '$iincludes':
this.getComparisonKey(ctx, entity, key, opts);
ctx.append(' LIKE ');
ctx.addValue(`%${val.toLowerCase()}%`);
break;
case '$ilike':
this.getComparisonKey(ctx, entity, key, opts);
ctx.append(' LIKE ');
ctx.addValue(val.toLowerCase());
break;
case '$like':
this.getComparisonKey(ctx, entity, key, opts);
ctx.append(' LIKE ');
ctx.addValue(val);
break;
case '$in':
this.getComparisonKey(ctx, entity, key, opts);
if (Array.isArray(val) && val.length > 0) {
ctx.append(' IN (');
this.addValues(ctx, val);
ctx.append(')');
}
else {
ctx.append(' IN (NULL)');
}
break;
case '$nin':
this.getComparisonKey(ctx, entity, key, opts);
if (Array.isArray(val) && val.length > 0) {
ctx.append(' NOT IN (');
this.addValues(ctx, val);
ctx.append(')');
}
else {
ctx.append(' NOT IN (NULL)');
}
break;
case '$regex':
this.getComparisonKey(ctx, entity, key, opts);
ctx.append(' REGEXP ');
ctx.addValue(val);
break;
default:
throw TypeError(`unknown operator: ${op}`);
}
}
addValues(ctx, vals) {
vals.forEach((val, index) => {
if (index > 0) {
ctx.append(', ');
}
ctx.addValue(val);
});
}
getComparisonKey(ctx, entity, key, { prefix } = {}) {
const meta = getMeta(entity);
const escapedPrefix = this.escapeId(prefix, true, true);
const field = meta.fields[key];
if (field?.virtual) {
this.getRawValue(ctx, {
value: field.virtual,
prefix,
escapedPrefix,
});
return;
}
const columnName = this.resolveColumnName(key, field);
ctx.append(escapedPrefix + this.escapeId(columnName));
}
sort(ctx, entity, sort, { prefix }) {
const sortMap = buildSortMap(sort);
if (!hasKeys(sortMap)) {
return;
}
const meta = getMeta(entity);
const flattenedSort = flatObject(sortMap, prefix);
const directionMap = { 1: '', asc: '', '-1': ' DESC', desc: ' DESC' };
ctx.append(' ORDER BY ');
Object.entries(flattenedSort).forEach(([key, sort], index) => {
if (index > 0) {
ctx.append(', ');
}
const field = meta.fields[key];
const name = this.resolveColumnName(key, field);
const direction = directionMap[sort];
ctx.append(this.escapeId(name) + direction);
});
}
pager(ctx, opts) {
if (opts.$limit) {
ctx.append(` LIMIT ${Number(opts.$limit)}`);
}
if (opts.$skip !== undefined) {
ctx.append(` OFFSET ${Number(opts.$skip)}`);
}
}
count(ctx, entity, q, opts) {
const search = { ...q };
delete search.$sort;
this.select(ctx, entity, [raw('COUNT(*)', 'count')], undefined);
this.search(ctx, entity, search, opts);
}
find(ctx, entity, q = {}, opts) {
this.select(ctx, entity, q.$select, opts);
this.search(ctx, entity, q, opts);
}
insert(ctx, entity, payload, opts) {
const meta = getMeta(entity);
const payloads = fillOnFields(meta, payload, 'onInsert');
const keys = filterFieldKeys(meta, payloads[0], 'onInsert');
const columns = keys.map((key) => {
const field = meta.fields[key];
return this.escapeId(this.resolveColumnName(key, field));
});
const tableName = this.resolveTableName(entity, meta);
ctx.append(`INSERT INTO ${this.escapeId(tableName)} (${columns.join(', ')}) VALUES (`);
payloads.forEach((it, recordIndex) => {
if (recordIndex > 0) {
ctx.append('), (');
}
keys.forEach((key, keyIndex) => {
if (keyIndex > 0) {
ctx.append(', ');
}
const field = meta.fields[key];
this.formatPersistableValue(ctx, field, it[key]);
});
});
ctx.append(')');
}
update(ctx, entity, q, payload, opts) {
const meta = getMeta(entity);
const [filledPayload] = fillOnFields(meta, payload, 'onUpdate');
const keys = filterFieldKeys(meta, filledPayload, 'onUpdate');
const tableName = this.resolveTableName(entity, meta);
ctx.append(`UPDATE ${this.escapeId(tableName)} SET `);
keys.forEach((key, index) => {
if (index > 0) {
ctx.append(', ');
}
const field = meta.fields[key];
const columnName = this.resolveColumnName(key, field);
ctx.append(`${this.escapeId(columnName)} = `);
this.formatPersistableValue(ctx, field, filledPayload[key]);
});
this.search(ctx, entity, q, opts);
}
upsert(ctx, entity, conflictPaths, payload) {
const meta = getMeta(entity);
const update = this.getUpsertUpdateAssignments(ctx, meta, conflictPaths, payload, (name) => `VALUES(${name})`);
if (update) {
this.insert(ctx, entity, payload);
ctx.append(` ON DUPLICATE KEY UPDATE ${update}`);
}
else {
const insertCtx = this.createContext();
this.insert(insertCtx, entity, payload);
ctx.append(insertCtx.sql.replace(/^INSERT/, 'INSERT IGNORE'));
insertCtx.values.forEach((val) => {
ctx.pushValue(val);
});
}
}
getUpsertUpdateAssignments(ctx, meta, conflictPaths, payload, callback) {
const [filledPayload] = fillOnFields(meta, payload, 'onUpdate');
const fields = filterFieldKeys(meta, filledPayload, 'onUpdate');
return fields
.filter((col) => !conflictPaths[col])
.map((col) => {
const field = meta.fields[col];
const columnName = this.resolveColumnName(col, field);
if (callback) {
return `${this.escapeId(columnName)} = ${callback(this.escapeId(columnName))}`;
}
const valCtx = this.createContext();
this.formatPersistableValue(valCtx, field, filledPayload[col]);
valCtx.values.forEach((val) => {
ctx.pushValue(val);
});
return `${this.escapeId(columnName)} = ${valCtx.sql}`;
})
.join(', ');
}
getUpsertConflictPathsStr(meta, conflictPaths) {
return getKeys(conflictPaths)
.map((key) => {
const field = meta.fields[key];
const columnName = this.resolveColumnName(key, field);
return this.escapeId(columnName);
})
.join(', ');
}
delete(ctx, entity, q, opts = {}) {
const meta = getMeta(entity);
const tableName = this.resolveTableName(entity, meta);
if (opts.softDelete || opts.softDelete === undefined) {
if (meta.softDelete) {
const field = meta.fields[meta.softDelete];
const value = getFieldCallbackValue(field.onDelete);
const columnName = this.resolveColumnName(meta.softDelete, field);
ctx.append(`UPDATE ${this.escapeId(tableName)} SET ${this.escapeId(columnName)} = `);
ctx.addValue(value);
this.search(ctx, entity, q, opts);
return;
}
if (opts.softDelete) {
throw TypeError(`'${tableName}' has not enabled 'softDelete'`);
}
}
ctx.append(`DELETE FROM ${this.escapeId(tableName)}`);
this.search(ctx, entity, q, opts);
}
escapeId(val, forbidQualified, addDot) {
return escapeSqlId(val, this.escapeIdChar, forbidQualified, addDot);
}
getPersistables(ctx, meta, payload, callbackKey) {
const payloads = fillOnFields(meta, payload, callbackKey);
return payloads.map((it) => this.getPersistable(ctx, meta, it, callbackKey));
}
getPersistable(ctx, meta, payload, callbackKey) {
const filledPayload = fillOnFields(meta, payload, callbackKey)[0];
const keys = filterFieldKeys(meta, filledPayload, callbackKey);
return keys.reduce((acc, key) => {
const field = meta.fields[key];
const valCtx = this.createContext();
this.formatPersistableValue(valCtx, field, filledPayload[key]);
valCtx.values.forEach((val) => {
ctx.pushValue(val);
});
acc[key] = valCtx.sql;
return acc;
}, {});
}
formatPersistableValue(ctx, field, value) {
if (value instanceof QueryRaw) {
this.getRawValue(ctx, { value });
return;
}
if (field?.type === 'json' || field?.type === 'jsonb') {
ctx.addValue(value ? JSON.stringify(value) : null);
return;
}
if (field?.type === 'vector' && Array.isArray(value)) {
ctx.addValue(`[${value.join(',')}]`);
return;
}
ctx.addValue(value);
}
getRawValue(ctx, opts) {
const { value, prefix = '', escapedPrefix, autoPrefixAlias } = opts;
if (typeof value.value === 'function') {
const res = value.value({
...opts,
ctx,
dialect: this,
prefix,
escapedPrefix: escapedPrefix ?? this.escapeId(prefix, true, true),
});
if (typeof res === 'string' || (typeof res === 'number' && !Number.isNaN(res))) {
ctx.append(String(res));
}
}
else {
ctx.append(prefix + String(value.value));
}
const alias = value.alias;
if (alias) {
const fullAlias = autoPrefixAlias ? prefix + alias : alias;
// Replace dots with underscores for alias to avoid syntax errors
const safeAlias = fullAlias.replace(/\./g, '_');
const escapedFullAlias = this.escapeId(safeAlias, true);
ctx.append(' ' + escapedFullAlias);
}
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWJzdHJhY3RTcWxEaWFsZWN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2RpYWxlY3QvYWJzdHJhY3RTcWxEaWFsZWN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUM3QyxPQUFPLEVBWUwsUUFBUSxHQWdCVCxNQUFNLGtCQUFrQixDQUFDO0FBRTFCLE9BQU8sRUFDTCxZQUFZLEVBQ1osbUJBQW1CLEVBRW5CLFdBQVcsRUFDWCxZQUFZLEVBQ1osZUFBZSxFQUNmLGtCQUFrQixFQUNsQixVQUFVLEVBQ1YscUJBQXFCLEVBQ3JCLFlBQVksRUFDWixPQUFPLEVBQ1AsT0FBTyxFQUNQLG9CQUFvQixFQUNwQixHQUFHLEdBQ0osTUFBTSxrQkFBa0IsQ0FBQztBQUUxQixPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDdkQsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBRXBELE1BQU0sT0FBZ0Isa0JBQW1CLFNBQVEsZUFBZTtJQUduRDtJQUNBO0lBQ0E7SUFDQTtJQUxYLFlBQ0UsY0FBK0IsRUFDdEIsZUFBMEIsR0FBRyxFQUM3QiwwQkFBa0MsbUJBQW1CLEVBQ3JELDJCQUFtQyxRQUFRLEVBQzNDLDZCQUFxQyxVQUFVO1FBRXhELEtBQUssQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUxiLGlCQUFZLEdBQVosWUFBWSxDQUFpQjtRQUM3Qiw0QkFBdUIsR0FBdkIsdUJBQXVCLENBQThCO1FBQ3JELDZCQUF3QixHQUF4Qix3QkFBd0IsQ0FBbUI7UUFDM0MsK0JBQTBCLEdBQTFCLDBCQUEwQixDQUFxQjtJQUcxRCxDQUFDO0lBRUQsYUFBYTtRQUNYLE9BQU8sSUFBSSxlQUFlLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDbkMsQ0FBQztJQUVELFFBQVEsQ0FBQyxNQUFpQixFQUFFLEtBQWM7UUFDeEMsTUFBTSxDQUFD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