halfcode-compiler.xnl 0.1.1

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.
@@ -0,0 +1,607 @@
1
+ import { n as loadResourceTree } from "./src-COEMEqZw.js";
2
+ import { readFile } from "node:fs/promises";
3
+ import { dirname, join } from "node:path";
4
+ import { parse } from "yaml";
5
+ //#region ../application-assembly/src/internal-bindings.ts
6
+ const bindingsByDefinition = /* @__PURE__ */ new WeakMap();
7
+ const compilationsByAssembly = /* @__PURE__ */ new WeakMap();
8
+ const compilationsByBusinessObjects = /* @__PURE__ */ new WeakMap();
9
+ function setObjectOperationBinding(definition, binding) {
10
+ bindingsByDefinition.set(definition, binding);
11
+ }
12
+ function requireObjectOperationBinding(definition) {
13
+ const binding = bindingsByDefinition.get(definition);
14
+ if (!binding) throw new Error(`Object operation ${definition.ref} has no internal binding`);
15
+ return binding;
16
+ }
17
+ function setObjectOperationCompilations(assembly, compilations) {
18
+ compilationsByAssembly.set(assembly, compilations);
19
+ compilationsByBusinessObjects.set(assembly.businessObjects, compilations);
20
+ }
21
+ function resolveObjectOperationCompilation(assembly, operationRef) {
22
+ const compilation = (compilationsByAssembly.get(assembly) ?? compilationsByBusinessObjects.get(assembly.businessObjects))?.get(operationRef);
23
+ if (!compilation) throw new Error(`Unknown object operation: ${operationRef}`);
24
+ return compilation;
25
+ }
26
+ //#endregion
27
+ //#region ../application-assembly/src/index.ts
28
+ var ObjectOperationContractError = class extends TypeError {
29
+ code;
30
+ path;
31
+ constructor(code, message, path) {
32
+ super(`${code}: ${message}${path ? ` at ${path}` : ""}`);
33
+ this.code = code;
34
+ this.path = path;
35
+ this.name = "ObjectOperationContractError";
36
+ }
37
+ };
38
+ function assertObjectOperationCatalog(catalog) {
39
+ const targetKinds = /* @__PURE__ */ new Map();
40
+ for (const definition of catalog.targetKinds) {
41
+ assertNonEmptyString(definition.kindFqn, "OBJECT_TARGET_KIND_INVALID", "target kind FQN", "targetKinds.kindFqn");
42
+ assertNonEmptyString(definition.ownerKindFqn, "OBJECT_OWNER_KIND_INVALID", "owner kind FQN", "targetKinds.ownerKindFqn");
43
+ if (definition.role !== "object" && definition.role !== "nested-subject") fail("OBJECT_TARGET_ROLE_INVALID", "target role must be object or nested-subject", "targetKinds.role");
44
+ if (targetKinds.has(definition.kindFqn)) fail("OBJECT_TARGET_KIND_DUPLICATE", `duplicate target kind ${definition.kindFqn}`, "targetKinds");
45
+ targetKinds.set(definition.kindFqn, definition);
46
+ }
47
+ const operationRefs = /* @__PURE__ */ new Set();
48
+ for (const definition of catalog.operations) {
49
+ assertObjectOperationDefinition(definition);
50
+ if (operationRefs.has(definition.ref)) fail("OBJECT_OPERATION_REF_DUPLICATE", `duplicate operation ref ${definition.ref}`, "operations");
51
+ operationRefs.add(definition.ref);
52
+ const ownerTarget = targetKinds.get(definition.ownerKindFqn);
53
+ if (!ownerTarget || ownerTarget.ownerKindFqn !== definition.ownerKindFqn || ownerTarget.role !== "object") fail("OBJECT_OWNER_TARGET_MISSING", `owner ${definition.ownerKindFqn} must publish itself as an object target`, "targetKinds");
54
+ if (definition.targets.kind !== "none") {
55
+ const targetKind = targetKinds.get(definition.targets.kindFqn);
56
+ if (!targetKind) fail("OBJECT_TARGET_KIND_UNPUBLISHED", `operation ${definition.ref} targets unpublished kind ${definition.targets.kindFqn}`, "operations.targets.kindFqn");
57
+ if (targetKind.ownerKindFqn !== definition.ownerKindFqn) fail("OBJECT_TARGET_OWNER_MISMATCH", `target kind ${targetKind.kindFqn} is owned by ${targetKind.ownerKindFqn}`, "operations.targets.kindFqn");
58
+ }
59
+ }
60
+ }
61
+ function assertObjectOperationDefinition(definition) {
62
+ assertNonEmptyString(definition.id, "OBJECT_OPERATION_ID_INVALID", "operation id", "operation.id");
63
+ assertNonEmptyString(definition.ownerKindFqn, "OBJECT_OWNER_KIND_INVALID", "owner kind FQN", "operation.ownerKindFqn");
64
+ const expectedRef = `${definition.ownerKindFqn}.${definition.id}`;
65
+ if (definition.ref !== expectedRef) fail("OBJECT_OPERATION_REF_INVALID", `operation ref must be ${expectedRef}`, "operation.ref");
66
+ if (definition.ownerResourceKind !== "PageObject" && definition.ownerResourceKind !== "BusinessObject") fail("OBJECT_OWNER_RESOURCE_KIND_INVALID", "owner resource kind must be PageObject or BusinessObject", "operation.ownerResourceKind");
67
+ if (definition.behavior !== "action" && definition.behavior !== "mutation") fail("OBJECT_OPERATION_BEHAVIOR_INVALID", "behavior must be action or mutation", "operation.behavior");
68
+ if (definition.effect !== "read-only" && definition.effect !== "write" && definition.effect !== "mixed") fail("OBJECT_OPERATION_EFFECT_INVALID", "effect must be read-only, write or mixed", "operation.effect");
69
+ if (definition.targets.kind !== "none" && definition.targets.kind !== "single" && definition.targets.kind !== "selection") fail("OBJECT_TARGET_CARDINALITY_INVALID", "target cardinality must be none, single or selection", "operation.targets.kind");
70
+ if (definition.targets.kind !== "none") assertNonEmptyString(definition.targets.kindFqn, "OBJECT_TARGET_KIND_INVALID", "target kind FQN", "operation.targets.kindFqn");
71
+ if (definition.invocationModes.length === 0 || new Set(definition.invocationModes).size !== definition.invocationModes.length || definition.invocationModes.some((mode) => mode !== "single" && mode !== "batch")) fail("OBJECT_INVOCATION_MODES_INVALID", "invocationModes must contain distinct single or batch modes", "operation.invocationModes");
72
+ }
73
+ function assertObjectOperationCall(call, definition, mode = "single") {
74
+ assertObjectOperationDefinition(definition);
75
+ if (!definition.invocationModes.includes(mode)) fail("OBJECT_INVOCATION_MODE_UNSUPPORTED", `operation ${definition.ref} does not support ${mode}`, "mode");
76
+ if (call.invocation.operationRef !== definition.ref) fail("OBJECT_OPERATION_REF_MISMATCH", `expected ${definition.ref}`, "invocation.operationRef");
77
+ if (call.invocation.kind !== definition.behavior) fail("OBJECT_OPERATION_BEHAVIOR_MISMATCH", `expected ${definition.behavior}`, "invocation.kind");
78
+ assertObjectTargets(call.targets, definition.targets);
79
+ if (call.invocation.kind === "action") {
80
+ if (call.invocation.input !== void 0) assertJsonValue(call.invocation.input, "invocation.input");
81
+ } else {
82
+ if (!("desired" in call.invocation)) fail("OBJECT_MUTATION_DESIRED_REQUIRED", "mutation invocation requires desired", "invocation.desired");
83
+ assertJsonValue(call.invocation.desired, "invocation.desired");
84
+ }
85
+ if (call.config !== void 0) assertJsonValue(call.config, "config", true);
86
+ }
87
+ function assertExecuteObjectOperationRequest(request, resolveDefinition) {
88
+ if (request.mode === "single") {
89
+ const definition = requiredOperationDefinition(request.call.invocation.operationRef, resolveDefinition);
90
+ assertObjectOperationCall(request.call, definition);
91
+ return;
92
+ }
93
+ if (request.config.atomicity !== "best-effort") fail("OBJECT_BATCH_ATOMICITY_UNSUPPORTED", "object operation batch only supports best-effort atomicity", "config.atomicity");
94
+ if (request.items.length === 0) fail("OBJECT_BATCH_EMPTY", "batch requires at least one item", "items");
95
+ const keys = /* @__PURE__ */ new Set();
96
+ let operationRef;
97
+ for (const [index, item] of request.items.entries()) {
98
+ assertNonEmptyString(item.key, "OBJECT_BATCH_KEY_INVALID", "batch item key", `items[${index}].key`);
99
+ if (keys.has(item.key)) fail("OBJECT_BATCH_KEY_DUPLICATE", `duplicate batch key ${item.key}`, `items[${index}].key`);
100
+ keys.add(item.key);
101
+ if (operationRef !== void 0 && item.call.invocation.operationRef !== operationRef) fail("OBJECT_BATCH_OPERATION_MISMATCH", "all batch items must use the same operation", `items[${index}].call.invocation.operationRef`);
102
+ operationRef = item.call.invocation.operationRef;
103
+ const definition = requiredOperationDefinition(operationRef, resolveDefinition);
104
+ assertObjectOperationCall(item.call, definition, "batch");
105
+ }
106
+ }
107
+ function requiredOperationDefinition(operationRef, resolveDefinition) {
108
+ const definition = resolveDefinition(operationRef);
109
+ if (!definition) fail("OBJECT_OPERATION_UNKNOWN", `unknown operation ${operationRef}`, "invocation.operationRef");
110
+ return definition;
111
+ }
112
+ function assertObjectTargets(actual, expected) {
113
+ if (actual.kind !== expected.kind) fail("OBJECT_TARGET_CARDINALITY_MISMATCH", `expected ${expected.kind}, received ${actual.kind}`, "targets.kind");
114
+ if (actual.kind === "none" || expected.kind === "none") return;
115
+ if (actual.kind === "single" && expected.kind === "single") {
116
+ assertTargetRef(actual.ref, expected.kindFqn, "targets.ref");
117
+ return;
118
+ }
119
+ if (actual.kind !== "selection" || expected.kind !== "selection") return;
120
+ if (actual.kindFqn !== expected.kindFqn) fail("OBJECT_TARGET_KIND_MISMATCH", `expected ${expected.kindFqn}, received ${actual.kindFqn}`, "targets.kindFqn");
121
+ if (actual.selector.kind === "all") return;
122
+ if (actual.selector.kind === "filter") {
123
+ assertJsonValue(actual.selector.where, "targets.selector.where", true);
124
+ return;
125
+ }
126
+ if (actual.selector.kind === "refs") {
127
+ if (actual.selector.refs.length === 0) fail("OBJECT_TARGET_REFS_EMPTY", "refs selector requires at least one ref", "targets.selector.refs");
128
+ actual.selector.refs.forEach((ref, index) => assertTargetRef(ref, expected.kindFqn, `targets.selector.refs[${index}]`));
129
+ return;
130
+ }
131
+ fail("OBJECT_TARGET_SELECTOR_UNSUPPORTED", "selector kind must be all, filter or refs", "targets.selector.kind");
132
+ }
133
+ function assertTargetRef(ref, expectedKindFqn, path) {
134
+ if (!ref || typeof ref !== "object" || ref.kindFqn !== expectedKindFqn) fail("OBJECT_TARGET_KIND_MISMATCH", `expected ${expectedKindFqn}`, `${path}.kindFqn`);
135
+ assertJsonValue(ref.key, `${path}.key`, true);
136
+ }
137
+ function assertJsonValue(value, path, requireObject = false) {
138
+ const seen = /* @__PURE__ */ new Set();
139
+ const visit = (current, currentPath) => {
140
+ if (current === null || typeof current === "string" || typeof current === "boolean") return;
141
+ if (typeof current === "number" && Number.isFinite(current)) return;
142
+ if (typeof current !== "object") fail("OBJECT_JSON_VALUE_INVALID", "value must be JSON-compatible", currentPath);
143
+ if (seen.has(current)) fail("OBJECT_JSON_VALUE_INVALID", "cyclic values are not JSON-compatible", currentPath);
144
+ seen.add(current);
145
+ if (Array.isArray(current)) current.forEach((item, index) => visit(item, `${currentPath}[${index}]`));
146
+ else {
147
+ const prototype = Object.getPrototypeOf(current);
148
+ if (prototype !== Object.prototype && prototype !== null) fail("OBJECT_JSON_VALUE_INVALID", "value must use plain JSON objects", currentPath);
149
+ for (const [key, item] of Object.entries(current)) visit(item, `${currentPath}.${key}`);
150
+ }
151
+ seen.delete(current);
152
+ };
153
+ if (requireObject && (!value || typeof value !== "object" || Array.isArray(value))) fail("OBJECT_JSON_OBJECT_REQUIRED", "value must be a JSON object", path);
154
+ visit(value, path);
155
+ }
156
+ function assertNonEmptyString(value, code, label, path) {
157
+ if (typeof value !== "string" || !value.trim()) fail(code, `${label} must be a non-empty string`, path);
158
+ }
159
+ function fail(code, message, path) {
160
+ throw new ObjectOperationContractError(code, message, path);
161
+ }
162
+ async function loadApplicationAssembly(options) {
163
+ return resolveApplicationAssembly({ modules: [{
164
+ id: "DefaultAuthoringModule",
165
+ packageName: options.packageName ?? "anonymous-authoring-module",
166
+ family: "standalone",
167
+ scope: "domain",
168
+ resourceRootDir: options.resourceRootDir,
169
+ manifestPath: options.manifestPath
170
+ }] });
171
+ }
172
+ async function resolveApplicationAssembly(options) {
173
+ if (options.modules.length === 0) throw new Error("Application assembly requires at least one authoring module");
174
+ assertUniqueModuleIds(options.modules);
175
+ const loaded = await Promise.all(options.modules.map(loadAuthoringModule));
176
+ const all = loaded.flatMap((module) => module.resources);
177
+ const internalOperationResources = loaded.flatMap((module) => module.internalOperationResources);
178
+ const byFqn = uniqueResourceMap(all);
179
+ const compilations = assertObjectOperationAssemblyClosure(all, uniqueResourceMap([...all, ...internalOperationResources]));
180
+ const portBindings = resolvePortBindings(options.modules.flatMap((module) => module.ports ?? []), options.portBindings ?? [], byFqn);
181
+ const assembly = {
182
+ rootDir: options.modules[0]?.resourceRootDir ?? "",
183
+ modules: [...options.modules],
184
+ portBindings,
185
+ functions: loaded.flatMap((module) => module.functions),
186
+ composedFunctions: loaded.flatMap((module) => module.composedFunctions),
187
+ businessObjects: loaded.flatMap((module) => module.businessObjects),
188
+ businessObjectSops: loaded.flatMap((module) => module.businessObjectSops),
189
+ applicationSops: loaded.flatMap((module) => module.applicationSops),
190
+ promptFragments: loaded.flatMap((module) => module.promptFragments),
191
+ wikiPages: loaded.flatMap((module) => module.wikiPages),
192
+ skillCapsules: loaded.flatMap((module) => module.skillCapsules),
193
+ pageObjects: loaded.flatMap((module) => module.pageObjects),
194
+ byFqn
195
+ };
196
+ setObjectOperationCompilations(assembly, compilations);
197
+ return assembly;
198
+ }
199
+ async function loadAuthoringModule(module) {
200
+ const records = [...(await loadResourceTree({
201
+ rootDir: module.resourceRootDir,
202
+ manifestPath: module.manifestPath
203
+ })).registry.byKind.values()].flat();
204
+ const functions = await Promise.all(records.filter((record) => record.kind === "Function").map((record) => readContractedCallable(module, record, "Function")));
205
+ const composedFunctions = await Promise.all(records.filter((record) => record.kind === "ComposedFunction").map((record) => readContractedCallable(module, record, "ComposedFunction")));
206
+ const businessActions = await Promise.all(records.filter((record) => record.kind === "BusinessAction").map((record) => readContractedCallable(module, record, "BusinessAction")));
207
+ const businessObjects = await Promise.all(records.filter((record) => record.kind === "BusinessObject").map((record) => readBusinessObject(module, record)));
208
+ const businessMutations = await Promise.all(records.filter((record) => record.kind === "BusinessMutation").map((record) => readBusinessMutation(module, record)));
209
+ const businessObjectSops = await Promise.all(records.filter((record) => record.kind === "BusinessObjectSOP").map((record) => readBusinessObjectSop(module, record)));
210
+ const applicationSops = await Promise.all(records.filter((record) => record.kind === "ApplicationSOP").map((record) => readTextResource(module, record, "ApplicationSOP")));
211
+ const promptFragments = await Promise.all(records.filter((record) => record.kind === "PromptFragment").map((record) => readTextResource(module, record, "PromptFragment")));
212
+ const wikiPages = await Promise.all(records.filter((record) => record.kind === "WikiPage").map((record) => readTextResource(module, record, "WikiPage")));
213
+ const skillCapsules = await Promise.all(records.filter((record) => record.kind === "SkillCapsule").map((record) => readSkillCapsule(module, record)));
214
+ const pageObjects = records.filter((record) => record.kind === "PageObject").map((record) => readPageObject(module, record));
215
+ return {
216
+ functions,
217
+ composedFunctions,
218
+ businessObjects,
219
+ businessActions,
220
+ businessMutations,
221
+ businessObjectSops,
222
+ applicationSops,
223
+ promptFragments,
224
+ wikiPages,
225
+ skillCapsules,
226
+ pageObjects,
227
+ resources: [
228
+ ...functions,
229
+ ...composedFunctions,
230
+ ...businessObjects,
231
+ ...businessObjectSops,
232
+ ...applicationSops,
233
+ ...promptFragments,
234
+ ...wikiPages,
235
+ ...skillCapsules,
236
+ ...pageObjects
237
+ ],
238
+ internalOperationResources: [...businessActions, ...businessMutations]
239
+ };
240
+ }
241
+ function readPageObject(module, record) {
242
+ const ownerKindFqn = requiredFqn(record);
243
+ const operations = requiredNode(record, "Operations");
244
+ const moduleBinding = requiredNodeCodeModuleBinding(record);
245
+ const operationDefinitions = readXnlObjectOperations(operations, "PageObject", ownerKindFqn, record, (operation) => ({
246
+ kind: "export",
247
+ codeBinding: {
248
+ ...moduleBinding,
249
+ exportName: requiredNodeProperty(operation, "export", record)
250
+ }
251
+ }));
252
+ if (operationDefinitions.length === 0) throw new Error(`${record.logicalPath} is missing Action or Mutation operation`);
253
+ return {
254
+ kind: "PageObject",
255
+ fqn: ownerKindFqn,
256
+ id: requiredRootProperty(record, "localId"),
257
+ description: requiredDescription(record),
258
+ targetKinds: readXnlObjectTargetKinds(record.node.subdomains.TargetKinds, ownerKindFqn, record),
259
+ operations: operationDefinitions,
260
+ source: sourceFor(module, record)
261
+ };
262
+ }
263
+ function readXnlObjectOperations(operations, ownerResourceKind, ownerKindFqn, record, binding) {
264
+ const result = [];
265
+ for (const operation of nodeMembers(operations).filter((node) => node.tag === "Action" || node.tag === "Mutation")) {
266
+ const id = operation.resourceId;
267
+ if (!id) throw new Error(`${record.logicalPath} ${operation.tag} is missing #id`);
268
+ const target = requiredNodeProperty(operation, "target", record);
269
+ const targetKindFqn = optionalNodeProperty(operation, "targetKindFqn");
270
+ let targets;
271
+ if (target === "none") targets = { kind: "none" };
272
+ else if (target === "single" || target === "selection") targets = {
273
+ kind: target,
274
+ kindFqn: targetKindFqn ?? ""
275
+ };
276
+ else invalidObjectOperation(record, `${operation.tag} target must be none, single or selection`);
277
+ if (target === "none" && targetKindFqn) throw new Error(`${record.logicalPath} ${operation.tag} target none must not declare targetKindFqn`);
278
+ const definition = {
279
+ ref: `${ownerKindFqn}.${id}`,
280
+ id,
281
+ ownerKindFqn,
282
+ ownerResourceKind,
283
+ behavior: operation.tag === "Action" ? "action" : "mutation",
284
+ targets,
285
+ invocationModes: requiredNodeStringList(operation, "invocationModes", record),
286
+ effect: requiredNodeProperty(operation, "effect", record)
287
+ };
288
+ try {
289
+ assertObjectOperationDefinition(definition);
290
+ } catch (error) {
291
+ throw new Error(`${record.logicalPath} has invalid ${operation.tag} '${id}': ${error.message}`);
292
+ }
293
+ setObjectOperationBinding(definition, binding(operation));
294
+ result.push(definition);
295
+ }
296
+ return result;
297
+ }
298
+ function readXnlObjectTargetKinds(value, ownerKindFqn, record) {
299
+ const result = [{
300
+ kindFqn: ownerKindFqn,
301
+ ownerKindFqn,
302
+ role: "object"
303
+ }];
304
+ if (!value) return result;
305
+ for (const targetKind of nodeMembers(value).filter((node) => node.tag === "TargetKind")) {
306
+ const role = requiredNodeProperty(targetKind, "role", record);
307
+ if (role !== "nested-subject") throw new Error(`${record.logicalPath} explicit TargetKind role must be nested-subject`);
308
+ result.push({
309
+ kindFqn: requiredNodeProperty(targetKind, "kindFqn", record),
310
+ ownerKindFqn,
311
+ role
312
+ });
313
+ }
314
+ return result;
315
+ }
316
+ function invalidObjectOperation(record, message) {
317
+ throw new Error(`${record.logicalPath} ${message}`);
318
+ }
319
+ async function readContractedCallable(module, record, kind) {
320
+ const common = {
321
+ kind,
322
+ fqn: requiredFqn(record),
323
+ description: requiredDescription(record),
324
+ instruction: await readOptionalMaterial(module, record, "Instruction"),
325
+ inputContractRef: requiredNodeRef(record, "InputContract"),
326
+ outputContractRef: requiredNodeRef(record, "OutputContract"),
327
+ codeBinding: requiredNodeCodeBinding(record),
328
+ mutationRefs: refsFromNodeContainer(record.node.subdomains.Mutations, "Mutation"),
329
+ source: sourceFor(module, record)
330
+ };
331
+ return kind === "BusinessAction" ? {
332
+ ...common,
333
+ kind,
334
+ ownerRef: requiredRootProperty(record, "ownerRef")
335
+ } : {
336
+ ...common,
337
+ kind
338
+ };
339
+ }
340
+ async function readBusinessObject(module, record) {
341
+ const ownerKindFqn = requiredFqn(record);
342
+ const operations = record.node.subdomains.Operations;
343
+ return {
344
+ kind: "BusinessObject",
345
+ fqn: ownerKindFqn,
346
+ description: requiredDescription(record),
347
+ instruction: await readOptionalMaterial(module, record, "Instruction"),
348
+ sopRefs: refsFromNodeContainer(record.node.subdomains.SOPs, "SOP"),
349
+ relatedRefs: refsFromNodeContainer(record.node.subdomains.RelatedResources, "Resource"),
350
+ targetKinds: readXnlObjectTargetKinds(record.node.subdomains.TargetKinds, ownerKindFqn, record),
351
+ operations: operations ? readXnlObjectOperations(operations, "BusinessObject", ownerKindFqn, record, (operation) => ({
352
+ kind: "resource",
353
+ resourceRef: requiredNodeProperty(operation, "resourceRef", record)
354
+ })) : [],
355
+ source: sourceFor(module, record)
356
+ };
357
+ }
358
+ async function readBusinessMutation(module, record) {
359
+ return {
360
+ kind: "BusinessMutation",
361
+ fqn: requiredFqn(record),
362
+ description: requiredDescription(record),
363
+ instruction: await readOptionalMaterial(module, record, "Instruction"),
364
+ ownerRef: requiredRootProperty(record, "ownerRef"),
365
+ codeBinding: requiredNodeCodeBinding(record),
366
+ source: sourceFor(module, record)
367
+ };
368
+ }
369
+ async function readBusinessObjectSop(module, record) {
370
+ return {
371
+ kind: "BusinessObjectSOP",
372
+ fqn: requiredFqn(record),
373
+ description: requiredDescription(record),
374
+ instruction: await readOptionalMaterial(module, record, "Instruction"),
375
+ source: sourceFor(module, record)
376
+ };
377
+ }
378
+ async function readTextResource(module, record, kind) {
379
+ return {
380
+ kind,
381
+ fqn: requiredFqn(record),
382
+ description: requiredDescription(record),
383
+ instruction: await readOptionalMaterial(module, record, "Instruction"),
384
+ source: sourceFor(module, record)
385
+ };
386
+ }
387
+ async function readSkillCapsule(module, record) {
388
+ const metadata = await readRequiredMaterial(module, record, "SkillMetadata");
389
+ const template = await readRequiredMaterial(module, record, "Template");
390
+ return {
391
+ kind: "SkillCapsule",
392
+ fqn: requiredFqn(record),
393
+ description: requiredDescription(record),
394
+ metadata: parse(metadata.content),
395
+ template,
396
+ resourceMappings: await readOptionalMaterial(module, record, "ResourceMappings"),
397
+ includes: nodeMembers(record.node.subdomains.Includes).filter((node) => node.tag === "Include").map((include) => ({
398
+ kind: requiredNodeProperty(include, "kind", record),
399
+ ref: requiredNodeProperty(include, "ref", record)
400
+ })),
401
+ source: sourceFor(module, record)
402
+ };
403
+ }
404
+ async function readOptionalMaterial(module, record, childName) {
405
+ const child = record.node.subdomains[childName];
406
+ if (!child) return void 0;
407
+ const href = optionalNodeProperty(child, "href");
408
+ if (!href) return void 0;
409
+ return readMaterial(module, record, href, optionalNodeProperty(child, "format"));
410
+ }
411
+ async function readRequiredMaterial(module, record, childName) {
412
+ const material = await readOptionalMaterial(module, record, childName);
413
+ if (!material) throw new Error(`${record.logicalPath} is missing required ${childName} material`);
414
+ return material;
415
+ }
416
+ async function readMaterial(module, record, href, format) {
417
+ const absolutePath = resolveMaterialHref(module, record, href);
418
+ return {
419
+ href,
420
+ format,
421
+ absolutePath,
422
+ content: await readFile(absolutePath, "utf8")
423
+ };
424
+ }
425
+ function requiredNodeCodeBinding(record) {
426
+ const moduleBinding = requiredNodeCodeModuleBinding(record);
427
+ const codeBinding = requiredNode(record, "CodeBinding");
428
+ return {
429
+ ...moduleBinding,
430
+ exportName: requiredNodeProperty(codeBinding, "export", record)
431
+ };
432
+ }
433
+ function requiredNodeCodeModuleBinding(record) {
434
+ const codeBinding = requiredNode(record, "CodeBinding");
435
+ const packageName = requiredNodeProperty(codeBinding, "package", record);
436
+ const module = requiredNodeProperty(codeBinding, "module", record);
437
+ return {
438
+ packageName,
439
+ module,
440
+ moduleSpecifier: module.startsWith("./") ? `${packageName}/${module.slice(2)}` : module
441
+ };
442
+ }
443
+ function refsFromNodeContainer(value, childName) {
444
+ return nodeMembers(value).filter((node) => node.tag === childName).map((node) => optionalNodeProperty(node, "ref")).filter((ref) => Boolean(ref));
445
+ }
446
+ function resolveMaterialHref(module, record, href) {
447
+ const relativePrefix = href.startsWith("vfs://./") ? "vfs://./" : void 0;
448
+ const rootPrefix = href.startsWith("vfs://@/") ? "vfs://@/" : void 0;
449
+ const prefix = relativePrefix ?? rootPrefix;
450
+ if (!prefix) throw new Error(`Unsupported material href '${href}' in ${record.logicalPath}`);
451
+ const local = href.slice(prefix.length);
452
+ if (!local || local.includes("..") || local.includes("\\") || local.startsWith("/")) throw new Error(`Unsafe material href '${href}' in ${record.logicalPath}`);
453
+ const source = sourceFor(module, record);
454
+ const base = rootPrefix ? source.resourceRootDir : source.directory;
455
+ return join(base, local);
456
+ }
457
+ function sourceFor(module, record) {
458
+ const relative = record.logicalPath.replace(/^vfs:\/\/@\//, "");
459
+ return {
460
+ logicalPath: record.logicalPath,
461
+ directory: join(module.resourceRootDir, dirname(relative)),
462
+ moduleId: module.id,
463
+ packageName: module.packageName,
464
+ resourceRootDir: module.resourceRootDir
465
+ };
466
+ }
467
+ function assertUniqueModuleIds(modules) {
468
+ const ids = /* @__PURE__ */ new Set();
469
+ for (const module of modules) {
470
+ if (!/^[A-Z][A-Za-z0-9]*$/.test(module.id)) throw new Error(`Authoring module id must be a PascalCase segment: ${module.id}`);
471
+ if (ids.has(module.id)) throw new Error(`Duplicate authoring module id: ${module.id}`);
472
+ ids.add(module.id);
473
+ }
474
+ }
475
+ function uniqueResourceMap(resources) {
476
+ const byFqn = /* @__PURE__ */ new Map();
477
+ for (const resource of resources) {
478
+ const prior = byFqn.get(resource.fqn);
479
+ if (prior) throw new Error(`Duplicate resource FQN ${resource.fqn} from ${prior.source.packageName}:${prior.source.logicalPath} and ${resource.source.packageName}:${resource.source.logicalPath}`);
480
+ byFqn.set(resource.fqn, resource);
481
+ }
482
+ return byFqn;
483
+ }
484
+ function assertObjectOperationAssemblyClosure(resources, byFqn) {
485
+ const owners = resources.filter(isObjectOperationOwner);
486
+ assertObjectOperationCatalog({
487
+ targetKinds: owners.flatMap((owner) => owner.targetKinds),
488
+ operations: owners.flatMap((owner) => owner.operations)
489
+ });
490
+ const boundResources = /* @__PURE__ */ new Set();
491
+ const compilations = /* @__PURE__ */ new Map();
492
+ for (const owner of owners) for (const definition of owner.operations) {
493
+ const binding = requireObjectOperationBinding(definition);
494
+ if (binding.kind === "export") {
495
+ compilations.set(definition.ref, { codeBinding: binding.codeBinding });
496
+ continue;
497
+ }
498
+ const resourceFqn = resourceRefToFqn(binding.resourceRef);
499
+ if (boundResources.has(resourceFqn)) throw new Error(`Object operation resource ${resourceFqn} is bound more than once`);
500
+ boundResources.add(resourceFqn);
501
+ const resource = byFqn.get(resourceFqn);
502
+ const expectedKind = definition.behavior === "action" ? "BusinessAction" : "BusinessMutation";
503
+ if (!resource) throw new Error(`Object operation ${definition.ref} binds unknown resource ${resourceFqn}`);
504
+ if (resource.kind !== expectedKind) throw new Error(`Object operation ${definition.ref} requires ${expectedKind}, received ${resource.kind}`);
505
+ const expectedOwnerRef = `resource://${definition.ownerKindFqn}`;
506
+ if (resource.ownerRef !== expectedOwnerRef) throw new Error(`Object operation ${definition.ref} binding owner does not match ${expectedOwnerRef}`);
507
+ compilations.set(definition.ref, {
508
+ codeBinding: resource.codeBinding,
509
+ ...resource.kind === "BusinessAction" ? {
510
+ inputContractRef: resource.inputContractRef,
511
+ outputContractRef: resource.outputContractRef
512
+ } : {}
513
+ });
514
+ }
515
+ return compilations;
516
+ }
517
+ function isObjectOperationOwner(resource) {
518
+ return resource.kind === "PageObject" || resource.kind === "BusinessObject";
519
+ }
520
+ function resolvePortBindings(ports, bindings, resources) {
521
+ const portsByFqn = /* @__PURE__ */ new Map();
522
+ for (const port of ports) {
523
+ if (portsByFqn.has(port.fqn)) throw new Error(`Duplicate assembly port FQN: ${port.fqn}`);
524
+ portsByFqn.set(port.fqn, port);
525
+ }
526
+ const resolved = [];
527
+ const boundPorts = /* @__PURE__ */ new Set();
528
+ for (const binding of bindings) {
529
+ if (boundPorts.has(binding.portFqn)) throw new Error(`Assembly port is bound more than once: ${binding.portFqn}`);
530
+ const port = portsByFqn.get(binding.portFqn);
531
+ if (!port) throw new Error(`Unknown assembly port: ${binding.portFqn}`);
532
+ const resourceFqn = resourceRefToFqn(binding.resourceRef);
533
+ const resource = resources.get(resourceFqn);
534
+ if (!resource) throw new Error(`Assembly port ${binding.portFqn} targets unknown resource: ${resourceFqn}`);
535
+ if (resource.kind !== port.resourceKind) throw new Error(`Assembly port ${binding.portFqn} requires ${port.resourceKind}, received ${resource.kind}`);
536
+ if (port.contractRef && isContractedCallable(resource)) {
537
+ if (![resource.inputContractRef, resource.outputContractRef].includes(port.contractRef)) throw new Error(`Assembly port ${binding.portFqn} requires contract ${port.contractRef}`);
538
+ }
539
+ boundPorts.add(binding.portFqn);
540
+ resolved.push({
541
+ ...binding,
542
+ port,
543
+ resource
544
+ });
545
+ }
546
+ for (const port of ports) if (!port.optional && !boundPorts.has(port.fqn)) throw new Error(`Required assembly port is not bound: ${port.fqn}`);
547
+ return resolved.sort((left, right) => left.portFqn.localeCompare(right.portFqn));
548
+ }
549
+ function isContractedCallable(resource) {
550
+ return resource.kind === "Function" || resource.kind === "ComposedFunction";
551
+ }
552
+ function requiredFqn(record) {
553
+ if (!record.fqn) throw new Error(`${record.logicalPath} is missing fqn`);
554
+ return record.fqn;
555
+ }
556
+ function requiredDescription(record) {
557
+ if (!record.description) throw new Error(`${record.logicalPath} ${record.kind} is missing description`);
558
+ return record.description;
559
+ }
560
+ function requiredNode(record, childName) {
561
+ const child = record.node.subdomains[childName];
562
+ if (!child) throw new Error(`${record.logicalPath} is missing ${childName}`);
563
+ return child;
564
+ }
565
+ function requiredNodeRef(record, childName) {
566
+ return requiredNodeProperty(requiredNode(record, childName), "ref", record);
567
+ }
568
+ function requiredRootProperty(record, name) {
569
+ const value = stringResourceValue(record.node.properties[name]);
570
+ if (!value) throw new Error(`${record.logicalPath} ${record.kind} is missing ${name}`);
571
+ return value;
572
+ }
573
+ function requiredNodeProperty(node, name, record) {
574
+ const value = optionalNodeProperty(node, name);
575
+ if (!value) throw new Error(`${record.logicalPath} ${node.tag} is missing ${name}`);
576
+ return value;
577
+ }
578
+ function optionalNodeProperty(node, name) {
579
+ return stringResourceValue(node.properties[name]);
580
+ }
581
+ function requiredNodeStringList(node, name, record) {
582
+ const value = node.properties[name];
583
+ if (!Array.isArray(value)) throw new Error(`${record.logicalPath} ${node.tag} is missing ${name}`);
584
+ const strings = value.map(stringResourceValue);
585
+ if (strings.some((item) => !item)) throw new Error(`${record.logicalPath} ${node.tag} ${name} must contain strings`);
586
+ return strings;
587
+ }
588
+ function nodeMembers(node) {
589
+ return (node?.body ?? []).filter(isResourceNode);
590
+ }
591
+ function isResourceNode(value) {
592
+ return typeof value === "object" && value !== null && !Array.isArray(value) && "tag" in value;
593
+ }
594
+ function stringResourceValue(value) {
595
+ return typeof value === "string" && value.trim() ? value : void 0;
596
+ }
597
+ function resourceRefToFqn(ref) {
598
+ if (!ref.startsWith("resource://")) throw new Error(`Unsupported resource reference '${ref}'`);
599
+ return ref.slice(11);
600
+ }
601
+ const applicationAssemblyPackage = {
602
+ role: "framework",
603
+ area: "application-assembly",
604
+ owns: "resource registry facts normalized for target-neutral compiler projections"
605
+ };
606
+ //#endregion
607
+ export { assertObjectOperationCatalog as a, resolveApplicationAssembly as c, assertObjectOperationCall as i, resourceRefToFqn as l, applicationAssemblyPackage as n, assertObjectOperationDefinition as o, assertExecuteObjectOperationRequest as r, loadApplicationAssembly as s, ObjectOperationContractError as t, resolveObjectOperationCompilation as u };
@@ -0,0 +1,30 @@
1
+ import { n as AuthoringRuntime } from "./index-Dg0imcjf.js";
2
+ //#region ../runtime-mock/src/index.d.ts
3
+ interface MockEffectCall {
4
+ effectFqn: string;
5
+ input: unknown;
6
+ }
7
+ interface MockLogEntry {
8
+ level: "info" | "warn" | "error";
9
+ message: string;
10
+ fields?: Readonly<Record<string, unknown>>;
11
+ }
12
+ interface MockRuntime extends AuthoringRuntime {
13
+ readonly mock: {
14
+ readonly effectCalls: MockEffectCall[];
15
+ readonly logs: MockLogEntry[];
16
+ };
17
+ }
18
+ interface MockRuntimeOptions {
19
+ context?: Readonly<Record<string, unknown>>;
20
+ handlers?: Readonly<Record<string, (input: unknown) => unknown | Promise<unknown>>>;
21
+ }
22
+ declare function createMockRuntime(options?: MockRuntimeOptions): MockRuntime;
23
+ declare function runWithMockRuntime<T>(runtime: MockRuntime, callback: () => T): T;
24
+ declare const runtimeMockPackage: {
25
+ readonly role: "framework";
26
+ readonly area: "runtime-mock";
27
+ readonly owns: "inspectable target-neutral effect harness for deterministic authoring tests";
28
+ };
29
+ //#endregion
30
+ export { MockEffectCall, MockLogEntry, MockRuntime, MockRuntimeOptions, createMockRuntime, runWithMockRuntime, runtimeMockPackage };