@fieldia/core 0.10.0 → 0.12.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.
Files changed (205) hide show
  1. package/README.md +204 -0
  2. package/package.json +1 -1
  3. package/schema/page.schema.json +4700 -904
  4. package/src/index.d.mts +2 -1
  5. package/src/index.d.ts +2 -1
  6. package/src/index.js +7 -1
  7. package/src/index.js.map +1 -1
  8. package/src/index.mjs +2 -1
  9. package/src/index.mjs.map +1 -1
  10. package/src/lib/expression/built-ins.d.mts +4 -0
  11. package/src/lib/expression/built-ins.d.ts +4 -0
  12. package/src/lib/expression/built-ins.js +8 -0
  13. package/src/lib/expression/built-ins.js.map +1 -0
  14. package/src/lib/expression/built-ins.mjs +5 -0
  15. package/src/lib/expression/built-ins.mjs.map +1 -0
  16. package/src/lib/expression/evaluator.js +17 -7
  17. package/src/lib/expression/evaluator.js.map +1 -1
  18. package/src/lib/expression/evaluator.mjs +17 -7
  19. package/src/lib/expression/evaluator.mjs.map +1 -1
  20. package/src/lib/expression/expression.d.mts +7 -0
  21. package/src/lib/expression/expression.d.ts +7 -0
  22. package/src/lib/expression/expression.js +2 -0
  23. package/src/lib/expression/expression.js.map +1 -1
  24. package/src/lib/expression/expression.mjs +3 -1
  25. package/src/lib/expression/expression.mjs.map +1 -1
  26. package/src/lib/expression/functions.d.mts +2 -0
  27. package/src/lib/expression/functions.d.ts +2 -0
  28. package/src/lib/expression/functions.js +38 -5
  29. package/src/lib/expression/functions.js.map +1 -1
  30. package/src/lib/expression/functions.mjs +38 -5
  31. package/src/lib/expression/functions.mjs.map +1 -1
  32. package/src/lib/expression/modifier.d.mts +7 -0
  33. package/src/lib/expression/modifier.d.ts +7 -0
  34. package/src/lib/expression/modifier.js +3 -1
  35. package/src/lib/expression/modifier.js.map +1 -1
  36. package/src/lib/expression/modifier.mjs +4 -2
  37. package/src/lib/expression/modifier.mjs.map +1 -1
  38. package/src/lib/expression/parser.d.mts +8 -1
  39. package/src/lib/expression/parser.d.ts +8 -1
  40. package/src/lib/expression/parser.js +30 -2
  41. package/src/lib/expression/parser.js.map +1 -1
  42. package/src/lib/expression/parser.mjs +30 -2
  43. package/src/lib/expression/parser.mjs.map +1 -1
  44. package/src/lib/expression/reads.d.mts +7 -0
  45. package/src/lib/expression/reads.d.ts +7 -0
  46. package/src/lib/expression/reads.js +23 -0
  47. package/src/lib/expression/reads.js.map +1 -1
  48. package/src/lib/expression/reads.mjs +21 -0
  49. package/src/lib/expression/reads.mjs.map +1 -1
  50. package/src/lib/format/actions.d.mts +1176 -0
  51. package/src/lib/format/actions.d.ts +1176 -0
  52. package/src/lib/format/actions.js +62 -0
  53. package/src/lib/format/actions.js.map +1 -0
  54. package/src/lib/format/actions.mjs +59 -0
  55. package/src/lib/format/actions.mjs.map +1 -0
  56. package/src/lib/format/check-page.d.mts +7 -2
  57. package/src/lib/format/check-page.d.ts +7 -2
  58. package/src/lib/format/check-page.js +6 -3
  59. package/src/lib/format/check-page.js.map +1 -1
  60. package/src/lib/format/check-page.mjs +6 -3
  61. package/src/lib/format/check-page.mjs.map +1 -1
  62. package/src/lib/format/field.d.mts +3285 -214
  63. package/src/lib/format/field.d.ts +3285 -214
  64. package/src/lib/format/field.js +105 -16
  65. package/src/lib/format/field.js.map +1 -1
  66. package/src/lib/format/field.mjs +104 -15
  67. package/src/lib/format/field.mjs.map +1 -1
  68. package/src/lib/format/hotkeys.d.mts +6 -0
  69. package/src/lib/format/hotkeys.d.ts +6 -0
  70. package/src/lib/format/hotkeys.js +11 -0
  71. package/src/lib/format/hotkeys.js.map +1 -0
  72. package/src/lib/format/hotkeys.mjs +7 -0
  73. package/src/lib/format/hotkeys.mjs.map +1 -0
  74. package/src/lib/format/layout.d.mts +4773 -211
  75. package/src/lib/format/layout.d.ts +4773 -211
  76. package/src/lib/format/layout.js +147 -21
  77. package/src/lib/format/layout.js.map +1 -1
  78. package/src/lib/format/layout.mjs +146 -20
  79. package/src/lib/format/layout.mjs.map +1 -1
  80. package/src/lib/format/layout.types.d.mts +2 -1
  81. package/src/lib/format/layout.types.d.ts +2 -1
  82. package/src/lib/format/page.d.mts +3563 -222
  83. package/src/lib/format/page.d.ts +3563 -222
  84. package/src/lib/format/page.js +19 -2
  85. package/src/lib/format/page.js.map +1 -1
  86. package/src/lib/format/page.mjs +20 -3
  87. package/src/lib/format/page.mjs.map +1 -1
  88. package/src/lib/format/part-look.d.mts +36 -0
  89. package/src/lib/format/part-look.d.ts +36 -0
  90. package/src/lib/format/part-look.js +23 -0
  91. package/src/lib/format/part-look.js.map +1 -0
  92. package/src/lib/format/part-look.mjs +20 -0
  93. package/src/lib/format/part-look.mjs.map +1 -0
  94. package/src/lib/format/references.d.mts +54 -2
  95. package/src/lib/format/references.d.ts +54 -2
  96. package/src/lib/format/references.js +450 -43
  97. package/src/lib/format/references.js.map +1 -1
  98. package/src/lib/format/references.mjs +450 -43
  99. package/src/lib/format/references.mjs.map +1 -1
  100. package/src/lib/format/translate.js +5 -3
  101. package/src/lib/format/translate.js.map +1 -1
  102. package/src/lib/format/translate.mjs +5 -3
  103. package/src/lib/format/translate.mjs.map +1 -1
  104. package/src/lib/format/words.d.mts +9 -0
  105. package/src/lib/format/words.d.ts +9 -0
  106. package/src/lib/format/words.js +35 -0
  107. package/src/lib/format/words.js.map +1 -0
  108. package/src/lib/format/words.mjs +30 -0
  109. package/src/lib/format/words.mjs.map +1 -0
  110. package/src/lib/record/cells.d.mts +37 -0
  111. package/src/lib/record/cells.d.ts +37 -0
  112. package/src/lib/record/cells.js +59 -0
  113. package/src/lib/record/cells.js.map +1 -0
  114. package/src/lib/record/cells.mjs +54 -0
  115. package/src/lib/record/cells.mjs.map +1 -0
  116. package/src/lib/record/compute.d.mts +5 -4
  117. package/src/lib/record/compute.d.ts +5 -4
  118. package/src/lib/record/compute.js +11 -10
  119. package/src/lib/record/compute.js.map +1 -1
  120. package/src/lib/record/compute.mjs +12 -11
  121. package/src/lib/record/compute.mjs.map +1 -1
  122. package/src/lib/record/data-source.d.mts +37 -3
  123. package/src/lib/record/data-source.d.ts +37 -3
  124. package/src/lib/record/data-source.js.map +1 -1
  125. package/src/lib/record/data-source.mjs.map +1 -1
  126. package/src/lib/record/env.d.mts +38 -1
  127. package/src/lib/record/env.d.ts +38 -1
  128. package/src/lib/record/env.js +41 -3
  129. package/src/lib/record/env.js.map +1 -1
  130. package/src/lib/record/env.mjs +38 -3
  131. package/src/lib/record/env.mjs.map +1 -1
  132. package/src/lib/record/filter.d.mts +10 -0
  133. package/src/lib/record/filter.d.ts +10 -0
  134. package/src/lib/record/filter.js +49 -0
  135. package/src/lib/record/filter.js.map +1 -1
  136. package/src/lib/record/filter.mjs +48 -0
  137. package/src/lib/record/filter.mjs.map +1 -1
  138. package/src/lib/record/form.d.mts +226 -25
  139. package/src/lib/record/form.d.ts +226 -25
  140. package/src/lib/record/form.js +785 -83
  141. package/src/lib/record/form.js.map +1 -1
  142. package/src/lib/record/form.mjs +787 -85
  143. package/src/lib/record/form.mjs.map +1 -1
  144. package/src/lib/record/locales/ar.js +3 -0
  145. package/src/lib/record/locales/ar.js.map +1 -1
  146. package/src/lib/record/locales/ar.mjs +3 -0
  147. package/src/lib/record/locales/ar.mjs.map +1 -1
  148. package/src/lib/record/locales/de.js +3 -0
  149. package/src/lib/record/locales/de.js.map +1 -1
  150. package/src/lib/record/locales/de.mjs +3 -0
  151. package/src/lib/record/locales/de.mjs.map +1 -1
  152. package/src/lib/record/locales/fr.js +3 -0
  153. package/src/lib/record/locales/fr.js.map +1 -1
  154. package/src/lib/record/locales/fr.mjs +3 -0
  155. package/src/lib/record/locales/fr.mjs.map +1 -1
  156. package/src/lib/record/memory-data-source.d.mts +26 -2
  157. package/src/lib/record/memory-data-source.d.ts +26 -2
  158. package/src/lib/record/memory-data-source.js +98 -7
  159. package/src/lib/record/memory-data-source.js.map +1 -1
  160. package/src/lib/record/memory-data-source.mjs +98 -7
  161. package/src/lib/record/memory-data-source.mjs.map +1 -1
  162. package/src/lib/record/messages.d.mts +5 -0
  163. package/src/lib/record/messages.d.ts +5 -0
  164. package/src/lib/record/messages.js +3 -0
  165. package/src/lib/record/messages.js.map +1 -1
  166. package/src/lib/record/messages.mjs +3 -0
  167. package/src/lib/record/messages.mjs.map +1 -1
  168. package/src/lib/record/roles.d.mts +10 -0
  169. package/src/lib/record/roles.d.ts +10 -0
  170. package/src/lib/record/roles.js +21 -0
  171. package/src/lib/record/roles.js.map +1 -0
  172. package/src/lib/record/roles.mjs +18 -0
  173. package/src/lib/record/roles.mjs.map +1 -0
  174. package/src/lib/record/rules.js +30 -0
  175. package/src/lib/record/rules.js.map +1 -1
  176. package/src/lib/record/rules.mjs +31 -1
  177. package/src/lib/record/rules.mjs.map +1 -1
  178. package/src/lib/record/run.d.mts +248 -0
  179. package/src/lib/record/run.d.ts +248 -0
  180. package/src/lib/record/run.js +455 -0
  181. package/src/lib/record/run.js.map +1 -0
  182. package/src/lib/record/run.mjs +450 -0
  183. package/src/lib/record/run.mjs.map +1 -0
  184. package/src/lib/record/set-when.d.mts +5 -2
  185. package/src/lib/record/set-when.d.ts +5 -2
  186. package/src/lib/record/set-when.js +28 -12
  187. package/src/lib/record/set-when.js.map +1 -1
  188. package/src/lib/record/set-when.mjs +30 -14
  189. package/src/lib/record/set-when.mjs.map +1 -1
  190. package/src/lib/record/value-map.d.mts +41 -0
  191. package/src/lib/record/value-map.d.ts +41 -0
  192. package/src/lib/record/value-map.js +80 -0
  193. package/src/lib/record/value-map.js.map +1 -0
  194. package/src/lib/record/value-map.mjs +73 -0
  195. package/src/lib/record/value-map.mjs.map +1 -0
  196. package/src/lib/record/values.d.mts +10 -0
  197. package/src/lib/record/values.d.ts +10 -0
  198. package/src/lib/record/values.js.map +1 -1
  199. package/src/lib/record/values.mjs.map +1 -1
  200. package/src/runtime.d.mts +11 -4
  201. package/src/runtime.d.ts +11 -4
  202. package/src/runtime.js +13 -1
  203. package/src/runtime.js.map +1 -1
  204. package/src/runtime.mjs +4 -0
  205. package/src/runtime.mjs.map +1 -1
