@beehexa/hexasync-template-context 2608.20.18 → 2608.20.32

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 (49) hide show
  1. package/dist/completion.d.ts +80 -0
  2. package/dist/completion.d.ts.map +1 -0
  3. package/dist/completion.js +202 -0
  4. package/dist/completion.js.map +1 -0
  5. package/dist/detect.d.ts +38 -0
  6. package/dist/detect.d.ts.map +1 -0
  7. package/dist/detect.js +35 -0
  8. package/dist/detect.js.map +1 -0
  9. package/dist/environment.d.ts +79 -0
  10. package/dist/environment.d.ts.map +1 -0
  11. package/dist/environment.js +239 -0
  12. package/dist/environment.js.map +1 -0
  13. package/dist/hints.d.ts +62 -0
  14. package/dist/hints.d.ts.map +1 -0
  15. package/dist/hints.js +198 -0
  16. package/dist/hints.js.map +1 -0
  17. package/dist/index.d.ts +12 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +12 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/item.d.ts +87 -0
  22. package/dist/item.d.ts.map +1 -0
  23. package/dist/item.js +222 -0
  24. package/dist/item.js.map +1 -0
  25. package/dist/position.d.ts +36 -0
  26. package/dist/position.d.ts.map +1 -0
  27. package/dist/position.js +31 -0
  28. package/dist/position.js.map +1 -0
  29. package/dist/references.d.ts +60 -0
  30. package/dist/references.d.ts.map +1 -0
  31. package/dist/references.js +217 -0
  32. package/dist/references.js.map +1 -0
  33. package/dist/shape.d.ts +68 -0
  34. package/dist/shape.d.ts.map +1 -0
  35. package/dist/shape.js +23 -0
  36. package/dist/shape.js.map +1 -0
  37. package/dist/stepOutputs.d.ts +52 -0
  38. package/dist/stepOutputs.d.ts.map +1 -0
  39. package/dist/stepOutputs.js +102 -0
  40. package/dist/stepOutputs.js.map +1 -0
  41. package/dist/survival.d.ts +47 -0
  42. package/dist/survival.d.ts.map +1 -0
  43. package/dist/survival.js +50 -0
  44. package/dist/survival.js.map +1 -0
  45. package/dist/walk.d.ts +36 -0
  46. package/dist/walk.d.ts.map +1 -0
  47. package/dist/walk.js +162 -0
  48. package/dist/walk.js.map +1 -0
  49. package/package.json +1 -1
