@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 +33 -0
- package/dist/client.cjs +120 -137
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +19 -20
- package/dist/client.d.ts +19 -20
- package/dist/client.js +117 -110
- package/dist/client.js.map +1 -1
- package/dist/contracts.cjs +0 -19
- package/dist/contracts.d.cts +71 -71
- package/dist/contracts.d.ts +71 -71
- package/dist/contracts.js +1 -1
- package/dist/offline.cjs +307 -270
- package/dist/offline.cjs.map +1 -1
- package/dist/offline.d.cts +87 -88
- package/dist/offline.d.ts +87 -88
- package/dist/offline.js +305 -244
- package/dist/offline.js.map +1 -1
- package/dist/server.cjs +230 -225
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +88 -89
- package/dist/server.d.ts +88 -89
- package/dist/server.js +226 -200
- package/dist/server.js.map +1 -1
- package/package.json +8 -7
- package/dist/contracts.cjs.map +0 -1
- package/dist/contracts.js.map +0 -1
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
|
-
"
|
|
2
|
-
|
|
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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
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
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
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
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
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
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
});
|
|
124
|
+
//#endregion
|
|
125
|
+
exports.createExperienceSession = createExperienceSession;
|
|
126
|
+
exports.experienceClientChecks = experienceClientChecks;
|
|
127
|
+
exports.runExperienceClientChecks = runExperienceClientChecks;
|
|
128
|
+
|
|
146
129
|
//# sourceMappingURL=client.cjs.map
|
package/dist/client.cjs.map
CHANGED
|
@@ -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":"
|
|
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 {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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
|
-
|
|
10
|
-
|
|
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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
|
21
|
+
//#endregion
|
|
22
|
+
export type { ExperienceGatewayClient, ExperienceIntentRequest, ExperienceReadRequest, ExperienceSession, RenderPlanFragment, ScopedRenderPlan };
|
package/dist/client.d.ts
CHANGED
|
@@ -1,23 +1,22 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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
|
-
|
|
10
|
-
|
|
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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
|
21
|
+
//#endregion
|
|
22
|
+
export type { ExperienceGatewayClient, ExperienceIntentRequest, ExperienceReadRequest, ExperienceSession, RenderPlanFragment, ScopedRenderPlan };
|