@sanoma-ai/workflows 0.11.13 → 0.11.15

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.
@@ -1,6 +1,7 @@
1
- export { type Db, databaseOn, pgCode } from "../db.ts";
1
+ export { type Db, databaseOn, pgCode, underPreparationLock } from "../db.ts";
2
2
  export * from "./company.ts";
3
3
  export * from "./dbos.ts";
4
4
  export * from "./identity.ts";
5
5
  export * from "./kms.ts";
6
+ export * from "./migrate.ts";
6
7
  export * from "./wakeup.ts";
package/dist/db/index.js CHANGED
@@ -1,10 +1,12 @@
1
1
  // `@sanoma-ai/workflows/db`, server-only: the runtime's tables and the database they are read
2
- // with, for the packages that share them (the connectors' stores, the app's tests). Never a
3
- // workflow's import: the shipped `oxlint.json` refuses it, as it does `/wakeup-service`.
4
- export { databaseOn, pgCode } from "../db.js";
2
+ // with, for the packages that share them (the connectors' stores, the app's tests), and the
3
+ // migrator a connector applies its own generated folder with, under the preparation's lock. Never
4
+ // a workflow's import: the shipped `oxlint.json` refuses it, as it does `/wakeup-service`.
5
+ export { databaseOn, pgCode, underPreparationLock } from "../db.js";
5
6
  export * from "./company.js";
6
7
  export * from "./dbos.js";
7
8
  export * from "./identity.js";
8
9
  export * from "./kms.js";
10
+ export * from "./migrate.js";
9
11
  export * from "./wakeup.js";
10
12
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/db/index.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,4FAA4F;AAC5F,yFAAyF;AAEzF,OAAO,EAAW,UAAU,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AACvD,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/db/index.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,4FAA4F;AAC5F,kGAAkG;AAClG,2FAA2F;AAE3F,OAAO,EAAW,UAAU,EAAE,MAAM,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAC7E,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC"}
@@ -9,15 +9,18 @@ export interface MigrationsJournal {
9
9
  }
10
10
  /** A migrations folder with the journal table recording what of it a database has. */
11
11
  export interface Migrations {
12
- /** The folder's name under the package's `drizzle/`. */
13
- name: string;
12
+ /**
13
+ * The folder, beside the module declaring it (`new URL("../drizzle/<name>/", import.meta.url)`,
14
+ * from `src/` and from `dist/` alike), asked for only when migrating, never in the Worker.
15
+ */
16
+ folder(): URL;
14
17
  /** Its journal table in the schema `drizzle`. */
15
18
  table: string;
16
19
  journal: MigrationsJournal;
17
20
  }
18
21
  /** The tables every company database gets (`db/company.ts`). */
