@hyperscale0/hsx 5.0.1 → 5.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 +12 -0
- package/dist/src/compile.d.ts.map +1 -1
- package/dist/src/compile.js +90 -17
- package/dist/src/compile.js.map +1 -1
- package/dist/src/std-bundle.js +5 -5
- 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 +26 -18
- package/package.json +3 -3
- package/src/compile.ts +116 -17
- package/src/std-bundle.ts +5 -5
- package/src/version.ts +1 -1
- package/std/cards.hsx +2 -0
- package/std/financing.hsx +1 -1
- package/std/lending.hsx +3 -2
- package/std/money.hsx +1 -0
- package/std/reporting.hsx +32 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
# HSX 5.1.0
|
|
2
|
+
|
|
3
|
+
Child records of an attached instrument compile as their own attachments
|
|
4
|
+
(`<attachment>_<record>` with a `parent`), so a guarded child action is
|
|
5
|
+
discoverable and admissible from the object it belongs to (UDL 4.3.0).
|
|
6
|
+
|
|
7
|
+
Standard library review: card authorizations require an active holder,
|
|
8
|
+
a lending commitment records its investor account and caps tickets per
|
|
9
|
+
investor rather than per wallet, pool contributions are bounded at 366
|
|
10
|
+
paid records, portfolio ageing counts earned profit as outstanding, and
|
|
11
|
+
a late charge assesses a zero amount without refusing. Docs corrected.
|
|
12
|
+
|
|
1
13
|
# HSX 5.0.1
|
|
2
14
|
|
|
3
15
|
Per-action subject evidence compiles: `fields { price: money = subject.price }`
|
|
@@ -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;AAQ1B,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;AAQ1B,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,CAo4Ff"}
|
package/dist/src/compile.js
CHANGED
|
@@ -1831,7 +1831,7 @@ export function compile(source, options = {}) {
|
|
|
1831
1831
|
else
|
|
1832
1832
|
a[key] = data(expr);
|
|
1833
1833
|
}
|
|
1834
|
-
if (attachmentInfo) {
|
|
1834
|
+
if (attachmentInfo && !attachmentInfo.child) {
|
|
1835
1835
|
if (attachmentInfo.exposed.has(name)) {
|
|
1836
1836
|
a.publicAction = attachmentInfo.exposed.get(name);
|
|
1837
1837
|
}
|
|
@@ -1893,6 +1893,21 @@ export function compile(source, options = {}) {
|
|
|
1893
1893
|
}
|
|
1894
1894
|
document.instruments.push(inst);
|
|
1895
1895
|
for (const [key, definition] of records) {
|
|
1896
|
+
const childAttachment = attachmentInfo
|
|
1897
|
+
? {
|
|
1898
|
+
...attachmentInfo,
|
|
1899
|
+
attachmentName: `${attachmentInfo.attachmentName}_${key}`,
|
|
1900
|
+
child: true,
|
|
1901
|
+
exposed: new Map(),
|
|
1902
|
+
}
|
|
1903
|
+
: undefined;
|
|
1904
|
+
if (childAttachment)
|
|
1905
|
+
childAttachment.attachments.push({
|
|
1906
|
+
name: childAttachment.attachmentName,
|
|
1907
|
+
parent: attachmentInfo.attachmentName,
|
|
1908
|
+
instrument: `${id}_${key}`,
|
|
1909
|
+
parties: childAttachment.parties,
|
|
1910
|
+
});
|
|
1896
1911
|
const child = {
|
|
1897
1912
|
kind: "instrument",
|
|
1898
1913
|
name: key,
|
|
@@ -1913,9 +1928,7 @@ export function compile(source, options = {}) {
|
|
|
1913
1928
|
addInstrument(child, `${id}_${key}`, emptyBlock, origin, new Map([
|
|
1914
1929
|
...environment,
|
|
1915
1930
|
["parent", { kind: "name", value: id, span: origin }],
|
|
1916
|
-
]), enums,
|
|
1917
|
-
? { ...attachmentInfo, exposed: new Map() }
|
|
1918
|
-
: undefined, childFamily);
|
|
1931
|
+
]), enums, childAttachment, childFamily);
|
|
1919
1932
|
}
|
|
1920
1933
|
};
|
|
1921
1934
|
const compileObject = (decl) => {
|
|
@@ -1986,6 +1999,7 @@ export function compile(source, options = {}) {
|
|
|
1986
1999
|
span: entry.value.span,
|
|
1987
2000
|
};
|
|
1988
2001
|
const templateFamily = resolveFamily(targetTemplate, entry, false);
|
|
2002
|
+
const firstAttachedInstrument = document.instruments.length;
|
|
1989
2003
|
try {
|
|
1990
2004
|
addInstrument(template, instId, tunableBlock, entry.span, new Map(), new Map(), {
|
|
1991
2005
|
subjectKindId: decl.name,
|
|
@@ -1993,6 +2007,7 @@ export function compile(source, options = {}) {
|
|
|
1993
2007
|
renames,
|
|
1994
2008
|
exposed,
|
|
1995
2009
|
parties,
|
|
2010
|
+
attachments,
|
|
1996
2011
|
}, templateFamily ? { ...templateFamily } : undefined);
|
|
1997
2012
|
}
|
|
1998
2013
|
catch (error) {
|
|
@@ -2002,17 +2017,22 @@ export function compile(source, options = {}) {
|
|
|
2002
2017
|
continue;
|
|
2003
2018
|
}
|
|
2004
2019
|
const attachedInst = document.instruments.find((i) => i.id === instId);
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2020
|
+
for (const createdInst of document.instruments
|
|
2021
|
+
.slice(firstAttachedInstrument)
|
|
2022
|
+
.filter((instrument) => instrument.id === instId ||
|
|
2023
|
+
instrument.actions.create?.publicAction)) {
|
|
2024
|
+
if (!createdInst.actions.create)
|
|
2025
|
+
continue;
|
|
2026
|
+
const owned = new Set(createdInst.calculate.map((node) => node.target));
|
|
2027
|
+
for (const action of Object.values(createdInst.actions)) {
|
|
2008
2028
|
for (const node of action.calculate ?? [])
|
|
2009
2029
|
owned.add(node.target);
|
|
2010
2030
|
for (const move of action.moves)
|
|
2011
2031
|
if ("capture" in move && move.capture)
|
|
2012
2032
|
owned.add(move.capture);
|
|
2013
2033
|
}
|
|
2014
|
-
const create =
|
|
2015
|
-
for (const field of
|
|
2034
|
+
const create = createdInst.actions.create;
|
|
2035
|
+
for (const field of createdInst.fields) {
|
|
2016
2036
|
if (field.type === "account" ||
|
|
2017
2037
|
(field.type === "ref" && field.targetKind === "instrument") ||
|
|
2018
2038
|
(field.type === "list" &&
|
|
@@ -2020,13 +2040,14 @@ export function compile(source, options = {}) {
|
|
|
2020
2040
|
field.targetKind === "instrument") ||
|
|
2021
2041
|
field.optional ||
|
|
2022
2042
|
"value" in field ||
|
|
2023
|
-
owned.has(field.name)
|
|
2043
|
+
owned.has(field.name) ||
|
|
2044
|
+
create.input.some((input) => input.name === field.name))
|
|
2024
2045
|
continue;
|
|
2025
2046
|
create.subject ??= { requirements: [], adapters: [] };
|
|
2026
2047
|
const existing = create.subject.requirements.find((item) => item.field.name === field.name);
|
|
2027
2048
|
if (existing) {
|
|
2028
2049
|
if (canonicalJson(existing.field) !== canonicalJson(field))
|
|
2029
|
-
failWithCode(entry, "subject_field_conflict", `${
|
|
2050
|
+
failWithCode(entry, "subject_field_conflict", `${createdInst.id}.create.subject.${field.name} conflicts with its instrument field`, "use the instrument field's type and constraints");
|
|
2030
2051
|
continue;
|
|
2031
2052
|
}
|
|
2032
2053
|
const objectField = renames.get(field.name);
|
|
@@ -2038,7 +2059,7 @@ export function compile(source, options = {}) {
|
|
|
2038
2059
|
requirementOrigins.set(requirement, {
|
|
2039
2060
|
source: declarationSources.get(template) ?? "program",
|
|
2040
2061
|
span: entry.span,
|
|
2041
|
-
message: `${
|
|
2062
|
+
message: `${createdInst.id}.create.fields.${field.name}`,
|
|
2042
2063
|
});
|
|
2043
2064
|
}
|
|
2044
2065
|
}
|
|
@@ -2099,17 +2120,15 @@ export function compile(source, options = {}) {
|
|
|
2099
2120
|
.sort((a, b) => a.span.start - b.span.start)
|
|
2100
2121
|
.map((d) => diagnostic(d, "check")),
|
|
2101
2122
|
};
|
|
2102
|
-
// Propagate
|
|
2123
|
+
// Propagate invoked requirements with the conditions on each invocation path.
|
|
2103
2124
|
let changedInvocations = true;
|
|
2104
2125
|
let invocationIterations = 0;
|
|
2105
2126
|
while (changedInvocations && invocationIterations < 32) {
|
|
2106
2127
|
changedInvocations = false;
|
|
2107
2128
|
invocationIterations++;
|
|
2108
2129
|
for (const inst of document.instruments) {
|
|
2109
|
-
for (const action of Object.
|
|
2130
|
+
for (const [actionName, action] of Object.entries(inst.actions)) {
|
|
2110
2131
|
for (const call of action.invoke ?? []) {
|
|
2111
|
-
if (call.guard)
|
|
2112
|
-
continue;
|
|
2113
2132
|
let targetIds = [];
|
|
2114
2133
|
if ("instrument" in call) {
|
|
2115
2134
|
targetIds = [call.instrument];
|
|
@@ -2141,7 +2160,9 @@ export function compile(source, options = {}) {
|
|
|
2141
2160
|
if (!action.subject) {
|
|
2142
2161
|
action.subject = { requirements: [], adapters: [] };
|
|
2143
2162
|
}
|
|
2144
|
-
for (const adapter of
|
|
2163
|
+
for (const adapter of call.guard
|
|
2164
|
+
? []
|
|
2165
|
+
: targetAction.subject.adapters) {
|
|
2145
2166
|
if (!action.subject.adapters.some((existing) => existing.binding === adapter.binding)) {
|
|
2146
2167
|
action.subject.adapters.push(adapter);
|
|
2147
2168
|
changedInvocations = true;
|
|
@@ -2150,9 +2171,47 @@ export function compile(source, options = {}) {
|
|
|
2150
2171
|
for (const targetReq of targetAction.subject.requirements) {
|
|
2151
2172
|
const targetObjFieldName = targetReq.objectField ?? targetReq.field.name;
|
|
2152
2173
|
const existing = action.subject.requirements.find((cr) => (cr.objectField ?? cr.field.name) === targetObjFieldName);
|
|
2174
|
+
const guardValue = (value) => {
|
|
2175
|
+
if (!("field" in value) ||
|
|
2176
|
+
!value.field.startsWith("subject."))
|
|
2177
|
+
return value;
|
|
2178
|
+
const requirement = action.subject?.requirements.find((item) => item.field.name === value.field.slice(8));
|
|
2179
|
+
return {
|
|
2180
|
+
field: `subject.${requirement?.objectField ?? requirement?.field.name ?? value.field.slice(8)}`,
|
|
2181
|
+
};
|
|
2182
|
+
};
|
|
2183
|
+
const guardType = call.guard &&
|
|
2184
|
+
[call.guard.left, call.guard.right]
|
|
2185
|
+
.flatMap((value) => "field" in value
|
|
2186
|
+
? [
|
|
2187
|
+
resolveField(document, inst, value.field, action.input, action)?.type,
|
|
2188
|
+
]
|
|
2189
|
+
: [])
|
|
2190
|
+
.find((type) => type === "money" || type === "date");
|
|
2191
|
+
const condition = call.guard
|
|
2192
|
+
? {
|
|
2193
|
+
instrument: inst.id,
|
|
2194
|
+
action: actionName,
|
|
2195
|
+
guard: {
|
|
2196
|
+
...call.guard,
|
|
2197
|
+
left: guardValue(call.guard.left),
|
|
2198
|
+
right: guardValue(call.guard.right),
|
|
2199
|
+
},
|
|
2200
|
+
...(guardType === "money" || guardType === "date"
|
|
2201
|
+
? { valueType: guardType }
|
|
2202
|
+
: {}),
|
|
2203
|
+
}
|
|
2204
|
+
: undefined;
|
|
2205
|
+
const when = condition
|
|
2206
|
+
? (targetReq.when ?? [[]]).map((path) => [
|
|
2207
|
+
condition,
|
|
2208
|
+
...path.filter((item) => canonicalJson(item) !== canonicalJson(condition)),
|
|
2209
|
+
])
|
|
2210
|
+
: targetReq.when;
|
|
2153
2211
|
if (!existing) {
|
|
2154
2212
|
const inherited = {
|
|
2155
2213
|
field: { ...targetReq.field, name: targetObjFieldName },
|
|
2214
|
+
...(when ? { when: when.map((path) => [...path]) } : {}),
|
|
2156
2215
|
};
|
|
2157
2216
|
action.subject.requirements.push(inherited);
|
|
2158
2217
|
requirementOrigins.set(inherited, requirementOrigins.get(targetReq));
|
|
@@ -2170,6 +2229,20 @@ export function compile(source, options = {}) {
|
|
|
2170
2229
|
related: [first, second],
|
|
2171
2230
|
});
|
|
2172
2231
|
}
|
|
2232
|
+
else if (existing.when) {
|
|
2233
|
+
if (!when) {
|
|
2234
|
+
delete existing.when;
|
|
2235
|
+
changedInvocations = true;
|
|
2236
|
+
}
|
|
2237
|
+
else {
|
|
2238
|
+
for (const path of when) {
|
|
2239
|
+
if (!existing.when.some((known) => canonicalJson(known) === canonicalJson(path))) {
|
|
2240
|
+
existing.when.push(path);
|
|
2241
|
+
changedInvocations = true;
|
|
2242
|
+
}
|
|
2243
|
+
}
|
|
2244
|
+
}
|
|
2245
|
+
}
|
|
2173
2246
|
}
|
|
2174
2247
|
}
|
|
2175
2248
|
}
|