@@ -0,0 +1,239 @@
1
+ import { POSITION_LABEL } from './position.js';
2
+ import { stepOutputs } from './stepOutputs.js';
3
+ import { arrayShape, field, objectShape, scalarShape, unknownShape, } from './shape.js';
4
+ /** One unix-ms stamp per run. ⚠️ Never spelled `_pull` — that name appears in no runtime. */
5
+ const RUN_START = field('runStart', scalarShape('number'), {
6
+ kind: 'builtin',
7
+ note: 'One unix-millisecond stamp taken once per run. Never spelled `_pull`.',
8
+ });
9
+ const RELATED_TASKS = field('__related_tasks', unknownShape('The associated tasks, resolved at run time from the project — not declared in this document.'), { kind: 'builtin' });
10
+ const ENV_ROOT = (name) => field(name, unknownShape('Environment values come from the connection at run time, so their keys are not in this document. Read the ' +
11
+ "connector's declared options to find out which exist."), { kind: 'builtin' });
12
+ /**
13
+ * A step's own namespace. `__this.outputs` is refreshed BEFORE `next` is resolved, so a `next` expression can read
14
+ * the step it belongs to — which is why this is not simply an alias of `_outputs.<own key>`.
15
+ */
16
+ const THIS_ROOT = (ownArguments) => field('__this', objectShape([
17
+ field('arguments', objectShape(ownArguments), { kind: 'builtin' }, "This step's own arguments."),
18
+ field('outputs', unknownShape("This step's own outputs, refreshed before `next` is resolved."), { kind: 'builtin' }),
19
+ field('definition', unknownShape("This step's definition, as the platform holds it."), {
20
+ kind: 'builtin',
21
+ }),
22
+ ]), { kind: 'builtin' });
23
+ /**
24
+ * `_outputs`, plus the two namespaces an author cannot guess and cannot find.
25
+ *
26
+ * `_outputs.__error.chain` and `_history` exist to be read by `onErrorSteps`, `finalSteps` and `LOOKUP_STEP`, and
27
+ * they appear in no authoring surface at all — which is exactly why they are here.
28
+ */
29
+ const outputsRoot = (steps, phase) => {
30
+ const perStep = steps.map((step) => field(step.key, step.outputs ??
31
+ unknownShape(`\`${step.key}\` declares no response filters, so its output keys are not in this document.`), {
32
+ kind: 'step',
33
+ stepKey: step.key,
34
+ ...(phase === undefined ? {} : { phase }),
35
+ }));
36
+ return field('_outputs', objectShape([
37
+ ...perStep,
38
+ field('__error', objectShape([
39
+ field('type', scalarShape('string'), { kind: 'builtin' }),
40
+ field('message', scalarShape('string'), { kind: 'builtin' }),
41
+ field('stepKey', scalarShape('string'), { kind: 'builtin' }),
42
+ field('__flow', scalarShape('string'), { kind: 'builtin' }),
43
+ field('handled', scalarShape('boolean'), { kind: 'builtin' }),
44
+ field('chain', arrayShape(unknownShape('Each failure in the chain, oldest first.')), {
45
+ kind: 'builtin',
46
+ }),
47
+ field('previous', unknownShape("An earlier flow's failure, nested."), { kind: 'builtin' }),
48
+ ]), {
49
+ kind: 'builtin',
50
+ note: 'Run-level failure. Read by onErrorSteps and finalSteps.',
51
+ }),
52
+ ]), { kind: 'builtin' });
53
+ };
54
+ /**
55
+ * Read a step's facts straight from the authored step, so a caller never has to derive the output shape itself.
56
+ *
57
+ * ⚠️ The whole point of `stepOutputs` living beside this is that `…current.STEP_X.<field>` is EXACT — the union of
58
+ * the step's response-filter keys, written twenty lines above the caret — rather than a guess. A caller that built
59
+ * `StepFacts` by hand would be re-deriving that, which is how two surfaces start disagreeing.
60
+ */
61
+ export function stepFactsFrom(step) {
62
+ const key = String(step?.key ?? '');
63
+ return { key, outputs: stepOutputs(step).shape };
64
+ }
65
+ /**
66
+ * ⛔ **Earlier steps in the phase, plus the step itself.**
67
+ *
68
+ * `StepIterator` calls the context handler in each step's success path with the accumulated outputs, so after
69
+ * `STEP_A` the phase holds `{STEP_A}` and after `STEP_B` it holds `{STEP_A, STEP_B}`. A forward reference resolves
70
+ * to nothing — no error, no diagnostic, an empty string in a URL or a body.
71
+ *
72
+ * The step ITSELF is included, and that is not an off-by-one: each pagination iteration calls `ExecuteSteps` afresh
73
+ * with an empty outputs dict, so at the top of page 2 `puller.current` still holds page 1's values. Reading
74
+ * `puller.lastToken.PULL_DATA.offset` from inside `PULL_DATA` is the pagination idiom, not a mistake — it is why the
75
+ * alias is called `lastToken`.
76
+ */
77
+ export function visibleSteps(steps, stepIndex) {
78
+ if (stepIndex === undefined)
79
+ return steps;
80
+ return steps.slice(0, stepIndex + 1);
81
+ }
82
+ function pullerRoot(request) {
83
+ const component = request.component;
84
+ const phases = component?.phases ?? {};
85
+ const forPhase = (name) => name === request.phase
86
+ ? visibleSteps(phases[name] ?? [], request.stepIndex)
87
+ : (phases[name] ?? []);
88
+ /**
89
+ * ⛔ `sourcePhase` is the point. `history` and `lastToken` are not phases — they are ALIASES, written by
90
+ * `LegacyStepContextHandler.UpdateContext` as THE SAME OBJECT as `before` and `current`. Reading them from a phase
91
+ * of their own name produced two permanently empty roots, which is exactly how an alias silently becomes a store:
92
+ * the completion list is empty, nothing errors, and 1,695 corpus uses of `puller.lastToken` get no help at all.
93
+ */
94
+ const phaseField = (name, note, sourcePhase = name) => field(name, objectShape(forPhase(sourcePhase).map((step) => field(step.key, step.outputs ??
95
+ unknownShape(`\`${step.key}\` declares no response filters, so its output keys are not in this document.`), { kind: 'step', stepKey: step.key, phase: sourcePhase }))), { kind: 'builtin', note });
96
+ return field('puller', objectShape([
97
+ field('options', objectShape((component?.optionKeys ?? []).map((key) => field(key, unknownShape('An option value, supplied per connection.'), {
98
+ kind: 'builtin',
99
+ }))), { kind: 'builtin', note: 'The options declared on THIS puller.' }),
100
+ field('arguments', objectShape((component?.argumentKeys ?? []).map((key) => field(key, unknownShape('An argument the host passed.'), {
101
+ kind: 'builtin',
102
+ }))), { kind: 'builtin' }),
103
+ field('definition', unknownShape("The puller's own definition object."), {
104
+ kind: 'builtin',
105
+ }),
106
+ phaseField('before', 'The beforePullSteps phase.'),
107
+ phaseField('current', 'The pullSteps phase.'),
108
+ phaseField('after', 'The afterPullSteps phase.'),
109
+ phaseField('final', 'The finalSteps phase.'),
110
+ /**
111
+ * ⛔ Aliases, not stores. `LegacyStepContextHandler.UpdateContext` writes the phase's outputs to the phase key
112
+ * and then writes THE SAME OBJECT to `history` (for `before`) and to `lastToken` (for `current`, puller only).
113
+ * Corpus: `puller.lastToken` 1,695 uses, `puller.history` 1,085 — this is the alphabet the corpus is written
114
+ * in, and offering them from one resolved set is why hover has to explain which is which.
115
+ */
116
+ phaseField('history', 'An ALIAS of `before` — the same object, not a separate store.', 'before'),
117
+ phaseField('lastToken', 'An ALIAS of `current` — the same object. Read from inside a step it holds the PREVIOUS iteration, which is ' +
118
+ 'the pagination idiom.', 'current'),
119
+ ]), { kind: 'builtin' });
120
+ }
121
+ function pusherRoot(request) {
122
+ const component = request.component;
123
+ const phases = component?.phases ?? {};
124
+ const phaseField = (name) => field(name, objectShape((name === request.phase
125
+ ? visibleSteps(phases[name] ?? [], request.stepIndex)
126
+ : (phases[name] ?? [])).map((step) => field(step.key, step.outputs ??
127
+ unknownShape(`\`${step.key}\` declares no response filters.`), {
128
+ kind: 'step',
129
+ stepKey: step.key,
130
+ phase: name,
131
+ }))), { kind: 'builtin' });
132
+ // ⛔ NO `lastToken`. The handler gates that write on `root == "puller"`, so `pusher.lastToken` does not exist —
133
+ // and because it reads exactly like the puller idiom, it is worth a diagnostic rather than an empty completion.
134
+ return field('pusher', objectShape([
135
+ field('definition', unknownShape("The pusher's own definition object."), {
136
+ kind: 'builtin',
137
+ }),
138
+ /**
139
+ * ⛔ `options` and `arguments` exist on a PUSHER too, and omitting them cost 134 false findings.
140
+ *
141
+ * `CONTEXT-MODEL.md` §4 lists what `Pusher.PushItem` adds at ROOT level and says which phase keys exist; it
142
+ * does not enumerate what `ParametersBuilder.SetRoot` contributes, which is the same `definition` / `options`
143
+ * / `arguments` trio it contributes for a puller. I read the silence as absence and the corpus measurement
144
+ * said otherwise on its first run — 134 reports, every one of them `pusher.options.*`, which the corpus uses
145
+ * 62 times deliberately. Measuring BEFORE choosing a severity is exactly what caught it (Story 8.6 AC-7).
146
+ */
147
+ field('options', objectShape((component?.optionKeys ?? []).map((key) => field(key, unknownShape('An option value, supplied per connection.'), {
148
+ kind: 'builtin',
149
+ }))), { kind: 'builtin', note: 'The options declared on THIS pusher.' }),
150
+ field('arguments', objectShape((component?.argumentKeys ?? []).map((key) => field(key, unknownShape('An argument the host passed.'), {
151
+ kind: 'builtin',
152
+ }))), { kind: 'builtin' }),
153
+ phaseField('before'),
154
+ phaseField('current'),
155
+ phaseField('after'),
156
+ phaseField('final'),
157
+ phaseField('history'),
158
+ ]), { kind: 'builtin' });
159
+ }
160
+ /**
161
+ * Resolve one caret into one environment.
162
+ *
163
+ * ⛔ Pure. It reads no file, spawns nothing and imports nothing from an editor — Story 8.1 AC-5, and the reason the
164
+ * CLI and the extension cannot disagree: there is one function and they both call it. A test asserting "the editor
165
+ * and the CLI produce the same environment" is only worth writing because it could otherwise have been two engines.
166
+ */
167
+ export function resolveEnvironment(request) {
168
+ const { position } = request;
169
+ const roots = [];
170
+ let note = `Completing in ${POSITION_LABEL[position]}.`;
171
+ if (position === 'validation-field') {
172
+ /**
173
+ * ⛔ Columns only, and FLAT. The value is interpolated into SQL, so a nested path is not "unresolved" — it is a
174
+ * column name that does not exist and a query that fails at run time. A transformation-produced field is equally
175
+ * illegal here: it exists on the item, never on the table.
176
+ */
177
+ for (const column of request.columns ?? [])
178
+ roots.push(column);
179
+ return {
180
+ position,
181
+ roots: new Map(roots.map((each) => [each.name, each])),
182
+ note: "A validation's field takes a task COLUMN, flat. It is interpolated into SQL, so a nested path or a " +
183
+ 'transformation-produced field names a column that does not exist.',
184
+ };
185
+ }
186
+ if (position === 'transformation-expression') {
187
+ /**
188
+ * ⛔ The item's fields BARE. The context object IS the item here, so `{{ item.sku }}` — correct one position
189
+ * away, in a pusher step — resolves to nothing, silently. That single confusion is most of why this engine
190
+ * exists.
191
+ */
192
+ const item = request.item;
193
+ if (item?.kind === 'object' && item.fields) {
194
+ for (const each of item.fields.values())
195
+ roots.push(each);
196
+ }
197
+ roots.push(THIS_ROOT(request.ownArguments ?? []));
198
+ return {
199
+ position,
200
+ roots: new Map(roots.map((each) => [each.name, each])),
201
+ note: "A transformation expression is evaluated WITH THE ITEM AS ITS CONTEXT, so the item's fields are referenced " +
202
+ 'bare — `sku`, not `item.sku`.',
203
+ };
204
+ }
205
+ const component = request.component;
206
+ const steps = component?.phases?.[request.phase ?? ''] ?? [];
207
+ if (position === 'new-kind-puller-step') {
208
+ // ⛔ No `puller.*` at all. `Puller.RunWorkflow` builds this context by hand and the comment states the intent.
209
+ roots.push(field('_inputs', objectShape((component?.argumentKeys ?? []).map((key) => field(key, unknownShape('A workflow input, supplied when the flow is invoked.'), {
210
+ kind: 'builtin',
211
+ }))), {
212
+ kind: 'builtin',
213
+ note: "The workflow's inputs — the generic replacement for `puller.arguments`.",
214
+ }), outputsRoot(visibleSteps(steps, request.stepIndex), request.phase), THIS_ROOT(request.ownArguments ?? []), ENV_ROOT('_env'), field('_history', unknownShape('A newest-first ring per step key, depth from `retain`. Read by LOOKUP_STEP.'), { kind: 'builtin' }), RUN_START, RELATED_TASKS);
215
+ note =
216
+ 'This puller declares a `steps` array, so it is a NEW-KIND puller. It shares no context root with a legacy ' +
217
+ 'puller: `puller.*` resolves to nothing here.';
218
+ }
219
+ else if (position === 'legacy-puller-step') {
220
+ roots.push(pullerRoot(request), ENV_ROOT('env'), outputsRoot(visibleSteps(steps, request.stepIndex), request.phase), THIS_ROOT(request.ownArguments ?? []), RUN_START, RELATED_TASKS);
221
+ note =
222
+ 'This puller declares no `steps` array, so it is a LEGACY puller. It shares no context root with a new-kind ' +
223
+ 'puller: `_inputs` resolves to nothing here.';
224
+ }
225
+ else {
226
+ roots.push(field('item', request.item ??
227
+ unknownShape('The item could not be resolved from this document.'), { kind: 'builtin' }), field('task', unknownShape('The task this pusher writes, as the platform holds it.'), {
228
+ kind: 'builtin',
229
+ }), field('dependencies', unknownShape('The resolved dependencies of this item.'), { kind: 'builtin' }), pusherRoot(request), ENV_ROOT('env'), outputsRoot(visibleSteps(steps, request.stepIndex), request.phase), THIS_ROOT(request.ownArguments ?? []), RUN_START, RELATED_TASKS);
230
+ note =
231
+ 'A pusher step. ⚠️ `pusher.lastToken` does not exist — that alias is written only for a puller.';
232
+ }
233
+ return {
234
+ position,
235
+ roots: new Map(roots.map((each) => [each.name, each])),
236
+ note,
237
+ };
238
+ }
239
+ //# sourceMappingURL=environment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"environment.js","sourceRoot":"","sources":["../src/environment.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ import { type Field, type Shape } from './shape.js';
2
+ /**
3
+ * `dataHints` — declaring the shape the platform cannot know (Stories 8.8 and 8.12).
4
+ *
5
+ * Layer 2 of the item is the decoded `__raw`, and **nothing in the project declares it**: it is the source system's
6
+ * payload. Yet the corpus references it constantly — `item.line_items[0].code` works at run time while no document
7
+ * says `line_items` has a `code`. `dataHints` closes exactly that hole and nothing else.
8
+ *
9
+ * ⛔ **Values never survive.** The schema forbids every value-bearing keyword — `example`, `examples`, `default`,
10
+ * `enum`, `const` — so a payload full of customer names cannot reach a template repository even by accident. This is
11
+ * the property's one hard rule, and the reason it is safe to paste a real payload into an editor at all.
12
+ */
13
+ export declare const VALUE_BEARING_KEYWORDS: readonly ['example', 'examples', 'default', 'enum', 'const'];
14
+ /** The JSON-Schema subset a hint may use. Anything else is either a value or a constraint nobody consumes. */
15
+ export declare const ALLOWED_KEYWORDS: readonly ['type', 'properties', 'items', 'description'];
16
+ export interface HintProblem {
17
+ readonly path: string;
18
+ readonly reason: string;
19
+ }
20
+ /**
21
+ * Validate a hints block. Returns every problem, so an author fixes them in one pass rather than one per save.
22
+ *
23
+ * ⚠️ A value-bearing keyword is an ERROR rather than a strip-and-continue. Silently removing it would leave the
24
+ * author believing the tool accepted their input, and the next paste would put the value back.
25
+ */
26
+ export declare function checkHints(hints: unknown, at?: string): readonly HintProblem[];
27
+ /** Turn a validated hints block into the shape the engine completes against. */
28
+ export declare function shapeFromHints(hints: unknown): Shape;
29
+ /** Every top-level hinted key as a field, for merging into the item. */
30
+ export declare function hintFields(dataHints: unknown): readonly Field[];
31
+ export interface InferOptions {
32
+ readonly maxDepth?: number;
33
+ readonly maxProperties?: number;
34
+ }
35
+ export interface InferredHints {
36
+ readonly hints: Record<string, unknown>;
37
+ /** ⛔ Every cap that fired, named. A silent cap reads as "that is the whole payload". */
38
+ readonly truncations: readonly string[];
39
+ }
40
+ /**
41
+ * Infer a hints block from a real payload — Story 8.12.
42
+ *
43
+ * The edge cases are what decide whether the output can be trusted, and each one below is the NON-obvious choice:
44
+ *
45
+ * | input | emitted | why not the obvious thing |
46
+ * | --- | --- | --- |
47
+ * | array of objects | `items` from the **union of every element** | element 0 is routinely the least complete; an optional field appears on element 7 |
48
+ * | heterogeneous array | `items` unknown, with the reason | a union of unlike shapes is a lie that completes wrongly |
49
+ * | empty array / `null` | the key, shape unknown | the key's presence is the useful half; dropping it loses a real field |
50
+ * | a string containing JSON | `type: string` | the runtime hands the transformation a STRING; guessing structure outruns it |
51
+ */
52
+ export declare function inferHints(payload: unknown, options?: InferOptions): InferredHints;
53
+ /**
54
+ * Merge two hint blocks — Story 8.12's "a second paste merges, it does not overwrite".
55
+ *
56
+ * ⛔ A thinner payload must not DOWNGRADE what is already declared. Two payloads describe the same entity more
57
+ * completely than either alone — the optional field that appeared on neither is the whole reason to paste twice.
58
+ */
59
+ export declare function mergeHint(existing: Record<string, unknown>, incoming: Record<string, unknown>): Record<string, unknown>;
60
+ /** Merge a whole `dataHints` map, path by path. */
61
+ export declare function mergeHints(existing: Record<string, unknown>, incoming: Record<string, unknown>): Record<string, unknown>;
62
+ //# sourceMappingURL=hints.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hints.d.ts","sourceRoot":"","sources":["../src/hints.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,KAAK,EACV,KAAK,KAAK,EACX,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;;GAUG;AACH,eAAO,MAAM,sBAAsB,YACjC,SAAS,EACT,UAAU,EACV,SAAS,EACT,MAAM,EACN,OAAO,CACC,CAAC;AAEX,8GAA8G;AAC9G,eAAO,MAAM,gBAAgB,YAC3B,MAAM,EACN,YAAY,EACZ,OAAO,EACP,aAAa,CACL,CAAC;AAEX,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,SAAK,GAAG,SAAS,WAAW,EAAE,CAoC1E;AAED,gFAAgF;AAChF,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,CA+BpD;AAOD,wEAAwE;AACxE,wBAAgB,UAAU,CAAC,SAAS,EAAE,OAAO,GAAG,SAAS,KAAK,EAAE,CAO/D;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,wFAAwF;IACxF,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;CACzC;AAKD;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CACxB,OAAO,EAAE,OAAO,EAChB,OAAO,GAAE,YAAiB,GACzB,aAAa,CAiEf;AAKD;;;;;GAKG;AACH,wBAAgB,SAAS,CACvB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAqBzB;AAED,mDAAmD;AACnD,wBAAgB,UAAU,CACxB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAazB"}
package/dist/hints.js ADDED
@@ -0,0 +1,198 @@
1
+ import { arrayShape, field, objectShape, scalarShape, unknownShape, } from './shape.js';
2
+ /**
3
+ * `dataHints` — declaring the shape the platform cannot know (Stories 8.8 and 8.12).
4
+ *
5
+ * Layer 2 of the item is the decoded `__raw`, and **nothing in the project declares it**: it is the source system's
6
+ * payload. Yet the corpus references it constantly — `item.line_items[0].code` works at run time while no document
7
+ * says `line_items` has a `code`. `dataHints` closes exactly that hole and nothing else.
8
+ *
9
+ * ⛔ **Values never survive.** The schema forbids every value-bearing keyword — `example`, `examples`, `default`,
10
+ * `enum`, `const` — so a payload full of customer names cannot reach a template repository even by accident. This is
11
+ * the property's one hard rule, and the reason it is safe to paste a real payload into an editor at all.
12
+ */
13
+ export const VALUE_BEARING_KEYWORDS = [
14
+ 'example',
15
+ 'examples',
16
+ 'default',
17
+ 'enum',
18
+ 'const',
19
+ ];
20
+ /** The JSON-Schema subset a hint may use. Anything else is either a value or a constraint nobody consumes. */
21
+ export const ALLOWED_KEYWORDS = [
22
+ 'type',
23
+ 'properties',
24
+ 'items',
25
+ 'description',
26
+ ];
27
+ /**
28
+ * Validate a hints block. Returns every problem, so an author fixes them in one pass rather than one per save.
29
+ *
30
+ * ⚠️ A value-bearing keyword is an ERROR rather than a strip-and-continue. Silently removing it would leave the
31
+ * author believing the tool accepted their input, and the next paste would put the value back.
32
+ */
33
+ export function checkHints(hints, at = '') {
34
+ const problems = [];
35
+ if (!hints || typeof hints !== 'object' || Array.isArray(hints))
36
+ return problems;
37
+ for (const [key, value] of Object.entries(hints)) {
38
+ const path = at ? `${at}.${key}` : key;
39
+ if (VALUE_BEARING_KEYWORDS.includes(key)) {
40
+ problems.push({
41
+ path,
42
+ reason: `\`${key}\` carries a VALUE, and a hint declares only shape. A template repository is shared, so a value ` +
43
+ 'pasted from a real payload would be committed with it. Remove it — the shape is the useful half.',
44
+ });
45
+ continue;
46
+ }
47
+ if (at !== '' &&
48
+ !ALLOWED_KEYWORDS.includes(key) &&
49
+ at.endsWith('.properties') === false) {
50
+ // Keys under `properties` are field names and may be anything; keys elsewhere must be schema keywords.
51
+ if (/^(type|properties|items|description)$/.test(key) === false &&
52
+ at.includes('.properties.') === false) {
53
+ problems.push({
54
+ path,
55
+ reason: `\`${key}\` is not part of the hint subset. A hint uses only: ${ALLOWED_KEYWORDS.join(', ')}.`,
56
+ });
57
+ continue;
58
+ }
59
+ }
60
+ problems.push(...checkHints(value, path));
61
+ }
62
+ return problems;
63
+ }
64
+ /** Turn a validated hints block into the shape the engine completes against. */
65
+ export function shapeFromHints(hints) {
66
+ const node = hints;
67
+ const type = node?.['type'];
68
+ const description = typeof node?.['description'] === 'string'
69
+ ? node['description']
70
+ : undefined;
71
+ if (type === 'object') {
72
+ const properties = (node?.['properties'] ?? {});
73
+ return objectShape(Object.entries(properties).map(([name, child]) => field(name, shapeFromHints(child), { kind: 'hint' }, describe(child) ?? description)));
74
+ }
75
+ if (type === 'array') {
76
+ const items = node?.['items'];
77
+ return arrayShape(items === undefined
78
+ ? unknownShape('The hint declares an array but not its element shape.')
79
+ : shapeFromHints(items));
80
+ }
81
+ if (typeof type === 'string')
82
+ return scalarShape(type);
83
+ return unknownShape('The hint does not declare a type for this key.');
84
+ }
85
+ const describe = (node) => {
86
+ const value = node?.['description'];
87
+ return typeof value === 'string' ? value : undefined;
88
+ };
89
+ /** Every top-level hinted key as a field, for merging into the item. */
90
+ export function hintFields(dataHints) {
91
+ if (!dataHints || typeof dataHints !== 'object' || Array.isArray(dataHints))
92
+ return [];
93
+ return Object.entries(dataHints).map(([name, hint]) => field(name, shapeFromHints(hint), { kind: 'hint' }, describe(hint)));
94
+ }
95
+ const DEFAULT_DEPTH = 6;
96
+ const DEFAULT_BREADTH = 80;
97
+ /**
98
+ * Infer a hints block from a real payload — Story 8.12.
99
+ *
100
+ * The edge cases are what decide whether the output can be trusted, and each one below is the NON-obvious choice:
101
+ *
102
+ * | input | emitted | why not the obvious thing |
103
+ * | --- | --- | --- |
104
+ * | array of objects | `items` from the **union of every element** | element 0 is routinely the least complete; an optional field appears on element 7 |
105
+ * | heterogeneous array | `items` unknown, with the reason | a union of unlike shapes is a lie that completes wrongly |
106
+ * | empty array / `null` | the key, shape unknown | the key's presence is the useful half; dropping it loses a real field |
107
+ * | a string containing JSON | `type: string` | the runtime hands the transformation a STRING; guessing structure outruns it |
108
+ */
109
+ export function inferHints(payload, options = {}) {
110
+ const maxDepth = options.maxDepth ?? DEFAULT_DEPTH;
111
+ const maxProperties = options.maxProperties ?? DEFAULT_BREADTH;
112
+ const truncations = [];
113
+ const infer = (value, depth, at) => {
114
+ if (depth > maxDepth) {
115
+ truncations.push(`\`${at}\` is deeper than the ${maxDepth}-level cap, so its shape stops here.`);
116
+ return {};
117
+ }
118
+ if (value === null)
119
+ return {}; // The key survives; its type does not (see the table above).
120
+ if (Array.isArray(value)) {
121
+ if (value.length === 0)
122
+ return { type: 'array' };
123
+ const kinds = new Set(value.map((element) => kindOf(element)));
124
+ if (kinds.size > 1) {
125
+ truncations.push(`\`${at}\` holds elements of more than one kind, so its element shape is not declared.`);
126
+ return { type: 'array' };
127
+ }
128
+ // ⛔ The UNION of every element, not the first.
129
+ const merged = value.reduce((all, element) => mergeHint(all, infer(element, depth + 1, `${at}[]`)), {});
130
+ return { type: 'array', items: merged };
131
+ }
132
+ if (typeof value === 'object') {
133
+ const entries = Object.entries(value);
134
+ const kept = entries.slice(0, maxProperties);
135
+ if (kept.length < entries.length) {
136
+ truncations.push(`\`${at}\` has ${entries.length} keys, more than the ${maxProperties}-key cap — ${entries.length - kept.length} are not declared.`);
137
+ }
138
+ return {
139
+ type: 'object',
140
+ properties: Object.fromEntries(kept.map(([key, child]) => [
141
+ key,
142
+ infer(child, depth + 1, at ? `${at}.${key}` : key),
143
+ ])),
144
+ };
145
+ }
146
+ // ⛔ A string stays a string even when its content parses as JSON.
147
+ return {
148
+ type: typeof value === 'number'
149
+ ? 'number'
150
+ : typeof value === 'boolean'
151
+ ? 'boolean'
152
+ : 'string',
153
+ };
154
+ };
155
+ const root = infer(payload, 1, '');
156
+ const properties = (root['properties'] ?? {});
157
+ return { hints: properties, truncations };
158
+ }
159
+ const kindOf = (value) => value === null ? 'null' : Array.isArray(value) ? 'array' : typeof value;
160
+ /**
161
+ * Merge two hint blocks — Story 8.12's "a second paste merges, it does not overwrite".
162
+ *
163
+ * ⛔ A thinner payload must not DOWNGRADE what is already declared. Two payloads describe the same entity more
164
+ * completely than either alone — the optional field that appeared on neither is the whole reason to paste twice.
165
+ */
166
+ export function mergeHint(existing, incoming) {
167
+ const merged = { ...existing };
168
+ for (const [key, value] of Object.entries(incoming)) {
169
+ const current = merged[key];
170
+ if (key === 'properties' || key === 'items') {
171
+ merged[key] =
172
+ current &&
173
+ typeof current === 'object' &&
174
+ value &&
175
+ typeof value === 'object'
176
+ ? mergeHint(current, value)
177
+ : (current ?? value);
178
+ continue;
179
+ }
180
+ // An existing declaration wins: the first paste may have seen a field this one did not.
181
+ if (current === undefined)
182
+ merged[key] = value;
183
+ }
184
+ return merged;
185
+ }
186
+ /** Merge a whole `dataHints` map, path by path. */
187
+ export function mergeHints(existing, incoming) {
188
+ const merged = { ...existing };
189
+ for (const [key, value] of Object.entries(incoming)) {
190
+ const current = merged[key];
191
+ merged[key] =
192
+ current && typeof current === 'object'
193
+ ? mergeHint(current, value)
194
+ : value;
195
+ }
196
+ return merged;
197
+ }
198
+ //# sourceMappingURL=hints.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hints.js","sourceRoot":"","sources":["../src/hints.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export * from './shape.js';
2
+ export * from './position.js';
3
+ export * from './environment.js';
4
+ export * from './detect.js';
5
+ export * from './completion.js';
6
+ export * from './stepOutputs.js';
7
+ export * from './item.js';
8
+ export * from './references.js';
9
+ export * from './hints.js';
10
+ export * from './survival.js';
11
+ export * from './walk.js';
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,12 @@
1
+ export * from './shape.js';
2
+ export * from './position.js';
3
+ export * from './environment.js';
4
+ export * from './detect.js';
5
+ export * from './completion.js';
6
+ export * from './stepOutputs.js';
7
+ export * from './item.js';
8
+ export * from './references.js';
9
+ export * from './hints.js';
10
+ export * from './survival.js';
11
+ export * from './walk.js';
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC"}