@balena/pinejs 17.1.0-build-joshbwlng-tasks-e8a81b1d884e0039e67661a25a5cb81d46966640-1 → 17.1.0-build-model-based-typings-86a981c89f828217571c93fa010174529a5345f9-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 (64) hide show
  1. package/.pinejs-cache.json +1 -1
  2. package/.versionbot/CHANGELOG.yml +220 -7
  3. package/CHANGELOG.md +65 -2
  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/migrator/migrations.d.ts +113 -0
  13. package/out/migrator/migrations.js +3 -0
  14. package/out/migrator/migrations.js.map +1 -0
  15. package/out/migrator/sync.d.ts +17 -0
  16. package/out/migrator/sync.js +39 -40
  17. package/out/migrator/sync.js.map +1 -1
  18. package/out/sbvr-api/dev.d.ts +41 -0
  19. package/out/sbvr-api/dev.js +3 -0
  20. package/out/sbvr-api/dev.js.map +1 -0
  21. package/out/sbvr-api/hooks.d.ts +26 -26
  22. package/out/sbvr-api/hooks.js.map +1 -1
  23. package/out/sbvr-api/permissions.d.ts +26 -2
  24. package/out/sbvr-api/permissions.js +39 -40
  25. package/out/sbvr-api/permissions.js.map +1 -1
  26. package/out/sbvr-api/sbvr-utils.d.ts +46 -6
  27. package/out/sbvr-api/sbvr-utils.js +44 -44
  28. package/out/sbvr-api/sbvr-utils.js.map +1 -1
  29. package/out/sbvr-api/user.d.ts +467 -0
  30. package/out/sbvr-api/user.js +3 -0
  31. package/out/sbvr-api/user.js.map +1 -0
  32. package/out/server-glue/module.d.ts +0 -1
  33. package/out/server-glue/module.js +1 -4
  34. package/out/server-glue/module.js.map +1 -1
  35. package/package.json +18 -19
  36. package/src/config-loader/env.ts +1 -6
  37. package/src/data-server/sbvr-server.js +3 -2
  38. package/src/database-layer/db.ts +0 -25
  39. package/src/migrator/migrations.ts +120 -0
  40. package/src/migrator/sync.ts +46 -41
  41. package/src/sbvr-api/dev.ts +44 -0
  42. package/src/sbvr-api/hooks.ts +21 -18
  43. package/src/sbvr-api/permissions.ts +50 -44
  44. package/src/sbvr-api/sbvr-utils.ts +90 -53
  45. package/src/sbvr-api/user.ts +421 -0
  46. package/src/server-glue/module.ts +0 -3
  47. package/out/tasks/common.d.ts +0 -4
  48. package/out/tasks/common.js +0 -13
  49. package/out/tasks/common.js.map +0 -1
  50. package/out/tasks/index.d.ts +0 -8
  51. package/out/tasks/index.js +0 -142
  52. package/out/tasks/index.js.map +0 -1
  53. package/out/tasks/tasks.sbvr +0 -60
  54. package/out/tasks/types.d.ts +0 -38
  55. package/out/tasks/types.js +0 -10
  56. package/out/tasks/types.js.map +0 -1
  57. package/out/tasks/worker.d.ts +0 -16
  58. package/out/tasks/worker.js +0 -228
  59. package/out/tasks/worker.js.map +0 -1
  60. package/src/tasks/common.ts +0 -14
  61. package/src/tasks/index.ts +0 -158
  62. package/src/tasks/tasks.sbvr +0 -60
  63. package/src/tasks/types.ts +0 -58
  64. 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);
@@ -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
  };
@@ -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,
@@ -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');
@@ -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,