@sanoma-ai/workflows 0.2.0 → 0.4.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.
- package/README.md +146 -85
- package/dist/approvals.d.ts +11 -6
- package/dist/approvals.js +38 -10
- package/dist/approvals.js.map +1 -1
- package/dist/call-workflow.d.ts +16 -0
- package/dist/call-workflow.js +35 -0
- package/dist/call-workflow.js.map +1 -0
- package/dist/call.d.ts +33 -4
- package/dist/call.js +107 -42
- package/dist/call.js.map +1 -1
- package/dist/cedar.d.ts +87 -0
- package/dist/cedar.js +365 -0
- package/dist/cedar.js.map +1 -0
- package/dist/client.d.ts +85 -7
- package/dist/client.js +289 -25
- package/dist/client.js.map +1 -1
- package/dist/collection.d.ts +107 -0
- package/dist/collection.js +306 -0
- package/dist/collection.js.map +1 -0
- package/dist/config.d.ts +42 -14
- package/dist/config.js +82 -18
- package/dist/config.js.map +1 -1
- package/dist/constructors.d.ts +2 -0
- package/dist/constructors.js +5 -0
- package/dist/constructors.js.map +1 -0
- package/dist/data.d.ts +2 -0
- package/dist/data.js +3 -0
- package/dist/data.js.map +1 -0
- package/dist/datafile.d.ts +28 -2
- package/dist/datafile.js +118 -19
- package/dist/datafile.js.map +1 -1
- package/dist/db.d.ts +5 -3
- package/dist/db.js +88 -21
- package/dist/db.js.map +1 -1
- package/dist/define.d.ts +14 -5
- package/dist/define.js +1 -5
- package/dist/define.js.map +1 -1
- package/dist/describe.d.ts +45 -5
- package/dist/describe.js +72 -7
- package/dist/describe.js.map +1 -1
- package/dist/direct.d.ts +9 -0
- package/dist/direct.js +11 -0
- package/dist/direct.js.map +1 -0
- package/dist/errors.d.ts +16 -1
- package/dist/errors.js +30 -1
- package/dist/errors.js.map +1 -1
- package/dist/expectations.d.ts +3 -3
- package/dist/expectations.js +16 -7
- package/dist/expectations.js.map +1 -1
- package/dist/fill.d.ts +4 -0
- package/dist/fill.js +13 -0
- package/dist/fill.js.map +1 -1
- package/dist/index.d.ts +8 -4
- package/dist/index.js +10 -4
- package/dist/index.js.map +1 -1
- package/dist/ledger.d.ts +12 -1
- package/dist/ledger.js +18 -11
- package/dist/ledger.js.map +1 -1
- package/dist/lint.d.ts +5 -4
- package/dist/lint.js +24 -7
- package/dist/lint.js.map +1 -1
- package/dist/op.d.ts +6 -0
- package/dist/op.js.map +1 -1
- package/dist/outline.d.ts +2 -0
- package/dist/outline.js +1 -1
- package/dist/outline.js.map +1 -1
- package/dist/paths.d.ts +4 -0
- package/dist/paths.js +17 -3
- package/dist/paths.js.map +1 -1
- package/dist/person.d.ts +61 -0
- package/dist/person.js +69 -0
- package/dist/person.js.map +1 -0
- package/dist/plugin.d.ts +28 -0
- package/dist/plugin.js +52 -1
- package/dist/plugin.js.map +1 -1
- package/dist/policy.d.ts +51 -55
- package/dist/policy.js +14 -36
- package/dist/policy.js.map +1 -1
- package/dist/resource.d.ts +21 -5
- package/dist/resource.js +12 -3
- package/dist/resource.js.map +1 -1
- package/dist/resources.d.ts +58 -6
- package/dist/resources.js +119 -26
- package/dist/resources.js.map +1 -1
- package/dist/run.d.ts +17 -1
- package/dist/run.js.map +1 -1
- package/dist/scenario.d.ts +16 -9
- package/dist/scenario.js +149 -44
- package/dist/scenario.js.map +1 -1
- package/dist/scenarios.d.ts +10 -6
- package/dist/scenarios.js +8 -4
- package/dist/scenarios.js.map +1 -1
- package/dist/schema.d.ts +32 -0
- package/dist/schema.js +225 -0
- package/dist/schema.js.map +1 -0
- package/dist/sdk.d.ts +34 -0
- package/dist/sdk.js +168 -0
- package/dist/sdk.js.map +1 -0
- package/dist/shared.d.ts +181 -5
- package/dist/shared.js +160 -7
- package/dist/shared.js.map +1 -1
- package/dist/sites.d.ts +52 -0
- package/dist/sites.js +174 -0
- package/dist/sites.js.map +1 -0
- package/dist/version.d.ts +3 -2
- package/dist/version.js +3 -2
- package/dist/version.js.map +1 -1
- package/dist/worker.d.ts +3 -2
- package/dist/worker.js +24 -4
- package/dist/worker.js.map +1 -1
- package/oxlint.json +7 -20
- package/package.json +8 -3
- package/src/approvals.ts +49 -13
- package/src/call-workflow.ts +44 -0
- package/src/call.ts +157 -45
- package/src/cedar.ts +493 -0
- package/src/client.ts +368 -37
- package/src/collection.ts +431 -0
- package/src/config.ts +131 -34
- package/src/constructors.ts +4 -0
- package/src/data.ts +10 -0
- package/src/datafile.ts +141 -21
- package/src/db.ts +90 -22
- package/src/define.ts +15 -10
- package/src/describe.ts +113 -10
- package/src/direct.ts +15 -0
- package/src/errors.ts +36 -1
- package/src/expectations.ts +17 -8
- package/src/fill.ts +15 -0
- package/src/index.ts +33 -2
- package/src/ledger.ts +35 -17
- package/src/lint.ts +29 -12
- package/src/op.ts +6 -0
- package/src/outline.ts +1 -1
- package/src/paths.ts +18 -3
- package/src/person.ts +75 -0
- package/src/plugin.ts +74 -5
- package/src/policy.ts +59 -63
- package/src/resource.ts +35 -8
- package/src/resources.ts +165 -24
- package/src/run.ts +18 -1
- package/src/scenario.ts +186 -57
- package/src/scenarios.ts +15 -8
- package/src/schema.ts +261 -0
- package/src/sdk.ts +211 -0
- package/src/shared.ts +271 -8
- package/src/sites.ts +220 -0
- package/src/version.ts +3 -2
- package/src/worker.ts +29 -6
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { type Db } from "./db.ts";
|
|
3
|
+
import { type Fake } from "./fake.ts";
|
|
4
|
+
import { type Connector, type Driver, type Op, type OpSpec } from "./op.ts";
|
|
5
|
+
import { DATA_VENDOR, type FIELD_TYPES, type ListQuery, type Saved } from "./shared.ts";
|
|
6
|
+
export type FieldType = (typeof FIELD_TYPES)[number];
|
|
7
|
+
/** A field of a collection: its type, the type marked optional, or one of a list of strings. */
|
|
8
|
+
export type Field = FieldType | {
|
|
9
|
+
type: FieldType;
|
|
10
|
+
optional?: true;
|
|
11
|
+
} | {
|
|
12
|
+
enum: readonly [string, ...string[]];
|
|
13
|
+
optional?: true;
|
|
14
|
+
};
|
|
15
|
+
type ValueOfType<T> = T extends "number" ? number : T extends "boolean" ? boolean : string;
|
|
16
|
+
type ValueOf<F> = F extends {
|
|
17
|
+
enum: readonly (infer E)[];
|
|
18
|
+
} ? E : F extends {
|
|
19
|
+
type: infer T;
|
|
20
|
+
} ? ValueOfType<T> : ValueOfType<F>;
|
|
21
|
+
type OptionalKeys<F> = {
|
|
22
|
+
[K in keyof F]: F[K] extends {
|
|
23
|
+
optional: true;
|
|
24
|
+
} ? K : never;
|
|
25
|
+
}[keyof F];
|
|
26
|
+
type Flat<T> = {
|
|
27
|
+
[K in keyof T]: T[K];
|
|
28
|
+
};
|
|
29
|
+
/** A record of a collection with these fields: text, a person and a date are strings, an enum one of its strings. */
|
|
30
|
+
export type RecordOf<F extends Record<string, Field>> = Flat<{
|
|
31
|
+
-readonly [K in Exclude<keyof F & string, OptionalKeys<F>>]: ValueOf<F[K]>;
|
|
32
|
+
} & {
|
|
33
|
+
-readonly [K in OptionalKeys<F> & string]?: ValueOf<F[K]>;
|
|
34
|
+
}>;
|
|
35
|
+
/** The fields that may be a collection's key: required text. */
|
|
36
|
+
export type RequiredTextKeys<F extends Record<string, Field>> = {
|
|
37
|
+
[K in keyof F & string]: F[K] extends "text" | {
|
|
38
|
+
type: "text";
|
|
39
|
+
optional?: undefined;
|
|
40
|
+
} ? K : never;
|
|
41
|
+
}[keyof F & string];
|
|
42
|
+
/**
|
|
43
|
+
* Where a collection keeps its brand: a registered symbol, so a copy of this package reads a
|
|
44
|
+
* collection another copy made, as `VENDOR` and `RESOURCE`.
|
|
45
|
+
*/
|
|
46
|
+
export declare const COLLECTION: unique symbol;
|
|
47
|
+
/** A collection, as `collection()` declares it, with its four operations. */
|
|
48
|
+
export interface Collection<N extends string = string, F extends Record<string, Field> = Record<string, Field>, K extends string = string> {
|
|
49
|
+
readonly [COLLECTION]: true;
|
|
50
|
+
readonly kind: "collection";
|
|
51
|
+
readonly name: N;
|
|
52
|
+
readonly key: K;
|
|
53
|
+
readonly fields: F;
|
|
54
|
+
readonly title?: string;
|
|
55
|
+
readonly get: Op<typeof DATA_VENDOR, N, "get", {
|
|
56
|
+
key: string;
|
|
57
|
+
}, Saved<RecordOf<F>> | null>;
|
|
58
|
+
readonly list: Op<typeof DATA_VENDOR, N, "list", ListQuery<RecordOf<F>>, Saved<RecordOf<F>>[]>;
|
|
59
|
+
readonly save: Op<typeof DATA_VENDOR, N, "save", {
|
|
60
|
+
record: RecordOf<F>;
|
|
61
|
+
}, Saved<RecordOf<F>>>;
|
|
62
|
+
readonly delete: Op<typeof DATA_VENDOR, N, "delete", {
|
|
63
|
+
key: string;
|
|
64
|
+
}, {
|
|
65
|
+
deleted: boolean;
|
|
66
|
+
}>;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Declares a collection of records, in `resources/data.ts`:
|
|
70
|
+
* `collection({ name: "outbound", key: "company", fields: { company: "text", stage: { enum: ["new", "won"] } } })`.
|
|
71
|
+
* Its operations are `data.<name>.get`, `.list`, `.save` and `.delete`, which a workflow names in
|
|
72
|
+
* `uses` and calls on `ctx.data.<name>`. The name is a lowercase letter then letters and digits;
|
|
73
|
+
* the key is a required text field, each record's own and unique.
|
|
74
|
+
*/
|
|
75
|
+
export declare function collection<const N extends string, const F extends Record<string, Field>, const K extends RequiredTextKeys<F>>(declaration: {
|
|
76
|
+
name: N;
|
|
77
|
+
key: K;
|
|
78
|
+
fields: F;
|
|
79
|
+
title?: string;
|
|
80
|
+
}): Collection<N, F, K>;
|
|
81
|
+
/** True for a collection `collection()` made, in this copy of the package or another: read by its brand. */
|
|
82
|
+
export declare const isCollection: (x: unknown) => x is Collection;
|
|
83
|
+
/** The schema a collection's records are saved under: its fields, and nothing else. */
|
|
84
|
+
export declare const recordSchemaOf: (c: Collection) => z.ZodType;
|
|
85
|
+
/** Where the record no longer fits the collection's fields, as `Saved.issues` says it; none when it fits. */
|
|
86
|
+
export declare function recordIssues(c: Collection, record: unknown): NonNullable<Saved["issues"]>;
|
|
87
|
+
type Stored = Omit<Saved, "issues">;
|
|
88
|
+
type DataOps = Record<string, Record<string, OpSpec>>;
|
|
89
|
+
/** The vendor `data` as a connector of the collections' operations, the very ones each `collection()` made. */
|
|
90
|
+
export declare function collectionsConnector(list: readonly Collection[]): Connector<typeof DATA_VENDOR, DataOps>;
|
|
91
|
+
/**
|
|
92
|
+
* The collections' driver: their records in `DATA_TABLE` of the database `store` is on, through
|
|
93
|
+
* the pool a run's calls share, or one connection in a transaction (a direct write, with its
|
|
94
|
+
* ledger record). Every value reaches Postgres as a parameter, field names included; the field
|
|
95
|
+
* names and operators are the ones the input's schema accepts.
|
|
96
|
+
*/
|
|
97
|
+
export declare function collectionsDriver(list: readonly Collection[], store: {
|
|
98
|
+
db(): Promise<Db>;
|
|
99
|
+
}): Driver;
|
|
100
|
+
/** The collections' records in memory, by collection and key: what a sandbox run's fake holds. */
|
|
101
|
+
export type CollectionsState = Record<string, Record<string, Stored>>;
|
|
102
|
+
/**
|
|
103
|
+
* An in-memory fake of the collections' driver, which starts empty: a scenario seeds it
|
|
104
|
+
* (`Given data.<name> "<key>" has`), and a test may through `update`.
|
|
105
|
+
*/
|
|
106
|
+
export declare function collectionsFake(list: readonly Collection[]): Fake<CollectionsState>;
|
|
107
|
+
export {};
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { DATA_TABLE } from "./db.js";
|
|
3
|
+
import { defineFake } from "./fake.js";
|
|
4
|
+
import { isObject } from "./resource.js";
|
|
5
|
+
import { defineConnector, defineDriver, } from "./op.js";
|
|
6
|
+
import { checkCollection, DATA_VENDOR, LIST_LIMIT } from "./shared.js";
|
|
7
|
+
/**
|
|
8
|
+
* Where a collection keeps its brand: a registered symbol, so a copy of this package reads a
|
|
9
|
+
* collection another copy made, as `VENDOR` and `RESOURCE`.
|
|
10
|
+
*/
|
|
11
|
+
export const COLLECTION = Symbol.for("sanoma.collection");
|
|
12
|
+
/**
|
|
13
|
+
* Declares a collection of records, in `resources/data.ts`:
|
|
14
|
+
* `collection({ name: "outbound", key: "company", fields: { company: "text", stage: { enum: ["new", "won"] } } })`.
|
|
15
|
+
* Its operations are `data.<name>.get`, `.list`, `.save` and `.delete`, which a workflow names in
|
|
16
|
+
* `uses` and calls on `ctx.data.<name>`. The name is a lowercase letter then letters and digits;
|
|
17
|
+
* the key is a required text field, each record's own and unique.
|
|
18
|
+
*/
|
|
19
|
+
export function collection(declaration) {
|
|
20
|
+
checkCollection(declaration);
|
|
21
|
+
const { name, key, fields, title } = declaration;
|
|
22
|
+
const record = z.strictObject(Object.fromEntries(Object.entries(fields).map(([field, kind]) => {
|
|
23
|
+
const value = field === key ? z.string().min(1) : valueSchema(kind);
|
|
24
|
+
return [field, isObject(kind) && kind.optional ? value.optional() : value];
|
|
25
|
+
})));
|
|
26
|
+
const ops = defineConnector(DATA_VENDOR, { [name]: specsOf(name, key, fields, record) })[name];
|
|
27
|
+
return Object.freeze({
|
|
28
|
+
[COLLECTION]: true,
|
|
29
|
+
kind: "collection",
|
|
30
|
+
name,
|
|
31
|
+
key,
|
|
32
|
+
fields,
|
|
33
|
+
...(title !== undefined && { title }),
|
|
34
|
+
...ops,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* A date or a date and time with its offset, as ISO 8601 writes them, marked `format: "date"` in
|
|
39
|
+
* its JSON Schema (beside the union's own), which a form reads to draw a date's input.
|
|
40
|
+
*/
|
|
41
|
+
const DATE = z.union([z.iso.date(), z.iso.datetime({ offset: true })]).meta({ format: "date" });
|
|
42
|
+
/**
|
|
43
|
+
* A person's id: text that is not empty, marked `format: "person"` in its JSON Schema, which a form
|
|
44
|
+
* reads to draw a person's input.
|
|
45
|
+
*/
|
|
46
|
+
const PERSON = z.string().min(1).meta({ format: "person" });
|
|
47
|
+
/** The schema of a field's value, required. */
|
|
48
|
+
function valueSchema(kind) {
|
|
49
|
+
if (typeof kind === "object" && "enum" in kind)
|
|
50
|
+
return z.enum(kind.enum);
|
|
51
|
+
const type = typeof kind === "string" ? kind : kind.type;
|
|
52
|
+
return { text: z.string(), person: PERSON, date: DATE, number: z.number(), boolean: z.boolean() }[type];
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* What `get`, `list` and `save` answer: the record as it is stored, which an older declaration
|
|
56
|
+
* may have accepted, so it is not checked here; `issues` say where the fields refuse it.
|
|
57
|
+
*/
|
|
58
|
+
const SAVED = z.object({
|
|
59
|
+
key: z.string(),
|
|
60
|
+
record: z.record(z.string(), z.unknown()),
|
|
61
|
+
updatedAt: z.string(),
|
|
62
|
+
updatedBy: z.string(),
|
|
63
|
+
issues: z.array(z.object({ path: z.array(z.union([z.string(), z.number()])), message: z.string() })).optional(),
|
|
64
|
+
});
|
|
65
|
+
/** A collection's four operations, for `defineConnector`. */
|
|
66
|
+
function specsOf(name, key, fields, record) {
|
|
67
|
+
const at = (k) => `${DATA_VENDOR}:${name}/${k}`;
|
|
68
|
+
const byKey = z.object({ key: z.string().min(1) });
|
|
69
|
+
const names = Object.keys(fields);
|
|
70
|
+
const where = z.strictObject(Object.fromEntries(Object.entries(fields).map(([field, kind]) => {
|
|
71
|
+
const value = valueSchema(kind);
|
|
72
|
+
const range = z.strictObject({ gt: value, gte: value, lt: value, lte: value }).partial();
|
|
73
|
+
return [field, z.union([value, range]).optional()];
|
|
74
|
+
})));
|
|
75
|
+
return {
|
|
76
|
+
get: {
|
|
77
|
+
effect: "read",
|
|
78
|
+
idempotent: true,
|
|
79
|
+
description: `Get a record of ${name} by its ${key}`,
|
|
80
|
+
input: byKey,
|
|
81
|
+
output: SAVED.nullable(),
|
|
82
|
+
target: ({ key: k }) => at(k),
|
|
83
|
+
},
|
|
84
|
+
list: {
|
|
85
|
+
effect: "read",
|
|
86
|
+
idempotent: true,
|
|
87
|
+
description: `List records of ${name}: fields equal to a value or within a range, sorted, at most \`limit\``,
|
|
88
|
+
input: z.object({
|
|
89
|
+
where: where.optional(),
|
|
90
|
+
order: z.enum([...names, ...names.map((n) => `-${n}`)]).optional(),
|
|
91
|
+
limit: z.number().int().min(1).max(LIST_LIMIT.max).default(LIST_LIMIT.default),
|
|
92
|
+
}),
|
|
93
|
+
output: z.array(SAVED),
|
|
94
|
+
target: () => `${DATA_VENDOR}:${name}`,
|
|
95
|
+
},
|
|
96
|
+
save: {
|
|
97
|
+
effect: "write",
|
|
98
|
+
idempotent: true,
|
|
99
|
+
description: `Save a record of ${name}: added, or replacing the one with its ${key}`,
|
|
100
|
+
input: z.object({ record }),
|
|
101
|
+
output: SAVED,
|
|
102
|
+
target: ({ record: r }) => at(r[key]),
|
|
103
|
+
},
|
|
104
|
+
delete: {
|
|
105
|
+
effect: "write",
|
|
106
|
+
idempotent: true,
|
|
107
|
+
description: `Delete the record of ${name} with this ${key}`,
|
|
108
|
+
input: byKey,
|
|
109
|
+
output: z.object({ deleted: z.boolean() }),
|
|
110
|
+
target: ({ key: k }) => at(k),
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
/** True for a collection `collection()` made, in this copy of the package or another: read by its brand. */
|
|
115
|
+
export const isCollection = (x) => isObject(x) && x[COLLECTION] === true && x.kind === "collection";
|
|
116
|
+
/** The schema a collection's records are saved under: its fields, and nothing else. */
|
|
117
|
+
export const recordSchemaOf = (c) => c.save.input.shape.record;
|
|
118
|
+
/** Where the record no longer fits the collection's fields, as `Saved.issues` says it; none when it fits. */
|
|
119
|
+
export function recordIssues(c, record) {
|
|
120
|
+
const parsed = recordSchemaOf(c).safeParse(record);
|
|
121
|
+
if (parsed.success)
|
|
122
|
+
return [];
|
|
123
|
+
return parsed.error.issues.map(({ path, message }) => ({
|
|
124
|
+
path: path.filter((p) => typeof p !== "symbol"),
|
|
125
|
+
message,
|
|
126
|
+
}));
|
|
127
|
+
}
|
|
128
|
+
/** The record as `get`, `list` and `save` answer it: with its issues, when it has any. */
|
|
129
|
+
function answer(c, stored) {
|
|
130
|
+
const issues = recordIssues(c, stored.record);
|
|
131
|
+
return issues.length ? { ...stored, issues } : stored;
|
|
132
|
+
}
|
|
133
|
+
/** Who a save is by: the person a direct call is made as, else the run. */
|
|
134
|
+
const updatedBy = (call) => call.by ?? `run:${call.runId}`;
|
|
135
|
+
/** The vendor `data` as a connector of the collections' operations, the very ones each `collection()` made. */
|
|
136
|
+
export function collectionsConnector(list) {
|
|
137
|
+
const ops = list.map((c) => [c.name, { get: c.get, list: c.list, save: c.save, delete: c.delete }]);
|
|
138
|
+
return { ...defineConnector(DATA_VENDOR, {}), ...Object.fromEntries(ops) };
|
|
139
|
+
}
|
|
140
|
+
const COLUMNS = "key, record, updated_at, updated_by";
|
|
141
|
+
const RANGE = { gt: ">", gte: ">=", lt: "<", lte: "<=" };
|
|
142
|
+
/**
|
|
143
|
+
* The collections' driver: their records in `DATA_TABLE` of the database `store` is on, through
|
|
144
|
+
* the pool a run's calls share, or one connection in a transaction (a direct write, with its
|
|
145
|
+
* ledger record). Every value reaches Postgres as a parameter, field names included; the field
|
|
146
|
+
* names and operators are the ones the input's schema accepts.
|
|
147
|
+
*/
|
|
148
|
+
export function collectionsDriver(list, store) {
|
|
149
|
+
const query = async (sql, params) => (await store.db()).query(sql, params);
|
|
150
|
+
const impl = list.map((c) => {
|
|
151
|
+
const saved = (row) => answer(c, {
|
|
152
|
+
key: row.key,
|
|
153
|
+
record: row.record,
|
|
154
|
+
updatedAt: row.updated_at.toISOString(),
|
|
155
|
+
updatedBy: row.updated_by,
|
|
156
|
+
});
|
|
157
|
+
const ops = {
|
|
158
|
+
get: async ({ key }) => {
|
|
159
|
+
const sql = `SELECT ${COLUMNS} FROM ${DATA_TABLE} WHERE collection = $1 AND key = $2`;
|
|
160
|
+
const [row] = (await query(sql, [c.name, key])).rows;
|
|
161
|
+
return row ? saved(row) : null;
|
|
162
|
+
},
|
|
163
|
+
list: async (listing) => (await query(...listSql(c, listing))).rows.map(saved),
|
|
164
|
+
save: async ({ record }, call) => {
|
|
165
|
+
const sql = `INSERT INTO ${DATA_TABLE} (collection, key, record, updated_by) VALUES ($1, $2, $3, $4) ` +
|
|
166
|
+
"ON CONFLICT (collection, key) DO UPDATE SET record = EXCLUDED.record, updated_at = now(), " +
|
|
167
|
+
`updated_by = EXCLUDED.updated_by RETURNING ${COLUMNS}`;
|
|
168
|
+
const params = [c.name, record[c.key], JSON.stringify(record), updatedBy(call)];
|
|
169
|
+
return saved((await query(sql, params)).rows[0]);
|
|
170
|
+
},
|
|
171
|
+
delete: async ({ key }) => {
|
|
172
|
+
const sql = `DELETE FROM ${DATA_TABLE} WHERE collection = $1 AND key = $2`;
|
|
173
|
+
return { deleted: ((await query(sql, [c.name, key])).rowCount ?? 0) > 0 };
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
return [c.name, ops];
|
|
177
|
+
});
|
|
178
|
+
return defineDriver(collectionsConnector(list), Object.fromEntries(impl));
|
|
179
|
+
}
|
|
180
|
+
/** Each field's `JsonType`, by name: what `list` compares its values as. */
|
|
181
|
+
const jsonTypesOf = (c) => Object.fromEntries(Object.entries(c.fields).map(([name, kind]) => {
|
|
182
|
+
const type = typeof kind === "string" ? kind : "type" in kind ? kind.type : "text";
|
|
183
|
+
return [name, type === "number" || type === "boolean" ? type : "string"];
|
|
184
|
+
}));
|
|
185
|
+
const SQL_TYPE = { string: "text", number: "numeric", boolean: "boolean" };
|
|
186
|
+
/**
|
|
187
|
+
* The `list` query on Postgres, and its parameters. A field's value is compared as its declared
|
|
188
|
+
* type, text byte by byte (`COLLATE "C"`, whatever the database's collation, as the fake
|
|
189
|
+
* compares it); a missing value, or one of another type, is SQL's null: it matches no filter and
|
|
190
|
+
* sorts last.
|
|
191
|
+
*/
|
|
192
|
+
function listSql(c, { where = {}, order, limit }) {
|
|
193
|
+
const types = jsonTypesOf(c);
|
|
194
|
+
const params = [c.name];
|
|
195
|
+
const param = (value) => `$${params.push(value)}`;
|
|
196
|
+
const field = (name) => {
|
|
197
|
+
const type = types[name];
|
|
198
|
+
const json = `record -> ${param(name)}::text`;
|
|
199
|
+
const typed = `CASE WHEN jsonb_typeof(${json}) = '${type}' THEN (${json} #>> '{}')::${SQL_TYPE[type]} END`;
|
|
200
|
+
return type === "string" ? `(${typed}) COLLATE "C"` : typed;
|
|
201
|
+
};
|
|
202
|
+
const value = (name, v) => `${param(v)}::${SQL_TYPE[types[name]]}`;
|
|
203
|
+
const conditions = ["collection = $1"];
|
|
204
|
+
for (const [name, condition] of Object.entries(where)) {
|
|
205
|
+
if (condition === undefined)
|
|
206
|
+
continue;
|
|
207
|
+
if (!isObject(condition))
|
|
208
|
+
conditions.push(`${field(name)} = ${value(name, condition)}`);
|
|
209
|
+
else {
|
|
210
|
+
for (const [op, v] of Object.entries(condition)) {
|
|
211
|
+
const sign = RANGE[op];
|
|
212
|
+
if (v !== undefined)
|
|
213
|
+
conditions.push(`${field(name)} ${sign} ${value(name, v)}`);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
const byKey = `key COLLATE "C"`;
|
|
218
|
+
const by = order === undefined
|
|
219
|
+
? byKey
|
|
220
|
+
: `${field(order.replace(/^-/, ""))} ${order.startsWith("-") ? "DESC" : "ASC"} NULLS LAST, ${byKey}`;
|
|
221
|
+
const sql = `SELECT ${COLUMNS} FROM ${DATA_TABLE} WHERE ${conditions.join(" AND ")} ORDER BY ${by} LIMIT ${param(limit)}`;
|
|
222
|
+
return [sql, params];
|
|
223
|
+
}
|
|
224
|
+
/** Orders two values of one type as Postgres does under `COLLATE "C"`: strings by their UTF-8 bytes. */
|
|
225
|
+
const compare = (a, b) => typeof a === "string" && typeof b === "string"
|
|
226
|
+
? Buffer.compare(Buffer.from(a), Buffer.from(b))
|
|
227
|
+
: a < b
|
|
228
|
+
? -1
|
|
229
|
+
: a > b
|
|
230
|
+
? 1
|
|
231
|
+
: 0;
|
|
232
|
+
/** The record's value of a field when it is of the field's type; none otherwise, as for a missing one. */
|
|
233
|
+
const valueIn = (record, name, type) => typeof record[name] === type ? record[name] : undefined;
|
|
234
|
+
/** Whether the record meets each condition of `where`, as the driver's SQL decides it. */
|
|
235
|
+
function matches(record, where, types) {
|
|
236
|
+
return Object.entries(where).every(([name, condition]) => {
|
|
237
|
+
if (condition === undefined)
|
|
238
|
+
return true;
|
|
239
|
+
const value = valueIn(record, name, types[name]);
|
|
240
|
+
if (value === undefined)
|
|
241
|
+
return false;
|
|
242
|
+
if (!isObject(condition))
|
|
243
|
+
return compare(value, condition) === 0;
|
|
244
|
+
const { gt, gte, lt, lte } = condition;
|
|
245
|
+
return ((gt === undefined || compare(value, gt) > 0) &&
|
|
246
|
+
(gte === undefined || compare(value, gte) >= 0) &&
|
|
247
|
+
(lt === undefined || compare(value, lt) < 0) &&
|
|
248
|
+
(lte === undefined || compare(value, lte) <= 0));
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
const byKey = (a, b) => compare(a.key, b.key);
|
|
252
|
+
/** Sorts as the driver's SQL does: by the field (missing last), then by key; by key alone without one. */
|
|
253
|
+
function byOrder(order, types) {
|
|
254
|
+
if (order === undefined)
|
|
255
|
+
return byKey;
|
|
256
|
+
const name = order.replace(/^-/, "");
|
|
257
|
+
const sign = order.startsWith("-") ? -1 : 1;
|
|
258
|
+
return (a, b) => {
|
|
259
|
+
const x = valueIn(a.record, name, types[name]);
|
|
260
|
+
const y = valueIn(b.record, name, types[name]);
|
|
261
|
+
if ((x === undefined) !== (y === undefined))
|
|
262
|
+
return x === undefined ? 1 : -1;
|
|
263
|
+
return (x === undefined ? 0 : sign * compare(x, y)) || byKey(a, b);
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* An in-memory fake of the collections' driver, which starts empty: a scenario seeds it
|
|
268
|
+
* (`Given data.<name> "<key>" has`), and a test may through `update`.
|
|
269
|
+
*/
|
|
270
|
+
export function collectionsFake(list) {
|
|
271
|
+
return defineFake(collectionsConnector(list), {
|
|
272
|
+
// Null-prototype records, so any key is a record's own, `__proto__` too, as it is in Postgres.
|
|
273
|
+
initial: () => Object.fromEntries(list.map((c) => [c.name, Object.create(null)])),
|
|
274
|
+
ops: (state) => Object.fromEntries(list.map((c) => {
|
|
275
|
+
const records = () => state[c.name];
|
|
276
|
+
const types = jsonTypesOf(c);
|
|
277
|
+
const saved = (stored) => answer(c, structuredClone(stored));
|
|
278
|
+
const ops = {
|
|
279
|
+
get: async ({ key }) => (Object.hasOwn(records(), key) ? saved(records()[key]) : null),
|
|
280
|
+
list: async ({ where = {}, order, limit }) => Object.values(records())
|
|
281
|
+
.filter((s) => matches(s.record, where, types))
|
|
282
|
+
.toSorted(byOrder(order, types))
|
|
283
|
+
.slice(0, limit)
|
|
284
|
+
.map(saved),
|
|
285
|
+
save: async ({ record }, call) => {
|
|
286
|
+
const key = record[c.key];
|
|
287
|
+
const stored = {
|
|
288
|
+
key,
|
|
289
|
+
record: structuredClone(record),
|
|
290
|
+
updatedAt: new Date().toISOString(),
|
|
291
|
+
updatedBy: updatedBy(call),
|
|
292
|
+
};
|
|
293
|
+
records()[key] = stored;
|
|
294
|
+
return saved(stored);
|
|
295
|
+
},
|
|
296
|
+
delete: async ({ key }) => {
|
|
297
|
+
const had = Object.hasOwn(records(), key);
|
|
298
|
+
delete records()[key];
|
|
299
|
+
return { deleted: had };
|
|
300
|
+
},
|
|
301
|
+
};
|
|
302
|
+
return [c.name, ops];
|
|
303
|
+
})),
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
//# sourceMappingURL=collection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collection.js","sourceRoot":"","sources":["../src/collection.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { type Collection } from "./collection.ts";
|
|
2
|
+
import { type LazyPool } from "./db.ts";
|
|
1
3
|
import { type WorkflowDefinition } from "./define.ts";
|
|
2
4
|
import type { Fake } from "./fake.ts";
|
|
3
5
|
import type { LedgerStore } from "./ledger.ts";
|
|
@@ -6,11 +8,11 @@ import type { Policy } from "./policy.ts";
|
|
|
6
8
|
import { type Resource } from "./resource.ts";
|
|
7
9
|
import type { Steps } from "./steps.ts";
|
|
8
10
|
/**
|
|
9
|
-
* What a worker runs, on which connectors
|
|
11
|
+
* What a worker runs, on which connectors: the argument to `startWorker`.
|
|
10
12
|
* A project usually keeps it in `sanoma.config.ts` and passes it in; nothing loads that file
|
|
11
13
|
* automatically. The rest is convention: each connector carries its driver and its fake
|
|
12
|
-
* (`withSetup`), the app's name is its `package.json`'s, and the scenarios
|
|
13
|
-
* `scenarios/` and `
|
|
14
|
+
* (`withSetup`), the app's name is its `package.json`'s, and the scenarios, data files and
|
|
15
|
+
* policies are `scenarios/`, `resources/` and `policies/` in `root`.
|
|
14
16
|
*/
|
|
15
17
|
export interface SanomaConfig {
|
|
16
18
|
workflows: WorkflowDefinition<any, any>[];
|
|
@@ -22,8 +24,6 @@ export interface SanomaConfig {
|
|
|
22
24
|
* package attaches the maker of.
|
|
23
25
|
*/
|
|
24
26
|
connectors: Connector<any, any>[];
|
|
25
|
-
/** Checked before every operation call. Required: `allowAll` says that every call is allowed. */
|
|
26
|
-
policy: Policy;
|
|
27
27
|
/**
|
|
28
28
|
* Where the audit record goes. Default: `postgresLedger` on the config's database, which the
|
|
29
29
|
* worker, the app and other processes share; the worker and the client each make their own
|
|
@@ -50,8 +50,15 @@ export interface SanomaConfig {
|
|
|
50
50
|
appName?: never;
|
|
51
51
|
/** @deprecated Gone: the scenarios are `<root>/scenarios/`. Leave it out. */
|
|
52
52
|
scenarios?: never;
|
|
53
|
+
/** @deprecated Gone: the policy is `<root>/policies/**\/*.cedar`. Leave it out. */
|
|
54
|
+
policy?: never;
|
|
53
55
|
/** The company's own steps for its scenarios (`defineSteps`), besides those its connectors ship. */
|
|
54
56
|
steps?: Steps[];
|
|
57
|
+
/**
|
|
58
|
+
* The company's collections (`collection()`): their operations are `data.<name>.<op>`, their
|
|
59
|
+
* records in the config's database, and in memory for a sandbox run.
|
|
60
|
+
*/
|
|
61
|
+
collections?: readonly Collection[];
|
|
55
62
|
}
|
|
56
63
|
/** A config, checked, with everything a worker, client or app derives from it. */
|
|
57
64
|
export interface ResolvedConfig {
|
|
@@ -65,7 +72,10 @@ export interface ResolvedConfig {
|
|
|
65
72
|
version: string;
|
|
66
73
|
/** The DBOS queue runs are started on: `sanoma:<appName>`. */
|
|
67
74
|
queueName: string;
|
|
68
|
-
/**
|
|
75
|
+
/**
|
|
76
|
+
* The operations the connectors declare, by id, the built-in `sanoma.source.resolve` when one
|
|
77
|
+
* declares a host type, and the collections' (`data.<name>.<op>`).
|
|
78
|
+
*/
|
|
69
79
|
ops: Map<string, Op>;
|
|
70
80
|
/** The drivers' functions, by operation id, each guarded by its driver's `env` (`indexDrivers`). */
|
|
71
81
|
drivers: Map<string, DriverFn>;
|
|
@@ -82,12 +92,27 @@ export interface ResolvedConfig {
|
|
|
82
92
|
types: ReadonlyMap<string, Resource>;
|
|
83
93
|
/** The steps scenarios can use besides the generic ones: each connector's (`withSetup`), once each, then the config's own. */
|
|
84
94
|
steps: readonly Steps[];
|
|
95
|
+
/** The config's collections, by name: their operations are in `ops` and `drivers`, their fake in `fakes`, under `DATA_VENDOR`. */
|
|
96
|
+
collections: ReadonlyMap<string, Collection>;
|
|
85
97
|
/**
|
|
86
|
-
*
|
|
87
|
-
*
|
|
98
|
+
* The pool the collections' driver keeps their records through, when there are any: opened on
|
|
99
|
+
* its first call, and closed by whoever calls the driver (the worker, and the client, which
|
|
100
|
+
* calls it directly, when each stops).
|
|
101
|
+
*/
|
|
102
|
+
dataStore?: LazyPool;
|
|
103
|
+
/**
|
|
104
|
+
* By name; each checked against `ops` and `drivers`. The config's, the built-ins `drift`
|
|
105
|
+
* (`DRIFT_WORKFLOW`) and `apply` (`APPLY_WORKFLOW`) when its connectors declare resource types,
|
|
106
|
+
* and `call` (`CALL_WORKFLOW`) when an operation may be called directly (`isDirect`).
|
|
88
107
|
*/
|
|
89
108
|
workflows: Map<string, WorkflowDefinition<any, any>>;
|
|
109
|
+
/**
|
|
110
|
+
* Checked before every operation call and run start: the root's `policies/**\/*.cedar`
|
|
111
|
+
* (`policyAt`), `allowAll` without any, and one that refuses everything while they have problems.
|
|
112
|
+
*/
|
|
90
113
|
policy: Policy;
|
|
114
|
+
/** What is wrong in the policies, one printable line each (`file:line:col: <policy id>: <message>`). */
|
|
115
|
+
policyProblems: string[];
|
|
91
116
|
/** The config's `ledger`, when it gives one; the worker and the client otherwise make `postgresLedger` on `databaseUrl` (`ownedLedger`). */
|
|
92
117
|
ledger?: LedgerStore;
|
|
93
118
|
/**
|
|
@@ -110,14 +135,17 @@ export declare function resolveDatabaseUrl(config: {
|
|
|
110
135
|
export declare function rootOf(config: Pick<SanomaConfig, "root" | "file">): string | undefined;
|
|
111
136
|
/**
|
|
112
137
|
* Checks a config and derives what the runtime needs from it: the drivers and fakes from the
|
|
113
|
-
* connectors' setups (`withSetup`),
|
|
114
|
-
*
|
|
115
|
-
* `
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
* `
|
|
138
|
+
* connectors' setups (`withSetup`), the collections' operations, driver and fake, and from
|
|
139
|
+
* `root`, the app's name (`package.json`), the scenarios (`scenarios/`) and the policy
|
|
140
|
+
* (`policies/`, `policyAt`). Throws what
|
|
141
|
+
* `startWorker` would refuse, with the same message, so `describeConfig`, `SanomaClient.connect`
|
|
142
|
+
* and the app fail the same way the worker does. It opens nothing and reads no file outside
|
|
143
|
+
* `root`. Each entry point resolves once: the worker and the client when they start, the app at
|
|
144
|
+
* `startApp`, the `sanoma` bin when it loads the config.
|
|
119
145
|
*/
|
|
120
146
|
export declare function resolveConfig(config: SanomaConfig): ResolvedConfig;
|
|
147
|
+
/** The config's connectors and the runtime's people types' (`peopleConnector`): what its data files are read against. */
|
|
148
|
+
export declare const connectorsOf: (config: Pick<SanomaConfig, "connectors">) => Connector<any, any>[];
|
|
121
149
|
/**
|
|
122
150
|
* The drivers' functions by operation id, refusing one no connector declares. A driver that
|
|
123
151
|
* declares an `env` has each function guarded by it (`guarded`); a fake declares none, so a
|