19
22
  export declare const COMPANY_MIGRATIONS: {
20
- name: string;
23
+ folder: () => import("node:url").URL;
21
24
  table: string;
22
25
  journal: {
23
26
  version: string;
@@ -33,7 +36,7 @@ export declare const COMPANY_MIGRATIONS: {
33
36
  };
34
37
  /** The wakeup service's tables (`db/wakeup.ts`). */
35
38
  export declare const WAKEUP_MIGRATIONS: {
36
- name: string;
39
+ folder: () => import("node:url").URL;
37
40
  table: string;
38
41
  journal: {
39
42
  version: string;
@@ -50,8 +53,8 @@ export declare const WAKEUP_MIGRATIONS: {
50
53
  /**
51
54
  * Applies to `db` the migrations of `of` its database has not had, in one transaction, recording
52
55
  * each in the journal table. Drizzle's migrator compares only the newest timestamp, so a migration
53
- * older than the newest applied is skipped: `scripts/check-journal.ts` keeps a branch from adding
54
- * one. Two processes migrating one database at once race (the migrator takes no lock): callers
56
+ * older than the newest applied is skipped: the repository's `scripts/check-journal.ts` keeps a
57
+ * branch from adding one. Two processes migrating one database at once race (the migrator takes no lock): callers
55
58
  * hold `underPreparationLock`.
56
59
  */
57
60
  export declare const applyMigrations: (db: Db, of: Migrations) => Promise<void>;
@@ -3,28 +3,26 @@ import { sql } from "drizzle-orm";
3
3
  import { migrate } from "drizzle-orm/node-postgres/migrator";
4
4
  import companyJournal from "../../drizzle/company/meta/_journal.json" with { type: "json" };
5
5
  import wakeupJournal from "../../drizzle/wakeup/meta/_journal.json" with { type: "json" };
6
- /** The folder of `of`, from `src/` and from `dist/` alike; read only when migrating, never in the Worker. */
7
- const folderOf = (of) => fileURLToPath(new URL(`../../drizzle/${of.name}/`, import.meta.url));
8
6
  /** The tables every company database gets (`db/company.ts`). */
9
7
  export const COMPANY_MIGRATIONS = {
10
- name: "company",
8
+ folder: () => new URL("../../drizzle/company/", import.meta.url),
11
9
  table: "__drizzle_migrations",
12
10
  journal: companyJournal,
13
11
  };
14
12
  /** The wakeup service's tables (`db/wakeup.ts`). */
15
13
  export const WAKEUP_MIGRATIONS = {
16
- name: "wakeup",
14
+ folder: () => new URL("../../drizzle/wakeup/", import.meta.url),
17
15
  table: "__drizzle_migrations_wakeup",
18
16
  journal: wakeupJournal,
19
17
  };
20
18
  /**
21
19
  * Applies to `db` the migrations of `of` its database has not had, in one transaction, recording
22
20
  * each in the journal table. Drizzle's migrator compares only the newest timestamp, so a migration
23
- * older than the newest applied is skipped: `scripts/check-journal.ts` keeps a branch from adding
24
- * one. Two processes migrating one database at once race (the migrator takes no lock): callers
21
+ * older than the newest applied is skipped: the repository's `scripts/check-journal.ts` keeps a
22
+ * branch from adding one. Two processes migrating one database at once race (the migrator takes no lock): callers
25
23
  * hold `underPreparationLock`.
26
24
  */
27
- export const applyMigrations = (db, of) => migrate(db, { migrationsFolder: folderOf(of), migrationsTable: of.table });
25
+ export const applyMigrations = (db, of) => migrate(db, { migrationsFolder: fileURLToPath(of.folder()), migrationsTable: of.table });
28
26
  /**
29
27
  * Whether the database `db` is on has had every migration of `of`: each journal entry's `when`
30
28
  * is a `created_at` of its journal table, whatever else the table holds (a database a newer
@@ -1 +1 @@
1
- {"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../src/db/migrate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,MAAM,oCAAoC,CAAC;AAE7D,OAAO,cAAc,MAAM,0CAA0C,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAC5F,OAAO,aAAa,MAAM,yCAAyC,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAsB1F,6GAA6G;AAC7G,MAAM,QAAQ,GAAG,CAAC,EAAc,EAAU,EAAE,CAAC,aAAa,CAAC,IAAI,GAAG,CAAC,iBAAiB,EAAE,CAAC,IAAI,GAAG,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAElH,gEAAgE;AAChE,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,IAAI,EAAE,SAAS;IACf,KAAK,EAAE,sBAAsB;IAC7B,OAAO,EAAE,cAAc;CACH,CAAC;AAEvB,oDAAoD;AACpD,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,IAAI,EAAE,QAAQ;IACd,KAAK,EAAE,6BAA6B;IACpC,OAAO,EAAE,aAAa;CACF,CAAC;AAEvB;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,EAAM,EAAE,EAAc,EAAiB,EAAE,CACvE,OAAO,CAAC,EAAE,EAAE,EAAE,gBAAgB,EAAE,QAAQ,CAAC,EAAE,CAAC,EAAE,eAAe,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC;AAE7E;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,EAAM,EAAE,EAAc;IAC5D,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAC9B,GAAG,CAAA,sBAAsB,WAAW,EAAE,CAAC,KAAK,EAAE,0BAA0B,CACzE,CAAC;IACF,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IACpD,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,EAAE,CAAC,OAAO,CAC/B,GAAG,CAAA,8CAA8C,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAC5E,CAAC;IACF,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC3D,OAAO,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;AACtE,CAAC"}
1
+ {"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../src/db/migrate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,MAAM,oCAAoC,CAAC;AAE7D,OAAO,cAAc,MAAM,0CAA0C,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAC5F,OAAO,aAAa,MAAM,yCAAyC,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AA0B1F,gEAAgE;AAChE,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI,GAAG,CAAC,wBAAwB,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC;IAChE,KAAK,EAAE,sBAAsB;IAC7B,OAAO,EAAE,cAAc;CACH,CAAC;AAEvB,oDAAoD;AACpD,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI,GAAG,CAAC,uBAAuB,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC;IAC/D,KAAK,EAAE,6BAA6B;IACpC,OAAO,EAAE,aAAa;CACF,CAAC;AAEvB;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,EAAM,EAAE,EAAc,EAAiB,EAAE,CACvE,OAAO,CAAC,EAAE,EAAE,EAAE,gBAAgB,EAAE,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,EAAE,eAAe,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC;AAE3F;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,EAAM,EAAE,EAAc;IAC5D,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAC9B,GAAG,CAAA,sBAAsB,WAAW,EAAE,CAAC,KAAK,EAAE,0BAA0B,CACzE,CAAC;IACF,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IACpD,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,EAAE,CAAC,OAAO,CAC/B,GAAG,CAAA,8CAA8C,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAC5E,CAAC;IACF,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC3D,OAAO,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;AACtE,CAAC"}
package/dist/fill.d.ts CHANGED
@@ -1,7 +1,11 @@
1
1
  import { z } from "zod";
2
2
  /** Seeds the generator from a name, so one name always makes up the same values. */
3
3
  export declare const seedFrom: (name: string) => void;
4
- /** The schema's value with every field `given` does not set made up, parsed by the schema. */
4
+ /**
5
+ * The schema's value with every required field `given` does not set made up, parsed by the schema.
6
+ * Optional fields are left out, as a caller may leave them: made up, they could break a rule
7
+ * between fields (one of two ids, not both).
8
+ */
5
9
  export declare function fill(schema: z.ZodType, given: Record<string, unknown>): unknown;
6
10
  /** An object schema's fields by name; none for any other schema. */
7
11
  export declare const shapeOf: (schema: z.ZodType) => Record<string, z.ZodType>;
package/dist/fill.js CHANGED
@@ -6,9 +6,18 @@ import { z } from "zod";
6
6
  setFaker(faker);
7
7
  /** Seeds the generator from a name, so one name always makes up the same values. */
8
8
  export const seedFrom = (name) => seed(createHash("sha256").update(name).digest().readUInt32BE(0));
9
- /** The schema's value with every field `given` does not set made up, parsed by the schema. */
9
+ /**
10
+ * The schema's value with every required field `given` does not set made up, parsed by the schema.
11
+ * Optional fields are left out, as a caller may leave them: made up, they could break a rule
12
+ * between fields (one of two ids, not both).
13
+ */
10
14
  export function fill(schema, given) {
11
- return schema.parse({ ...fake(schema), ...given });
15
+ const made = fake(schema);
16
+ for (const [name, field] of Object.entries(shapeOf(schema))) {
17
+ if (field.safeParse(undefined).success)
18
+ delete made[name];
19
+ }
20
+ return schema.parse({ ...made, ...given });
12
21
  }
13
22
  /** An object schema's fields by name; none for any other schema. */
14
23
  export const shapeOf = (schema) => schema instanceof z.ZodObject ? schema.shape : {};
package/dist/fill.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"fill.js","sourceRoot":"","sources":["../src/fill.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,+DAA+D;AAE/D,QAAQ,CAAC,KAAK,CAAC,CAAC;AAEhB,oFAAoF;AACpF,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;AAE3G,8FAA8F;AAC9F,MAAM,UAAU,IAAI,CAAC,MAAiB,EAAE,KAA8B;IACpE,OAAO,MAAM,CAAC,KAAK,CAAC,EAAE,GAAI,IAAI,CAAC,MAAM,CAAY,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;AACjE,CAAC;AAED,oEAAoE;AACpE,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,MAAiB,EAA6B,EAAE,CACtE,MAAM,YAAY,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AAEpD,sHAAsH;AACtH,MAAM,UAAU,MAAM,CAAC,MAAiB;IACtC,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,CAAC,SAAS,CAAC,CAAC,CAAE,MAAM,CAAC,GAAG,CAAC,QAAkC,CAAC,CAAC,CAAC,SAAS,CAAC;IACxG,OAAO,IAAI,YAAY,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;AACvD,CAAC;AAED,gGAAgG;AAChG,MAAM,UAAU,WAAW,CAAC,MAAiB;IAC3C,IAAI,KAAK,GAAG,MAAM,CAAC;IACnB,OAAO,KAAK,YAAY,CAAC,CAAC,WAAW,IAAI,KAAK,YAAY,CAAC,CAAC,WAAW,IAAI,KAAK,YAAY,CAAC,CAAC,UAAU,EAAE,CAAC;QACzG,KAAK,GAAG,KAAK,CAAC,MAAM,EAAe,CAAC;IACtC,CAAC;IACD,OAAO,KAAK,YAAY,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AAC1D,CAAC;AAED,gHAAgH;AAChH,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,GAAY,EAAE,EAAE,CACpC,GAAG,YAAY,SAAS,IAAI,GAAG,YAAY,UAAU,IAAI,GAAG,YAAY,cAAc,CAAC"}
1
+ {"version":3,"file":"fill.js","sourceRoot":"","sources":["../src/fill.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,+DAA+D;AAE/D,QAAQ,CAAC,KAAK,CAAC,CAAC;AAEhB,oFAAoF;AACpF,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;AAE3G;;;;GAIG;AACH,MAAM,UAAU,IAAI,CAAC,MAAiB,EAAE,KAA8B;IACpE,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAA4B,CAAC;IACrD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;QAC5D,IAAI,KAAK,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;AAC7C,CAAC;AAED,oEAAoE;AACpE,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,MAAiB,EAA6B,EAAE,CACtE,MAAM,YAAY,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AAEpD,sHAAsH;AACtH,MAAM,UAAU,MAAM,CAAC,MAAiB;IACtC,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,CAAC,SAAS,CAAC,CAAC,CAAE,MAAM,CAAC,GAAG,CAAC,QAAkC,CAAC,CAAC,CAAC,SAAS,CAAC;IACxG,OAAO,IAAI,YAAY,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;AACvD,CAAC;AAED,gGAAgG;AAChG,MAAM,UAAU,WAAW,CAAC,MAAiB;IAC3C,IAAI,KAAK,GAAG,MAAM,CAAC;IACnB,OAAO,KAAK,YAAY,CAAC,CAAC,WAAW,IAAI,KAAK,YAAY,CAAC,CAAC,WAAW,IAAI,KAAK,YAAY,CAAC,CAAC,UAAU,EAAE,CAAC;QACzG,KAAK,GAAG,KAAK,CAAC,MAAM,EAAe,CAAC;IACtC,CAAC;IACD,OAAO,KAAK,YAAY,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AAC1D,CAAC;AAED,gHAAgH;AAChH,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,GAAY,EAAE,EAAE,CACpC,GAAG,YAAY,SAAS,IAAI,GAAG,YAAY,UAAU,IAAI,GAAG,YAAY,cAAc,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanoma-ai/workflows",
3
- "version": "0.11.13",
3
+ "version": "0.11.15",
4
4
  "description": "Business processes as TypeScript functions, run durably on DBOS",
5
5
  "keywords": [
6
6
  "approvals",
package/src/db/index.ts CHANGED
@@ -1,10 +1,12 @@
1
1
  // `@sanoma-ai/workflows/db`, server-only: the runtime's tables and the database they are read
2
- // with, for the packages that share them (the connectors' stores, the app's tests). Never a
3
- // workflow's import: the shipped `oxlint.json` refuses it, as it does `/wakeup-service`.
2
+ // with, for the packages that share them (the connectors' stores, the app's tests), and the
3
+ // migrator a connector applies its own generated folder with, under the preparation's lock. Never
4
+ // a workflow's import: the shipped `oxlint.json` refuses it, as it does `/wakeup-service`.
4
5
 
5
- export { type Db, databaseOn, pgCode } from "../db.ts";
6
+ export { type Db, databaseOn, pgCode, underPreparationLock } from "../db.ts";
6
7
  export * from "./company.ts";
7
8
  export * from "./dbos.ts";
8
9
  export * from "./identity.ts";
9
10
  export * from "./kms.ts";
11
+ export * from "./migrate.ts";
10
12
  export * from "./wakeup.ts";
package/src/db/migrate.ts CHANGED
@@ -7,9 +7,10 @@ import wakeupJournal from "../../drizzle/wakeup/meta/_journal.json" with { type:
7
7
 
8
8
  // The generated migrations (`pnpm --filter @sanoma-ai/workflows generate`), one folder per
9
9
  // database the runtime makes tables in, each with its own journal table in the schema `drizzle`,
10
- // since the wakeup service's database may be a company's own. The Worker, which never migrates,
11
- // checks a database against the journal shipped with the package (`migrationsApplied`), with no
12
- // file read: the journal is imported.
10
+ // since the wakeup service's database may be a company's own. A connector's tables have folders
11
+ // of their own, shaped the same (`@sanoma-ai/connector-better-auth`). The Worker, which never
12
+ // migrates, checks a database against the journal shipped with the package
13
+ // (`migrationsApplied`), with no file read: the journal is imported.
13
14
 
14
15
  /** Drizzle's journal, `meta/_journal.json` of a migrations folder. */
15
16
  export interface MigrationsJournal {
@@ -18,26 +19,26 @@ export interface MigrationsJournal {
18
19
 
19
20
  /** A migrations folder with the journal table recording what of it a database has. */
20
21
  export interface Migrations {
21
- /** The folder's name under the package's `drizzle/`. */
22
- name: string;
22
+ /**
23
+ * The folder, beside the module declaring it (`new URL("../drizzle/<name>/", import.meta.url)`,
24
+ * from `src/` and from `dist/` alike), asked for only when migrating, never in the Worker.
25
+ */
26
+ folder(): URL;
23
27
  /** Its journal table in the schema `drizzle`. */
24
28
  table: string;
25
29
  journal: MigrationsJournal;
26
30
  }
27
31
 
28
- /** The folder of `of`, from `src/` and from `dist/` alike; read only when migrating, never in the Worker. */
29
- const folderOf = (of: Migrations): string => fileURLToPath(new URL(`../../drizzle/${of.name}/`, import.meta.url));
30
-
31
32
  /** The tables every company database gets (`db/company.ts`). */
32
33
  export const COMPANY_MIGRATIONS = {
33
- name: "company",
34
+ folder: () => new URL("../../drizzle/company/", import.meta.url),
34
35
  table: "__drizzle_migrations",
35
36
  journal: companyJournal,
36
37
  } satisfies Migrations;
37
38
 
38
39
  /** The wakeup service's tables (`db/wakeup.ts`). */
39
40
  export const WAKEUP_MIGRATIONS = {
40
- name: "wakeup",
41
+ folder: () => new URL("../../drizzle/wakeup/", import.meta.url),
41
42
  table: "__drizzle_migrations_wakeup",
42
43
  journal: wakeupJournal,
43
44
  } satisfies Migrations;
@@ -45,12 +46,12 @@ export const WAKEUP_MIGRATIONS = {
45
46
  /**
46
47
  * Applies to `db` the migrations of `of` its database has not had, in one transaction, recording
47
48
  * each in the journal table. Drizzle's migrator compares only the newest timestamp, so a migration
48
- * older than the newest applied is skipped: `scripts/check-journal.ts` keeps a branch from adding
49
- * one. Two processes migrating one database at once race (the migrator takes no lock): callers
49
+ * older than the newest applied is skipped: the repository's `scripts/check-journal.ts` keeps a
50
+ * branch from adding one. Two processes migrating one database at once race (the migrator takes no lock): callers
50
51
  * hold `underPreparationLock`.
51
52
  */
52
53
  export const applyMigrations = (db: Db, of: Migrations): Promise<void> =>
53
- migrate(db, { migrationsFolder: folderOf(of), migrationsTable: of.table });
54
+ migrate(db, { migrationsFolder: fileURLToPath(of.folder()), migrationsTable: of.table });
54
55
 
55
56
  /**
56
57
  * Whether the database `db` is on has had every migration of `of`: each journal entry's `when`
package/src/fill.ts CHANGED
@@ -10,9 +10,17 @@ setFaker(faker);
10
10
  /** Seeds the generator from a name, so one name always makes up the same values. */
11
11
  export const seedFrom = (name: string) => seed(createHash("sha256").update(name).digest().readUInt32BE(0));
12
12
 
13
- /** The schema's value with every field `given` does not set made up, parsed by the schema. */
13
+ /**
14
+ * The schema's value with every required field `given` does not set made up, parsed by the schema.
15
+ * Optional fields are left out, as a caller may leave them: made up, they could break a rule
16
+ * between fields (one of two ids, not both).
17
+ */
14
18
  export function fill(schema: z.ZodType, given: Record<string, unknown>): unknown {
15
- return schema.parse({ ...(fake(schema) as object), ...given });
19
+ const made = fake(schema) as Record<string, unknown>;
20
+ for (const [name, field] of Object.entries(shapeOf(schema))) {
21
+ if (field.safeParse(undefined).success) delete made[name];
22
+ }
23
+ return schema.parse({ ...made, ...given });
16
24
  }
17
25
 
18
26
  /** An object schema's fields by name; none for any other schema. */