@balena/pinejs 17.1.0-build-joshbwlng-tasks-e3dcb0e73ea9c960af553c67cbf7121650f8d1ea-1 → 17.1.0-build-model-based-typings-c276ef4fb8482a246c25940d617d76b76847eff8-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 +227 -13
  3. package/CHANGELOG.md +70 -4
  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 +58 -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 +22 -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 +28 -28
  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 +236 -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 +20 -21
  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 +64 -0
  40. package/src/migrator/sync.ts +46 -41
  41. package/src/sbvr-api/dev.ts +26 -0
  42. package/src/sbvr-api/hooks.ts +19 -18
  43. package/src/sbvr-api/permissions.ts +54 -48
  44. package/src/sbvr-api/sbvr-utils.ts +93 -53
  45. package/src/sbvr-api/user.ts +216 -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 -11
  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 -140
  52. package/out/tasks/index.js.map +0 -1
  53. package/out/tasks/tasks.sbvr +0 -55
  54. package/out/tasks/types.d.ts +0 -37
  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 -226
  59. package/out/tasks/worker.js.map +0 -1
  60. package/src/tasks/common.ts +0 -9
  61. package/src/tasks/index.ts +0 -155
  62. package/src/tasks/tasks.sbvr +0 -55
  63. package/src/tasks/types.ts +0 -56
  64. package/src/tasks/worker.ts +0 -276
@@ -2,6 +2,10 @@ import type * as Express from 'express';
2
2
  import type * as Db from '../database-layer/db';
3
3
  import type { Model } from '../config-loader/config-loader';
4
4
  import type { AnyObject, RequiredField } from './common-types';
5
+ import type {
6
+ PickDeferred,
7
+ Resource,
8
+ } from '@balena/abstract-sql-to-typescript';
5
9
 
6
10
  // Augment the Express typings
7
11
  declare global {
@@ -32,6 +36,7 @@ import {
32
36
  } from '@balena/odata-to-abstract-sql';
33
37
  import sbvrTypes from '@balena/sbvr-types';
34
38
  import deepFreeze = require('deep-freeze');
39
+ import type { AnyResource, Params } from 'pinejs-client-core';
35
40
  import { PinejsClientCore, type PromiseResultTypes } from 'pinejs-client-core';
36
41
 
37
42
  import { ExtendedSBVRParser } from '../extended-sbvr-parser/extended-sbvr-parser';
@@ -40,9 +45,9 @@ import * as asyncMigrator from '../migrator/async';
40
45
  import * as syncMigrator from '../migrator/sync';
41
46
  import { generateODataMetadata } from '../odata-metadata/odata-metadata-generator';
42
47
 
48
+ import type DevModel from './dev';
43
49
  // eslint-disable-next-line @typescript-eslint/no-var-requires
44
50
  const devModel = require('./dev.sbvr');
45
- import * as tasks from '../tasks';
46
51
  import * as permissions from './permissions';
47
52
  import {
48
53
  BadRequestError,
@@ -78,7 +83,6 @@ export {
78
83
  addPureHook,
79
84
  addSideEffectHook,
80
85
  } from './hooks';
81
- export { addTaskHandler } from '../tasks';
82
86
 
83
87
  import memoizeWeak = require('memoizee/weak');
84
88
  import * as controlFlow from './control-flow';
@@ -712,7 +716,7 @@ export const executeModels = async (
712
716
  },
713
717
  });
714
718
  }
715
- const result = (await api.dev.get({
719
+ const result = await api.dev.get({
716
720
  resource: 'model',
717
721
  passthrough: {
718
722
  tx,
@@ -725,7 +729,7 @@ export const executeModels = async (
725
729
  model_type: modelType,
726
730
  },
727
731
  },
728
- })) as Array<{ id: number }>;
732
+ });
729
733
 
730
734
  let method: SupportedMethod = 'POST';
731
735
  let uri = '/dev/model';
