@intentius/chant 0.20.0 → 0.22.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/build.d.ts +7 -0
- package/dist/build.d.ts.map +1 -1
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/commands/check-lexicon-examples.d.ts.map +1 -1
- package/dist/cli/commands/check-lexicon-intrinsics.d.ts +17 -0
- package/dist/cli/commands/check-lexicon-intrinsics.d.ts.map +1 -1
- package/dist/cli/commands/check-lexicon.d.ts.map +1 -1
- package/dist/codegen/docs-types.d.ts +2 -0
- package/dist/codegen/docs-types.d.ts.map +1 -1
- package/dist/declarable.d.ts +16 -0
- package/dist/declarable.d.ts.map +1 -1
- package/dist/discovery/entity-wire-codec.d.ts.map +1 -1
- package/dist/discovery/fold-import.d.ts +64 -3
- package/dist/discovery/fold-import.d.ts.map +1 -1
- package/dist/discovery/index.d.ts +12 -0
- package/dist/discovery/index.d.ts.map +1 -1
- package/dist/fold/fold.d.ts +89 -16
- package/dist/fold/fold.d.ts.map +1 -1
- package/dist/fold/foldable-helpers.d.ts +121 -0
- package/dist/fold/foldable-helpers.d.ts.map +1 -0
- package/dist/fold/subset.d.ts +58 -3
- package/dist/fold/subset.d.ts.map +1 -1
- package/dist/lexicon-schema.d.ts +2 -0
- package/dist/lexicon-schema.d.ts.map +1 -1
- package/dist/lexicon.d.ts +73 -23
- package/dist/lexicon.d.ts.map +1 -1
- package/dist/runtime.d.ts +10 -1
- package/dist/runtime.d.ts.map +1 -1
- package/dist/serializer-walker.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/build.ts +9 -0
- package/src/cli/commands/build.ts +9 -0
- package/src/cli/commands/check-lexicon-examples.ts +16 -1
- package/src/cli/commands/check-lexicon-intrinsics.test.ts +35 -1
- package/src/cli/commands/check-lexicon-intrinsics.ts +38 -2
- package/src/cli/commands/check-lexicon.ts +18 -0
- package/src/codegen/docs-sections.test.ts +7 -1
- package/src/codegen/docs-sections.ts +1 -1
- package/src/codegen/docs-types.ts +2 -0
- package/src/declarable.ts +20 -0
- package/src/discovery/entity-wire-codec.ts +9 -7
- package/src/discovery/fold-import.test.ts +900 -1
- package/src/discovery/fold-import.ts +441 -47
- package/src/discovery/index.ts +25 -1
- package/src/fold/fold.test.ts +277 -0
- package/src/fold/fold.ts +219 -58
- package/src/fold/foldable-helpers.ts +171 -0
- package/src/fold/subset-doc-parity.test.ts +27 -0
- package/src/fold/subset.test.ts +177 -0
- package/src/fold/subset.ts +139 -31
- package/src/lexicon-schema.test.ts +43 -0
- package/src/lexicon-schema.ts +5 -0
- package/src/lexicon.ts +74 -24
- package/src/runtime.ts +11 -2
- package/src/serializer-walker.ts +14 -0
|
@@ -32,11 +32,16 @@ describe("generateIntrinsics — Folds? column", () => {
|
|
|
32
32
|
expect(page).toContain("| `Sub` | — | `Sub` | Yes | Yes |");
|
|
33
33
|
});
|
|
34
34
|
|
|
35
|
-
test("a plain-call intrinsic does not fold
|
|
35
|
+
test("a plain-call intrinsic its lexicon never opted in does not fold", () => {
|
|
36
36
|
const page = generateIntrinsics(config, manifestWith([{ name: "Ref", isTag: false }]));
|
|
37
37
|
expect(page).toContain("| `Ref` | — | `Ref` | No | No |");
|
|
38
38
|
});
|
|
39
39
|
|
|
40
|
+
test("a plain-call intrinsic opted into call-form folding does fold (chant #1044)", () => {
|
|
41
|
+
const page = generateIntrinsics(config, manifestWith([{ name: "Ref", isTag: false, foldsAsCall: true }]));
|
|
42
|
+
expect(page).toContain("| `Ref` | — | `Ref` | No | Yes |");
|
|
43
|
+
});
|
|
44
|
+
|
|
40
45
|
test("an intrinsic with isTag omitted does not fold (same as isTag: false)", () => {
|
|
41
46
|
const page = generateIntrinsics(config, manifestWith([{ name: "reference", outputKey: "!reference" }]));
|
|
42
47
|
expect(page).toContain("| `reference` | — | `!reference` | No | No |");
|
|
@@ -47,6 +52,7 @@ describe("generateIntrinsics — Folds? column", () => {
|
|
|
47
52
|
{ name: "Sub", isTag: true },
|
|
48
53
|
{ name: "Ref" },
|
|
49
54
|
{ name: "GetAtt", isTag: false },
|
|
55
|
+
{ name: "Join", isTag: false, foldsAsCall: true },
|
|
50
56
|
];
|
|
51
57
|
const page = generateIntrinsics(config, manifestWith(intrinsics));
|
|
52
58
|
for (const fn of intrinsics) {
|
|
@@ -95,7 +95,7 @@ export function generateIntrinsics(
|
|
|
95
95
|
"",
|
|
96
96
|
`The ${config.displayName} lexicon provides **${intrinsics.length}** intrinsic functions.`,
|
|
97
97
|
"",
|
|
98
|
-
`**Tag?** shows how an intrinsic is authored: a genuine tagged template (\`Sub\\\`...\\\`\`) or a plain function call (\`Ref(...)\`). **Folds?** shows whether [\`chant build --fold\`](/chant/concepts/typescript-as-data/#folded-vs-run) can reduce a
|
|
98
|
+
`**Tag?** shows how an intrinsic is authored: a genuine tagged template (\`Sub\\\`...\\\`\`) or a plain function call (\`Ref(...)\`). **Folds?** shows whether [\`chant build --fold\`](/chant/concepts/typescript-as-data/#folded-vs-run) can reduce a use of this intrinsic today, without running the file — generated directly from this lexicon's registration, not restated by hand. A tagged template folds once it is registered. A plain call folds only where this lexicon has opted that intrinsic in one at a time (\`foldsAsCall\`), so a \`No\` in this column means this intrinsic has not been opted in, not that calls in general cannot fold.`,
|
|
99
99
|
"",
|
|
100
100
|
"| Function | Description | Output Key | Tag? | Folds? |",
|
|
101
101
|
"|----------|-------------|------------|------|--------|",
|
|
@@ -55,6 +55,8 @@ export interface ManifestJSON {
|
|
|
55
55
|
description?: string;
|
|
56
56
|
outputKey?: string;
|
|
57
57
|
isTag?: boolean;
|
|
58
|
+
/** chant #1044 — the call-form fold opt-in, as published in the lexicon's manifest. Absent in any manifest built before #1044, which reads the same as "not opted in". */
|
|
59
|
+
foldsAsCall?: boolean;
|
|
58
60
|
}>;
|
|
59
61
|
pseudoParameters?: Record<string, string>;
|
|
60
62
|
}
|
package/src/declarable.ts
CHANGED
|
@@ -13,6 +13,26 @@ export interface Declarable {
|
|
|
13
13
|
readonly [DECLARABLE_MARKER]: true;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* A `Declarable` that carries a resource payload — the `props`/`attributes`
|
|
18
|
+
* fields that most lexicon serializers read to produce output. Not every
|
|
19
|
+
* `Declarable` has one (outputs and parameters genuinely don't), so this is
|
|
20
|
+
* kept as a sub-interface rather than widening the base type. See chant #1049.
|
|
21
|
+
*/
|
|
22
|
+
export interface ResourceDeclarable extends Declarable {
|
|
23
|
+
readonly props: unknown;
|
|
24
|
+
readonly attributes?: unknown;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Type guard for `ResourceDeclarable` — replaces the ad-hoc `"props" in x`
|
|
29
|
+
* checks that were previously repeated (with an `as unknown as` cast) at every
|
|
30
|
+
* call site that reads `props`/`attributes` off a `Declarable`.
|
|
31
|
+
*/
|
|
32
|
+
export function isResourceDeclarable(value: Declarable): value is ResourceDeclarable {
|
|
33
|
+
return "props" in value;
|
|
34
|
+
}
|
|
35
|
+
|
|
16
36
|
/**
|
|
17
37
|
* Core parameter type for lexicon-agnostic parameters
|
|
18
38
|
*/
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
* today.
|
|
55
55
|
*/
|
|
56
56
|
|
|
57
|
-
import { DECLARABLE_MARKER, type Declarable } from "../declarable";
|
|
57
|
+
import { DECLARABLE_MARKER, isResourceDeclarable, type Declarable } from "../declarable";
|
|
58
58
|
import { AttrRef } from "../attrref";
|
|
59
59
|
import { INTRINSIC_MARKER, type Intrinsic } from "../intrinsic";
|
|
60
60
|
import { isAttrRefLike } from "../utils";
|
|
@@ -256,7 +256,7 @@ function encodeValue(value: unknown, entityNames: Map<unknown, string>): WireVal
|
|
|
256
256
|
// directly rather than walking `resource` as a Declarable reference).
|
|
257
257
|
// Inline exactly that, discarding the unresolvable (and, in every corpus
|
|
258
258
|
// entry today, unread) identity layer.
|
|
259
|
-
const props =
|
|
259
|
+
const props = isResourceDeclarable(decl) ? decl.props : undefined;
|
|
260
260
|
return { __property: { lexicon: decl.lexicon, entityType: decl.entityType, props: props !== undefined ? encodeValue(props, entityNames) : undefined } };
|
|
261
261
|
}
|
|
262
262
|
|
|
@@ -280,11 +280,13 @@ function encodeDeclarable(entity: Declarable, entityNames: Map<unknown, string>)
|
|
|
280
280
|
const wire: Omit<WireDeclarableEntity, "form" | "name"> = { lexicon: entity.lexicon, entityType: entity.entityType, markers: [] };
|
|
281
281
|
if (entity.kind !== undefined) wire.kind = entity.kind;
|
|
282
282
|
|
|
283
|
-
if (
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
283
|
+
if (isResourceDeclarable(entity)) {
|
|
284
|
+
if (entity.props !== undefined) {
|
|
285
|
+
wire.props = encodeValue(entity.props, entityNames);
|
|
286
|
+
}
|
|
287
|
+
if (entity.attributes !== undefined) {
|
|
288
|
+
wire.attributes = encodeValue(entity.attributes, entityNames);
|
|
289
|
+
}
|
|
288
290
|
}
|
|
289
291
|
|
|
290
292
|
const markers: string[] = [];
|