@@ -0,0 +1,248 @@
1
+ import type { ActionStep, OpenStep, PanelSide } from '../format/actions';
2
+ import type { Field } from '../format/field';
3
+ import type { JsonValue } from '../format/json';
4
+ import type { Tone } from '../format/layout';
5
+ import { type ExpressionEnv } from '../expression/expression';
6
+ import type { ResolvedFilter } from './data-source';
7
+ import { type RecordId, type Values } from './values';
8
+ /**
9
+ * The engine that runs steps — a button's, a moment's, or the app's own —
10
+ * against a form. Steps run in order; one whose `when` does not hold is
11
+ * passed over; the first that fails or is refused stops the rest, and the
12
+ * run's result says which and why. What the core cannot draw — a page opened,
13
+ * words said, a question asked — it asks of the host the viewer gives.
14
+ */
15
+ /** A button pressed, or a `call` step run: what the app's `onAction` is handed. */
16
+ export interface ActionRequest {
17
+ /** The button or stat button pressed; for a moment, `on.open`, `on.change.<field>`, `on.beforeSave`, `on.afterSave` or `on.show.<id>`; for `form.run`, the id it was given. */
18
+ id: string;
19
+ action: string;
20
+ params?: {
21
+ [key: string]: JsonValue;
22
+ };
23
+ recordId: RecordId | null;
24
+ values: Values;
25
+ /** The records chosen in a list, when the button belongs to one. */
26
+ recordIds?: RecordId[];
27
+ /** The line a button on a table's line was pressed on: the table's field, the line's key and values. */
28
+ line?: {
29
+ field: string;
30
+ key: string;
31
+ values: Values;
32
+ };
33
+ /** The lines chosen in a table when a button for them was pressed: the table's field, their keys, the ids of those saved, and their values. */
34
+ lines?: ChosenLines;
35
+ }
36
+ /** Lines chosen in a table, as a button for them hands them on. */
37
+ export interface ChosenLines {
38
+ field: string;
39
+ keys: string[];
40
+ /** The saved records among them, by id: a new line has none yet. */
41
+ ids: RecordId[];
42
+ values: Values[];
43
+ }
44
+ /**
45
+ * What the app may answer a call with. Nothing at all means go on. `values`
46
+ * are set as a `set` step sets them (no person's change); `say` is said;
47
+ * `open` runs as an `open` step would; `stop` stops the steps after it — with
48
+ * words, said to the person as a warning.
49
+ */
50
+ export interface ActionResult {
51
+ values?: Values;
52
+ /** The app changed the record on its server: it is loaded again before the steps go on. */
53
+ reload?: boolean;
54
+ say?: string | {
55
+ message: string;
56
+ tone?: Tone;
57
+ };
58
+ open?: Omit<OpenStep, 'do' | 'when'>;
59
+ /**
60
+ * Show this record in the form's place from now on, as the pager moves to
61
+ * one — the copy a duplicate made, the record a server action made — or a
62
+ * new one for null. Changes not saved are dropped.
63
+ */
64
+ record?: RecordId | null;
65
+ /** Post words in the record's conversation, as a `post` step does: a note unless it is a `message`. */
66
+ post?: string | {
67
+ message: string;
68
+ kind?: 'note' | 'message';
69
+ };
70
+ stop?: boolean | string;
71
+ }
72
+ /** Words posted in a record's conversation by a `post` step or the app's answer. */
73
+ export interface PostedMessage {
74
+ kind: 'note' | 'message';
75
+ /** The words as typed, each `{field}` filled in. */
76
+ text: string;
77
+ /** The same as HTML: every character escaped, each line its own. An html field's value comes as it is. */
78
+ body: string;
79
+ }
80
+ /** What a button does that only the app can: handed over, and awaited. */
81
+ export type OnAction = (request: ActionRequest) => void | ActionResult | Promise<void | ActionResult>;
82
+ /** A page the host is asked to open: in a dialog over the form, a panel beside it, or in its place. */
83
+ export interface OpenRequest {
84
+ /** The page's id, as the app's `pages` finds it. */
85
+ page: string;
86
+ /** One published version; left out, the latest. */
87
+ version?: number;
88
+ as: 'dialog' | 'panel' | 'page';
89
+ /** Where a panel comes from, when its step names a side: the end of the line unless told. */
90
+ side?: PanelSide;
91
+ /** The words over it; left out, the page's own title. */
92
+ title?: string;
93
+ /** The record to open; null for a new one. */
94
+ recordId?: RecordId | null;
95
+ /** What a new one starts with. */
96
+ values?: Values;
97
+ /** On a list page, the records it shows: each `valueFrom` already read from the form that opened it. */
98
+ filter?: ResolvedFilter[];
99
+ }
100
+ /** How an opened page ended: saved (or sent), or closed without. */
101
+ export interface OpenResult {
102
+ saved: boolean;
103
+ /** The record it saved. */
104
+ recordId?: RecordId | null;
105
+ /** Its values, once saved. */
106
+ values?: Values;
107
+ /** The saved record's name, as its page's title field shows it: what a link set to it is labelled. */
108
+ label?: string;
109
+ }
110
+ /**
111
+ * The UI the core cannot draw, given by the viewer. Without one, a form says
112
+ * nothing, asks `FormOptions.confirm` (or goes on as though answered Yes), and
113
+ * cannot open, close or show a tab: those steps stop with reason `cannot`.
114
+ */
115
+ export interface ActionHost {
116
+ open(request: OpenRequest): Promise<OpenResult>;
117
+ say(message: string, tone: Tone): void;
118
+ ask(message: string): Promise<boolean>;
119
+ /** Close the dialog or panel this form was opened in. */
120
+ close?(): void;
121
+ /** Show a tab by its id. The viewer then calls `form.shown(id)`, as for a tab a person picks. */
122
+ show?(target: string): void;
123
+ /** Open a web address: in a new tab, or in this one. */
124
+ openUrl?(url: string, newTab: boolean): void;
125
+ /**
126
+ * Post words in a record's conversation. Left out, the form tells its own
127
+ * listeners (`post`): the chatter beside it. A page opened over a record
128
+ * is given one that posts in that record's. False: nothing heard them.
129
+ */
130
+ post?(message: PostedMessage): boolean | void | Promise<boolean | void>;
131
+ }
132
+ /**
133
+ * Why a run stopped: a check found problems (`check`), a question was
134
+ * answered No (`no`), a save was refused (`save`), the app said stop or threw
135
+ * (`app`), an opened page was closed without saving (`closed`), or the step
136
+ * could not run here — no host to open with, a field the page lacks
137
+ * (`cannot`).
138
+ */
139
+ export type RunStop = 'check' | 'no' | 'save' | 'app' | 'closed' | 'cannot';
140
+ /** How a run of steps ended. */
141
+ export interface RunResult {
142
+ /** Every step ran, or was passed over by its `when`. */
143
+ done: boolean;
144
+ /**
145
+ * The place, among the steps run, of the one that stopped: for a step of
146
+ * an `open`'s `then`, the open step's place; for a button's `action`, one
147
+ * past its steps. Absent when a button's `confirm` was answered No.
148
+ */
149
+ stoppedAt?: number;
150
+ /** The step that stopped, wherever it was. */
151
+ step?: ActionStep;
152
+ reason?: RunStop;
153
+ /** Why, in words: the first problem found, the question, the save's or the app's words. */
154
+ message?: string;
155
+ /** What the app or the host threw, when that stopped it. */
156
+ error?: unknown;
157
+ }
158
+ /** What a run is for: the id calls carry, the records chosen in a list. */
159
+ export interface RunContext {
160
+ id?: string;
161
+ recordIds?: RecordId[];
162
+ }
163
+ /** A step stopped: why, and which (a step of an `open`'s `then`, the deepest). */
164
+ export interface Stopped {
165
+ reason: RunStop;
166
+ message?: string;
167
+ step?: ActionStep;
168
+ error?: unknown;
169
+ }
170
+ /** A run as it goes: its id, the records chosen, and the moments it was set off by — a moment one of them sets off again does not run. */
171
+ export interface RunScope {
172
+ id: string;
173
+ recordIds?: RecordId[];
174
+ line?: {
175
+ field: string;
176
+ key: string;
177
+ values: Values;
178
+ };
179
+ lines?: ChosenLines;
180
+ chain: readonly string[];
181
+ }
182
+ /** What a run reaches its form by: the form gives these. */
183
+ export interface RunForm {
184
+ readonly fields: Readonly<Record<string, Field>>;
185
+ values(): Readonly<Values>;
186
+ recordId(): RecordId | null;
187
+ /** The values as expressions read them, and what else they read. */
188
+ reading(): {
189
+ context: Record<string, unknown>;
190
+ env: ExpressionEnv;
191
+ };
192
+ today(): string;
193
+ /** Write fields as a step does: worked out once, no person's change. Throws for a field the page lacks. */
194
+ write(values: Values): void;
195
+ addLine(field: string, values: Values): void;
196
+ check(fields: readonly string[] | undefined): Stopped | null;
197
+ save(chain: readonly string[]): Promise<Stopped | null>;
198
+ /** Load the record again from its data source; a new record cannot be. */
199
+ reload(): Promise<Stopped | null>;
200
+ reset(): void;
201
+ /** Go to a wizard's step; `undefined` when the target is none of its steps (a tab). */
202
+ goTo(target: string, chain: readonly string[]): Stopped | null | undefined;
203
+ /** Run `show` of the host while `chain` is the run's, so a tab it shows knows who showed it. */
204
+ showing(chain: readonly string[], show: () => void): void;
205
+ host?: ActionHost;
206
+ confirm?: (message: string) => boolean | Promise<boolean>;
207
+ onAction?: OnAction;
208
+ /** The app answered a call. */
209
+ answered(request: ActionRequest, result: ActionResult | undefined): void;
210
+ /** Whether something changed since the record was loaded or saved. */
211
+ changed(): boolean;
212
+ /**
213
+ * The record's own operations through the data source, each only when the
214
+ * data source has it; without, the app's action of the step's name is called.
215
+ */
216
+ archive?(archive: boolean): Promise<void>;
217
+ copy?(): Promise<RecordId>;
218
+ remove?(): Promise<void>;
219
+ /** Show another record in this form's place, loaded as a pager loads it; a new one for null. */
220
+ showRecord(id: RecordId | null): Promise<Stopped | null>;
221
+ /** The record was archived (or brought back), copied, or deleted: told to the app. Deleted, the form leaves it unless a listener moved it on. */
222
+ told(event: {
223
+ archived: boolean;
224
+ } | {
225
+ copied: RecordId;
226
+ } | {
227
+ deleted: true;
228
+ }, id: RecordId): void;
229
+ /** Post words in the record's conversation: false when nothing here can. */
230
+ post(message: PostedMessage): Promise<boolean>;
231
+ /** A field's value as words in a posted message: a link's name, a choice's label. */
232
+ wordsOf(field: string): string;
233
+ }
234
+ export declare const DONE: RunResult;
235
+ /** Steps run against one form. Expressions are read once and kept. */
236
+ export declare function createRunner(form: RunForm): {
237
+ runSteps: (steps: readonly ActionStep[], scope: RunScope) => Promise<RunResult>;
238
+ ask: (message: string) => Promise<boolean>;
239
+ };
240
+ /**
241
+ * One run of each moment at a time. A moment set off by a step of its own
242
+ * run — or a run it set off — does not run. Set off while a run of it is
243
+ * going: `again` moments (open, change, show) run once more after it, with
244
+ * the values as they are then, however many times they were set off
245
+ * meanwhile; the others (beforeSave, afterSave) do not run — a save made
246
+ * meanwhile goes ahead without them, so nothing waits on itself.
247
+ */
248
+ export declare function createMoments(run: (key: string, steps: readonly ActionStep[], chain: readonly string[]) => Promise<RunResult>): (key: string, steps: readonly ActionStep[] | undefined, chain: readonly string[], again: boolean) => Promise<RunResult>;