@@ -775,7 +779,7 @@ export const postExecuteModels = async (tx: Db.Tx): Promise<void> => {
775
779
  // Hence, skipped migrations from earlier models are not set as executed as the `migration` table is missing
776
780
  // Here the skipped migrations that haven't been set properly are covered
777
781
  // This is mostly an edge case when running on an empty database schema and migrations model hasn't been executed, yet.
778
- // One specific case are tests to run tests against migrated and unmigrated database states
782
+ // One specifc case are tests to run tests against migrated and unmigrated database states
779
783
 
780
784
  for (const modelKey of Object.keys(models)) {
781
785
  const pendingToSetExecutedMigrations =
@@ -785,9 +789,6 @@ export const postExecuteModels = async (tx: Db.Tx): Promise<void> => {
785
789
  await setExecutedMigrations(tx, modelKey, pendingToSetExecutedMigrations);
786
790
  }
787
791
  }
788
-
789
- // Initialize task worker and create required hooks
790
- await tasks.setup(db);
791
792
  };
792
793
 
793
794
  const cleanupModel = (vocab: string) => {
@@ -1007,7 +1008,16 @@ export type Passthrough = AnyObject & {
1007
1008
  tx?: Db.Tx;
1008
1009
  };
1009
1010
 
1010
- export class PinejsClient extends PinejsClientCore {
1011
+ export class PinejsClient<
1012
+ M extends {
1013
+ [key in keyof M]: Resource;
1014
+ } = {
1015
+ [key in string]: {
1016
+ Read: AnyObject;
1017
+ Write: AnyObject;
1018
+ };
1019
+ },
1020
+ > extends PinejsClientCore<unknown, M> {
1011
1021
  public async _request({
1012
1022
  method,
1013
1023
  url,
@@ -1025,11 +1035,37 @@ export class PinejsClient extends PinejsClientCore {
1025
1035
  }) {
1026
1036
  return (await runURI(method, url, body, tx, req, custom)) as object;
1027
1037
  }
1038
+
1039
+ public post<TResource extends keyof M & string>(
1040
+ params: {
1041
+ resource: TResource;
1042
+ options?: Params<M[TResource]>['options'] & { returnResource?: true };
1043
+ } & Params<M[TResource]>,
1044
+ ): Promise<PickDeferred<M[TResource]['Read']>>;
1045
+ public post<TResource extends keyof M & string>(
1046
+ params: {
1047
+ resource: TResource;
1048
+ options: Params<M[TResource]>['options'] & { returnResource: boolean };
1049
+ } & Params<M[TResource]>,
1050
+ ): Promise<Pick<M[TResource]['Read'], 'id'>>; // TODO: This should use the primary key rather than hardcoding `id`
1051
+ /**
1052
+ * @deprecated POSTing via `url` is deprecated
1053
+ */
1054
+ public post<T extends Resource = AnyResource>(
1055
+ params: {
1056
+ resource?: undefined;
1057
+ url: NonNullable<Params<T>['url']>;
1058
+ } & Params<T>,
1059
+ ): Promise<AnyObject>;
1060
+ public post(params: Params<AnyResource>): Promise<AnyObject> {
1061
+ return super.post(params as Parameters<PinejsClient['post']>[0]);
1062
+ }
1028
1063
  }
1029
1064
 
1030
- export const api: {
1065
+ export interface API {
1031
1066
  [vocab: string]: PinejsClient;
1032
- } = {};
1067
+ }
1068
+ export const api = {} as API;
1033
1069
  export const logger: {
1034
1070
  [vocab: string]: Console;
1035
1071
  } = {};
@@ -1136,8 +1172,8 @@ const getIdField = (
1136
1172
  // TODO: Should resolveSynonym also be using the finalAbstractSqlModel?
1137
1173
  getFinalAbstractSqlModel(request).tables[resolveSynonym(request)].idField;
1138
1174
 
1139
- export const getAffectedIds = async (
1140
- args: HookArgs & {
1175
+ export const getAffectedIds = async <Vocab extends string>(
1176
+ args: HookArgs<Vocab> & {
1141
1177
  tx: Db.Tx;
1142
1178
  },
1143
1179
  ): Promise<number[]> => {
@@ -1159,11 +1195,11 @@ export const getAffectedIds = async (
1159
1195
  return request.affectedIds;
1160
1196
  };
1161
1197
 
1162
- const $getAffectedIds = async ({
1198
+ const $getAffectedIds = async <Vocab extends string>({
1163
1199
  req,
1164
1200
  request,
1165
1201
  tx,
1166
- }: HookArgs & {
1202
+ }: HookArgs<Vocab> & {
1167
1203
  tx: Db.Tx;
1168
1204
  }): Promise<number[]> => {
1169
1205
  if (!['PATCH', 'DELETE'].includes(request.method)) {
@@ -1946,47 +1982,51 @@ const runDelete = async (
1946
1982
  }
1947
1983
  };
1948
1984
 
1985
+ export interface API {
1986
+ [devModelConfig.apiRoot]: PinejsClient<DevModel>;
1987
+ }
1988
+ const devModelConfig = {
1989
+ apiRoot: 'dev',
1990
+ modelText: devModel,
1991
+ logging: {
1992
+ log: false,
1993
+ },
1994
+ migrations: {
1995
+ '11.0.0-modified-at': `
1996
+ ALTER TABLE "model"
1997
+ ADD COLUMN IF NOT EXISTS "modified at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL;
1998
+ `,
1999
+ '15.0.0-data-types': async ($tx, sbvrUtils) => {
2000
+ switch (sbvrUtils.db.engine) {
2001
+ case 'mysql':
2002
+ await $tx.executeSql(`\
2003
+ ALTER TABLE "model"
2004
+ MODIFY "model value" JSON NOT NULL;
2005
+
2006
+ UPDATE "model"
2007
+ SET "model value" = CAST('{"value":' || CAST("model value" AS CHAR) || '}' AS JSON)
2008
+ WHERE "model type" IN ('se', 'odataMetadata')
2009
+ AND CAST("model value" AS CHAR) LIKE '"%';`);
2010
+ break;
2011
+ case 'postgres':
2012
+ await $tx.executeSql(`\
2013
+ ALTER TABLE "model"
2014
+ ALTER COLUMN "model value" SET DATA TYPE JSONB USING "model value"::JSONB;
2015
+
2016
+ UPDATE "model"
2017
+ SET "model value" = CAST('{"value":' || CAST("model value" AS TEXT) || '}' AS JSON)
2018
+ WHERE "model type" IN ('se', 'odataMetadata')
2019
+ AND CAST("model value" AS TEXT) LIKE '"%';`);
2020
+ break;
2021
+ // No need to migrate for websql
2022
+ }
2023
+ },
2024
+ },
2025
+ } as const satisfies ExecutableModel;
1949
2026
  export const executeStandardModels = async (tx: Db.Tx): Promise<void> => {
1950
2027
  try {
1951
2028
  // dev model must run first
1952
- await executeModel(tx, {
1953
- apiRoot: 'dev',
1954
- modelText: devModel,
1955
- logging: {
1956
- log: false,
1957
- },
1958
- migrations: {
1959
- '11.0.0-modified-at': `
1960
- ALTER TABLE "model"
1961
- ADD COLUMN IF NOT EXISTS "modified at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL;
1962
- `,
1963
- '15.0.0-data-types': async ($tx, sbvrUtils) => {
1964
- switch (sbvrUtils.db.engine) {
1965
- case 'mysql':
1966
- await $tx.executeSql(`\
1967
- ALTER TABLE "model"
1968
- MODIFY "model value" JSON NOT NULL;
1969
-
1970
- UPDATE "model"
1971
- SET "model value" = CAST('{"value":' || CAST("model value" AS CHAR) || '}' AS JSON)
1972
- WHERE "model type" IN ('se', 'odataMetadata')
1973
- AND CAST("model value" AS CHAR) LIKE '"%';`);
1974
- break;
1975
- case 'postgres':
1976
- await $tx.executeSql(`\
1977
- ALTER TABLE "model"
1978
- ALTER COLUMN "model value" SET DATA TYPE JSONB USING "model value"::JSONB;
1979
-
1980
- UPDATE "model"
1981
- SET "model value" = CAST('{"value":' || CAST("model value" AS TEXT) || '}' AS JSON)
1982
- WHERE "model type" IN ('se', 'odataMetadata')
1983
- AND CAST("model value" AS TEXT) LIKE '"%';`);
1984
- break;
1985
- // No need to migrate for websql
1986
- }
1987
- },
1988
- },
1989
- });
2029
+ await executeModel(tx, devModelConfig);
1990
2030
  await executeModels(tx, permissions.config.models);
1991
2031
  console.info('Successfully executed standard models.');
1992
2032
  } catch (err: any) {
@@ -0,0 +1,216 @@
1
+ // These types were generated by @balena/abstract-sql-to-typescript v3.2.1
2
+
3
+ import type { Types } from '@balena/abstract-sql-to-typescript';
4
+
5
+ export interface Permission {
6
+ Read: {
7
+ created_at: Types['Date Time']['Read'];
8
+ modified_at: Types['Date Time']['Read'];
9
+ id: Types['Serial']['Read'];
10
+ name: Types['Text']['Read'];
11
+ is_of__role?: Array<RoleHasPermission['Read']>;
12
+ is_of__user?: Array<UserHasPermission['Read']>;
13
+ is_of__api_key?: Array<ApiKeyHasPermission['Read']>;
14
+ user__has__permission?: Array<UserHasPermission['Read']>;
15
+ user_permission?: Array<UserHasPermission['Read']>;
16
+ };
17
+ Write: {
18
+ created_at: Types['Date Time']['Write'];
19
+ modified_at: Types['Date Time']['Write'];
20
+ id: Types['Serial']['Write'];
21
+ name: Types['Text']['Write'];
22
+ };
23
+ }
24
+
25
+ export interface Role {
26
+ Read: {
27
+ created_at: Types['Date Time']['Read'];
28
+ modified_at: Types['Date Time']['Read'];
29
+ id: Types['Serial']['Read'];
30
+ name: Types['Text']['Read'];
31
+ role__has__permission?: Array<RoleHasPermission['Read']>;
32
+ user__has__role?: Array<UserHasRole['Read']>;
33
+ user_role?: Array<UserHasRole['Read']>;
34
+ is_of__user?: Array<UserHasRole['Read']>;
35
+ is_of__api_key?: Array<ApiKeyHasRole['Read']>;
36
+ };
37
+ Write: {
38
+ created_at: Types['Date Time']['Write'];
39
+ modified_at: Types['Date Time']['Write'];
40
+ id: Types['Serial']['Write'];
41
+ name: Types['Text']['Write'];
42
+ };
43
+ }
44
+
45
+ export interface RoleHasPermission {
46
+ Read: {
47
+ created_at: Types['Date Time']['Read'];
48
+ modified_at: Types['Date Time']['Read'];
49
+ role: { __id: Role['Read']['id'] } | [Role['Read']];
50
+ permission: { __id: Permission['Read']['id'] } | [Permission['Read']];
51
+ id: Types['Serial']['Read'];
52
+ is_of__role: { __id: Role['Read']['id'] } | [Role['Read']];
53
+ };
54
+ Write: {
55
+ created_at: Types['Date Time']['Write'];
56
+ modified_at: Types['Date Time']['Write'];
57
+ role: Role['Write']['id'];
58
+ permission: Permission['Write']['id'];
59
+ id: Types['Serial']['Write'];
60
+ };
61
+ }
62
+
63
+ export interface Actor {
64
+ Read: {
65
+ created_at: Types['Date Time']['Read'];
66
+ modified_at: Types['Date Time']['Read'];
67
+ id: Types['Serial']['Read'];
68
+ is_of__user?: Array<User['Read']>;
69
+ api_key?: Array<ApiKey['Read']>;
70
+ };
71
+ Write: {
72
+ created_at: Types['Date Time']['Write'];
73
+ modified_at: Types['Date Time']['Write'];
74
+ id: Types['Serial']['Write'];
75
+ };
76
+ }
77
+
78
+ export interface User {
79
+ Read: {
80
+ created_at: Types['Date Time']['Read'];
81
+ modified_at: Types['Date Time']['Read'];
82
+ id: Types['Serial']['Read'];
83
+ actor: { __id: Actor['Read']['id'] } | [Actor['Read']];
84
+ username: Types['Short Text']['Read'];
85
+ password: Types['Hashed']['Read'];
86
+ user__has__role?: Array<UserHasRole['Read']>;
87
+ user_role?: Array<UserHasRole['Read']>;
88
+ user__has__permission?: Array<UserHasPermission['Read']>;
89
+ user_permission?: Array<UserHasPermission['Read']>;
90
+ };
91
+ Write: {
92
+ created_at: Types['Date Time']['Write'];
93
+ modified_at: Types['Date Time']['Write'];
94
+ id: Types['Serial']['Write'];
95
+ actor: Actor['Write']['id'];
96
+ username: Types['Short Text']['Write'];
97
+ password: Types['Hashed']['Write'];
98
+ };
99
+ }
100
+
101
+ export interface UserHasRole {
102
+ Read: {
103
+ created_at: Types['Date Time']['Read'];
104
+ modified_at: Types['Date Time']['Read'];
105
+ user: { __id: User['Read']['id'] } | [User['Read']];
106
+ role: { __id: Role['Read']['id'] } | [Role['Read']];
107
+ id: Types['Serial']['Read'];
108
+ expiry_date: Types['Date Time']['Read'] | null;
109
+ is_of__user: { __id: User['Read']['id'] } | [User['Read']];
110
+ };
111
+ Write: {
112
+ created_at: Types['Date Time']['Write'];
113
+ modified_at: Types['Date Time']['Write'];
114
+ user: User['Write']['id'];
115
+ role: Role['Write']['id'];
116
+ id: Types['Serial']['Write'];
117
+ expiry_date: Types['Date Time']['Write'] | null;
118
+ };
119
+ }
120
+
121
+ export interface UserHasPermission {
122
+ Read: {
123
+ created_at: Types['Date Time']['Read'];
124
+ modified_at: Types['Date Time']['Read'];
125
+ user: { __id: User['Read']['id'] } | [User['Read']];
126
+ permission: { __id: Permission['Read']['id'] } | [Permission['Read']];
127
+ id: Types['Serial']['Read'];
128
+ expiry_date: Types['Date Time']['Read'] | null;
129
+ is_of__user: { __id: User['Read']['id'] } | [User['Read']];
130
+ };
131
+ Write: {
132
+ created_at: Types['Date Time']['Write'];
133
+ modified_at: Types['Date Time']['Write'];
134
+ user: User['Write']['id'];
135
+ permission: Permission['Write']['id'];
136
+ id: Types['Serial']['Write'];
137
+ expiry_date: Types['Date Time']['Write'] | null;
138
+ };
139
+ }
140
+
141
+ export interface ApiKey {
142
+ Read: {
143
+ created_at: Types['Date Time']['Read'];
144
+ modified_at: Types['Date Time']['Read'];
145
+ id: Types['Serial']['Read'];
146
+ key: Types['Short Text']['Read'];
147
+ expiry_date: Types['Date Time']['Read'] | null;
148
+ is_of__actor: { __id: Actor['Read']['id'] } | [Actor['Read']];
149
+ name: Types['Text']['Read'] | null;
150
+ description: Types['Text']['Read'] | null;
151
+ api_key__has__role?: Array<ApiKeyHasRole['Read']>;
152
+ api_key__has__permission?: Array<ApiKeyHasPermission['Read']>;
153
+ };
154
+ Write: {
155
+ created_at: Types['Date Time']['Write'];
156
+ modified_at: Types['Date Time']['Write'];
157
+ id: Types['Serial']['Write'];
158
+ key: Types['Short Text']['Write'];
159
+ expiry_date: Types['Date Time']['Write'] | null;
160
+ is_of__actor: Actor['Write']['id'];
161
+ name: Types['Text']['Write'] | null;
162
+ description: Types['Text']['Write'] | null;
163
+ };
164
+ }
165
+
166
+ export interface ApiKeyHasRole {
167
+ Read: {
168
+ created_at: Types['Date Time']['Read'];
169
+ modified_at: Types['Date Time']['Read'];
170
+ api_key: { __id: ApiKey['Read']['id'] } | [ApiKey['Read']];
171
+ role: { __id: Role['Read']['id'] } | [Role['Read']];
172
+ id: Types['Serial']['Read'];
173
+ is_of__api_key: { __id: ApiKey['Read']['id'] } | [ApiKey['Read']];
174
+ };
175
+ Write: {
176
+ created_at: Types['Date Time']['Write'];
177
+ modified_at: Types['Date Time']['Write'];
178
+ api_key: ApiKey['Write']['id'];
179
+ role: Role['Write']['id'];
180
+ id: Types['Serial']['Write'];
181
+ };
182
+ }
183
+
184
+ export interface ApiKeyHasPermission {
185
+ Read: {
186
+ created_at: Types['Date Time']['Read'];
187
+ modified_at: Types['Date Time']['Read'];
188
+ api_key: { __id: ApiKey['Read']['id'] } | [ApiKey['Read']];
189
+ permission: { __id: Permission['Read']['id'] } | [Permission['Read']];
190
+ id: Types['Serial']['Read'];
191
+ is_of__api_key: { __id: ApiKey['Read']['id'] } | [ApiKey['Read']];
192
+ };
193
+ Write: {
194
+ created_at: Types['Date Time']['Write'];
195
+ modified_at: Types['Date Time']['Write'];
196
+ api_key: ApiKey['Write']['id'];
197
+ permission: Permission['Write']['id'];
198
+ id: Types['Serial']['Write'];
199
+ };
200
+ }
201
+
202
+ export default interface $Model {
203
+ permission: Permission;
204
+ role: Role;
205
+ role__has__permission: RoleHasPermission;
206
+ actor: Actor;
207
+ user: User;
208
+ user__has__role: UserHasRole;
209
+ user__has__permission: UserHasPermission;
210
+ api_key: ApiKey;
211
+ api_key__has__role: ApiKeyHasRole;
212
+ api_key__has__permission: ApiKeyHasPermission;
213
+ // Synonyms
214
+ user_role: UserHasRole;
215
+ user_permission: UserHasPermission;
216
+ }
@@ -6,7 +6,6 @@ import * as dbModule from '../database-layer/db';
6
6
  import * as configLoader from '../config-loader/config-loader';
7
7
  import * as migrator from '../migrator/sync';
8
8
  import type * as migratorUtils from '../migrator/utils';
9
- import * as tasks from '../tasks';
10
9
 
11
10
  import * as sbvrUtils from '../sbvr-api/sbvr-utils';
12
11
  import { PINEJS_ADVISORY_LOCK } from '../config-loader/env';
@@ -20,7 +19,6 @@ export * as errors from '../sbvr-api/errors';
20
19
  export * as env from '../config-loader/env';
21
20
  export * as types from '../sbvr-api/common-types';
22
21
  export * as hooks from '../sbvr-api/hooks';
23
- export * as tasks from '../tasks';
24
22
  export * as webResourceHandler from '../webresource-handler';
25
23
  export type { configLoader as ConfigLoader };
26
24
  export type { migratorUtils as Migrator };
@@ -65,7 +63,6 @@ export const init = async <T extends string>(
65
63
  await sbvrUtils.setup(app, db);
66
64
  const cfgLoader = await configLoader.setup(app);
67
65
  await cfgLoader.loadConfig(migrator.config);
68
- await cfgLoader.loadConfig(tasks.config);
69
66
 
70
67
  const promises: Array<Promise<void>> = [];
71
68
  if (process.env.SBVR_SERVER_ENABLED) {
@@ -1,4 +0,0 @@
1
- import Ajv from 'ajv';
2
- export declare const apiRoot = "tasks";
3
- export declare const channel = "pinejs$task_insert";
4
- export declare const ajv: Ajv;
@@ -1,11 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.ajv = exports.channel = exports.apiRoot = void 0;
7
- const ajv_1 = __importDefault(require("ajv"));
8
- exports.apiRoot = 'tasks';
9
- exports.channel = 'pinejs$task_insert';
10
- exports.ajv = new ajv_1.default();
11
- //# sourceMappingURL=common.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"common.js","sourceRoot":"","sources":["../../src/tasks/common.ts"],"names":[],"mappings":";;;;;;AAAA,8CAAsB;AAGT,QAAA,OAAO,GAAG,OAAO,CAAC;AAGlB,QAAA,OAAO,GAAG,oBAAoB,CAAC;AAE/B,QAAA,GAAG,GAAG,IAAI,aAAG,EAAE,CAAC"}
@@ -1,8 +0,0 @@
1
- import type { Schema } from 'ajv';
2
- import type * as Db from '../database-layer/db';
3
- import type { ConfigLoader } from '../server-glue/module';
4
- import type { TaskHandler } from './types';
5
- export * from './types';
6
- export declare const config: ConfigLoader.Config;
7
- export declare function setup(db: Db.Database): Promise<void>;
8
- export declare function addTaskHandler(name: string, fn: TaskHandler['fn'], schema?: Schema): void;
@@ -1,140 +0,0 @@
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
26
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
27
- };
28
- Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.addTaskHandler = exports.setup = exports.config = void 0;
30
- const cronParser = __importStar(require("cron-parser"));
31
- const env_1 = require("../config-loader/env");
32
- const errors_1 = require("../sbvr-api/errors");
33
- const hooks_1 = require("../sbvr-api/hooks");
34
- const sbvrUtils = __importStar(require("../sbvr-api/sbvr-utils"));
35
- const common_1 = require("./common");
36
- const worker_1 = require("./worker");
37
- __exportStar(require("./types"), exports);
38
- const modelText = require('./tasks.sbvr');
39
- const initSql = `
40
- CREATE OR REPLACE FUNCTION notify_task_insert()
41
- RETURNS TRIGGER AS $$
42
- BEGIN
43
- PERFORM pg_notify('${common_1.channel}', NEW.id::text);
44
- RETURN NEW;
45
- END;
46
- $$ LANGUAGE plpgsql;
47
-
48
- CREATE OR REPLACE TRIGGER task_insert_trigger
49
- AFTER INSERT ON task
50
- FOR EACH ROW WHEN (NEW.status = 'queued' AND NEW."is scheduled to execute on-time" IS NULL)
51
- EXECUTE FUNCTION notify_task_insert();
52
-
53
- CREATE INDEX IF NOT EXISTS idx_task_poll ON task USING btree (
54
- "is executed by-handler",
55
- "is scheduled to execute on-time" ASC,
56
- "id" ASC
57
- ) WHERE status = 'queued';
58
- `;
59
- exports.config = {
60
- models: [
61
- {
62
- modelName: common_1.apiRoot,
63
- apiRoot: common_1.apiRoot,
64
- modelText,
65
- customServerCode: exports,
66
- initSql,
67
- },
68
- ],
69
- };
70
- let worker = null;
71
- async function setup(db) {
72
- if (db.engine !== 'postgres') {
73
- console.warn('Skipping task setup as database not supported');
74
- return;
75
- }
76
- const client = sbvrUtils.api[common_1.apiRoot];
77
- worker = new worker_1.Worker(client);
78
- (0, hooks_1.addPureHook)('POST', common_1.apiRoot, 'task', {
79
- POSTPARSE: async ({ req, request }) => {
80
- request.values.is_created_by__actor =
81
- req.user?.actor ?? req.apiKey?.actor;
82
- if (request.values.is_created_by__actor == null) {
83
- throw new errors_1.BadRequestError('Creating tasks with missing actor on req is not allowed');
84
- }
85
- request.values.status = 'queued';
86
- request.values.attempt_count = 0;
87
- request.values.attempt_limit ??= 1;
88
- if (request.values.is_scheduled_with__cron_expression != null &&
89
- request.values.is_scheduled_to_execute_on__time == null) {
90
- try {
91
- request.values.is_scheduled_to_execute_on__time = cronParser
92
- .parseExpression(request.values.is_scheduled_with__cron_expression)
93
- .next()
94
- .toDate()
95
- .toISOString();
96
- }
97
- catch {
98
- throw new errors_1.BadRequestError(`Invalid cron expression: ${request.values.is_scheduled_with__cron_expression}`);
99
- }
100
- }
101
- if (request.values.is_scheduled_to_execute_on__time != null) {
102
- const now = new Date(Date.now() + env_1.tasks.queueIntervalMS);
103
- const startTime = new Date(request.values.is_scheduled_to_execute_on__time);
104
- if (startTime < now) {
105
- throw new errors_1.BadRequestError(`Task scheduled start time must be greater than ${env_1.tasks.queueIntervalMS} milliseconds in the future`);
106
- }
107
- }
108
- const handlerName = request.values.is_executed_by__handler;
109
- if (handlerName == null) {
110
- throw new errors_1.BadRequestError(`Must specify a task handler to execute`);
111
- }
112
- const handler = worker?.handlers[handlerName];
113
- if (handler == null) {
114
- throw new errors_1.BadRequestError(`No task handler with name '${handlerName}' registered`);
115
- }
116
- if (handler.validate != null) {
117
- if (!handler.validate(request.values.is_executed_with__parameter_set)) {
118
- throw new errors_1.BadRequestError(`Invalid parameter set: ${common_1.ajv.errorsText(handler.validate.errors)}`);
119
- }
120
- }
121
- },
122
- });
123
- worker.start();
124
- }
125
- exports.setup = setup;
126
- function addTaskHandler(name, fn, schema) {
127
- if (worker == null) {
128
- throw new Error('Database does not support tasks');
129
- }
130
- if (worker.handlers[name] != null) {
131
- throw new Error(`Task handler with name '${name}' already registered`);
132
- }
133
- worker.handlers[name] = {
134
- name,
135
- fn,
136
- validate: schema != null ? common_1.ajv.compile(schema) : undefined,
137
- };
138
- }
139
- exports.addTaskHandler = addTaskHandler;
140
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tasks/index.ts"],"names":[],"mappings":"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"}