@fabricorg/experience-runtime 0.4.7 → 0.4.9

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 CHANGED
@@ -1,5 +1,38 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.9
4
+
5
+ ### Patch Changes
6
+
7
+ - 939bcad: Build packages with tsdown in place of tsup. Preserve the published ESM/CommonJS
8
+ entry paths, ES2022 target, declaration filenames, and raw external module
9
+ specifier spellings, including the existing Node built-in spellings.
10
+
11
+ Generated JavaScript, source-map contents, declaration formatting, and internal
12
+ chunk layout change. Comparison with the saved tsup build found unchanged named
13
+ runtime exports and public declaration signatures. Declaration maps remain
14
+ unpublished. Facade maps are no longer published for Platform's root, evidence,
15
+ and policies entries, or experience-runtime's contracts entry (both `.js.map`
16
+ and `.cjs.map`). Their new JavaScript output has no source-map URL comment.
17
+
18
+ CommonJS interop: 29 of 72 baseline CJS files expose an `__esModule` marker;
19
+ 0 of 57 tsdown CJS files do. The compared package entries have no default runtime
20
+ export, and the emitted `.d.cts` files declare none. Typed consumers of the
21
+ unchanged declared exports are unaffected. For entries whose marker was removed,
22
+ an untyped CJS `import X from` compiled with a Babel-style default-interop helper
23
+ now yields the namespace instead of `undefined`.
24
+
25
+ - Updated dependencies [939bcad]
26
+ - @fabricorg/sdui-release@0.7.9
27
+
28
+ ## 0.4.8
29
+
30
+ ### Patch Changes
31
+
32
+ - 5d93521: Republish workspace dependents of `@fabricorg/platform` and `@fabricorg/platform-host`, including transitive and development dependencies, alongside the handler reconciliation contract (issue #70). Workspace ranges resolve to the released versions when packed; existing literal compatibility ranges remain unchanged. Runtime source is unchanged. Private example workspaces are not published.
33
+ - Updated dependencies [5d93521]
34
+ - @fabricorg/sdui-release@0.7.8
35
+
3
36
  ## 0.4.7
4
37
 
5
38
  ### Patch Changes
package/dist/client.cjs CHANGED
@@ -1,146 +1,129 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // client.ts
21
- var client_exports = {};
22
- __export(client_exports, {
23
- createExperienceSession: () => createExperienceSession,
24
- experienceClientChecks: () => experienceClientChecks,
25
- runExperienceClientChecks: () => runExperienceClientChecks
26
- });
27
- module.exports = __toCommonJS(client_exports);
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region client.ts
28
3
  function createExperienceSession(plan, gateway) {
29
- const fragments = indexFragments(plan.root);
30
- return {
31
- plan,
32
- async invoke(fragmentId, eventName, parameters, idempotencyKey) {
33
- const fragment = fragments.get(fragmentId);
34
- if (!fragment?.events?.includes(eventName)) {
35
- throw new Error(`Fragment event "${fragmentId}.${eventName}" is not in the render plan.`);
36
- }
37
- return gateway.invoke({
38
- planId: plan.planId,
39
- fragmentId,
40
- eventName,
41
- parameters,
42
- ...idempotencyKey === void 0 ? {} : { idempotencyKey }
43
- });
44
- },
45
- async read(fragmentId, bindingName, parameters) {
46
- const fragment = fragments.get(fragmentId);
47
- if (!fragment?.bindings?.includes(bindingName)) {
48
- throw new Error(`Fragment binding "${fragmentId}.${bindingName}" is not in the render plan.`);
49
- }
50
- return gateway.read({
51
- planId: plan.planId,
52
- fragmentId,
53
- bindingName,
54
- ...parameters === void 0 ? {} : { parameters }
55
- });
56
- }
57
- };
4
+ const fragments = indexFragments(plan.root);
5
+ return {
6
+ plan,
7
+ async invoke(fragmentId, eventName, parameters, idempotencyKey) {
8
+ if (!fragments.get(fragmentId)?.events?.includes(eventName)) throw new Error(`Fragment event "${fragmentId}.${eventName}" is not in the render plan.`);
9
+ return gateway.invoke({
10
+ planId: plan.planId,
11
+ fragmentId,
12
+ eventName,
13
+ parameters,
14
+ ...idempotencyKey === void 0 ? {} : { idempotencyKey }
15
+ });
16
+ },
17
+ async read(fragmentId, bindingName, parameters) {
18
+ if (!fragments.get(fragmentId)?.bindings?.includes(bindingName)) throw new Error(`Fragment binding "${fragmentId}.${bindingName}" is not in the render plan.`);
19
+ return gateway.read({
20
+ planId: plan.planId,
21
+ fragmentId,
22
+ bindingName,
23
+ ...parameters === void 0 ? {} : { parameters }
24
+ });
25
+ }
26
+ };
58
27
  }
59
28
  function experienceClientChecks() {
60
- const plan = {
61
- formatVersion: 1,
62
- planId: "conformance-plan",
63
- application: "conformance",
64
- channel: "test",
65
- releaseDigest: "a".repeat(64),
66
- assemblyDigest: "b".repeat(64),
67
- treeId: "root",
68
- tokenSet: { name: "conformance", version: "1.0.0" },
69
- expiresAt: "2099-01-01T00:00:00.000Z",
70
- root: { id: "root", component: "Action", events: ["press"], bindings: ["summary"] }
71
- };
72
- return [
73
- {
74
- id: "fabric.experience.client-tuple-routing.v1",
75
- async run(subject) {
76
- const calls = [];
77
- const session = subject.create(plan, {
78
- async invoke(request) {
79
- calls.push(`${request.fragmentId}.${request.eventName}`);
80
- return { status: "accepted" };
81
- },
82
- async read(request) {
83
- calls.push(`${request.fragmentId}.${request.bindingName}`);
84
- return { data: { ok: true } };
85
- }
86
- });
87
- await session.invoke("root", "press", {});
88
- await session.read("root", "summary");
89
- if (calls.join(",") !== "root.press,root.summary") throw new Error("Client did not route through fragment-event and fragment-binding tuples.");
90
- return calls;
91
- }
92
- },
93
- {
94
- id: "fabric.experience.client-plan-denial.v1",
95
- async run(subject) {
96
- let called = false;
97
- const session = subject.create(plan, {
98
- async invoke() {
99
- called = true;
100
- return { status: "accepted" };
101
- },
102
- async read() {
103
- called = true;
104
- return { data: null };
105
- }
106
- });
107
- let rejected = false;
108
- try {
109
- await session.invoke("root", "undeclared", {});
110
- } catch {
111
- rejected = true;
112
- }
113
- if (!rejected || called) throw new Error("Client forwarded an event that was absent from the scoped plan.");
114
- return ["undeclared event rejected locally"];
115
- }
116
- }
117
- ];
29
+ const plan = {
30
+ formatVersion: 1,
31
+ planId: "conformance-plan",
32
+ application: "conformance",
33
+ channel: "test",
34
+ releaseDigest: "a".repeat(64),
35
+ assemblyDigest: "b".repeat(64),
36
+ treeId: "root",
37
+ tokenSet: {
38
+ name: "conformance",
39
+ version: "1.0.0"
40
+ },
41
+ expiresAt: "2099-01-01T00:00:00.000Z",
42
+ root: {
43
+ id: "root",
44
+ component: "Action",
45
+ events: ["press"],
46
+ bindings: ["summary"]
47
+ }
48
+ };
49
+ return [{
50
+ id: "fabric.experience.client-tuple-routing.v1",
51
+ async run(subject) {
52
+ const calls = [];
53
+ const session = subject.create(plan, {
54
+ async invoke(request) {
55
+ calls.push(`${request.fragmentId}.${request.eventName}`);
56
+ return { status: "accepted" };
57
+ },
58
+ async read(request) {
59
+ calls.push(`${request.fragmentId}.${request.bindingName}`);
60
+ return { data: { ok: true } };
61
+ }
62
+ });
63
+ await session.invoke("root", "press", {});
64
+ await session.read("root", "summary");
65
+ if (calls.join(",") !== "root.press,root.summary") throw new Error("Client did not route through fragment-event and fragment-binding tuples.");
66
+ return calls;
67
+ }
68
+ }, {
69
+ id: "fabric.experience.client-plan-denial.v1",
70
+ async run(subject) {
71
+ let called = false;
72
+ const session = subject.create(plan, {
73
+ async invoke() {
74
+ called = true;
75
+ return { status: "accepted" };
76
+ },
77
+ async read() {
78
+ called = true;
79
+ return { data: null };
80
+ }
81
+ });
82
+ let rejected = false;
83
+ try {
84
+ await session.invoke("root", "undeclared", {});
85
+ } catch {
86
+ rejected = true;
87
+ }
88
+ if (!rejected || called) throw new Error("Client forwarded an event that was absent from the scoped plan.");
89
+ return ["undeclared event rejected locally"];
90
+ }
91
+ }];
118
92
  }
119
93
  async function runExperienceClientChecks(subject, checks = experienceClientChecks()) {
120
- const results = [];
121
- for (const check of checks) {
122
- try {
123
- results.push({ id: check.id, status: "passed", evidence: await check.run(subject) });
124
- } catch (error) {
125
- results.push({ id: check.id, status: "failed", evidence: [], error: error instanceof Error ? error.message : String(error) });
126
- }
127
- }
128
- return { passed: results.every((result) => result.status === "passed"), checks: results };
94
+ const results = [];
95
+ for (const check of checks) try {
96
+ results.push({
97
+ id: check.id,
98
+ status: "passed",
99
+ evidence: await check.run(subject)
100
+ });
101
+ } catch (error) {
102
+ results.push({
103
+ id: check.id,
104
+ status: "failed",
105
+ evidence: [],
106
+ error: error instanceof Error ? error.message : String(error)
107
+ });
108
+ }
109
+ return {
110
+ passed: results.every((result) => result.status === "passed"),
111
+ checks: results
112
+ };
129
113
  }
130
114
  function indexFragments(root) {
131
- const fragments = /* @__PURE__ */ new Map();
132
- const visit = (fragment) => {
133
- if (fragments.has(fragment.id)) throw new Error(`Render plan repeats fragment "${fragment.id}".`);
134
- fragments.set(fragment.id, fragment);
135
- for (const child of fragment.children ?? []) visit(child);
136
- };
137
- visit(root);
138
- return fragments;
115
+ const fragments = /* @__PURE__ */ new Map();
116
+ const visit = (fragment) => {
117
+ if (fragments.has(fragment.id)) throw new Error(`Render plan repeats fragment "${fragment.id}".`);
118
+ fragments.set(fragment.id, fragment);
119
+ for (const child of fragment.children ?? []) visit(child);
120
+ };
121
+ visit(root);
122
+ return fragments;
139
123
  }
140
- // Annotate the CommonJS export names for ESM import in node:
141
- 0 && (module.exports = {
142
- createExperienceSession,
143
- experienceClientChecks,
144
- runExperienceClientChecks
145
- });
124
+ //#endregion
125
+ exports.createExperienceSession = createExperienceSession;
126
+ exports.experienceClientChecks = experienceClientChecks;
127
+ exports.runExperienceClientChecks = runExperienceClientChecks;
128
+
146
129
  //# sourceMappingURL=client.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../client.ts"],"sourcesContent":["import type {\n\tExperienceGatewayClient,\n\tExperienceSession,\n\tRenderPlanFragment,\n\tScopedRenderPlan,\n} from \"./contracts\";\n\nexport type {\n\tExperienceGatewayClient,\n\tExperienceIntentRequest,\n\tExperienceReadRequest,\n\tExperienceSession,\n\tRenderPlanFragment,\n\tScopedRenderPlan,\n} from \"./contracts\";\n\nexport function createExperienceSession(\n\tplan: ScopedRenderPlan,\n\tgateway: ExperienceGatewayClient,\n): ExperienceSession {\n\tconst fragments = indexFragments(plan.root);\n\treturn {\n\t\tplan,\n\t\tasync invoke(fragmentId, eventName, parameters, idempotencyKey) {\n\t\t\tconst fragment = fragments.get(fragmentId);\n\t\t\tif (!fragment?.events?.includes(eventName)) {\n\t\t\t\tthrow new Error(`Fragment event \"${fragmentId}.${eventName}\" is not in the render plan.`);\n\t\t\t}\n\t\t\treturn gateway.invoke({\n\t\t\t\tplanId: plan.planId,\n\t\t\t\tfragmentId,\n\t\t\t\teventName,\n\t\t\t\tparameters,\n\t\t\t\t...(idempotencyKey === undefined ? {} : { idempotencyKey }),\n\t\t\t});\n\t\t},\n\t\tasync read(fragmentId, bindingName, parameters) {\n\t\t\tconst fragment = fragments.get(fragmentId);\n\t\t\tif (!fragment?.bindings?.includes(bindingName)) {\n\t\t\t\tthrow new Error(`Fragment binding \"${fragmentId}.${bindingName}\" is not in the render plan.`);\n\t\t\t}\n\t\t\treturn gateway.read({\n\t\t\t\tplanId: plan.planId,\n\t\t\t\tfragmentId,\n\t\t\t\tbindingName,\n\t\t\t\t...(parameters === undefined ? {} : { parameters }),\n\t\t\t});\n\t\t},\n\t};\n}\n\nexport interface ExperienceClientConformanceSubject {\n\tcreate(plan: ScopedRenderPlan, gateway: ExperienceGatewayClient): ExperienceSession;\n}\n\nexport interface ExperienceClientCheck {\n\tid: \"fabric.experience.client-tuple-routing.v1\" | \"fabric.experience.client-plan-denial.v1\";\n\trun(subject: ExperienceClientConformanceSubject): Promise<string[]>;\n}\n\nexport function experienceClientChecks(): readonly ExperienceClientCheck[] {\n\tconst plan: ScopedRenderPlan = {\n\t\tformatVersion: 1,\n\t\tplanId: \"conformance-plan\",\n\t\tapplication: \"conformance\",\n\t\tchannel: \"test\",\n\t\treleaseDigest: \"a\".repeat(64),\n\t\tassemblyDigest: \"b\".repeat(64),\n\t\ttreeId: \"root\",\n\t\ttokenSet: { name: \"conformance\", version: \"1.0.0\" },\n\t\texpiresAt: \"2099-01-01T00:00:00.000Z\",\n\t\troot: { id: \"root\", component: \"Action\", events: [\"press\"], bindings: [\"summary\"] },\n\t};\n\treturn [\n\t\t{\n\t\t\tid: \"fabric.experience.client-tuple-routing.v1\",\n\t\t\tasync run(subject) {\n\t\t\t\tconst calls: string[] = [];\n\t\t\t\tconst session = subject.create(plan, {\n\t\t\t\t\tasync invoke(request) { calls.push(`${request.fragmentId}.${request.eventName}`); return { status: \"accepted\" }; },\n\t\t\t\t\tasync read(request) { calls.push(`${request.fragmentId}.${request.bindingName}`); return { data: { ok: true } }; },\n\t\t\t\t});\n\t\t\t\tawait session.invoke(\"root\", \"press\", {});\n\t\t\t\tawait session.read(\"root\", \"summary\");\n\t\t\t\tif (calls.join(\",\") !== \"root.press,root.summary\") throw new Error(\"Client did not route through fragment-event and fragment-binding tuples.\");\n\t\t\t\treturn calls;\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"fabric.experience.client-plan-denial.v1\",\n\t\t\tasync run(subject) {\n\t\t\t\tlet called = false;\n\t\t\t\tconst session = subject.create(plan, {\n\t\t\t\t\tasync invoke() { called = true; return { status: \"accepted\" }; },\n\t\t\t\t\tasync read() { called = true; return { data: null }; },\n\t\t\t\t});\n\t\t\t\tlet rejected = false;\n\t\t\t\ttry { await session.invoke(\"root\", \"undeclared\", {}); } catch { rejected = true; }\n\t\t\t\tif (!rejected || called) throw new Error(\"Client forwarded an event that was absent from the scoped plan.\");\n\t\t\t\treturn [\"undeclared event rejected locally\"];\n\t\t\t},\n\t\t},\n\t];\n}\n\nexport async function runExperienceClientChecks(\n\tsubject: ExperienceClientConformanceSubject,\n\tchecks: readonly ExperienceClientCheck[] = experienceClientChecks(),\n): Promise<{ passed: boolean; checks: Array<{ id: ExperienceClientCheck[\"id\"]; status: \"passed\" | \"failed\"; evidence: string[]; error?: string }> }> {\n\tconst results: Array<{ id: ExperienceClientCheck[\"id\"]; status: \"passed\" | \"failed\"; evidence: string[]; error?: string }> = [];\n\tfor (const check of checks) {\n\t\ttry { results.push({ id: check.id, status: \"passed\", evidence: await check.run(subject) }); }\n\t\tcatch (error) { results.push({ id: check.id, status: \"failed\", evidence: [], error: error instanceof Error ? error.message : String(error) }); }\n\t}\n\treturn { passed: results.every((result) => result.status === \"passed\"), checks: results };\n}\n\nfunction indexFragments(root: RenderPlanFragment): Map<string, RenderPlanFragment> {\n\tconst fragments = new Map<string, RenderPlanFragment>();\n\tconst visit = (fragment: RenderPlanFragment): void => {\n\t\tif (fragments.has(fragment.id)) throw new Error(`Render plan repeats fragment \"${fragment.id}\".`);\n\t\tfragments.set(fragment.id, fragment);\n\t\tfor (const child of fragment.children ?? []) visit(child);\n\t};\n\tvisit(root);\n\treturn fragments;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"file":"client.cjs","names":[],"sources":["../client.ts"],"sourcesContent":["import type {\n\tExperienceGatewayClient,\n\tExperienceSession,\n\tRenderPlanFragment,\n\tScopedRenderPlan,\n} from \"./contracts\";\n\nexport type {\n\tExperienceGatewayClient,\n\tExperienceIntentRequest,\n\tExperienceReadRequest,\n\tExperienceSession,\n\tRenderPlanFragment,\n\tScopedRenderPlan,\n} from \"./contracts\";\n\nexport function createExperienceSession(\n\tplan: ScopedRenderPlan,\n\tgateway: ExperienceGatewayClient,\n): ExperienceSession {\n\tconst fragments = indexFragments(plan.root);\n\treturn {\n\t\tplan,\n\t\tasync invoke(fragmentId, eventName, parameters, idempotencyKey) {\n\t\t\tconst fragment = fragments.get(fragmentId);\n\t\t\tif (!fragment?.events?.includes(eventName)) {\n\t\t\t\tthrow new Error(`Fragment event \"${fragmentId}.${eventName}\" is not in the render plan.`);\n\t\t\t}\n\t\t\treturn gateway.invoke({\n\t\t\t\tplanId: plan.planId,\n\t\t\t\tfragmentId,\n\t\t\t\teventName,\n\t\t\t\tparameters,\n\t\t\t\t...(idempotencyKey === undefined ? {} : { idempotencyKey }),\n\t\t\t});\n\t\t},\n\t\tasync read(fragmentId, bindingName, parameters) {\n\t\t\tconst fragment = fragments.get(fragmentId);\n\t\t\tif (!fragment?.bindings?.includes(bindingName)) {\n\t\t\t\tthrow new Error(`Fragment binding \"${fragmentId}.${bindingName}\" is not in the render plan.`);\n\t\t\t}\n\t\t\treturn gateway.read({\n\t\t\t\tplanId: plan.planId,\n\t\t\t\tfragmentId,\n\t\t\t\tbindingName,\n\t\t\t\t...(parameters === undefined ? {} : { parameters }),\n\t\t\t});\n\t\t},\n\t};\n}\n\nexport interface ExperienceClientConformanceSubject {\n\tcreate(plan: ScopedRenderPlan, gateway: ExperienceGatewayClient): ExperienceSession;\n}\n\nexport interface ExperienceClientCheck {\n\tid: \"fabric.experience.client-tuple-routing.v1\" | \"fabric.experience.client-plan-denial.v1\";\n\trun(subject: ExperienceClientConformanceSubject): Promise<string[]>;\n}\n\nexport function experienceClientChecks(): readonly ExperienceClientCheck[] {\n\tconst plan: ScopedRenderPlan = {\n\t\tformatVersion: 1,\n\t\tplanId: \"conformance-plan\",\n\t\tapplication: \"conformance\",\n\t\tchannel: \"test\",\n\t\treleaseDigest: \"a\".repeat(64),\n\t\tassemblyDigest: \"b\".repeat(64),\n\t\ttreeId: \"root\",\n\t\ttokenSet: { name: \"conformance\", version: \"1.0.0\" },\n\t\texpiresAt: \"2099-01-01T00:00:00.000Z\",\n\t\troot: { id: \"root\", component: \"Action\", events: [\"press\"], bindings: [\"summary\"] },\n\t};\n\treturn [\n\t\t{\n\t\t\tid: \"fabric.experience.client-tuple-routing.v1\",\n\t\t\tasync run(subject) {\n\t\t\t\tconst calls: string[] = [];\n\t\t\t\tconst session = subject.create(plan, {\n\t\t\t\t\tasync invoke(request) { calls.push(`${request.fragmentId}.${request.eventName}`); return { status: \"accepted\" }; },\n\t\t\t\t\tasync read(request) { calls.push(`${request.fragmentId}.${request.bindingName}`); return { data: { ok: true } }; },\n\t\t\t\t});\n\t\t\t\tawait session.invoke(\"root\", \"press\", {});\n\t\t\t\tawait session.read(\"root\", \"summary\");\n\t\t\t\tif (calls.join(\",\") !== \"root.press,root.summary\") throw new Error(\"Client did not route through fragment-event and fragment-binding tuples.\");\n\t\t\t\treturn calls;\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"fabric.experience.client-plan-denial.v1\",\n\t\t\tasync run(subject) {\n\t\t\t\tlet called = false;\n\t\t\t\tconst session = subject.create(plan, {\n\t\t\t\t\tasync invoke() { called = true; return { status: \"accepted\" }; },\n\t\t\t\t\tasync read() { called = true; return { data: null }; },\n\t\t\t\t});\n\t\t\t\tlet rejected = false;\n\t\t\t\ttry { await session.invoke(\"root\", \"undeclared\", {}); } catch { rejected = true; }\n\t\t\t\tif (!rejected || called) throw new Error(\"Client forwarded an event that was absent from the scoped plan.\");\n\t\t\t\treturn [\"undeclared event rejected locally\"];\n\t\t\t},\n\t\t},\n\t];\n}\n\nexport async function runExperienceClientChecks(\n\tsubject: ExperienceClientConformanceSubject,\n\tchecks: readonly ExperienceClientCheck[] = experienceClientChecks(),\n): Promise<{ passed: boolean; checks: Array<{ id: ExperienceClientCheck[\"id\"]; status: \"passed\" | \"failed\"; evidence: string[]; error?: string }> }> {\n\tconst results: Array<{ id: ExperienceClientCheck[\"id\"]; status: \"passed\" | \"failed\"; evidence: string[]; error?: string }> = [];\n\tfor (const check of checks) {\n\t\ttry { results.push({ id: check.id, status: \"passed\", evidence: await check.run(subject) }); }\n\t\tcatch (error) { results.push({ id: check.id, status: \"failed\", evidence: [], error: error instanceof Error ? error.message : String(error) }); }\n\t}\n\treturn { passed: results.every((result) => result.status === \"passed\"), checks: results };\n}\n\nfunction indexFragments(root: RenderPlanFragment): Map<string, RenderPlanFragment> {\n\tconst fragments = new Map<string, RenderPlanFragment>();\n\tconst visit = (fragment: RenderPlanFragment): void => {\n\t\tif (fragments.has(fragment.id)) throw new Error(`Render plan repeats fragment \"${fragment.id}\".`);\n\t\tfragments.set(fragment.id, fragment);\n\t\tfor (const child of fragment.children ?? []) visit(child);\n\t};\n\tvisit(root);\n\treturn fragments;\n}\n"],"mappings":"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"}
package/dist/client.d.cts CHANGED
@@ -1,23 +1,22 @@
1
- import { ScopedRenderPlan, ExperienceGatewayClient, ExperienceSession } from './contracts.cjs';
2
- export { ExperienceIntentRequest, ExperienceReadRequest, RenderPlanFragment } from './contracts.cjs';
3
-
4
- declare function createExperienceSession(plan: ScopedRenderPlan, gateway: ExperienceGatewayClient): ExperienceSession;
5
- interface ExperienceClientConformanceSubject {
6
- create(plan: ScopedRenderPlan, gateway: ExperienceGatewayClient): ExperienceSession;
1
+ import { ExperienceGatewayClient, ExperienceIntentRequest, ExperienceReadRequest, ExperienceSession, RenderPlanFragment, ScopedRenderPlan } from "./contracts.cjs";
2
+ //#region client.d.ts
3
+ export declare function createExperienceSession(plan: ScopedRenderPlan, gateway: ExperienceGatewayClient): ExperienceSession;
4
+ export interface ExperienceClientConformanceSubject {
5
+ create(plan: ScopedRenderPlan, gateway: ExperienceGatewayClient): ExperienceSession;
7
6
  }
8
- interface ExperienceClientCheck {
9
- id: "fabric.experience.client-tuple-routing.v1" | "fabric.experience.client-plan-denial.v1";
10
- run(subject: ExperienceClientConformanceSubject): Promise<string[]>;
7
+ export interface ExperienceClientCheck {
8
+ id: "fabric.experience.client-tuple-routing.v1" | "fabric.experience.client-plan-denial.v1";
9
+ run(subject: ExperienceClientConformanceSubject): Promise<string[]>;
11
10
  }
12
- declare function experienceClientChecks(): readonly ExperienceClientCheck[];
13
- declare function runExperienceClientChecks(subject: ExperienceClientConformanceSubject, checks?: readonly ExperienceClientCheck[]): Promise<{
14
- passed: boolean;
15
- checks: Array<{
16
- id: ExperienceClientCheck["id"];
17
- status: "passed" | "failed";
18
- evidence: string[];
19
- error?: string;
20
- }>;
11
+ export declare function experienceClientChecks(): readonly ExperienceClientCheck[];
12
+ export declare function runExperienceClientChecks(subject: ExperienceClientConformanceSubject, checks?: readonly ExperienceClientCheck[]): Promise<{
13
+ passed: boolean;
14
+ checks: Array<{
15
+ id: ExperienceClientCheck["id"];
16
+ status: "passed" | "failed";
17
+ evidence: string[];
18
+ error?: string;
19
+ }>;
21
20
  }>;
22
-
23
- export { type ExperienceClientCheck, type ExperienceClientConformanceSubject, ExperienceGatewayClient, ExperienceSession, ScopedRenderPlan, createExperienceSession, experienceClientChecks, runExperienceClientChecks };
21
+ //#endregion
22
+ export type { ExperienceGatewayClient, ExperienceIntentRequest, ExperienceReadRequest, ExperienceSession, RenderPlanFragment, ScopedRenderPlan };
package/dist/client.d.ts CHANGED
@@ -1,23 +1,22 @@
1
- import { ScopedRenderPlan, ExperienceGatewayClient, ExperienceSession } from './contracts.js';
2
- export { ExperienceIntentRequest, ExperienceReadRequest, RenderPlanFragment } from './contracts.js';
3
-
4
- declare function createExperienceSession(plan: ScopedRenderPlan, gateway: ExperienceGatewayClient): ExperienceSession;
5
- interface ExperienceClientConformanceSubject {
6
- create(plan: ScopedRenderPlan, gateway: ExperienceGatewayClient): ExperienceSession;
1
+ import { ExperienceGatewayClient, ExperienceIntentRequest, ExperienceReadRequest, ExperienceSession, RenderPlanFragment, ScopedRenderPlan } from "./contracts.js";
2
+ //#region client.d.ts
3
+ export declare function createExperienceSession(plan: ScopedRenderPlan, gateway: ExperienceGatewayClient): ExperienceSession;
4
+ export interface ExperienceClientConformanceSubject {
5
+ create(plan: ScopedRenderPlan, gateway: ExperienceGatewayClient): ExperienceSession;
7
6
  }
8
- interface ExperienceClientCheck {
9
- id: "fabric.experience.client-tuple-routing.v1" | "fabric.experience.client-plan-denial.v1";
10
- run(subject: ExperienceClientConformanceSubject): Promise<string[]>;
7
+ export interface ExperienceClientCheck {
8
+ id: "fabric.experience.client-tuple-routing.v1" | "fabric.experience.client-plan-denial.v1";
9
+ run(subject: ExperienceClientConformanceSubject): Promise<string[]>;
11
10
  }
12
- declare function experienceClientChecks(): readonly ExperienceClientCheck[];
13
- declare function runExperienceClientChecks(subject: ExperienceClientConformanceSubject, checks?: readonly ExperienceClientCheck[]): Promise<{
14
- passed: boolean;
15
- checks: Array<{
16
- id: ExperienceClientCheck["id"];
17
- status: "passed" | "failed";
18
- evidence: string[];
19
- error?: string;
20
- }>;
11
+ export declare function experienceClientChecks(): readonly ExperienceClientCheck[];
12
+ export declare function runExperienceClientChecks(subject: ExperienceClientConformanceSubject, checks?: readonly ExperienceClientCheck[]): Promise<{
13
+ passed: boolean;
14
+ checks: Array<{
15
+ id: ExperienceClientCheck["id"];
16
+ status: "passed" | "failed";
17
+ evidence: string[];
18
+ error?: string;
19
+ }>;
21
20
  }>;
22
-
23
- export { type ExperienceClientCheck, type ExperienceClientConformanceSubject, ExperienceGatewayClient, ExperienceSession, ScopedRenderPlan, createExperienceSession, experienceClientChecks, runExperienceClientChecks };
21
+ //#endregion
22
+ export type { ExperienceGatewayClient, ExperienceIntentRequest, ExperienceReadRequest, ExperienceSession, RenderPlanFragment, ScopedRenderPlan };