ngx-t-forms-types 0.0.30 → 0.0.34

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 (68) hide show
  1. package/dist/interfaces/Form/formSubmissionHandleInterface.d.ts +6 -0
  2. package/dist/interfaces/FormBuilder/DefaultEelement.js +76 -0
  3. package/dist/interfaces/FormBuilder/DefaultInputConfigInterface.d.ts +13 -0
  4. package/dist/interfaces/FormBuilder/FormInputKeys.d.ts +6 -0
  5. package/dist/interfaces/FormBuilder/FormInputKeys.js +6 -0
  6. package/dist/interfaces/FormBuilder/inputConfig/ElementEditConfig.js +188 -3
  7. package/dist/interfaces/Import/ImportIdentity.d.ts +32 -0
  8. package/dist/interfaces/Import/ImportIdentity.js +1 -0
  9. package/dist/interfaces/Import/ImportProgress.d.ts +12 -1
  10. package/dist/interfaces/Import/ImportRowState.d.ts +52 -1
  11. package/dist/interfaces/Import/index.d.ts +2 -1
  12. package/dist/interfaces/formInput/APIDataFetchingConfigurationInterface.d.ts +34 -0
  13. package/dist/interfaces/formInput/BasicFormInputInterface.d.ts +1 -0
  14. package/dist/interfaces/formInput/BasicFormInputInterface.js +1 -0
  15. package/dist/interfaces/formInput/IMscoaAccount.d.ts +19 -3
  16. package/dist/interfaces/formInput/ISelectInputInterface.d.ts +12 -0
  17. package/dist/interfaces/formInput/MultipleInterface.d.ts +10 -0
  18. package/dist/interfaces/formInput/WorkflowDocumentPicker.d.ts +2 -0
  19. package/dist/schemas/FormInputSchema.js +41 -2
  20. package/dist/schemas/MatOptionsSchema.js +7 -0
  21. package/dist/schemas/MscoaConfigSchema.js +1 -0
  22. package/dist/schemas/index.d.ts +2 -1
  23. package/dist/schemas/index.js +2 -1
  24. package/dist/skillet/authoring-rules.d.ts +41 -0
  25. package/dist/skillet/authoring-rules.js +61 -0
  26. package/dist/skillet/extra-members.d.ts +143 -0
  27. package/dist/skillet/extra-members.js +79 -0
  28. package/dist/skillet/form.d.ts +170 -0
  29. package/dist/skillet/form.js +139 -0
  30. package/dist/skillet/index.d.ts +43 -0
  31. package/dist/skillet/index.js +46 -0
  32. package/dist/skillet/input-members.d.ts +375 -0
  33. package/dist/skillet/input-members.js +186 -0
  34. package/dist/skillet/internal/coupling.d.ts +63 -0
  35. package/dist/skillet/internal/coupling.js +69 -0
  36. package/dist/skillet/internal/editor-guidance.d.ts +64 -0
  37. package/dist/skillet/internal/editor-guidance.js +291 -0
  38. package/dist/skillet/members/calculated-field.d.ts +155 -0
  39. package/dist/skillet/members/calculated-field.js +105 -0
  40. package/dist/skillet/members/conditional.d.ts +69 -0
  41. package/dist/skillet/members/conditional.js +16 -0
  42. package/dist/skillet/members/document-picker.d.ts +182 -0
  43. package/dist/skillet/members/document-picker.js +111 -0
  44. package/dist/skillet/members/mat-options.d.ts +187 -0
  45. package/dist/skillet/members/mat-options.js +92 -0
  46. package/dist/skillet/members/mscoa.d.ts +182 -0
  47. package/dist/skillet/members/mscoa.js +129 -0
  48. package/dist/skillet/members/pagination.d.ts +59 -0
  49. package/dist/skillet/members/pagination.js +16 -0
  50. package/dist/skillet/members/table.d.ts +178 -0
  51. package/dist/skillet/members/table.js +105 -0
  52. package/dist/skillet/members/validators.d.ts +197 -0
  53. package/dist/skillet/members/validators.js +74 -0
  54. package/dist/skillet/members/value.d.ts +154 -0
  55. package/dist/skillet/members/value.js +97 -0
  56. package/dist/skillet/shared-types.d.ts +57 -0
  57. package/dist/skillet/shared-types.js +69 -0
  58. package/dist/skillet/tests/house-rules.spec.d.ts +1 -0
  59. package/dist/skillet/tests/house-rules.spec.js +162 -0
  60. package/dist/skillet/tests/skillet-coupling.spec.d.ts +1 -0
  61. package/dist/skillet/tests/skillet-coupling.spec.js +191 -0
  62. package/dist/skillet/tests/variant-assembly.spec.d.ts +1 -0
  63. package/dist/skillet/tests/variant-assembly.spec.js +643 -0
  64. package/dist/skillet/variants.d.ts +138 -0
  65. package/dist/skillet/variants.js +536 -0
  66. package/dist/skillet/workflow-context.d.ts +95 -0
  67. package/dist/skillet/workflow-context.js +128 -0
  68. package/package.json +78 -60
