@balena/pinejs 16.0.0-build--batch-f2ffc3d6bcb9f3294fd4fc9de3c21bfe167e100d-1 → 16.0.0-build-fisehara-update-sbvr-types-cfbbecbb0387e87e17e14be8991be73d1a4efdd0-1

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.
Files changed (141) hide show
  1. package/.pinejs-cache.json +1 -1
  2. package/.versionbot/CHANGELOG.yml +2168 -11
  3. package/CHANGELOG.md +815 -2
  4. package/Gruntfile.ts +9 -6
  5. package/README.md +10 -0
  6. package/build/browser.ts +2 -2
  7. package/build/config.ts +1 -1
  8. package/build/module.ts +2 -2
  9. package/build/server.ts +2 -2
  10. package/docker-compose.npm-test.yml +21 -3
  11. package/out/bin/abstract-sql-compiler.js +5 -5
  12. package/out/bin/abstract-sql-compiler.js.map +1 -1
  13. package/out/bin/odata-compiler.js +10 -10
  14. package/out/bin/odata-compiler.js.map +1 -1
  15. package/out/bin/sbvr-compiler.js +34 -11
  16. package/out/bin/sbvr-compiler.js.map +1 -1
  17. package/out/bin/utils.js +25 -2
  18. package/out/bin/utils.js.map +1 -1
  19. package/out/config-loader/config-loader.d.ts +4 -2
  20. package/out/config-loader/config-loader.js +54 -13
  21. package/out/config-loader/config-loader.js.map +1 -1
  22. package/out/config-loader/env.d.ts +2 -1
  23. package/out/config-loader/env.js +5 -2
  24. package/out/config-loader/env.js.map +1 -1
  25. package/out/data-server/sbvr-server.d.ts +1 -1
  26. package/out/data-server/sbvr-server.js +3 -1
  27. package/out/data-server/sbvr-server.js.map +1 -1
  28. package/out/database-layer/db.js +40 -14
  29. package/out/database-layer/db.js.map +1 -1
  30. package/out/express-emulator/express.js +5 -3
  31. package/out/express-emulator/express.js.map +1 -1
  32. package/out/http-transactions/transactions.d.ts +1 -1
  33. package/out/http-transactions/transactions.js +10 -5
  34. package/out/http-transactions/transactions.js.map +1 -1
  35. package/out/migrator/async.js +32 -5
  36. package/out/migrator/async.js.map +1 -1
  37. package/out/migrator/sync.d.ts +2 -1
  38. package/out/migrator/sync.js +29 -3
  39. package/out/migrator/sync.js.map +1 -1
  40. package/out/migrator/utils.d.ts +6 -3
  41. package/out/migrator/utils.js +30 -4
  42. package/out/migrator/utils.js.map +1 -1
  43. package/out/odata-metadata/odata-metadata-generator.js +4 -1
  44. package/out/odata-metadata/odata-metadata-generator.js.map +1 -1
  45. package/out/passport-pinejs/mount-login-router.d.ts +3 -0
  46. package/out/passport-pinejs/mount-login-router.js +65 -0
  47. package/out/passport-pinejs/mount-login-router.js.map +1 -0
  48. package/out/passport-pinejs/passport-pinejs.d.ts +2 -1
  49. package/out/passport-pinejs/passport-pinejs.js +28 -2
  50. package/out/passport-pinejs/passport-pinejs.js.map +1 -1
  51. package/out/pinejs-session-store/pinejs-session-store.js +30 -7
  52. package/out/pinejs-session-store/pinejs-session-store.js.map +1 -1
  53. package/out/sbvr-api/abstract-sql.d.ts +2 -2
  54. package/out/sbvr-api/abstract-sql.js +35 -9
  55. package/out/sbvr-api/abstract-sql.js.map +1 -1
  56. package/out/sbvr-api/cached-compile.js +9 -6
  57. package/out/sbvr-api/cached-compile.js.map +1 -1
  58. package/out/sbvr-api/common-types.d.ts +1 -1
  59. package/out/sbvr-api/control-flow.js +5 -2
  60. package/out/sbvr-api/control-flow.js.map +1 -1
  61. package/out/sbvr-api/express-extension.d.ts +10 -7
  62. package/out/sbvr-api/express-extension.js +1 -0
  63. package/out/sbvr-api/hooks.d.ts +5 -1
  64. package/out/sbvr-api/hooks.js +12 -10
  65. package/out/sbvr-api/hooks.js.map +1 -1
  66. package/out/sbvr-api/odata-response.d.ts +5 -2
  67. package/out/sbvr-api/odata-response.js +36 -6
  68. package/out/sbvr-api/odata-response.js.map +1 -1
  69. package/out/sbvr-api/permissions.d.ts +6 -7
  70. package/out/sbvr-api/permissions.js +69 -38
  71. package/out/sbvr-api/permissions.js.map +1 -1
  72. package/out/sbvr-api/sbvr-utils.d.ts +20 -9
  73. package/out/sbvr-api/sbvr-utils.js +134 -136
  74. package/out/sbvr-api/sbvr-utils.js.map +1 -1
  75. package/out/sbvr-api/translations.d.ts +2 -2
  76. package/out/sbvr-api/translations.js +17 -10
  77. package/out/sbvr-api/translations.js.map +1 -1
  78. package/out/sbvr-api/uri-parser.d.ts +7 -10
  79. package/out/sbvr-api/uri-parser.js +46 -19
  80. package/out/sbvr-api/uri-parser.js.map +1 -1
  81. package/out/server-glue/global-ext.d.ts +2 -1
  82. package/out/server-glue/module.d.ts +3 -1
  83. package/out/server-glue/module.js +40 -13
  84. package/out/server-glue/module.js.map +1 -1
  85. package/out/server-glue/sbvr-loader.js.map +1 -1
  86. package/out/server-glue/server.js +31 -39
  87. package/out/server-glue/server.js.map +1 -1
  88. package/out/webresource-handler/handlers/NoopHandler.d.ts +7 -0
  89. package/out/webresource-handler/handlers/NoopHandler.js +20 -0
  90. package/out/webresource-handler/handlers/NoopHandler.js.map +1 -0
  91. package/out/webresource-handler/handlers/S3Handler.d.ts +28 -0
  92. package/out/webresource-handler/handlers/S3Handler.js +97 -0
  93. package/out/webresource-handler/handlers/S3Handler.js.map +1 -0
  94. package/out/webresource-handler/handlers/index.d.ts +2 -0
  95. package/out/webresource-handler/handlers/index.js +19 -0
  96. package/out/webresource-handler/handlers/index.js.map +1 -0
  97. package/out/webresource-handler/index.d.ts +34 -0
  98. package/out/webresource-handler/index.js +307 -0
  99. package/out/webresource-handler/index.js.map +1 -0
  100. package/package.json +68 -62
  101. package/src/bin/abstract-sql-compiler.ts +7 -9
  102. package/src/bin/odata-compiler.ts +12 -15
  103. package/src/bin/sbvr-compiler.ts +14 -18
  104. package/src/bin/utils.ts +1 -1
  105. package/src/config-loader/config-loader.ts +44 -10
  106. package/src/config-loader/env.ts +1 -1
  107. package/src/data-server/sbvr-server.js +3 -1
  108. package/src/database-layer/db.ts +23 -19
  109. package/src/express-emulator/express.js +5 -3
  110. package/src/extended-sbvr-parser/extended-sbvr-parser.ts +1 -1
  111. package/src/http-transactions/transactions.js +10 -5
  112. package/src/migrator/async.ts +7 -6
  113. package/src/migrator/sync.ts +10 -7
  114. package/src/migrator/utils.ts +11 -5
  115. package/src/odata-metadata/odata-metadata-generator.ts +2 -2
  116. package/src/passport-pinejs/mount-login-router.ts +46 -0
  117. package/src/passport-pinejs/passport-pinejs.ts +7 -3
  118. package/src/pinejs-session-store/pinejs-session-store.ts +6 -6
  119. package/src/sbvr-api/abstract-sql.ts +5 -5
  120. package/src/sbvr-api/cached-compile.ts +1 -2
  121. package/src/sbvr-api/common-types.ts +1 -1
  122. package/src/sbvr-api/control-flow.ts +1 -1
  123. package/src/sbvr-api/express-extension.ts +12 -8
  124. package/src/sbvr-api/hooks.ts +11 -11
  125. package/src/sbvr-api/odata-response.ts +56 -9
  126. package/src/sbvr-api/permissions.ts +44 -35
  127. package/src/sbvr-api/sbvr-utils.ts +118 -172
  128. package/src/sbvr-api/translations.ts +9 -6
  129. package/src/sbvr-api/uri-parser.ts +22 -28
  130. package/src/server-glue/global-ext.d.ts +2 -1
  131. package/src/server-glue/module.ts +8 -2
  132. package/src/server-glue/sbvr-loader.ts +1 -1
  133. package/src/server-glue/server.ts +11 -49
  134. package/src/webresource-handler/handlers/NoopHandler.ts +21 -0
  135. package/src/webresource-handler/handlers/S3Handler.ts +143 -0
  136. package/src/webresource-handler/handlers/index.ts +2 -0
  137. package/src/webresource-handler/index.ts +450 -0
  138. package/tsconfig.dev.json +2 -1
  139. package/tsconfig.json +1 -1
  140. package/typings/lf-to-abstract-sql.d.ts +1 -1
  141. package/typings/memoizee.d.ts +3 -4
