@balena/pinejs 17.1.0-build-joshbwlng-tasks-149b21c81ddf7cbb2a934500dc16e0b5ed4c74a7-1 → 17.1.0-build-model-based-typings-a10277597a28577bcb204b378925c9df795a10e8-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 (76) hide show
  1. package/.pinejs-cache.json +1 -1
  2. package/.versionbot/CHANGELOG.yml +232 -7
  3. package/CHANGELOG.md +71 -3
  4. package/out/config-loader/env.d.ts +0 -4
  5. package/out/config-loader/env.js +1 -5
  6. package/out/config-loader/env.js.map +1 -1
  7. package/out/data-server/sbvr-server.js +3 -2
  8. package/out/data-server/sbvr-server.js.map +1 -1
  9. package/out/database-layer/db.d.ts +0 -3
  10. package/out/database-layer/db.js +0 -17
  11. package/out/database-layer/db.js.map +1 -1
  12. package/out/http-transactions/transactions.js +1 -6
  13. package/out/http-transactions/transactions.js.map +1 -1
  14. package/out/migrator/migrations.d.ts +113 -0
  15. package/out/migrator/migrations.js +3 -0
  16. package/out/migrator/migrations.js.map +1 -0
  17. package/out/migrator/sync.d.ts +17 -0
  18. package/out/migrator/sync.js +39 -40
  19. package/out/migrator/sync.js.map +1 -1
  20. package/out/sbvr-api/abstract-sql.js +1 -1
  21. package/out/sbvr-api/abstract-sql.js.map +1 -1
  22. package/out/sbvr-api/dev.d.ts +41 -0
  23. package/out/sbvr-api/dev.js +3 -0
  24. package/out/sbvr-api/dev.js.map +1 -0
  25. package/out/sbvr-api/hooks.d.ts +26 -26
  26. package/out/sbvr-api/hooks.js.map +1 -1
  27. package/out/sbvr-api/odata-response.js +3 -3
  28. package/out/sbvr-api/odata-response.js.map +1 -1
  29. package/out/sbvr-api/permissions.d.ts +26 -2
  30. package/out/sbvr-api/permissions.js +41 -42
  31. package/out/sbvr-api/permissions.js.map +1 -1
  32. package/out/sbvr-api/sbvr-utils.d.ts +46 -6
  33. package/out/sbvr-api/sbvr-utils.js +44 -44
  34. package/out/sbvr-api/sbvr-utils.js.map +1 -1
  35. package/out/sbvr-api/uri-parser.js +1 -1
  36. package/out/sbvr-api/uri-parser.js.map +1 -1
  37. package/out/sbvr-api/user.d.ts +467 -0
  38. package/out/sbvr-api/user.js +3 -0
  39. package/out/sbvr-api/user.js.map +1 -0
  40. package/out/server-glue/module.d.ts +0 -1
  41. package/out/server-glue/module.js +1 -4
  42. package/out/server-glue/module.js.map +1 -1
  43. package/package.json +18 -19
  44. package/src/config-loader/env.ts +1 -6
  45. package/src/data-server/sbvr-server.js +3 -2
  46. package/src/database-layer/db.ts +0 -25
  47. package/src/http-transactions/transactions.js +1 -6
  48. package/src/migrator/migrations.ts +120 -0
  49. package/src/migrator/sync.ts +46 -41
  50. package/src/sbvr-api/abstract-sql.ts +1 -1
  51. package/src/sbvr-api/dev.ts +44 -0
  52. package/src/sbvr-api/hooks.ts +21 -18
  53. package/src/sbvr-api/odata-response.ts +3 -4
  54. package/src/sbvr-api/permissions.ts +52 -46
  55. package/src/sbvr-api/sbvr-utils.ts +90 -53
  56. package/src/sbvr-api/uri-parser.ts +1 -1
  57. package/src/sbvr-api/user.ts +421 -0
  58. package/src/server-glue/module.ts +0 -3
  59. package/out/tasks/common.d.ts +0 -4
  60. package/out/tasks/common.js +0 -13
  61. package/out/tasks/common.js.map +0 -1
  62. package/out/tasks/index.d.ts +0 -8
  63. package/out/tasks/index.js +0 -142
  64. package/out/tasks/index.js.map +0 -1
  65. package/out/tasks/tasks.sbvr +0 -60
  66. package/out/tasks/types.d.ts +0 -38
  67. package/out/tasks/types.js +0 -10
  68. package/out/tasks/types.js.map +0 -1
  69. package/out/tasks/worker.d.ts +0 -16
  70. package/out/tasks/worker.js +0 -228
  71. package/out/tasks/worker.js.map +0 -1
  72. package/src/tasks/common.ts +0 -14
  73. package/src/tasks/index.ts +0 -158
  74. package/src/tasks/tasks.sbvr +0 -60
  75. package/src/tasks/types.ts +0 -58
  76. package/src/tasks/worker.ts +0 -281
