@balena/pinejs 14.60.0-build-translated-models-85baf731130de328e2067a26c40b37309cdb1ac5-1 → 15.0.0-build-15-x-4681209f5dd8d896491fb5ed64aea47df511c14d-1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. package/.pinejs-cache.json +1 -1
  2. package/.versionbot/CHANGELOG.yml +106 -6
  3. package/CHANGELOG.md +16 -4
  4. package/VERSION +1 -1
  5. package/build/browser.ts +0 -1
  6. package/out/bin/abstract-sql-compiler.js +0 -0
  7. package/out/bin/abstract-sql-compiler.js.map +1 -1
  8. package/out/bin/odata-compiler.js +1 -4
  9. package/out/bin/odata-compiler.js.map +1 -1
  10. package/out/bin/sbvr-compiler.js +0 -0
  11. package/out/bin/sbvr-compiler.js.map +1 -1
  12. package/out/config-loader/config-loader.d.ts +2 -5
  13. package/out/config-loader/config-loader.js +19 -38
  14. package/out/config-loader/config-loader.js.map +1 -1
  15. package/out/config-loader/env.js +4 -4
  16. package/out/config-loader/env.js.map +1 -1
  17. package/out/data-server/sbvr-server.d.ts +1 -13
  18. package/out/data-server/sbvr-server.js +17 -1
  19. package/out/data-server/sbvr-server.js.map +1 -1
  20. package/out/database-layer/db.js +12 -15
  21. package/out/database-layer/db.js.map +1 -1
  22. package/out/express-emulator/express.js +4 -4
  23. package/out/express-emulator/express.js.map +1 -1
  24. package/out/http-transactions/transactions.d.ts +1 -12
  25. package/out/http-transactions/transactions.js +18 -0
  26. package/out/http-transactions/transactions.js.map +1 -1
  27. package/out/migrator/async.js +12 -16
  28. package/out/migrator/async.js.map +1 -1
  29. package/out/migrator/sync.js +6 -12
  30. package/out/migrator/sync.js.map +1 -1
  31. package/out/migrator/utils.d.ts +5 -4
  32. package/out/migrator/utils.js +38 -20
  33. package/out/migrator/utils.js.map +1 -1
  34. package/out/pinejs-session-store/pinejs-session-store.js +18 -3
  35. package/out/pinejs-session-store/pinejs-session-store.js.map +1 -1
  36. package/out/sbvr-api/abstract-sql.js +2 -4
  37. package/out/sbvr-api/abstract-sql.js.map +1 -1
  38. package/out/sbvr-api/cached-compile.js +1 -1
  39. package/out/sbvr-api/cached-compile.js.map +1 -1
  40. package/out/sbvr-api/hooks.d.ts +3 -3
  41. package/out/sbvr-api/hooks.js +32 -48
  42. package/out/sbvr-api/hooks.js.map +1 -1
  43. package/out/sbvr-api/odata-response.js +4 -5
  44. package/out/sbvr-api/odata-response.js.map +1 -1
  45. package/out/sbvr-api/permissions.js +25 -65
  46. package/out/sbvr-api/permissions.js.map +1 -1
  47. package/out/sbvr-api/sbvr-utils.d.ts +5 -11
  48. package/out/sbvr-api/sbvr-utils.js +94 -145
  49. package/out/sbvr-api/sbvr-utils.js.map +1 -1
  50. package/out/sbvr-api/uri-parser.d.ts +1 -4
  51. package/out/sbvr-api/uri-parser.js +4 -11
  52. package/out/sbvr-api/uri-parser.js.map +1 -1
  53. package/package.json +8 -8
  54. package/src/bin/abstract-sql-compiler.ts +2 -1
  55. package/src/bin/odata-compiler.ts +2 -4
  56. package/src/bin/sbvr-compiler.ts +2 -1
  57. package/src/config-loader/config-loader.ts +24 -62
  58. package/src/config-loader/env.ts +3 -7
  59. package/src/data-server/sbvr-server.js +17 -1
  60. package/src/database-layer/db.ts +1 -1
  61. package/src/express-emulator/express.js +4 -4
  62. package/src/http-transactions/transactions.js +18 -0
  63. package/src/migrator/utils.ts +40 -20
  64. package/src/pinejs-session-store/pinejs-session-store.ts +15 -0
  65. package/src/sbvr-api/abstract-sql.ts +1 -2
  66. package/src/sbvr-api/hooks.ts +33 -80
  67. package/src/sbvr-api/odata-response.ts +1 -2
  68. package/src/sbvr-api/permissions.ts +20 -68
  69. package/src/sbvr-api/sbvr-utils.ts +107 -195
  70. package/src/sbvr-api/uri-parser.ts +5 -8
  71. package/tsconfig.json +1 -1
  72. package/out/sbvr-api/translations.d.ts +0 -6
  73. package/out/sbvr-api/translations.js +0 -136
  74. package/out/sbvr-api/translations.js.map +0 -1
  75. package/src/sbvr-api/translations.ts +0 -219
