@hyperscale0/hsx 5.6.0 → 5.7.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 +15 -0
- package/dist/src/compile.d.ts.map +1 -1
- package/dist/src/compile.js +74 -3
- package/dist/src/compile.js.map +1 -1
- package/dist/src/examples-bundle.js +3 -3
- package/dist/src/examples-bundle.js.map +1 -1
- package/dist/src/std-bundle.js +1 -1
- 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 +45 -11
- package/docs/examples.md +1 -1
- package/examples/collections.hsx +8 -2
- package/examples/financing.hsx +5 -0
- package/examples/lending.hsx +7 -1
- package/package.json +3 -3
- package/src/compile.ts +95 -3
- package/src/examples-bundle.ts +3 -3
- package/src/std-bundle.ts +1 -1
- package/src/version.ts +1 -1
- package/std/financing.hsx +3 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
# HSX 5.7.0
|
|
2
|
+
|
|
3
|
+
Follows UDL 4.9.0. Object `entryActions` admits enrolled customers through named
|
|
4
|
+
actor-bound create actions. Product-scoped limits resolve across records with
|
|
5
|
+
matching parties. `programTax` moves use an operator-owned pass-through account.
|
|
6
|
+
|
|
7
|
+
Late charge creation accepts a slice reference for plans with multiple instalments.
|
|
8
|
+
Financing, collections and lending samples expose repayment child actions.
|
|
9
|
+
Aggregate selectors retain their selected instrument family, including child
|
|
10
|
+
records, so shared limits compare the matching contracts across Builds.
|
|
11
|
+
|
|
12
|
+
# HSX 5.6.1
|
|
13
|
+
|
|
14
|
+
Action summaries without authored text use the action title without the instrument id.
|
|
15
|
+
|
|
1
16
|
# HSX 5.6.0
|
|
2
17
|
|
|
3
18
|
The compiler records the standard block origin of every instrument compiled
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../src/compile.ts"],"names":[],"mappings":"AAEA,OAAO,EAAwB,KAAK,eAAe,EAAE,MAAM,WAAW,CAAC;AACvE,OAAO,EAeL,KAAK,WAAW,EAOjB,MAAM,kBAAkB,CAAC;AAS1B,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;IAC9C,aAAa,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3E;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;AAqTD,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":"AAEA,OAAO,EAAwB,KAAK,eAAe,EAAE,MAAM,WAAW,CAAC;AACvE,OAAO,EAeL,KAAK,WAAW,EAOjB,MAAM,kBAAkB,CAAC;AAS1B,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;IAC9C,aAAa,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3E;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;AAqTD,wBAAgB,OAAO,CACrB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,cAAmB,GAC3B,aAAa,CA8yGf"}
|
package/dist/src/compile.js
CHANGED
|
@@ -1014,6 +1014,7 @@ export function compile(source, options = {}) {
|
|
|
1014
1014
|
"parameterDiagnostics",
|
|
1015
1015
|
"reports",
|
|
1016
1016
|
"revisioned",
|
|
1017
|
+
"scope",
|
|
1017
1018
|
].includes(key) &&
|
|
1018
1019
|
!key.startsWith("action "))
|
|
1019
1020
|
fail(decl, `unknown instrument clause ${key}`, "use fields, lifecycle, actions, invariants, or records");
|
|
@@ -1646,7 +1647,7 @@ export function compile(source, options = {}) {
|
|
|
1646
1647
|
const a = {
|
|
1647
1648
|
summary: slots.has("summary")
|
|
1648
1649
|
? String(data(slots.get("summary")))
|
|
1649
|
-
:
|
|
1650
|
+
: title(name),
|
|
1650
1651
|
publicAction: camel(`${name}_${id}`),
|
|
1651
1652
|
event: `${id}.${name}`,
|
|
1652
1653
|
actor: "caller",
|
|
@@ -2033,9 +2034,38 @@ export function compile(source, options = {}) {
|
|
|
2033
2034
|
inst.actions[name] = a;
|
|
2034
2035
|
inst.actionOrder.push(name);
|
|
2035
2036
|
}
|
|
2036
|
-
for (const key of [
|
|
2037
|
+
for (const key of [
|
|
2038
|
+
"invariants",
|
|
2039
|
+
"reports",
|
|
2040
|
+
"revisioned",
|
|
2041
|
+
"scope",
|
|
2042
|
+
])
|
|
2037
2043
|
if (body.has(key))
|
|
2038
2044
|
inst[key] = data(body.get(key));
|
|
2045
|
+
let usesTax = false;
|
|
2046
|
+
for (const action of Object.values(inst.actions)) {
|
|
2047
|
+
for (const move of action.moves) {
|
|
2048
|
+
if (!("from" in move))
|
|
2049
|
+
continue;
|
|
2050
|
+
for (const endpoint of ["from", "to"]) {
|
|
2051
|
+
if (move[endpoint] === "party.programTax") {
|
|
2052
|
+
move[endpoint] = "self.programTaxPayable";
|
|
2053
|
+
usesTax = true;
|
|
2054
|
+
}
|
|
2055
|
+
}
|
|
2056
|
+
}
|
|
2057
|
+
}
|
|
2058
|
+
if (usesTax) {
|
|
2059
|
+
if (inst.fields.some((field) => field.name === "programTaxPayable"))
|
|
2060
|
+
fail(decl, "programTaxPayable is reserved for the tax account", "rename the authored field");
|
|
2061
|
+
inst.fields.push({
|
|
2062
|
+
name: "programTaxPayable",
|
|
2063
|
+
type: "account",
|
|
2064
|
+
owner: "programOperator",
|
|
2065
|
+
book: "cash",
|
|
2066
|
+
key: "programTax",
|
|
2067
|
+
});
|
|
2068
|
+
}
|
|
2039
2069
|
const shape = udlInstrumentSchema.safeParse(inst);
|
|
2040
2070
|
if (!shape.success) {
|
|
2041
2071
|
const issue = shape.error.issues[0];
|
|
@@ -2111,8 +2141,9 @@ export function compile(source, options = {}) {
|
|
|
2111
2141
|
for (const key of body.keys()) {
|
|
2112
2142
|
if (key !== "fields" &&
|
|
2113
2143
|
key !== "columns" &&
|
|
2144
|
+
key !== "entryActions" &&
|
|
2114
2145
|
!key.startsWith("attach ")) {
|
|
2115
|
-
fail(decl, `unknown object clause ${key}`, "use fields, columns, or attach");
|
|
2146
|
+
fail(decl, `unknown object clause ${key}`, "use fields, columns, entryActions, or attach");
|
|
2116
2147
|
}
|
|
2117
2148
|
}
|
|
2118
2149
|
const authoredFields = [];
|
|
@@ -2271,9 +2302,17 @@ export function compile(source, options = {}) {
|
|
|
2271
2302
|
fail(columnsExpr, `The object list selects ${columns.length} columns; this release supports 8. The object may retain all its fields.`, `Remove ${columns.length === 9 ? "one name" : `${columns.length - 8} names`} from \`columns\`, not from \`fields\`.`);
|
|
2272
2303
|
}
|
|
2273
2304
|
}
|
|
2305
|
+
const entryExpr = body.get("entryActions");
|
|
2306
|
+
let entryActions;
|
|
2307
|
+
if (entryExpr) {
|
|
2308
|
+
if (entryExpr.kind !== "list" || !entryExpr.items.length)
|
|
2309
|
+
fail(entryExpr, "entryActions needs a nonempty list", "name exposed create actions bound to actor");
|
|
2310
|
+
entryActions = entryExpr.items.map(text);
|
|
2311
|
+
}
|
|
2274
2312
|
document.objects.push({
|
|
2275
2313
|
id: decl.name,
|
|
2276
2314
|
title: decl.title,
|
|
2315
|
+
...(entryActions ? { entryActions } : {}),
|
|
2277
2316
|
authoredFields: authoredNames,
|
|
2278
2317
|
attachments,
|
|
2279
2318
|
fields: authoredFields,
|
|
@@ -2302,6 +2341,25 @@ export function compile(source, options = {}) {
|
|
|
2302
2341
|
.sort((a, b) => a.span.start - b.span.start)
|
|
2303
2342
|
.map((d) => diagnostic(d, "check")),
|
|
2304
2343
|
};
|
|
2344
|
+
// Resolve selectors after every attachment and child has its family.
|
|
2345
|
+
const retainSelectionFamilies = (value) => {
|
|
2346
|
+
if (!value || typeof value !== "object")
|
|
2347
|
+
return;
|
|
2348
|
+
const record = value;
|
|
2349
|
+
const selection = record.selection;
|
|
2350
|
+
if (selection && !selection.family) {
|
|
2351
|
+
const families = [selection.instrument]
|
|
2352
|
+
.flat()
|
|
2353
|
+
.map((id) => document.instruments.find((item) => item.id === id)?.family);
|
|
2354
|
+
const family = families[0];
|
|
2355
|
+
if (family &&
|
|
2356
|
+
families.every((item) => canonicalJson(item) === canonicalJson(family)))
|
|
2357
|
+
selection.family = family;
|
|
2358
|
+
}
|
|
2359
|
+
for (const child of Object.values(record))
|
|
2360
|
+
retainSelectionFamilies(child);
|
|
2361
|
+
};
|
|
2362
|
+
retainSelectionFamilies(document);
|
|
2305
2363
|
// Propagate invoked requirements with the conditions on each invocation path.
|
|
2306
2364
|
let changedInvocations = true;
|
|
2307
2365
|
let invocationIterations = 0;
|
|
@@ -2557,6 +2615,19 @@ export function compile(source, options = {}) {
|
|
|
2557
2615
|
if (Object.values(instrument.actions).filter((action) => action.publicAction === decl.name).length > 1)
|
|
2558
2616
|
fail(decl, `public action ${decl.name} is used more than once on ${parts.join(".")}`, "give each exposed action a distinct public name");
|
|
2559
2617
|
}
|
|
2618
|
+
for (const kind of document.objects) {
|
|
2619
|
+
for (const name of kind.entryActions ?? []) {
|
|
2620
|
+
const eligible = kind.attachments.some((attachment) => {
|
|
2621
|
+
const create = document.instruments.find((instrument) => instrument.id === attachment.instrument)?.actions.create;
|
|
2622
|
+
return (create?.publicAction === name &&
|
|
2623
|
+
typeof create.actor === "object" &&
|
|
2624
|
+
"party" in create.actor &&
|
|
2625
|
+
create.actor.party === "actor");
|
|
2626
|
+
});
|
|
2627
|
+
if (!eligible)
|
|
2628
|
+
fail(objects.get(kind.id), `entry action ${name} must create an attachment as actor`, "expose its create action and bind its acting party to actor");
|
|
2629
|
+
}
|
|
2630
|
+
}
|
|
2560
2631
|
const usedParties = new Set();
|
|
2561
2632
|
const collectParties = (value) => {
|
|
2562
2633
|
if (typeof value === "string") {
|