@adminiumjs/manifest 0.3.0-rc.4 → 0.3.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.
Files changed (67) hide show
  1. package/dist/add-ons.d.ts +63 -0
  2. package/dist/add-ons.d.ts.map +1 -0
  3. package/dist/add-ons.js +100 -0
  4. package/dist/add-ons.js.map +1 -0
  5. package/dist/booking.d.ts +100 -0
  6. package/dist/booking.d.ts.map +1 -0
  7. package/dist/booking.js +237 -0
  8. package/dist/booking.js.map +1 -0
  9. package/dist/documents.d.ts +100 -0
  10. package/dist/documents.d.ts.map +1 -0
  11. package/dist/documents.js +148 -0
  12. package/dist/documents.js.map +1 -0
  13. package/dist/formula.d.ts +124 -0
  14. package/dist/formula.d.ts.map +1 -0
  15. package/dist/formula.js +428 -0
  16. package/dist/formula.js.map +1 -0
  17. package/dist/index.d.ts +14 -3
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +14 -3
  20. package/dist/index.js.map +1 -1
  21. package/dist/outbox.d.ts +543 -0
  22. package/dist/outbox.d.ts.map +1 -0
  23. package/dist/outbox.js +559 -0
  24. package/dist/outbox.js.map +1 -0
  25. package/dist/page-calendar.d.ts +42 -0
  26. package/dist/page-calendar.d.ts.map +1 -0
  27. package/dist/page-calendar.js +95 -0
  28. package/dist/page-calendar.js.map +1 -0
  29. package/dist/plan-model.d.ts +1 -1
  30. package/dist/plan-model.d.ts.map +1 -1
  31. package/dist/public-access.d.ts +208 -0
  32. package/dist/public-access.d.ts.map +1 -0
  33. package/dist/public-access.js +681 -0
  34. package/dist/public-access.js.map +1 -0
  35. package/dist/refs.d.ts +91 -0
  36. package/dist/refs.d.ts.map +1 -0
  37. package/dist/refs.js +82 -0
  38. package/dist/refs.js.map +1 -0
  39. package/dist/roles.d.ts +44 -0
  40. package/dist/roles.d.ts.map +1 -0
  41. package/dist/roles.js +75 -0
  42. package/dist/roles.js.map +1 -0
  43. package/dist/sample.d.ts +150 -2
  44. package/dist/sample.d.ts.map +1 -1
  45. package/dist/sample.js +101 -3
  46. package/dist/sample.js.map +1 -1
  47. package/dist/schema.d.ts +3464 -151
  48. package/dist/schema.d.ts.map +1 -1
  49. package/dist/schema.js +681 -143
  50. package/dist/schema.js.map +1 -1
  51. package/dist/semver.d.ts +28 -0
  52. package/dist/semver.d.ts.map +1 -0
  53. package/dist/semver.js +85 -0
  54. package/dist/semver.js.map +1 -0
  55. package/dist/shapes.d.ts +97 -0
  56. package/dist/shapes.d.ts.map +1 -0
  57. package/dist/shapes.js +190 -0
  58. package/dist/shapes.js.map +1 -0
  59. package/dist/states.d.ts +134 -0
  60. package/dist/states.d.ts.map +1 -0
  61. package/dist/states.js +244 -0
  62. package/dist/states.js.map +1 -0
  63. package/dist/validate.d.ts +14 -0
  64. package/dist/validate.d.ts.map +1 -1
  65. package/dist/validate.js +29 -2
  66. package/dist/validate.js.map +1 -1
  67. package/package.json +2 -2