@@ -63,7 +63,6 @@ import {
63
63
  rollbackRequestHooks,
64
64
  getHooks,
65
65
  runHooks,
66
- InstantiatedHooks,
67
66
  } from './hooks';
68
67
  export {
69
68
  HookReq,
@@ -93,7 +92,6 @@ import {
93
92
  export { resolveOdataBind } from './abstract-sql';
94
93
  import * as odataResponse from './odata-response';
95
94
  import { env } from '../server-glue/module';
96
- import { translateAbstractSqlModel } from './translations';
97
95
 
98
96
  const LF2AbstractSQLTranslator = LF2AbstractSQL.createTranslator(sbvrTypes);
99
97
  const LF2AbstractSQLTranslatorVersion = `${LF2AbstractSQLVersion}+${sbvrTypesVersion}`;
@@ -104,18 +102,14 @@ export type ExecutableModel =
104
102
 
105
103
  interface CompiledModel {
106
104
  vocab: string;
107
- translateTo?: string;
108
- resourceRenames?: ReturnType<typeof translateAbstractSqlModel>;
109
105
  se?: string | undefined;
110
106
  lf?: LFModel | undefined;
111
107
  abstractSql: AbstractSQLCompiler.AbstractSqlModel;
112
- sql?: AbstractSQLCompiler.SqlModel;
108
+ sql: AbstractSQLCompiler.SqlModel;
113
109
  odataMetadata: ReturnType<typeof generateODataMetadata>;
114
110
  }
115
111
  const models: {
116
- [vocabulary: string]: CompiledModel & {
117
- versions: string[];
118
- };
112
+ [vocabulary: string]: CompiledModel;
119
113
  } = {};
120
114
 
121
115
  export interface Actor {
@@ -129,7 +123,7 @@ export interface User extends Actor {
129
123
 
130
124
  export interface ApiKey extends Actor {
131
125
  key: string;
132
- actor?: number;
126
+ actor: number;
133
127
  }
134
128
 
135
129
  export interface Response {
@@ -240,7 +234,7 @@ const prettifyConstraintError = (
240
234
  break;
241
235
  case 'postgres':
242
236
  const resourceName = resolveSynonym(request);
243
- const abstractSqlModel = getFinalAbstractSqlModel(request);
237
+ const abstractSqlModel = getAbstractSqlModel(request);
244
238
  matches = new RegExp(
245
239
  '"' + abstractSqlModel.tables[resourceName].name + '_(.*?)_key"',
246
240
  ).exec(err.message);
@@ -273,7 +267,7 @@ const prettifyConstraintError = (
273
267
  break;
274
268
  case 'postgres':
275
269
  const resourceName = resolveSynonym(request);
276
- const abstractSqlModel = getFinalAbstractSqlModel(request);
270
+ const abstractSqlModel = getAbstractSqlModel(request);
277
271
  const tableName = abstractSqlModel.tables[resourceName].name;
278
272
  matches = new RegExp(
279
273
  '"' +
@@ -305,7 +299,7 @@ const prettifyConstraintError = (
305
299
 
306
300
  if (err instanceof db.CheckConstraintError) {
307
301
  const resourceName = resolveSynonym(request);
308
- const abstractSqlModel = getFinalAbstractSqlModel(request);
302
+ const abstractSqlModel = getAbstractSqlModel(request);
309
303
  const table = abstractSqlModel.tables[resourceName];
310
304
  if (table.checks) {
311
305
  switch (db.engine) {
@@ -380,12 +374,8 @@ export const validateModel = async (
380
374
  'abstractSqlQuery' | 'modifiedFields' | 'method' | 'vocabulary'
381
375
  >,
382
376
  ): Promise<void> => {
383
- const { sql } = models[modelName];
384
- if (!sql) {
385
- throw new Error(`Tried to validate a virtual model: '${modelName}'`);
386
- }
387
377
  await Promise.all(
388
- sql.rules.map(async (rule) => {
378
+ models[modelName].sql.rules.map(async (rule) => {
389
379
  if (!isRuleAffected(rule, request)) {
390
380
  // If none of the fields intersect we don't need to run the rule! :D
391
381
  return;
@@ -436,19 +426,11 @@ export const generateSqlModel = (
436
426
  () => AbstractSQLCompiler[targetDatabaseEngine].compileSchema(abstractSql),
437
427
  );
438
428
 
439
- export function generateModels(
440
- model: ExecutableModel & { translateTo?: undefined },
441
- targetDatabaseEngine: AbstractSQLCompiler.Engines,
442
- ): RequiredField<CompiledModel, 'sql'>;
443
- export function generateModels(
429
+ export const generateModels = (
444
430
  model: ExecutableModel,
445
431
  targetDatabaseEngine: AbstractSQLCompiler.Engines,
446
- ): CompiledModel;
447
- export function generateModels(
448
- model: ExecutableModel,
449
- targetDatabaseEngine: AbstractSQLCompiler.Engines,
450
- ): CompiledModel {
451
- const { apiRoot: vocab, modelText: se, translateTo, translations } = model;
432
+ ): CompiledModel => {
433
+ const { apiRoot: vocab, modelText: se } = model;
452
434
  let { abstractSql: maybeAbstractSql } = model;
453
435
 
454
436
  let lf: ReturnType<typeof generateLfModel> | undefined;
@@ -476,41 +458,16 @@ export function generateModels(
476
458
  () => generateODataMetadata(vocab, abstractSql),
477
459
  );
478
460
 
479
- let sql: AbstractSQLCompiler.SqlModel | undefined;
480
- let resourceRenames: ReturnType<typeof translateAbstractSqlModel> | undefined;
481
-
482
- if (translateTo != null) {
483
- resourceRenames = translateAbstractSqlModel(
484
- abstractSql,
485
- models[translateTo].abstractSql,
486
- model.apiRoot,
487
- translateTo,
488
- translations,
489
- );
490
- } else {
491
- for (const [key, table] of Object.entries(abstractSql.tables)) {
492
- // Alias the current version so it can be explicitly referenced
493
- abstractSql.tables[`${key}$${model.apiRoot}`] = { ...table };
494
- }
495
- try {
496
- sql = generateSqlModel(abstractSql, targetDatabaseEngine);
497
- } catch (e) {
498
- console.error(`Error compiling model '${vocab}':`, e);
499
- throw new Error(`Error compiling model '${vocab}': ` + e);
500
- }
461
+ let sql: ReturnType<AbstractSQLCompiler.EngineInstance['compileSchema']>;
462
+ try {
463
+ sql = generateSqlModel(abstractSql, targetDatabaseEngine);
464
+ } catch (e) {
465
+ console.error(`Error compiling model '${vocab}':`, e);
466
+ throw new Error(`Error compiling model '${vocab}': ` + e);
501
467
  }
502
468
 
503
- return {
504
- vocab,
505
- translateTo,
506
- resourceRenames,
507
- se,
508
- lf,
509
- abstractSql,
510
- sql,
511
- odataMetadata,
512
- };
513
- }
469
+ return { vocab, se, lf, abstractSql, sql, odataMetadata };
470
+ };
514
471
 
515
472
  export const executeModel = (
516
473
  tx: Db.Tx,
@@ -529,42 +486,30 @@ export const executeModels = async (
529
486
  await syncMigrator.run(tx, model);
530
487
  const compiledModel = generateModels(model, db.engine);
531
488
 
532
- if (compiledModel.sql) {
533
- // Create tables related to terms and fact types
534
- // Run statements sequentially, as the order of the CREATE TABLE statements matters (eg. for foreign keys).
535
- for (const createStatement of compiledModel.sql.createSchema) {
536
- const promise = tx.executeSql(createStatement);
537
- if (db.engine === 'websql') {
538
- promise.catch((err) => {
539
- console.warn(
540
- "Ignoring errors in the create table statements for websql as it doesn't support CREATE IF NOT EXISTS",
541
- err,
542
- );
543
- });
544
- }
545
- await promise;
489
+ // Create tables related to terms and fact types
490
+ // Run statements sequentially, as the order of the CREATE TABLE statements matters (eg. for foreign keys).
491
+ for (const createStatement of compiledModel.sql.createSchema) {
492
+ const promise = tx.executeSql(createStatement);
493
+ if (db.engine === 'websql') {
494
+ promise.catch((err) => {
495
+ console.warn(
496
+ "Ignoring errors in the create table statements for websql as it doesn't support CREATE IF NOT EXISTS",
497
+ err,
498
+ );
499
+ });
546
500
  }
501
+ await promise;
547
502
  }
548
503
  await syncMigrator.postRun(tx, model);
549
504
 
550
505
  odataResponse.prepareModel(compiledModel.abstractSql);
551
506
  deepFreeze(compiledModel.abstractSql);
552
-
553
- const versions = [apiRoot];
554
- if (compiledModel.translateTo != null) {
555
- versions.push(...models[compiledModel.translateTo].versions);
556
- }
557
- models[apiRoot] = {
558
- ...compiledModel,
559
- versions,
560
- };
507
+ models[apiRoot] = compiledModel;
561
508
 
562
509
  // Validate the [empty] model according to the rules.
563
510
  // This may eventually lead to entering obligatory data.
564
511
  // For the moment it blocks such models from execution.
565
- if (compiledModel.sql) {
566
- await validateModel(tx, apiRoot);
567
- }
512
+ await validateModel(tx, apiRoot);
568
513
 
569
514
  // TODO: Can we do this without the cast?
570
515
  api[apiRoot] = new PinejsClient('/' + apiRoot + '/') as LoggingClient;
@@ -624,7 +569,10 @@ export const executeModels = async (
624
569
  let uri = '/dev/model';
625
570
  const body: AnyObject = {
626
571
  is_of__vocabulary: model.vocab,
627
- model_value: model[modelType],
572
+ model_value:
573
+ typeof model[modelType] === 'string'
574
+ ? { value: model[modelType] }
575
+ : model[modelType],
628
576
  model_type: modelType,
629
577
  };
630
578
  const id = result?.[0]?.id;
@@ -666,30 +614,27 @@ const cleanupModel = (vocab: string) => {
666
614
  };
667
615
 
668
616
  export const deleteModel = async (vocabulary: string) => {
669
- const { sql } = models[vocabulary];
670
- if (sql) {
671
- await db.transaction(async (tx) => {
672
- const dropStatements: Array<Promise<any>> = sql.dropSchema.map(
673
- (dropStatement) => tx.executeSql(dropStatement),
674
- );
675
- await Promise.all(
676
- dropStatements.concat([
677
- api.dev.delete({
678
- resource: 'model',
679
- passthrough: {
680
- tx,
681
- req: permissions.root,
682
- },
683
- options: {
684
- $filter: {
685
- is_of__vocabulary: vocabulary,
686
- },
617
+ await db.transaction(async (tx) => {
618
+ const dropStatements: Array<Promise<any>> = models[
619
+ vocabulary
620
+ ].sql.dropSchema.map((dropStatement) => tx.executeSql(dropStatement));
621
+ await Promise.all(
622
+ dropStatements.concat([
623
+ api.dev.delete({
624
+ resource: 'model',
625
+ passthrough: {
626
+ tx,
627
+ req: permissions.root,
628
+ },
629
+ options: {
630
+ $filter: {
631
+ is_of__vocabulary: vocabulary,
687
632
  },
688
- }),
689
- ]),
690
- );
691
- });
692
- }
633
+ },
634
+ }),
635
+ ]),
636
+ );
637
+ });
693
638
  await cleanupModel(vocabulary);
694
639
  };
695
640
 
@@ -982,28 +927,12 @@ export const getAbstractSqlModel = (
982
927
  return (request.abstractSqlModel ??= models[request.vocabulary].abstractSql);
983
928
  };
984
929
 
985
- const getFinalAbstractSqlModel = (
986
- request: Pick<
987
- uriParser.ODataRequest,
988
- 'translateVersions' | 'finalAbstractSqlModel'
989
- >,
990
- ): AbstractSQLCompiler.AbstractSqlModel => {
991
- const finalModel = _.last(request.translateVersions)!;
992
- return (request.finalAbstractSqlModel ??= models[finalModel].abstractSql);
993
- };
994
-
995
930
  const getIdField = (
996
931
  request: Pick<
997
932
  uriParser.ODataRequest,
998
- | 'translateVersions'
999
- | 'finalAbstractSqlModel'
1000
- | 'abstractSqlModel'
1001
- | 'resourceName'
1002
- | 'vocabulary'
933
+ 'vocabulary' | 'abstractSqlModel' | 'resourceName'
1003
934
  >,
1004
- ) =>
1005
- // TODO: Should resolveSynonym also be using the finalAbstractSqlModel?
1006
- getFinalAbstractSqlModel(request).tables[resolveSynonym(request)].idField;
935
+ ) => getAbstractSqlModel(request).tables[resolveSynonym(request)].idField;
1007
936
 
1008
937
  export const getAffectedIds = async (
1009
938
  args: HookArgs & {
@@ -1046,18 +975,17 @@ const $getAffectedIds = async ({
1046
975
  // We reparse to make sure we get a clean odataQuery, without permissions already added
1047
976
  // And we use the request's url rather than the req for things like batch where the req url is ../$batch
1048
977
  const parsedRequest: uriParser.ParsedODataRequest &
1049
- Partial<Pick<uriParser.ODataRequest, 'engine' | 'translateVersions'>> =
978
+ Partial<Pick<uriParser.ODataRequest, 'engine'>> =
1050
979
  await uriParser.parseOData({
1051
980
  method: request.method,
1052
981
  url: `/${request.vocabulary}${request.url}`,
1053
982
  });
1054
983
 
1055
984
  parsedRequest.engine = request.engine;
1056
- parsedRequest.translateVersions = request.translateVersions;
1057
985
  // Mark that the engine is required now that we've set it
1058
986
  let affectedRequest: uriParser.ODataRequest = parsedRequest as RequiredField<
1059
987
  typeof parsedRequest,
1060
- 'engine' | 'translateVersions'
988
+ 'engine'
1061
989
  >;
1062
990
  const abstractSqlModel = getAbstractSqlModel(affectedRequest);
1063
991
  const resourceName = resolveSynonym(affectedRequest);
@@ -1100,18 +1028,10 @@ const runODataRequest = (req: Express.Request, vocabulary: string) => {
1100
1028
 
1101
1029
  // Get the hooks for the current method/vocabulary as we know it,
1102
1030
  // in order to run PREPARSE hooks, before parsing gets us more info
1103
- const { versions } = models[vocabulary];
1104
- const reqHooks = versions.map((version): [string, InstantiatedHooks] => [
1105
- version,
1106
- getHooks(
1107
- {
1108
- method: req.method as SupportedMethod,
1109
- vocabulary: version,
1110
- },
1111
- // Only include the `all` vocab for the first model version
1112
- version === versions[0],
1113
- ),
1114
- ]);
1031
+ const reqHooks = getHooks({
1032
+ method: req.method as SupportedMethod,
1033
+ vocabulary,
1034
+ });
1115
1035
 
1116
1036
  const transactions: Db.Tx[] = [];
1117
1037
  const tryCancelRequest = () => {
@@ -1154,49 +1074,23 @@ const runODataRequest = (req: Express.Request, vocabulary: string) => {
1154
1074
 
1155
1075
  const prepareRequest = async (
1156
1076
  parsedRequest: uriParser.ParsedODataRequest &
1157
- Partial<Pick<uriParser.ODataRequest, 'engine' | 'translateVersions'>>,
1077
+ Partial<Pick<uriParser.ODataRequest, 'engine'>>,
1158
1078
  ): Promise<uriParser.ODataRequest> => {
1159
1079
  parsedRequest.engine = db.engine;
1160
- parsedRequest.translateVersions = [...versions];
1161
- // Mark that the engine/translateVersions is required now that we've set it
1080
+ // Mark that the engine is required now that we've set it
1162
1081
  const $request: uriParser.ODataRequest = parsedRequest as RequiredField<
1163
1082
  typeof parsedRequest,
1164
- 'engine' | 'translateVersions'
1083
+ 'engine'
1165
1084
  >;
1085
+ // Get the full hooks list now that we can.
1086
+ $request.hooks = getHooks($request);
1166
1087
  // Add/check the relevant permissions
1167
1088
  try {
1168
- $request.hooks = [];
1169
- for (const version of versions) {
1170
- // We get the hooks list between each `runHooks` so that any resource renames will be used
1171
- // when getting hooks for later versions
1172
- const hooks: [string, InstantiatedHooks] = [
1173
- version,
1174
- getHooks(
1175
- {
1176
- resourceName: $request.resourceName,
1177
- vocabulary: version,
1178
- method: $request.method,
1179
- },
1180
- // Only include the `all` vocab for the first model version
1181
- version === versions[0],
1182
- ),
1183
- ];
1184
- $request.hooks.push(hooks);
1185
- await runHooks('POSTPARSE', [hooks], {
1186
- req,
1187
- request: $request,
1188
- tx: req.tx,
1189
- });
1190
- const { resourceRenames } = models[version];
1191
- if (resourceRenames) {
1192
- const resourceName = resolveSynonym($request);
1193
- if (resourceRenames[resourceName]) {
1194
- $request.resourceName = sqlNameToODataName(
1195
- resourceRenames[resourceName],
1196
- );
1197
- }
1198
- }
1199
- }
1089
+ await runHooks('POSTPARSE', $request.hooks, {
1090
+ req,
1091
+ request: $request,
1092
+ tx: req.tx,
1093
+ });
1200
1094
  const translatedRequest = await uriParser.translateUri($request);
1201
1095
  return await compileRequest(translatedRequest);
1202
1096
  } catch (err: any) {
@@ -1531,12 +1425,9 @@ const checkReadOnlyRequests = (request: uriParser.ODataRequest) => {
1531
1425
  return true;
1532
1426
  }
1533
1427
  // If there are hooks then check that they're all read-only
1534
- return hooks.every(([, versionedHooks]) =>
1535
- Object.values(versionedHooks).every((hookTypeHooks) => {
1536
- return (
1537
- hookTypeHooks == null || hookTypeHooks.every((hook) => hook.readOnlyTx)
1538
- );
1539
- }),
1428
+ return Object.values(hooks).every(
1429
+ (hookTypeHooks) =>
1430
+ hookTypeHooks == null || hookTypeHooks.every((hook) => hook.readOnlyTx),
1540
1431
  );
1541
1432
  };
1542
1433
 
@@ -1631,7 +1522,7 @@ const respondGet = async (
1631
1522
  const d = await odataResponse.process(
1632
1523
  vocab,
1633
1524
  getAbstractSqlModel(request),
1634
- request.originalResourceName,
1525
+ request.resourceName,
1635
1526
  result.rows,
1636
1527
  { includeMetadata: metadata === 'full' },
1637
1528
  );
@@ -1680,7 +1571,7 @@ const runPost = async (
1680
1571
  if (rowsAffected === 0) {
1681
1572
  throw new PermissionError();
1682
1573
  }
1683
- await validateModel(tx, _.last(request.translateVersions)!, request);
1574
+ await validateModel(tx, request.vocabulary, request);
1684
1575
 
1685
1576
  return insertId;
1686
1577
  };
@@ -1692,11 +1583,7 @@ const respondPost = async (
1692
1583
  tx: Db.Tx,
1693
1584
  ): Promise<Response> => {
1694
1585
  const vocab = request.vocabulary;
1695
- const location = odataResponse.resourceURI(
1696
- vocab,
1697
- request.originalResourceName,
1698
- id,
1699
- );
1586
+ const location = odataResponse.resourceURI(vocab, request.resourceName, id);
1700
1587
  if (env.DEBUG) {
1701
1588
  api[vocab].logger.log('Insert ID: ', request.resourceName, id);
1702
1589
  }
@@ -1754,7 +1641,7 @@ const runPut = async (
1754
1641
  ({ rowsAffected } = await runQuery(tx, request, undefined, idField));
1755
1642
  }
1756
1643
  if (rowsAffected > 0) {
1757
- await validateModel(tx, _.last(request.translateVersions)!, request);
1644
+ await validateModel(tx, request.vocabulary, request);
1758
1645
  }
1759
1646
  return undefined;
1760
1647
  };
@@ -1792,7 +1679,7 @@ const runDelete = async (
1792
1679
  getIdField(request),
1793
1680
  );
1794
1681
  if (rowsAffected > 0) {
1795
- await validateModel(tx, _.last(request.translateVersions)!, request);
1682
+ await validateModel(tx, request.vocabulary, request);
1796
1683
  }
1797
1684
 
1798
1685
  return undefined;
@@ -1812,6 +1699,31 @@ export const executeStandardModels = async (tx: Db.Tx): Promise<void> => {
1812
1699
  ALTER TABLE "model"
1813
1700
  ADD COLUMN IF NOT EXISTS "modified at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL;
1814
1701
  `,
1702
+ '15.0.0-data-types': async ($tx, sbvrUtils) => {
1703
+ switch (sbvrUtils.db.engine) {
1704
+ case 'mysql':
1705
+ await $tx.executeSql(`\
1706
+ ALTER TABLE "model"
1707
+ MODIFY "model value" JSON NOT NULL;
1708
+
1709
+ UPDATE "model"
1710
+ SET "model value" = CAST('{"value":' || CAST("model value" AS CHAR) || '}' AS JSON)
1711
+ WHERE "model type" IN ('se', 'odataMetadata')
1712
+ AND CAST("model value" AS CHAR) LIKE '"%';`);
1713
+ break;
1714
+ case 'postgres':
1715
+ await $tx.executeSql(`\
1716
+ ALTER TABLE "model"
1717
+ ALTER COLUMN "model value" SET DATA TYPE JSONB USING "model value"::JSONB;
1718
+
1719
+ UPDATE "model"
1720
+ SET "model value" = CAST('{"value":' || CAST("model value" AS TEXT) || '}' AS JSON)
1721
+ WHERE "model type" IN ('se', 'odataMetadata')
1722
+ AND CAST("model value" AS TEXT) LIKE '"%';`);
1723
+ break;
1724
+ // No need to migrate for websql
1725
+ }
1726
+ },
1815
1727
  },
1816
1728
  });
1817
1729
  await executeModels(tx, permissions.config.models);
@@ -42,7 +42,6 @@ export interface ParsedODataRequest {
42
42
  url: string;
43
43
  vocabulary: string;
44
44
  resourceName: string;
45
- originalResourceName: string;
46
45
  values: AnyObject;
47
46
  odataQuery: ODataQuery;
48
47
  odataBinds: OdataBinds;
@@ -51,9 +50,7 @@ export interface ParsedODataRequest {
51
50
  _defer?: boolean;
52
51
  }
53
52
  export interface ODataRequest extends ParsedODataRequest {
54
- translateVersions: string[];
55
53
  abstractSqlModel?: AbstractSQLCompiler.AbstractSqlModel;
56
- finalAbstractSqlModel?: AbstractSQLCompiler.AbstractSqlModel;
57
54
  abstractSqlQuery?: AbstractSQLCompiler.AbstractSqlQuery;
58
55
  sqlQuery?: AbstractSQLCompiler.SqlResult | AbstractSQLCompiler.SqlResult[];
59
56
  tx?: Tx;
@@ -62,7 +59,7 @@ export interface ODataRequest extends ParsedODataRequest {
62
59
  >;
63
60
  affectedIds?: number[];
64
61
  pendingAffectedIds?: Promise<number[]>;
65
- hooks?: Array<[string, InstantiatedHooks]>;
62
+ hooks?: InstantiatedHooks;
66
63
  engine: AbstractSQLCompiler.Engines;
67
64
  }
68
65
 
@@ -147,7 +144,8 @@ export const memoizedParseOdata = (() => {
147
144
 
148
145
  export const memoizedGetOData2AbstractSQL = memoizeWeak(
149
146
  (abstractSqlModel: AbstractSQLCompiler.AbstractSqlModel) => {
150
- return new OData2AbstractSQL(abstractSqlModel, undefined, {
147
+ // TODO: REMOVE THIS, it's temporary due to mismatched abstract-sql-compiler versions
148
+ return new OData2AbstractSQL(abstractSqlModel as any, undefined, {
151
149
  // Use minimized aliases when not in debug mode for smaller queries
152
150
  minimizeAliases: !env.DEBUG,
153
151
  });
@@ -294,7 +292,6 @@ export async function parseOData(
294
292
  url,
295
293
  vocabulary: apiRoot,
296
294
  resourceName: odata.tree.resource,
297
- originalResourceName: odata.tree.resource,
298
295
  values: b.data ?? {},
299
296
  odataQuery: odata.tree,
300
297
  odataBinds: odata.binds,
@@ -357,7 +354,6 @@ const parseODataChangeset = (
357
354
  url,
358
355
  vocabulary: apiRoot,
359
356
  resourceName: odata.tree.resource,
360
- originalResourceName: odata.tree.resource,
361
357
  odataBinds: odata.binds,
362
358
  odataQuery: odata.tree,
363
359
  values: b.data ?? {},
@@ -423,7 +419,8 @@ export const translateUri = <
423
419
  return true;
424
420
  },
425
421
  });
426
- request.abstractSqlQuery = abstractSqlQuery;
422
+ // TODO: REMOVE THIS, it's temporary due to mismatched abstract-sql-compiler versions
423
+ request.abstractSqlQuery = abstractSqlQuery as any;
427
424
  return request;
428
425
  }
429
426
  return request;
package/tsconfig.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "removeComments": true,
12
12
  "rootDir": "src",
13
13
  "sourceMap": true,
14
- "target": "es2019",
14
+ "target": "es2021",
15
15
  "declaration": true,
16
16
  "skipLibCheck": true,
17
17
  "resolveJsonModule": true,
@@ -1,6 +0,0 @@
1
- import { AbstractSqlModel, ReferencedFieldNode, Definition, SelectQueryNode, NumberTypeNodes, BooleanTypeNodes, UnknownTypeNodes, NullNode } from '@balena/abstract-sql-compiler';
2
- import { Dictionary } from './common-types';
3
- export type AliasValidNodeType = ReferencedFieldNode | SelectQueryNode | NumberTypeNodes | BooleanTypeNodes | UnknownTypeNodes | NullNode;
4
- export declare const translateAbstractSqlModel: (fromAbstractSqlModel: AbstractSqlModel, toAbstractSqlModel: AbstractSqlModel, fromVersion: string, toVersion: string, translationDefinitions?: Dictionary<(Definition & {
5
- $toResource?: string;
6
- }) | Dictionary<string | AliasValidNodeType>>) => Dictionary<string>;