@balena/pinejs 20.1.0-build-large-file-uploads-2-1a7d50e8660ff52fe7df8d6ef9ce8b6b707027dc-1 → 21.0.0-build-21-x-658ee19ce50a7abb157362062f95f9c0ec721330-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 (59) hide show
  1. package/.pinejs-cache.json +1 -1
  2. package/.versionbot/CHANGELOG.yml +323 -17
  3. package/CHANGELOG.md +77 -5
  4. package/VERSION +1 -1
  5. package/build/browser.cts +0 -1
  6. package/build/module.cts +0 -1
  7. package/build/server.cts +0 -1
  8. package/out/config-loader/env.d.ts +0 -5
  9. package/out/config-loader/env.js +0 -7
  10. package/out/config-loader/env.js.map +1 -1
  11. package/out/migrator/async.js +6 -7
  12. package/out/migrator/async.js.map +1 -1
  13. package/out/sbvr-api/abstract-sql.js +19 -11
  14. package/out/sbvr-api/abstract-sql.js.map +1 -1
  15. package/out/sbvr-api/sbvr-utils.d.ts +0 -10
  16. package/out/sbvr-api/sbvr-utils.js +7 -48
  17. package/out/sbvr-api/sbvr-utils.js.map +1 -1
  18. package/out/sbvr-api/translations.js +4 -17
  19. package/out/sbvr-api/translations.js.map +1 -1
  20. package/out/sbvr-api/uri-parser.d.ts +7 -1
  21. package/out/sbvr-api/uri-parser.js +0 -2
  22. package/out/sbvr-api/uri-parser.js.map +1 -1
  23. package/out/server-glue/module.js +1 -13
  24. package/out/server-glue/module.js.map +1 -1
  25. package/out/tasks/worker.js +1 -0
  26. package/out/tasks/worker.js.map +1 -1
  27. package/out/webresource-handler/index.d.ts +0 -42
  28. package/out/webresource-handler/index.js +1 -24
  29. package/out/webresource-handler/index.js.map +1 -1
  30. package/package.json +30 -30
  31. package/src/config-loader/env.ts +0 -14
  32. package/src/migrator/async.ts +20 -21
  33. package/src/sbvr-api/abstract-sql.ts +30 -25
  34. package/src/sbvr-api/sbvr-utils.ts +9 -58
  35. package/src/sbvr-api/translations.ts +5 -18
  36. package/src/sbvr-api/uri-parser.ts +11 -4
  37. package/src/server-glue/module.ts +1 -15
  38. package/src/tasks/worker.ts +3 -0
  39. package/src/webresource-handler/index.ts +0 -85
  40. package/out/data-server/sbvr-server.d.ts +0 -17
  41. package/out/data-server/sbvr-server.js +0 -350
  42. package/out/data-server/sbvr-server.js.map +0 -1
  43. package/out/http-transactions/transaction.sbvr +0 -59
  44. package/out/http-transactions/transactions.d.ts +0 -3
  45. package/out/http-transactions/transactions.js +0 -305
  46. package/out/http-transactions/transactions.js.map +0 -1
  47. package/out/webresource-handler/multipartUpload.d.ts +0 -12
  48. package/out/webresource-handler/multipartUpload.js +0 -251
  49. package/out/webresource-handler/multipartUpload.js.map +0 -1
  50. package/out/webresource-handler/webresource.d.ts +0 -42
  51. package/out/webresource-handler/webresource.js +0 -2
  52. package/out/webresource-handler/webresource.js.map +0 -1
  53. package/out/webresource-handler/webresource.sbvr +0 -60
  54. package/src/data-server/sbvr-server.ts +0 -412
  55. package/src/http-transactions/transaction.sbvr +0 -59
  56. package/src/http-transactions/transactions.js +0 -305
  57. package/src/webresource-handler/multipartUpload.ts +0 -368
  58. package/src/webresource-handler/webresource.sbvr +0 -60
  59. package/src/webresource-handler/webresource.ts +0 -48
@@ -471,7 +471,7 @@ const bindsForAffectedIds = (
471
471
  return odataBinds;
472
472
  };
473
473
 
474
- export const validateModel = async (
474
+ const validateModel = async (
475
475
  tx: Db.Tx,
476
476
  modelName: string,
477
477
  request?: Pick<
@@ -770,6 +770,13 @@ export const executeModels = async (
770
770
  await asyncMigrator.run(tx, model);
771
771
  }),
772
772
  );