@@ -1,46 +1,72 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
2
28
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.setup = exports.executeStandardModels = exports.handleHttpErrors = exports.onHandleHttpError = exports.handleODataRequest = exports.getAffectedIds = exports.getAbstractSqlModel = exports.runURI = exports.api = exports.PinejsClient = exports.runRule = exports.getID = exports.deleteModel = exports.executeModels = exports.executeModel = exports.generateModels = exports.generateSqlModel = exports.generateAbstractSqlModel = exports.generateLfModel = exports.validateModel = exports.isModelNew = exports.resolveNavigationResource = exports.resolveSynonym = exports.resolveOdataBind = exports.sbvrTypes = exports.db = exports.addSideEffectHook = exports.addPureHook = void 0;
4
- const _ = require("lodash");
29
+ exports.postSetup = exports.setup = exports.executeStandardModels = exports.handleHttpErrors = exports.onHandleHttpError = exports.handleODataRequest = exports.getApiRoot = exports.getModel = exports.getAffectedIds = exports.getAbstractSqlModel = exports.runURI = exports.api = exports.PinejsClient = exports.runRule = exports.getID = exports.deleteModel = exports.postExecuteModels = exports.executeModels = exports.executeModel = exports.generateModels = exports.generateSqlModel = exports.generateAbstractSqlModel = exports.generateLfModel = exports.validateModel = exports.isModelNew = exports.resolveNavigationResource = exports.resolveSynonym = exports.resolveOdataBind = exports.sbvrTypes = exports.db = exports.addSideEffectHook = exports.addPureHook = void 0;
30
+ const lodash_1 = __importDefault(require("lodash"));
5
31
  const cached_compile_1 = require("./cached-compile");