package/dist/shapes.js ADDED
@@ -0,0 +1,190 @@
1
+ /** `invoices` + `invoice@1` → `invoices/invoice@1`, the way an app names it. */
2
+ export function shapeKey(addOn, shape) {
3
+ return `${addOn}/${shape.name}@${String(shape.version)}`;
4
+ }
5
+ /** Rules an app may add to a part's column: they label or narrow, never decide. */
6
+ const ADDABLE_RULES = new Set(['enumLabels', 'personal', 'validation', 'required', 'options', 'notAfter', 'notBefore']);
7
+ /** JSON with sorted keys, so two spellings of one value compare equal. */
8
+ function canonical(value) {
9
+ if (Array.isArray(value))
10
+ return `[${value.map(canonical).join(',')}]`;
11
+ if (value !== null && typeof value === 'object') {
12
+ return `{${Object.keys(value)
13
+ .filter((key) => value[key] !== undefined)
14
+ .sort()
15
+ .map((key) => `${JSON.stringify(key)}:${canonical(value[key])}`)
16
+ .join(',')}}`;
17
+ }
18
+ return JSON.stringify(value);
19
+ }
20
+ /**
21
+ * Every way the app's tables built on a shape differ from it. `shapes` maps
22
+ * `<addOn>/<name>@<version>` to its definition; a table built on a shape that
23
+ * is not there is `SHAPE_UNKNOWN`.
24
+ */
25
+ export function shapeConformanceIssues(app, shapes) {
26
+ const out = [];
27
+ const tables = app.requiredSchema?.tables ?? [];
28
+ /** The app's table built on a part: `document` in the same shape, or `quote@1/document` in another of the add-on's. */
29
+ const tableFor = (builtOn, ref) => {
30
+ const addOn = builtOn.split('/')[0];
31
+ const [shape, part] = ref.includes('/') ? [`${addOn}/${ref.split('/')[0]}`, ref.split('/')[1]] : [builtOn, ref];
32
+ return tables.find((t) => t.builtOn === shape && t.part === part)?.ref;
33
+ };
34
+ const usedShapes = new Set();
35
+ tables.forEach((table, t) => {
36
+ if (table.builtOn === undefined || table.part === undefined)
37
+ return;
38
+ const at = (...rest) => ['requiredSchema', 'tables', t, ...rest].join('.');
39
+ const shape = shapes.get(table.builtOn);
40
+ if (shape === undefined) {
41
+ out.push({ code: 'SHAPE_UNKNOWN', path: at('builtOn'), message: `"${table.builtOn}" is not a shape the add-on defines` });
42
+ return;
43
+ }
44
+ usedShapes.add(table.builtOn);
45
+ const part = shape.parts[table.part];
46
+ if (part === undefined) {
47
+ out.push({ code: 'SHAPE_MISMATCH', path: at('part'), message: `"${table.builtOn}" has no part "${table.part}"` });
48
+ return;
49
+ }
50
+ const map = (ref) => tableFor(table.builtOn, ref) ?? `(no table built on ${ref})`;
51
+ const mismatch = (path, message) => out.push({ code: 'SHAPE_MISMATCH', path, message });
52
+ for (const want of part.columns) {
53
+ const c = table.columns.findIndex((column) => column.ref === want.ref);
54
+ const have = table.columns[c];
55
+ if (have === undefined) {
56
+ mismatch(at('columns'), `"${table.ref}" has no column "${want.ref}", which "${table.builtOn}" ${table.part} has`);
57
+ continue;
58
+ }
59
+ const here = at('columns', c);
60
+ const shapeOf = (column, references) => canonical({
61
+ type: column.type,
62
+ role: column.role,
63
+ nullable: column.nullable === true,
64
+ enum: column.enum,
65
+ references,
66
+ maxLength: column.maxLength,
67
+ scale: column.scale,
68
+ unique: column.unique,
69
+ default: column.default,
70
+ });
71
+ if (shapeOf(have, have.references) !== shapeOf(want, want.references === undefined ? undefined : map(want.references))) {
72
+ mismatch(here, `"${table.ref}.${want.ref}" is not declared as the shape declares it`);
73
+ }
74
+ const wantRules = mapRules(want.rules, map);
75
+ const haveRules = (have.rules ?? {});
76
+ for (const [name, value] of Object.entries(wantRules)) {
77
+ if (canonical(haveRules[name]) !== canonical(value)) {
78
+ mismatch(`${here}.rules.${name}`, `"${table.ref}.${want.ref}" changes the shape's ${name} rule`);
79
+ }
80
+ }
81
+ for (const name of Object.keys(haveRules)) {
82
+ const copyBeforeFill = name === 'copy' && wantRules['default'] !== undefined && wantRules['copy'] === undefined;
83
+ if (wantRules[name] === undefined && !ADDABLE_RULES.has(name) && !copyBeforeFill) {
84
+ mismatch(`${here}.rules.${name}`, `"${table.ref}.${want.ref}" adds a ${name} rule the shape does not keep`);
85
+ }
86
+ }
87
+ }
88
+ if (part.states !== undefined || table.states !== undefined) {
89
+ if (part.states === undefined) {
90
+ // The part keeps no states: the app's own are its business.
91
+ }
92
+ else if (table.states === undefined) {
93
+ mismatch(at('states'), `"${table.ref}" drops the shape's states`);
94
+ }
95
+ else {
96
+ for (const message of statesDifferences(mapStates(part.states, map), table.states))
97
+ mismatch(at('states'), message);
98
+ }
99
+ }
100
+ });
101
+ // The shape's messages are part of it: an app built on it sends them.
102
+ for (const key of usedShapes) {
103
+ const shape = shapes.get(key);
104
+ for (const producer of shape.outbox?.producers ?? []) {
105
+ if (app.outbox?.kinds[producer.kind] === undefined || !(app.outbox.producers ?? []).some((p) => p.kind === producer.kind)) {
106
+ out.push({ code: 'SHAPE_MISMATCH', path: 'outbox', message: `"${key}" sends "${producer.kind}", and the app's outbox does not` });
107
+ }
108
+ }
109
+ }
110
+ return out;
111
+ }
112
+ /** A part's rules with the part names they read replaced by the app's tables. */
113
+ function mapRules(rules, map) {
114
+ if (rules === undefined)
115
+ return {};
116
+ const out = { ...rules };
117
+ if (rules.rollup !== undefined)
118
+ out['rollup'] = { ...rules.rollup, from: map(rules.rollup.from) };
119
+ const set = rules.stamp?.set;
120
+ if (typeof set === 'object' && 'hashOf' in set) {
121
+ const child = (c) => ({ ...c, table: map(c.table) });
122
+ out['stamp'] = {
123
+ ...rules.stamp,
124
+ set: {
125
+ hashOf: {
126
+ ...set.hashOf,
127
+ ...(set.hashOf.children === undefined ? {} : { children: set.hashOf.children.map(child) }),
128
+ ...(set.hashOf.linked === undefined
129
+ ? {}
130
+ : { linked: set.hashOf.linked.map((l) => ({ ...child(l), ...(l.children === undefined ? {} : { children: l.children.map(child) }) })) }),
131
+ },
132
+ },
133
+ };
134
+ }
135
+ return out;
136
+ }
137
+ function mapStates(states, map) {
138
+ return {
139
+ ...states,
140
+ moves: Object.fromEntries(Object.entries(states.moves).map(([from, moves]) => [
141
+ from,
142
+ moves.map((move) => typeof move === 'string' || move.requires?.children === undefined
143
+ ? move
144
+ : { ...move, requires: { ...move.requires, children: Object.fromEntries(Object.entries(move.requires.children).map(([ref, n]) => [map(ref), n])) } }),
145
+ ])),
146
+ ...(states.children === undefined ? {} : { children: Object.fromEntries(Object.entries(states.children).map(([ref, rule]) => [map(ref), rule])) }),
147
+ ...(states.lockedWhenReferencedBy === undefined
148
+ ? {}
149
+ : { lockedWhenReferencedBy: states.lockedWhenReferencedBy.map((ref) => ({ ...ref, table: map(ref.table) })) }),
150
+ };
151
+ }
152
+ /** How an app's states differ from the part's, beyond what an app may add. */
153
+ function statesDifferences(want, have) {
154
+ const out = [];
155
+ const same = (a, b) => canonical(a) === canonical(b);
156
+ if (want.column !== have.column || want.initial !== have.initial)
157
+ out.push('the state column and the first state are the shape\'s');
158
+ const moveList = (moves) => Object.fromEntries(Object.entries(moves).map(([from, list]) => [
159
+ from,
160
+ list.map((move) => (typeof move === 'string' ? { to: move } : { ...move, roles: undefined })),
161
+ ]));
162
+ if (!same(moveList(want.moves), moveList(have.moves)))
163
+ out.push('the moves between states are the shape\'s (an app may only keep a move for some roles)');
164
+ if (want.lock !== undefined) {
165
+ if (have.lock === undefined || !same(want.lock.when, have.lock.when))
166
+ out.push('the lock is the shape\'s');
167
+ const missing = (want.lock.except ?? []).filter((ref) => !(have.lock?.except ?? []).includes(ref));
168
+ if (missing.length > 0)
169
+ out.push(`the lock keeps ${missing.join(', ')} open, as the shape does`);
170
+ }
171
+ else if (have.lock !== undefined) {
172
+ out.push('the shape locks nothing');
173
+ }
174
+ for (const [ref, rule] of Object.entries(want.children ?? {})) {
175
+ const own = have.children?.[ref];
176
+ if (own === undefined || own.via !== rule.via || own.lock !== rule.lock || !same(own.parentIn, rule.parentIn)) {
177
+ out.push(`"${ref}" is tied to the state as the shape ties it`);
178
+ continue;
179
+ }
180
+ const cleared = (rule.clearOnCreate ?? []).filter((col) => !(own.clearOnCreate ?? []).includes(col));
181
+ if (cleared.length > 0)
182
+ out.push(`creating a "${ref}" row empties ${cleared.join(', ')}, as the shape says`);
183
+ }
184
+ for (const name of ['lockedWhenReferencedBy', 'noDelete', 'onlyLater']) {
185
+ if (!same(want[name], have[name]))
186
+ out.push(`${name} is the shape's`);
187
+ }
188
+ return out;
189
+ }
190
+ //# sourceMappingURL=shapes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shapes.js","sourceRoot":"","sources":["../src/shapes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,134 @@
1
+ /**
2
+ * `table.states` — the life of a document, kept by Adminium for every writer.
3
+ *
4
+ * ```json
5
+ * "states": {
6
+ * "column": "status", "initial": "draft",
7
+ * "moves": {
8
+ * "draft": [{ "to": "sent", "requires": { "children": { "invoice_lines": 1 }, "where": [{ "column": "total", "gt": 0 }] } }, "void"],
9
+ * "sent": [{ "to": "void", "requires": { "where": [{ "column": "paid", "eq": 0 }] }, "roles": ["studio-manager"] }]
10
+ * },
11
+ * "lock": { "when": ["sent", "void"], "except": ["due_on", "ladder"] },
12
+ * "children": {
13
+ * "invoice_lines": { "via": "document_id", "lock": true },
14
+ * "payments": { "via": "document_id", "parentIn": ["sent"], "clearOnCreate": ["client_paid_at"] }
15
+ * },
16
+ * "noDelete": { "when": "numbered" },
17
+ * "onlyLater": ["valid_until"]
18
+ * }
19
+ * ```
20
+ *
21
+ * - `moves`: from each state, the states a write may move a row to. A move
22
+ * may ask for something first — child rows, a column's value — and may be
23
+ * kept for some of the app's roles. A move not listed is refused.
24
+ * - `lock`: while a row is in one of `when`, only `except` (and the state
25
+ * itself, through a move) may change. Adminium's own columns (totals,
26
+ * stamps) keep being written by Adminium.
27
+ * - `children`: child tables tied to this row's state. `lock` refuses their
28
+ * writes while the row is locked; `parentIn` allows them only while the row
29
+ * is in those states (payments on a sent invoice); `clearOnCreate` empties
30
+ * columns of this row when one of them is created (a recorded payment
31
+ * clears the client's "I've sent it").
32
+ * - `lockedWhenReferencedBy`: this row locks once a row of another table in
33
+ * one of the states points at it (a terms version once a proposal naming it
34
+ * is sent).
35
+ * - `noDelete`: rows in these states, or any row with a number
36
+ * (`"numbered"`), are never deleted — voided instead.
37
+ * - `onlyLater`: date columns that may move later and never earlier.
38
+ *
39
+ * Adding sample data and importing past records are history: they write any
40
+ * state their rows were in.
41
+ */
42
+ import { z } from 'zod';
43
+ import { type ColumnShape, type ReferenceIssue, type TableIndex } from './refs.js';
44
+ /** A condition on the row itself, checked in the same statement that changes it. */
45
+ export declare const stateConditionSchema: z.ZodObject<{
46
+ column: z.ZodString;
47
+ eq: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>;
48
+ in: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
49
+ isNull: z.ZodOptional<z.ZodBoolean>;
50
+ gt: z.ZodOptional<z.ZodNumber>;
51
+ gte: z.ZodOptional<z.ZodNumber>;
52
+ lt: z.ZodOptional<z.ZodNumber>;
53
+ lte: z.ZodOptional<z.ZodNumber>;
54
+ }, z.core.$strict>;
55
+ export type StateCondition = z.infer<typeof stateConditionSchema>;
56
+ export declare const stateMoveSchema: z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
57
+ to: z.ZodString;
58
+ requires: z.ZodOptional<z.ZodObject<{
59
+ children: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNumber>>;
60
+ where: z.ZodOptional<z.ZodArray<z.ZodObject<{
61
+ column: z.ZodString;
62
+ eq: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>;
63
+ in: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
64
+ isNull: z.ZodOptional<z.ZodBoolean>;
65
+ gt: z.ZodOptional<z.ZodNumber>;
66
+ gte: z.ZodOptional<z.ZodNumber>;
67
+ lt: z.ZodOptional<z.ZodNumber>;
68
+ lte: z.ZodOptional<z.ZodNumber>;
69
+ }, z.core.$strict>>>;
70
+ }, z.core.$strict>>;
71
+ roles: z.ZodOptional<z.ZodArray<z.ZodString>>;
72
+ }, z.core.$strict>]>;
73
+ export type StateMove = z.infer<typeof stateMoveSchema>;
74
+ export declare const stateChildSchema: z.ZodObject<{
75
+ via: z.ZodString;
76
+ lock: z.ZodOptional<z.ZodLiteral<true>>;
77
+ parentIn: z.ZodOptional<z.ZodArray<z.ZodString>>;
78
+ clearOnCreate: z.ZodOptional<z.ZodArray<z.ZodString>>;
79
+ }, z.core.$strict>;
80
+ export type StateChild = z.infer<typeof stateChildSchema>;
81
+ export declare const statesSchema: z.ZodObject<{
82
+ column: z.ZodString;
83
+ initial: z.ZodString;
84
+ moves: z.ZodRecord<z.ZodString, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
85
+ to: z.ZodString;
86
+ requires: z.ZodOptional<z.ZodObject<{
87
+ children: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNumber>>;
88
+ where: z.ZodOptional<z.ZodArray<z.ZodObject<{
89
+ column: z.ZodString;
90
+ eq: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>;
91
+ in: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
92
+ isNull: z.ZodOptional<z.ZodBoolean>;
93
+ gt: z.ZodOptional<z.ZodNumber>;
94
+ gte: z.ZodOptional<z.ZodNumber>;
95
+ lt: z.ZodOptional<z.ZodNumber>;
96
+ lte: z.ZodOptional<z.ZodNumber>;
97
+ }, z.core.$strict>>>;
98
+ }, z.core.$strict>>;
99
+ roles: z.ZodOptional<z.ZodArray<z.ZodString>>;
100
+ }, z.core.$strict>]>>>;
101
+ lock: z.ZodOptional<z.ZodObject<{
102
+ when: z.ZodArray<z.ZodString>;
103
+ except: z.ZodOptional<z.ZodArray<z.ZodString>>;
104
+ }, z.core.$strict>>;
105
+ children: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
106
+ via: z.ZodString;
107
+ lock: z.ZodOptional<z.ZodLiteral<true>>;
108
+ parentIn: z.ZodOptional<z.ZodArray<z.ZodString>>;
109
+ clearOnCreate: z.ZodOptional<z.ZodArray<z.ZodString>>;
110
+ }, z.core.$strict>>>;
111
+ lockedWhenReferencedBy: z.ZodOptional<z.ZodArray<z.ZodObject<{
112
+ table: z.ZodString;
113
+ via: z.ZodString;
114
+ in: z.ZodArray<z.ZodString>;
115
+ }, z.core.$strict>>>;
116
+ noDelete: z.ZodOptional<z.ZodObject<{
117
+ when: z.ZodUnion<readonly [z.ZodLiteral<"numbered">, z.ZodArray<z.ZodString>]>;
118
+ }, z.core.$strict>>;
119
+ onlyLater: z.ZodOptional<z.ZodArray<z.ZodString>>;
120
+ }, z.core.$strict>;
121
+ export type States = z.infer<typeof statesSchema>;
122
+ /** A move written as a bare state is a move with nothing asked first. */
123
+ export declare function moveTarget(move: StateMove): string;
124
+ interface StatesContext<C extends ColumnShape> {
125
+ index: TableIndex<C>;
126
+ /** The app's role keys, when the manifest declares roles (an add-on's shape has none to name). */
127
+ roles?: readonly string[] | undefined;
128
+ /** A column of this table decides "numbered": a gapless running number. */
129
+ numbered: boolean;
130
+ }
131
+ /** Everything wrong with one table's `states` against the manifest's tables. */
132
+ export declare function statesIssues<C extends ColumnShape>(table: string, states: States, ctx: StatesContext<C>, at: (...rest: (string | number)[]) => (string | number)[]): ReferenceIssue[];
133
+ export {};
134
+ //# sourceMappingURL=states.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"states.d.ts","sourceRoot":"","sources":["../src/states.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAsC,KAAK,WAAW,EAAE,KAAK,cAAc,EAAE,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AAKvH,oFAAoF;AACpF,eAAO,MAAM,oBAAoB;;;;;;;;;kBAc7B,CAAC;AACL,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;oBAiB1B,CAAC;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAExD,eAAO,MAAM,gBAAgB;;;;;kBAWzB,CAAC;AACL,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAqBd,CAAC;AACZ,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAElD,yEAAyE;AACzE,wBAAgB,UAAU,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAElD;AAED,UAAU,aAAa,CAAC,CAAC,SAAS,WAAW;IAC3C,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;IACrB,kGAAkG;IAClG,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IACtC,2EAA2E;IAC3E,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,gFAAgF;AAChF,wBAAgB,YAAY,CAAC,CAAC,SAAS,WAAW,EAChD,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,aAAa,CAAC,CAAC,CAAC,EACrB,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GACxD,cAAc,EAAE,CAyFlB"}
package/dist/states.js ADDED
@@ -0,0 +1,244 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ /**
3
+ * `table.states` — the life of a document, kept by Adminium for every writer.
4
+ *
5
+ * ```json
6
+ * "states": {
7
+ * "column": "status", "initial": "draft",
8
+ * "moves": {
9
+ * "draft": [{ "to": "sent", "requires": { "children": { "invoice_lines": 1 }, "where": [{ "column": "total", "gt": 0 }] } }, "void"],
10
+ * "sent": [{ "to": "void", "requires": { "where": [{ "column": "paid", "eq": 0 }] }, "roles": ["studio-manager"] }]
11
+ * },
12
+ * "lock": { "when": ["sent", "void"], "except": ["due_on", "ladder"] },
13
+ * "children": {
14
+ * "invoice_lines": { "via": "document_id", "lock": true },
15
+ * "payments": { "via": "document_id", "parentIn": ["sent"], "clearOnCreate": ["client_paid_at"] }
16
+ * },
17
+ * "noDelete": { "when": "numbered" },
18
+ * "onlyLater": ["valid_until"]
19
+ * }
20
+ * ```
21
+ *
22
+ * - `moves`: from each state, the states a write may move a row to. A move
23
+ * may ask for something first — child rows, a column's value — and may be
24
+ * kept for some of the app's roles. A move not listed is refused.
25
+ * - `lock`: while a row is in one of `when`, only `except` (and the state
26
+ * itself, through a move) may change. Adminium's own columns (totals,
27
+ * stamps) keep being written by Adminium.
28
+ * - `children`: child tables tied to this row's state. `lock` refuses their
29
+ * writes while the row is locked; `parentIn` allows them only while the row
30
+ * is in those states (payments on a sent invoice); `clearOnCreate` empties
31
+ * columns of this row when one of them is created (a recorded payment
32
+ * clears the client's "I've sent it").
33
+ * - `lockedWhenReferencedBy`: this row locks once a row of another table in
34
+ * one of the states points at it (a terms version once a proposal naming it
35
+ * is sent).
36
+ * - `noDelete`: rows in these states, or any row with a number
37
+ * (`"numbered"`), are never deleted — voided instead.
38
+ * - `onlyLater`: date columns that may move later and never earlier.
39
+ *
40
+ * Adding sample data and importing past records are history: they write any
41
+ * state their rows were in.
42
+ */
43
+ import { z } from 'zod';
44
+ import { refSchema, scalarSchema, valueFits } from './refs.js';
45
+ const stateName = z.string().min(1).max(64);
46
+ const roleKey = z.string().regex(/^[a-z][a-z0-9-]*$/, 'a role key');
47
+ /** A condition on the row itself, checked in the same statement that changes it. */
48
+ export const stateConditionSchema = z
49
+ .object({
50
+ column: refSchema,
51
+ eq: scalarSchema.optional(),
52
+ in: z.array(scalarSchema).min(1).max(32).optional(),
53
+ isNull: z.boolean().optional(),
54
+ gt: z.number().finite().optional(),
55
+ gte: z.number().finite().optional(),
56
+ lt: z.number().finite().optional(),
57
+ lte: z.number().finite().optional(),
58
+ })
59
+ .strict()
60
+ .refine((c) => [c.eq, c.in, c.isNull, c.gt, c.gte, c.lt, c.lte].filter((part) => part !== undefined).length === 1, {
61
+ message: 'a condition says one of eq, in, isNull, gt, gte, lt or lte',
62
+ });
63
+ export const stateMoveSchema = z.union([
64
+ stateName,
65
+ z
66
+ .object({
67
+ to: stateName,
68
+ /** What must be true first: at least n child rows of a table, and conditions on the row. */
69
+ requires: z
70
+ .object({
71
+ children: z.record(refSchema, z.number().int().min(1).max(1000)).optional(),
72
+ where: z.array(stateConditionSchema).min(1).max(8).optional(),
73
+ })
74
+ .strict()
75
+ .optional(),
76
+ /** Only people holding one of these app roles may make this move. */
77
+ roles: z.array(roleKey).min(1).max(8).optional(),
78
+ })
79
+ .strict(),
80
+ ]);
81
+ export const stateChildSchema = z
82
+ .object({
83
+ /** The child's foreign key to this row. */
84
+ via: refSchema,
85
+ lock: z.literal(true).optional(),
86
+ parentIn: z.array(stateName).min(1).max(16).optional(),
87
+ clearOnCreate: z.array(refSchema).min(1).max(8).optional(),
88
+ })
89
+ .strict()
90
+ .refine((c) => c.lock === undefined || c.parentIn === undefined, {
91
+ message: 'a child is locked with its parent, or writable only in some of its states — not both',
92
+ });
93
+ export const statesSchema = z
94
+ .object({
95
+ column: refSchema,
96
+ initial: stateName,
97
+ moves: z.record(stateName, z.array(stateMoveSchema).max(16)),
98
+ lock: z
99
+ .object({
100
+ when: z.array(stateName).min(1).max(16),
101
+ except: z.array(refSchema).max(32).optional(),
102
+ })
103
+ .strict()
104
+ .optional(),
105
+ children: z.record(refSchema, stateChildSchema).optional(),
106
+ lockedWhenReferencedBy: z
107
+ .array(z.object({ table: refSchema, via: refSchema, in: z.array(stateName).min(1).max(16) }).strict())
108
+ .min(1)
109
+ .max(4)
110
+ .optional(),
111
+ noDelete: z.object({ when: z.union([z.literal('numbered'), z.array(stateName).min(1).max(16)]) }).strict().optional(),
112
+ onlyLater: z.array(refSchema).min(1).max(8).optional(),
113
+ })
114
+ .strict();
115
+ /** A move written as a bare state is a move with nothing asked first. */
116
+ export function moveTarget(move) {
117
+ return typeof move === 'string' ? move : move.to;
118
+ }
119
+ /** Everything wrong with one table's `states` against the manifest's tables. */
120
+ export function statesIssues(table, states, ctx, at) {
121
+ const out = [];
122
+ const { index } = ctx;
123
+ const column = index.column(table, states.column);
124
+ let values = [];
125
+ if (column === undefined) {
126
+ out.push({ path: at('column'), message: `"${table}" has no column "${states.column}"` });
127
+ }
128
+ else if (column.type !== 'enum') {
129
+ out.push({ path: at('column'), message: `"${table}.${states.column}" is not an enum, so it cannot hold a state` });
130
+ }
131
+ else {
132
+ values = column.enum ?? [];
133
+ }
134
+ const isState = (value) => values.length === 0 || values.includes(value);
135
+ const known = (value, path) => {
136
+ if (!isState(value))
137
+ out.push({ path, message: `"${value}" is not a value of "${table}.${states.column}"` });
138
+ };
139
+ known(states.initial, at('initial'));
140
+ for (const [from, moves] of Object.entries(states.moves)) {
141
+ known(from, at('moves', from));
142
+ moves.forEach((move, m) => {
143
+ const to = moveTarget(move);
144
+ known(to, at('moves', from, m));
145
+ if (to === from)
146
+ out.push({ path: at('moves', from, m), message: 'a move goes to another state' });
147
+ if (typeof move === 'string')
148
+ return;
149
+ for (const child of Object.keys(move.requires?.children ?? {})) {
150
+ if (states.children?.[child] === undefined) {
151
+ out.push({ path: at('moves', from, m, 'requires', 'children', child), message: `"${child}" is not one of this table's children` });
152
+ }
153
+ }
154
+ (move.requires?.where ?? []).forEach((condition, w) => {
155
+ out.push(...conditionIssues(table, condition, index, at('moves', from, m, 'requires', 'where', w)));
156
+ });
157
+ for (const role of move.roles ?? []) {
158
+ if (ctx.roles !== undefined && !ctx.roles.includes(role)) {
159
+ out.push({ path: at('moves', from, m, 'roles'), message: `"${role}" is not one of the app's roles` });
160
+ }
161
+ }
162
+ });
163
+ }
164
+ if (states.lock !== undefined) {
165
+ states.lock.when.forEach((value, i) => known(value, at('lock', 'when', i)));
166
+ for (const ref of states.lock.except ?? []) {
167
+ if (index.column(table, ref) === undefined)
168
+ out.push({ path: at('lock', 'except'), message: `"${table}" has no column "${ref}"` });
169
+ if (ref === states.column)
170
+ out.push({ path: at('lock', 'except'), message: 'the state moves by its moves, never by the lock' });
171
+ }
172
+ }
173
+ for (const [child, rule] of Object.entries(states.children ?? {})) {
174
+ const here = (...rest) => at('children', child, ...rest);
175
+ if (index.table(child) === undefined) {
176
+ out.push({ path: here(), message: `"${child}" is not a table of this manifest` });
177
+ continue;
178
+ }
179
+ const via = index.column(child, rule.via);
180
+ if (via === undefined)
181
+ out.push({ path: here('via'), message: `"${child}" has no column "${rule.via}"` });
182
+ else if (via.type !== 'fk' || via.references !== table)
183
+ out.push({ path: here('via'), message: `"${child}.${rule.via}" does not point at "${table}"` });
184
+ if (rule.lock === true && states.lock === undefined)
185
+ out.push({ path: here('lock'), message: 'a child is locked with its parent, and the parent has no lock' });
186
+ (rule.parentIn ?? []).forEach((value, i) => known(value, here('parentIn', i)));
187
+ for (const ref of rule.clearOnCreate ?? []) {
188
+ const found = index.column(table, ref);
189
+ if (found === undefined)
190
+ out.push({ path: here('clearOnCreate'), message: `"${table}" has no column "${ref}"` });
191
+ else if (found.nullable !== true)
192
+ out.push({ path: here('clearOnCreate'), message: `"${table}.${ref}" is not nullable, so it cannot be emptied` });
193
+ }
194
+ if (rule.lock === undefined && rule.parentIn === undefined && rule.clearOnCreate === undefined) {
195
+ out.push({ path: here(), message: 'a child says lock, parentIn or clearOnCreate' });
196
+ }
197
+ }
198
+ (states.lockedWhenReferencedBy ?? []).forEach((ref, r) => {
199
+ const here = (...rest) => at('lockedWhenReferencedBy', r, ...rest);
200
+ if (index.table(ref.table) === undefined) {
201
+ out.push({ path: here('table'), message: `"${ref.table}" is not a table of this manifest` });
202
+ return;
203
+ }
204
+ const via = index.column(ref.table, ref.via);
205
+ if (via?.type !== 'fk' || via.references !== table)
206
+ out.push({ path: here('via'), message: `"${ref.table}.${ref.via}" does not point at "${table}"` });
207
+ if (states.lock === undefined)
208
+ out.push({ path: here(), message: 'a row locked by a reference needs a lock to say what stays open' });
209
+ });
210
+ if (states.noDelete !== undefined) {
211
+ if (states.noDelete.when === 'numbered') {
212
+ if (!ctx.numbered)
213
+ out.push({ path: at('noDelete', 'when'), message: '"numbered" needs a column numbered without gaps (sequence.gapless)' });
214
+ }
215
+ else {
216
+ states.noDelete.when.forEach((value, i) => known(value, at('noDelete', 'when', i)));
217
+ }
218
+ }
219
+ for (const ref of states.onlyLater ?? []) {
220
+ const found = index.column(table, ref);
221
+ if (found === undefined)
222
+ out.push({ path: at('onlyLater'), message: `"${table}" has no column "${ref}"` });
223
+ else if (found.type !== 'date' && found.type !== 'timestamptz')
224
+ out.push({ path: at('onlyLater'), message: `"${table}.${ref}" is not a date` });
225
+ }
226
+ return out;
227
+ }
228
+ function conditionIssues(table, condition, index, path) {
229
+ const found = index.column(table, condition.column);
230
+ if (found === undefined)
231
+ return [{ path, message: `"${table}" has no column "${condition.column}"` }];
232
+ const out = [];
233
+ const values = condition.eq !== undefined ? [condition.eq] : (condition.in ?? []);
234
+ for (const value of values) {
235
+ if (!valueFits(found, value))
236
+ out.push({ path, message: `${JSON.stringify(value)} is not a value of "${table}.${condition.column}"` });
237
+ }
238
+ const ordered = [condition.gt, condition.gte, condition.lt, condition.lte].some((part) => part !== undefined);
239
+ if (ordered && !['int', 'bigint', 'decimal', 'money', 'float'].includes(found.type)) {
240
+ out.push({ path, message: `"${table}.${condition.column}" is not a number, so it cannot be compared` });
241
+ }
242
+ return out;
243
+ }
244
+ //# sourceMappingURL=states.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"states.js","sourceRoot":"","sources":["../src/states.ts"],"names":[],"mappings":"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"}
@@ -28,13 +28,27 @@ export interface ValidateManifestOptions {
28
28
  /** The host app's table refs, so an add-on's `scopes` can be bounded. */
29
29
  hostTables?: readonly string[];
30
30
  }
31
+ /**
32
+ * A warning is advice, never a refusal: a manifest with warnings validates.
33
+ * Kept apart from `issues` on purpose — every app repo compares its vendored
34
+ * validator's issues with Adminium's, and a warning reported as an issue
35
+ * would fail them all on their next push.
36
+ */
31
37
  export type ValidateManifestResult = {
32
38
  ok: true;
33
39
  manifest: Manifest;
40
+ warnings: ManifestIssue[];
34
41
  } | {
35
42
  ok: false;
36
43
  issues: ManifestIssue[];
44
+ warnings: ManifestIssue[];
37
45
  };
46
+ /**
47
+ * Advice about an app that validates: a column with no default that is not
48
+ * nullable is NOT NULL once installed, so every insert must give it a value —
49
+ * a draft saved half-filled is refused. Every app round has hit this once.
50
+ */
51
+ export declare function manifestWarnings(manifest: Manifest): ManifestIssue[];
38
52
  /**
39
53
  * Validate an untrusted manifest document. Returns the typed manifest on
40
54
  * success, or every issue found (schema + policy) on failure — never throws.