@travetto/model-sql 7.0.0-rc.1 → 7.0.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,7 +9,7 @@ import { DeleteWrapper, InsertWrapper, DialectState } from '../internal/types.ts
9
9
  import { Connection } from '../connection/base.ts';
10
10
  import { VisitStack } from '../types.ts';
11
11
 
12
- const PointImpl = toConcrete<Point>();
12
+ const PointConcrete = toConcrete<Point>();
13
13
 
14
14
  interface Alias {
15
15
  alias: string;
@@ -39,20 +39,20 @@ export abstract class SQLDialect implements DialectState {
39
39
  /**
40
40
  * Default length of unique ids
41
41
  */
42
- ID_LEN = 32;
42
+ ID_LENGTH = 32;
43
43
 
44
44
  /**
45
45
  * Hash Length
46
46
  */
47
- HASH_LEN = 64;
47
+ HASH_LENGTH = 64;
48
48
 
49
49
  /**
50
50
  * Default length for varchar
51
51
  */
52
- DEFAULT_STRING_LEN = 1024;
52
+ DEFAULT_STRING_LENGTH = 1024;
53
53
 
54
54
  /**
55
- * Mapping between query ops and SQL operations
55
+ * Mapping between query operators and SQL operations
56
56
  */
57
57
  SQL_OPS = {
58
58
  $and: 'AND',
@@ -95,8 +95,8 @@ export abstract class SQLDialect implements DialectState {
95
95
  * Column types with inputs
96
96
  */
97
97
  PARAMETERIZED_COLUMN_TYPES: Record<'VARCHAR' | 'DECIMAL', (...values: number[]) => string> = {
98
- VARCHAR: n => `VARCHAR(${n})`,
99
- DECIMAL: (d, p) => `DECIMAL(${d},${p})`
98
+ VARCHAR: count => `VARCHAR(${count})`,
99
+ DECIMAL: (digits, precision) => `DECIMAL(${digits},${precision})`
100
100
  };
101
101
 
102
102
  ID_AFFIX = '`';
@@ -105,8 +105,8 @@ export abstract class SQLDialect implements DialectState {
105
105
  * Generate an id field
106
106
  */
107
107
  idField = makeField('id', String, true, {
108
- maxlength: { n: this.ID_LEN },
109
- minlength: { n: this.ID_LEN }
108
+ maxlength: { n: this.ID_LENGTH },
109
+ minlength: { n: this.ID_LENGTH }
110
110
  });
111
111
 
112
112
  /**
@@ -118,8 +118,8 @@ export abstract class SQLDialect implements DialectState {
118
118
  * Parent path reference
119
119
  */
120
120
  parentPathField = makeField('__parent_path', String, true, {
121
- maxlength: { n: this.HASH_LEN },
122
- minlength: { n: this.HASH_LEN },
121
+ maxlength: { n: this.HASH_LENGTH },
122
+ minlength: { n: this.HASH_LENGTH },
123
123
  required: { active: true }
124
124
  });
125
125
 
@@ -127,8 +127,8 @@ export abstract class SQLDialect implements DialectState {
127
127
  * Path reference
128
128
  */
129
129
  pathField = makeField('__path', String, true, {
130
- maxlength: { n: this.HASH_LEN },
131
- minlength: { n: this.HASH_LEN },
130
+ maxlength: { n: this.HASH_LENGTH },
131
+ minlength: { n: this.HASH_LENGTH },
132
132
  required: { active: true }
133
133
  });
134
134
 
@@ -137,38 +137,38 @@ export abstract class SQLDialect implements DialectState {
137
137
  rootAlias = '_ROOT';
138
138
 
139
139
  aliasCache = new Map<Class, Map<string, Alias>>();
140
- ns: string;
140
+ namespacePrefix: string;
141
141
 
142
- constructor(ns: string) {
142
+ constructor(namespacePrefix: string) {
143
143
  this.namespace = this.namespace.bind(this);
144
144
  this.table = this.table.bind(this);
145
- this.ident = this.ident.bind(this);
146
- this.ns = ns ? `${ns}_` : ns;
145
+ this.identifier = this.identifier.bind(this);
146
+ this.namespacePrefix = namespacePrefix ? `${namespacePrefix}_` : namespacePrefix;
147
147
  }
148
148
 
149
149
  /**
150
150
  * Get connection
151
151
  */
152
- abstract get conn(): Connection<unknown>;
152
+ abstract get connection(): Connection<unknown>;
153
153
 
154
154
  /**
155
155
  * Hash a value
156
156
  */
157
- abstract hash(inp: string): string;
157
+ abstract hash(input: string): string;
158
158
 
159
159
  executeSQL<T>(sql: string): Promise<{ records: T[], count: number }> {
160
- return this.conn.execute<T>(this.conn.active, sql);
160
+ return this.connection.execute<T>(this.connection.active, sql);
161
161
  }
162
162
 
163
163
  /**
164
164
  * Identify a name or field (escape it)
165
165
  */
166
- ident(field: SchemaFieldConfig | string | symbol): string {
166
+ identifier(field: SchemaFieldConfig | string): string {
167
167
  if (field === '*') {
168
168
  return field;
169
169
  } else {
170
- const name = (typeof field === 'symbol' || typeof field === 'string') ? field : field.name;
171
- return `${this.ID_AFFIX}${name.toString()}${this.ID_AFFIX}`;
170
+ const name = (typeof field === 'string') ? field : field.name;
171
+ return `${this.ID_AFFIX}${name}${this.ID_AFFIX}`;
172
172
  }
173
173
  }
174
174
 
@@ -189,44 +189,44 @@ export abstract class SQLDialect implements DialectState {
189
189
  /**
190
190
  * Convert value to SQL valid representation
191
191
  */
192
- resolveValue(conf: SchemaFieldConfig, value: unknown): string {
192
+ resolveValue(config: SchemaFieldConfig, value: unknown): string {
193
193
  if (value === undefined || value === null) {
194
194
  return 'NULL';
195
- } else if (conf.type === String) {
195
+ } else if (config.type === String) {
196
196
  if (value instanceof RegExp) {
197
- const src = DataUtil.toRegex(value).source.replace(/\\b/g, this.regexWordBoundary);
198
- return this.quote(src);
197
+ const regexSource = DataUtil.toRegex(value).source.replace(/\\b/g, this.regexWordBoundary);
198
+ return this.quote(regexSource);
199
199
  } else {
200
200
  return this.quote(castTo(value));
201
201
  }
202
- } else if (conf.type === Boolean) {
202
+ } else if (config.type === Boolean) {
203
203
  return `${value ? 'TRUE' : 'FALSE'}`;
204
- } else if (conf.type === Number) {
204
+ } else if (config.type === Number) {
205
205
  return `${value}`;
206
- } else if (conf.type === Date) {
206
+ } else if (config.type === Date) {
207
207
  if (typeof value === 'string' && TimeUtil.isTimeSpan(value)) {
208
208
  return this.resolveDateValue(TimeUtil.fromNow(value));
209
209
  } else {
210
210
  return this.resolveDateValue(DataUtil.coerceType(value, Date, true));
211
211
  }
212
- } else if (conf.type === PointImpl && Array.isArray(value)) {
212
+ } else if (config.type === PointConcrete && Array.isArray(value)) {
213
213
  return `point(${value[0]},${value[1]})`;
214
- } else if (conf.type === Object) {
214
+ } else if (config.type === Object) {
215
215
  return this.quote(JSON.stringify(value).replace(/[']/g, "''"));
216
216
  }
217
- throw new AppError(`Unknown value type for field ${conf.name.toString()}, ${value}`, { category: 'data' });
217
+ throw new AppError(`Unknown value type for field ${config.name}, ${value}`, { category: 'data' });
218
218
  }
219
219
 
220
220
  /**
221
221
  * Get column type from field config
222
222
  */
223
- getColumnType(conf: SchemaFieldConfig): string {
223
+ getColumnType(config: SchemaFieldConfig): string {
224
224
  let type: string = '';
225
225
 
226
- if (conf.type === Number) {
226
+ if (config.type === Number) {
227
227
  type = this.COLUMN_TYPES.INT;
228
- if (conf.precision) {
229
- const [digits, decimals] = conf.precision;
228
+ if (config.precision) {
229
+ const [digits, decimals] = config.precision;
230
230
  if (decimals) {
231
231
  type = this.PARAMETERIZED_COLUMN_TYPES.DECIMAL(digits, decimals);
232
232
  } else if (digits) {
@@ -245,19 +245,19 @@ export abstract class SQLDialect implements DialectState {
245
245
  } else {
246
246
  type = this.COLUMN_TYPES.INT;
247
247
  }
248
- } else if (conf.type === Date) {
248
+ } else if (config.type === Date) {
249
249
  type = this.COLUMN_TYPES.TIMESTAMP;
250
- } else if (conf.type === Boolean) {
250
+ } else if (config.type === Boolean) {
251
251
  type = this.COLUMN_TYPES.BOOLEAN;
252
- } else if (conf.type === String) {
253
- if (conf.specifiers?.includes('text')) {
252
+ } else if (config.type === String) {
253
+ if (config.specifiers?.includes('text')) {
254
254
  type = this.COLUMN_TYPES.TEXT;
255
255
  } else {
256
- type = this.PARAMETERIZED_COLUMN_TYPES.VARCHAR(conf.maxlength ? conf.maxlength.n : this.DEFAULT_STRING_LEN);
256
+ type = this.PARAMETERIZED_COLUMN_TYPES.VARCHAR(config.maxlength ? config.maxlength.n : this.DEFAULT_STRING_LENGTH);
257
257
  }
258
- } else if (conf.type === PointImpl) {
258
+ } else if (config.type === PointConcrete) {
259
259
  type = this.COLUMN_TYPES.POINT;
260
- } else if (conf.type === Object) {
260
+ } else if (config.type === Object) {
261
261
  type = this.COLUMN_TYPES.JSON;
262
262
  }
263
263
 
@@ -267,12 +267,12 @@ export abstract class SQLDialect implements DialectState {
267
267
  /**
268
268
  * FieldConfig to Column definition
269
269
  */
270
- getColumnDefinition(conf: SchemaFieldConfig): string | undefined {
271
- const type = this.getColumnType(conf);
270
+ getColumnDefinition(config: SchemaFieldConfig): string | undefined {
271
+ const type = this.getColumnType(config);
272
272
  if (!type) {
273
273
  return;
274
274
  }
275
- return `${this.ident(conf)} ${type} ${(conf.required?.active !== false) ? 'NOT NULL' : 'DEFAULT NULL'}`;
275
+ return `${this.identifier(config)} ${type} ${(config.required?.active !== false) ? 'NOT NULL' : 'DEFAULT NULL'}`;
276
276
  }
277
277
 
278
278
  /**
@@ -297,7 +297,7 @@ export abstract class SQLDialect implements DialectState {
297
297
  */
298
298
  getDropColumnSQL(stack: VisitStack[]): string {
299
299
  const field = stack.at(-1)!;
300
- return `ALTER TABLE ${this.parentTable(stack)} DROP COLUMN ${this.ident(field.name)};`;
300
+ return `ALTER TABLE ${this.parentTable(stack)} DROP COLUMN ${this.identifier(field.name)};`;
301
301
  }
302
302
 
303
303
  /**
@@ -317,7 +317,7 @@ export abstract class SQLDialect implements DialectState {
317
317
  * Determine table/field namespace for a given stack location
318
318
  */
319
319
  namespace(stack: VisitStack[]): string {
320
- return `${this.ns}${SQLModelUtil.buildTable(stack)}`;
320
+ return `${this.namespacePrefix}${SQLModelUtil.buildTable(stack)}`;
321
321
  }
322
322
 
323
323
  /**
@@ -331,7 +331,7 @@ export abstract class SQLDialect implements DialectState {
331
331
  * Determine table name for a given stack location
332
332
  */
333
333
  table(stack: VisitStack[]): string {
334
- return this.ident(this.namespace(stack));
334
+ return this.identifier(this.namespace(stack));
335
335
  }
336
336
 
337
337
  /**
@@ -351,8 +351,8 @@ export abstract class SQLDialect implements DialectState {
351
351
  /**
352
352
  * Alias a field for usage
353
353
  */
354
- alias(field: string | symbol | SchemaFieldConfig, alias: string = this.rootAlias): string {
355
- return `${alias}.${this.ident(field)}`;
354
+ alias(field: string | SchemaFieldConfig, alias: string = this.rootAlias): string {
355
+ return `${alias}.${this.identifier(field)}`;
356
356
  }
357
357
 
358
358
  /**
@@ -376,12 +376,12 @@ export abstract class SQLDialect implements DialectState {
376
376
  },
377
377
  onSub: ({ descend, config, path }) => {
378
378
  const table = resolve(path);
379
- clauses.set(table, { alias: `${config.name.toString().charAt(0)}${idx++}`, path });
379
+ clauses.set(table, { alias: `${config.name.charAt(0)}${idx++}`, path });
380
380
  return descend();
381
381
  },
382
382
  onSimple: ({ config, path }) => {
383
383
  const table = resolve(path);
384
- clauses.set(table, { alias: `${config.name.toString().charAt(0)}${idx++}`, path });
384
+ clauses.set(table, { alias: `${config.name.charAt(0)}${idx++}`, path });
385
385
  }
386
386
  });
387
387
 
@@ -404,13 +404,13 @@ export abstract class SQLDialect implements DialectState {
404
404
  /**
405
405
  * Generate WHERE field clause
406
406
  */
407
- getWhereFieldSQL(stack: VisitStack[], o: Record<string, unknown>): string {
407
+ getWhereFieldSQL(stack: VisitStack[], input: Record<string, unknown>): string {
408
408
  const items = [];
409
409
  const { foreignMap, localMap } = SQLModelUtil.getFieldsByLocation(stack);
410
410
  const SQL_OPS = this.SQL_OPS;
411
411
 
412
- for (const key of Object.keys(o)) {
413
- const top = o[key];
412
+ for (const key of Object.keys(input)) {
413
+ const top = input[key];
414
414
  const field = localMap[key] ?? foreignMap[key];
415
415
  if (!field) {
416
416
  throw new Error(`Unknown field: ${key}`);
@@ -432,38 +432,38 @@ export abstract class SQLDialect implements DialectState {
432
432
  const inner = this.getWhereFieldSQL(sStack, top);
433
433
  items.push(inner);
434
434
  } else {
435
- const v = top[subKey];
435
+ const value = top[subKey];
436
436
  const resolve = this.resolveValue.bind(this, field);
437
437
 
438
438
  switch (subKey) {
439
439
  case '$nin': case '$in': {
440
- const arr = (Array.isArray(v) ? v : [v]).map(el => resolve(el));
440
+ const arr = (Array.isArray(value) ? value : [value]).map(item => resolve(item));
441
441
  items.push(`${sPath} ${SQL_OPS[subKey]} (${arr.join(',')})`);
442
442
  break;
443
443
  }
444
444
  case '$all': {
445
445
  const set = new Set();
446
- const arr = [v].flat().filter(x => !set.has(x) && !!set.add(x)).map(el => resolve(el));
446
+ const arr = [value].flat().filter(item => !set.has(item) && !!set.add(item)).map(item => resolve(item));
447
447
  const valueTable = this.parentTable(sStack);
448
448
  const alias = `_all_${sStack.length}`;
449
- const pPath = this.ident(this.parentPathField.name);
449
+ const pPath = this.identifier(this.parentPathField.name);
450
450
  const rpPath = this.resolveName([...sStack, field, this.parentPathField]);
451
451
 
452
452
  items.push(`${arr.length} = (
453
- SELECT COUNT(DISTINCT ${alias}.${this.ident(field.name)})
453
+ SELECT COUNT(DISTINCT ${alias}.${this.identifier(field.name)})
454
454
  FROM ${valueTable} ${alias}
455
455
  WHERE ${alias}.${pPath} = ${rpPath}
456
- AND ${alias}.${this.ident(field.name)} IN (${arr.join(',')})
456
+ AND ${alias}.${this.identifier(field.name)} IN (${arr.join(',')})
457
457
  )`);
458
458
  break;
459
459
  }
460
460
  case '$regex': {
461
- const re = DataUtil.toRegex(castTo(v));
462
- const src = re.source;
463
- const ins = re.flags && re.flags.includes('i');
461
+ const regex = DataUtil.toRegex(castTo(value));
462
+ const regexSource = regex.source;
463
+ const ins = regex.flags && regex.flags.includes('i');
464
464
 
465
- if (/^[\^]\S+[.][*][$]?$/.test(src)) {
466
- const inner = src.substring(1, src.length - 2);
465
+ if (/^[\^]\S+[.][*][$]?$/.test(regexSource)) {
466
+ const inner = regexSource.substring(1, regexSource.length - 2);
467
467
  if (!ins || SQL_OPS.$ilike) {
468
468
  items.push(`${sPath} ${ins ? SQL_OPS.$ilike : SQL_OPS.$like} ${resolve(`${inner}%`)}`);
469
469
  } else {
@@ -471,11 +471,11 @@ export abstract class SQLDialect implements DialectState {
471
471
  }
472
472
  } else {
473
473
  if (!ins || SQL_OPS.$iregex) {
474
- const val = resolve(v);
475
- items.push(`${sPath} ${SQL_OPS[!ins ? subKey : '$iregex']} ${val}`);
474
+ const result = resolve(value);
475
+ items.push(`${sPath} ${SQL_OPS[!ins ? subKey : '$iregex']} ${result}`);
476
476
  } else {
477
- const val = resolve(new RegExp(src.toLowerCase(), re.flags));
478
- items.push(`LOWER(${sPath}) ${SQL_OPS[subKey]} ${val}`);
477
+ const result = resolve(new RegExp(regexSource.toLowerCase(), regex.flags));
478
+ items.push(`LOWER(${sPath}) ${SQL_OPS[subKey]} ${result}`);
479
479
  }
480
480
  }
481
481
  break;
@@ -484,31 +484,31 @@ export abstract class SQLDialect implements DialectState {
484
484
  if (field.array) {
485
485
  const valueTable = this.parentTable(sStack);
486
486
  const alias = `_all_${sStack.length}`;
487
- const pPath = this.ident(this.parentPathField.name);
487
+ const pPath = this.identifier(this.parentPathField.name);
488
488
  const rpPath = this.resolveName([...sStack, field, this.parentPathField]);
489
489
 
490
- items.push(`0 ${!v ? '=' : '<>'} (
491
- SELECT COUNT(${alias}.${this.ident(field.name)})
490
+ items.push(`0 ${!value ? '=' : '<>'} (
491
+ SELECT COUNT(${alias}.${this.identifier(field.name)})
492
492
  FROM ${valueTable} ${alias}
493
493
  WHERE ${alias}.${pPath} = ${rpPath}
494
494
  )`);
495
495
  } else {
496
- items.push(`${sPath} ${v ? SQL_OPS.$isNot : SQL_OPS.$is} NULL`);
496
+ items.push(`${sPath} ${value ? SQL_OPS.$isNot : SQL_OPS.$is} NULL`);
497
497
  }
498
498
  break;
499
499
  }
500
500
  case '$ne': case '$eq': {
501
- if (v === null || v === undefined) {
501
+ if (value === null || value === undefined) {
502
502
  items.push(`${sPath} ${subKey === '$ne' ? SQL_OPS.$isNot : SQL_OPS.$is} NULL`);
503
503
  } else {
504
- const base = `${sPath} ${SQL_OPS[subKey]} ${resolve(v)}`;
504
+ const base = `${sPath} ${SQL_OPS[subKey]} ${resolve(value)}`;
505
505
  items.push(subKey === '$ne' ? `(${base} OR ${sPath} ${SQL_OPS.$is} NULL)` : base);
506
506
  }
507
507
  break;
508
508
  }
509
509
  case '$lt': case '$gt': case '$gte': case '$lte': {
510
510
  const subItems = TypedObject.keys(castTo<typeof SQL_OPS>(top))
511
- .map(ssk => `${sPath} ${SQL_OPS[ssk]} ${resolve(top[ssk])}`);
511
+ .map(subSubKey => `${sPath} ${SQL_OPS[subSubKey]} ${resolve(top[subSubKey])}`);
512
512
  items.push(subItems.length > 1 ? `(${subItems.join(` ${SQL_OPS.$and} `)})` : subItems[0]);
513
513
  break;
514
514
  }
@@ -534,17 +534,17 @@ export abstract class SQLDialect implements DialectState {
534
534
  /**
535
535
  * Grouping of where clauses
536
536
  */
537
- getWhereGroupingSQL<T>(cls: Class<T>, o: WhereClause<T>): string {
537
+ getWhereGroupingSQL<T>(cls: Class<T>, clause: WhereClause<T>): string {
538
538
  const SQL_OPS = this.SQL_OPS;
539
539
 
540
- if (ModelQueryUtil.has$And(o)) {
541
- return `(${o.$and.map(x => this.getWhereGroupingSQL<T>(cls, x)).join(` ${SQL_OPS.$and} `)})`;
542
- } else if (ModelQueryUtil.has$Or(o)) {
543
- return `(${o.$or.map(x => this.getWhereGroupingSQL<T>(cls, x)).join(` ${SQL_OPS.$or} `)})`;
544
- } else if (ModelQueryUtil.has$Not(o)) {
545
- return `${SQL_OPS.$not} (${this.getWhereGroupingSQL<T>(cls, o.$not)})`;
540
+ if (ModelQueryUtil.has$And(clause)) {
541
+ return `(${clause.$and.map(item => this.getWhereGroupingSQL<T>(cls, item)).join(` ${SQL_OPS.$and} `)})`;
542
+ } else if (ModelQueryUtil.has$Or(clause)) {
543
+ return `(${clause.$or.map(item => this.getWhereGroupingSQL<T>(cls, item)).join(` ${SQL_OPS.$or} `)})`;
544
+ } else if (ModelQueryUtil.has$Not(clause)) {
545
+ return `${SQL_OPS.$not} (${this.getWhereGroupingSQL<T>(cls, clause.$not)})`;
546
546
  } else {
547
- return this.getWhereFieldSQL(SQLModelUtil.classToStack(cls), o);
547
+ return this.getWhereFieldSQL(SQLModelUtil.classToStack(cls), clause);
548
548
  }
549
549
  }
550
550
 
@@ -563,8 +563,8 @@ export abstract class SQLDialect implements DialectState {
563
563
  getOrderBySQL<T>(cls: Class<T>, sortBy?: SortClause<T>[]): string {
564
564
  return !sortBy ?
565
565
  '' :
566
- `ORDER BY ${SQLModelUtil.orderBy(cls, sortBy).map((ob) =>
567
- `${this.resolveName(ob.stack)} ${ob.asc ? 'ASC' : 'DESC'}`
566
+ `ORDER BY ${SQLModelUtil.orderBy(cls, sortBy).map((item) =>
567
+ `${this.resolveName(item.stack)} ${item.asc ? 'ASC' : 'DESC'}`
568
568
  ).join(', ')}`;
569
569
  }
570
570
 
@@ -591,7 +591,7 @@ export abstract class SQLDialect implements DialectState {
591
591
  const tables = [...aliases.keys()].toSorted((a, b) => a.length - b.length); // Shortest first
592
592
  return `FROM ${tables.map((table) => {
593
593
  const { alias, path } = aliases.get(table)!;
594
- let from = `${this.ident(table)} ${alias}`;
594
+ let from = `${this.identifier(table)} ${alias}`;
595
595
  if (path.length > 1) {
596
596
  const key = this.namespaceParent(path);
597
597
  const { alias: parentAlias } = aliases.get(key)!;
@@ -620,7 +620,7 @@ LEFT OUTER JOIN ${from} ON
620
620
  const sortFields = !query.sort ?
621
621
  '' :
622
622
  SQLModelUtil.orderBy(cls, query.sort)
623
- .map(x => this.resolveName(x.stack))
623
+ .map(item => this.resolveName(item.stack))
624
624
  .join(', ');
625
625
 
626
626
  // TODO: Really confused on this
@@ -649,21 +649,21 @@ ${this.getLimitSQL(cls, query)}`;
649
649
  (array ? [castTo<SchemaFieldConfig>(config)] : []);
650
650
 
651
651
  if (!parent) {
652
- let idField = fields.find(x => x.name === this.idField.name);
652
+ let idField = fields.find(field => field.name === this.idField.name);
653
653
  if (!idField) {
654
654
  fields.push(idField = this.idField);
655
655
  } else {
656
- idField.maxlength = { n: this.ID_LEN };
656
+ idField.maxlength = { n: this.ID_LENGTH };
657
657
  }
658
658
  }
659
659
 
660
660
  const fieldSql = fields
661
- .map(f => {
662
- const def = this.getColumnDefinition(f) || '';
663
- return f.name === this.idField.name && !parent ?
661
+ .map(field => {
662
+ const def = this.getColumnDefinition(field) || '';
663
+ return field.name === this.idField.name && !parent ?
664
664
  def.replace('DEFAULT NULL', 'NOT NULL') : def;
665
665
  })
666
- .filter(x => !!x.trim())
666
+ .filter(line => !!line.trim())
667
667
  .join(',\n ');
668
668
 
669
669
  const out = `
@@ -671,11 +671,11 @@ CREATE TABLE IF NOT EXISTS ${this.table(stack)} (
671
671
  ${fieldSql}${fieldSql.length ? ',' : ''}
672
672
  ${this.getColumnDefinition(this.pathField)} UNIQUE,
673
673
  ${!parent ?
674
- `PRIMARY KEY (${this.ident(this.idField)})` :
674
+ `PRIMARY KEY (${this.identifier(this.idField)})` :
675
675
  `${this.getColumnDefinition(this.parentPathField)},
676
676
  ${array ? `${this.getColumnDefinition(this.idxField)},` : ''}
677
- PRIMARY KEY (${this.ident(this.pathField)}),
678
- FOREIGN KEY (${this.ident(this.parentPathField)}) REFERENCES ${this.parentTable(stack)}(${this.ident(this.pathField)}) ON DELETE CASCADE`}
677
+ PRIMARY KEY (${this.identifier(this.pathField)}),
678
+ FOREIGN KEY (${this.identifier(this.parentPathField)}) REFERENCES ${this.parentTable(stack)}(${this.identifier(this.pathField)}) ON DELETE CASCADE`}
679
679
  );`;
680
680
  return out;
681
681
  }
@@ -719,17 +719,17 @@ CREATE TABLE IF NOT EXISTS ${this.table(stack)} (
719
719
  */
720
720
  getCreateIndexSQL<T extends ModelType>(cls: Class<T>, idx: IndexConfig<T>): string {
721
721
  const table = this.namespace(SQLModelUtil.classToStack(cls));
722
- const fields: [string, boolean][] = idx.fields.map(x => {
723
- const key = TypedObject.keys(x)[0];
724
- const val = x[key];
725
- if (DataUtil.isPlainObject(val)) {
722
+ const fields: [string, boolean][] = idx.fields.map(field => {
723
+ const key = TypedObject.keys(field)[0];
724
+ const value = field[key];
725
+ if (DataUtil.isPlainObject(value)) {
726
726
  throw new Error('Unable to supported nested fields for indices');
727
727
  }
728
- return [castTo(key), typeof val === 'number' ? val === 1 : (!!val)];
728
+ return [castTo(key), typeof value === 'number' ? value === 1 : (!!value)];
729
729
  });
730
- const constraint = `idx_${table}_${fields.map(([f]) => f).join('_')}`;
731
- return `CREATE ${idx.type === 'unique' ? 'UNIQUE ' : ''}INDEX ${constraint} ON ${this.ident(table)} (${fields
732
- .map(([name, sel]) => `${this.ident(name)} ${sel ? 'ASC' : 'DESC'}`)
730
+ const constraint = `idx_${table}_${fields.map(([field]) => field).join('_')}`;
731
+ return `CREATE ${idx.type === 'unique' ? 'UNIQUE ' : ''}INDEX ${constraint} ON ${this.identifier(table)} (${fields
732
+ .map(([name, sel]) => `${this.identifier(name)} ${sel ? 'ASC' : 'DESC'}`)
733
733
  .join(', ')});`;
734
734
  }
735
735
 
@@ -765,30 +765,30 @@ CREATE TABLE IF NOT EXISTS ${this.table(stack)} (
765
765
  getInsertSQL(stack: VisitStack[], instances: InsertWrapper['records']): string | undefined {
766
766
  const config = stack.at(-1)!;
767
767
  const columns = SQLModelUtil.getFieldsByLocation(stack).local
768
- .filter(x => !SchemaRegistryIndex.has(x.type))
769
- .toSorted((a, b) => a.name.toString().localeCompare(b.name.toString()));
770
- const columnNames = columns.map(c => c.name);
768
+ .filter(field => !SchemaRegistryIndex.has(field.type))
769
+ .toSorted((a, b) => a.name.localeCompare(b.name));
770
+ const columnNames = columns.map(column => column.name);
771
771
 
772
772
  const hasParent = stack.length > 1;
773
773
  const isArray = !!config.array;
774
774
 
775
775
  if (isArray) {
776
776
  const newInstances: typeof instances = [];
777
- for (const el of instances) {
778
- if (el.value === null || el.value === undefined) {
777
+ for (const instance of instances) {
778
+ if (instance.value === null || instance.value === undefined) {
779
779
  continue;
780
- } else if (Array.isArray(el.value)) {
781
- const name = el.stack.at(-1)!.name;
782
- for (const sel of el.value) {
780
+ } else if (Array.isArray(instance.value)) {
781
+ const name = instance.stack.at(-1)!.name;
782
+ for (const sel of instance.value) {
783
783
  newInstances.push({
784
- stack: el.stack,
784
+ stack: instance.stack,
785
785
  value: {
786
786
  [name]: sel
787
787
  }
788
788
  });
789
789
  }
790
790
  } else {
791
- newInstances.push(el);
791
+ newInstances.push(instance);
792
792
  }
793
793
  }
794
794
  instances = newInstances;
@@ -798,7 +798,8 @@ CREATE TABLE IF NOT EXISTS ${this.table(stack)} (
798
798
  return;
799
799
  }
800
800
 
801
- const matrix = instances.map(inst => columns.map(c => this.resolveValue(c, castTo<Record<string | symbol, unknown>>(inst.value)[c.name])));
801
+ const matrix = instances.map(inst => columns.map(column =>
802
+ this.resolveValue(column, castTo<Record<string, unknown>>(inst.value)[column.name])));
802
803
 
803
804
  columnNames.push(this.pathField.name);
804
805
  if (hasParent) {
@@ -824,7 +825,7 @@ CREATE TABLE IF NOT EXISTS ${this.table(stack)} (
824
825
  }
825
826
 
826
827
  return `
827
- INSERT INTO ${this.table(stack)} (${columnNames.map(this.ident).join(', ')})
828
+ INSERT INTO ${this.table(stack)} (${columnNames.map(this.identifier).join(', ')})
828
829
  VALUES
829
830
  ${matrix.map(row => `(${row.join(', ')})`).join(',\n')};`;
830
831
  }
@@ -854,8 +855,8 @@ UPDATE ${this.table(stack)} ${this.rootAlias}
854
855
  SET
855
856
  ${Object
856
857
  .entries(data)
857
- .filter(([k]) => k in localMap)
858
- .map(([k, v]) => `${this.ident(k)}=${this.resolveValue(localMap[k], v)}`).join(', ')}
858
+ .filter(([key]) => key in localMap)
859
+ .map(([key, value]) => `${this.identifier(key)}=${this.resolveValue(localMap[key], value)}`).join(', ')}
859
860
  ${this.getWhereSQL(type, where)};`;
860
861
  }
861
862
 
@@ -874,12 +875,12 @@ ${this.getWhereSQL(type, where)};`;
874
875
  const config = stack.at(-1)!;
875
876
  const orderBy = !config.array ?
876
877
  '' :
877
- `ORDER BY ${this.rootAlias}.${this.idxField.name.toString()} ASC`;
878
+ `ORDER BY ${this.rootAlias}.${this.idxField.name} ASC`;
878
879
 
879
880
  const idField = (stack.length > 1 ? this.parentPathField : this.idField);
880
881
 
881
882
  return `
882
- SELECT ${select.length ? select.map(x => this.alias(x)).join(',') : '*'}
883
+ SELECT ${select.length ? select.map(field => this.alias(field)).join(',') : '*'}
883
884
  FROM ${this.table(stack)} ${this.rootAlias}
884
885
  WHERE ${this.alias(idField)} IN (${ids.map(id => this.resolveValue(idField, id)).join(', ')})
885
886
  ${orderBy};`;
@@ -904,9 +905,9 @@ ${this.getWhereSQL(cls, where!)}`;
904
905
 
905
906
  await SQLModelUtil.visitSchema(SchemaRegistryIndex.getConfig(cls), {
906
907
  onRoot: async (config) => {
907
- const res = buildSet(items); // Already filtered by initial select query
908
+ const fieldSet = buildSet(items); // Already filtered by initial select query
908
909
  selectStack.push(select);
909
- stack.push(res);
910
+ stack.push(fieldSet);
910
911
  await config.descend();
911
912
  },
912
913
  onSub: async ({ config, descend, fields, path }) => {
@@ -917,28 +918,28 @@ ${this.getWhereSQL(cls, where!)}`;
917
918
  const subSelectTop: SelectClause<T> | undefined = castTo(selectTop?.[fieldKey]);
918
919
 
919
920
  // See if a selection exists at all
920
- const sel: SchemaFieldConfig[] = subSelectTop ? fields
921
- .filter(f => typeof subSelectTop === 'object' && subSelectTop[castTo<typeof fieldKey>(f.name)] === 1)
921
+ const selected: SchemaFieldConfig[] = subSelectTop ? fields
922
+ .filter(field => typeof subSelectTop === 'object' && subSelectTop[castTo<typeof fieldKey>(field.name)] === 1)
922
923
  : [];
923
924
 
924
- if (sel.length) {
925
- sel.push(this.pathField, this.parentPathField);
925
+ if (selected.length) {
926
+ selected.push(this.pathField, this.parentPathField);
926
927
  if (config.array) {
927
- sel.push(this.idxField);
928
+ selected.push(this.idxField);
928
929
  }
929
930
  }
930
931
 
931
932
  // If children and selection exists
932
- if (ids.length && (!subSelectTop || sel)) {
933
+ if (ids.length && (!subSelectTop || selected)) {
933
934
  const { records: children } = await this.executeSQL<unknown[]>(this.getSelectRowsByIdsSQL(
934
935
  path,
935
936
  ids,
936
- sel
937
+ selected
937
938
  ));
938
939
 
939
- const res = buildSet(children, config);
940
+ const fieldSet = buildSet(children, config);
940
941
  try {
941
- stack.push(res);
942
+ stack.push(fieldSet);
942
943
  selectStack.push(subSelectTop);
943
944
  await descend();
944
945
  } finally {
@@ -982,30 +983,34 @@ ${this.getWhereSQL(cls, where!)}`;
982
983
  async bulkProcess(deletes: DeleteWrapper[], inserts: InsertWrapper[], upserts: InsertWrapper[], updates: InsertWrapper[]): Promise<BulkResponse> {
983
984
  const out = {
984
985
  counts: {
985
- delete: deletes.reduce((acc, el) => acc + el.ids.length, 0),
986
+ delete: deletes.reduce((count, item) => count + item.ids.length, 0),
986
987
  error: 0,
987
- insert: inserts.filter(x => x.stack.length === 1).reduce((acc, el) => acc + el.records.length, 0),
988
- update: updates.filter(x => x.stack.length === 1).reduce((acc, el) => acc + el.records.length, 0),
989
- upsert: upserts.filter(x => x.stack.length === 1).reduce((acc, el) => acc + el.records.length, 0)
988
+ insert: inserts.filter(item => item.stack.length === 1).reduce((count, item) => count + item.records.length, 0),
989
+ update: updates.filter(item => item.stack.length === 1).reduce((count, item) => count + item.records.length, 0),
990
+ upsert: upserts.filter(item => item.stack.length === 1).reduce((count, item) => count + item.records.length, 0)
990
991
  },
991
992
  errors: [],
992
993
  insertedIds: new Map()
993
994
  };
994
995
 
995
996
  // Full removals
996
- await Promise.all(deletes.map(el => this.deleteByIds(el.stack, el.ids)));
997
+ await Promise.all(deletes.map(item => this.deleteByIds(item.stack, item.ids)));
997
998
 
998
999
  // Adding deletes
999
1000
  if (upserts.length || updates.length) {
1000
1001
  const idx = this.idField.name;
1001
1002
 
1002
1003
  await Promise.all([
1003
- ...upserts.filter(x => x.stack.length === 1).map(i =>
1004
- this.deleteByIds(i.stack, i.records.map(v => castTo<Record<string | symbol, string>>(v.value)[idx]))
1005
- ),
1006
- ...updates.filter(x => x.stack.length === 1).map(i =>
1007
- this.deleteByIds(i.stack, i.records.map(v => castTo<Record<string | symbol, string>>(v.value)[idx]))
1008
- ),
1004
+ ...upserts
1005
+ .filter(item => item.stack.length === 1)
1006
+ .map(item =>
1007
+ this.deleteByIds(item.stack, item.records.map(value => castTo<Record<string, string>>(value.value)[idx]))
1008
+ ),
1009
+ ...updates
1010
+ .filter(item => item.stack.length === 1)
1011
+ .map(item =>
1012
+ this.deleteByIds(item.stack, item.records.map(value => castTo<Record<string, string>>(value.value)[idx]))
1013
+ ),
1009
1014
  ]);
1010
1015
  }
1011
1016
 
@@ -1014,17 +1019,17 @@ ${this.getWhereSQL(cls, where!)}`;
1014
1019
  if (!items.length) {
1015
1020
  continue;
1016
1021
  }
1017
- let lvl = 1; // Add by level
1022
+ let level = 1; // Add by level
1018
1023
  for (; ;) { // Loop until done
1019
- const leveled = items.filter(f => f.stack.length === lvl);
1024
+ const leveled = items.filter(insertWrapper => insertWrapper.stack.length === level);
1020
1025
  if (!leveled.length) {
1021
1026
  break;
1022
1027
  }
1023
1028
  await Promise.all(leveled
1024
- .map(iw => this.getInsertSQL(iw.stack, iw.records))
1029
+ .map(inserted => this.getInsertSQL(inserted.stack, inserted.records))
1025
1030
  .filter(sql => !!sql)
1026
1031
  .map(sql => this.executeSQL(sql!)));
1027
- lvl += 1;
1032
+ level += 1;
1028
1033
  }
1029
1034
  }
1030
1035