6
- const AbstractSQLCompiler = require("@balena/abstract-sql-compiler");
32
+ const AbstractSQLCompiler = __importStar(require("@balena/abstract-sql-compiler"));
7
33
  const package_json_1 = require("@balena/abstract-sql-compiler/package.json");
8
- const LF2AbstractSQL = require("@balena/lf-to-abstract-sql");
34
+ const LF2AbstractSQL = __importStar(require("@balena/lf-to-abstract-sql"));
9
35
  const odata_to_abstract_sql_1 = require("@balena/odata-to-abstract-sql");
10
- const sbvr_types_1 = require("@balena/sbvr-types");
36
+ const sbvr_types_1 = __importDefault(require("@balena/sbvr-types"));
11
37
  exports.sbvrTypes = sbvr_types_1.default;
12
38
  const deepFreeze = require("deep-freeze");
13
39
  const pinejs_client_core_1 = require("pinejs-client-core");
14
40
  const extended_sbvr_parser_1 = require("../extended-sbvr-parser/extended-sbvr-parser");
15
- const asyncMigrator = require("../migrator/async");
16
- const syncMigrator = require("../migrator/sync");
41
+ const asyncMigrator = __importStar(require("../migrator/async"));
42
+ const syncMigrator = __importStar(require("../migrator/sync"));
17
43
  const odata_metadata_generator_1 = require("../odata-metadata/odata-metadata-generator");
18
44
  const devModel = require('./dev.sbvr');
19
- const permissions = require("./permissions");
45
+ const permissions = __importStar(require("./permissions"));
20
46
  const errors_1 = require("./errors");
21
- const uriParser = require("./uri-parser");
47
+ const uriParser = __importStar(require("./uri-parser"));
22
48
  const hooks_1 = require("./hooks");
23
49
  var hooks_2 = require("./hooks");
24
50
  Object.defineProperty(exports, "addPureHook", { enumerable: true, get: function () { return hooks_2.addPureHook; } });
25
51
  Object.defineProperty(exports, "addSideEffectHook", { enumerable: true, get: function () { return hooks_2.addSideEffectHook; } });
26
52
  const memoizeWeak = require("memoizee/weak");
27
- const controlFlow = require("./control-flow");
53
+ const controlFlow = __importStar(require("./control-flow"));
28
54
  exports.db = undefined;
29
55
  const package_json_2 = require("@balena/lf-to-abstract-sql/package.json");
30
56
  const package_json_3 = require("@balena/sbvr-types/package.json");
31
57
  const abstract_sql_1 = require("./abstract-sql");
32
58
  var abstract_sql_2 = require("./abstract-sql");
33
59
  Object.defineProperty(exports, "resolveOdataBind", { enumerable: true, get: function () { return abstract_sql_2.resolveOdataBind; } });
34
- const odataResponse = require("./odata-response");
60
+ const odataResponse = __importStar(require("./odata-response"));
35
61
  const module_1 = require("../server-glue/module");
36
62
  const translations_1 = require("./translations");
37
- const validBatchMethods = new Set(['PUT', 'POST', 'PATCH', 'DELETE', 'GET']);
63
+ const utils_1 = require("../migrator/utils");
38
64
  const LF2AbstractSQLTranslator = LF2AbstractSQL.createTranslator(sbvr_types_1.default);
39
65
  const LF2AbstractSQLTranslatorVersion = `${package_json_2.version}+${package_json_3.version}`;
40
66
  const models = {};
