@balena/pinejs 14.44.0-linear-runtime-migrator-e15bea04e85fb013aeed7d4770052b51747a619c → 15.0.0-delete-state-default-user-permissions-ba0732a0c5d0da9d1d5be818cb08cc898e86ebe3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. package/.versionbot/CHANGELOG.yml +24 -45
  2. package/CHANGELOG.md +8 -6
  3. package/VERSION +1 -1
  4. package/docs/Migrations.md +1 -101
  5. package/out/config-loader/config-loader.d.ts +4 -2
  6. package/out/config-loader/config-loader.js +20 -35
  7. package/out/config-loader/config-loader.js.map +1 -1
  8. package/out/config-loader/env.d.ts +0 -3
  9. package/out/config-loader/env.js +0 -3
  10. package/out/config-loader/env.js.map +1 -1
  11. package/out/migrator/migrations.sbvr +0 -66
  12. package/out/migrator/migrator.d.ts +17 -0
  13. package/out/migrator/migrator.js +185 -0
  14. package/out/migrator/migrator.js.map +1 -0
  15. package/out/sbvr-api/sbvr-utils.d.ts +1 -3
  16. package/out/sbvr-api/sbvr-utils.js +4 -13
  17. package/out/sbvr-api/sbvr-utils.js.map +1 -1
  18. package/out/server-glue/module.d.ts +2 -2
  19. package/out/server-glue/module.js +1 -2
  20. package/out/server-glue/module.js.map +1 -1
  21. package/package.json +3 -3
  22. package/src/config-loader/config-loader.ts +26 -73
  23. package/src/config-loader/env.ts +0 -3
  24. package/src/migrator/migrations.sbvr +0 -66
  25. package/src/migrator/migrator.ts +278 -0
  26. package/src/sbvr-api/sbvr-utils.ts +3 -18
  27. package/src/server-glue/module.ts +2 -3
  28. package/out/migrator/async.d.ts +0 -6
  29. package/out/migrator/async.js +0 -160
  30. package/out/migrator/async.js.map +0 -1
  31. package/out/migrator/sync.d.ts +0 -9
  32. package/out/migrator/sync.js +0 -126
  33. package/out/migrator/sync.js.map +0 -1
  34. package/out/migrator/utils.d.ts +0 -56
  35. package/out/migrator/utils.js +0 -187
  36. package/out/migrator/utils.js.map +0 -1
  37. package/src/migrator/async.ts +0 -279
  38. package/src/migrator/sync.ts +0 -177
  39. package/src/migrator/utils.ts +0 -296
