@fieldia/core 0.9.2 → 0.11.0
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 +199 -0
- package/package.json +1 -1
- package/schema/page.schema.json +1837 -94
- package/src/index.d.mts +1 -0
- package/src/index.d.ts +1 -0
- package/src/index.js +4 -1
- package/src/index.js.map +1 -1
- package/src/index.mjs +1 -0
- package/src/index.mjs.map +1 -1
- package/src/lib/expression/evaluator.d.mts +6 -5
- package/src/lib/expression/evaluator.d.ts +6 -5
- package/src/lib/expression/evaluator.js +37 -22
- package/src/lib/expression/evaluator.js.map +1 -1
- package/src/lib/expression/evaluator.mjs +32 -18
- package/src/lib/expression/evaluator.mjs.map +1 -1
- package/src/lib/expression/expression.d.mts +21 -0
- package/src/lib/expression/expression.d.ts +21 -0
- package/src/lib/expression/expression.js +29 -0
- package/src/lib/expression/expression.js.map +1 -0
- package/src/lib/expression/expression.mjs +26 -0
- package/src/lib/expression/expression.mjs.map +1 -0
- package/src/lib/expression/extractFieldNames.js +6 -1
- package/src/lib/expression/extractFieldNames.js.map +1 -1
- package/src/lib/expression/extractFieldNames.mjs +6 -1
- package/src/lib/expression/extractFieldNames.mjs.map +1 -1
- package/src/lib/expression/functions.d.mts +35 -0
- package/src/lib/expression/functions.d.ts +35 -0
- package/src/lib/expression/functions.js +129 -0
- package/src/lib/expression/functions.js.map +1 -0
- package/src/lib/expression/functions.mjs +124 -0
- package/src/lib/expression/functions.mjs.map +1 -0
- package/src/lib/expression/modifier.d.mts +3 -1
- package/src/lib/expression/modifier.d.ts +3 -1
- package/src/lib/expression/modifier.js +4 -27
- package/src/lib/expression/modifier.js.map +1 -1
- package/src/lib/expression/modifier.mjs +3 -26
- package/src/lib/expression/modifier.mjs.map +1 -1
- package/src/lib/expression/operations.d.mts +25 -0
- package/src/lib/expression/operations.d.ts +25 -0
- package/src/lib/expression/operations.js +81 -0
- package/src/lib/expression/operations.js.map +1 -0
- package/src/lib/expression/operations.mjs +72 -0
- package/src/lib/expression/operations.mjs.map +1 -0
- package/src/lib/expression/order.d.mts +11 -0
- package/src/lib/expression/order.d.ts +11 -0
- package/src/lib/expression/order.js +36 -0
- package/src/lib/expression/order.js.map +1 -0
- package/src/lib/expression/order.mjs +33 -0
- package/src/lib/expression/order.mjs.map +1 -0
- package/src/lib/expression/parser.d.mts +34 -4
- package/src/lib/expression/parser.d.ts +34 -4
- package/src/lib/expression/parser.js +72 -6
- package/src/lib/expression/parser.js.map +1 -1
- package/src/lib/expression/parser.mjs +72 -6
- package/src/lib/expression/parser.mjs.map +1 -1
- package/src/lib/expression/reads.d.mts +8 -0
- package/src/lib/expression/reads.d.ts +8 -0
- package/src/lib/expression/reads.js +48 -0
- package/src/lib/expression/reads.js.map +1 -0
- package/src/lib/expression/reads.mjs +44 -0
- package/src/lib/expression/reads.mjs.map +1 -0
- package/src/lib/expression/tokenizer.d.mts +7 -6
- package/src/lib/expression/tokenizer.d.ts +7 -6
- package/src/lib/expression/tokenizer.js +28 -18
- package/src/lib/expression/tokenizer.js.map +1 -1
- package/src/lib/expression/tokenizer.mjs +28 -18
- package/src/lib/expression/tokenizer.mjs.map +1 -1
- package/src/lib/format/actions.d.mts +692 -0
- package/src/lib/format/actions.d.ts +692 -0
- package/src/lib/format/actions.js +53 -0
- package/src/lib/format/actions.js.map +1 -0
- package/src/lib/format/actions.mjs +50 -0
- package/src/lib/format/actions.mjs.map +1 -0
- package/src/lib/format/field.d.mts +686 -5
- package/src/lib/format/field.d.ts +686 -5
- package/src/lib/format/field.js +117 -13
- package/src/lib/format/field.js.map +1 -1
- package/src/lib/format/field.mjs +116 -12
- package/src/lib/format/field.mjs.map +1 -1
- package/src/lib/format/layout.d.mts +1130 -22
- package/src/lib/format/layout.d.ts +1130 -22
- package/src/lib/format/layout.js +67 -5
- package/src/lib/format/layout.js.map +1 -1
- package/src/lib/format/layout.mjs +66 -4
- package/src/lib/format/layout.mjs.map +1 -1
- package/src/lib/format/layout.types.d.mts +2 -1
- package/src/lib/format/layout.types.d.ts +2 -1
- package/src/lib/format/names.d.mts +1 -1
- package/src/lib/format/names.d.ts +1 -1
- package/src/lib/format/names.js +1 -0
- package/src/lib/format/names.js.map +1 -1
- package/src/lib/format/names.mjs +1 -0
- package/src/lib/format/names.mjs.map +1 -1
- package/src/lib/format/page.d.mts +1007 -7
- package/src/lib/format/page.d.ts +1007 -7
- package/src/lib/format/page.js +28 -0
- package/src/lib/format/page.js.map +1 -1
- package/src/lib/format/page.mjs +28 -0
- package/src/lib/format/page.mjs.map +1 -1
- package/src/lib/format/part-look.d.mts +36 -0
- package/src/lib/format/part-look.d.ts +36 -0
- package/src/lib/format/part-look.js +23 -0
- package/src/lib/format/part-look.js.map +1 -0
- package/src/lib/format/part-look.mjs +20 -0
- package/src/lib/format/part-look.mjs.map +1 -0
- package/src/lib/format/references.d.mts +33 -1
- package/src/lib/format/references.d.ts +33 -1
- package/src/lib/format/references.js +227 -10
- package/src/lib/format/references.js.map +1 -1
- package/src/lib/format/references.mjs +227 -10
- package/src/lib/format/references.mjs.map +1 -1
- package/src/lib/format/translate.d.mts +20 -0
- package/src/lib/format/translate.d.ts +20 -0
- package/src/lib/format/translate.js +79 -21
- package/src/lib/format/translate.js.map +1 -1
- package/src/lib/format/translate.mjs +76 -21
- package/src/lib/format/translate.mjs.map +1 -1
- package/src/lib/record/check.d.mts +19 -1
- package/src/lib/record/check.d.ts +19 -1
- package/src/lib/record/check.js +84 -21
- package/src/lib/record/check.js.map +1 -1
- package/src/lib/record/check.mjs +82 -21
- package/src/lib/record/check.mjs.map +1 -1
- package/src/lib/record/compute.d.mts +24 -0
- package/src/lib/record/compute.d.ts +24 -0
- package/src/lib/record/compute.js +107 -0
- package/src/lib/record/compute.js.map +1 -0
- package/src/lib/record/compute.mjs +103 -0
- package/src/lib/record/compute.mjs.map +1 -0
- package/src/lib/record/data-source.d.mts +14 -2
- package/src/lib/record/data-source.d.ts +14 -2
- package/src/lib/record/data-source.js.map +1 -1
- package/src/lib/record/data-source.mjs.map +1 -1
- package/src/lib/record/env.d.mts +9 -0
- package/src/lib/record/env.d.ts +9 -0
- package/src/lib/record/env.js +28 -0
- package/src/lib/record/env.js.map +1 -0
- package/src/lib/record/env.mjs +25 -0
- package/src/lib/record/env.mjs.map +1 -0
- package/src/lib/record/form.d.mts +110 -18
- package/src/lib/record/form.d.ts +110 -18
- package/src/lib/record/form.js +497 -72
- package/src/lib/record/form.js.map +1 -1
- package/src/lib/record/form.mjs +497 -72
- package/src/lib/record/form.mjs.map +1 -1
- package/src/lib/record/inputs.d.mts +5 -0
- package/src/lib/record/inputs.d.ts +5 -0
- package/src/lib/record/inputs.js +47 -0
- package/src/lib/record/inputs.js.map +1 -0
- package/src/lib/record/inputs.mjs +44 -0
- package/src/lib/record/inputs.mjs.map +1 -0
- package/src/lib/record/limits.d.mts +13 -0
- package/src/lib/record/limits.d.ts +13 -0
- package/src/lib/record/limits.js +45 -0
- package/src/lib/record/limits.js.map +1 -0
- package/src/lib/record/limits.mjs +41 -0
- package/src/lib/record/limits.mjs.map +1 -0
- package/src/lib/record/locales/all.d.mts +7 -0
- package/src/lib/record/locales/all.d.ts +7 -0
- package/src/lib/record/locales/all.js +13 -0
- package/src/lib/record/locales/all.js.map +1 -0
- package/src/lib/record/locales/all.mjs +10 -0
- package/src/lib/record/locales/all.mjs.map +1 -0
- package/src/lib/record/locales/ar.d.mts +3 -0
- package/src/lib/record/locales/ar.d.ts +3 -0
- package/src/lib/record/locales/ar.js +55 -0
- package/src/lib/record/locales/ar.js.map +1 -0
- package/src/lib/record/locales/ar.mjs +52 -0
- package/src/lib/record/locales/ar.mjs.map +1 -0
- package/src/lib/record/locales/de.d.mts +3 -0
- package/src/lib/record/locales/de.d.ts +3 -0
- package/src/lib/record/locales/de.js +55 -0
- package/src/lib/record/locales/de.js.map +1 -0
- package/src/lib/record/locales/de.mjs +52 -0
- package/src/lib/record/locales/de.mjs.map +1 -0
- package/src/lib/record/locales/fr.d.mts +3 -0
- package/src/lib/record/locales/fr.d.ts +3 -0
- package/src/lib/record/locales/fr.js +55 -0
- package/src/lib/record/locales/fr.js.map +1 -0
- package/src/lib/record/locales/fr.mjs +52 -0
- package/src/lib/record/locales/fr.mjs.map +1 -0
- package/src/lib/record/memory-data-source.d.mts +3 -0
- package/src/lib/record/memory-data-source.d.ts +3 -0
- package/src/lib/record/memory-data-source.js +8 -0
- package/src/lib/record/memory-data-source.js.map +1 -1
- package/src/lib/record/memory-data-source.mjs +8 -0
- package/src/lib/record/memory-data-source.mjs.map +1 -1
- package/src/lib/record/messages.d.mts +46 -0
- package/src/lib/record/messages.d.ts +46 -0
- package/src/lib/record/messages.js +58 -101
- package/src/lib/record/messages.js.map +1 -1
- package/src/lib/record/messages.mjs +58 -101
- package/src/lib/record/messages.mjs.map +1 -1
- package/src/lib/record/rules.d.mts +33 -0
- package/src/lib/record/rules.d.ts +33 -0
- package/src/lib/record/rules.js +83 -0
- package/src/lib/record/rules.js.map +1 -0
- package/src/lib/record/rules.mjs +79 -0
- package/src/lib/record/rules.mjs.map +1 -0
- package/src/lib/record/run.d.mts +169 -0
- package/src/lib/record/run.d.ts +169 -0
- package/src/lib/record/run.js +350 -0
- package/src/lib/record/run.js.map +1 -0
- package/src/lib/record/run.mjs +345 -0
- package/src/lib/record/run.mjs.map +1 -0
- package/src/lib/record/score.d.mts +16 -0
- package/src/lib/record/score.d.ts +16 -0
- package/src/lib/record/score.js +35 -0
- package/src/lib/record/score.js.map +1 -0
- package/src/lib/record/score.mjs +32 -0
- package/src/lib/record/score.mjs.map +1 -0
- package/src/lib/record/set-when.d.mts +24 -0
- package/src/lib/record/set-when.d.ts +24 -0
- package/src/lib/record/set-when.js +68 -0
- package/src/lib/record/set-when.js.map +1 -0
- package/src/lib/record/set-when.mjs +65 -0
- package/src/lib/record/set-when.mjs.map +1 -0
- package/src/lib/record/structures.d.mts +14 -0
- package/src/lib/record/structures.d.ts +14 -0
- package/src/lib/record/structures.js +32 -0
- package/src/lib/record/structures.js.map +1 -0
- package/src/lib/record/structures.mjs +28 -0
- package/src/lib/record/structures.mjs.map +1 -0
- package/src/lib/record/values.d.mts +10 -5
- package/src/lib/record/values.d.ts +10 -5
- package/src/lib/record/values.js +20 -6
- package/src/lib/record/values.js.map +1 -1
- package/src/lib/record/values.mjs +19 -6
- package/src/lib/record/values.mjs.map +1 -1
- package/src/runtime.d.mts +13 -7
- package/src/runtime.d.ts +13 -7
- package/src/runtime.js +14 -1
- package/src/runtime.js.map +1 -1
- package/src/runtime.mjs +6 -2
- package/src/runtime.mjs.map +1 -1
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Field, LineField } from '../format/field.mjs';
|
|
2
|
+
import type { Page } from '../format/page.mjs';
|
|
3
|
+
import { type Value, type Values } from './values.mjs';
|
|
4
|
+
/**
|
|
5
|
+
* Values worked out from others: a field's `compute`. A page's own fields are
|
|
6
|
+
* worked out in the order they read each other; a one2many's line fields from
|
|
7
|
+
* the fields of the same line, before the page's own, so a page's sum reads
|
|
8
|
+
* lines already worked out. What does not change keeps its identity, so a
|
|
9
|
+
* form redraws only what did.
|
|
10
|
+
*/
|
|
11
|
+
export interface Computed {
|
|
12
|
+
/** The values with every worked-out field brought up to date. */
|
|
13
|
+
apply(values: Values): Values;
|
|
14
|
+
/** One line of a one2many with its worked-out fields brought up to date. */
|
|
15
|
+
line(field: string, values: Values): Values;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* A worked-out value as its field holds it: a whole number rounded, a number
|
|
19
|
+
* to the field's decimals, a number as text in a text field, yes or no by
|
|
20
|
+
* Python's idea of true, and null for what the field cannot hold.
|
|
21
|
+
*/
|
|
22
|
+
export declare function fitTo(def: Field | LineField, value: unknown): Value;
|
|
23
|
+
/** Read every `compute` of a page once. `today` is the day `today()` gives. */
|
|
24
|
+
export declare function compileComputed(page: Page, today: () => string): Computed;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Field, LineField } from '../format/field';
|
|
2
|
+
import type { Page } from '../format/page';
|
|
3
|
+
import { type Value, type Values } from './values';
|
|
4
|
+
/**
|
|
5
|
+
* Values worked out from others: a field's `compute`. A page's own fields are
|
|
6
|
+
* worked out in the order they read each other; a one2many's line fields from
|
|
7
|
+
* the fields of the same line, before the page's own, so a page's sum reads
|
|
8
|
+
* lines already worked out. What does not change keeps its identity, so a
|
|
9
|
+
* form redraws only what did.
|
|
10
|
+
*/
|
|
11
|
+
export interface Computed {
|
|
12
|
+
/** The values with every worked-out field brought up to date. */
|
|
13
|
+
apply(values: Values): Values;
|
|
14
|
+
/** One line of a one2many with its worked-out fields brought up to date. */
|
|
15
|
+
line(field: string, values: Values): Values;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* A worked-out value as its field holds it: a whole number rounded, a number
|
|
19
|
+
* to the field's decimals, a number as text in a text field, yes or no by
|
|
20
|
+
* Python's idea of true, and null for what the field cannot hold.
|
|
21
|
+
*/
|
|
22
|
+
export declare function fitTo(def: Field | LineField, value: unknown): Value;
|
|
23
|
+
/** Read every `compute` of a page once. `today` is the day `today()` gives. */
|
|
24
|
+
export declare function compileComputed(page: Page, today: () => string): Computed;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.fitTo = fitTo;
|
|
4
|
+
exports.compileComputed = compileComputed;
|
|
5
|
+
const expression_1 = require("../expression/expression");
|
|
6
|
+
const operations_1 = require("../expression/operations");
|
|
7
|
+
const order_1 = require("../expression/order");
|
|
8
|
+
const env_1 = require("./env");
|
|
9
|
+
const values_1 = require("./values");
|
|
10
|
+
/** The worked-out fields among `fields`, each read once, in the order to work them out. */
|
|
11
|
+
function steps(fields) {
|
|
12
|
+
const compiled = new Map();
|
|
13
|
+
for (const [name, def] of Object.entries(fields))
|
|
14
|
+
if (def.compute !== undefined)
|
|
15
|
+
compiled.set(name, (0, expression_1.compileExpression)(def.compute));
|
|
16
|
+
const { order } = (0, order_1.dependencyOrder)(new Map([...compiled].map(([name, expression]) => [name, expression.fields])));
|
|
17
|
+
return order.map((name) => [name, compiled.get(name), fields[name]]);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* A worked-out value as its field holds it: a whole number rounded, a number
|
|
21
|
+
* to the field's decimals, a number as text in a text field, yes or no by
|
|
22
|
+
* Python's idea of true, and null for what the field cannot hold.
|
|
23
|
+
*/
|
|
24
|
+
function fitTo(def, value) {
|
|
25
|
+
if (def.type === 'boolean')
|
|
26
|
+
return (0, operations_1.truthy)(value);
|
|
27
|
+
if (value === null || value === undefined)
|
|
28
|
+
return null;
|
|
29
|
+
switch (def.type) {
|
|
30
|
+
case 'integer':
|
|
31
|
+
return (0, operations_1.isNumber)(value) ? (0, operations_1.roundTo)(value, 0) : null;
|
|
32
|
+
case 'float':
|
|
33
|
+
case 'monetary':
|
|
34
|
+
if (!(0, operations_1.isNumber)(value))
|
|
35
|
+
return null;
|
|
36
|
+
return def.digits ? (0, operations_1.roundTo)(value, def.digits[1]) : value;
|
|
37
|
+
case 'char':
|
|
38
|
+
case 'text':
|
|
39
|
+
case 'html':
|
|
40
|
+
return typeof value === 'string' ? value : (0, operations_1.isNumber)(value) ? String(value) : null;
|
|
41
|
+
case 'date':
|
|
42
|
+
case 'datetime':
|
|
43
|
+
return typeof value === 'string' ? value : null;
|
|
44
|
+
default:
|
|
45
|
+
return value;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/** Read every `compute` of a page once. `today` is the day `today()` gives. */
|
|
49
|
+
function compileComputed(page, today) {
|
|
50
|
+
const own = steps(page.fields);
|
|
51
|
+
const lineSteps = new Map();
|
|
52
|
+
for (const [name, def] of Object.entries(page.fields)) {
|
|
53
|
+
if (def.type !== 'one2many')
|
|
54
|
+
continue;
|
|
55
|
+
const found = steps(def.fields);
|
|
56
|
+
if (found.length)
|
|
57
|
+
lineSteps.set(name, { def, steps: found });
|
|
58
|
+
}
|
|
59
|
+
// Lines hold no lines of their own: inside one, only today() needs the env.
|
|
60
|
+
const lineEnv = { today };
|
|
61
|
+
/** Work out the steps on these values, writing each change into a copy. */
|
|
62
|
+
function run(values, list, fields, env) {
|
|
63
|
+
let next = values;
|
|
64
|
+
const context = (0, values_1.expressionContext)(values, fields);
|
|
65
|
+
for (const [name, expression, def] of list) {
|
|
66
|
+
const value = fitTo(def, expression.evaluate(context, env));
|
|
67
|
+
if ((0, values_1.sameValue)(value, next[name]))
|
|
68
|
+
continue;
|
|
69
|
+
next = { ...next, [name]: value };
|
|
70
|
+
// What comes after reads this value as it is now.
|
|
71
|
+
Object.assign(context, (0, values_1.expressionContext)({ [name]: value }, fields));
|
|
72
|
+
}
|
|
73
|
+
return next;
|
|
74
|
+
}
|
|
75
|
+
function line(field, values) {
|
|
76
|
+
const found = lineSteps.get(field);
|
|
77
|
+
// A section or a note has nothing to work out.
|
|
78
|
+
if (!found || (0, values_1.lineKind)(found.def, values) !== null)
|
|
79
|
+
return values;
|
|
80
|
+
return run(values, found.steps, found.def.fields, lineEnv);
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
line,
|
|
84
|
+
apply(values) {
|
|
85
|
+
let next = values;
|
|
86
|
+
for (const field of lineSteps.keys()) {
|
|
87
|
+
const current = next[field];
|
|
88
|
+
if (!Array.isArray(current))
|
|
89
|
+
continue;
|
|
90
|
+
let changed = false;
|
|
91
|
+
const updated = current.map((l) => {
|
|
92
|
+
const worked = line(field, l.values);
|
|
93
|
+
if (worked === l.values)
|
|
94
|
+
return l;
|
|
95
|
+
changed = true;
|
|
96
|
+
return { ...l, values: worked };
|
|
97
|
+
});
|
|
98
|
+
if (changed)
|
|
99
|
+
next = { ...next, [field]: updated };
|
|
100
|
+
}
|
|
101
|
+
if (!own.length)
|
|
102
|
+
return next;
|
|
103
|
+
return run(next, own, page.fields, (0, env_1.expressionEnv)(next, page.fields, today));
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=compute.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compute.js","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/record/compute.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { compileExpression } from '../expression/expression.mjs';
|
|
2
|
+
import { isNumber, roundTo, truthy } from '../expression/operations.mjs';
|
|
3
|
+
import { dependencyOrder } from '../expression/order.mjs';
|
|
4
|
+
import { expressionEnv } from './env.mjs';
|
|
5
|
+
import { expressionContext, lineKind, sameValue } from './values.mjs';
|
|
6
|
+
/** The worked-out fields among `fields`, each read once, in the order to work them out. */
|
|
7
|
+
function steps(fields) {
|
|
8
|
+
const compiled = new Map();
|
|
9
|
+
for (const [name, def] of Object.entries(fields))
|
|
10
|
+
if (def.compute !== undefined)
|
|
11
|
+
compiled.set(name, compileExpression(def.compute));
|
|
12
|
+
const { order } = dependencyOrder(new Map([...compiled].map(([name, expression]) => [name, expression.fields])));
|
|
13
|
+
return order.map((name) => [name, compiled.get(name), fields[name]]);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* A worked-out value as its field holds it: a whole number rounded, a number
|
|
17
|
+
* to the field's decimals, a number as text in a text field, yes or no by
|
|
18
|
+
* Python's idea of true, and null for what the field cannot hold.
|
|
19
|
+
*/
|
|
20
|
+
export function fitTo(def, value) {
|
|
21
|
+
if (def.type === 'boolean')
|
|
22
|
+
return truthy(value);
|
|
23
|
+
if (value === null || value === undefined)
|
|
24
|
+
return null;
|
|
25
|
+
switch (def.type) {
|
|
26
|
+
case 'integer':
|
|
27
|
+
return isNumber(value) ? roundTo(value, 0) : null;
|
|
28
|
+
case 'float':
|
|
29
|
+
case 'monetary':
|
|
30
|
+
if (!isNumber(value))
|
|
31
|
+
return null;
|
|
32
|
+
return def.digits ? roundTo(value, def.digits[1]) : value;
|
|
33
|
+
case 'char':
|
|
34
|
+
case 'text':
|
|
35
|
+
case 'html':
|
|
36
|
+
return typeof value === 'string' ? value : isNumber(value) ? String(value) : null;
|
|
37
|
+
case 'date':
|
|
38
|
+
case 'datetime':
|
|
39
|
+
return typeof value === 'string' ? value : null;
|
|
40
|
+
default:
|
|
41
|
+
return value;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/** Read every `compute` of a page once. `today` is the day `today()` gives. */
|
|
45
|
+
export function compileComputed(page, today) {
|
|
46
|
+
const own = steps(page.fields);
|
|
47
|
+
const lineSteps = new Map();
|
|
48
|
+
for (const [name, def] of Object.entries(page.fields)) {
|
|
49
|
+
if (def.type !== 'one2many')
|
|
50
|
+
continue;
|
|
51
|
+
const found = steps(def.fields);
|
|
52
|
+
if (found.length)
|
|
53
|
+
lineSteps.set(name, { def, steps: found });
|
|
54
|
+
}
|
|
55
|
+
// Lines hold no lines of their own: inside one, only today() needs the env.
|
|
56
|
+
const lineEnv = { today };
|
|
57
|
+
/** Work out the steps on these values, writing each change into a copy. */
|
|
58
|
+
function run(values, list, fields, env) {
|
|
59
|
+
let next = values;
|
|
60
|
+
const context = expressionContext(values, fields);
|
|
61
|
+
for (const [name, expression, def] of list) {
|
|
62
|
+
const value = fitTo(def, expression.evaluate(context, env));
|
|
63
|
+
if (sameValue(value, next[name]))
|
|
64
|
+
continue;
|
|
65
|
+
next = { ...next, [name]: value };
|
|
66
|
+
// What comes after reads this value as it is now.
|
|
67
|
+
Object.assign(context, expressionContext({ [name]: value }, fields));
|
|
68
|
+
}
|
|
69
|
+
return next;
|
|
70
|
+
}
|
|
71
|
+
function line(field, values) {
|
|
72
|
+
const found = lineSteps.get(field);
|
|
73
|
+
// A section or a note has nothing to work out.
|
|
74
|
+
if (!found || lineKind(found.def, values) !== null)
|
|
75
|
+
return values;
|
|
76
|
+
return run(values, found.steps, found.def.fields, lineEnv);
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
line,
|
|
80
|
+
apply(values) {
|
|
81
|
+
let next = values;
|
|
82
|
+
for (const field of lineSteps.keys()) {
|
|
83
|
+
const current = next[field];
|
|
84
|
+
if (!Array.isArray(current))
|
|
85
|
+
continue;
|
|
86
|
+
let changed = false;
|
|
87
|
+
const updated = current.map((l) => {
|
|
88
|
+
const worked = line(field, l.values);
|
|
89
|
+
if (worked === l.values)
|
|
90
|
+
return l;
|
|
91
|
+
changed = true;
|
|
92
|
+
return { ...l, values: worked };
|
|
93
|
+
});
|
|
94
|
+
if (changed)
|
|
95
|
+
next = { ...next, [field]: updated };
|
|
96
|
+
}
|
|
97
|
+
if (!own.length)
|
|
98
|
+
return next;
|
|
99
|
+
return run(next, own, page.fields, expressionEnv(next, page.fields, today));
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=compute.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compute.mjs","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/record/compute.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type { FilterCondition, Fields } from '../format/field.mjs';
|
|
1
|
+
import type { FilterCondition, Fields, Option } from '../format/field.mjs';
|
|
2
2
|
import type { JsonValue } from '../format/json.mjs';
|
|
3
3
|
import type { RecordId, RelatedRecord, Values } from './values.mjs';
|
|
4
|
+
import type { RunStop } from './run.mjs';
|
|
4
5
|
/**
|
|
5
6
|
* How Fieldia reaches data. Fieldia knows no backend: an app implements this
|
|
6
7
|
* interface for its own (a Flectra adapter, a REST client, a survey store),
|
|
@@ -23,6 +24,14 @@ export interface DataSource {
|
|
|
23
24
|
list?(request: ListRequest): Promise<ListResult>;
|
|
24
25
|
/** How many records fall under each value of a field, for a list's Group By. */
|
|
25
26
|
groups?(request: GroupRequest): Promise<Group[]>;
|
|
27
|
+
/** The choices of one of the app's lists, for a selection with `optionsFrom`. */
|
|
28
|
+
options?(request: OptionsRequest): Promise<Option[]>;
|
|
29
|
+
}
|
|
30
|
+
export interface OptionsRequest {
|
|
31
|
+
/** The list's name, from the field's `optionsFrom.list`. */
|
|
32
|
+
list: string;
|
|
33
|
+
/** Every value of the form, for a list that changes with another field (`dependsOn`). */
|
|
34
|
+
values: Values;
|
|
26
35
|
}
|
|
27
36
|
export interface CreateRequest {
|
|
28
37
|
model: string;
|
|
@@ -167,10 +176,13 @@ export type LinkOp = {
|
|
|
167
176
|
* `network` in a banner with Retry, and `other` beside Save with Retry.
|
|
168
177
|
*/
|
|
169
178
|
export interface SaveProblem {
|
|
170
|
-
|
|
179
|
+
/** `stopped`: a step of the page's `beforeSave` stopped it, with `reason` — no data source was asked. */
|
|
180
|
+
kind: 'fields' | 'rule' | 'network' | 'other' | 'stopped';
|
|
171
181
|
message: string;
|
|
172
182
|
/** For `fields`: a message for each field, by name. */
|
|
173
183
|
fields?: Record<string, string>;
|
|
184
|
+
/** For `stopped`: why the step stopped. */
|
|
185
|
+
reason?: RunStop;
|
|
174
186
|
}
|
|
175
187
|
/** An error for a data source's save to throw when the backend refuses it. */
|
|
176
188
|
export declare function saveRefused(problem: SaveProblem): Error & {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type { FilterCondition, Fields } from '../format/field';
|
|
1
|
+
import type { FilterCondition, Fields, Option } from '../format/field';
|
|
2
2
|
import type { JsonValue } from '../format/json';
|
|
3
3
|
import type { RecordId, RelatedRecord, Values } from './values';
|
|
4
|
+
import type { RunStop } from './run';
|
|
4
5
|
/**
|
|
5
6
|
* How Fieldia reaches data. Fieldia knows no backend: an app implements this
|
|
6
7
|
* interface for its own (a Flectra adapter, a REST client, a survey store),
|
|
@@ -23,6 +24,14 @@ export interface DataSource {
|
|
|
23
24
|
list?(request: ListRequest): Promise<ListResult>;
|
|
24
25
|
/** How many records fall under each value of a field, for a list's Group By. */
|
|
25
26
|
groups?(request: GroupRequest): Promise<Group[]>;
|
|
27
|
+
/** The choices of one of the app's lists, for a selection with `optionsFrom`. */
|
|
28
|
+
options?(request: OptionsRequest): Promise<Option[]>;
|
|
29
|
+
}
|
|
30
|
+
export interface OptionsRequest {
|
|
31
|
+
/** The list's name, from the field's `optionsFrom.list`. */
|
|
32
|
+
list: string;
|
|
33
|
+
/** Every value of the form, for a list that changes with another field (`dependsOn`). */
|
|
34
|
+
values: Values;
|
|
26
35
|
}
|
|
27
36
|
export interface CreateRequest {
|
|
28
37
|
model: string;
|
|
@@ -167,10 +176,13 @@ export type LinkOp = {
|
|
|
167
176
|
* `network` in a banner with Retry, and `other` beside Save with Retry.
|
|
168
177
|
*/
|
|
169
178
|
export interface SaveProblem {
|
|
170
|
-
|
|
179
|
+
/** `stopped`: a step of the page's `beforeSave` stopped it, with `reason` — no data source was asked. */
|
|
180
|
+
kind: 'fields' | 'rule' | 'network' | 'other' | 'stopped';
|
|
171
181
|
message: string;
|
|
172
182
|
/** For `fields`: a message for each field, by name. */
|
|
173
183
|
fields?: Record<string, string>;
|
|
184
|
+
/** For `stopped`: why the step stopped. */
|
|
185
|
+
reason?: RunStop;
|
|
174
186
|
}
|
|
175
187
|
/** An error for a data source's save to throw when the backend refuses it. */
|
|
176
188
|
export declare function saveRefused(problem: SaveProblem): Error & {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-source.js","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/record/data-source.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"data-source.js","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/record/data-source.ts"],"names":[],"mappings":";;AA0LA,kCAEC;AAGD,sCAMC;AAZD,8EAA8E;AAC9E,SAAgB,WAAW,CAAC,OAAoB;IAC9C,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;AAChE,CAAC;AAED,wGAAwG;AACxG,SAAgB,aAAa,CAAC,KAAc;IAC1C,MAAM,OAAO,GAAI,KAA0C,EAAE,OAAO,CAAC;IACrE,IAAI,OAAO,IAAI,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAC;IAChE,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,IAAI,KAAK,YAAY,SAAS,IAAI,4BAA4B,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC;IAClH,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AACpC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-source.mjs","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/record/data-source.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"data-source.mjs","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/record/data-source.ts"],"names":[],"mappings":"AAyLA,8EAA8E;AAC9E,MAAM,UAAU,WAAW,CAAC,OAAoB;IAC9C,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;AAChE,CAAC;AAED,wGAAwG;AACxG,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,MAAM,OAAO,GAAI,KAA0C,EAAE,OAAO,CAAC;IACrE,IAAI,OAAO,IAAI,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAC;IAChE,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,IAAI,KAAK,YAAY,SAAS,IAAI,4BAA4B,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC;IAClH,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AACpC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Field, LineField } from '../format/field.mjs';
|
|
2
|
+
import type { ExpressionEnv } from '../expression/functions.mjs';
|
|
3
|
+
import { type Values } from './values.mjs';
|
|
4
|
+
/**
|
|
5
|
+
* What an expression on a record is worked out with besides its values: the
|
|
6
|
+
* rows of each one2many for `sum` and `count` — the items, not the sections
|
|
7
|
+
* and notes between them — and today's date for `today()`.
|
|
8
|
+
*/
|
|
9
|
+
export declare function expressionEnv(values: Values, fields: Record<string, Field | LineField>, today: () => string): ExpressionEnv;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Field, LineField } from '../format/field';
|
|
2
|
+
import type { ExpressionEnv } from '../expression/functions';
|
|
3
|
+
import { type Values } from './values';
|
|
4
|
+
/**
|
|
5
|
+
* What an expression on a record is worked out with besides its values: the
|
|
6
|
+
* rows of each one2many for `sum` and `count` — the items, not the sections
|
|
7
|
+
* and notes between them — and today's date for `today()`.
|
|
8
|
+
*/
|
|
9
|
+
export declare function expressionEnv(values: Values, fields: Record<string, Field | LineField>, today: () => string): ExpressionEnv;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.expressionEnv = expressionEnv;
|
|
4
|
+
const values_1 = require("./values");
|
|
5
|
+
/**
|
|
6
|
+
* What an expression on a record is worked out with besides its values: the
|
|
7
|
+
* rows of each one2many for `sum` and `count` — the items, not the sections
|
|
8
|
+
* and notes between them — and today's date for `today()`.
|
|
9
|
+
*/
|
|
10
|
+
function expressionEnv(values, fields, today) {
|
|
11
|
+
const rows = new Map();
|
|
12
|
+
return {
|
|
13
|
+
today,
|
|
14
|
+
lines(name) {
|
|
15
|
+
const def = fields[name];
|
|
16
|
+
if (def?.type !== 'one2many')
|
|
17
|
+
return undefined;
|
|
18
|
+
let found = rows.get(name);
|
|
19
|
+
if (!found) {
|
|
20
|
+
const items = (values[name] ?? []).filter((line) => (0, values_1.lineKind)(def, line.values) === null);
|
|
21
|
+
found = items.map((line) => (0, values_1.expressionContext)(line.values, def.fields));
|
|
22
|
+
rows.set(name, found);
|
|
23
|
+
}
|
|
24
|
+
return found;
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=env.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/record/env.ts"],"names":[],"mappings":";;AASA,sCAgBC;AAvBD,qCAA+E;AAE/E;;;;GAIG;AACH,SAAgB,aAAa,CAAC,MAAc,EAAE,MAAyC,EAAE,KAAmB;IAC1G,MAAM,IAAI,GAAG,IAAI,GAAG,EAAqC,CAAC;IAC1D,OAAO;QACL,KAAK;QACL,KAAK,CAAC,IAAI;YACR,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;YACzB,IAAI,GAAG,EAAE,IAAI,KAAK,UAAU;gBAAE,OAAO,SAAS,CAAC;YAC/C,IAAI,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC3B,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,MAAM,KAAK,GAAG,CAAE,MAAM,CAAC,IAAI,CAAmB,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAA,iBAAQ,EAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,CAAC;gBAC5G,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAA,0BAAiB,EAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;gBACxE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YACxB,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { expressionContext, lineKind } from './values.mjs';
|
|
2
|
+
/**
|
|
3
|
+
* What an expression on a record is worked out with besides its values: the
|
|
4
|
+
* rows of each one2many for `sum` and `count` — the items, not the sections
|
|
5
|
+
* and notes between them — and today's date for `today()`.
|
|
6
|
+
*/
|
|
7
|
+
export function expressionEnv(values, fields, today) {
|
|
8
|
+
const rows = new Map();
|
|
9
|
+
return {
|
|
10
|
+
today,
|
|
11
|
+
lines(name) {
|
|
12
|
+
const def = fields[name];
|
|
13
|
+
if (def?.type !== 'one2many')
|
|
14
|
+
return undefined;
|
|
15
|
+
let found = rows.get(name);
|
|
16
|
+
if (!found) {
|
|
17
|
+
const items = (values[name] ?? []).filter((line) => lineKind(def, line.values) === null);
|
|
18
|
+
found = items.map((line) => expressionContext(line.values, def.fields));
|
|
19
|
+
rows.set(name, found);
|
|
20
|
+
}
|
|
21
|
+
return found;
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=env.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.mjs","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/record/env.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAA0B,MAAM,UAAU,CAAC;AAE/E;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,MAAc,EAAE,MAAyC,EAAE,KAAmB;IAC1G,MAAM,IAAI,GAAG,IAAI,GAAG,EAAqC,CAAC;IAC1D,OAAO;QACL,KAAK;QACL,KAAK,CAAC,IAAI;YACR,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;YACzB,IAAI,GAAG,EAAE,IAAI,KAAK,UAAU;gBAAE,OAAO,SAAS,CAAC;YAC/C,IAAI,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC3B,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,MAAM,KAAK,GAAG,CAAE,MAAM,CAAC,IAAI,CAAmB,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,CAAC;gBAC5G,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;gBACxE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YACxB,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;KACF,CAAC;AACJ,CAAC"}
|