41
67
  const memoizedResolvedSynonym = memoizeWeak((abstractSqlModel, resourceName) => {
42
68
  const sqlName = (0, odata_to_abstract_sql_1.odataNameToSqlName)(resourceName);
43
- return _(sqlName)
69
+ return (0, lodash_1.default)(sqlName)
44
70
  .split('-')
45
71
  .map((namePart) => {
46
72
  const synonym = abstractSqlModel.synonyms[namePart];
@@ -62,7 +88,7 @@ const memoizedResolveNavigationResource = memoizeWeak((abstractSqlModel, resourc
62
88
  .flatMap((namePart) => memoizedResolvedSynonym(abstractSqlModel, namePart).split('-'));
63
89
  navigation.push('$');
64
90
  const resolvedResourceName = memoizedResolvedSynonym(abstractSqlModel, resourceName);
65
- const mapping = _.get(abstractSqlModel.relationships[resolvedResourceName], navigation);
91
+ const mapping = lodash_1.default.get(abstractSqlModel.relationships[resolvedResourceName], navigation);
66
92
  if (mapping == null) {
67
93
  throw new Error(`Cannot navigate from '${resourceName}' to '${navigationName}'`);
68
94
  }
@@ -85,11 +111,12 @@ const prettifyConstraintError = (err, request) => {
85
111
  matches =
86
112
  /ER_DUP_ENTRY: Duplicate entry '.*?[^\\]' for key '(.*?[^\\])'/.exec(err.message);
87
113
  break;
88
- case 'postgres':
114
+ case 'postgres': {
89
115
  const resourceName = (0, exports.resolveSynonym)(request);
90
116
  const abstractSqlModel = getFinalAbstractSqlModel(request);
91
117
  matches = new RegExp('"' + abstractSqlModel.tables[resourceName].name + '_(.*?)_key"').exec(err.message);
92
118
  break;
119
+ }
93
120
  }
94
121
  if (matches == null) {
95
122
  throw new exports.db.UniqueConstraintError('Unique key constraint violated');
@@ -108,7 +135,7 @@ const prettifyConstraintError = (err, request) => {
108
135
  matches =
109
136
  /ER_ROW_IS_REFERENCED_: Cannot delete or update a parent row: a foreign key constraint fails \(".*?"\.(".*?").*/.exec(err.message);
110
137
  break;
111
- case 'postgres':
138
+ case 'postgres': {
112
139
  const resourceName = (0, exports.resolveSynonym)(request);
113
140
  const abstractSqlModel = getFinalAbstractSqlModel(request);
114
141
  const tableName = abstractSqlModel.tables[resourceName].name;
@@ -123,6 +150,7 @@ const prettifyConstraintError = (err, request) => {
123
150
  '_(.*?)_fkey"').exec(err.message);
124
151
  }
125
152
  break;
153
+ }
126
154
  }
127
155
  if (matches == null) {
128
156
  throw new exports.db.ForeignKeyConstraintError('Foreign key constraint violated');
@@ -277,7 +305,7 @@ const executeModels = async (tx, execModels) => {
277
305
  try {
278
306
  const compiledModels = await Promise.all(execModels.map(async (model) => {
279
307
  const { apiRoot } = model;
280
- await syncMigrator.run(tx, model);
308
+ const migrationExecutionResult = await syncMigrator.run(tx, model);
281
309
  const compiledModel = generateModels(model, exports.db.engine);
282
310
  if (compiledModel.sql) {
283
311
  for (const createStatement of compiledModel.sql.createSchema) {
@@ -300,6 +328,9 @@ const executeModels = async (tx, execModels) => {
300
328
  models[apiRoot] = {
301
329
  ...compiledModel,
302
330
  versions,
331
+ modelExecutionResult: {
332
+ migrationExecutionResult,
333
+ },
303
334
  };
304
335
  if (compiledModel.sql) {
305
336
  await (0, exports.validateModel)(tx, apiRoot);
@@ -314,7 +345,7 @@ const executeModels = async (tx, execModels) => {
314
345
  if (key !== 'Console' &&
315
346
  typeof logger[key] === 'function' &&
316
347
  !(model.logging?.[key] ?? defaultSetting)) {
317
- logger[key] = _.noop;
348
+ logger[key] = lodash_1.default.noop;
318
349
  }
319
350
  }
320
351
  }
@@ -385,6 +416,16 @@ const executeModels = async (tx, execModels) => {
385
416
  }
386
417
  };
387
418
  exports.executeModels = executeModels;
419
+ const postExecuteModels = async (tx) => {
420
+ for (const modelKey of Object.keys(models)) {
421
+ const pendingToSetExecutedMigrations = models[modelKey]?.modelExecutionResult?.migrationExecutionResult
422
+ ?.pendingUnsetMigrations;
423
+ if (pendingToSetExecutedMigrations != null) {
424
+ await (0, utils_1.setExecutedMigrations)(tx, modelKey, pendingToSetExecutedMigrations);
425
+ }
426
+ }
427
+ };
428
+ exports.postExecuteModels = postExecuteModels;
388
429
  const cleanupModel = (vocab) => {
389
430
  delete models[vocab];
390
431
  delete exports.api[vocab];
@@ -479,7 +520,7 @@ exports.runRule = (() => {
479
520
  resourceName = ruleLF[1][1][1][2][1];
480
521
  }
481
522
  let fetchingViolators = false;
482
- const ruleAbs = _.last(abstractSqlModel.rules);
523
+ const ruleAbs = lodash_1.default.last(abstractSqlModel.rules);
483
524
  if (ruleAbs == null) {
484
525
  throw new Error('Unable to generate rule');
485
526
  }
@@ -530,7 +571,7 @@ exports.runRule = (() => {
530
571
  const table = models[vocab].abstractSql.tables[resourceName];
531
572
  const odataIdField = (0, odata_to_abstract_sql_1.sqlNameToODataName)(table.idField);
532
573
  let ids = result.rows.map((row) => row[table.idField]);
533
- ids = _.uniq(ids);
574
+ ids = lodash_1.default.uniq(ids);
534
575
  ids = ids.map((id) => odataIdField + ' eq ' + id);
535
576
  let filter;
536
577
  if (ids.length > 0) {
@@ -578,13 +619,13 @@ const runURI = async (method, uri, body = {}, tx, req, custom) => {
578
619
  permissions: [],
579
620
  };
580
621
  }
581
- _.forEach(body, (v, k) => {
622
+ lodash_1.default.forEach(body, (v, k) => {
582
623
  if (v === undefined) {
583
624
  delete body[k];
584
625
  }
585
626
  });
586
627
  const emulatedReq = {
587
- on: _.noop,
628
+ on: lodash_1.default.noop,
588
629
  custom,
589
630
  user,
590
631
  apiKey,
@@ -597,16 +638,16 @@ const runURI = async (method, uri, body = {}, tx, req, custom) => {
597
638
  };
598
639
  const { promise } = runODataRequest(emulatedReq, apiRoot);
599
640
  const [response] = await promise;
600
- if (_.isError(response)) {
641
+ if (lodash_1.default.isError(response)) {
601
642
  throw response;
602
643
  }
603
- const { body: responseBody, status, headers } = response;
604
- if (status != null && status >= 400) {
605
- const ErrorClass = errors_1.statusCodeToError[status];
644
+ const { body: responseBody, statusCode, headers } = response;
645
+ if (statusCode != null && statusCode >= 400) {
646
+ const ErrorClass = errors_1.statusCodeToError[statusCode];
606
647
  if (ErrorClass != null) {
607
648
  throw new ErrorClass(undefined, responseBody, headers);
608
649
  }
609
- throw new errors_1.HttpError(status, undefined, responseBody, headers);
650
+ throw new errors_1.HttpError(statusCode, undefined, responseBody, headers);
610
651
  }
611
652
  return responseBody;
612
653
  };
@@ -616,7 +657,7 @@ const getAbstractSqlModel = (request) => {
616
657
  };
617
658
  exports.getAbstractSqlModel = getAbstractSqlModel;
618
659
  const getFinalAbstractSqlModel = (request) => {
619
- const finalModel = _.last(request.translateVersions);
660
+ const finalModel = lodash_1.default.last(request.translateVersions);
620
661
  return (request.finalAbstractSqlModel ??= models[finalModel].abstractSql);
621
662
  };
622
663
  const getIdField = (request) => getFinalAbstractSqlModel(request).tables[(0, exports.resolveSynonym)(request)].idField;
@@ -638,8 +679,7 @@ const $getAffectedIds = async ({ req, request, tx, }) => {
638
679
  if (!['PATCH', 'DELETE'].includes(request.method)) {
639
680
  throw new Error('Can only call `getAffectedIds` with PATCH/DELETE requests');
640
681
  }
641
- const parsedRequest = await uriParser.parseOData({
642
- id: request.batchRequestId,
682
+ const parsedRequest = uriParser.parseOData({
643
683
  method: request.method,
644
684
  url: `/${request.vocabulary}${request.url}`,
645
685
  });
@@ -671,61 +711,14 @@ const $getAffectedIds = async ({ req, request, tx, }) => {
671
711
  }
672
712
  return result.rows.map((row) => row[idField]);
673
713
  };
674
- const validateBatch = (req) => {
675
- const { requests } = req.body;
676
- if (!Array.isArray(requests)) {
677
- throw new errors_1.BadRequestError('Batch requests must include an array of requests in the body via the "requests" property');
678
- }
679
- if (req.headers != null && req.headers['content-type'] == null) {
680
- throw new errors_1.BadRequestError('Headers in a batch request must include a "content-type" header if they are provided');
681
- }
682
- if (requests.find((request) => request.headers?.authorization != null ||
683
- request.url?.includes('apikey=')) != null) {
684
- throw new errors_1.BadRequestError('Authorization may only be passed to the main batch request');
685
- }
686
- const ids = new Set(requests
687
- .map((request) => request.id)
688
- .filter((id) => typeof id === 'string'));
689
- if (ids.size !== requests.length) {
690
- throw new errors_1.BadRequestError('All requests in a batch request must have unique string ids');
691
- }
692
- for (const request of requests) {
693
- if (request.headers != null &&
694
- request.headers['content-type'] == null &&
695
- (req.headers == null || req.headers['content-type'] == null)) {
696
- throw new errors_1.BadRequestError('Requests of a batch request that have headers must include a "content-type" header');
697
- }
698
- if (request.method == null) {
699
- throw new errors_1.BadRequestError('Requests of a batch request must have a "method"');
700
- }
701
- const upperCaseMethod = request.method.toUpperCase();
702
- if (!validBatchMethods.has(upperCaseMethod)) {
703
- throw new errors_1.BadRequestError(`Requests of a batch request must have a method matching one of the following: ${Array.from(validBatchMethods).join(', ')}`);
704
- }
705
- if (request.body !== undefined &&
706
- (upperCaseMethod === 'GET' || upperCaseMethod === 'DELETE')) {
707
- throw new errors_1.BadRequestError('GET and DELETE requests of a batch request must not have a body');
708
- }
709
- }
710
- const urls = new Set(requests.map((request) => request.url));
711
- if (urls.has(undefined)) {
712
- throw new errors_1.BadRequestError('Requests of a batch request must have a "url"');
713
- }
714
- if (urls.has('/university/$batch')) {
715
- throw new errors_1.BadRequestError('Batch requests cannot contain batch requests');
716
- }
717
- const urlModels = new Set(Array.from(urls.values()).map((url) => url.split('/')[1]));
718
- if (urlModels.size > 1) {
719
- throw new errors_1.BadRequestError('Batch requests must consist of requests for only one model');
720
- }
714
+ const getModel = (vocabulary) => {
715
+ return models[vocabulary];
721
716
  };
717
+ exports.getModel = getModel;
722
718
  const runODataRequest = (req, vocabulary) => {
723
719
  if (module_1.env.DEBUG) {
724
720
  exports.api[vocabulary].logger.log('Parsing', req.method, req.url);
725
721
  }
726
- if (req.url.startsWith(`/${vocabulary}/$batch`)) {
727
- validateBatch(req);
728
- }
729
722
  const { versions } = models[vocabulary];
730
723
  const reqHooks = versions.map((version) => [
731
724
  version,
@@ -760,25 +753,27 @@ const runODataRequest = (req, vocabulary) => {
760
753
  promise: (async () => {
761
754
  await (0, hooks_1.runHooks)('PREPARSE', reqHooks, { req, tx: req.tx });
762
755
  let requests;
763
- if (req.url.startsWith(`/${vocabulary}/$batch`)) {
764
- await Promise.all(req.body.requests.map(async (request) => await (0, hooks_1.runHooks)('PREPARSE', reqHooks, {
765
- req: request,
766
- tx: req.tx,
767
- })));
768
- requests = req.body.requests;
756
+ if (req.batch != null && req.batch.length > 0) {
757
+ requests = req.batch;
769
758
  }
770
759
  else {
771
760
  const { method, url, body } = req;
772
- requests = [{ method, url, body }];
761
+ requests = [{ method, url, data: body }];
773
762
  }
774
763
  const prepareRequest = async (parsedRequest) => {
775
- if (models[parsedRequest.vocabulary] == null) {
764
+ const abstractSqlModel = (0, exports.getAbstractSqlModel)(parsedRequest);
765
+ if (abstractSqlModel == null) {
776
766
  throw new errors_1.BadRequestError('Unknown vocabulary: ' + parsedRequest.vocabulary);
777
767
  }
778
768
  parsedRequest.engine = exports.db.engine;
779
769
  parsedRequest.translateVersions = [...versions];
780
770
  const $request = parsedRequest;
781
771
  try {
772
+ const resolvedResourceName = (0, exports.resolveSynonym)($request);
773
+ if (abstractSqlModel.tables[resolvedResourceName] == null &&
774
+ !resolvedResourceName.endsWith('#canAccess')) {
775
+ throw new errors_1.UnauthorizedError();
776
+ }
782
777
  $request.hooks = [];
783
778
  for (const version of versions) {
784
779
  const hooks = [
@@ -813,10 +808,7 @@ const runODataRequest = (req, vocabulary) => {
813
808
  }
814
809
  };
815
810
  const results = await mappingFn(requests, async (requestPart) => {
816
- const parsedRequest = await uriParser.parseOData(requestPart, req.url.startsWith(`/${vocabulary}/$batch`) &&
817
- !requestPart.url.includes(`/${vocabulary}/$batch`)
818
- ? req.headers
819
- : undefined);
811
+ const parsedRequest = uriParser.parseOData(requestPart);
820
812
  let request;
821
813
  if (Array.isArray(parsedRequest)) {
822
814
  request = await controlFlow.mapSeries(parsedRequest, prepareRequest);
@@ -851,13 +843,13 @@ const runODataRequest = (req, vocabulary) => {
851
843
  });
852
844
  });
853
845
  const responses = results.map((result) => {
854
- if (_.isError(result)) {
846
+ if (lodash_1.default.isError(result)) {
855
847
  return convertToHttpError(result);
856
848
  }
857
849
  else {
858
850
  if (!Array.isArray(result) &&
859
851
  result.body == null &&
860
- result.status == null) {
852
+ result.statusCode == null) {
861
853
  console.error('No status or body set', req.url, responses);
862
854
  return new errors_1.InternalRequestError();
863
855
  }
@@ -868,8 +860,13 @@ const runODataRequest = (req, vocabulary) => {
868
860
  })(),
869
861
  };
870
862
  };
871
- const handleODataRequest = async (req, res, next) => {
863
+ const getApiRoot = (req) => {
872
864
  const [, apiRoot] = req.url.split('/', 2);
865
+ return apiRoot;
866
+ };
867
+ exports.getApiRoot = getApiRoot;
868
+ const handleODataRequest = async (req, res, next) => {
869
+ const apiRoot = (0, exports.getApiRoot)(req);
873
870
  if (apiRoot == null || models[apiRoot] == null) {
874
871
  return next('route');
875
872
  }
@@ -878,8 +875,7 @@ const handleODataRequest = async (req, res, next) => {
878
875
  res.on('close', tryCancelRequest);
879
876
  const responses = await promise;
880
877
  res.set('Cache-Control', 'no-cache');
881
- if (!req.url.startsWith(`/${apiRoot}/$batch`) ||
882
- req.body.requests?.length === 0) {
878
+ if (req.batch == null || req.batch.length === 0) {
883
879
  let [response] = responses;
884
880
  if (response instanceof errors_1.HttpError) {
885
881
  response = httpErrorToResponse(response);
@@ -887,16 +883,14 @@ const handleODataRequest = async (req, res, next) => {
887
883
  handleResponse(res, response);
888
884
  }
889
885
  else {
890
- res.status(200).json({
891
- responses: responses.map((response) => {
892
- if (response instanceof errors_1.HttpError) {
893
- return httpErrorToResponse(response);
894
- }
895
- else {
896
- return response;
897
- }
898
- }),
899
- });
886
+ res.status(200).sendMulti(responses.map((response) => {
887
+ if (response instanceof errors_1.HttpError) {
888
+ return httpErrorToResponse(response);
889
+ }
890
+ else {
891
+ return response;
892
+ }
893
+ }));
900
894
  }
901
895
  }
902
896
  catch (e) {
@@ -918,7 +912,7 @@ const handleHttpErrors = (req, res, err) => {
918
912
  for (const handleErrorFn of handleErrorFns) {
919
913
  handleErrorFn(req, err);
920
914
  }
921
- const response = httpErrorToResponse(err, req);
915
+ const response = httpErrorToResponse(err);
922
916
  handleResponse(res, response);
923
917
  return true;
924
918
  }
@@ -926,9 +920,9 @@ const handleHttpErrors = (req, res, err) => {
926
920
  };
927
921
  exports.handleHttpErrors = handleHttpErrors;
928
922
  const handleResponse = (res, response) => {
929
- const { body, headers, status } = response;
923
+ const { body, headers, statusCode } = response;
930
924
  res.set(headers);
931
- res.status(status);
925
+ res.status(statusCode);
932
926
  if (!body) {
933
927
  res.end();
934
928
  }
@@ -936,11 +930,10 @@ const handleResponse = (res, response) => {
936
930
  res.json(body);
937
931
  }
938
932
  };
939
- const httpErrorToResponse = (err, req) => {
940
- const message = err.getResponseBody();
933
+ const httpErrorToResponse = (err) => {
941
934
  return {
942
- status: err.status,
943
- body: req != null && 'batch' in req ? { responses: [], message } : message,
935
+ statusCode: err.status,
936
+ body: err.getResponseBody(),
944
937
  headers: err.headers,
945
938
  };
946
939
  };
@@ -1032,8 +1025,7 @@ const runChangeSet = (req, tx) => async (changeSetResults, request) => {
1032
1025
  throw new Error('No request id');
1033
1026
  }
1034
1027
  result.headers ??= {};
1035
- result.headers['content-id'] = request.batchRequestId;
1036
- result.id = request.batchRequestId;
1028
+ result.headers['content-id'] = request.id;
1037
1029
  changeSetResults.set(request.id, result);
1038
1030
  };
1039
1031
  const updateBinds = (changeSetResults, request) => {
@@ -1054,29 +1046,22 @@ const updateBinds = (changeSetResults, request) => {
1054
1046
  return request;
1055
1047
  };
1056
1048
  const prepareResponse = async (req, request, result, tx) => {
1057
- let response;
1058
1049
  switch (request.method) {
1059
1050
  case 'GET':
1060
- response = await respondGet(req, request, result, tx);
1061
- break;
1051
+ return await respondGet(req, request, result, tx);
1062
1052
  case 'POST':
1063
- response = await respondPost(req, request, result, tx);
1064
- break;
1053
+ return await respondPost(req, request, result, tx);
1065
1054
  case 'PUT':
1066
1055
  case 'PATCH':
1067
1056
  case 'MERGE':
1068
- response = await respondPut(req, request, result, tx);
1069
- break;
1057
+ return await respondPut(req, request, result, tx);
1070
1058
  case 'DELETE':
1071
- response = await respondDelete(req, request, result, tx);
1072
- break;
1059
+ return await respondDelete(req, request, result, tx);
1073
1060
  case 'OPTIONS':
1074
- response = await respondOptions(req, request, result, tx);
1075
- break;
1061
+ return await respondOptions(req, request, result, tx);
1076
1062
  default:
1077
1063
  throw new errors_1.MethodNotAllowedError();
1078
1064
  }
1079
- return { ...response, id: request.batchRequestId };
1080
1065
  };
1081
1066
  const checkReadOnlyRequests = (request) => {
1082
1067
  if (request.method !== 'GET') {
@@ -1145,7 +1130,7 @@ const respondGet = async (req, request, result, tx) => {
1145
1130
  : undefined;
1146
1131
  const d = await odataResponse.process(vocab, (0, exports.getAbstractSqlModel)(request), request.originalResourceName, result.rows, { includeMetadata: metadata === 'full' });
1147
1132
  const response = {
1148
- status: 200,
1133
+ statusCode: 200,
1149
1134
  body: { d },
1150
1135
  headers: { 'content-type': 'application/json' },
1151
1136
  };
@@ -1161,14 +1146,14 @@ const respondGet = async (req, request, result, tx) => {
1161
1146
  else {
1162
1147
  if (request.resourceName === '$metadata') {
1163
1148
  return {
1164
- status: 200,
1149
+ statusCode: 200,
1165
1150
  body: models[vocab].odataMetadata,
1166
1151
  headers: { 'content-type': 'xml' },
1167
1152
  };
1168
1153
  }
1169
1154
  else {
1170
1155
  return {
1171
- status: 404,
1156
+ statusCode: 404,
1172
1157
  };
1173
1158
  }
1174
1159
  }
@@ -1178,7 +1163,7 @@ const runPost = async (_req, request, tx) => {
1178
1163
  if (rowsAffected === 0) {
1179
1164
  throw new errors_1.PermissionError();
1180
1165
  }
1181
- await (0, exports.validateModel)(tx, _.last(request.translateVersions), request);
1166
+ await (0, exports.validateModel)(tx, lodash_1.default.last(request.translateVersions), request);
1182
1167
  return insertId;
1183
1168
  };
1184
1169
  const respondPost = async (req, request, id, tx) => {
@@ -1197,7 +1182,7 @@ const respondPost = async (req, request, id, tx) => {
1197
1182
  }
1198
1183
  }
1199
1184
  const response = {
1200
- status: 201,
1185
+ statusCode: 201,
1201
1186
  body: result.d[0],
1202
1187
  headers: {
1203
1188
  'content-type': 'application/json',
@@ -1225,13 +1210,13 @@ const runPut = async (_req, request, tx) => {
1225
1210
  ({ rowsAffected } = await runQuery(tx, request, undefined, true));
1226
1211
  }
1227
1212
  if (rowsAffected > 0) {
1228
- await (0, exports.validateModel)(tx, _.last(request.translateVersions), request);
1213
+ await (0, exports.validateModel)(tx, lodash_1.default.last(request.translateVersions), request);
1229
1214
  }
1230
1215
  return undefined;
1231
1216
  };
1232
1217
  const respondPut = async (req, request, result, tx) => {
1233
1218
  const response = {
1234
- status: 200,
1219
+ statusCode: 200,
1235
1220
  };
1236
1221
  await (0, hooks_1.runHooks)('PRERESPOND', request.hooks, {
1237
1222
  req,
@@ -1247,7 +1232,7 @@ const respondOptions = respondPut;
1247
1232
  const runDelete = async (_req, request, tx) => {
1248
1233
  const { rowsAffected } = await runQuery(tx, request, undefined, true);
1249
1234
  if (rowsAffected > 0) {
1250
- await (0, exports.validateModel)(tx, _.last(request.translateVersions), request);
1235
+ await (0, exports.validateModel)(tx, lodash_1.default.last(request.translateVersions), request);
1251
1236
  }
1252
1237
  return undefined;
1253
1238
  };
@@ -1318,4 +1303,17 @@ const setup = async (_app, $db) => {
1318
1303
  }
1319
1304
  };
1320
1305
  exports.setup = setup;
1306
+ const postSetup = async (_app, $db) => {
1307
+ exports.db = exports.db = $db;
1308
+ try {
1309
+ await exports.db.transaction(async (tx) => {
1310
+ await (0, exports.postExecuteModels)(tx);
1311
+ });
1312
+ }
1313
+ catch (err) {
1314
+ console.error('Could not post execute models', err);
1315
+ process.exit(1);
1316
+ }
1317
+ };
1318
+ exports.postSetup = postSetup;
1321
1319
  //# sourceMappingURL=sbvr-utils.js.map