@hyperscale0/hsx 4.0.0 → 4.1.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/CHANGELOG.md +8 -0
- package/dist/src/compile.d.ts.map +1 -1
- package/dist/src/compile.js +46 -148
- 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/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +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/package.json +4 -4
- package/src/compile.ts +57 -214
- 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/src/version.ts +1 -1
- 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/src/compile.ts
CHANGED
|
@@ -545,17 +545,6 @@ export function compile(
|
|
|
545
545
|
}
|
|
546
546
|
}
|
|
547
547
|
const origins: CompileOriginMapEntry[] = [];
|
|
548
|
-
const materialApprovals = new Set<UdlAction>();
|
|
549
|
-
const implicitDecisions = new Map<
|
|
550
|
-
string,
|
|
551
|
-
{
|
|
552
|
-
target: string;
|
|
553
|
-
action: string;
|
|
554
|
-
party: string;
|
|
555
|
-
protectedRequest: string;
|
|
556
|
-
origin: Span;
|
|
557
|
-
}
|
|
558
|
-
>();
|
|
559
548
|
const resolveFamily = (
|
|
560
549
|
rawPath: string,
|
|
561
550
|
expr: { span: Span; source?: string },
|
|
@@ -629,7 +618,6 @@ export function compile(
|
|
|
629
618
|
arguments_: BlockExpr,
|
|
630
619
|
origin: Span,
|
|
631
620
|
inherited = new Map<string, Expr>(),
|
|
632
|
-
inheritedApprovers = new Set<string>(),
|
|
633
621
|
inheritedEnums = new Map<string, string[]>(),
|
|
634
622
|
attachmentInfo?: {
|
|
635
623
|
subjectKindId: string;
|
|
@@ -696,17 +684,18 @@ export function compile(
|
|
|
696
684
|
return result;
|
|
697
685
|
};
|
|
698
686
|
|
|
699
|
-
const
|
|
687
|
+
const collectChildExportPaths = (
|
|
700
688
|
parentDecl: InstrumentDecl,
|
|
701
689
|
suffix: string,
|
|
702
|
-
): string
|
|
690
|
+
): string[] => {
|
|
703
691
|
const recs = entries(asBlock(entries(parentDecl.body).get("records")));
|
|
692
|
+
const matches: string[] = [];
|
|
704
693
|
for (const [recName] of recs) {
|
|
705
|
-
if (suffix === recName)
|
|
694
|
+
if (suffix === recName) matches.push(recName);
|
|
706
695
|
}
|
|
707
696
|
for (const [recName, recBlock] of recs) {
|
|
708
697
|
if (suffix.startsWith(`${recName}_`)) {
|
|
709
|
-
const
|
|
698
|
+
const nested = collectChildExportPaths(
|
|
710
699
|
{
|
|
711
700
|
kind: "instrument",
|
|
712
701
|
name: recName,
|
|
@@ -716,10 +705,28 @@ export function compile(
|
|
|
716
705
|
},
|
|
717
706
|
suffix.slice(recName.length + 1),
|
|
718
707
|
);
|
|
719
|
-
|
|
708
|
+
for (const rest of nested) {
|
|
709
|
+
matches.push(`${recName}.${rest}`);
|
|
710
|
+
}
|
|
720
711
|
}
|
|
721
712
|
}
|
|
722
|
-
return
|
|
713
|
+
return matches;
|
|
714
|
+
};
|
|
715
|
+
|
|
716
|
+
const resolveChildExportPath = (
|
|
717
|
+
parentDecl: InstrumentDecl,
|
|
718
|
+
suffix: string,
|
|
719
|
+
): string | undefined => {
|
|
720
|
+
const matches = collectChildExportPaths(parentDecl, suffix);
|
|
721
|
+
if (matches.length > 1) {
|
|
722
|
+
failWithCode(
|
|
723
|
+
parentDecl,
|
|
724
|
+
"HSX1001",
|
|
725
|
+
`ambiguous child export path suffix '${suffix}': multiple candidates (${matches.join(", ")})`,
|
|
726
|
+
"rename conflicting records to remove duplicate export path suffixes",
|
|
727
|
+
);
|
|
728
|
+
}
|
|
729
|
+
return matches[0];
|
|
723
730
|
};
|
|
724
731
|
|
|
725
732
|
const getInstrumentFamily = (targetId: string): UdlFamily | undefined => {
|
|
@@ -803,7 +810,6 @@ export function compile(
|
|
|
803
810
|
if (type.kind === "call" && type.name === "enum")
|
|
804
811
|
enums.set(parameter.key, type.args.map(text));
|
|
805
812
|
}
|
|
806
|
-
const approvers = new Set(inheritedApprovers);
|
|
807
813
|
const supplied = new Map<string, Expr>();
|
|
808
814
|
for (const entry of arguments_.entries) {
|
|
809
815
|
if (supplied.has(entry.key))
|
|
@@ -822,8 +828,7 @@ export function compile(
|
|
|
822
828
|
param.value.kind === "default" ? param.value.value : undefined;
|
|
823
829
|
const typeName =
|
|
824
830
|
type.kind === "type" || type.kind === "call" ? type.name : text(type);
|
|
825
|
-
const partyParameter =
|
|
826
|
-
attachmentInfo && (typeName === "party" || typeName === "approval");
|
|
831
|
+
const partyParameter = attachmentInfo && typeName === "party";
|
|
827
832
|
const byName: Expr | undefined =
|
|
828
833
|
partyParameter &&
|
|
829
834
|
(subjectPartyRoles.includes(param.key as SubjectPartyRole) ||
|
|
@@ -981,11 +986,7 @@ export function compile(
|
|
|
981
986
|
const v =
|
|
982
987
|
(supplied.has(param.key) && !attachmentInfo) || type === "enum"
|
|
983
988
|
? actual
|
|
984
|
-
: resolve(
|
|
985
|
-
actual,
|
|
986
|
-
new Set(),
|
|
987
|
-
!!attachmentInfo && (type === "party" || type === "approval"),
|
|
988
|
-
);
|
|
989
|
+
: resolve(actual, new Set(), !!attachmentInfo && type === "party");
|
|
989
990
|
environment.set(param.key, v);
|
|
990
991
|
if (type === "enum" && t.kind === "call") {
|
|
991
992
|
if (v.kind !== "name" || !t.args.some((a) => text(a) === v.value))
|
|
@@ -997,7 +998,7 @@ export function compile(
|
|
|
997
998
|
} else if (type === "list") {
|
|
998
999
|
if (v.kind !== "list")
|
|
999
1000
|
fail(v, `${param.key} needs a list`, "write [value, value]");
|
|
1000
|
-
} else if (type === "party"
|
|
1001
|
+
} else if (type === "party") {
|
|
1001
1002
|
if (v.kind !== "name" || !isParty(v.value))
|
|
1002
1003
|
failWithCode(
|
|
1003
1004
|
actual,
|
|
@@ -1007,18 +1008,14 @@ export function compile(
|
|
|
1007
1008
|
);
|
|
1008
1009
|
const party = document.parties[v.value];
|
|
1009
1010
|
if (
|
|
1010
|
-
(
|
|
1011
|
-
(
|
|
1012
|
-
(party?.kind === "staff" ||
|
|
1013
|
-
(attachmentInfo && party?.kind === "person")))
|
|
1011
|
+
(party?.kind === "staff" && !party.role) ||
|
|
1012
|
+
(attachmentInfo && party?.kind === "person")
|
|
1014
1013
|
)
|
|
1015
1014
|
failWithCode(
|
|
1016
1015
|
actual,
|
|
1017
1016
|
"party_kind_mismatch",
|
|
1018
1017
|
`${param.key} cannot bind ${v.value}`,
|
|
1019
|
-
|
|
1020
|
-
? "use a declared staff party with a role"
|
|
1021
|
-
: "use a subject role or declared business",
|
|
1018
|
+
"use a subject role, declared business, or staff with a role",
|
|
1022
1019
|
);
|
|
1023
1020
|
resolvedParties.add(param.key);
|
|
1024
1021
|
if (attachmentInfo)
|
|
@@ -1027,7 +1024,6 @@ export function compile(
|
|
|
1027
1024
|
)
|
|
1028
1025
|
? { role: v.value as SubjectPartyRole }
|
|
1029
1026
|
: { party: v.value };
|
|
1030
|
-
if (type === "approval") approvers.add(text(v));
|
|
1031
1027
|
} else if (type === "ref") {
|
|
1032
1028
|
const values = v.kind === "list" ? v.items : [v];
|
|
1033
1029
|
if (v.kind === "list" && (t.kind !== "type" || !t.many))
|
|
@@ -1073,6 +1069,14 @@ export function compile(
|
|
|
1073
1069
|
fail(value, "duplicate reference", "list each object once");
|
|
1074
1070
|
seen.add(value.value);
|
|
1075
1071
|
}
|
|
1072
|
+
// A many-reference tunable is a list even when one object is bound,
|
|
1073
|
+
// so report datasets and other value positions never see a bare name.
|
|
1074
|
+
if (t.kind === "type" && t.many && v.kind !== "list")
|
|
1075
|
+
environment.set(param.key, {
|
|
1076
|
+
kind: "list",
|
|
1077
|
+
items: [v],
|
|
1078
|
+
span: v.span,
|
|
1079
|
+
});
|
|
1076
1080
|
} else if (type === "fee" || type === "split" || type === "policy") {
|
|
1077
1081
|
if (v.kind !== "block")
|
|
1078
1082
|
fail(v, `${param.key} needs a block`, `write ${param.key} { ... }`);
|
|
@@ -1438,6 +1442,14 @@ export function compile(
|
|
|
1438
1442
|
fail(row, "reference needs a target", "write ref<object>");
|
|
1439
1443
|
const [root, ...tail] = target.split(".");
|
|
1440
1444
|
const resolved = environment.get(root!);
|
|
1445
|
+
// An optional field pointing at an unsupplied optional tunable
|
|
1446
|
+
// has nothing to point at, so the instrument drops it.
|
|
1447
|
+
if (
|
|
1448
|
+
!resolved &&
|
|
1449
|
+
f.optional &&
|
|
1450
|
+
decl.parameters.some((parameter) => parameter.key === root)
|
|
1451
|
+
)
|
|
1452
|
+
continue;
|
|
1441
1453
|
const resolvedTargets =
|
|
1442
1454
|
resolved?.kind === "list"
|
|
1443
1455
|
? resolved.items
|
|
@@ -1769,10 +1781,18 @@ export function compile(
|
|
|
1769
1781
|
const adapterList: UdlActionSubject["adapters"] = [];
|
|
1770
1782
|
for (const entry of subjectBlock.entries) {
|
|
1771
1783
|
if (entry.key === "adapter") {
|
|
1784
|
+
// A tunable names the adapter; anything else is the binding itself.
|
|
1785
|
+
const adapterName = (item: Expr): string =>
|
|
1786
|
+
item.kind === "name" &&
|
|
1787
|
+
decl.parameters.some(
|
|
1788
|
+
(parameter) => parameter.key === item.value,
|
|
1789
|
+
)
|
|
1790
|
+
? text(resolve(item))
|
|
1791
|
+
: text(item);
|
|
1772
1792
|
const bindingNames =
|
|
1773
1793
|
entry.value.kind === "list"
|
|
1774
|
-
? entry.value.items.map(
|
|
1775
|
-
: [
|
|
1794
|
+
? entry.value.items.map(adapterName)
|
|
1795
|
+
: [adapterName(entry.value)];
|
|
1776
1796
|
for (const bindingName of bindingNames) {
|
|
1777
1797
|
const target = options.adapterRegistry?.[bindingName];
|
|
1778
1798
|
if (target) {
|
|
@@ -2265,13 +2285,6 @@ export function compile(
|
|
|
2265
2285
|
"choose create, reserve, post, or void from internal_transfer",
|
|
2266
2286
|
);
|
|
2267
2287
|
}
|
|
2268
|
-
} else if (key === "approval") {
|
|
2269
|
-
const approval = data(expr) as UdlAction["approval"];
|
|
2270
|
-
if (approval && (approval.input as unknown) === "material") {
|
|
2271
|
-
approval.input = {};
|
|
2272
|
-
materialApprovals.add(a);
|
|
2273
|
-
}
|
|
2274
|
-
a.approval = approval;
|
|
2275
2288
|
} else (a as unknown as Record<string, unknown>)[key] = data(expr);
|
|
2276
2289
|
}
|
|
2277
2290
|
if (attachmentInfo) {
|
|
@@ -2309,34 +2322,6 @@ export function compile(
|
|
|
2309
2322
|
checkSubjectPaths(a.invoke, row.span);
|
|
2310
2323
|
currentAction = undefined;
|
|
2311
2324
|
currentActionName = undefined;
|
|
2312
|
-
for (const requirement of a.requires ?? []) {
|
|
2313
|
-
if (
|
|
2314
|
-
requirement.kind !== "approval" ||
|
|
2315
|
-
!approvers.has(requirement.party)
|
|
2316
|
-
)
|
|
2317
|
-
continue;
|
|
2318
|
-
const action = requirement.action ?? name;
|
|
2319
|
-
const key = `${id}_${action}_decision`;
|
|
2320
|
-
const previous = implicitDecisions.get(key);
|
|
2321
|
-
if (
|
|
2322
|
-
previous &&
|
|
2323
|
-
(previous.party !== requirement.party ||
|
|
2324
|
-
previous.protectedRequest !==
|
|
2325
|
-
(requirement.protectedRequest ?? "self"))
|
|
2326
|
-
)
|
|
2327
|
-
fail(
|
|
2328
|
-
{ span: origin },
|
|
2329
|
-
`action ${action} has conflicting approval parties or protected requests`,
|
|
2330
|
-
"use a separate decision action for each party",
|
|
2331
|
-
);
|
|
2332
|
-
implicitDecisions.set(key, {
|
|
2333
|
-
target: id,
|
|
2334
|
-
action,
|
|
2335
|
-
party: requirement.party,
|
|
2336
|
-
protectedRequest: requirement.protectedRequest ?? "self",
|
|
2337
|
-
origin,
|
|
2338
|
-
});
|
|
2339
|
-
}
|
|
2340
2325
|
for (const requirement of a.subject?.requirements ?? []) {
|
|
2341
2326
|
const entry =
|
|
2342
2327
|
asBlock(subjectExpr).entries.find(
|
|
@@ -2401,7 +2386,6 @@ export function compile(
|
|
|
2401
2386
|
...environment,
|
|
2402
2387
|
["parent", { kind: "name", value: id, span: origin } as Expr],
|
|
2403
2388
|
]),
|
|
2404
|
-
approvers,
|
|
2405
2389
|
enums,
|
|
2406
2390
|
attachmentInfo
|
|
2407
2391
|
? { ...attachmentInfo, exposed: new Map() }
|
|
@@ -2506,7 +2490,6 @@ export function compile(
|
|
|
2506
2490
|
tunableBlock,
|
|
2507
2491
|
entry.span,
|
|
2508
2492
|
new Map(),
|
|
2509
|
-
new Set(),
|
|
2510
2493
|
new Map(),
|
|
2511
2494
|
{
|
|
2512
2495
|
subjectKindId: decl.name,
|
|
@@ -2643,7 +2626,6 @@ export function compile(
|
|
|
2643
2626
|
decl.body,
|
|
2644
2627
|
decl.span,
|
|
2645
2628
|
new Map(),
|
|
2646
|
-
new Set(),
|
|
2647
2629
|
new Map(),
|
|
2648
2630
|
undefined,
|
|
2649
2631
|
templateFamily ? { ...templateFamily } : undefined,
|
|
@@ -2861,145 +2843,6 @@ export function compile(
|
|
|
2861
2843
|
);
|
|
2862
2844
|
}
|
|
2863
2845
|
}
|
|
2864
|
-
// Approval tunables instantiate the same library record as an explicit decision.
|
|
2865
|
-
if (implicitDecisions.size) {
|
|
2866
|
-
const content = (
|
|
2867
|
-
options.standardLibrary ?? bundledStandardLibrary
|
|
2868
|
-
).source("approvals");
|
|
2869
|
-
const parsed = content ? parseProgram(content) : undefined;
|
|
2870
|
-
const template = parsed?.program.decls.find(
|
|
2871
|
-
(decl) => decl.kind === "instrument" && decl.name === "decision",
|
|
2872
|
-
);
|
|
2873
|
-
if (
|
|
2874
|
-
!template ||
|
|
2875
|
-
template.kind !== "instrument" ||
|
|
2876
|
-
parsed?.diagnostics.length
|
|
2877
|
-
)
|
|
2878
|
-
fail(
|
|
2879
|
-
program,
|
|
2880
|
-
"implicit decisions need the approvals header",
|
|
2881
|
-
"provide the standard approvals header",
|
|
2882
|
-
);
|
|
2883
|
-
for (const [id, decision] of implicitDecisions) {
|
|
2884
|
-
if (
|
|
2885
|
-
!document.instruments.find((inst) => inst.id === decision.target)
|
|
2886
|
-
?.actions[decision.action]
|
|
2887
|
-
)
|
|
2888
|
-
continue;
|
|
2889
|
-
const existing = document.instruments.some((inst) =>
|
|
2890
|
-
Object.values(inst.actions).some(
|
|
2891
|
-
(action) =>
|
|
2892
|
-
action.approval?.action === decision.action &&
|
|
2893
|
-
action.approval.party === decision.party &&
|
|
2894
|
-
inst.fields.some((field) => {
|
|
2895
|
-
if (
|
|
2896
|
-
field.type !== "ref" ||
|
|
2897
|
-
field.target !== decision.target ||
|
|
2898
|
-
`self.${field.name}` !== action.approval?.target
|
|
2899
|
-
)
|
|
2900
|
-
return false;
|
|
2901
|
-
const [root, name, ...tail] =
|
|
2902
|
-
decision.protectedRequest.split(".");
|
|
2903
|
-
const input = name && action.approval.input[name];
|
|
2904
|
-
const request =
|
|
2905
|
-
root === "self"
|
|
2906
|
-
? [action.approval.target, name, ...tail]
|
|
2907
|
-
.filter(Boolean)
|
|
2908
|
-
.join(".")
|
|
2909
|
-
: root === "input" && name
|
|
2910
|
-
? input && "field" in input
|
|
2911
|
-
? [input.field, ...tail].join(".")
|
|
2912
|
-
: materialApprovals.has(action)
|
|
2913
|
-
? [`self.material_${name}`, ...tail].join(".")
|
|
2914
|
-
: undefined
|
|
2915
|
-
: undefined;
|
|
2916
|
-
return (
|
|
2917
|
-
request !== undefined &&
|
|
2918
|
-
action.approval.protectedRequest === request
|
|
2919
|
-
);
|
|
2920
|
-
}),
|
|
2921
|
-
),
|
|
2922
|
-
);
|
|
2923
|
-
if (existing) continue;
|
|
2924
|
-
if (document.instruments.some((inst) => inst.id === id))
|
|
2925
|
-
fail(
|
|
2926
|
-
{ span: decision.origin },
|
|
2927
|
-
`implicit decision name ${id} is already used`,
|
|
2928
|
-
"rename the conflicting object",
|
|
2929
|
-
);
|
|
2930
|
-
const protectedRequest =
|
|
2931
|
-
decision.protectedRequest === "self"
|
|
2932
|
-
? "self.target"
|
|
2933
|
-
: decision.protectedRequest.startsWith("self.")
|
|
2934
|
-
? `self.target.${decision.protectedRequest.slice(5)}`
|
|
2935
|
-
: fail(
|
|
2936
|
-
{ span: decision.origin },
|
|
2937
|
-
"implicit approval needs a stored protected request",
|
|
2938
|
-
"declare an explicit decision for an input-based protected request",
|
|
2939
|
-
);
|
|
2940
|
-
addInstrument(
|
|
2941
|
-
template,
|
|
2942
|
-
id,
|
|
2943
|
-
{
|
|
2944
|
-
kind: "block",
|
|
2945
|
-
span: decision.origin,
|
|
2946
|
-
entries: Object.entries({
|
|
2947
|
-
for: decision.target,
|
|
2948
|
-
approved_by: decision.party,
|
|
2949
|
-
action: decision.action,
|
|
2950
|
-
protected_request: protectedRequest,
|
|
2951
|
-
}).map(([key, value]) => ({
|
|
2952
|
-
key,
|
|
2953
|
-
value: {
|
|
2954
|
-
kind:
|
|
2955
|
-
key === "action" || key === "protected_request"
|
|
2956
|
-
? "text"
|
|
2957
|
-
: "name",
|
|
2958
|
-
value,
|
|
2959
|
-
span: decision.origin,
|
|
2960
|
-
},
|
|
2961
|
-
span: decision.origin,
|
|
2962
|
-
})),
|
|
2963
|
-
},
|
|
2964
|
-
decision.origin,
|
|
2965
|
-
new Map(),
|
|
2966
|
-
new Set(),
|
|
2967
|
-
new Map(),
|
|
2968
|
-
document.instruments.find(
|
|
2969
|
-
(instrument) => instrument.id === decision.target,
|
|
2970
|
-
)?.subject
|
|
2971
|
-
? {
|
|
2972
|
-
subjectKindId: document.instruments.find(
|
|
2973
|
-
(instrument) => instrument.id === decision.target,
|
|
2974
|
-
)!.subject!,
|
|
2975
|
-
attachmentName: id,
|
|
2976
|
-
parties: {},
|
|
2977
|
-
renames: new Map(),
|
|
2978
|
-
exposed: new Map(),
|
|
2979
|
-
}
|
|
2980
|
-
: undefined,
|
|
2981
|
-
);
|
|
2982
|
-
}
|
|
2983
|
-
}
|
|
2984
|
-
// Material approval fields are inferred from the selected action's typed input.
|
|
2985
|
-
for (const inst of document.instruments)
|
|
2986
|
-
for (const action of Object.values(inst.actions)) {
|
|
2987
|
-
if (!materialApprovals.has(action) || !action.approval) continue;
|
|
2988
|
-
const targetField = inst.fields.find(
|
|
2989
|
-
(f) => `self.${f.name}` === action.approval!.target,
|
|
2990
|
-
);
|
|
2991
|
-
if (targetField?.type !== "ref") continue;
|
|
2992
|
-
const target = document.instruments.find(
|
|
2993
|
-
(i) => i.id === targetField.target,
|
|
2994
|
-
)?.actions[action.approval.action];
|
|
2995
|
-
if (!target) continue;
|
|
2996
|
-
for (const field of target.input) {
|
|
2997
|
-
const name = `material_${field.name}`;
|
|
2998
|
-
if (!inst.fields.some((f) => f.name === name))
|
|
2999
|
-
inst.fields.push({ ...field, name });
|
|
3000
|
-
action.approval.input[field.name] = { field: `self.${name}` };
|
|
3001
|
-
}
|
|
3002
|
-
}
|
|
3003
2846
|
const changed = new Set<string>();
|
|
3004
2847
|
for (const decl of program.decls)
|
|
3005
2848
|
if (decl.kind === "hide" || decl.kind === "expose") {
|
package/src/headers.ts
CHANGED
|
@@ -11,7 +11,6 @@ export const HEADER_NAMES = [
|
|
|
11
11
|
"financing",
|
|
12
12
|
"lending",
|
|
13
13
|
"insurance",
|
|
14
|
-
"approvals",
|
|
15
14
|
"collections",
|
|
16
15
|
"travel",
|
|
17
16
|
"cards",
|
|
@@ -144,7 +143,7 @@ export function headerManifest(
|
|
|
144
143
|
: [];
|
|
145
144
|
})(),
|
|
146
145
|
parties: tunables
|
|
147
|
-
.filter((t) =>
|
|
146
|
+
.filter((t) => t.type === "party")
|
|
148
147
|
.map((t) => t.name),
|
|
149
148
|
actions: actions(decl.body),
|
|
150
149
|
};
|
package/src/lex.ts
CHANGED
package/src/parse.ts
CHANGED
|
@@ -330,20 +330,6 @@ class Parser {
|
|
|
330
330
|
return this.node(operator.text);
|
|
331
331
|
}
|
|
332
332
|
private requirement(): BlockExpr {
|
|
333
|
-
if (this.eat("approval")) {
|
|
334
|
-
this.expect("by");
|
|
335
|
-
const party = this.atom();
|
|
336
|
-
const values: Record<string, Expr> = {
|
|
337
|
-
kind: this.node("approval"),
|
|
338
|
-
party,
|
|
339
|
-
decision: this.node("approved"),
|
|
340
|
-
};
|
|
341
|
-
if (this.eat("for")) values.action = this.atom();
|
|
342
|
-
if (this.eat("is")) values.decision = this.atom();
|
|
343
|
-
for (const key of ["protectedRequest", "differentFromInitiator"])
|
|
344
|
-
if (this.eat(key)) values[key] = this.atom();
|
|
345
|
-
return this.record(values);
|
|
346
|
-
}
|
|
347
333
|
if (this.eat("unique")) {
|
|
348
334
|
const namespace = this.atom();
|
|
349
335
|
this.expect("on");
|