@balena/pinejs 17.1.0-build-joshbwlng-tasks-e8a81b1d884e0039e67661a25a5cb81d46966640-1 → 17.1.0-build-model-based-typings-86a981c89f828217571c93fa010174529a5345f9-1

Sign up to get free protection for your applications and to get access to all the features.
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,