@@ -1,296 +0,0 @@
1
- import type { Result, Tx } from '../database-layer/db';
2
- import type { Resolvable } from '../sbvr-api/common-types';
3
-
4
- import { Engines } from '@balena/abstract-sql-compiler';
5
- import * as _ from 'lodash';
6
- import { TypedError } from 'typed-error';
7
- import { migrator as migratorEnv } from '../config-loader/env';
8
- export { migrator as migratorEnv } from '../config-loader/env';
9
- import { delay } from '../sbvr-api/control-flow';
10
-
11
- // tslint:disable-next-line:no-var-requires
12
- export const modelText = require('./migrations.sbvr');
13
-
14
- import * as sbvrUtils from '../sbvr-api/sbvr-utils';
15
-
16
- export const defaultMigrationCategory: MigrationCategory = 'sync';
17
- export enum MigrationCategories {
18
- 'sync' = 'sync',
19
- 'async' = 'async',
20
- }
21
- export type MigrationCategory = 'sync';
22
- export type CategorizedMigrations = {
23
- [key in MigrationCategories]: Migrations;
24
- };
25
-
26
- type SbvrUtils = typeof sbvrUtils;
27
-
28
- export type MigrationTuple = [string, Migration];
29
-
30
- export type MigrationFn = (tx: Tx, sbvrUtils: SbvrUtils) => Resolvable<void>;
31
- export type RunnableMigrations = { [key: string]: Migration };
32
- export type Migrations = CategorizedMigrations | RunnableMigrations;
33
- export type AsyncMigrationFn = (
34
- tx: Tx,
35
- sbvrUtils: SbvrUtils,
36
- ) => Resolvable<Result>;
37
-
38
- export type AsyncMigration = {
39
- fn?: AsyncMigrationFn | undefined;
40
- sql?: string | undefined;
41
- delayMS?: number | undefined;
42
- backoffDelayMS?: number | undefined;
43
- errorThreshold?: number | undefined;
44
- };
45
-
46
- export type Migration = string | MigrationFn | AsyncMigration;
47
- export class MigrationError extends TypedError {}
48
-
49
- export type MigrationStatus = {
50
- migration_key: string;
51
- start_time: Date;
52
- last_run_time: Date;
53
- run_counter: number;
54
- migrated_rows: number;
55
- error_counter: number;
56
- error_threshold: number;
57
- delayMS: number;
58
- backoffDelayMS: number;
59
- converged_time: Date | undefined;
60
- last_error_message: string | undefined;
61
- is_backoff: boolean;
62
- should_stop: boolean;
63
- };
64
-
65
- // Tagged template to convert binds from `?` format to the necessary output format,
66
- // eg `$1`/`$2`/etc for postgres
67
- export const binds = (strings: TemplateStringsArray, ...bindNums: number[]) =>
68
- strings
69
- .map((str, i) => {
70
- if (i === bindNums.length) {
71
- return str;
72
- }
73
- if (i + 1 !== bindNums[i]) {
74
- throw new SyntaxError('Migration sql binds must be sequential');
75
- }
76
- if (sbvrUtils.db.engine === Engines.postgres) {
77
- return str + `$${bindNums[i]}`;
78
- }
79
- return str + `?`;
80
- })
81
- .join('');
82
-
83
- export const lockMigrations = async <T>(
84
- tx: Tx,
85
- modelName: string,
86
- fn: () => Promise<T>,
87
- ): Promise<T> => {
88
- try {
89
- await tx.executeSql(
90
- binds`
91
- DELETE FROM "migration lock"
92
- WHERE "model name" = ${1}
93
- AND "created at" < ${2}`,
94
- [modelName, new Date(Date.now() - migratorEnv.lockTimeout)],
95
- );
96
- await tx.executeSql(
97
- binds`
98
- INSERT INTO "migration lock" ("model name")
99
- VALUES (${1})`,
100
- [modelName],
101
- );
102
- } catch (err) {
103
- await delay(migratorEnv.lockFailDelay);
104
- throw err;
105
- }
106
- try {
107
- return await fn();
108
- } finally {
109
- try {
110
- await tx.executeSql(
111
- binds`
112
- DELETE FROM "migration lock"
113
- WHERE "model name" = ${1}`,
114
- [modelName],
115
- );
116
- } catch {
117
- // We ignore errors here as it's mostly likely caused by the migration failing and
118
- // rolling back the transaction, and if we rethrow here we'll overwrite the real error
119
- // making it much harder for users to see what went wrong and fix it
120
- }
121
- }
122
- };
123
-
124
- export const checkModelAlreadyExists = async (
125
- tx: Tx,
126
- modelName: string,
127
- ): Promise<boolean> => {
128
- const result = await tx.tableList("name = 'migration'");
129
- if (result.rows.length === 0) {
130
- return false;
131
- }
132
- const { rows } = await tx.executeSql(
133
- binds`
134
- SELECT 1
135
- FROM "model"
136
- WHERE "model"."is of-vocabulary" = ${1}
137
- LIMIT 1`,
138
- [modelName],
139
- );
140
-
141
- return rows.length > 0;
142
- };
143
-
144
- export const setExecutedMigrations = async (
145
- tx: Tx,
146
- modelName: string,
147
- executedMigrations: string[],
148
- ): Promise<void> => {
149
- const stringifiedMigrations = JSON.stringify(executedMigrations);
150
-
151
- const result = await tx.tableList("name = 'migration'");
152
- if (result.rows.length === 0) {
153
- return;
154
- }
155
-
156
- const { rowsAffected } = await tx.executeSql(
157
- binds`
158
- UPDATE "migration"
159
- SET "model name" = ${1},
160
- "executed migrations" = ${2}
161
- WHERE "migration"."model name" = ${3}`,
162
- [modelName, stringifiedMigrations, modelName],
163
- );
164
-
165
- if (rowsAffected === 0) {
166
- await tx.executeSql(
167
- binds`
168
- INSERT INTO "migration" ("model name", "executed migrations")
169
- VALUES (${1}, ${2})`,
170
- [modelName, stringifiedMigrations],
171
- );
172
- }
173
- };
174
-
175
- export const getExecutedMigrations = async (
176
- tx: Tx,
177
- modelName: string,
178
- ): Promise<string[]> => {
179
- const { rows } = await tx.executeSql(
180
- binds`
181
- SELECT "migration"."executed migrations" AS "executed_migrations"
182
- FROM "migration"
183
- WHERE "migration"."model name" = ${1}`,
184
- [modelName],
185
- );
186
-
187
- const data = rows[0];
188
- if (data == null) {
189
- return [];
190
- }
191
-
192
- return JSON.parse(data.executed_migrations) as string[];
193
- };
194
-
195
- // Just update the "modified at" field to show liveness
196
- export const initMigrationStatus = async (
197
- tx: Tx,
198
- migrationStatus: MigrationStatus,
199
- ): Promise<Result | undefined> => {
200
- try {
201
- const result = await tx.executeSql(
202
- binds`
203
- INSERT INTO "migration status" ("migration key", "start time", "delayMS", "backoffDelayMS", "is backoff", "error threshold", "should stop")
204
- VALUES (${1}, ${2}, ${3}, ${4}, ${5}, ${6}, ${7});
205
- `,
206
- [
207
- migrationStatus['migration_key'],
208
- migrationStatus['start_time'],
209
- migrationStatus['delayMS'],
210
- migrationStatus['backoffDelayMS'],
211
- migrationStatus['is_backoff'] === true ? 1 : 0,
212
- migrationStatus['error_threshold'],
213
- migrationStatus['should_stop'] === true ? 1 : 0,
214
- ],
215
- );
216
- return result;
217
- } catch (err) {
218
- // it already exists and we can ignore this error.
219
- }
220
- };
221
-
222
- // Just update the "modified at" field to show liveness
223
- export const updateMigrationStatus = async (
224
- tx: Tx,
225
- migrationStatus: MigrationStatus,
226
- ): Promise<Result | undefined> => {
227
- try {
228
- return await tx.executeSql(
229
- binds`
230
- UPDATE "migration status"
231
- SET
232
- "run counter" = ${1},
233
- "last run time" = ${2},
234
- "migrated rows" = ${3},
235
- "error counter" = ${4},
236
- "converged time" = ${5},
237
- "last error message" = ${6},
238
- "is backoff" = ${7},
239
- "should stop" = ${8}
240
- WHERE "migration status"."migration key" = ${9};`,
241
- [
242
- migrationStatus['run_counter'],
243
- migrationStatus['last_run_time'],
244
- migrationStatus['migrated_rows'],
245
- migrationStatus['error_counter'],
246
- migrationStatus['converged_time'],
247
- migrationStatus['last_error_message'],
248
- migrationStatus['is_backoff'] === true ? 1 : 0,
249
- migrationStatus['should_stop'] === true ? 1 : 0,
250
- migrationStatus['migration_key'],
251
- ],
252
- );
253
- } catch (err) {
254
- // we ignore all errors to not spam the api logs
255
- }
256
- };
257
-
258
- export const readMigrationStatus = async (
259
- tx: Tx,
260
- migrationKey: string,
261
- ): Promise<MigrationStatus | undefined> => {
262
- try {
263
- const { rows } = await tx.executeSql(
264
- binds`
265
- SELECT *
266
- FROM "migration status"
267
- WHERE "migration status"."migration key" = ${1}
268
- LIMIT 1;`,
269
- [migrationKey],
270
- );
271
-
272
- const data = rows[0];
273
- if (data == null) {
274
- return undefined;
275
- }
276
-
277
- return {
278
- migration_key: data['migration key'],
279
- start_time: data['start time'],
280
- last_run_time: data['last run time'],
281
- run_counter: data['run counter'],
282
- migrated_rows: data['migrated rows'],
283
- error_counter: data['error counter'],
284
- error_threshold: data['error threshold'],
285
- delayMS: data['delayMS'],
286
- backoffDelayMS: data['backoffDelayMS'],
287
- converged_time: data['converged_time'],
288
- last_error_message: data['last error message'],
289
- is_backoff: data['is backoff'] === 1 ? true : false,
290
- should_stop: data['should stop'] === 1 ? true : false,
291
- };
292
- } catch (err) {
293
- // we ignore all errors to not spam the api logs
294
- return undefined;
295
- }
296
- };