@hyperscale0/hsx 4.0.1 → 4.1.1
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/CHANGELOG.md +8 -0
- package/dist/src/compile.d.ts.map +1 -1
- package/dist/src/compile.js +31 -142
- package/dist/src/compile.js.map +1 -1
- package/dist/src/headers.d.ts +2 -2
- package/dist/src/headers.d.ts.map +1 -1
- package/dist/src/headers.js +1 -2
- package/dist/src/headers.js.map +1 -1
- package/dist/src/lex.d.ts +1 -1
- package/dist/src/lex.d.ts.map +1 -1
- package/dist/src/lex.js +0 -1
- package/dist/src/lex.js.map +1 -1
- package/dist/src/parse.js +0 -17
- package/dist/src/parse.js.map +1 -1
- package/dist/src/std-bundle.d.ts.map +1 -1
- package/dist/src/std-bundle.js +10 -11
- package/dist/src/std-bundle.js.map +1 -1
- package/docs/README.md +0 -10
- package/docs/headers.md +15 -16
- package/examples/cost-table.json +8 -144
- package/examples/library.hsx +4 -4
- package/examples/serviced.hsx +23 -0
- package/package.json +3 -3
- package/src/compile.ts +32 -208
- package/src/headers.ts +1 -2
- package/src/lex.ts +0 -1
- package/src/parse.ts +0 -14
- package/src/std-bundle.ts +10 -11
- package/std/cards.hsx +10 -11
- package/std/collections.hsx +3 -3
- package/std/escrow.hsx +2 -2
- package/std/financing.hsx +56 -53
- package/std/insurance.hsx +17 -16
- package/std/lending.hsx +8 -7
- package/std/money.hsx +8 -18
- package/std/reporting.hsx +0 -4
- package/std/travel.hsx +5 -6
- package/std/wallet.hsx +3 -3
- package/std/approvals.hsx +0 -17
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
# HSX 4.1.1
|
|
2
|
+
|
|
3
|
+
`examples/serviced.hsx` is a second worked programme: a financed sale with a late charge, payment reminders, an early payoff rebate and a write-off. The car financing spec compiles it from the file. No grammar or standard library change.
|
|
4
|
+
|
|
5
|
+
# HSX 4.1.0
|
|
6
|
+
|
|
7
|
+
Second-person approval is deleted from the grammar and the standard library. `financing.portfolio_limit` is a top-level instrument, a plan's `funds` hold is optional, and `insurance.cover` and `financing.credit_line` name their provider with `adapter: text` instead of a party. A car financing programme compiles from the standard library and is covered by its own spec.
|
|
8
|
+
|
|
1
9
|
# HSX 4.0.1
|
|
2
10
|
|
|
3
11
|
The compiler resolves list targets in field blocks and child record export paths, refuses duplicate child export path suffixes naming both candidates, and no longer restricts aggregate limit bounds at compile time; `<= self.<field>` bounds resolve at runtime. No grammar change.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../src/compile.ts"],"names":[],"mappings":"AACA,OAAO,EAAwB,KAAK,eAAe,EAAE,MAAM,WAAW,CAAC;AACvE,OAAO,EAcL,KAAK,WAAW,EAOjB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAIL,KAAK,UAAU,EAKf,KAAK,IAAI,EACV,MAAM,UAAU,CAAC;AAClB,OAAO,EAA0B,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEhF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,MAAM,WAAW,iBAAkB,SAAQ,UAAU;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;CACpC;AACD,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,IAAI,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/C;AACD,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,eAAe,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;CACnB;AACD,MAAM,WAAW,cAAc;IAC7B,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,eAAe,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC,CAAC;CAClE;AACD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,GAAG,SAAS,CAAC;IAC7B,WAAW,EAAE,iBAAiB,EAAE,CAAC;IACjC,SAAS,CAAC,EAAE;QACV,QAAQ,EAAE,WAAW,CAAC;QACtB,YAAY,EAAE,eAAe,CAAC;QAC9B,SAAS,EAAE,qBAAqB,EAAE,CAAC;KACpC,CAAC;CACH;AA2TD,wBAAgB,OAAO,CACrB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,cAAmB,GAC3B,aAAa,
|
|
1
|
+
{"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../src/compile.ts"],"names":[],"mappings":"AACA,OAAO,EAAwB,KAAK,eAAe,EAAE,MAAM,WAAW,CAAC;AACvE,OAAO,EAcL,KAAK,WAAW,EAOjB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAIL,KAAK,UAAU,EAKf,KAAK,IAAI,EACV,MAAM,UAAU,CAAC;AAClB,OAAO,EAA0B,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEhF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,MAAM,WAAW,iBAAkB,SAAQ,UAAU;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;CACpC;AACD,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,IAAI,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/C;AACD,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,eAAe,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;CACnB;AACD,MAAM,WAAW,cAAc;IAC7B,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,eAAe,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC,CAAC;CAClE;AACD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,GAAG,SAAS,CAAC;IAC7B,WAAW,EAAE,iBAAiB,EAAE,CAAC;IACjC,SAAS,CAAC,EAAE;QACV,QAAQ,EAAE,WAAW,CAAC;QACtB,YAAY,EAAE,eAAe,CAAC;QAC9B,SAAS,EAAE,qBAAqB,EAAE,CAAC;KACpC,CAAC;CACH;AA2TD,wBAAgB,OAAO,CACrB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,cAAmB,GAC3B,aAAa,CAs+Ef"}
|
package/dist/src/compile.js
CHANGED
|
@@ -368,8 +368,6 @@ export function compile(source, options = {}) {
|
|
|
368
368
|
}
|
|
369
369
|
}
|
|
370
370
|
const origins = [];
|
|
371
|
-
const materialApprovals = new Set();
|
|
372
|
-
const implicitDecisions = new Map();
|
|
373
371
|
const resolveFamily = (rawPath, expr, required = true) => {
|
|
374
372
|
const parts = rawPath.split(".");
|
|
375
373
|
if (parts.length < 2) {
|
|
@@ -419,7 +417,7 @@ export function compile(source, options = {}) {
|
|
|
419
417
|
}
|
|
420
418
|
return { module: moduleName, exportPath, revision };
|
|
421
419
|
};
|
|
422
|
-
const addInstrument = (decl, id, arguments_, origin, inherited = new Map(),
|
|
420
|
+
const addInstrument = (decl, id, arguments_, origin, inherited = new Map(), inheritedEnums = new Map(), attachmentInfo, familyDeclaration) => {
|
|
423
421
|
const resolveFamilyInstruments = (family, currentInstId, expr) => {
|
|
424
422
|
const found = new Set();
|
|
425
423
|
if (currentInstId && familyDeclaration) {
|
|
@@ -551,7 +549,6 @@ export function compile(source, options = {}) {
|
|
|
551
549
|
if (type.kind === "call" && type.name === "enum")
|
|
552
550
|
enums.set(parameter.key, type.args.map(text));
|
|
553
551
|
}
|
|
554
|
-
const approvers = new Set(inheritedApprovers);
|
|
555
552
|
const supplied = new Map();
|
|
556
553
|
for (const entry of arguments_.entries) {
|
|
557
554
|
if (supplied.has(entry.key))
|
|
@@ -563,7 +560,7 @@ export function compile(source, options = {}) {
|
|
|
563
560
|
const type = param.value.kind === "default" ? param.value.type : param.value;
|
|
564
561
|
const fallback = param.value.kind === "default" ? param.value.value : undefined;
|
|
565
562
|
const typeName = type.kind === "type" || type.kind === "call" ? type.name : text(type);
|
|
566
|
-
const partyParameter = attachmentInfo &&
|
|
563
|
+
const partyParameter = attachmentInfo && typeName === "party";
|
|
567
564
|
const byName = partyParameter &&
|
|
568
565
|
(subjectPartyRoles.includes(param.key) ||
|
|
569
566
|
document.parties[param.key])
|
|
@@ -671,7 +668,7 @@ export function compile(source, options = {}) {
|
|
|
671
668
|
const type = t.kind === "type" || t.kind === "call" ? t.name : text(t);
|
|
672
669
|
const v = (supplied.has(param.key) && !attachmentInfo) || type === "enum"
|
|
673
670
|
? actual
|
|
674
|
-
: resolve(actual, new Set(), !!attachmentInfo &&
|
|
671
|
+
: resolve(actual, new Set(), !!attachmentInfo && type === "party");
|
|
675
672
|
environment.set(param.key, v);
|
|
676
673
|
if (type === "enum" && t.kind === "call") {
|
|
677
674
|
if (v.kind !== "name" || !t.args.some((a) => text(a) === v.value))
|
|
@@ -681,24 +678,18 @@ export function compile(source, options = {}) {
|
|
|
681
678
|
if (v.kind !== "list")
|
|
682
679
|
fail(v, `${param.key} needs a list`, "write [value, value]");
|
|
683
680
|
}
|
|
684
|
-
else if (type === "party"
|
|
681
|
+
else if (type === "party") {
|
|
685
682
|
if (v.kind !== "name" || !isParty(v.value))
|
|
686
683
|
failWithCode(actual, attachmentInfo ? "subject_party_unbound" : "HSX1001", `${param.key} needs a declared party`, "declare a party and use its name here");
|
|
687
684
|
const party = document.parties[v.value];
|
|
688
|
-
if ((
|
|
689
|
-
(
|
|
690
|
-
|
|
691
|
-
(attachmentInfo && party?.kind === "person"))))
|
|
692
|
-
failWithCode(actual, "party_kind_mismatch", `${param.key} cannot bind ${v.value}`, type === "approval"
|
|
693
|
-
? "use a declared staff party with a role"
|
|
694
|
-
: "use a subject role or declared business");
|
|
685
|
+
if ((party?.kind === "staff" && !party.role) ||
|
|
686
|
+
(attachmentInfo && party?.kind === "person"))
|
|
687
|
+
failWithCode(actual, "party_kind_mismatch", `${param.key} cannot bind ${v.value}`, "use a subject role, declared business, or staff with a role");
|
|
695
688
|
resolvedParties.add(param.key);
|
|
696
689
|
if (attachmentInfo)
|
|
697
690
|
attachmentInfo.parties[param.key] = subjectPartyRoles.includes(v.value)
|
|
698
691
|
? { role: v.value }
|
|
699
692
|
: { party: v.value };
|
|
700
|
-
if (type === "approval")
|
|
701
|
-
approvers.add(text(v));
|
|
702
693
|
}
|
|
703
694
|
else if (type === "ref") {
|
|
704
695
|
const values = v.kind === "list" ? v.items : [v];
|
|
@@ -725,6 +716,14 @@ export function compile(source, options = {}) {
|
|
|
725
716
|
fail(value, "duplicate reference", "list each object once");
|
|
726
717
|
seen.add(value.value);
|
|
727
718
|
}
|
|
719
|
+
// A many-reference tunable is a list even when one object is bound,
|
|
720
|
+
// so report datasets and other value positions never see a bare name.
|
|
721
|
+
if (t.kind === "type" && t.many && v.kind !== "list")
|
|
722
|
+
environment.set(param.key, {
|
|
723
|
+
kind: "list",
|
|
724
|
+
items: [v],
|
|
725
|
+
span: v.span,
|
|
726
|
+
});
|
|
728
727
|
}
|
|
729
728
|
else if (type === "fee" || type === "split" || type === "policy") {
|
|
730
729
|
if (v.kind !== "block")
|
|
@@ -1009,6 +1008,12 @@ export function compile(source, options = {}) {
|
|
|
1009
1008
|
fail(row, "reference needs a target", "write ref<object>");
|
|
1010
1009
|
const [root, ...tail] = target.split(".");
|
|
1011
1010
|
const resolved = environment.get(root);
|
|
1011
|
+
// An optional field pointing at an unsupplied optional tunable
|
|
1012
|
+
// has nothing to point at, so the instrument drops it.
|
|
1013
|
+
if (!resolved &&
|
|
1014
|
+
f.optional &&
|
|
1015
|
+
decl.parameters.some((parameter) => parameter.key === root))
|
|
1016
|
+
continue;
|
|
1012
1017
|
const resolvedTargets = resolved?.kind === "list"
|
|
1013
1018
|
? resolved.items
|
|
1014
1019
|
: resolved
|
|
@@ -1272,9 +1277,14 @@ export function compile(source, options = {}) {
|
|
|
1272
1277
|
const adapterList = [];
|
|
1273
1278
|
for (const entry of subjectBlock.entries) {
|
|
1274
1279
|
if (entry.key === "adapter") {
|
|
1280
|
+
// A tunable names the adapter; anything else is the binding itself.
|
|
1281
|
+
const adapterName = (item) => item.kind === "name" &&
|
|
1282
|
+
decl.parameters.some((parameter) => parameter.key === item.value)
|
|
1283
|
+
? text(resolve(item))
|
|
1284
|
+
: text(item);
|
|
1275
1285
|
const bindingNames = entry.value.kind === "list"
|
|
1276
|
-
? entry.value.items.map(
|
|
1277
|
-
: [
|
|
1286
|
+
? entry.value.items.map(adapterName)
|
|
1287
|
+
: [adapterName(entry.value)];
|
|
1278
1288
|
for (const bindingName of bindingNames) {
|
|
1279
1289
|
const target = options.adapterRegistry?.[bindingName];
|
|
1280
1290
|
if (target) {
|
|
@@ -1626,14 +1636,6 @@ export function compile(source, options = {}) {
|
|
|
1626
1636
|
fail(move, `unknown transfer instruction ${op}`, "choose create, reserve, post, or void from internal_transfer");
|
|
1627
1637
|
}
|
|
1628
1638
|
}
|
|
1629
|
-
else if (key === "approval") {
|
|
1630
|
-
const approval = data(expr);
|
|
1631
|
-
if (approval && approval.input === "material") {
|
|
1632
|
-
approval.input = {};
|
|
1633
|
-
materialApprovals.add(a);
|
|
1634
|
-
}
|
|
1635
|
-
a.approval = approval;
|
|
1636
|
-
}
|
|
1637
1639
|
else
|
|
1638
1640
|
a[key] = data(expr);
|
|
1639
1641
|
}
|
|
@@ -1671,26 +1673,6 @@ export function compile(source, options = {}) {
|
|
|
1671
1673
|
checkSubjectPaths(a.invoke, row.span);
|
|
1672
1674
|
currentAction = undefined;
|
|
1673
1675
|
currentActionName = undefined;
|
|
1674
|
-
for (const requirement of a.requires ?? []) {
|
|
1675
|
-
if (requirement.kind !== "approval" ||
|
|
1676
|
-
!approvers.has(requirement.party))
|
|
1677
|
-
continue;
|
|
1678
|
-
const action = requirement.action ?? name;
|
|
1679
|
-
const key = `${id}_${action}_decision`;
|
|
1680
|
-
const previous = implicitDecisions.get(key);
|
|
1681
|
-
if (previous &&
|
|
1682
|
-
(previous.party !== requirement.party ||
|
|
1683
|
-
previous.protectedRequest !==
|
|
1684
|
-
(requirement.protectedRequest ?? "self")))
|
|
1685
|
-
fail({ span: origin }, `action ${action} has conflicting approval parties or protected requests`, "use a separate decision action for each party");
|
|
1686
|
-
implicitDecisions.set(key, {
|
|
1687
|
-
target: id,
|
|
1688
|
-
action,
|
|
1689
|
-
party: requirement.party,
|
|
1690
|
-
protectedRequest: requirement.protectedRequest ?? "self",
|
|
1691
|
-
origin,
|
|
1692
|
-
});
|
|
1693
|
-
}
|
|
1694
1676
|
for (const requirement of a.subject?.requirements ?? []) {
|
|
1695
1677
|
const entry = asBlock(subjectExpr).entries.find((entry) => entry.key === requirement.field.name) ??
|
|
1696
1678
|
asBlock(subjectExpr).entries.find((entry) => entry.key === "adapter");
|
|
@@ -1739,7 +1721,7 @@ export function compile(source, options = {}) {
|
|
|
1739
1721
|
addInstrument(child, `${id}_${key}`, emptyBlock, origin, new Map([
|
|
1740
1722
|
...environment,
|
|
1741
1723
|
["parent", { kind: "name", value: id, span: origin }],
|
|
1742
|
-
]),
|
|
1724
|
+
]), enums, attachmentInfo
|
|
1743
1725
|
? { ...attachmentInfo, exposed: new Map() }
|
|
1744
1726
|
: undefined, childFamily);
|
|
1745
1727
|
}
|
|
@@ -1812,7 +1794,7 @@ export function compile(source, options = {}) {
|
|
|
1812
1794
|
span: entry.value.span,
|
|
1813
1795
|
};
|
|
1814
1796
|
const templateFamily = resolveFamily(targetTemplate, entry, false);
|
|
1815
|
-
addInstrument(template, instId, tunableBlock, entry.span, new Map(), new
|
|
1797
|
+
addInstrument(template, instId, tunableBlock, entry.span, new Map(), new Map(), {
|
|
1816
1798
|
subjectKindId: decl.name,
|
|
1817
1799
|
attachmentName,
|
|
1818
1800
|
renames,
|
|
@@ -1901,7 +1883,7 @@ export function compile(source, options = {}) {
|
|
|
1901
1883
|
if (!template)
|
|
1902
1884
|
fail(decl, `unknown instrument ${decl.target}`, `add use ${decl.target.split(".")[0]} and choose a declared instrument`);
|
|
1903
1885
|
const templateFamily = resolveFamily(decl.target, decl, false);
|
|
1904
|
-
addInstrument(template, decl.name, decl.body, decl.span, new Map(), new
|
|
1886
|
+
addInstrument(template, decl.name, decl.body, decl.span, new Map(), new Map(), undefined, templateFamily ? { ...templateFamily } : undefined);
|
|
1905
1887
|
}
|
|
1906
1888
|
if (decl.kind === "object") {
|
|
1907
1889
|
compileObject(decl);
|
|
@@ -2070,99 +2052,6 @@ export function compile(source, options = {}) {
|
|
|
2070
2052
|
: field.target).some((id) => eliminatedStates.get(id)?.has(state)));
|
|
2071
2053
|
}
|
|
2072
2054
|
}
|
|
2073
|
-
// Approval tunables instantiate the same library record as an explicit decision.
|
|
2074
|
-
if (implicitDecisions.size) {
|
|
2075
|
-
const content = (options.standardLibrary ?? bundledStandardLibrary).source("approvals");
|
|
2076
|
-
const parsed = content ? parseProgram(content) : undefined;
|
|
2077
|
-
const template = parsed?.program.decls.find((decl) => decl.kind === "instrument" && decl.name === "decision");
|
|
2078
|
-
if (!template ||
|
|
2079
|
-
template.kind !== "instrument" ||
|
|
2080
|
-
parsed?.diagnostics.length)
|
|
2081
|
-
fail(program, "implicit decisions need the approvals header", "provide the standard approvals header");
|
|
2082
|
-
for (const [id, decision] of implicitDecisions) {
|
|
2083
|
-
if (!document.instruments.find((inst) => inst.id === decision.target)
|
|
2084
|
-
?.actions[decision.action])
|
|
2085
|
-
continue;
|
|
2086
|
-
const existing = document.instruments.some((inst) => Object.values(inst.actions).some((action) => action.approval?.action === decision.action &&
|
|
2087
|
-
action.approval.party === decision.party &&
|
|
2088
|
-
inst.fields.some((field) => {
|
|
2089
|
-
if (field.type !== "ref" ||
|
|
2090
|
-
field.target !== decision.target ||
|
|
2091
|
-
`self.${field.name}` !== action.approval?.target)
|
|
2092
|
-
return false;
|
|
2093
|
-
const [root, name, ...tail] = decision.protectedRequest.split(".");
|
|
2094
|
-
const input = name && action.approval.input[name];
|
|
2095
|
-
const request = root === "self"
|
|
2096
|
-
? [action.approval.target, name, ...tail]
|
|
2097
|
-
.filter(Boolean)
|
|
2098
|
-
.join(".")
|
|
2099
|
-
: root === "input" && name
|
|
2100
|
-
? input && "field" in input
|
|
2101
|
-
? [input.field, ...tail].join(".")
|
|
2102
|
-
: materialApprovals.has(action)
|
|
2103
|
-
? [`self.material_${name}`, ...tail].join(".")
|
|
2104
|
-
: undefined
|
|
2105
|
-
: undefined;
|
|
2106
|
-
return (request !== undefined &&
|
|
2107
|
-
action.approval.protectedRequest === request);
|
|
2108
|
-
})));
|
|
2109
|
-
if (existing)
|
|
2110
|
-
continue;
|
|
2111
|
-
if (document.instruments.some((inst) => inst.id === id))
|
|
2112
|
-
fail({ span: decision.origin }, `implicit decision name ${id} is already used`, "rename the conflicting object");
|
|
2113
|
-
const protectedRequest = decision.protectedRequest === "self"
|
|
2114
|
-
? "self.target"
|
|
2115
|
-
: decision.protectedRequest.startsWith("self.")
|
|
2116
|
-
? `self.target.${decision.protectedRequest.slice(5)}`
|
|
2117
|
-
: fail({ span: decision.origin }, "implicit approval needs a stored protected request", "declare an explicit decision for an input-based protected request");
|
|
2118
|
-
addInstrument(template, id, {
|
|
2119
|
-
kind: "block",
|
|
2120
|
-
span: decision.origin,
|
|
2121
|
-
entries: Object.entries({
|
|
2122
|
-
for: decision.target,
|
|
2123
|
-
approved_by: decision.party,
|
|
2124
|
-
action: decision.action,
|
|
2125
|
-
protected_request: protectedRequest,
|
|
2126
|
-
}).map(([key, value]) => ({
|
|
2127
|
-
key,
|
|
2128
|
-
value: {
|
|
2129
|
-
kind: key === "action" || key === "protected_request"
|
|
2130
|
-
? "text"
|
|
2131
|
-
: "name",
|
|
2132
|
-
value,
|
|
2133
|
-
span: decision.origin,
|
|
2134
|
-
},
|
|
2135
|
-
span: decision.origin,
|
|
2136
|
-
})),
|
|
2137
|
-
}, decision.origin, new Map(), new Set(), new Map(), document.instruments.find((instrument) => instrument.id === decision.target)?.subject
|
|
2138
|
-
? {
|
|
2139
|
-
subjectKindId: document.instruments.find((instrument) => instrument.id === decision.target).subject,
|
|
2140
|
-
attachmentName: id,
|
|
2141
|
-
parties: {},
|
|
2142
|
-
renames: new Map(),
|
|
2143
|
-
exposed: new Map(),
|
|
2144
|
-
}
|
|
2145
|
-
: undefined);
|
|
2146
|
-
}
|
|
2147
|
-
}
|
|
2148
|
-
// Material approval fields are inferred from the selected action's typed input.
|
|
2149
|
-
for (const inst of document.instruments)
|
|
2150
|
-
for (const action of Object.values(inst.actions)) {
|
|
2151
|
-
if (!materialApprovals.has(action) || !action.approval)
|
|
2152
|
-
continue;
|
|
2153
|
-
const targetField = inst.fields.find((f) => `self.${f.name}` === action.approval.target);
|
|
2154
|
-
if (targetField?.type !== "ref")
|
|
2155
|
-
continue;
|
|
2156
|
-
const target = document.instruments.find((i) => i.id === targetField.target)?.actions[action.approval.action];
|
|
2157
|
-
if (!target)
|
|
2158
|
-
continue;
|
|
2159
|
-
for (const field of target.input) {
|
|
2160
|
-
const name = `material_${field.name}`;
|
|
2161
|
-
if (!inst.fields.some((f) => f.name === name))
|
|
2162
|
-
inst.fields.push({ ...field, name });
|
|
2163
|
-
action.approval.input[field.name] = { field: `self.${name}` };
|
|
2164
|
-
}
|
|
2165
|
-
}
|
|
2166
2055
|
const changed = new Set();
|
|
2167
2056
|
for (const decl of program.decls)
|
|
2168
2057
|
if (decl.kind === "hide" || decl.kind === "expose") {
|