@tai42/studio-sdk 13.3.0 → 15.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/components.css +19 -0
- package/dist/components/icons.d.ts +2 -0
- package/dist/components/icons.d.ts.map +1 -1
- package/dist/components/icons.js +2 -0
- package/dist/components/icons.js.map +1 -1
- package/dist/components/templated-text-field.d.ts +98 -0
- package/dist/components/templated-text-field.d.ts.map +1 -0
- package/dist/components/templated-text-field.js +217 -0
- package/dist/components/templated-text-field.js.map +1 -0
- package/dist/hooks/useApi.d.ts +461 -59
- package/dist/hooks/useApi.d.ts.map +1 -1
- package/dist/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/navigation/types.d.ts +2 -1
- package/dist/navigation/types.d.ts.map +1 -1
- package/dist/query-keys.d.ts +13 -0
- package/dist/query-keys.d.ts.map +1 -1
- package/dist/query-keys.js +13 -0
- package/dist/query-keys.js.map +1 -1
- package/dist/state-binding/AdapterMapping.d.ts +33 -0
- package/dist/state-binding/AdapterMapping.d.ts.map +1 -0
- package/dist/state-binding/AdapterMapping.js +205 -0
- package/dist/state-binding/AdapterMapping.js.map +1 -0
- package/dist/state-binding/BindingJqField.d.ts +43 -0
- package/dist/state-binding/BindingJqField.d.ts.map +1 -0
- package/dist/state-binding/BindingJqField.js +57 -0
- package/dist/state-binding/BindingJqField.js.map +1 -0
- package/dist/state-binding/BindingTemplatedJqField.d.ts +24 -0
- package/dist/state-binding/BindingTemplatedJqField.d.ts.map +1 -0
- package/dist/state-binding/BindingTemplatedJqField.js +7 -0
- package/dist/state-binding/BindingTemplatedJqField.js.map +1 -0
- package/dist/state-binding/InputInjectionRow.d.ts +18 -0
- package/dist/state-binding/InputInjectionRow.d.ts.map +1 -0
- package/dist/state-binding/InputInjectionRow.js +55 -0
- package/dist/state-binding/InputInjectionRow.js.map +1 -0
- package/dist/state-binding/StateAttachRow.d.ts +27 -0
- package/dist/state-binding/StateAttachRow.d.ts.map +1 -0
- package/dist/state-binding/StateAttachRow.js +102 -0
- package/dist/state-binding/StateAttachRow.js.map +1 -0
- package/dist/state-binding/StateBindingEditor.d.ts +37 -0
- package/dist/state-binding/StateBindingEditor.d.ts.map +1 -0
- package/dist/state-binding/StateBindingEditor.js +54 -0
- package/dist/state-binding/StateBindingEditor.js.map +1 -0
- package/dist/state-binding/StateBindingSection.d.ts +14 -0
- package/dist/state-binding/StateBindingSection.d.ts.map +1 -0
- package/dist/state-binding/StateBindingSection.js +17 -0
- package/dist/state-binding/StateBindingSection.js.map +1 -0
- package/dist/state-binding/SubjectScopeFields.d.ts +20 -0
- package/dist/state-binding/SubjectScopeFields.d.ts.map +1 -0
- package/dist/state-binding/SubjectScopeFields.js +8 -0
- package/dist/state-binding/SubjectScopeFields.js.map +1 -0
- package/dist/state-binding/UpdateRow.d.ts +20 -0
- package/dist/state-binding/UpdateRow.d.ts.map +1 -0
- package/dist/state-binding/UpdateRow.js +89 -0
- package/dist/state-binding/UpdateRow.js.map +1 -0
- package/dist/state-binding/adapter.d.ts +93 -0
- package/dist/state-binding/adapter.d.ts.map +1 -0
- package/dist/state-binding/adapter.js +251 -0
- package/dist/state-binding/adapter.js.map +1 -0
- package/dist/state-binding/build-catalog.d.ts +19 -0
- package/dist/state-binding/build-catalog.d.ts.map +1 -0
- package/dist/state-binding/build-catalog.js +43 -0
- package/dist/state-binding/build-catalog.js.map +1 -0
- package/dist/state-binding/catalog.d.ts +26 -0
- package/dist/state-binding/catalog.d.ts.map +1 -0
- package/dist/state-binding/catalog.js +71 -0
- package/dist/state-binding/catalog.js.map +1 -0
- package/dist/state-binding/index.d.ts +33 -0
- package/dist/state-binding/index.d.ts.map +1 -0
- package/dist/state-binding/index.js +20 -0
- package/dist/state-binding/index.js.map +1 -0
- package/dist/state-binding/templated-text-catalog.d.ts +21 -0
- package/dist/state-binding/templated-text-catalog.d.ts.map +1 -0
- package/dist/state-binding/templated-text-catalog.js +48 -0
- package/dist/state-binding/templated-text-catalog.js.map +1 -0
- package/dist/state-binding/types.d.ts +78 -0
- package/dist/state-binding/types.d.ts.map +1 -0
- package/dist/state-binding/types.js +2 -0
- package/dist/state-binding/types.js.map +1 -0
- package/package.json +5 -5
- package/src/components/components.css +19 -0
- package/src/components/icons.tsx +8 -0
- package/src/components/templated-text-field.tsx +508 -0
- package/src/index.ts +76 -1
- package/src/navigation/types.ts +4 -1
- package/src/query-keys.ts +15 -0
- package/src/state-binding/AdapterMapping.tsx +468 -0
- package/src/state-binding/BindingJqField.tsx +146 -0
- package/src/state-binding/BindingTemplatedJqField.tsx +73 -0
- package/src/state-binding/InputInjectionRow.tsx +157 -0
- package/src/state-binding/README.md +46 -0
- package/src/state-binding/StateAttachRow.tsx +289 -0
- package/src/state-binding/StateBindingEditor.tsx +166 -0
- package/src/state-binding/StateBindingSection.tsx +37 -0
- package/src/state-binding/SubjectScopeFields.tsx +57 -0
- package/src/state-binding/UpdateRow.tsx +227 -0
- package/src/state-binding/adapter.ts +276 -0
- package/src/state-binding/build-catalog.ts +59 -0
- package/src/state-binding/catalog.ts +87 -0
- package/src/state-binding/index.ts +67 -0
- package/src/state-binding/templated-text-catalog.ts +69 -0
- package/src/state-binding/types.ts +91 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Badge } from '../components/badge';
|
|
3
|
+
import { Button } from '../components/primitives';
|
|
4
|
+
import { Field } from '../components/field';
|
|
5
|
+
import { Select } from '../components/select';
|
|
6
|
+
import { TemplatedTextField } from '../components/templated-text-field';
|
|
7
|
+
import { CloseIcon } from '../components/icons';
|
|
8
|
+
import { AdapterMapping } from './AdapterMapping';
|
|
9
|
+
import { BindingTemplatedJqField } from './BindingTemplatedJqField';
|
|
10
|
+
import { findByRef } from './catalog';
|
|
11
|
+
const CUSTOM = '__custom__';
|
|
12
|
+
function optionLabel(entry) {
|
|
13
|
+
return entry.description !== undefined && entry.description !== ''
|
|
14
|
+
? `${entry.ref} — ${entry.description}`
|
|
15
|
+
: entry.ref;
|
|
16
|
+
}
|
|
17
|
+
function writesLabel(entry) {
|
|
18
|
+
if (entry?.writes === undefined || entry.writes.length === 0)
|
|
19
|
+
return null;
|
|
20
|
+
return entry.writes.map((path) => path.join('.')).join(', ');
|
|
21
|
+
}
|
|
22
|
+
function UpdateRowEditor({ update, index, updateJq, sources, suggestions, templates, onChange, onRemove, }) {
|
|
23
|
+
const isCustom = update.jq !== null;
|
|
24
|
+
const selectValue = isCustom ? CUSTOM : (update.template_jq ?? '');
|
|
25
|
+
const resolved = update.template_jq !== null ? findByRef(update.template_jq, updateJq) : undefined;
|
|
26
|
+
const writes = writesLabel(resolved);
|
|
27
|
+
return (_jsxs("div", { "data-testid": `update-row-${String(index)}`, style: {
|
|
28
|
+
display: 'flex',
|
|
29
|
+
flexDirection: 'column',
|
|
30
|
+
gap: 'var(--tai-space-2)',
|
|
31
|
+
padding: 'var(--tai-space-2)',
|
|
32
|
+
border: '1px solid var(--tai-color-border)',
|
|
33
|
+
borderRadius: 'var(--tai-radius-md)',
|
|
34
|
+
}, children: [_jsxs("div", { style: {
|
|
35
|
+
display: 'flex',
|
|
36
|
+
gap: 'var(--tai-space-2)',
|
|
37
|
+
alignItems: 'center',
|
|
38
|
+
flexWrap: 'wrap',
|
|
39
|
+
}, children: [_jsx(Field, { label: `Update source ${String(index + 1)}`, hideLabel: true, children: _jsx(Select, { placeholder: "Choose a template jq", value: selectValue, onValueChange: (next) => {
|
|
40
|
+
if (next === CUSTOM)
|
|
41
|
+
onChange({
|
|
42
|
+
template_jq: null,
|
|
43
|
+
jq: { content: '' },
|
|
44
|
+
adapter: null,
|
|
45
|
+
op_id: update.op_id,
|
|
46
|
+
});
|
|
47
|
+
else
|
|
48
|
+
onChange({ template_jq: next, jq: null, adapter: null, op_id: update.op_id });
|
|
49
|
+
}, groups: [
|
|
50
|
+
{
|
|
51
|
+
label: 'Template jq',
|
|
52
|
+
options: updateJq.map((entry) => ({ value: entry.ref, label: optionLabel(entry) })),
|
|
53
|
+
},
|
|
54
|
+
{ label: 'Custom', options: [{ value: CUSTOM, label: 'Custom jq' }] },
|
|
55
|
+
] }) }), writes !== null ? _jsx(Badge, { variant: "neutral", children: `writes: ${writes}` }) : null, _jsx(Button, { type: "button", variant: "ghost", "aria-label": `Remove update ${String(index + 1)}`, onClick: onRemove, children: _jsx(CloseIcon, { "aria-hidden": "true" }) })] }), isCustom ? (_jsx(BindingTemplatedJqField, { label: `Custom update jq ${String(index + 1)}`, required: true, description: "A jq over `{ record, output, input }` returning a template-relative op batch.", value: update.jq, onChange: (next) => {
|
|
56
|
+
onChange({
|
|
57
|
+
template_jq: null,
|
|
58
|
+
jq: next ?? { content: '' },
|
|
59
|
+
adapter: null,
|
|
60
|
+
op_id: update.op_id,
|
|
61
|
+
});
|
|
62
|
+
}, suggestions: suggestions, templates: templates })) : (_jsx(TemplatedTextField
|
|
63
|
+
// Remount on a template change so the mapping rebuilds from the newly
|
|
64
|
+
// declared input (and re-seeds its shown default) instead of stale rows.
|
|
65
|
+
, { label: "Adapter", value: update.adapter, templates: templates?.templates, templatesLoading: templates?.loading, templatesError: templates?.error, onTemplatesRetry: templates?.onRetry, storageAbsent: templates?.storageAbsent, storagePresenceLoading: templates?.storagePresenceLoading, onChange: (next) => {
|
|
66
|
+
onChange({ ...update, adapter: next });
|
|
67
|
+
}, renderInline: ({ value: inlineValue, onChange: onInline }) => (_jsx(AdapterMapping, { declaredInput: resolved?.params ?? [], value: inlineValue, sources: sources, suggestions: suggestions, onChange: (adapterJq) => {
|
|
68
|
+
onInline(adapterJq ?? '');
|
|
69
|
+
} })) }, resolved?.ref ?? '__none__')), _jsx(BindingTemplatedJqField, { label: "Op id", description: "Optional \u2014 an idempotency-key expression.", value: update.op_id, onChange: (next) => {
|
|
70
|
+
onChange({ ...update, op_id: next });
|
|
71
|
+
}, suggestions: suggestions, templates: templates })] }));
|
|
72
|
+
}
|
|
73
|
+
export function UpdateList({ updates, onChange, updateJq, sources, suggestions, templates, }) {
|
|
74
|
+
const add = () => {
|
|
75
|
+
const first = updateJq[0];
|
|
76
|
+
const next = first !== undefined
|
|
77
|
+
? { template_jq: first.ref, jq: null, adapter: null, op_id: null }
|
|
78
|
+
: { template_jq: null, jq: { content: '' }, adapter: null, op_id: null };
|
|
79
|
+
onChange([...updates, next]);
|
|
80
|
+
};
|
|
81
|
+
return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 'var(--tai-space-2)' }, children: [updates.map((update, index) => (_jsx(UpdateRowEditor
|
|
82
|
+
// Rows are positional; the index is their stable identity within a save.
|
|
83
|
+
, { update: update, index: index, updateJq: updateJq, sources: sources, suggestions: suggestions, templates: templates, onChange: (next) => {
|
|
84
|
+
onChange(updates.map((current, position) => (position === index ? next : current)));
|
|
85
|
+
}, onRemove: () => {
|
|
86
|
+
onChange(updates.filter((_, position) => position !== index));
|
|
87
|
+
} }, index))), _jsx("div", { children: _jsx(Button, { type: "button", variant: "ghost", onClick: add, children: "Add update" }) })] }));
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=UpdateRow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UpdateRow.js","sourceRoot":"","sources":["../../src/state-binding/UpdateRow.tsx"],"names":[],"mappings":";AAQA,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAClD,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AACxE,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAEpE,OAAO,EAAE,SAAS,EAA2B,MAAM,WAAW,CAAC;AAG/D,MAAM,MAAM,GAAG,YAAY,CAAC;AAE5B,SAAS,WAAW,CAAC,KAAyB;IAC5C,OAAO,KAAK,CAAC,WAAW,KAAK,SAAS,IAAI,KAAK,CAAC,WAAW,KAAK,EAAE;QAChE,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,MAAM,KAAK,CAAC,WAAW,EAAE;QACvC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC;AAChB,CAAC;AAED,SAAS,WAAW,CAAC,KAAqC;IACxD,IAAI,KAAK,EAAE,MAAM,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1E,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC/D,CAAC;AAED,SAAS,eAAe,CAAC,EACvB,MAAM,EACN,KAAK,EACL,QAAQ,EACR,OAAO,EACP,WAAW,EACX,SAAS,EACT,QAAQ,EACR,QAAQ,GAUT;IACC,MAAM,QAAQ,GAAG,MAAM,CAAC,EAAE,KAAK,IAAI,CAAC;IACpC,MAAM,WAAW,GAAG,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;IACnE,MAAM,QAAQ,GACZ,MAAM,CAAC,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACpF,MAAM,MAAM,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;IAErC,OAAO,CACL,8BACe,cAAc,MAAM,CAAC,KAAK,CAAC,EAAE,EAC1C,KAAK,EAAE;YACL,OAAO,EAAE,MAAM;YACf,aAAa,EAAE,QAAQ;YACvB,GAAG,EAAE,oBAAoB;YACzB,OAAO,EAAE,oBAAoB;YAC7B,MAAM,EAAE,mCAAmC;YAC3C,YAAY,EAAE,sBAAsB;SACrC,aAED,eACE,KAAK,EAAE;oBACL,OAAO,EAAE,MAAM;oBACf,GAAG,EAAE,oBAAoB;oBACzB,UAAU,EAAE,QAAQ;oBACpB,QAAQ,EAAE,MAAM;iBACjB,aAED,KAAC,KAAK,IAAC,KAAK,EAAE,iBAAiB,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,EAAE,SAAS,kBAC3D,KAAC,MAAM,IACL,WAAW,EAAC,sBAAsB,EAClC,KAAK,EAAE,WAAW,EAClB,aAAa,EAAE,CAAC,IAAI,EAAE,EAAE;gCACtB,IAAI,IAAI,KAAK,MAAM;oCACjB,QAAQ,CAAC;wCACP,WAAW,EAAE,IAAI;wCACjB,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE;wCACnB,OAAO,EAAE,IAAI;wCACb,KAAK,EAAE,MAAM,CAAC,KAAK;qCACpB,CAAC,CAAC;;oCACA,QAAQ,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;4BACrF,CAAC,EACD,MAAM,EAAE;gCACN;oCACE,KAAK,EAAE,aAAa;oCACpB,OAAO,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,EAAE,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;iCACpF;gCACD,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,EAAE;6BACtE,GACD,GACI,EACP,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,KAAC,KAAK,IAAC,OAAO,EAAC,SAAS,YAAE,WAAW,MAAM,EAAE,GAAS,CAAC,CAAC,CAAC,IAAI,EAChF,KAAC,MAAM,IACL,IAAI,EAAC,QAAQ,EACb,OAAO,EAAC,OAAO,gBACH,iBAAiB,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,EAChD,OAAO,EAAE,QAAQ,YAEjB,KAAC,SAAS,mBAAa,MAAM,GAAG,GACzB,IACL,EAEL,QAAQ,CAAC,CAAC,CAAC,CACV,KAAC,uBAAuB,IACtB,KAAK,EAAE,oBAAoB,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,EAC9C,QAAQ,QACR,WAAW,EAAC,+EAA+E,EAC3F,KAAK,EAAE,MAAM,CAAC,EAAE,EAChB,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE;oBACjB,QAAQ,CAAC;wBACP,WAAW,EAAE,IAAI;wBACjB,EAAE,EAAE,IAAI,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE;wBAC3B,OAAO,EAAE,IAAI;wBACb,KAAK,EAAE,MAAM,CAAC,KAAK;qBACpB,CAAC,CAAC;gBACL,CAAC,EACD,WAAW,EAAE,WAAW,EACxB,SAAS,EAAE,SAAS,GACpB,CACH,CAAC,CAAC,CAAC,CACF,KAAC,kBAAkB;YACjB,sEAAsE;YACtE,yEAAyE;gBAEzE,KAAK,EAAC,SAAS,EACf,KAAK,EAAE,MAAM,CAAC,OAAO,EACrB,SAAS,EAAE,SAAS,EAAE,SAAS,EAC/B,gBAAgB,EAAE,SAAS,EAAE,OAAO,EACpC,cAAc,EAAE,SAAS,EAAE,KAAK,EAChC,gBAAgB,EAAE,SAAS,EAAE,OAAO,EACpC,aAAa,EAAE,SAAS,EAAE,aAAa,EACvC,sBAAsB,EAAE,SAAS,EAAE,sBAAsB,EACzD,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE;oBACjB,QAAQ,CAAC,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;gBACzC,CAAC,EACD,YAAY,EAAE,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAC5D,KAAC,cAAc,IACb,aAAa,EAAE,QAAQ,EAAE,MAAM,IAAI,EAAE,EACrC,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,CAAC,SAAS,EAAE,EAAE;wBACtB,QAAQ,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;oBAC5B,CAAC,GACD,CACH,IAtBI,QAAQ,EAAE,GAAG,IAAI,UAAU,CAuBhC,CACH,EAED,KAAC,uBAAuB,IACtB,KAAK,EAAC,OAAO,EACb,WAAW,EAAC,gDAA2C,EACvD,KAAK,EAAE,MAAM,CAAC,KAAK,EACnB,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE;oBACjB,QAAQ,CAAC,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;gBACvC,CAAC,EACD,WAAW,EAAE,WAAW,EACxB,SAAS,EAAE,SAAS,GACpB,IACE,CACP,CAAC;AACJ,CAAC;AAWD,MAAM,UAAU,UAAU,CAAC,EACzB,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,WAAW,EACX,SAAS,GACO;IAChB,MAAM,GAAG,GAAG,GAAS,EAAE;QACrB,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QAC1B,MAAM,IAAI,GACR,KAAK,KAAK,SAAS;YACjB,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE;YAClE,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QAC7E,QAAQ,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;IAC/B,CAAC,CAAC;IAEF,OAAO,CACL,eAAK,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,GAAG,EAAE,oBAAoB,EAAE,aAChF,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAC9B,KAAC,eAAe;YACd,yEAAyE;gBAEzE,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,WAAW,EACxB,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE;oBACjB,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;gBACtF,CAAC,EACD,QAAQ,EAAE,GAAG,EAAE;oBACb,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,CAAC,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC;gBAChE,CAAC,IAZI,KAAK,CAaV,CACH,CAAC,EACF,wBACE,KAAC,MAAM,IAAC,IAAI,EAAC,QAAQ,EAAC,OAAO,EAAC,OAAO,EAAC,OAAO,EAAE,GAAG,2BAEzC,GACL,IACF,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The adapter compiler — a PURE function set, no React, no jq engine.
|
|
3
|
+
*
|
|
4
|
+
* A named template `update` jq declares an input object (its `params` / declared
|
|
5
|
+
* input keys). A binding must map the run's OUTPUT (and the run's INPUT) into that
|
|
6
|
+
* object; that mapping is the `adapter` — a single jq program over `{ output, input }`
|
|
7
|
+
* that CONSTRUCTS the update jq's declared input (which the update jq then reads as
|
|
8
|
+
* `.input` alongside the record).
|
|
9
|
+
*
|
|
10
|
+
* The editor authors the adapter as a ROW form: one row per declared input key,
|
|
11
|
+
* each row picking one of three value sources — a picked field (from the run's
|
|
12
|
+
* output / input schema), a hardcoded literal, or a raw jq expression. The whole
|
|
13
|
+
* form compiles here into ONE adapter jq; each row's own jq fragment is shown on demand.
|
|
14
|
+
*
|
|
15
|
+
* Compilation never throws: an invalid literal or an empty field surfaces as a
|
|
16
|
+
* loud, human error the editor renders in a `role="alert"`, never a silent empty
|
|
17
|
+
* object.
|
|
18
|
+
*/
|
|
19
|
+
/** Which root of `{ output, input }` a picked field reads. */
|
|
20
|
+
export type FieldRoot = 'output' | 'input';
|
|
21
|
+
/** A picked field: a path into `output` or `input`. */
|
|
22
|
+
export interface FieldSource {
|
|
23
|
+
readonly kind: 'field';
|
|
24
|
+
readonly root: FieldRoot;
|
|
25
|
+
readonly path: readonly string[];
|
|
26
|
+
}
|
|
27
|
+
/** A hardcoded literal, authored as JSON text (`"a"`, `42`, `true`, `{…}`). */
|
|
28
|
+
export interface LiteralSource {
|
|
29
|
+
readonly kind: 'literal';
|
|
30
|
+
readonly json: string;
|
|
31
|
+
}
|
|
32
|
+
/** A raw jq expression over `{ output, input }`. */
|
|
33
|
+
export interface JqSource {
|
|
34
|
+
readonly kind: 'jq';
|
|
35
|
+
readonly expr: string;
|
|
36
|
+
}
|
|
37
|
+
/** The three value sources one mapping row may carry — exactly one at a time. */
|
|
38
|
+
export type MappingSource = FieldSource | LiteralSource | JqSource;
|
|
39
|
+
/** One mapping row: a target key of the update jq's declared input + its value source. */
|
|
40
|
+
export interface MappingRow {
|
|
41
|
+
readonly target: string;
|
|
42
|
+
readonly source: MappingSource;
|
|
43
|
+
}
|
|
44
|
+
/** A compile outcome: the jq program, or a human error to surface loudly. */
|
|
45
|
+
export type AdapterCompileResult = {
|
|
46
|
+
readonly ok: true;
|
|
47
|
+
readonly jq: string;
|
|
48
|
+
} | {
|
|
49
|
+
readonly ok: false;
|
|
50
|
+
readonly error: string;
|
|
51
|
+
};
|
|
52
|
+
/** An object key rendered for jq: a bare identifier, or a quoted string otherwise. */
|
|
53
|
+
export declare function jqKey(key: string): string;
|
|
54
|
+
/** A picked field rendered as a jq path, e.g. `.output.user.name` / `.input["odd key"]`. */
|
|
55
|
+
export declare function fieldPathToJq(root: FieldRoot, path: readonly string[]): string;
|
|
56
|
+
/** The jq fragment ONE row's value compiles to — the row's "show jq". */
|
|
57
|
+
export declare function rowValueJq(source: MappingSource): AdapterCompileResult;
|
|
58
|
+
/**
|
|
59
|
+
* Compile a mapping form into ONE adapter jq that constructs the update jq's
|
|
60
|
+
* declared input over `{ output, input }`. An empty form compiles to the
|
|
61
|
+
* empty object `{}`; a blank target, a duplicate target, or an invalid source is a
|
|
62
|
+
* loud error.
|
|
63
|
+
*/
|
|
64
|
+
export declare function compileAdapter(rows: readonly MappingRow[]): AdapterCompileResult;
|
|
65
|
+
/** One row per declared input key, each defaulting to a picked `output` field. */
|
|
66
|
+
export declare function defaultRowsForInput(params: readonly string[]): MappingRow[];
|
|
67
|
+
/** Recover a field source from a pure path expression, or `null` if it is not one. */
|
|
68
|
+
export declare function parseFieldPath(value: string): FieldSource | null;
|
|
69
|
+
/** Recover the mapping rows from a stored adapter jq, or `null` if it is not the generated shape. */
|
|
70
|
+
export declare function parseAdapter(jq: string): MappingRow[] | null;
|
|
71
|
+
/**
|
|
72
|
+
* Encode a template-name slug for a jq identifier: each `-` becomes `_`. Under the slug
|
|
73
|
+
* invariant (no consecutive or trailing hyphens) the result carries no `__` and no
|
|
74
|
+
* trailing `_`, which is what makes the first `__` in a call name the template boundary.
|
|
75
|
+
*/
|
|
76
|
+
export declare function encodeTemplateSegment(template: string): string;
|
|
77
|
+
/**
|
|
78
|
+
* The single-expression form of a named template update built from a mapping form:
|
|
79
|
+
* `tjq_<enc(template)>__<name>({…})` for a qualified ref, `tjq_<name>({…})` for a bare
|
|
80
|
+
* one (see the module note on the `__` boundary invariant).
|
|
81
|
+
*/
|
|
82
|
+
export declare function generateTemplateCall(ref: string, rows: readonly MappingRow[]): string;
|
|
83
|
+
/**
|
|
84
|
+
* Recover `{ callName, adapter }` from a `tjq_<callName>(<adapter>)` call, or `null`
|
|
85
|
+
* otherwise. `callName` is the RAW jq identifier — NEVER split here (a jq name may carry
|
|
86
|
+
* its own `__` past the template boundary); resolve it to a catalog ref with
|
|
87
|
+
* `resolveCallName`.
|
|
88
|
+
*/
|
|
89
|
+
export declare function parseTemplateCall(expr: string): {
|
|
90
|
+
callName: string;
|
|
91
|
+
adapter: string;
|
|
92
|
+
} | null;
|
|
93
|
+
//# sourceMappingURL=adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/state-binding/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,8DAA8D;AAC9D,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE3C,uDAAuD;AACvD,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;CAClC;AAED,+EAA+E;AAC/E,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,oDAAoD;AACpD,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,iFAAiF;AACjF,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,aAAa,GAAG,QAAQ,CAAC;AAEnE,0FAA0F;AAC1F,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;CAChC;AAED,6EAA6E;AAC7E,MAAM,MAAM,oBAAoB,GAC9B;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAI9F,sFAAsF;AACtF,wBAAgB,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEzC;AAED,4FAA4F;AAC5F,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAM9E;AAED,yEAAyE;AACzE,wBAAgB,UAAU,CAAC,MAAM,EAAE,aAAa,GAAG,oBAAoB,CAsBtE;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,UAAU,EAAE,GAAG,oBAAoB,CAchF;AAED,kFAAkF;AAClF,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,UAAU,EAAE,CAK3E;AAgBD,sFAAsF;AACtF,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAuBhE;AAmCD,qGAAqG;AACrG,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,UAAU,EAAE,GAAG,IAAI,CAqB5D;AAmBD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE9D;AASD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,UAAU,EAAE,GAAG,MAAM,CAGrF;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAI5F"}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The adapter compiler — a PURE function set, no React, no jq engine.
|
|
3
|
+
*
|
|
4
|
+
* A named template `update` jq declares an input object (its `params` / declared
|
|
5
|
+
* input keys). A binding must map the run's OUTPUT (and the run's INPUT) into that
|
|
6
|
+
* object; that mapping is the `adapter` — a single jq program over `{ output, input }`
|
|
7
|
+
* that CONSTRUCTS the update jq's declared input (which the update jq then reads as
|
|
8
|
+
* `.input` alongside the record).
|
|
9
|
+
*
|
|
10
|
+
* The editor authors the adapter as a ROW form: one row per declared input key,
|
|
11
|
+
* each row picking one of three value sources — a picked field (from the run's
|
|
12
|
+
* output / input schema), a hardcoded literal, or a raw jq expression. The whole
|
|
13
|
+
* form compiles here into ONE adapter jq; each row's own jq fragment is shown on demand.
|
|
14
|
+
*
|
|
15
|
+
* Compilation never throws: an invalid literal or an empty field surfaces as a
|
|
16
|
+
* loud, human error the editor renders in a `role="alert"`, never a silent empty
|
|
17
|
+
* object.
|
|
18
|
+
*/
|
|
19
|
+
const IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
20
|
+
/** An object key rendered for jq: a bare identifier, or a quoted string otherwise. */
|
|
21
|
+
export function jqKey(key) {
|
|
22
|
+
return IDENTIFIER.test(key) ? key : JSON.stringify(key);
|
|
23
|
+
}
|
|
24
|
+
/** A picked field rendered as a jq path, e.g. `.output.user.name` / `.input["odd key"]`. */
|
|
25
|
+
export function fieldPathToJq(root, path) {
|
|
26
|
+
let out = `.${root}`;
|
|
27
|
+
for (const segment of path) {
|
|
28
|
+
out += IDENTIFIER.test(segment) ? `.${segment}` : `[${JSON.stringify(segment)}]`;
|
|
29
|
+
}
|
|
30
|
+
return out;
|
|
31
|
+
}
|
|
32
|
+
/** The jq fragment ONE row's value compiles to — the row's "show jq". */
|
|
33
|
+
export function rowValueJq(source) {
|
|
34
|
+
switch (source.kind) {
|
|
35
|
+
case 'field':
|
|
36
|
+
return { ok: true, jq: fieldPathToJq(source.root, source.path) };
|
|
37
|
+
case 'literal': {
|
|
38
|
+
const text = source.json.trim();
|
|
39
|
+
if (text === '')
|
|
40
|
+
return { ok: false, error: 'Enter a value.' };
|
|
41
|
+
let parsed;
|
|
42
|
+
try {
|
|
43
|
+
parsed = JSON.parse(text);
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return { ok: false, error: 'This is not valid JSON.' };
|
|
47
|
+
}
|
|
48
|
+
// A parsed JSON value is a valid jq literal verbatim.
|
|
49
|
+
return { ok: true, jq: JSON.stringify(parsed) };
|
|
50
|
+
}
|
|
51
|
+
case 'jq': {
|
|
52
|
+
const expr = source.expr.trim();
|
|
53
|
+
if (expr === '')
|
|
54
|
+
return { ok: false, error: 'Enter a jq expression.' };
|
|
55
|
+
return { ok: true, jq: expr };
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Compile a mapping form into ONE adapter jq that constructs the update jq's
|
|
61
|
+
* declared input over `{ output, input }`. An empty form compiles to the
|
|
62
|
+
* empty object `{}`; a blank target, a duplicate target, or an invalid source is a
|
|
63
|
+
* loud error.
|
|
64
|
+
*/
|
|
65
|
+
export function compileAdapter(rows) {
|
|
66
|
+
if (rows.length === 0)
|
|
67
|
+
return { ok: true, jq: '{}' };
|
|
68
|
+
const seen = new Set();
|
|
69
|
+
const parts = [];
|
|
70
|
+
for (const row of rows) {
|
|
71
|
+
const target = row.target.trim();
|
|
72
|
+
if (target === '')
|
|
73
|
+
return { ok: false, error: 'Every mapping row needs a target field.' };
|
|
74
|
+
if (seen.has(target))
|
|
75
|
+
return { ok: false, error: `The field '${target}' is mapped twice.` };
|
|
76
|
+
seen.add(target);
|
|
77
|
+
const value = rowValueJq(row.source);
|
|
78
|
+
if (!value.ok)
|
|
79
|
+
return { ok: false, error: `${target}: ${value.error}` };
|
|
80
|
+
parts.push(`${jqKey(target)}: (${value.jq})`);
|
|
81
|
+
}
|
|
82
|
+
return { ok: true, jq: `{ ${parts.join(', ')} }` };
|
|
83
|
+
}
|
|
84
|
+
/** One row per declared input key, each defaulting to a picked `output` field. */
|
|
85
|
+
export function defaultRowsForInput(params) {
|
|
86
|
+
return params.map((target) => ({
|
|
87
|
+
target,
|
|
88
|
+
source: { kind: 'field', root: 'output', path: [] },
|
|
89
|
+
}));
|
|
90
|
+
}
|
|
91
|
+
// -- The round-trip: recover a mapping form from a STORED adapter jq --------------
|
|
92
|
+
//
|
|
93
|
+
// `compileAdapter` emits a canonical, PARSEABLE shape so a stored adapter reopens as
|
|
94
|
+
// the form it was authored in (never UI-only state): the object
|
|
95
|
+
// `{ <key>: (<value>), … }` where `<key>` is a bare identifier or a JSON string and
|
|
96
|
+
// `<value>` is one of — a field path `.output…` / `.input…`, a JSON literal, or a raw
|
|
97
|
+
// jq expression. `parseAdapter` inverts it; `parse(compileAdapter(rows).jq) === rows`
|
|
98
|
+
// for every row kind whose literal is already canonical JSON. A shape it does not
|
|
99
|
+
// recognise returns `null` — the editor falls back to the raw-jq escape hatch.
|
|
100
|
+
const IDENTIFIER_HEAD = /^([A-Za-z_][A-Za-z0-9_]*)/;
|
|
101
|
+
const BRACKET_SEGMENT = /^\[("(?:[^"\\]|\\.)*")\]/;
|
|
102
|
+
const ADAPTER_KEY = /^("(?:[^"\\]|\\.)*"|[A-Za-z_][A-Za-z0-9_]*)\s*:\s*\(/;
|
|
103
|
+
/** Recover a field source from a pure path expression, or `null` if it is not one. */
|
|
104
|
+
export function parseFieldPath(value) {
|
|
105
|
+
const head = /^\.(output|input)/.exec(value);
|
|
106
|
+
if (head === null)
|
|
107
|
+
return null;
|
|
108
|
+
const root = head[1];
|
|
109
|
+
let rest = value.slice(head[0].length);
|
|
110
|
+
const path = [];
|
|
111
|
+
while (rest.length > 0) {
|
|
112
|
+
if (rest.startsWith('.')) {
|
|
113
|
+
const segment = IDENTIFIER_HEAD.exec(rest.slice(1));
|
|
114
|
+
if (segment?.[1] === undefined)
|
|
115
|
+
return null;
|
|
116
|
+
path.push(segment[1]);
|
|
117
|
+
rest = rest.slice(1 + segment[0].length);
|
|
118
|
+
}
|
|
119
|
+
else if (rest.startsWith('[')) {
|
|
120
|
+
const bracket = BRACKET_SEGMENT.exec(rest);
|
|
121
|
+
if (bracket?.[1] === undefined)
|
|
122
|
+
return null;
|
|
123
|
+
path.push(JSON.parse(bracket[1]));
|
|
124
|
+
rest = rest.slice(bracket[0].length);
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
// Trailing content (e.g. ` + 1`) means this is a jq expression, not a path.
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return { kind: 'field', root, path };
|
|
132
|
+
}
|
|
133
|
+
/** Classify one recovered value into its source (field, else JSON literal, else jq). */
|
|
134
|
+
function parseValue(value) {
|
|
135
|
+
const field = parseFieldPath(value);
|
|
136
|
+
if (field !== null)
|
|
137
|
+
return field;
|
|
138
|
+
try {
|
|
139
|
+
const parsed = JSON.parse(value);
|
|
140
|
+
return { kind: 'literal', json: JSON.stringify(parsed) };
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
return { kind: 'jq', expr: value };
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/** Find the index of the paren that closes the `(` at `open`, respecting jq strings. */
|
|
147
|
+
function matchingParen(text, open) {
|
|
148
|
+
let depth = 0;
|
|
149
|
+
let inString = false;
|
|
150
|
+
for (let i = open; i < text.length; i += 1) {
|
|
151
|
+
const ch = text[i];
|
|
152
|
+
if (inString) {
|
|
153
|
+
if (ch === '\\')
|
|
154
|
+
i += 1;
|
|
155
|
+
else if (ch === '"')
|
|
156
|
+
inString = false;
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
if (ch === '"')
|
|
160
|
+
inString = true;
|
|
161
|
+
else if (ch === '(')
|
|
162
|
+
depth += 1;
|
|
163
|
+
else if (ch === ')') {
|
|
164
|
+
depth -= 1;
|
|
165
|
+
if (depth === 0)
|
|
166
|
+
return i;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return -1;
|
|
170
|
+
}
|
|
171
|
+
/** Recover the mapping rows from a stored adapter jq, or `null` if it is not the generated shape. */
|
|
172
|
+
export function parseAdapter(jq) {
|
|
173
|
+
const trimmed = jq.trim();
|
|
174
|
+
if (trimmed === '{}')
|
|
175
|
+
return [];
|
|
176
|
+
if (!trimmed.startsWith('{') || !trimmed.endsWith('}'))
|
|
177
|
+
return null;
|
|
178
|
+
let inner = trimmed.slice(1, -1).trim();
|
|
179
|
+
const rows = [];
|
|
180
|
+
while (inner.length > 0) {
|
|
181
|
+
const keyMatch = ADAPTER_KEY.exec(inner);
|
|
182
|
+
if (keyMatch?.[1] === undefined)
|
|
183
|
+
return null;
|
|
184
|
+
const rawKey = keyMatch[1];
|
|
185
|
+
const target = rawKey.startsWith('"') ? JSON.parse(rawKey) : rawKey;
|
|
186
|
+
const open = keyMatch[0].length - 1;
|
|
187
|
+
const close = matchingParen(inner, open);
|
|
188
|
+
if (close === -1)
|
|
189
|
+
return null;
|
|
190
|
+
const value = inner.slice(open + 1, close).trim();
|
|
191
|
+
rows.push({ target, source: parseValue(value) });
|
|
192
|
+
inner = inner.slice(close + 1).trim();
|
|
193
|
+
if (inner.startsWith(','))
|
|
194
|
+
inner = inner.slice(1).trim();
|
|
195
|
+
else if (inner.length > 0)
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
return rows;
|
|
199
|
+
}
|
|
200
|
+
// -- The canonical single-expression form: `tjq_<callName>(<adapter object>)` --------
|
|
201
|
+
//
|
|
202
|
+
// When a template update rides inside ONE jq field (rather than the structured
|
|
203
|
+
// `template_jq` + `adapter` pair), it is written as the call `tjq_<callName>({ … })`.
|
|
204
|
+
// A jq name is `[a-z][a-z0-9_]*` (double underscores legal); a tai42 template name is a
|
|
205
|
+
// SLUG (`[a-z][a-z0-9-]*` with no leading, trailing, or consecutive hyphens). So the
|
|
206
|
+
// qualified call name is `enc(template) + "__" + name`, where `enc` maps each `-` to
|
|
207
|
+
// `_`. BECAUSE the slug has no consecutive or trailing hyphens, `enc(template)` never
|
|
208
|
+
// contains `__` and never ends in `_` — so the FIRST `__` in the call name is the
|
|
209
|
+
// unambiguous template/name boundary. Resolution back to a catalog ref is therefore
|
|
210
|
+
// injective, but done catalog-driven (`resolveCallName`, `catalog.ts`) rather than by
|
|
211
|
+
// string splitting, since a jq name may itself contain `__` after that boundary. A jq
|
|
212
|
+
// field whose expression is EXACTLY this generated call reopens as the mapping form;
|
|
213
|
+
// any other expression reopens as raw jq.
|
|
214
|
+
const TEMPLATE_CALL = /^tjq_([a-z][a-z0-9_]*)\(([\s\S]*)\)$/;
|
|
215
|
+
/**
|
|
216
|
+
* Encode a template-name slug for a jq identifier: each `-` becomes `_`. Under the slug
|
|
217
|
+
* invariant (no consecutive or trailing hyphens) the result carries no `__` and no
|
|
218
|
+
* trailing `_`, which is what makes the first `__` in a call name the template boundary.
|
|
219
|
+
*/
|
|
220
|
+
export function encodeTemplateSegment(template) {
|
|
221
|
+
return template.replace(/-/g, '_');
|
|
222
|
+
}
|
|
223
|
+
/** The jq call-name of a catalog ref: `template.name` → `enc(template)__name`; a bare `name` unchanged. */
|
|
224
|
+
function refToCallName(ref) {
|
|
225
|
+
const dot = ref.indexOf('.');
|
|
226
|
+
if (dot === -1)
|
|
227
|
+
return ref;
|
|
228
|
+
return `${encodeTemplateSegment(ref.slice(0, dot))}__${ref.slice(dot + 1)}`;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* The single-expression form of a named template update built from a mapping form:
|
|
232
|
+
* `tjq_<enc(template)>__<name>({…})` for a qualified ref, `tjq_<name>({…})` for a bare
|
|
233
|
+
* one (see the module note on the `__` boundary invariant).
|
|
234
|
+
*/
|
|
235
|
+
export function generateTemplateCall(ref, rows) {
|
|
236
|
+
const compiled = compileAdapter(rows);
|
|
237
|
+
return `tjq_${refToCallName(ref)}(${compiled.ok ? compiled.jq : '{}'})`;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Recover `{ callName, adapter }` from a `tjq_<callName>(<adapter>)` call, or `null`
|
|
241
|
+
* otherwise. `callName` is the RAW jq identifier — NEVER split here (a jq name may carry
|
|
242
|
+
* its own `__` past the template boundary); resolve it to a catalog ref with
|
|
243
|
+
* `resolveCallName`.
|
|
244
|
+
*/
|
|
245
|
+
export function parseTemplateCall(expr) {
|
|
246
|
+
const match = TEMPLATE_CALL.exec(expr.trim());
|
|
247
|
+
if (match?.[1] === undefined || match[2] === undefined)
|
|
248
|
+
return null;
|
|
249
|
+
return { callName: match[1], adapter: match[2].trim() };
|
|
250
|
+
}
|
|
251
|
+
//# sourceMappingURL=adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../src/state-binding/adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Map the api-client's list shapes into the editor's catalogs, so every door screen
|
|
3
|
+
* feeds `StateBindingEditor` the same way. Pure data transforms; the api-client types
|
|
4
|
+
* are imported type-only (this package keeps no runtime edge to the client).
|
|
5
|
+
*/
|
|
6
|
+
import type { StateListItem, StateTemplateListItem } from '@tai42/api-client';
|
|
7
|
+
import type { BindingStateOption, BindingTemplateOption, SchemaFieldPath } from './types';
|
|
8
|
+
/** The template catalog (with each template's template jq) from `listStateTemplates()`. */
|
|
9
|
+
export declare function templatesCatalogFromList(items: readonly StateTemplateListItem[]): BindingTemplateOption[];
|
|
10
|
+
/** The states catalog from `listStates()`; per-state attachments are resolved lazily elsewhere. */
|
|
11
|
+
export declare function statesCatalogFromList(states: readonly StateListItem[]): BindingStateOption[];
|
|
12
|
+
/**
|
|
13
|
+
* Flatten a JSON schema's `properties` into selectable field paths (top-level and
|
|
14
|
+
* every nested object level), each labelled with its dotted path — the picker source
|
|
15
|
+
* for the adapter's `output`/`input` roots. A non-object or property-less schema
|
|
16
|
+
* yields no fields (the field control then falls back to a free path input).
|
|
17
|
+
*/
|
|
18
|
+
export declare function fieldPathsFromSchema(schema: unknown): SchemaFieldPath[];
|
|
19
|
+
//# sourceMappingURL=build-catalog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-catalog.d.ts","sourceRoot":"","sources":["../../src/state-binding/build-catalog.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAE9E,OAAO,KAAK,EACV,kBAAkB,EAElB,qBAAqB,EACrB,eAAe,EAChB,MAAM,SAAS,CAAC;AAEjB,2FAA2F;AAC3F,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,SAAS,qBAAqB,EAAE,GACtC,qBAAqB,EAAE,CAczB;AAED,mGAAmG;AACnG,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,GAAG,kBAAkB,EAAE,CAE5F;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,OAAO,GAAG,eAAe,EAAE,CAcvE"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/** The template catalog (with each template's template jq) from `listStateTemplates()`. */
|
|
2
|
+
export function templatesCatalogFromList(items) {
|
|
3
|
+
return items.map((item) => {
|
|
4
|
+
const templateJq = item.template_jq === null
|
|
5
|
+
? []
|
|
6
|
+
: Object.entries(item.template_jq).map(([name, jq]) => ({
|
|
7
|
+
name,
|
|
8
|
+
purpose: jq.purpose,
|
|
9
|
+
description: jq.description,
|
|
10
|
+
params: jq.params,
|
|
11
|
+
writes: jq.writes,
|
|
12
|
+
}));
|
|
13
|
+
return { name: item.name, description: item.description, templateJq };
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
/** The states catalog from `listStates()`; per-state attachments are resolved lazily elsewhere. */
|
|
17
|
+
export function statesCatalogFromList(states) {
|
|
18
|
+
return states.map((state) => ({ name: state.name }));
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Flatten a JSON schema's `properties` into selectable field paths (top-level and
|
|
22
|
+
* every nested object level), each labelled with its dotted path — the picker source
|
|
23
|
+
* for the adapter's `output`/`input` roots. A non-object or property-less schema
|
|
24
|
+
* yields no fields (the field control then falls back to a free path input).
|
|
25
|
+
*/
|
|
26
|
+
export function fieldPathsFromSchema(schema) {
|
|
27
|
+
const out = [];
|
|
28
|
+
const walk = (node, prefix) => {
|
|
29
|
+
if (typeof node !== 'object' || node === null)
|
|
30
|
+
return;
|
|
31
|
+
const props = node.properties;
|
|
32
|
+
if (typeof props !== 'object' || props === null)
|
|
33
|
+
return;
|
|
34
|
+
for (const [key, child] of Object.entries(props)) {
|
|
35
|
+
const path = [...prefix, key];
|
|
36
|
+
out.push({ path, label: path.join('.') });
|
|
37
|
+
walk(child, path);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
walk(schema, []);
|
|
41
|
+
return out;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=build-catalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-catalog.js","sourceRoot":"","sources":["../../src/state-binding/build-catalog.ts"],"names":[],"mappings":"AAcA,2FAA2F;AAC3F,MAAM,UAAU,wBAAwB,CACtC,KAAuC;IAEvC,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACxB,MAAM,UAAU,GACd,IAAI,CAAC,WAAW,KAAK,IAAI;YACvB,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;gBACpD,IAAI;gBACJ,OAAO,EAAE,EAAE,CAAC,OAAO;gBACnB,WAAW,EAAE,EAAE,CAAC,WAAW;gBAC3B,MAAM,EAAE,EAAE,CAAC,MAAM;gBACjB,MAAM,EAAE,EAAE,CAAC,MAAM;aAClB,CAAC,CAAC,CAAC;QACV,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,UAAU,EAAE,CAAC;IACxE,CAAC,CAAC,CAAC;AACL,CAAC;AAED,mGAAmG;AACnG,MAAM,UAAU,qBAAqB,CAAC,MAAgC;IACpE,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;AACvD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAe;IAClD,MAAM,GAAG,GAAsB,EAAE,CAAC;IAClC,MAAM,IAAI,GAAG,CAAC,IAAa,EAAE,MAAyB,EAAQ,EAAE;QAC9D,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI;YAAE,OAAO;QACtD,MAAM,KAAK,GAAI,IAAiC,CAAC,UAAU,CAAC;QAC5D,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;YAAE,OAAO;QACxD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC,EAAE,CAAC;YAC5E,MAAM,IAAI,GAAG,CAAC,GAAG,MAAM,EAAE,GAAG,CAAC,CAAC;YAC9B,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC1C,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACpB,CAAC;IACH,CAAC,CAAC;IACF,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACjB,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { BindingTemplateJqOption, BindingTemplateOption } from './types';
|
|
2
|
+
/** One template jq of an attached template, resolved to the reference a binding stores. */
|
|
3
|
+
export interface ResolvedTemplateJq extends BindingTemplateJqOption {
|
|
4
|
+
/** The owning template. */
|
|
5
|
+
readonly template: string;
|
|
6
|
+
/** The reference a binding writes: `name`, or `template.name` when ambiguous. */
|
|
7
|
+
readonly ref: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Every template jq the given attached templates offer for a purpose (or all
|
|
11
|
+
* purposes when `purpose` is omitted), each carrying the reference a binding stores.
|
|
12
|
+
*/
|
|
13
|
+
export declare function resolveTemplateJq(templateNames: readonly string[], catalog: readonly BindingTemplateOption[], purpose?: 'input' | 'update'): ResolvedTemplateJq[];
|
|
14
|
+
/** Find one resolved template jq by the reference a binding stores. */
|
|
15
|
+
export declare function findByRef(ref: string, resolved: readonly ResolvedTemplateJq[]): ResolvedTemplateJq | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* Resolve a jq call name (`enc(template)__name`, or a bare `name`) back to the catalog
|
|
18
|
+
* ref, driven by the catalog — never by string splitting, since a jq name may carry its
|
|
19
|
+
* own `__` past the template boundary and `enc` maps `-`→`_`. Under the template-slug
|
|
20
|
+
* invariant (no consecutive/trailing hyphens ⇒ `enc(template)` has no `__` and no
|
|
21
|
+
* trailing `_`) the FIRST `__` is the one true boundary, so the longest encoded-template
|
|
22
|
+
* prefix whose remainder is a jq the template declares is the unique qualified match;
|
|
23
|
+
* failing that, a bare name a single template declares. `null` when nothing claims it.
|
|
24
|
+
*/
|
|
25
|
+
export declare function resolveCallName(callName: string, catalog: readonly BindingTemplateOption[]): string | null;
|
|
26
|
+
//# sourceMappingURL=catalog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/state-binding/catalog.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAE9E,2FAA2F;AAC3F,MAAM,WAAW,kBAAmB,SAAQ,uBAAuB;IACjE,2BAA2B;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,iFAAiF;IACjF,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,aAAa,EAAE,SAAS,MAAM,EAAE,EAChC,OAAO,EAAE,SAAS,qBAAqB,EAAE,EACzC,OAAO,CAAC,EAAE,OAAO,GAAG,QAAQ,GAC3B,kBAAkB,EAAE,CAsBtB;AAED,uEAAuE;AACvE,wBAAgB,SAAS,CACvB,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,SAAS,kBAAkB,EAAE,GACtC,kBAAkB,GAAG,SAAS,CAEhC;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,SAAS,qBAAqB,EAAE,GACxC,MAAM,GAAG,IAAI,CAiBf"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure catalog helpers — resolve the template jq an attached state offers, with the
|
|
3
|
+
* name-collision rule shared by every layer: an unqualified name that TWO attached
|
|
4
|
+
* templates declare is ambiguous, so both are offered attachment-qualified as
|
|
5
|
+
* `template.name`; a name only one template declares stays bare.
|
|
6
|
+
*/
|
|
7
|
+
import { encodeTemplateSegment } from './adapter';
|
|
8
|
+
/**
|
|
9
|
+
* Every template jq the given attached templates offer for a purpose (or all
|
|
10
|
+
* purposes when `purpose` is omitted), each carrying the reference a binding stores.
|
|
11
|
+
*/
|
|
12
|
+
export function resolveTemplateJq(templateNames, catalog, purpose) {
|
|
13
|
+
const chosen = catalog.filter((template) => templateNames.includes(template.name));
|
|
14
|
+
const counts = new Map();
|
|
15
|
+
for (const template of chosen) {
|
|
16
|
+
for (const jq of template.templateJq) {
|
|
17
|
+
if (purpose !== undefined && jq.purpose !== purpose)
|
|
18
|
+
continue;
|
|
19
|
+
counts.set(jq.name, (counts.get(jq.name) ?? 0) + 1);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
const resolved = [];
|
|
23
|
+
for (const template of chosen) {
|
|
24
|
+
for (const jq of template.templateJq) {
|
|
25
|
+
if (purpose !== undefined && jq.purpose !== purpose)
|
|
26
|
+
continue;
|
|
27
|
+
const ambiguous = (counts.get(jq.name) ?? 0) > 1;
|
|
28
|
+
resolved.push({
|
|
29
|
+
...jq,
|
|
30
|
+
template: template.name,
|
|
31
|
+
ref: ambiguous ? `${template.name}.${jq.name}` : jq.name,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return resolved;
|
|
36
|
+
}
|
|
37
|
+
/** Find one resolved template jq by the reference a binding stores. */
|
|
38
|
+
export function findByRef(ref, resolved) {
|
|
39
|
+
return resolved.find((entry) => entry.ref === ref);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Resolve a jq call name (`enc(template)__name`, or a bare `name`) back to the catalog
|
|
43
|
+
* ref, driven by the catalog — never by string splitting, since a jq name may carry its
|
|
44
|
+
* own `__` past the template boundary and `enc` maps `-`→`_`. Under the template-slug
|
|
45
|
+
* invariant (no consecutive/trailing hyphens ⇒ `enc(template)` has no `__` and no
|
|
46
|
+
* trailing `_`) the FIRST `__` is the one true boundary, so the longest encoded-template
|
|
47
|
+
* prefix whose remainder is a jq the template declares is the unique qualified match;
|
|
48
|
+
* failing that, a bare name a single template declares. `null` when nothing claims it.
|
|
49
|
+
*/
|
|
50
|
+
export function resolveCallName(callName, catalog) {
|
|
51
|
+
let bestRef = null;
|
|
52
|
+
let bestPrefixLength = -1;
|
|
53
|
+
for (const template of catalog) {
|
|
54
|
+
const prefix = `${encodeTemplateSegment(template.name)}__`;
|
|
55
|
+
if (!callName.startsWith(prefix))
|
|
56
|
+
continue;
|
|
57
|
+
const jqName = callName.slice(prefix.length);
|
|
58
|
+
if (template.templateJq.some((jq) => jq.name === jqName) && prefix.length > bestPrefixLength) {
|
|
59
|
+
bestRef = `${template.name}.${jqName}`;
|
|
60
|
+
bestPrefixLength = prefix.length;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (bestRef !== null)
|
|
64
|
+
return bestRef;
|
|
65
|
+
for (const template of catalog) {
|
|
66
|
+
if (template.templateJq.some((jq) => jq.name === callName))
|
|
67
|
+
return callName;
|
|
68
|
+
}
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=catalog.js.map
|