@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
package/dist/scenarios.d.ts
CHANGED
|
@@ -8,14 +8,18 @@ export interface RunScenarioOptions {
|
|
|
8
8
|
client: SanomaClient;
|
|
9
9
|
/** What the scenario was loaded from (`loadScenarios`), whose feature files its run is checked against: the resolved config. */
|
|
10
10
|
scope: Scope;
|
|
11
|
-
/**
|
|
12
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Who starts the run, by id (`"ada"` or `{ id: "ada" }`), unless the scenario says who is acting.
|
|
13
|
+
* Defaults to `scenarios`, one of the runtime's own agents.
|
|
14
|
+
*/
|
|
15
|
+
startedBy?: Principal | string;
|
|
13
16
|
/** How long the run may take, passed to `drive`. */
|
|
14
17
|
timeoutMs?: number;
|
|
15
18
|
}
|
|
16
19
|
/**
|
|
17
|
-
* Runs a scenario as a sandbox run: starts its workflow with its input,
|
|
18
|
-
* as it says, and checks the run's ledger against it (`check`:
|
|
20
|
+
* Runs a scenario as a sandbox run: starts its workflow with its input, as whoever it says is
|
|
21
|
+
* acting, decides its approvals as it says, and checks the run's ledger against it (`check`:
|
|
22
|
+
* Cucumber runs its `Then` steps).
|
|
19
23
|
*/
|
|
20
24
|
export declare function runScenario(scenario: Scenario, { client, scope, startedBy, timeoutMs }: RunScenarioOptions): Promise<{
|
|
21
25
|
runId: string;
|
|
@@ -33,8 +37,8 @@ export interface ScenarioFailure {
|
|
|
33
37
|
export interface RunScenariosOptions {
|
|
34
38
|
/** The Postgres the worker and the client run on, instead of the config's: a database of its own. */
|
|
35
39
|
databaseUrl: string;
|
|
36
|
-
/** Who starts the runs
|
|
37
|
-
startedBy?: Principal;
|
|
40
|
+
/** Who starts the runs whose scenario does not say who is acting (`runScenario`'s). */
|
|
41
|
+
startedBy?: Principal | string;
|
|
38
42
|
/** How long each run may take (`drive`'s; 15 seconds by default). */
|
|
39
43
|
timeoutMs?: number;
|
|
40
44
|
/** Receives a line per scenario as it ends. */
|
package/dist/scenarios.js
CHANGED
|
@@ -5,11 +5,15 @@ import { check, drive, loadScenarios } from "./scenario.js";
|
|
|
5
5
|
import { errorMessage } from "./shared.js";
|
|
6
6
|
import { startWorker } from "./worker.js";
|
|
7
7
|
/**
|
|
8
|
-
* Runs a scenario as a sandbox run: starts its workflow with its input,
|
|
9
|
-
* as it says, and checks the run's ledger against it (`check`:
|
|
8
|
+
* Runs a scenario as a sandbox run: starts its workflow with its input, as whoever it says is
|
|
9
|
+
* acting, decides its approvals as it says, and checks the run's ledger against it (`check`:
|
|
10
|
+
* Cucumber runs its `Then` steps).
|
|
10
11
|
*/
|
|
11
|
-
export async function runScenario(scenario, { client, scope, startedBy =
|
|
12
|
-
const runId = await client.start(scenario.workflow, scenario.input, {
|
|
12
|
+
export async function runScenario(scenario, { client, scope, startedBy = "scenarios", timeoutMs }) {
|
|
13
|
+
const runId = await client.start(scenario.workflow, scenario.input, {
|
|
14
|
+
startedBy: scenario.startedBy ?? startedBy,
|
|
15
|
+
sandbox: scenario.name,
|
|
16
|
+
});
|
|
13
17
|
const run = await drive(client, runId, scenario, { timeoutMs });
|
|
14
18
|
const ledger = await client.ledger(runId);
|
|
15
19
|
return { runId, run, ledger, checks: await check(scope, scenario, ledger) };
|
package/dist/scenarios.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scenarios.js","sourceRoot":"","sources":["../src/scenarios.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,YAAY,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAqB,MAAM,aAAa,CAAC;AAE/D,OAAO,EAAqB,YAAY,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAc,KAAK,EAAE,KAAK,EAAE,aAAa,EAA6B,MAAM,eAAe,CAAC;AACnG,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"scenarios.js","sourceRoot":"","sources":["../src/scenarios.ts"],"names":[],"mappings":"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"}
|
package/dist/schema.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { DetailedError, RecordType, SchemaJson, Type } from "@cedar-policy/cedar-wasm/nodejs";
|
|
2
|
+
import type { ResolvedConfig } from "./config.ts";
|
|
3
|
+
import { type PeopleResource } from "./shared.ts";
|
|
4
|
+
/** `@cedar-policy/cedar-wasm`'s Node build, loaded (synchronously, once) on first use, so a process that never decides with Cedar never loads it. */
|
|
5
|
+
export declare const cedarWasm: () => typeof import("@cedar-policy/cedar-wasm/nodejs");
|
|
6
|
+
/** The schema as Cedar's JSON format has it. */
|
|
7
|
+
export type CedarSchemaJson = SchemaJson<string>;
|
|
8
|
+
/** Where the schema's text is written, under a company's root. */
|
|
9
|
+
export declare const SCHEMA_FILE: string;
|
|
10
|
+
/** The schema's namespace: policies name `Sanoma::Group::"finance"`, `Sanoma::Action::"effect:money"`. */
|
|
11
|
+
export declare const NAMESPACE = "Sanoma";
|
|
12
|
+
/** The action group every workflow start (`workflow:<name>`) is in. */
|
|
13
|
+
export declare const START = "start";
|
|
14
|
+
/**
|
|
15
|
+
* The Cedar schema for a resolved config and its people (`buildSchema`), made once for each pair:
|
|
16
|
+
* validating, deciding and writing it share one.
|
|
17
|
+
*/
|
|
18
|
+
export declare function schemaOf(resolved: Pick<ResolvedConfig, "ops" | "workflows" | "collections">, people: readonly PeopleResource[]): CedarSchemaJson;
|
|
19
|
+
/** The schema as Cedar's text, through the package's own `schemaToText`: what `.sanoma/schema.cedarschema` holds. */
|
|
20
|
+
export declare function schemaText(schema: CedarSchemaJson): string;
|
|
21
|
+
/** Cedar's message, with its help when it has one. */
|
|
22
|
+
export declare const messageOf: (e: DetailedError) => string;
|
|
23
|
+
/** An action's context type in the schema: a record, when the action is there. */
|
|
24
|
+
export declare const contextTypeOf: (schema: CedarSchemaJson, action: string) => (RecordType<string> & {
|
|
25
|
+
type: "Record";
|
|
26
|
+
}) | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* A value as Cedar takes it for a type `schemaOf` wrote (`cedarType`'s other side): a record's
|
|
29
|
+
* fields it declares only, a set's elements, a number where it is a `String` as text. An unknown
|
|
30
|
+
* (`{ __extn: unknown }`) passes as it is; what does not fit is left out (undefined), as `null` is.
|
|
31
|
+
*/
|
|
32
|
+
export declare function cedarValue(value: unknown, type: Type<string>): unknown;
|
package/dist/schema.js
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { recordSchemaOf } from "./collection.js";
|
|
4
|
+
import { jsonSchemaOf } from "./define.js";
|
|
5
|
+
import { isObject } from "./resource.js";
|
|
6
|
+
import { DATA_VENDOR, EFFECTS, groupNamesOf, WORKFLOW_ACTION } from "./shared.js";
|
|
7
|
+
// The Cedar schema a company's policies are validated and decided against: made from the
|
|
8
|
+
// resolved config and the people, in memory for the evaluator, and written as text to
|
|
9
|
+
// `.sanoma/schema.cedarschema` for the policies' author.
|
|
10
|
+
const require = createRequire(import.meta.url);
|
|
11
|
+
let wasm;
|
|
12
|
+
/** `@cedar-policy/cedar-wasm`'s Node build, loaded (synchronously, once) on first use, so a process that never decides with Cedar never loads it. */
|
|
13
|
+
export const cedarWasm = () => (wasm ??= require("@cedar-policy/cedar-wasm/nodejs"));
|
|
14
|
+
/** Where the schema's text is written, under a company's root. */
|
|
15
|
+
export const SCHEMA_FILE = join(".sanoma", "schema.cedarschema");
|
|
16
|
+
/** The schema's namespace: policies name `Sanoma::Group::"finance"`, `Sanoma::Action::"effect:money"`. */
|
|
17
|
+
export const NAMESPACE = "Sanoma";
|
|
18
|
+
/** The action group every workflow start (`workflow:<name>`) is in. */
|
|
19
|
+
export const START = "start";
|
|
20
|
+
const STRING = { type: "EntityOrCommon", name: "String" };
|
|
21
|
+
const LONG = { type: "EntityOrCommon", name: "Long" };
|
|
22
|
+
const BOOL = { type: "EntityOrCommon", name: "Bool" };
|
|
23
|
+
const entity = (name) => ({ type: "Entity", name });
|
|
24
|
+
const record = (attributes) => ({
|
|
25
|
+
type: "Record",
|
|
26
|
+
attributes,
|
|
27
|
+
});
|
|
28
|
+
const optional = (type) => ({ ...type, required: false });
|
|
29
|
+
/**
|
|
30
|
+
* The Cedar type of a zod schema's parsed value (`io: "output"`: what the policy is given, defaults
|
|
31
|
+
* filled and transforms applied), through its JSON Schema; undefined when it has none.
|
|
32
|
+
*/
|
|
33
|
+
const typeOf = (schema) => {
|
|
34
|
+
const json = jsonSchemaOf(schema, "output");
|
|
35
|
+
return cedarType(json, { root: json, seen: new Set() });
|
|
36
|
+
};
|
|
37
|
+
/** A context's `input`, typed from a zod schema: none when it has no Cedar type. */
|
|
38
|
+
const input = (schema) => {
|
|
39
|
+
const type = typeOf(schema);
|
|
40
|
+
return type ? { input: type } : {};
|
|
41
|
+
};
|
|
42
|
+
/** A collection's operations that change a record, whose context has the record as it was (`before`). */
|
|
43
|
+
const WRITES = new Set(["save", "delete"]);
|
|
44
|
+
/**
|
|
45
|
+
* The Cedar schema for a resolved config and its people, namespace `Sanoma`:
|
|
46
|
+
*
|
|
47
|
+
* - `entity Group enum [...]`, the declared groups and `agents`, so a policy naming another fails
|
|
48
|
+
* validation; `entity Principal in [Group] { onBehalfOf?: Principal }`; `Collection`;
|
|
49
|
+
* `Target in [Collection]`; `Workflow`;
|
|
50
|
+
* - an action per operation id, in its effect's group (`effect:money`), on a `Target`, with
|
|
51
|
+
* `context` `{ input, before? }`: `input` from the operation's input schema, `before` the record
|
|
52
|
+
* as it was for a collection's `save` and `delete`;
|
|
53
|
+
* - `workflow:<name>` per workflow, in the group `start`, on a `Workflow`, with its `input`.
|
|
54
|
+
*
|
|
55
|
+
* Zod to Cedar, through the JSON Schema of the parsed value: string and enum `String`, integer `Long`, boolean `Bool`,
|
|
56
|
+
* object a record (its optional and nullable fields optional), array a `Set`; a decimal number
|
|
57
|
+
* is a `String`; a field with no Cedar type (a union of types, a map, a recursive type) is left
|
|
58
|
+
* out, so a policy naming it fails validation. Pure: the same config and people give the same schema.
|
|
59
|
+
*/
|
|
60
|
+
function buildSchema(resolved, people) {
|
|
61
|
+
const applies = (resource, context) => ({
|
|
62
|
+
principalTypes: ["Principal"],
|
|
63
|
+
resourceTypes: [resource],
|
|
64
|
+
context: record(context),
|
|
65
|
+
});
|
|
66
|
+
const actions = { [START]: {} };
|
|
67
|
+
for (const effect of EFFECTS)
|
|
68
|
+
actions[`effect:${effect}`] = {};
|
|
69
|
+
for (const op of [...resolved.ops.values()].toSorted((a, b) => a.id.localeCompare(b.id))) {
|
|
70
|
+
const collection = op.vendor === DATA_VENDOR && WRITES.has(op.name) ? resolved.collections.get(op.resource) : undefined;
|
|
71
|
+
const before = collection && typeOf(recordSchemaOf(collection));
|
|
72
|
+
actions[op.id] = {
|
|
73
|
+
memberOf: [{ id: `effect:${op.effect}` }],
|
|
74
|
+
appliesTo: applies("Target", { ...input(op.input), ...(before && { before: optional(before) }) }),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
for (const name of [...resolved.workflows.keys()].toSorted()) {
|
|
78
|
+
actions[`${WORKFLOW_ACTION}${name}`] = {
|
|
79
|
+
memberOf: [{ id: START }],
|
|
80
|
+
appliesTo: applies("Workflow", input(resolved.workflows.get(name).input)),
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
const entityTypes = {
|
|
84
|
+
Group: { enum: groupNamesOf(people) },
|
|
85
|
+
Principal: { memberOfTypes: ["Group"], shape: record({ onBehalfOf: optional(entity("Principal")) }) },
|
|
86
|
+
Collection: {},
|
|
87
|
+
Target: { memberOfTypes: ["Collection"] },
|
|
88
|
+
Workflow: {},
|
|
89
|
+
};
|
|
90
|
+
return { [NAMESPACE]: { entityTypes, actions } };
|
|
91
|
+
}
|
|
92
|
+
const schemas = new WeakMap();
|
|
93
|
+
/**
|
|
94
|
+
* The Cedar schema for a resolved config and its people (`buildSchema`), made once for each pair:
|
|
95
|
+
* validating, deciding and writing it share one.
|
|
96
|
+
*/
|
|
97
|
+
export function schemaOf(resolved, people) {
|
|
98
|
+
let byPeople = schemas.get(resolved.ops);
|
|
99
|
+
if (!byPeople)
|
|
100
|
+
schemas.set(resolved.ops, (byPeople = new WeakMap()));
|
|
101
|
+
let schema = byPeople.get(people);
|
|
102
|
+
if (!schema)
|
|
103
|
+
byPeople.set(people, (schema = buildSchema(resolved, people)));
|
|
104
|
+
return schema;
|
|
105
|
+
}
|
|
106
|
+
/** The schema as Cedar's text, through the package's own `schemaToText`: what `.sanoma/schema.cedarschema` holds. */
|
|
107
|
+
export function schemaText(schema) {
|
|
108
|
+
const answer = cedarWasm().schemaToText(schema);
|
|
109
|
+
if (answer.type === "failure") {
|
|
110
|
+
throw new Error(`The Cedar schema does not print: ${answer.errors.map(messageOf).join("; ")}`);
|
|
111
|
+
}
|
|
112
|
+
return answer.text;
|
|
113
|
+
}
|
|
114
|
+
/** The Cedar type of a JSON Schema (`jsonSchemaOf`'s, draft 2020-12), or undefined when it has none. */
|
|
115
|
+
function cedarType(schema, typing) {
|
|
116
|
+
if (!isObject(schema) || typing.seen.has(schema))
|
|
117
|
+
return undefined;
|
|
118
|
+
if (typeof schema.$ref === "string") {
|
|
119
|
+
const defs = typing.root.$defs;
|
|
120
|
+
const target = schema.$ref.startsWith("#/$defs/") ? defs?.[schema.$ref.slice("#/$defs/".length)] : undefined;
|
|
121
|
+
return within(schema, typing, () => cedarType(target, typing));
|
|
122
|
+
}
|
|
123
|
+
const variants = schema.anyOf ?? schema.oneOf;
|
|
124
|
+
if (Array.isArray(variants)) {
|
|
125
|
+
const each = within(schema, typing, () => variants.filter((v) => !isNull(v)).map((v) => cedarType(v, typing)));
|
|
126
|
+
const first = each[0];
|
|
127
|
+
return first && each.every((t) => t && JSON.stringify(t) === JSON.stringify(first)) ? first : undefined;
|
|
128
|
+
}
|
|
129
|
+
const values = Array.isArray(schema.enum) ? schema.enum : "const" in schema ? [schema.const] : undefined;
|
|
130
|
+
if (values) {
|
|
131
|
+
if (values.every((v) => typeof v === "string"))
|
|
132
|
+
return STRING;
|
|
133
|
+
if (values.every((v) => Number.isSafeInteger(v)))
|
|
134
|
+
return LONG;
|
|
135
|
+
return values.every((v) => typeof v === "boolean") ? BOOL : undefined;
|
|
136
|
+
}
|
|
137
|
+
const types = Array.isArray(schema.type) ? schema.type.filter((t) => t !== "null") : [schema.type];
|
|
138
|
+
if (types.length !== 1)
|
|
139
|
+
return undefined;
|
|
140
|
+
switch (types[0]) {
|
|
141
|
+
case "string":
|
|
142
|
+
case "number":
|
|
143
|
+
// Cedar has no decimal number: one is compared as text.
|
|
144
|
+
return STRING;
|
|
145
|
+
case "integer":
|
|
146
|
+
return LONG;
|
|
147
|
+
case "boolean":
|
|
148
|
+
return BOOL;
|
|
149
|
+
case "array": {
|
|
150
|
+
const element = within(schema, typing, () => cedarType(schema.items, typing));
|
|
151
|
+
return element && { type: "Set", element };
|
|
152
|
+
}
|
|
153
|
+
case "object": {
|
|
154
|
+
// A map's keys are not known: it has no Cedar type.
|
|
155
|
+
if (!isObject(schema.properties))
|
|
156
|
+
return schema.additionalProperties ? undefined : record({});
|
|
157
|
+
const required = new Set(Array.isArray(schema.required) ? schema.required : []);
|
|
158
|
+
const attributes = {};
|
|
159
|
+
for (const [name, property] of Object.entries(schema.properties)) {
|
|
160
|
+
const type = within(schema, typing, () => cedarType(property, typing));
|
|
161
|
+
if (type)
|
|
162
|
+
attributes[name] = required.has(name) && !allowsNull(property) ? type : optional(type);
|
|
163
|
+
}
|
|
164
|
+
return record(attributes);
|
|
165
|
+
}
|
|
166
|
+
default:
|
|
167
|
+
return undefined;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/** `type()` with `schema` marked as being typed, so a reference back to it is not followed. */
|
|
171
|
+
function within(schema, typing, type) {
|
|
172
|
+
typing.seen.add(schema);
|
|
173
|
+
try {
|
|
174
|
+
return type();
|
|
175
|
+
}
|
|
176
|
+
finally {
|
|
177
|
+
typing.seen.delete(schema);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
const isNull = (schema) => isObject(schema) && schema.type === "null";
|
|
181
|
+
/** True when a JSON Schema accepts `null`: its value is then optional in Cedar, which has no null. */
|
|
182
|
+
const allowsNull = (schema) => isObject(schema) &&
|
|
183
|
+
(isNull(schema) ||
|
|
184
|
+
(Array.isArray(schema.type) && schema.type.includes("null")) ||
|
|
185
|
+
[schema.anyOf, schema.oneOf].some((v) => Array.isArray(v) && v.some(isNull)));
|
|
186
|
+
/** Cedar's message, with its help when it has one. */
|
|
187
|
+
export const messageOf = (e) => (e.help ? `${e.message} (${e.help})` : e.message);
|
|
188
|
+
/** An action's context type in the schema: a record, when the action is there. */
|
|
189
|
+
export const contextTypeOf = (schema, action) => schema[NAMESPACE]?.actions[action]?.appliesTo?.context;
|
|
190
|
+
/**
|
|
191
|
+
* A value as Cedar takes it for a type `schemaOf` wrote (`cedarType`'s other side): a record's
|
|
192
|
+
* fields it declares only, a set's elements, a number where it is a `String` as text. An unknown
|
|
193
|
+
* (`{ __extn: unknown }`) passes as it is; what does not fit is left out (undefined), as `null` is.
|
|
194
|
+
*/
|
|
195
|
+
export function cedarValue(value, type) {
|
|
196
|
+
if (value === null || value === undefined)
|
|
197
|
+
return undefined;
|
|
198
|
+
if (isObject(value) && "__extn" in value)
|
|
199
|
+
return value;
|
|
200
|
+
const t = type;
|
|
201
|
+
if (t.attributes) {
|
|
202
|
+
if (!isObject(value))
|
|
203
|
+
return undefined;
|
|
204
|
+
return Object.fromEntries(Object.entries(t.attributes).flatMap(([name, field]) => {
|
|
205
|
+
const shaped = cedarValue(value[name], field);
|
|
206
|
+
return shaped === undefined ? [] : [[name, shaped]];
|
|
207
|
+
}));
|
|
208
|
+
}
|
|
209
|
+
if (t.type === "Set") {
|
|
210
|
+
return Array.isArray(value)
|
|
211
|
+
? value.map((v) => cedarValue(v, t.element)).filter((v) => v !== undefined)
|
|
212
|
+
: undefined;
|
|
213
|
+
}
|
|
214
|
+
switch (t.name) {
|
|
215
|
+
case STRING.name:
|
|
216
|
+
return typeof value === "string" ? value : typeof value === "number" ? String(value) : undefined;
|
|
217
|
+
case LONG.name:
|
|
218
|
+
return Number.isSafeInteger(value) ? value : undefined;
|
|
219
|
+
case BOOL.name:
|
|
220
|
+
return typeof value === "boolean" ? value : undefined;
|
|
221
|
+
default:
|
|
222
|
+
return undefined;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
|
package/dist/sdk.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { ConfigDescription } from "./describe.ts";
|
|
2
|
+
import { type CedarSchemaJson } from "./schema.ts";
|
|
3
|
+
/** Where `writeApi` writes, under a company's root. */
|
|
4
|
+
export declare const API_FILE: string;
|
|
5
|
+
/** `describeConfig`'s problem on a workflow whose api name is taken: `taken` says by what. */
|
|
6
|
+
export declare const apiNameProblem: (api: string, taken: string) => string;
|
|
7
|
+
/**
|
|
8
|
+
* `.sanoma/api.ts` for a description: one record type per collection, and `CompanyApi` (not `Api`,
|
|
9
|
+
* which inside `declare module "sanoma/site"` is the module's own), one member per
|
|
10
|
+
* workflow (`apiNameOf`), per vendor of the operations a person may call directly (`OpEntry.direct`,
|
|
11
|
+
* by resource) and `data` for the collections, each with its JSDoc; then `Register`'s
|
|
12
|
+
* augmentation. Pure: the same description gives the same text. A workflow whose api name another
|
|
13
|
+
* has, `describeConfig`'s problem on its entry, is left out, and its problem is in `problems`.
|
|
14
|
+
*/
|
|
15
|
+
export declare function generateApi(description: ConfigDescription): {
|
|
16
|
+
source: string;
|
|
17
|
+
problems: string[];
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Writes `<root>/.sanoma/api.ts` (`generateApi`) when its text differs from the file's, so an
|
|
21
|
+
* editor or a dev server sees no change when there is none; `wrote` says whether it did.
|
|
22
|
+
*/
|
|
23
|
+
export declare function writeApi(root: string, description: ConfigDescription): Promise<{
|
|
24
|
+
wrote: boolean;
|
|
25
|
+
file: string;
|
|
26
|
+
}>;
|
|
27
|
+
/**
|
|
28
|
+
* The generated files, each written when its text changed: `.sanoma/api.ts` (`writeApi`) and the
|
|
29
|
+
* Cedar schema's text, `.sanoma/schema.cedarschema` (`schemaText` of `schemaOf`). `wrote` lists
|
|
30
|
+
* those written, relative to the root.
|
|
31
|
+
*/
|
|
32
|
+
export declare function writeGenerated(root: string, description: ConfigDescription, schema: CedarSchemaJson): Promise<{
|
|
33
|
+
wrote: string[];
|
|
34
|
+
}>;
|
package/dist/sdk.js
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { isObject } from "./resource.js";
|
|
4
|
+
import { SCHEMA_FILE, schemaText } from "./schema.js";
|
|
5
|
+
import { apiNameOf, DATA_VENDOR, problemLine } from "./shared.js";
|
|
6
|
+
// A company's generated SDK, `.sanoma/api.ts`: the types of a site's `api` from `sanoma/site`,
|
|
7
|
+
// written from `describeConfig` (types and JSDoc only: `api` itself is one generic client). It
|
|
8
|
+
// augments `sanoma/site`'s `Register`, so it is type-checked only through the sites' generated
|
|
9
|
+
// tsconfig, never the company's root one (Node, no DOM).
|
|
10
|
+
/** Where `writeApi` writes, under a company's root. */
|
|
11
|
+
export const API_FILE = join(".sanoma", "api.ts");
|
|
12
|
+
const API_NAME_PROBLEM = "A site calls this workflow api.";
|
|
13
|
+
/** `describeConfig`'s problem on a workflow whose api name is taken: `taken` says by what. */
|
|
14
|
+
export const apiNameProblem = (api, taken) => `${API_NAME_PROBLEM}${api}, ${taken}: rename it`;
|
|
15
|
+
/**
|
|
16
|
+
* `.sanoma/api.ts` for a description: one record type per collection, and `CompanyApi` (not `Api`,
|
|
17
|
+
* which inside `declare module "sanoma/site"` is the module's own), one member per
|
|
18
|
+
* workflow (`apiNameOf`), per vendor of the operations a person may call directly (`OpEntry.direct`,
|
|
19
|
+
* by resource) and `data` for the collections, each with its JSDoc; then `Register`'s
|
|
20
|
+
* augmentation. Pure: the same description gives the same text. A workflow whose api name another
|
|
21
|
+
* has, `describeConfig`'s problem on its entry, is left out, and its problem is in `problems`.
|
|
22
|
+
*/
|
|
23
|
+
export function generateApi(description) {
|
|
24
|
+
const problems = [];
|
|
25
|
+
const members = [];
|
|
26
|
+
for (const wf of description.workflows) {
|
|
27
|
+
const taken = wf.problems.filter((p) => p.message.startsWith(API_NAME_PROBLEM));
|
|
28
|
+
if (taken.length)
|
|
29
|
+
problems.push(...taken.map((p) => problemLine({ file: wf.file, ...p })));
|
|
30
|
+
else
|
|
31
|
+
members.push(workflowMember(wf));
|
|
32
|
+
}
|
|
33
|
+
// The ops are sorted by id, so by vendor and then resource.
|
|
34
|
+
const direct = description.ops.filter((op) => op.direct && op.vendor !== DATA_VENDOR);
|
|
35
|
+
for (const [vendor, ops] of Map.groupBy(direct, (op) => op.vendor)) {
|
|
36
|
+
const title = description.vendors[vendor]?.title ?? vendor;
|
|
37
|
+
const resources = [...Map.groupBy(ops, (op) => op.resource)].map(([resource, own]) => member(undefined, resource, block(own.map(opMember))));
|
|
38
|
+
members.push(member(`${title}: the operations a person may call directly.`, vendor, block(resources)));
|
|
39
|
+
}
|
|
40
|
+
if (description.collections.length) {
|
|
41
|
+
const data = description.collections.map((c) => member(collectionDoc(c), c.name, `CollectionApi<${recordName(c)}>`));
|
|
42
|
+
members.push(member("The company's collections.", DATA_VENDOR, block(data)));
|
|
43
|
+
}
|
|
44
|
+
const source = [
|
|
45
|
+
"// Generated by sanoma from sanoma.config.ts and the connectors it names; do not edit.",
|
|
46
|
+
"// The types of `api` from sanoma/site: what a site may call, as the person on the page.",
|
|
47
|
+
'import type { CollectionApi, OpFn, WorkflowFn } from "sanoma/site";',
|
|
48
|
+
...description.collections.map((c) => `\n${jsdoc(`A record of ${c.title ?? c.name}.`)}type ${recordName(c)} = ${typeOf(c.record)};`),
|
|
49
|
+
"",
|
|
50
|
+
`interface CompanyApi ${block(members)}`,
|
|
51
|
+
"",
|
|
52
|
+
'declare module "sanoma/site" {',
|
|
53
|
+
" interface Register {",
|
|
54
|
+
" api: CompanyApi;",
|
|
55
|
+
" }",
|
|
56
|
+
"}",
|
|
57
|
+
"",
|
|
58
|
+
"export {};",
|
|
59
|
+
"",
|
|
60
|
+
].join("\n");
|
|
61
|
+
return { source, problems };
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Writes `<root>/.sanoma/api.ts` (`generateApi`) when its text differs from the file's, so an
|
|
65
|
+
* editor or a dev server sees no change when there is none; `wrote` says whether it did.
|
|
66
|
+
*/
|
|
67
|
+
export async function writeApi(root, description) {
|
|
68
|
+
const file = join(root, API_FILE);
|
|
69
|
+
return { wrote: await writeChanged(file, generateApi(description).source), file };
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* The generated files, each written when its text changed: `.sanoma/api.ts` (`writeApi`) and the
|
|
73
|
+
* Cedar schema's text, `.sanoma/schema.cedarschema` (`schemaText` of `schemaOf`). `wrote` lists
|
|
74
|
+
* those written, relative to the root.
|
|
75
|
+
*/
|
|
76
|
+
export async function writeGenerated(root, description, schema) {
|
|
77
|
+
const [api, cedar] = await Promise.all([
|
|
78
|
+
writeApi(root, description),
|
|
79
|
+
writeChanged(join(root, SCHEMA_FILE), schemaText(schema)),
|
|
80
|
+
]);
|
|
81
|
+
return { wrote: [...(api.wrote ? [API_FILE] : []), ...(cedar ? [SCHEMA_FILE] : [])] };
|
|
82
|
+
}
|
|
83
|
+
/** Writes `text` to `file` unless the file holds it already; true when it wrote. */
|
|
84
|
+
async function writeChanged(file, text) {
|
|
85
|
+
if ((await readFile(file, "utf8").catch(() => undefined)) === text)
|
|
86
|
+
return false;
|
|
87
|
+
await mkdir(dirname(file), { recursive: true });
|
|
88
|
+
await writeFile(file, text);
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
const workflowMember = (wf) => member(`${wf.title ?? wf.name}: the workflow \`${wf.name}\`${wf.builtin ? ", built in" : ""}.`, apiNameOf(wf.name), `WorkflowFn<${typeOf(wf.input)}, unknown>`);
|
|
92
|
+
const opMember = (op) => member(`${op.description ? `${op.description}\n\n` : ""}\`${op.id}\`, a ${op.effect}.`, op.name, `OpFn<${typeOf(op.input)}, unknown>`);
|
|
93
|
+
const collectionDoc = (c) => `${c.title ?? c.name}: the collection \`${c.name}\`, keyed by \`${c.key}\`.`;
|
|
94
|
+
/** A collection's record type's name: `outbound` gives `OutboundRecord`, never `CompanyApi` nor an imported type's. */
|
|
95
|
+
const recordName = (c) => `${c.name[0].toUpperCase()}${c.name.slice(1)}Record`;
|
|
96
|
+
/**
|
|
97
|
+
* A JSON Schema as a TypeScript type, for the kinds a start form draws (`fieldsOf` in the app):
|
|
98
|
+
* strings (a date-time among them), numbers, integers, booleans, enums and constants, objects and
|
|
99
|
+
* arrays, each property with its description, and unions of those, `null` among them (a
|
|
100
|
+
* collection's date, a date or a date-time; a nullable field); anything else is `unknown`.
|
|
101
|
+
*/
|
|
102
|
+
const typeOf = (schema) => union(alternatives(schema));
|
|
103
|
+
/** One type of several: `unknown` when any is. */
|
|
104
|
+
function union(types) {
|
|
105
|
+
const distinct = new Set(types);
|
|
106
|
+
return distinct.has("unknown") ? "unknown" : [...distinct].join(" | ");
|
|
107
|
+
}
|
|
108
|
+
/** The types a schema allows, one per alternative. */
|
|
109
|
+
function alternatives(schema) {
|
|
110
|
+
if (!isObject(schema))
|
|
111
|
+
return ["unknown"];
|
|
112
|
+
if ("const" in schema && !isObject(schema.const) && !Array.isArray(schema.const)) {
|
|
113
|
+
return [JSON.stringify(schema.const)];
|
|
114
|
+
}
|
|
115
|
+
if (Array.isArray(schema.enum) && schema.enum.length && schema.enum.every((v) => v === null || !isObject(v))) {
|
|
116
|
+
return schema.enum.map((v) => JSON.stringify(v));
|
|
117
|
+
}
|
|
118
|
+
if (Array.isArray(schema.anyOf) && schema.anyOf.length)
|
|
119
|
+
return schema.anyOf.flatMap(alternatives);
|
|
120
|
+
if (Array.isArray(schema.type) && schema.type.length) {
|
|
121
|
+
return schema.type.flatMap((type) => alternatives({ ...schema, type }));
|
|
122
|
+
}
|
|
123
|
+
switch (schema.type) {
|
|
124
|
+
case "string":
|
|
125
|
+
return ["string"];
|
|
126
|
+
case "number":
|
|
127
|
+
case "integer":
|
|
128
|
+
return ["number"];
|
|
129
|
+
case "boolean":
|
|
130
|
+
return ["boolean"];
|
|
131
|
+
case "null":
|
|
132
|
+
return ["null"];
|
|
133
|
+
case "array": {
|
|
134
|
+
const item = typeOf(schema.items);
|
|
135
|
+
return [new Set(alternatives(schema.items)).size > 1 && item !== "unknown" ? `(${item})[]` : `${item}[]`];
|
|
136
|
+
}
|
|
137
|
+
case "object":
|
|
138
|
+
return [isObject(schema.properties) ? objectType(schema) : "Record<string, unknown>"];
|
|
139
|
+
default:
|
|
140
|
+
return ["unknown"];
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
function objectType(schema) {
|
|
144
|
+
const required = new Set(Array.isArray(schema.required) ? schema.required : []);
|
|
145
|
+
const lines = Object.entries(schema.properties).map(([name, prop]) => {
|
|
146
|
+
const doc = isObject(prop) && typeof prop.description === "string" ? jsdoc(prop.description) : "";
|
|
147
|
+
return `${doc}${key(name)}${required.has(name) ? "" : "?"}: ${typeOf(prop)};`;
|
|
148
|
+
});
|
|
149
|
+
// An object that takes other keys too.
|
|
150
|
+
if (schema.additionalProperties !== undefined && schema.additionalProperties !== false) {
|
|
151
|
+
lines.push("[key: string]: unknown;");
|
|
152
|
+
}
|
|
153
|
+
return block(lines);
|
|
154
|
+
}
|
|
155
|
+
/** A property's name, quoted when it is not an identifier. */
|
|
156
|
+
const key = (name) => (/^[A-Za-z_$][\w$]*$/.test(name) ? name : JSON.stringify(name));
|
|
157
|
+
/** A member, under its JSDoc when there is one. */
|
|
158
|
+
const member = (doc, name, type) => `${doc ? jsdoc(doc) : ""}${key(name)}: ${type};`;
|
|
159
|
+
/** `{ … }` around lines, each indented a level (a nested block's lines with it); `{}` for none. */
|
|
160
|
+
const block = (lines) => lines.length ? `{\n${lines.map((l) => l.replace(/^(?=.)/gm, " ")).join("\n")}\n}` : "{}";
|
|
161
|
+
/** A JSDoc comment and the line break after it; `*\/` in the text cannot end it. */
|
|
162
|
+
function jsdoc(text) {
|
|
163
|
+
const lines = text.replaceAll("*/", "*\\/").split("\n");
|
|
164
|
+
return lines.length === 1
|
|
165
|
+
? `/** ${lines[0]} */\n`
|
|
166
|
+
: `/**\n${lines.map((l) => ` *${l ? ` ${l}` : ""}`).join("\n")}\n */\n`;
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=sdk.js.map
|
package/dist/sdk.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdk.js","sourceRoot":"","sources":["../src/sdk.ts"],"names":[],"mappings":"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"}
|