@@ -0,0 +1,375 @@
1
+ import { s } from '@hashbrownai/core';
2
+ import type { FormColumnInputs } from '../interfaces/Form/index.js';
3
+ import { AllFormInputPrimaryKeys } from '../interfaces/FormBuilder/FormInputKeys.js';
4
+ import { type MatOptionsDraft } from './members/mat-options.js';
5
+ import { type CalculatedFieldRulesDraft } from './members/calculated-field.js';
6
+ import { type ValidatorEntryDraft } from './members/validators.js';
7
+ import { type ConditionalRuleDraft } from './members/conditional.js';
8
+ import { type MscoaConfigDraft } from './members/mscoa.js';
9
+ import { type PaginationSelectionConfigDraft } from './members/pagination.js';
10
+ import { type CalculateListFunctionsDraft } from './members/value.js';
11
+ import { AssertNever } from './internal/coupling.js';
12
+ /**
13
+ * One Skillet node per member a form input can carry.
14
+ *
15
+ * This registry is the single place a property's LLM-facing shape is defined.
16
+ * Per-element variants are assembled by PICKING from it — they never redeclare
17
+ * a node — so a property means the same thing everywhere it appears.
18
+ *
19
+ * ## Nodes are unwrapped
20
+ *
21
+ * Every node here describes the value as it looks WHEN PRESENT. Optionality is
22
+ * not encoded, because it is not a property of the member — it is a property of
23
+ * the member *within an element*. `colSize` is required on an input and absent
24
+ * on a section title. Variant assembly consults
25
+ * `DefaultInputConfig[element].requiredProperties` and wraps the optional ones
26
+ * with `optional()` at that point.
27
+ *
28
+ * ## Descriptions are composed, not written twice
29
+ *
30
+ * Each authored description is passed through `describe()`, which layers on the
31
+ * hint and the applicability rules the form-builder's own editor config already
32
+ * carries for that property. See `internal/editor-guidance.ts` for what is
33
+ * drawn from there and what was inspected and deliberately rejected.
34
+ *
35
+ * ## The five categories are exhaustive
36
+ *
37
+ * Every `AllFormInputPrimaryKeys` member belongs to exactly one of
38
+ * {@link inputMemberSchemas}, {@link draftMemberSchemas},
39
+ * {@link PENDING_INPUT_MEMBERS}, {@link SYSTEM_OWNED_INPUT_MEMBERS}, or
40
+ * {@link DEPRECATED_INPUT_MEMBERS}. The assertions at the foot of this file
41
+ * prove it, so a key added to the enum breaks the build until it is
42
+ * classified. Nothing can be silently forgotten.
43
+ */
44
+ /**
45
+ * The type a member is required to produce, read off the real interface.
46
+ *
47
+ * Keys the interfaces do not declare resolve to `unknown`, which imposes no
48
+ * constraint — see {@link UnbackedInputMember} for why that is a finding rather
49
+ * than a feature.
50
+ */
51
+ type MemberValue<K extends AllFormInputPrimaryKeys> = K extends keyof FormColumnInputs ? NonNullable<FormColumnInputs[K]> : unknown;
52
+ /**
53
+ * Members a model must never author: identifiers the builder assigns and
54
+ * runtime state the form owns while it is open. These are excluded from
55
+ * generation schemas entirely and stitched in afterwards.
56
+ */
57
+ export declare const SYSTEM_OWNED_INPUT_MEMBERS: readonly [AllFormInputPrimaryKeys.Id, AllFormInputPrimaryKeys.SectionId, AllFormInputPrimaryKeys.SystemDefault, AllFormInputPrimaryKeys.Status, AllFormInputPrimaryKeys.ValueUpdatedAt, AllFormInputPrimaryKeys.TemporaryHint, AllFormInputPrimaryKeys.FormIsOpen, AllFormInputPrimaryKeys.MultipleInputInEditId, AllFormInputPrimaryKeys.CanReload];
58
+ /**
59
+ * Members kept only so stored forms keep deserialising. They are excluded from
60
+ * generation entirely: a model must never author a property the codebase has
61
+ * already moved on from, and leaving one in the schema would see it reappear on
62
+ * every newly generated input.
63
+ */
64
+ export declare const DEPRECATED_INPUT_MEMBERS: readonly [AllFormInputPrimaryKeys.IServeInputWithRequisitionItems];
65
+ /**
66
+ * Members whose shape is a nested configuration object deserving its own
67
+ * module. Listed rather than stubbed: a placeholder node would compile and then
68
+ * quietly feed the model a wrong shape, which is worse than an absent one.
69
+ */
70
+ export declare const PENDING_INPUT_MEMBERS: readonly [AllFormInputPrimaryKeys.AdjudicationReviewFeedbackTemplate];
71
+ /**
72
+ * Members whose node cannot be built until assembly, because its shape depends
73
+ * on something only the caller knows.
74
+ *
75
+ * These differ from {@link DRAFT_INPUT_MEMBERS} in that there is no sensible
76
+ * default node to publish at all:
77
+ *
78
+ * - `workflowPickerConfig` needs the workflows available in the caller's
79
+ * context. With none, the member is not offered — the same reasoning that
80
+ * withholds the `api` source in `members/mat-options.ts`, and for the same
81
+ * reason: a fabricated `workflowId` produces a picker that looks right and
82
+ * points at nothing.
83
+ * - `formInputs` is the contents of a repeatable list, which is itself a list
84
+ * of columns. It can only be built once the remaining nesting depth is known,
85
+ * because Skillet has no way to express a recursive schema and the recursion
86
+ * has to be unrolled to a fixed depth instead.
87
+ *
88
+ * `variants.ts` resolves both while it walks an element's properties.
89
+ */
90
+ export declare const ASSEMBLED_INPUT_MEMBERS: readonly [AllFormInputPrimaryKeys.WorkflowPickerConfig, AllFormInputPrimaryKeys.FormInputs];
91
+ /**
92
+ * Members whose schema produces an AUTHORING DRAFT rather than the stored
93
+ * shape, because some part of the stored shape is not knowable from a prompt.
94
+ *
95
+ * `matOptions` is the first of these: an api source is stored as a full
96
+ * endpoint configuration — `_id`, `httpEndPoint`, `httpMethod`, headers — and a
97
+ * model asked for that invents a URL. So the draft carries the id of an
98
+ * endpoint the caller supplied, and the application expands it before the form
99
+ * is validated.
100
+ *
101
+ * These are checked against their declared draft type rather than against the
102
+ * interface member, so the compiler still holds them to something. What it
103
+ * cannot check is the expansion itself; that contract lives with the caller.
104
+ */
105
+ export declare const DRAFT_INPUT_MEMBERS: readonly [AllFormInputPrimaryKeys.MatOptions, AllFormInputPrimaryKeys.CalculatedFieldRules, AllFormInputPrimaryKeys.Validators, AllFormInputPrimaryKeys.ConditionalInputConfig, AllFormInputPrimaryKeys.MscoaConfig, AllFormInputPrimaryKeys.PaginationSelectionConfig, AllFormInputPrimaryKeys.CalculateListFunctions];
106
+ type SystemOwnedKey = (typeof SYSTEM_OWNED_INPUT_MEMBERS)[number];
107
+ type DeprecatedKey = (typeof DEPRECATED_INPUT_MEMBERS)[number];
108
+ type PendingKey = (typeof PENDING_INPUT_MEMBERS)[number];
109
+ type DraftKey = (typeof DRAFT_INPUT_MEMBERS)[number];
110
+ type AssembledKey = (typeof ASSEMBLED_INPUT_MEMBERS)[number];
111
+ /**
112
+ * The draft each drafted member is held to.
113
+ *
114
+ * Every one of these exists because the stored shape carries an identifier the
115
+ * builder assigns — an input's `id`, a rule's `id`, a segment's row key. A
116
+ * model authoring a form that does not exist yet cannot know any of them, so it
117
+ * binds by `formControlName` and the application resolves the pair. Each
118
+ * module states its own version of this; the list is here so the compiler
119
+ * checks them all in one place.
120
+ */
121
+ interface MemberDrafts {
122
+ [AllFormInputPrimaryKeys.MatOptions]: MatOptionsDraft;
123
+ [AllFormInputPrimaryKeys.CalculatedFieldRules]: CalculatedFieldRulesDraft;
124
+ [AllFormInputPrimaryKeys.Validators]: ValidatorEntryDraft[];
125
+ [AllFormInputPrimaryKeys.ConditionalInputConfig]: ConditionalRuleDraft[];
126
+ [AllFormInputPrimaryKeys.MscoaConfig]: MscoaConfigDraft;
127
+ [AllFormInputPrimaryKeys.PaginationSelectionConfig]: PaginationSelectionConfigDraft;
128
+ [AllFormInputPrimaryKeys.CalculateListFunctions]: CalculateListFunctionsDraft;
129
+ }
130
+ /**
131
+ * Members whose model output must be expanded before it satisfies the
132
+ * interfaces. Kept apart from {@link inputMemberSchemas} so that consuming code
133
+ * cannot treat a draft as a finished value by accident.
134
+ */
135
+ export declare const draftMemberSchemas: {
136
+ matOptions: s.ObjectType<{
137
+ optionType: import("@hashbrownai/core/src/schema/base").SchemaForUnion<"user" | null>;
138
+ options: s.ArrayType<s.ObjectType<{
139
+ label: s.StringType;
140
+ value: s.StringType;
141
+ }>>;
142
+ fetch: s.ObjectType<{
143
+ value: import("@hashbrownai/core/src/schema/base").SchemaForUnion<{
144
+ source: import("..").DataSources.Local;
145
+ inputSourceId: string;
146
+ allowManualValueEntry: boolean;
147
+ } | {
148
+ source: import("..").DataSources.CustomOptions;
149
+ } | {
150
+ source: import("..").DataSources.Api;
151
+ endpointId: string;
152
+ allowManualValueEntry: boolean;
153
+ } | {
154
+ source: import("..").DataSources.MongoDb;
155
+ workflowId: string;
156
+ } | null>;
157
+ options: import("@hashbrownai/core/src/schema/base").SchemaForUnion<{
158
+ source: import("..").DataSources.Local;
159
+ inputSourceId: string;
160
+ allowManualValueEntry: boolean;
161
+ } | {
162
+ source: import("..").DataSources.CustomOptions;
163
+ } | {
164
+ source: import("..").DataSources.Api;
165
+ endpointId: string;
166
+ allowManualValueEntry: boolean;
167
+ } | {
168
+ source: import("..").DataSources.MongoDb;
169
+ workflowId: string;
170
+ } | null>;
171
+ }>;
172
+ }>;
173
+ calculatedFieldRules: s.ObjectType<{
174
+ formula: s.StringType;
175
+ variables: s.ArrayType<import("@hashbrownai/core/src/schema/base").SchemaForUnion<{
176
+ bindingType: "field";
177
+ variable: string;
178
+ label: string;
179
+ formControlName: string;
180
+ } | {
181
+ bindingType: "listAggregate";
182
+ variable: string;
183
+ label: string;
184
+ formControlName: string;
185
+ parentInputFormControl: string;
186
+ function: import("..").CalculationFunctions;
187
+ applyFunctionToCol: string;
188
+ applyFunctionToLabel: string | null;
189
+ filterValuesByCol: string | null;
190
+ filterValuesByThisColLabel: string | null;
191
+ tableCell: boolean | null;
192
+ }>>;
193
+ decimalPlaces: import("@hashbrownai/core/src/schema/base").SchemaForUnion<number | null>;
194
+ roundingMode: import("@hashbrownai/core/src/schema/base").SchemaForUnion<"FLOOR" | "CEIL" | "ROUND" | null>;
195
+ getFormulaFromAFormInput: import("@hashbrownai/core/src/schema/base").SchemaForUnion<boolean | null>;
196
+ formControlWithFormula: import("@hashbrownai/core/src/schema/base").SchemaForUnion<string | null>;
197
+ }>;
198
+ validators: s.ArrayType<import("@hashbrownai/core/src/schema/base").SchemaForUnion<string | {
199
+ message: string;
200
+ expression: string;
201
+ canOverride: boolean;
202
+ inputsObservedForChanges: {
203
+ formControlName: string;
204
+ variable: string;
205
+ parentInputFormControl: string | null;
206
+ function: import("..").CalculationFunctions | null;
207
+ }[];
208
+ }>> | s.ArrayType<s.ObjectType<{
209
+ message: s.StringType;
210
+ expression: s.StringType;
211
+ canOverride: s.BooleanType;
212
+ inputsObservedForChanges: s.ArrayType<s.ObjectType<{
213
+ formControlName: s.StringType;
214
+ variable: s.StringType;
215
+ parentInputFormControl: import("@hashbrownai/core/src/schema/base").SchemaForUnion<string | null>;
216
+ function: import("@hashbrownai/core/src/schema/base").SchemaForUnion<import("..").CalculationFunctions | null>;
217
+ }>>;
218
+ }>>;
219
+ conditionalInputConfig: s.ArrayType<s.ObjectType<{
220
+ expression: s.StringType;
221
+ inputsObservedForChanges: s.ArrayType<s.ObjectType<{
222
+ formControlName: s.StringType;
223
+ variable: s.StringType;
224
+ parentInputFormControl: import("@hashbrownai/core/src/schema/base").SchemaForUnion<string | null>;
225
+ function: import("@hashbrownai/core/src/schema/base").SchemaForUnion<import("..").CalculationFunctions | null>;
226
+ }>>;
227
+ }>>;
228
+ mscoaConfig: s.ObjectType<{
229
+ accountingBasis: import("@hashbrownai/core/src/schema/base").SchemaForUnion<import("..").AccountingBasis | null>;
230
+ segments: s.ArrayType<s.ObjectType<{
231
+ segment: s.StringType;
232
+ customSegment: import("@hashbrownai/core/src/schema/base").SchemaForUnion<string | null>;
233
+ label: s.StringType;
234
+ readOnly: s.BooleanType;
235
+ singleSelect: s.BooleanType;
236
+ additionalAccounts: s.ArrayType<s.StringType>;
237
+ inheritValueFromAccrual: import("@hashbrownai/core/src/schema/base").SchemaForUnion<boolean | null>;
238
+ vatSelectonActive: import("@hashbrownai/core/src/schema/base").SchemaForUnion<boolean | null>;
239
+ segmentExtension: s.BooleanType;
240
+ }>>;
241
+ cashSegments: import("@hashbrownai/core/src/schema/base").SchemaForUnion<{
242
+ segment: string;
243
+ customSegment: string | null;
244
+ label: string;
245
+ readOnly: boolean;
246
+ singleSelect: boolean;
247
+ additionalAccounts: string[];
248
+ inheritValueFromAccrual: boolean | null;
249
+ vatSelectonActive: boolean | null;
250
+ segmentExtension: boolean;
251
+ }[] | null>;
252
+ accountValueLabel: s.EnumType<string[]>;
253
+ showAllSegments: s.BooleanType;
254
+ extensionAccountsForSegments: s.ArrayType<s.StringType>;
255
+ dualCashExclusion: import("@hashbrownai/core/src/schema/base").SchemaForUnion<{
256
+ rules: {
257
+ pattern: string;
258
+ flags: string | null;
259
+ matchField: string | null;
260
+ segment: string | null;
261
+ description: string | null;
262
+ }[] | null;
263
+ matchMode: "any" | "all" | null;
264
+ } | null>;
265
+ }>;
266
+ paginationSelectionConfig: s.ObjectType<{
267
+ useLocalPagination: import("@hashbrownai/core/src/schema/base").SchemaForUnion<boolean | null>;
268
+ columns: s.ArrayType<s.ObjectType<{
269
+ key: s.StringType;
270
+ label: s.StringType;
271
+ }>>;
272
+ }>;
273
+ calculateListFunctions: s.ArrayType<s.ObjectType<{
274
+ formControlName: s.StringType;
275
+ func: s.EnumType<import("..").CalculationFunctions[]>;
276
+ }>>;
277
+ };
278
+ /** Every key this registry is obliged to cover. */
279
+ export type ModelledKey = Exclude<AllFormInputPrimaryKeys, SystemOwnedKey | PendingKey | DeprecatedKey | DraftKey | AssembledKey>;
280
+ export declare const inputMemberSchemas: {
281
+ element: s.EnumType<import("..").ElementTypes[]>;
282
+ label: s.StringType;
283
+ formControlName: s.StringType;
284
+ colSize: s.IntegerType;
285
+ appearance: s.EnumType<["fill", "outline"]>;
286
+ dataType: s.EnumType<import("..").InputDataTypes[]>;
287
+ type: s.EnumType<import("..").InputTypes[]>;
288
+ viewType: s.EnumType<import("../interfaces/formInput/BasicFormInputInterface.js").InputViewTypes.ViewOnly[]>;
289
+ required: s.BooleanType;
290
+ readonly: s.BooleanType;
291
+ showAsLabel: s.BooleanType;
292
+ onlySetTempErrorOnTouch: s.BooleanType;
293
+ isCalculatedField: s.BooleanType;
294
+ hintLabel: s.StringType;
295
+ tourContent: s.StringType;
296
+ spellcheck: s.BooleanType;
297
+ autocapitalize: s.EnumType<import("..").AutocapitalizeOptions[]>;
298
+ rows: s.IntegerType;
299
+ wrap: s.EnumType<["hard", "soft"]>;
300
+ richTextEditorLibrary: s.EnumType<import("..").RichTextEditorType[]>;
301
+ min: import("@hashbrownai/core/src/schema/base").SchemaForUnion<string | number>;
302
+ max: import("@hashbrownai/core/src/schema/base").SchemaForUnion<string | number>;
303
+ minLength: s.IntegerType;
304
+ maxLength: s.IntegerType;
305
+ optionSelectType: s.EnumType<import("..").OptionSelectTypes[]>;
306
+ allowMultipleSelection: s.BooleanType;
307
+ singleSelect: s.BooleanType;
308
+ groupBy: s.ArrayType<s.StringType>;
309
+ labelPosition: s.EnumType<import("../interfaces/formInput/ToggleInputInterface.js").LabelPosition[]>;
310
+ trueLabel: s.StringType;
311
+ falseLabel: s.StringType;
312
+ startDateControl: s.StringType;
313
+ endDateControl: s.StringType;
314
+ fileType: s.EnumType<import("..").InputFileType[]>;
315
+ accept: s.StringType;
316
+ handleLabel: s.StringType;
317
+ pipe: s.ObjectType<{
318
+ pipeType: s.EnumType<import("..").InputPipeTypes[]>;
319
+ param: s.StringType;
320
+ }>;
321
+ linkedSegmentId: s.StringType;
322
+ adjudicationStep: s.EnumType<import("..").AdjudicationSteps[]>;
323
+ adjudicationPointTypes: s.ArrayType<s.StringType>;
324
+ workflowFormForScoreSheet: s.StringType;
325
+ value: import("@hashbrownai/core/src/schema/base").SchemaForUnion<string | number | boolean>;
326
+ script: s.ObjectType<{
327
+ onChange: s.StringType;
328
+ }>;
329
+ };
330
+ /**
331
+ * Every key is classified. Adding a member to `AllFormInputPrimaryKeys` fails
332
+ * here until it is modelled, deferred, or declared system-owned.
333
+ */
334
+ export type _EveryKeyClassified = AssertNever<Exclude<AllFormInputPrimaryKeys, ModelledKey | PendingKey | SystemOwnedKey | DeprecatedKey | DraftKey | AssembledKey>>;
335
+ /**
336
+ * No key may be claimed by two categories at once.
337
+ *
338
+ * Written as each category against the union of those after it rather than as
339
+ * every pair spelled out: the pairwise form needed ten lines for five
340
+ * categories and would need fifteen for six, which is the kind of list that
341
+ * quietly loses an entry when the next category is added.
342
+ */
343
+ export type _CategoriesDisjoint = AssertNever<(ModelledKey & (PendingKey | SystemOwnedKey | DeprecatedKey | DraftKey | AssembledKey)) | (PendingKey & (SystemOwnedKey | DeprecatedKey | DraftKey | AssembledKey)) | (SystemOwnedKey & (DeprecatedKey | DraftKey | AssembledKey)) | (DeprecatedKey & (DraftKey | AssembledKey)) | (DraftKey & AssembledKey)>;
344
+ /**
345
+ * Every drafted node produces the draft it declares. The expansion from draft
346
+ * to stored shape is the caller's, but the draft itself stays checked.
347
+ */
348
+ export type _NoDraftDrift = AssertNever<{
349
+ [K in DraftKey]: [s.Infer<(typeof draftMemberSchemas)[K]>] extends [
350
+ MemberDrafts[K]
351
+ ] ? never : K;
352
+ }[DraftKey]>;
353
+ /**
354
+ * Every modelled node still produces a value its interface member can hold.
355
+ * Retyping a member in the interfaces surfaces here, by name, as a constraint
356
+ * violation on the offending key.
357
+ *
358
+ * Narrowing is permitted by design — several nodes deliberately refuse value
359
+ * shapes the interface tolerates but a model should never invent.
360
+ */
361
+ export type _NoValueDrift = AssertNever<{
362
+ [K in ModelledKey]: [s.Infer<(typeof inputMemberSchemas)[K]>] extends [
363
+ MemberValue<K>
364
+ ] ? never : K;
365
+ }[ModelledKey]>;
366
+ /**
367
+ * Keys the enum declares but no interface in this package backs, so
368
+ * {@link MemberValue} cannot constrain them and their nodes go unverified.
369
+ * Exported deliberately: this is pre-existing drift the schemas inherit, not
370
+ * something they introduce.
371
+ */
372
+ export type UnbackedInputMember = Exclude<AllFormInputPrimaryKeys, keyof FormColumnInputs>;
373
+ /** Runtime access to the full key list, derived from the enum. */
374
+ export declare const ALL_INPUT_MEMBER_KEYS: AllFormInputPrimaryKeys[];
375
+ export {};
@@ -0,0 +1,186 @@
1
+ import { s } from '@hashbrownai/core';
2
+ import { AllFormInputPrimaryKeys } from '../interfaces/FormBuilder/FormInputKeys.js';
3
+ import { matOptionsSchema } from './members/mat-options.js';
4
+ import { calculatedFieldRulesDraftSchema, } from './members/calculated-field.js';
5
+ import { validatorsDraftSchema, } from './members/validators.js';
6
+ import { conditionalInputConfigDraftSchema, } from './members/conditional.js';
7
+ import { mscoaConfigSchema } from './members/mscoa.js';
8
+ import { paginationSelectionConfigDraftSchema, } from './members/pagination.js';
9
+ import { calculateListFunctionsSchema, scriptSchema, valueSchema, } from './members/value.js';
10
+ import { enumValues } from './internal/coupling.js';
11
+ import { CONTROL_NAME_PATTERN } from './authoring-rules.js';
12
+ import { describe, rangeFor } from './internal/editor-guidance.js';
13
+ import { adjudicationStepSchema, appearanceSchema, autocapitalizeSchema, elementTypeSchema, inputDataTypeSchema, inputFileTypeSchema, inputPipeTypeSchema, inputTypeSchema, inputViewTypeSchema, labelPositionSchema, optionSelectTypeSchema, richTextEditorTypeSchema, textareaWrapSchema, } from './shared-types.js';
14
+ /**
15
+ * Members a model must never author: identifiers the builder assigns and
16
+ * runtime state the form owns while it is open. These are excluded from
17
+ * generation schemas entirely and stitched in afterwards.
18
+ */
19
+ export const SYSTEM_OWNED_INPUT_MEMBERS = [
20
+ AllFormInputPrimaryKeys.Id,
21
+ AllFormInputPrimaryKeys.SectionId,
22
+ AllFormInputPrimaryKeys.SystemDefault,
23
+ AllFormInputPrimaryKeys.Status,
24
+ AllFormInputPrimaryKeys.ValueUpdatedAt,
25
+ AllFormInputPrimaryKeys.TemporaryHint,
26
+ AllFormInputPrimaryKeys.FormIsOpen,
27
+ AllFormInputPrimaryKeys.MultipleInputInEditId,
28
+ AllFormInputPrimaryKeys.CanReload,
29
+ ];
30
+ /**
31
+ * Members kept only so stored forms keep deserialising. They are excluded from
32
+ * generation entirely: a model must never author a property the codebase has
33
+ * already moved on from, and leaving one in the schema would see it reappear on
34
+ * every newly generated input.
35
+ */
36
+ export const DEPRECATED_INPUT_MEMBERS = [
37
+ AllFormInputPrimaryKeys.IServeInputWithRequisitionItems,
38
+ ];
39
+ /**
40
+ * Members whose shape is a nested configuration object deserving its own
41
+ * module. Listed rather than stubbed: a placeholder node would compile and then
42
+ * quietly feed the model a wrong shape, which is worse than an absent one.
43
+ */
44
+ export const PENDING_INPUT_MEMBERS = [
45
+ AllFormInputPrimaryKeys.AdjudicationReviewFeedbackTemplate,
46
+ ];
47
+ /**
48
+ * Members whose node cannot be built until assembly, because its shape depends
49
+ * on something only the caller knows.
50
+ *
51
+ * These differ from {@link DRAFT_INPUT_MEMBERS} in that there is no sensible
52
+ * default node to publish at all:
53
+ *
54
+ * - `workflowPickerConfig` needs the workflows available in the caller's
55
+ * context. With none, the member is not offered — the same reasoning that
56
+ * withholds the `api` source in `members/mat-options.ts`, and for the same
57
+ * reason: a fabricated `workflowId` produces a picker that looks right and
58
+ * points at nothing.
59
+ * - `formInputs` is the contents of a repeatable list, which is itself a list
60
+ * of columns. It can only be built once the remaining nesting depth is known,
61
+ * because Skillet has no way to express a recursive schema and the recursion
62
+ * has to be unrolled to a fixed depth instead.
63
+ *
64
+ * `variants.ts` resolves both while it walks an element's properties.
65
+ */
66
+ export const ASSEMBLED_INPUT_MEMBERS = [
67
+ AllFormInputPrimaryKeys.WorkflowPickerConfig,
68
+ AllFormInputPrimaryKeys.FormInputs,
69
+ ];
70
+ /**
71
+ * Members whose schema produces an AUTHORING DRAFT rather than the stored
72
+ * shape, because some part of the stored shape is not knowable from a prompt.
73
+ *
74
+ * `matOptions` is the first of these: an api source is stored as a full
75
+ * endpoint configuration — `_id`, `httpEndPoint`, `httpMethod`, headers — and a
76
+ * model asked for that invents a URL. So the draft carries the id of an
77
+ * endpoint the caller supplied, and the application expands it before the form
78
+ * is validated.
79
+ *
80
+ * These are checked against their declared draft type rather than against the
81
+ * interface member, so the compiler still holds them to something. What it
82
+ * cannot check is the expansion itself; that contract lives with the caller.
83
+ */
84
+ export const DRAFT_INPUT_MEMBERS = [
85
+ AllFormInputPrimaryKeys.MatOptions,
86
+ AllFormInputPrimaryKeys.CalculatedFieldRules,
87
+ AllFormInputPrimaryKeys.Validators,
88
+ AllFormInputPrimaryKeys.ConditionalInputConfig,
89
+ AllFormInputPrimaryKeys.MscoaConfig,
90
+ AllFormInputPrimaryKeys.PaginationSelectionConfig,
91
+ AllFormInputPrimaryKeys.CalculateListFunctions,
92
+ ];
93
+ /**
94
+ * Members whose model output must be expanded before it satisfies the
95
+ * interfaces. Kept apart from {@link inputMemberSchemas} so that consuming code
96
+ * cannot treat a draft as a finished value by accident.
97
+ */
98
+ export const draftMemberSchemas = {
99
+ [AllFormInputPrimaryKeys.MatOptions]: matOptionsSchema,
100
+ [AllFormInputPrimaryKeys.CalculatedFieldRules]: calculatedFieldRulesDraftSchema,
101
+ [AllFormInputPrimaryKeys.Validators]: validatorsDraftSchema,
102
+ [AllFormInputPrimaryKeys.ConditionalInputConfig]: conditionalInputConfigDraftSchema,
103
+ [AllFormInputPrimaryKeys.MscoaConfig]: mscoaConfigSchema,
104
+ [AllFormInputPrimaryKeys.PaginationSelectionConfig]: paginationSelectionConfigDraftSchema,
105
+ [AllFormInputPrimaryKeys.CalculateListFunctions]: calculateListFunctionsSchema,
106
+ };
107
+ // Descriptions on the members every element shares are kept SHORT on purpose:
108
+ // each is repeated once per element per nesting level in the emitted schema,
109
+ // because Hashbrown names `$defs` entries by their description. The
110
+ // definition and the one rule that belongs at the member stay here; the
111
+ // form-wide rules live in `authoring-rules.ts`, emitted once at the root.
112
+ export const inputMemberSchemas = {
113
+ // --- identity and layout --------------------------------------------------
114
+ [AllFormInputPrimaryKeys.Element]: elementTypeSchema,
115
+ [AllFormInputPrimaryKeys.Label]: s.string(describe("The visible field label: a noun phrase of one to three words in sentence case, in the words of the people who fill the form in ('Cost centre', not 'cc_code'), with no colon or trailing punctuation. It is also the heading the answer is printed under, so it must make sense on its own.", AllFormInputPrimaryKeys.Label)),
116
+ [AllFormInputPrimaryKeys.FormControlName]: s.string(describe("The key this value is stored under, derived from the label so that it identifies the field on its own: 'budgetReview', not 'toggle1'. Unique across the whole form; never a reserved name; never changed once the form is live.", AllFormInputPrimaryKeys.FormControlName), { pattern: CONTROL_NAME_PATTERN }),
117
+ [AllFormInputPrimaryKeys.ColSize]: s.integer(describe('How many of the 12 grid columns this control spans. Size it to the data: 12 for long text, a textarea, an item list, a picker, an uploader or a signature; 6, 4 or 3 for a date, an amount, a quantity, a short code or a toggle.', AllFormInputPrimaryKeys.ColSize), rangeFor(AllFormInputPrimaryKeys.ColSize) ?? { minimum: 1, maximum: 12 }),
118
+ [AllFormInputPrimaryKeys.Appearance]: appearanceSchema,
119
+ [AllFormInputPrimaryKeys.DataType]: inputDataTypeSchema,
120
+ [AllFormInputPrimaryKeys.Type]: inputTypeSchema,
121
+ [AllFormInputPrimaryKeys.ViewType]: inputViewTypeSchema,
122
+ // --- obligation and state -------------------------------------------------
123
+ [AllFormInputPrimaryKeys.Required]: s.boolean(describe('Whether the user must supply a value before the form can be submitted. Required when the next step cannot proceed without it; if in doubt, not required; if required only sometimes, use a validator or a conditional display rule instead.', AllFormInputPrimaryKeys.Required)),
124
+ [AllFormInputPrimaryKeys.Readonly]: s.boolean(describe("Whether the value is displayed but cannot be edited: for an earlier step's answer, a profile value, a fetched figure. The value is still submitted.", AllFormInputPrimaryKeys.Readonly)),
125
+ [AllFormInputPrimaryKeys.ShowAsLabel]: s.boolean(describe('Renders the value as plain text instead of a form control.', AllFormInputPrimaryKeys.ShowAsLabel)),
126
+ [AllFormInputPrimaryKeys.OnlySetTempErrorOnTouch]: s.boolean(describe('Withholds validation errors until the user has interacted with the field. True on nearly every field.', AllFormInputPrimaryKeys.OnlySetTempErrorOnTouch)),
127
+ [AllFormInputPrimaryKeys.IsCalculatedField]: s.boolean(describe('Whether this value is computed from other fields rather than entered by the user.', AllFormInputPrimaryKeys.IsCalculatedField)),
128
+ // --- guidance -------------------------------------------------------------
129
+ [AllFormInputPrimaryKeys.HintLabel]: s.string(describe('Short helper text shown under the field permanently: one sentence with no full stop, giving the format, the source, or the reason for asking. On a sectionTitle it is the guidance for the whole group that follows and may run to two sentences.', AllFormInputPrimaryKeys.HintLabel)),
130
+ [AllFormInputPrimaryKeys.TourContent]: s.string(describe('Guided-tour copy shown when the form is first walked through. Only for a genuinely unfamiliar control such as an account picker or a document picker: two sentences, what it is and what to do.', AllFormInputPrimaryKeys.TourContent)),
131
+ // --- text behaviour -------------------------------------------------------
132
+ [AllFormInputPrimaryKeys.Spellcheck]: s.boolean(describe('Whether the browser spell-checks the typed text. Enable for prose, disable for codes and identifiers.', AllFormInputPrimaryKeys.Spellcheck)),
133
+ [AllFormInputPrimaryKeys.Autocapitalize]: autocapitalizeSchema,
134
+ [AllFormInputPrimaryKeys.Rows]: s.integer(describe('Visible height of a textarea, in lines.', AllFormInputPrimaryKeys.Rows), { minimum: 1 }),
135
+ [AllFormInputPrimaryKeys.Wrap]: textareaWrapSchema,
136
+ [AllFormInputPrimaryKeys.RichTextEditorLibrary]: richTextEditorTypeSchema,
137
+ // --- constraints ----------------------------------------------------------
138
+ // A union node has no description slot of its own, so the applicability rule
139
+ // the editor declares for these — they mean nothing unless the input is
140
+ // numeric or a date — is composed onto each branch instead. Dropping it would
141
+ // lose the single most useful thing the editor config knows about them.
142
+ [AllFormInputPrimaryKeys.Min]: s.anyOf([
143
+ s.number(describe('A numeric lower bound: 1 for a quantity, 0 for an amount or a percentage.', AllFormInputPrimaryKeys.Min)),
144
+ s.string(describe('A lower bound as an ISO date, for date controls.', AllFormInputPrimaryKeys.Min)),
145
+ ]),
146
+ [AllFormInputPrimaryKeys.Max]: s.anyOf([
147
+ s.number(describe('A numeric upper bound: 100 for a percentage.', AllFormInputPrimaryKeys.Max)),
148
+ s.string(describe('An upper bound as an ISO date, for date controls.', AllFormInputPrimaryKeys.Max)),
149
+ ]),
150
+ [AllFormInputPrimaryKeys.MinLength]: s.integer(describe('The fewest characters the value may contain.', AllFormInputPrimaryKeys.MinLength), { minimum: 0 }),
151
+ [AllFormInputPrimaryKeys.MaxLength]: s.integer(describe('The most characters the value may contain. Match the limit of the system the value is stored in, and say so in the hint when it matters.', AllFormInputPrimaryKeys.MaxLength), { minimum: 1 }),
152
+ // --- options and selection ------------------------------------------------
153
+ [AllFormInputPrimaryKeys.OptionSelectType]: optionSelectTypeSchema,
154
+ [AllFormInputPrimaryKeys.AllowMultipleSelection]: s.boolean(describe('Whether more than one option may be chosen at once.', AllFormInputPrimaryKeys.AllowMultipleSelection)),
155
+ [AllFormInputPrimaryKeys.SingleSelect]: s.boolean(describe('Restricts the control to exactly one selection.', AllFormInputPrimaryKeys.SingleSelect)),
156
+ [AllFormInputPrimaryKeys.GroupBy]: s.array(describe('Option properties to group the list under, outermost first. Leave empty for a flat list.', AllFormInputPrimaryKeys.GroupBy), s.string('An option property name to group by.')),
157
+ // --- toggle ---------------------------------------------------------------
158
+ [AllFormInputPrimaryKeys.LabelPosition]: labelPositionSchema,
159
+ [AllFormInputPrimaryKeys.TrueLabel]: s.string(describe("Text shown when a toggle is on. Name the real state — 'Approve', 'VAT registered' — never a bare 'Yes', which forces the user to re-read the label.", AllFormInputPrimaryKeys.TrueLabel)),
160
+ [AllFormInputPrimaryKeys.FalseLabel]: s.string(describe("Text shown when a toggle is off: the direct opposite of the true label — 'Reject', 'Not VAT registered' — never a bare 'No'.", AllFormInputPrimaryKeys.FalseLabel)),
161
+ // --- dates ----------------------------------------------------------------
162
+ [AllFormInputPrimaryKeys.StartDateControl]: s.string(describe('The formControlName holding the start of a date range. A range stores two values, so both this and endDateControl must be set, or the field is dropped from prefill, export and print.', AllFormInputPrimaryKeys.StartDateControl)),
163
+ [AllFormInputPrimaryKeys.EndDateControl]: s.string(describe('The formControlName holding the end of a date range. Both this and startDateControl must be set.', AllFormInputPrimaryKeys.EndDateControl)),
164
+ // --- files ----------------------------------------------------------------
165
+ [AllFormInputPrimaryKeys.FileType]: inputFileTypeSchema,
166
+ [AllFormInputPrimaryKeys.Accept]: s.string(describe('Accepted upload types as an HTML accept attribute, for example ".pdf,.docx" or "image/*". Match it to the documents actually expected, and name the accepted types in the hint as well.', AllFormInputPrimaryKeys.Accept)),
167
+ [AllFormInputPrimaryKeys.HandleLabel]: s.string(describe("The text of the button that adds a row to an item list. Name the action — 'Add item', 'Add attendee' — not the default 'Add to list'.", AllFormInputPrimaryKeys.HandleLabel)),
168
+ // --- display transform ----------------------------------------------------
169
+ [AllFormInputPrimaryKeys.Pipe]: s.object(describe('A display transform applied when the value is shown back to the user: currency for an amount, percent for a rate, date for a date. Presentation only; the stored value is unchanged.', AllFormInputPrimaryKeys.Pipe), {
170
+ pipeType: inputPipeTypeSchema,
171
+ param: s.string('The pipe argument, such as a date format like "dd MMM yyyy" or a currency code like "ZAR".'),
172
+ }),
173
+ // --- domain ---------------------------------------------------------------
174
+ [AllFormInputPrimaryKeys.LinkedSegmentId]: s.string(describe('Identifier of the mSCOA segment this control resolves against.', AllFormInputPrimaryKeys.LinkedSegmentId)),
175
+ [AllFormInputPrimaryKeys.AdjudicationStep]: adjudicationStepSchema,
176
+ [AllFormInputPrimaryKeys.AdjudicationPointTypes]: s.array(describe('The scoring categories available at this adjudication step.', AllFormInputPrimaryKeys.AdjudicationPointTypes), s.string('A scoring category name.')),
177
+ [AllFormInputPrimaryKeys.WorkflowFormForScoreSheet]: s.string(describe('Identifier of the form supplying the score sheet for this adjudication.', AllFormInputPrimaryKeys.WorkflowFormForScoreSheet)),
178
+ // --- prefilled value and behaviour ---------------------------------------
179
+ // Both are modelled rather than drafted: they carry no builder-assigned
180
+ // identifier, so what the model emits is what gets stored. See
181
+ // `members/value.ts` for the narrowing each one applies.
182
+ [AllFormInputPrimaryKeys.Value]: valueSchema,
183
+ [AllFormInputPrimaryKeys.Script]: scriptSchema,
184
+ };
185
+ /** Runtime access to the full key list, derived from the enum. */
186
+ export const ALL_INPUT_MEMBER_KEYS = enumValues(AllFormInputPrimaryKeys);
@@ -0,0 +1,63 @@
1
+ import { s } from '@hashbrownai/core';
2
+ /**
3
+ * Compile-time coupling primitives that bind the Skillet schemas to the
4
+ * interfaces they describe.
5
+ *
6
+ * The rule these enforce, stated once:
7
+ *
8
+ * `s.Infer<node>` must be ASSIGNABLE TO the interface member's type.
9
+ *
10
+ * Assignability — not equality — is deliberate. A Skillet node is allowed to be
11
+ * NARROWER than the interface (we routinely refuse to let a model emit a `Date`
12
+ * object or a custom-script sentinel even where the interface permits one), but
13
+ * it may never be WIDER. Widening is precisely the drift that produces a value
14
+ * the rest of the codebase cannot hold, so that is the direction we fail on.
15
+ */
16
+ /**
17
+ * Guards a Skillet node against the type it is meant to produce.
18
+ *
19
+ * Curried so the expected type is written explicitly and the node type is
20
+ * inferred:
21
+ *
22
+ * ```ts
23
+ * const colSize = matches<number>()(s.integer('Grid width', { minimum: 1 }));
24
+ * ```
25
+ *
26
+ * If the node's inferred output stops being assignable to `Expected` — because
27
+ * someone retyped the interface member, or loosened the node — the argument
28
+ * collapses to `never` and the call fails to compile.
29
+ */
30
+ export declare function matches<Expected>(): <Node extends s.HashbrownType>(node: [s.Infer<Node>] extends [Expected] ? Node : never) => Node;
31
+ /**
32
+ * Derives Skillet enum entries from a TypeScript string enum at runtime, so the
33
+ * two can never disagree: add a member to the enum and it appears in the schema
34
+ * on the next evaluation, with `s.Infer` widening to match.
35
+ *
36
+ * The `Record<string, string>` constraint rejects numeric and mixed enums —
37
+ * `Object.values` on those also yields the reverse-mapped numeric keys, which
38
+ * would silently poison the entry list. Skillet enumerations are string-only.
39
+ */
40
+ export declare function enumValues<E extends Record<string, string>>(enumObject: E): E[keyof E][];
41
+ /**
42
+ * Asserts a literal tuple covers a string union exactly.
43
+ *
44
+ * Needed for union *types* (`'hard' | 'soft'`), which — unlike enums — have no
45
+ * runtime representation to derive from, so the members must be restated. This
46
+ * makes restating them safe: drop one and the argument becomes `never`.
47
+ *
48
+ * ```ts
49
+ * const WRAP = exhaustive<'hard' | 'soft'>()(['hard', 'soft'] as const);
50
+ * ```
51
+ */
52
+ export declare function exhaustive<Union extends string>(): <Tuple extends readonly Union[]>(entries: [Exclude<Union, Tuple[number]>] extends [never] ? Tuple : never) => Tuple;
53
+ /**
54
+ * Wraps a node as an absent-able member.
55
+ *
56
+ * Skillet has no `optional()`: every declared key must appear in the model's
57
+ * response. Optionality is therefore modelled as an explicit null branch — the
58
+ * key is always emitted, and `null` is how the model says "not set". Strip the
59
+ * nulls when converting a generated column into a `FormColumnInputs`.
60
+ */
61
+ export declare function optional<Node extends s.HashbrownType>(node: Node): import("@hashbrownai/core/src/schema/base").SchemaForUnion<(Node | s.NullType)["~schema"]["result"]>;
62
+ /** Resolves to `never` unless `T` is `never`; used to prove a set is empty. */
63
+ export type AssertNever<T extends never> = T;