773
+ // Allow the migrations to be GCed after we are done
774
+ // executing the models & their migrations.
775
+ for (const model of execModels) {
776
+ if (model.migrations != null) {
777
+ delete model.migrations;
778
+ }
779
+ }
773
780
  } catch (err) {
774
781
  for (const { apiRoot } of execModels) {
775
782
  cleanupModel(apiRoot);
@@ -800,62 +807,6 @@ const cleanupModel = (vocab: string) => {
800
807
  delete api[vocab];
801
808
  };
802
809
 
803
- export const deleteModel = async (vocabulary: string) => {
804
- const { sql } = models[vocabulary];
805
- if (sql) {
806
- await db.transaction(async (tx) => {
807
- const dropStatements: Array<Promise<any>> = sql.dropSchema.map(
808
- (dropStatement) => tx.executeSql(dropStatement),
809
- );
810
- await Promise.all(
811
- dropStatements.concat([
812
- api.dev.delete({
813
- resource: 'model',
814
- passthrough: {
815
- tx,
816
- req: permissions.root,
817
- },
818
- options: {
819
- $filter: {
820
- is_of__vocabulary: vocabulary,
821
- },
822
- },
823
- }),
824
- ]),
825
- );
826
- });
827
- }
828
- cleanupModel(vocabulary);
829
- };
830
-
831
- const isWhereNode = (
832
- x: AbstractSQLCompiler.AbstractSqlType,
833
- ): x is AbstractSQLCompiler.WhereNode => x[0] === 'Where';
834
- const isEqualsNode = (
835
- x: AbstractSQLCompiler.AbstractSqlType,
836
- ): x is AbstractSQLCompiler.EqualsNode => x[0] === 'Equals';
837
- export const getID = (vocab: string, request: uriParser.ODataRequest) => {
838
- if (request.abstractSqlQuery == null) {
839
- throw new Error('Can only get the id if an abstractSqlQuery is provided');
840
- }
841
- const { idField } = models[vocab].abstractSql.tables[request.resourceName];
842
- for (const whereClause of request.abstractSqlQuery) {
843
- if (isWhereNode(whereClause)) {
844
- for (const comparison of whereClause.slice(1)) {
845
- if (isEqualsNode(comparison)) {
846
- if (comparison[1][2] === idField) {
847
- return comparison[2][1];
848
- }
849
- if (comparison[2][2] === idField) {
850
- return comparison[1][1];
851
- }
852
- }
853
- }
854
- }
855
- }
856
- return 0;
857
- };
858
-
859
810
  export const runRule = (() => {
860
811
  const LF2AbstractSQLPrepHack = LF2AbstractSQL.LF2AbstractSQLPrep._extend({
861
812
  CardinalityOptimisation() {
@@ -2064,7 +2015,7 @@ const devModelConfig = {
2064
2015
  },
2065
2016
  },
2066
2017
  } as const satisfies ExecutableModel;
2067
- export const executeStandardModels = async (tx: Db.Tx): Promise<void> => {
2018
+ const executeStandardModels = async (tx: Db.Tx): Promise<void> => {
2068
2019
  try {
2069
2020
  // dev model must run first
2070
2021
  await executeModel(tx, devModelConfig);
@@ -206,30 +206,17 @@ export const translateAbstractSqlModel = (
206
206
  const { $toResource, ...definition } = translationDefinition;
207
207
  const hasToResource = typeof $toResource === 'string';
208
208
 
209
- const unaliasedToResource = hasToResource
210
- ? $toResource.endsWith(toVersionSuffix)
211
- ? // Ideally we want to rename to the unaliased resource of the next version
212
- // so when the alias matches the next version we can just strip it
213
- $toResource.slice(0, -toVersionSuffix.length)
214
- : // But if we can't safely strip the suffix then we'll use as-is, at least until the next major
215
- $toResource
216
- : key;
217
- let aliasedToResource;
209
+ const unaliasedToResource = hasToResource ? $toResource : key;
218
210
  if (hasToResource) {
219
- resourceRenames[key] = unaliasedToResource;
220
211
  if ($toResource.includes('$')) {
221
- // TODO-MAJOR: Change this to an error
222
- console.warn(
212
+ throw new Error(
223
213
  `'$toResource' should be the unaliased name of the resource in the subsequent model and not be targeting a specific model, got '${$toResource}'`,
224
- $toResource,
225
214
  );
226
- aliasedToResource = $toResource;
227
- } else {
228
- aliasedToResource = `${$toResource}${toVersionSuffix}`;
229
215
  }
230
- } else {
231
- aliasedToResource = `${key}${toVersionSuffix}`;
216
+ resourceRenames[key] = unaliasedToResource;
232
217
  }
218
+ const aliasedToResource = `${unaliasedToResource}${toVersionSuffix}`;
219
+
233
220
  const toTable = toAbstractSqlModel.tables[unaliasedToResource];
234
221
  if (!toTable) {
235
222
  if (hasToResource) {
@@ -16,7 +16,6 @@ import _ from 'lodash';
16
16
  import memoizeWeak from 'memoizee/weak.js';
17
17
 
18
18
  export { BadRequestError, ParsingError, TranslationError } from './errors.js';
19
- import deepFreeze from 'deep-freeze';
20
19
  import * as env from '../config-loader/env.js';
21
20
  import {
22
21
  BadRequestError,
@@ -53,11 +52,19 @@ export interface ParsedODataRequest {
53
52
  id?: number | undefined;
54
53
  _defer?: boolean;
55
54
  }
55
+ export interface CachedSqlQuery extends Array<never> {
56
+ length: 0;
57
+ engine: AbstractSQLCompiler.Engines;
58
+ sqlQuery: AbstractSQLCompiler.SqlResult | AbstractSQLCompiler.SqlResult[];
59
+ modifiedFields?: ReturnType<
60
+ AbstractSQLCompiler.EngineInstance['getModifiedFields']
61
+ >;
62
+ }
56
63
  export interface ODataRequest extends ParsedODataRequest {
57
64
  translateVersions: string[];
58
65
  abstractSqlModel?: AbstractSQLCompiler.AbstractSqlModel;
59
66
  finalAbstractSqlModel?: AbstractSQLCompiler.AbstractSqlModel;
60
- abstractSqlQuery?: AbstractSQLCompiler.AbstractSqlQuery;
67
+ abstractSqlQuery?: AbstractSQLCompiler.AbstractSqlQuery | CachedSqlQuery;
61
68
  sqlQuery?: AbstractSQLCompiler.SqlResult | AbstractSQLCompiler.SqlResult[];
62
69
  tx?: Tx;
63
70
  modifiedFields?: ReturnType<
@@ -178,8 +185,8 @@ const memoizedOdata2AbstractSQL = (() => {
178
185
  bodyKeys,
179
186
  existingBindVarsLength,
180
187
  );
181
- // We deep freeze to prevent mutations, which would pollute the cache
182
- deepFreeze(abstractSql);
188
+ // We do not deep freeze as the sql compilation intentionally mutates this object
189
+ // to clear the abstractSql tree and replace it with the compile sqlQuery to save memory
183
190
  return abstractSql;
184
191
  } catch (e) {
185
192
  if (e instanceof PermissionError) {
@@ -7,7 +7,6 @@ import * as configLoader from '../config-loader/config-loader.js';
7
7
  import * as migrator from '../migrator/sync.js';
8
8
  import type * as migratorUtils from '../migrator/utils.js';
9
9
  import * as tasks from '../tasks/index.js';
10
- import * as webresource from '../webresource-handler/index.js';
11
10
 
12
11
  import * as sbvrUtils from '../sbvr-api/sbvr-utils.js';
13
12
  import { PINEJS_ADVISORY_LOCK } from '../config-loader/env.js';
@@ -67,23 +66,10 @@ export const init = async <T extends string>(
67
66
  const cfgLoader = configLoader.setup(app);
68
67
  await cfgLoader.loadConfig(migrator.config);
69
68
  await cfgLoader.loadConfig(tasks.config);
70
- await cfgLoader.loadConfig(webresource.config);
71
69
 
72
- const promises: Array<Promise<void>> = [];
73
- if (process.env.SBVR_SERVER_ENABLED) {
74
- const sbvrServer = await import('../data-server/sbvr-server.js');
75
- const transactions = await import('../http-transactions/transactions.js');
76
- promises.push(cfgLoader.loadConfig(sbvrServer.config));
77
- promises.push(
78
- cfgLoader.loadConfig(transactions.config).then(() => {
79
- transactions.addModelHooks('data');
80
- }),
81
- );
82
- }
83
70
  if (!process.env.CONFIG_LOADER_DISABLED) {
84
- promises.push(cfgLoader.loadApplicationConfig(config));
71
+ await cfgLoader.loadApplicationConfig(config);
85
72
  }
86
- await Promise.all(promises);
87
73
  // Execute it after all other promises have resolved. Execution of promises is not neccessarily
88
74
  // guaranteed to be sequentially resolving them with Promise.all
89
75
  await sbvrUtils.postSetup(app, db);
@@ -246,6 +246,9 @@ export class Worker {
246
246
  });
247
247
  } catch (err) {
248
248
  console.error('Failed polling for tasks:', err);
249
+ // Add some delay after an error to avoid retrying at max speed
250
+ // TODO: This should be configurable/adaptive
251
+ await setTimeout(100);
249
252
  } finally {
250
253
  if (!executed) {
251
254
  await setTimeout(this.interval);
@@ -11,20 +11,12 @@ import {
11
11
  odataNameToSqlName,
12
12
  sqlNameToODataName,
13
13
  } from '@balena/odata-to-abstract-sql';
14
- import type { ConfigLoader } from '../server-glue/module.js';
15
14
  import { errors, permissions } from '../server-glue/module.js';
16
15
  import type { WebResourceType as WebResource } from '@balena/sbvr-types';
17
16
  import { TypedError } from 'typed-error';
18
17
  import type { Resolvable } from '../sbvr-api/common-types.js';
19
- import type WebresourceModel from './webresource.js';
20
- import { importSBVR } from '../server-glue/sbvr-loader.js';
21
- import {
22
- isMultipartUploadAvailable,
23
- multipartUploadHooks,
24
- } from './multipartUpload.js';
25
18
 
26
19
  export * from './handlers/index.js';
27
- export type { BeginUploadResponse } from './multipartUpload.js';
28
20
 
29
21
  export interface IncomingFile {
30
22
  fieldname: string;
@@ -39,51 +31,10 @@ export interface UploadResponse {
39
31
  filename: string;
40
32
  }
41
33
 
42
- export interface BeginMultipartUploadPayload {
43
- filename: string;
44
- content_type: string;
45
- size: number;
46
- chunk_size: number;
47
- }
48
-
49
- export interface UploadPart {
50
- url: string;
51
- chunkSize: number;
52
- partNumber: number;
53
- }
54
-
55
- export interface BeginMultipartUploadHandlerResponse {
56
- uploadParts: UploadPart[];
57
- fileKey: string;
58
- uploadId: string;
59
- }
60
-
61
- export interface CommitMultipartUploadPayload {
62
- fileKey: string;
63
- uploadId: string;
64
- filename: string;
65
- providerCommitData?: Record<string, any>;
66
- }
67
-
68
- export interface CancelMultipartUploadPayload {
69
- fileKey: string;
70
- uploadId: string;
71
- }
72
-
73
34
  export interface WebResourceHandler {
74
35
  handleFile: (resource: IncomingFile) => Promise<UploadResponse>;
75
36
  removeFile: (fileReference: string) => Promise<void>;
76
37
  onPreRespond: (webResource: WebResource) => Promise<WebResource>;
77
- multipartUpload?: {
78
- begin: (
79
- fieldName: string,
80
- payload: BeginMultipartUploadPayload,
81
- ) => Promise<BeginMultipartUploadHandlerResponse>;
82
- commit: (commitInfo: CommitMultipartUploadPayload) => Promise<WebResource>;
83
- cancel: (cancelInfo: CancelMultipartUploadPayload) => Promise<void>;
84
- getMinimumPartSize: () => number;
85
- getDefaultPartSize: () => number;
86
- };
87
38
  }
88
39
 
89
40
  export class WebResourceError extends TypedError {}
@@ -337,9 +288,6 @@ const throwIfWebresourceNotInMultipart = (
337
288
  { req, request }: HookArgs,
338
289
  ) => {
339
290
  if (
340
- request.custom.isAction !== 'beginUpload' &&
341
- request.custom.isAction !== 'commitUpload' &&
342
- request.custom.isAction !== 'cancelUpload' &&
343
291
  !req.is?.('multipart') &&
344
292
  webResourceFields.some((field) => request.values[field] != null)
345
293
  ) {
@@ -536,37 +484,4 @@ export const setupUploadHooks = (
536
484
  resourceName,
537
485
  getCreateWebResourceHooks(handler),
538
486
  );
539
-
540
- if (isMultipartUploadAvailable(handler)) {
541
- sbvrUtils.addPureHook(
542
- 'POST',
543
- apiRoot,
544
- resourceName,
545
- multipartUploadHooks(handler),
546
- );
547
- }
548
- };
549
-
550
- const initSql = `
551
- CREATE INDEX IF NOT EXISTS idx_multipart_upload_uuid ON "multipart upload" (uuid);
552
- CREATE INDEX IF NOT EXISTS idx_multipart_upload_status ON "multipart upload" (status);
553
- `;
554
-
555
- const modelText = await importSBVR('./webresource.sbvr', import.meta);
556
-
557
- declare module '../sbvr-api/sbvr-utils.js' {
558
- export interface API {
559
- webresource: PinejsClient<WebresourceModel>;
560
- }
561
- }
562
-
563
- export const config: ConfigLoader.Config = {
564
- models: [
565
- {
566
- modelName: 'webresource',
567
- apiRoot: 'webresource',
568
- modelText,
569
- initSql,
570
- },
571
- ],
572
487
  };
@@ -1,17 +0,0 @@
1
- import type { SetupFunction } from '../config-loader/config-loader.js';
2
- import type { Tx } from '../database-layer/db.js';
3
- export declare const setup: SetupFunction;
4
- export declare const config: {
5
- models: {
6
- modelName: string;
7
- modelText: string;
8
- apiRoot: string;
9
- customServerCode: {
10
- setup: SetupFunction;
11
- };
12
- migrations: {
13
- '11.0.0-modified-at': string;
14
- '15.0.0-data-types': (tx: Tx, sbvrUtils: typeof import("../sbvr-api/sbvr-utils.js")) => Promise<void>;
15
- };
16
- }[];
17
- };