@@ -98,13 +98,6 @@ export interface Database extends BaseDatabase {
98
98
  ) => Promise<Result>;
99
99
  transaction: TransactionFn;
100
100
  readTransaction: TransactionFn;
101
- on?: (
102
- name: 'notification',
103
- fn: (...args: any[]) => Promise<void>,
104
- options?: {
105
- channel?: string;
106
- },
107
- ) => void;
108
101
  }
109
102
 
110
103
  interface EngineParams {
@@ -696,24 +689,6 @@ if (maybePg != null) {
696
689
  return {
697
690
  engine: Engines.postgres,
698
691
  executeSql: atomicExecuteSql,
699
- on: async (name, fn, options) => {
700
- if (name === 'notification' && options?.channel === undefined) {
701
- throw new Error('Missing channel option for notification listener');
702
- }
703
-
704
- const client = await pool.connect();
705
- client.on(name, async (msg) => {
706
- try {
707
- await fn(msg);
708
- } catch (error) {
709
- console.error('Error handling message:', error);
710
- }
711
- });
712
-
713
- if (name === 'notification' && options?.channel !== undefined) {
714
- await client.query(`LISTEN "${options.channel}";`);
715
- }
716
- },
717
692
  transaction: createTransaction(async (stackTraceErr) => {
718
693
  const client = await pool.connect();
719
694
  const tx = new PostgresTx(client, false, stackTraceErr);
@@ -130,12 +130,7 @@ WHERE "conditional field"."conditional resource" = ?;`,
130
130
  modelField.dataType === 'ForeignKey' &&
131
131
  Number.isNaN(Number(fieldValue))
132
132
  ) {
133
- if (
134
- !Object.prototype.hasOwnProperty.call(
135
- placeholders,
136
- fieldValue,
137
- )
138
- ) {
133
+ if (!Object.hasOwn(placeholders, fieldValue)) {
139
134
  throw new Error('Cannot resolve placeholder' + fieldValue);
140
135
  } else {
141
136
  try {
@@ -0,0 +1,120 @@
1
+ import type { Types } from '@balena/abstract-sql-to-typescript';
2
+
3
+ export interface Migration {
4
+ Read: {
5
+ created_at: Types['Date Time']['Read'];
6
+ modified_at: Types['Date Time']['Read'];
7
+ model_name: Types['Short Text']['Read'];
8
+ executed_migrations: Types['JSON']['Read'];
9
+ };
10
+ Write: {
11
+ created_at: Types['Date Time']['Write'];
12
+ modified_at: Types['Date Time']['Write'];
13
+ model_name: Types['Short Text']['Write'];
14
+ executed_migrations: Types['JSON']['Write'];
15
+ };
16
+ }
17
+
18
+ export interface MigrationLock {
19
+ Read: {
20
+ created_at: Types['Date Time']['Read'];
21
+ modified_at: Types['Date Time']['Read'];
22
+ model_name: Types['Short Text']['Read'];
23
+ };
24
+ Write: {
25
+ created_at: Types['Date Time']['Write'];
26
+ modified_at: Types['Date Time']['Write'];
27
+ model_name: Types['Short Text']['Write'];
28
+ };
29
+ }
30
+
31
+ export interface MigrationStatus {
32
+ Read: {
33
+ created_at: Types['Date Time']['Read'];
34
+ modified_at: Types['Date Time']['Read'];
35
+ migration_key: Types['Short Text']['Read'];
36
+ start_time: Types['Date Time']['Read'] | null;
37
+ last_run_time: Types['Date Time']['Read'] | null;
38
+ run_count: Types['Integer']['Read'];
39
+ migrated_row_count: Types['Integer']['Read'] | null;
40
+ error_count: Types['Integer']['Read'] | null;
41
+ is_backing_off: Types['Boolean']['Read'];
42
+ converged_time: Types['Date Time']['Read'] | null;
43
+ };
44
+ Write: {
45
+ created_at: Types['Date Time']['Write'];
46
+ modified_at: Types['Date Time']['Write'];
47
+ migration_key: Types['Short Text']['Write'];
48
+ start_time: Types['Date Time']['Write'] | null;
49
+ last_run_time: Types['Date Time']['Write'] | null;
50
+ run_count: Types['Integer']['Write'];
51
+ migrated_row_count: Types['Integer']['Write'] | null;
52
+ error_count: Types['Integer']['Write'] | null;
53
+ is_backing_off: Types['Boolean']['Write'];
54
+ converged_time: Types['Date Time']['Write'] | null;
55
+ };
56
+ }
57
+
58
+ export interface Migration {
59
+ Read: {
60
+ created_at: Types['Date Time']['Read'];
61
+ modified_at: Types['Date Time']['Read'];
62
+ model_name: Types['Short Text']['Read'];
63
+ executed_migrations: Types['JSON']['Read'];
64
+ };
65
+ Write: {
66
+ created_at: Types['Date Time']['Write'];
67
+ modified_at: Types['Date Time']['Write'];
68
+ model_name: Types['Short Text']['Write'];
69
+ executed_migrations: Types['JSON']['Write'];
70
+ };
71
+ }
72
+
73
+ export interface MigrationLock {
74
+ Read: {
75
+ created_at: Types['Date Time']['Read'];
76
+ modified_at: Types['Date Time']['Read'];
77
+ model_name: Types['Short Text']['Read'];
78
+ };
79
+ Write: {
80
+ created_at: Types['Date Time']['Write'];
81
+ modified_at: Types['Date Time']['Write'];
82
+ model_name: Types['Short Text']['Write'];
83
+ };
84
+ }
85
+
86
+ export interface MigrationStatus {
87
+ Read: {
88
+ created_at: Types['Date Time']['Read'];
89
+ modified_at: Types['Date Time']['Read'];
90
+ migration_key: Types['Short Text']['Read'];
91
+ start_time: Types['Date Time']['Read'] | null;
92
+ last_run_time: Types['Date Time']['Read'] | null;
93
+ run_count: Types['Integer']['Read'];
94
+ migrated_row_count: Types['Integer']['Read'] | null;
95
+ error_count: Types['Integer']['Read'] | null;
96
+ is_backing_off: Types['Boolean']['Read'];
97
+ converged_time: Types['Date Time']['Read'] | null;
98
+ };
99
+ Write: {
100
+ created_at: Types['Date Time']['Write'];
101
+ modified_at: Types['Date Time']['Write'];
102
+ migration_key: Types['Short Text']['Write'];
103
+ start_time: Types['Date Time']['Write'] | null;
104
+ last_run_time: Types['Date Time']['Write'] | null;
105
+ run_count: Types['Integer']['Write'];
106
+ migrated_row_count: Types['Integer']['Write'] | null;
107
+ error_count: Types['Integer']['Write'] | null;
108
+ is_backing_off: Types['Boolean']['Write'];
109
+ converged_time: Types['Date Time']['Write'] | null;
110
+ };
111
+ }
112
+
113
+ export default interface $Model {
114
+ migration: Migration;
115
+ migration_lock: MigrationLock;
116
+ migration_status: MigrationStatus;
117
+ migration$sbvr__compiler: Migration;
118
+ migration_lock$sbvr__compiler: MigrationLock;
119
+ migration_status$sbvr__compiler: MigrationStatus;
120
+ }
@@ -1,3 +1,4 @@
1
+ import type MigrationsModel from './migrations';
1
2
  import {
2
3
  type MigrationTuple,
3
4
  MigrationError,
@@ -16,7 +17,7 @@ import _ from 'lodash';
16
17
  import * as sbvrUtils from '../sbvr-api/sbvr-utils';
17
18
 
18
19
  // eslint-disable-next-line @typescript-eslint/no-var-requires
19
- const modelText = require('./migrations.sbvr');
20
+ const migrationsModel = require('./migrations.sbvr');
20
21
 
21
22
  type ApiRootModel = Model & { apiRoot: string };
22
23
 
@@ -136,45 +137,49 @@ const executeMigration = async (
136
137
  }
137
138
  };
138
139
 
139
- export const config: Config = {
140
- models: [
141
- {
142
- modelName: 'migrations',
143
- apiRoot: 'migrations',
144
- modelText,
145
- migrations: {
146
- '11.0.0-modified-at': `
147
- ALTER TABLE "migration"
148
- ADD COLUMN IF NOT EXISTS "modified at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL;
149
- `,
150
- '11.0.1-modified-at': `
151
- ALTER TABLE "migration lock"
152
- ADD COLUMN IF NOT EXISTS "modified at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL;
153
- `,
154
- '15.0.0-data-types': async (tx, { db }) => {
155
- switch (db.engine) {
156
- case 'mysql':
157
- await tx.executeSql(`\
158
- ALTER TABLE "migration"
159
- MODIFY "executed migrations" JSON NOT NULL;`);
160
- await tx.executeSql(`\
161
- ALTER TABLE "migration status"
162
- MODIFY "is backing off" BOOLEAN NOT NULL;`);
163
- break;
164
- case 'postgres':
165
- await tx.executeSql(`\
166
- ALTER TABLE "migration"
167
- ALTER COLUMN "executed migrations" SET DATA TYPE JSONB USING "executed migrations"::JSONB;`);
168
- await tx.executeSql(`\
169
- ALTER TABLE "migration status"
170
- ALTER COLUMN "is backing off" DROP DEFAULT,
171
- ALTER COLUMN "is backing off" SET DATA TYPE BOOLEAN USING "is backing off"::BOOLEAN,
172
- ALTER COLUMN "is backing off" SET DEFAULT FALSE;`);
173
- break;
174
- // No need to migrate for websql
175
- }
176
- },
177
- },
140
+ declare module '../sbvr-api/sbvr-utils' {
141
+ export interface API {
142
+ [migrationModelConfig.apiRoot]: PinejsClient<MigrationsModel>;
143
+ }
144
+ }
145
+ const migrationModelConfig = {
146
+ modelName: 'migrations',
147
+ apiRoot: 'migrations',
148
+ modelText: migrationsModel,
149
+ migrations: {
150
+ '11.0.0-modified-at': `
151
+ ALTER TABLE "migration"
152
+ ADD COLUMN IF NOT EXISTS "modified at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL;
153
+ `,
154
+ '11.0.1-modified-at': `
155
+ ALTER TABLE "migration lock"
156
+ ADD COLUMN IF NOT EXISTS "modified at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL;
157
+ `,
158
+ '15.0.0-data-types': async (tx, { db }) => {
159
+ switch (db.engine) {
160
+ case 'mysql':
161
+ await tx.executeSql(`\
162
+ ALTER TABLE "migration"
163
+ MODIFY "executed migrations" JSON NOT NULL;`);
164
+ await tx.executeSql(`\
165
+ ALTER TABLE "migration status"
166
+ MODIFY "is backing off" BOOLEAN NOT NULL;`);
167
+ break;
168
+ case 'postgres':
169
+ await tx.executeSql(`\
170
+ ALTER TABLE "migration"
171
+ ALTER COLUMN "executed migrations" SET DATA TYPE JSONB USING "executed migrations"::JSONB;`);
172
+ await tx.executeSql(`\
173
+ ALTER TABLE "migration status"
174
+ ALTER COLUMN "is backing off" DROP DEFAULT,
175
+ ALTER COLUMN "is backing off" SET DATA TYPE BOOLEAN USING "is backing off"::BOOLEAN,
176
+ ALTER COLUMN "is backing off" SET DEFAULT FALSE;`);
177
+ break;
178
+ // No need to migrate for websql
179
+ }
178
180
  },
179
- ],
181
+ },
182
+ } as const satisfies sbvrUtils.ExecutableModel;
183
+ export const config: Config = {
184
+ models: [migrationModelConfig],
180
185
  };
@@ -116,7 +116,7 @@ export const getAndCheckBindValues = async (
116
116
  [dataType, value] = odataBinds[bindValue];
117
117
  field = { dataType };
118
118
  } else if (typeof bindValue === 'string') {
119
- if (!Object.prototype.hasOwnProperty.call(odataBinds, bindValue)) {
119
+ if (!Object.hasOwn(odataBinds, bindValue)) {
120
120
  console.error(
121
121
  `Invalid binding '${bindValue}' for binds: `,
122
122
  odataBinds,
@@ -0,0 +1,44 @@
1
+ import type { Types } from '@balena/abstract-sql-to-typescript';
2
+
3
+ export interface Model {
4
+ Read: {
5
+ created_at: Types['Date Time']['Read'];
6
+ modified_at: Types['Date Time']['Read'];
7
+ id: Types['Serial']['Read'];
8
+ is_of__vocabulary: Types['Short Text']['Read'];
9
+ model_type: Types['Short Text']['Read'];
10
+ model_value: Types['JSON']['Read'];
11
+ };
12
+ Write: {
13
+ created_at: Types['Date Time']['Write'];
14
+ modified_at: Types['Date Time']['Write'];
15
+ id: Types['Serial']['Write'];
16
+ is_of__vocabulary: Types['Short Text']['Write'];
17
+ model_type: Types['Short Text']['Write'];
18
+ model_value: Types['JSON']['Write'];
19
+ };
20
+ }
21
+
22
+ export interface Model {
23
+ Read: {
24
+ created_at: Types['Date Time']['Read'];
25
+ modified_at: Types['Date Time']['Read'];
26
+ id: Types['Serial']['Read'];
27
+ is_of__vocabulary: Types['Short Text']['Read'];
28
+ model_type: Types['Short Text']['Read'];
29
+ model_value: Types['JSON']['Read'];
30
+ };
31
+ Write: {
32
+ created_at: Types['Date Time']['Write'];
33
+ modified_at: Types['Date Time']['Write'];
34
+ id: Types['Serial']['Write'];
35
+ is_of__vocabulary: Types['Short Text']['Write'];
36
+ model_type: Types['Short Text']['Write'];
37
+ model_value: Types['JSON']['Write'];
38
+ };
39
+ }
40
+
41
+ export default interface $Model {
42
+ model: Model;
43
+ model$sbvr__compiler: Model;
44
+ }
@@ -9,7 +9,6 @@ import _ from 'lodash';
9
9
  import { settleMapSeries } from './control-flow';
10
10
  import memoize from 'memoizee';
11
11
  import {
12
- type PinejsClient,
13
12
  type User,
14
13
  type ApiKey,
15
14
  resolveSynonym,
@@ -31,23 +30,27 @@ export interface HookReq {
31
30
  hooks?: InstantiatedHooks;
32
31
  is?: (type: string | string[]) => string | false | null;
33
32
  }
34
- export interface HookArgs {
33
+ export interface HookArgs<Vocab extends string = string> {
35
34
  req: HookReq;
36
35
  request: ODataRequest;
37
- api: PinejsClient;
36
+ api: (typeof api)[Vocab];
38
37
  tx?: Tx | undefined;
39
38
  }
40
39
  export type HookResponse = PromiseLike<any> | null | void;
41
40
 
42
- export interface Hooks {
43
- PREPARSE?: (options: Omit<HookArgs, 'request' | 'api'>) => HookResponse;
44
- POSTPARSE?: (options: HookArgs) => HookResponse;
45
- PRERUN?: (options: HookArgs & { tx: Tx }) => HookResponse;
41
+ export interface Hooks<Vocab extends string = string> {
42
+ PREPARSE?: (
43
+ options: Omit<HookArgs<Vocab>, 'request' | 'api'>,
44
+ ) => HookResponse;
45
+ POSTPARSE?: (options: HookArgs<Vocab>) => HookResponse;
46
+ PRERUN?: (options: HookArgs<Vocab> & { tx: Tx }) => HookResponse;
46
47
  /** These are run in reverse translation order from newest to oldest */
47
- POSTRUN?: (options: HookArgs & { tx: Tx; result: any }) => HookResponse;
48
+ POSTRUN?: (
49
+ options: HookArgs<Vocab> & { tx: Tx; result: any },
50
+ ) => HookResponse;
48
51
  /** These are run in reverse translation order from newest to oldest */
49
52
  PRERESPOND?: (
50
- options: HookArgs & {
53
+ options: HookArgs<Vocab> & {
51
54
  tx: Tx;
52
55
  result: any;
53
56
  /** This can be mutated to modify the response sent to the client */
@@ -56,7 +59,7 @@ export interface Hooks {
56
59
  ) => HookResponse;
57
60
  /** These are run in reverse translation order from newest to oldest */
58
61
  'POSTRUN-ERROR'?: (
59
- options: HookArgs & { tx: Tx; error: TypedError | any },
62
+ options: HookArgs<Vocab> & { tx: Tx; error: TypedError | any },
60
63
  ) => HookResponse;
61
64
  }
62
65
  export type HookBlueprints = {
@@ -262,9 +265,9 @@ const apiHooks = {
262
265
  // Share hooks between merge and patch since they are the same operation,
263
266
  // just MERGE was the OData intermediary until the HTTP spec added PATCH.
264
267
  apiHooks.MERGE = apiHooks.PATCH;
265
- export const addHook = (
268
+ export const addHook = <Vocab extends string>(
266
269
  method: keyof typeof apiHooks,
267
- vocabulary: string,
270
+ vocabulary: Vocab,
268
271
  resourceName: string,
269
272
  hooks:
270
273
  | { [key in keyof Hooks]: HookBlueprint<NonNullable<Hooks[key]>> }
@@ -343,11 +346,11 @@ export const addHook = (
343
346
  getHooks.clear();
344
347
  };
345
348
 
346
- export const addSideEffectHook = (
349
+ export const addSideEffectHook = <Vocab extends string>(
347
350
  method: HookMethod,
348
- apiRoot: string,
351
+ apiRoot: Vocab,
349
352
  resourceName: string,
350
- hooks: Hooks,
353
+ hooks: Hooks<NoInfer<Vocab>>,
351
354
  ): void => {
352
355
  addHook(method, apiRoot, resourceName, {
353
356
  ...hooks,
@@ -356,11 +359,11 @@ export const addSideEffectHook = (
356
359
  });
357
360
  };
358
361
 
359
- export const addPureHook = (
362
+ export const addPureHook = <Vocab extends string>(
360
363
  method: HookMethod,
361
- apiRoot: string,
364
+ apiRoot: Vocab,
362
365
  resourceName: string,
363
- hooks: Hooks,
366
+ hooks: Hooks<NoInfer<Vocab>>,
364
367
  ): void => {
365
368
  addHook(method, apiRoot, resourceName, {
366
369
  ...hooks,
@@ -165,20 +165,19 @@ export const process = async (
165
165
 
166
166
  const fetchProcessingFields = getFetchProcessingFields(table);
167
167
  const processedFields = fieldNames.filter((fieldName) =>
168
- Object.prototype.hasOwnProperty.call(fetchProcessingFields, fieldName),
168
+ Object.hasOwn(fetchProcessingFields, fieldName),
169
169
  );
170
170
 
171
171
  const localFields = getLocalFields(table);
172
172
  // We check that it's not a local field, rather than that it is a foreign key because of the case where the foreign key is on the other resource
173
173
  // and hence not known to this resource
174
174
  const expandableFields = fieldNames.filter(
175
- (fieldName) =>
176
- !Object.prototype.hasOwnProperty.call(localFields, fieldName),
175
+ (fieldName) => !Object.hasOwn(localFields, fieldName),
177
176
  );
178
177
 
179
178
  const webresourceFields = getWebResourceFields(table);
180
179
  const requiredSigningFields = fieldNames.filter((fieldName) =>
181
- Object.prototype.hasOwnProperty.call(webresourceFields, fieldName),
180
+ Object.hasOwn(webresourceFields, fieldName),
182
181
  );
183
182
 
184
183
  const odataIdField = sqlNameToODataName(table.idField);
@@ -1,3 +1,4 @@
1
+ import type AuthModel from './user';
1
2
  import type {
2
3
  AbstractSqlModel,
3
4
  AbstractSqlQuery,
@@ -51,6 +52,7 @@ import {
51
52
  type ODataRequest,
52
53
  } from './uri-parser';
53
54
  import memoizeWeak = require('memoizee/weak');
55
+ import type { Config } from '../config-loader/config-loader';
54
56
 
55
57
  // eslint-disable-next-line @typescript-eslint/no-var-requires
56
58
  const userModel: string = require('./user.sbvr');
@@ -429,7 +431,7 @@ const convertToLambda = (filter: AnyObject, identifier: string) => {
429
431
  }
430
432
  }
431
433
 
432
- if (Object.prototype.hasOwnProperty.call(object, 'name')) {
434
+ if (Object.hasOwn(object, 'name')) {
433
435
  object.property = { ...object };
434
436
  object.name = identifier;
435
437
  delete object.lambda;
@@ -725,7 +727,7 @@ const deepFreezeExceptDefinition = (obj: AnyObject) => {
725
727
  // We skip the definition because we know it's a property we've defined that will throw an error in some cases
726
728
  if (
727
729
  prop !== 'definition' &&
728
- Object.prototype.hasOwnProperty.call(obj, prop) &&
730
+ Object.hasOwn(obj, prop) &&
729
731
  obj[prop] !== null &&
730
732
  !['object', 'function'].includes(typeof obj[prop])
731
733
  ) {
@@ -1586,7 +1588,7 @@ let guestPermissionsInitialized = false;
1586
1588
  const getGuestPermissions = memoize(
1587
1589
  async () => {
1588
1590
  // Get guest user
1589
- const result = (await sbvrUtils.api.Auth.get({
1591
+ const result = await sbvrUtils.api.Auth.get({
1590
1592
  resource: 'user',
1591
1593
  passthrough: {
1592
1594
  req: rootRead,
@@ -1597,7 +1599,7 @@ const getGuestPermissions = memoize(
1597
1599
  options: {
1598
1600
  $select: 'id',
1599
1601
  },
1600
- })) as { id: number } | undefined;
1602
+ });
1601
1603
  if (result == null) {
1602
1604
  throw new Error('No guest user');
1603
1605
  }
@@ -1686,49 +1688,53 @@ export const addPermissions = async (
1686
1688
  }
1687
1689
  };
1688
1690
 
1691
+ declare module './sbvr-utils' {
1692
+ export interface API {
1693
+ [authModelConfig.apiRoot]: PinejsClient<AuthModel>;
1694
+ }
1695
+ }
1696
+ const authModelConfig = {
1697
+ apiRoot: 'Auth',
1698
+ modelText: userModel,
1699
+ customServerCode: exports,
1700
+ migrations: {
1701
+ '11.0.0-modified-at': `
1702
+ ALTER TABLE "actor"
1703
+ ADD COLUMN IF NOT EXISTS "modified at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL;
1704
+
1705
+ ALTER TABLE "api key"
1706
+ ADD COLUMN IF NOT EXISTS "modified at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL;
1707
+ ALTER TABLE "api key-has-permission"
1708
+ ADD COLUMN IF NOT EXISTS "modified at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL;
1709
+ ALTER TABLE "api key-has-role"
1710
+ ADD COLUMN IF NOT EXISTS "modified at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL;
1711
+
1712
+ ALTER TABLE "permission"
1713
+ ADD COLUMN IF NOT EXISTS "modified at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL;
1714
+
1715
+ ALTER TABLE "role"
1716
+ ADD COLUMN IF NOT EXISTS "modified at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL;
1717
+
1718
+ ALTER TABLE "user"
1719
+ ADD COLUMN IF NOT EXISTS "modified at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL;
1720
+ ALTER TABLE "user-has-role"
1721
+ ADD COLUMN IF NOT EXISTS "modified at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL;
1722
+ ALTER TABLE "user-has-permission"
1723
+ ADD COLUMN IF NOT EXISTS "modified at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL;
1724
+ `,
1725
+ '11.0.1-modified-at': `
1726
+ ALTER TABLE "role-has-permission"
1727
+ ADD COLUMN IF NOT EXISTS "modified at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL;
1728
+ `,
1729
+ '14.42.0-api-key-expiry-date': `
1730
+ ALTER TABLE "api key"
1731
+ ADD COLUMN IF NOT EXISTS "expiry date" TIMESTAMP NULL;
1732
+ `,
1733
+ },
1734
+ } as const satisfies sbvrUtils.ExecutableModel;
1689
1735
  export const config = {
1690
- models: [
1691
- {
1692
- apiRoot: 'Auth',
1693
- modelText: userModel,
1694
- customServerCode: exports,
1695
- migrations: {
1696
- '11.0.0-modified-at': `
1697
- ALTER TABLE "actor"
1698
- ADD COLUMN IF NOT EXISTS "modified at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL;
1699
-
1700
- ALTER TABLE "api key"
1701
- ADD COLUMN IF NOT EXISTS "modified at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL;
1702
- ALTER TABLE "api key-has-permission"
1703
- ADD COLUMN IF NOT EXISTS "modified at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL;
1704
- ALTER TABLE "api key-has-role"
1705
- ADD COLUMN IF NOT EXISTS "modified at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL;
1706
-
1707
- ALTER TABLE "permission"
1708
- ADD COLUMN IF NOT EXISTS "modified at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL;
1709
-
1710
- ALTER TABLE "role"
1711
- ADD COLUMN IF NOT EXISTS "modified at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL;
1712
-
1713
- ALTER TABLE "user"
1714
- ADD COLUMN IF NOT EXISTS "modified at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL;
1715
- ALTER TABLE "user-has-role"
1716
- ADD COLUMN IF NOT EXISTS "modified at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL;
1717
- ALTER TABLE "user-has-permission"
1718
- ADD COLUMN IF NOT EXISTS "modified at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL;
1719
- `,
1720
- '11.0.1-modified-at': `
1721
- ALTER TABLE "role-has-permission"
1722
- ADD COLUMN IF NOT EXISTS "modified at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL;
1723
- `,
1724
- '14.42.0-api-key-expiry-date': `
1725
- ALTER TABLE "api key"
1726
- ADD COLUMN IF NOT EXISTS "expiry date" TIMESTAMP NULL;
1727
- `,
1728
- },
1729
- },
1730
- ] as sbvrUtils.ExecutableModel[],
1731
- };
1736
+ models: [authModelConfig],
1737
+ } satisfies Config;
1732
1738
  export const setup = () => {
1733
1739
  addHook('all', 'all', 'all', {
1734
1740
  sideEffects: false,