halfcode-compiler.xnl 0.1.1 → 0.2.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/application-assembly.js +1 -1
- package/dist/{index-DuRG4TQo.d.ts → index-DKwcVwK6.d.ts} +1 -1
- package/dist/{index-Ba5Gt9iW.d.ts → index-DqYap2u_.d.ts} +15 -1
- package/dist/{index-D-cBhQVw.d.ts → index-wU-iKJnW.d.ts} +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/kind-definition.d.ts +16 -4
- package/dist/kind-definition.js +33 -1
- package/dist/resource-core.d.ts +2 -2
- package/dist/resource-core.js +1 -1
- package/dist/resource-projection.d.ts +1 -1
- package/dist/skill-capsule.d.ts +1 -1
- package/dist/skill-capsule.js +1 -1
- package/dist/{src-DEuFHizY.js → src-B36aAZZE.js} +1 -1
- package/dist/{src-Dv8bfFUo.js → src-DJr-I4Kc.js} +1 -1
- package/dist/{src-COEMEqZw.js → src-xibObw5e.js} +84 -21
- package/package.json +1 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as assertObjectOperationCatalog, c as resolveApplicationAssembly, i as assertObjectOperationCall, l as resourceRefToFqn, n as applicationAssemblyPackage, o as assertObjectOperationDefinition, r as assertExecuteObjectOperationRequest, s as loadApplicationAssembly, t as ObjectOperationContractError } from "./src-
|
|
1
|
+
import { a as assertObjectOperationCatalog, c as resolveApplicationAssembly, i as assertObjectOperationCall, l as resourceRefToFqn, n as applicationAssemblyPackage, o as assertObjectOperationDefinition, r as assertExecuteObjectOperationRequest, s as loadApplicationAssembly, t as ObjectOperationContractError } from "./src-DJr-I4Kc.js";
|
|
2
2
|
export { ObjectOperationContractError, applicationAssemblyPackage, assertExecuteObjectOperationRequest, assertObjectOperationCall, assertObjectOperationCatalog, assertObjectOperationDefinition, loadApplicationAssembly, resolveApplicationAssembly, resourceRefToFqn };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { r as ResourceDescriptor } from "./index-DqYap2u_.js";
|
|
2
2
|
//#region ../resource-projection/src/index.d.ts
|
|
3
3
|
interface ResourceRegistry {
|
|
4
4
|
readonly byKind: ReadonlyMap<string, readonly ResourceDescriptor[]>;
|
|
@@ -35,8 +35,22 @@ interface ResourceRecord extends ResourceDescriptor {
|
|
|
35
35
|
format: "xnl";
|
|
36
36
|
node: ResourceNode;
|
|
37
37
|
}
|
|
38
|
+
interface ResourceKindContract {
|
|
39
|
+
resourceKind: string;
|
|
40
|
+
sourceShapes: readonly SourceShape[];
|
|
41
|
+
currentApiVersion: string;
|
|
42
|
+
supportedApiVersions: readonly string[];
|
|
43
|
+
documentCardinality?: "one" | "many";
|
|
44
|
+
}
|
|
45
|
+
interface RegisteredKindDefinition extends ResourceKindContract {
|
|
46
|
+
resourceId: string;
|
|
47
|
+
requiredFiles: readonly string[];
|
|
48
|
+
documentCardinality: "one" | "many";
|
|
49
|
+
documentUri: string;
|
|
50
|
+
}
|
|
38
51
|
interface ResourceRegistry {
|
|
39
52
|
readonly byKind: ReadonlyMap<string, readonly ResourceRecord[]>;
|
|
53
|
+
readonly kindDefinitions: ReadonlyMap<string, RegisteredKindDefinition>;
|
|
40
54
|
}
|
|
41
55
|
interface ResourceTree {
|
|
42
56
|
manifest: ResourceRecord;
|
|
@@ -64,4 +78,4 @@ declare class ResourceValidationError extends Error {
|
|
|
64
78
|
declare function loadResourceTree(options: LoadResourceTreeOptions): Promise<ResourceTree>;
|
|
65
79
|
declare function validateResourceTree(options: LoadResourceTreeOptions): Promise<ResourceDiagnostic[]>;
|
|
66
80
|
//#endregion
|
|
67
|
-
export {
|
|
81
|
+
export { ResourceValueMap as _, ResourceIdentity as a, validateResourceTree as b, ResourceNode as c, ResourceScalar as d, ResourceTree as f, ResourceValueList as g, ResourceValue as h, ResourceDiagnostic as i, ResourceRecord as l, ResourceValidationError as m, RegisteredKindDefinition as n, ResourceKindContract as o, ResourceTreeBuildResult as p, ResourceDescriptor as r, ResourceMetadata as s, LoadResourceTreeOptions as t, ResourceRegistry as u, SourceShape as v, loadResourceTree as y };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as ApplicationAssembly } from "./index-FdimP_SL.js";
|
|
2
|
-
import { t as ResourceRegistry } from "./index-
|
|
2
|
+
import { t as ResourceRegistry } from "./index-DKwcVwK6.js";
|
|
3
3
|
//#region ../compiler-skill/src/index.d.ts
|
|
4
4
|
interface SkillDescriptor {
|
|
5
5
|
name: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { A as ObjectTargets, B as assertExecuteObjectOperationRequest, C as ObjectOperationDefinition, D as ObjectOperationTargetDeclaration, E as ObjectOperationOwnerKind, F as ResourceSource, G as resolveApplicationAssembly, H as assertObjectOperationCatalog, I as SkillCapsuleResource, K as resourceRefToFqn, L as TextMaterial, M as ResolveApplicationAssemblyOptions, N as ResolvedAssemblyPortBinding, O as ObjectTargetKindDefinition, P as ResourceInclude, R as TextResource, S as ObjectOperationContractError, T as ObjectOperationHandler, U as assertObjectOperationDefinition, V as assertObjectOperationCall, W as loadApplicationAssembly, _ as ObjectInvocationMode, a as AssemblyResource, b as ObjectOperationCatalog, c as BusinessObjectSopResource, d as ExecuteObjectOperationRequest, f as JsonObject, g as ObjectInvocation, h as LoadApplicationAssemblyOptions, i as AssemblyPortBinding, j as PageObjectResource, k as ObjectTargetRef, l as CodeBinding, m as JsonValue, n as ApplicationScope, o as AuthoringModuleDescriptor, p as JsonPrimitive, r as AssemblyPort, s as BusinessObjectResource, t as ApplicationAssembly, u as ContractedCallableResource, v as ObjectOperationBehavior, w as ObjectOperationEffect, x as ObjectOperationConfig, y as ObjectOperationCall, z as applicationAssemblyPackage } from "./index-FdimP_SL.js";
|
|
2
|
-
import { a as SkillReference, c as compilerSkillPackage, i as SkillDescriptor, n as CompileSkillCapsuleInput, o as compileResourceSkillCapsule, r as SkillCapsulePlan, s as compileSkillCapsule, t as CompileResourceSkillCapsuleInput } from "./index-
|
|
2
|
+
import { a as SkillReference, c as compilerSkillPackage, i as SkillDescriptor, n as CompileSkillCapsuleInput, o as compileResourceSkillCapsule, r as SkillCapsulePlan, s as compileSkillCapsule, t as CompileResourceSkillCapsuleInput } from "./index-wU-iKJnW.js";
|
|
3
3
|
export { type ApplicationAssembly, type ApplicationScope, type AssemblyPort, type AssemblyPortBinding, type AssemblyResource, type AuthoringModuleDescriptor, type BusinessObjectResource, type BusinessObjectSopResource, type CodeBinding, CompileResourceSkillCapsuleInput, CompileSkillCapsuleInput, type ContractedCallableResource, type ExecuteObjectOperationRequest, type JsonObject, type JsonPrimitive, type JsonValue, type LoadApplicationAssemblyOptions, type ObjectInvocation, type ObjectInvocationMode, type ObjectOperationBehavior, type ObjectOperationCall, type ObjectOperationCatalog, type ObjectOperationConfig, ObjectOperationContractError, type ObjectOperationDefinition, type ObjectOperationEffect, type ObjectOperationHandler, type ObjectOperationOwnerKind, type ObjectOperationTargetDeclaration, type ObjectTargetKindDefinition, type ObjectTargetRef, type ObjectTargets, type PageObjectResource, type ResolveApplicationAssemblyOptions, type ResolvedAssemblyPortBinding, type ResourceInclude, type ResourceSource, SkillCapsulePlan, type SkillCapsuleResource, SkillDescriptor, SkillReference, type TextMaterial, type TextResource, applicationAssemblyPackage, assertExecuteObjectOperationRequest, assertObjectOperationCall, assertObjectOperationCatalog, assertObjectOperationDefinition, compileResourceSkillCapsule, compileSkillCapsule, compilerSkillPackage, loadApplicationAssembly, resolveApplicationAssembly, resourceRefToFqn };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as assertObjectOperationCatalog, c as resolveApplicationAssembly, i as assertObjectOperationCall, l as resourceRefToFqn, n as applicationAssemblyPackage, o as assertObjectOperationDefinition, r as assertExecuteObjectOperationRequest, s as loadApplicationAssembly, t as ObjectOperationContractError } from "./src-
|
|
1
|
+
import { a as assertObjectOperationCatalog, c as resolveApplicationAssembly, i as assertObjectOperationCall, l as resourceRefToFqn, n as applicationAssemblyPackage, o as assertObjectOperationDefinition, r as assertExecuteObjectOperationRequest, s as loadApplicationAssembly, t as ObjectOperationContractError } from "./src-DJr-I4Kc.js";
|
|
2
2
|
import "./application-assembly.js";
|
|
3
|
-
import { n as compileSkillCapsule, r as compilerSkillPackage, t as compileResourceSkillCapsule } from "./src-
|
|
3
|
+
import { n as compileSkillCapsule, r as compilerSkillPackage, t as compileResourceSkillCapsule } from "./src-B36aAZZE.js";
|
|
4
4
|
export { ObjectOperationContractError, applicationAssemblyPackage, assertExecuteObjectOperationRequest, assertObjectOperationCall, assertObjectOperationCatalog, assertObjectOperationDefinition, compileResourceSkillCapsule, compileSkillCapsule, compilerSkillPackage, loadApplicationAssembly, resolveApplicationAssembly, resourceRefToFqn };
|
|
@@ -1,9 +1,21 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { o as ResourceKindContract, r as ResourceDescriptor } from "./index-DqYap2u_.js";
|
|
2
2
|
//#region ../kind-definition/src/index.d.ts
|
|
3
|
-
interface KindDefinition extends ResourceDescriptor {
|
|
3
|
+
interface KindDefinition extends ResourceDescriptor, ResourceKindContract {
|
|
4
4
|
kind: "KindDefinition";
|
|
5
|
+
}
|
|
6
|
+
interface ResourceMigrationDefinition<T> {
|
|
7
|
+
id: string;
|
|
5
8
|
resourceKind: string;
|
|
6
|
-
|
|
9
|
+
fromApiVersion: string;
|
|
10
|
+
toApiVersion: string;
|
|
11
|
+
migrate: (resource: T) => T;
|
|
12
|
+
}
|
|
13
|
+
declare class ResourceMigrationRegistry<T> {
|
|
14
|
+
private readonly definitions;
|
|
15
|
+
private readonly ids;
|
|
16
|
+
register(definition: ResourceMigrationDefinition<T>): this;
|
|
17
|
+
plan(resourceKind: string, fromApiVersion: string, toApiVersion: string): readonly ResourceMigrationDefinition<T>[];
|
|
18
|
+
migrate(resourceKind: string, fromApiVersion: string, toApiVersion: string, resource: T): T;
|
|
7
19
|
}
|
|
8
20
|
declare const kindDefinitionPackage: {
|
|
9
21
|
readonly role: "framework";
|
|
@@ -11,4 +23,4 @@ declare const kindDefinitionPackage: {
|
|
|
11
23
|
readonly owns: "resource kind validation authority";
|
|
12
24
|
};
|
|
13
25
|
//#endregion
|
|
14
|
-
export { KindDefinition, kindDefinitionPackage };
|
|
26
|
+
export { KindDefinition, ResourceMigrationDefinition, ResourceMigrationRegistry, kindDefinitionPackage };
|
package/dist/kind-definition.js
CHANGED
|
@@ -1,8 +1,40 @@
|
|
|
1
1
|
//#region ../kind-definition/src/index.ts
|
|
2
|
+
var ResourceMigrationRegistry = class {
|
|
3
|
+
definitions = [];
|
|
4
|
+
ids = /* @__PURE__ */ new Set();
|
|
5
|
+
register(definition) {
|
|
6
|
+
if (this.ids.has(definition.id)) throw new Error(`Duplicate migration id '${definition.id}'`);
|
|
7
|
+
if (!definition.id || !definition.resourceKind || !definition.fromApiVersion || !definition.toApiVersion) throw new Error("Migration definitions require id, resourceKind, fromApiVersion, and toApiVersion");
|
|
8
|
+
if (definition.fromApiVersion === definition.toApiVersion) throw new Error(`Migration '${definition.id}' must change apiVersion`);
|
|
9
|
+
this.ids.add(definition.id);
|
|
10
|
+
this.definitions.push(Object.freeze({ ...definition }));
|
|
11
|
+
return this;
|
|
12
|
+
}
|
|
13
|
+
plan(resourceKind, fromApiVersion, toApiVersion) {
|
|
14
|
+
if (fromApiVersion === toApiVersion) return [];
|
|
15
|
+
const steps = [];
|
|
16
|
+
const visited = /* @__PURE__ */ new Set();
|
|
17
|
+
let current = fromApiVersion;
|
|
18
|
+
while (current !== toApiVersion) {
|
|
19
|
+
if (visited.has(current)) throw new Error(`Migration cycle detected for Kind '${resourceKind}' at '${current}'`);
|
|
20
|
+
visited.add(current);
|
|
21
|
+
const candidates = this.definitions.filter((definition) => definition.resourceKind === resourceKind && definition.fromApiVersion === current);
|
|
22
|
+
if (candidates.length === 0) throw new Error(`No migration for Kind '${resourceKind}' from '${current}' to '${toApiVersion}'`);
|
|
23
|
+
if (candidates.length > 1) throw new Error(`Ambiguous migration for Kind '${resourceKind}' from '${current}': ${candidates.map((candidate) => candidate.id).join(", ")}`);
|
|
24
|
+
const step = candidates[0];
|
|
25
|
+
steps.push(step);
|
|
26
|
+
current = step.toApiVersion;
|
|
27
|
+
}
|
|
28
|
+
return Object.freeze(steps);
|
|
29
|
+
}
|
|
30
|
+
migrate(resourceKind, fromApiVersion, toApiVersion, resource) {
|
|
31
|
+
return this.plan(resourceKind, fromApiVersion, toApiVersion).reduce((value, step) => step.migrate(value), resource);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
2
34
|
const kindDefinitionPackage = {
|
|
3
35
|
role: "framework",
|
|
4
36
|
area: "kind-definition",
|
|
5
37
|
owns: "resource kind validation authority"
|
|
6
38
|
};
|
|
7
39
|
//#endregion
|
|
8
|
-
export { kindDefinitionPackage };
|
|
40
|
+
export { ResourceMigrationRegistry, kindDefinitionPackage };
|
package/dist/resource-core.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { _ as
|
|
2
|
-
export { LoadResourceTreeOptions, ResourceDescriptor, ResourceDiagnostic, ResourceIdentity, ResourceMetadata, ResourceNode, ResourceRecord, ResourceRegistry, ResourceScalar, ResourceTree, ResourceTreeBuildResult, ResourceValidationError, ResourceValue, ResourceValueList, ResourceValueMap, SourceShape, loadResourceTree, validateResourceTree };
|
|
1
|
+
import { _ as ResourceValueMap, a as ResourceIdentity, b as validateResourceTree, c as ResourceNode, d as ResourceScalar, f as ResourceTree, g as ResourceValueList, h as ResourceValue, i as ResourceDiagnostic, l as ResourceRecord, m as ResourceValidationError, n as RegisteredKindDefinition, o as ResourceKindContract, p as ResourceTreeBuildResult, r as ResourceDescriptor, s as ResourceMetadata, t as LoadResourceTreeOptions, u as ResourceRegistry, v as SourceShape, y as loadResourceTree } from "./index-DqYap2u_.js";
|
|
2
|
+
export { LoadResourceTreeOptions, RegisteredKindDefinition, ResourceDescriptor, ResourceDiagnostic, ResourceIdentity, ResourceKindContract, ResourceMetadata, ResourceNode, ResourceRecord, ResourceRegistry, ResourceScalar, ResourceTree, ResourceTreeBuildResult, ResourceValidationError, ResourceValue, ResourceValueList, ResourceValueMap, SourceShape, loadResourceTree, validateResourceTree };
|
package/dist/resource-core.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as loadResourceTree, r as validateResourceTree, t as ResourceValidationError } from "./src-
|
|
1
|
+
import { n as loadResourceTree, r as validateResourceTree, t as ResourceValidationError } from "./src-xibObw5e.js";
|
|
2
2
|
export { ResourceValidationError, loadResourceTree, validateResourceTree };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as resourceProjectionPackage, t as ResourceRegistry } from "./index-
|
|
1
|
+
import { n as resourceProjectionPackage, t as ResourceRegistry } from "./index-DKwcVwK6.js";
|
|
2
2
|
export { ResourceRegistry, resourceProjectionPackage };
|
package/dist/skill-capsule.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as SkillReference, c as compilerSkillPackage, i as SkillDescriptor, n as CompileSkillCapsuleInput, o as compileResourceSkillCapsule, r as SkillCapsulePlan, s as compileSkillCapsule, t as CompileResourceSkillCapsuleInput } from "./index-
|
|
1
|
+
import { a as SkillReference, c as compilerSkillPackage, i as SkillDescriptor, n as CompileSkillCapsuleInput, o as compileResourceSkillCapsule, r as SkillCapsulePlan, s as compileSkillCapsule, t as CompileResourceSkillCapsuleInput } from "./index-wU-iKJnW.js";
|
|
2
2
|
export { CompileResourceSkillCapsuleInput, CompileSkillCapsuleInput, SkillCapsulePlan, SkillDescriptor, SkillReference, compileResourceSkillCapsule, compileSkillCapsule, compilerSkillPackage };
|
package/dist/skill-capsule.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as compileSkillCapsule, r as compilerSkillPackage, t as compileResourceSkillCapsule } from "./src-
|
|
1
|
+
import { n as compileSkillCapsule, r as compilerSkillPackage, t as compileResourceSkillCapsule } from "./src-B36aAZZE.js";
|
|
2
2
|
export { compileResourceSkillCapsule, compileSkillCapsule, compilerSkillPackage };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { l as resourceRefToFqn, u as resolveObjectOperationCompilation } from "./src-
|
|
1
|
+
import { l as resourceRefToFqn, u as resolveObjectOperationCompilation } from "./src-DJr-I4Kc.js";
|
|
2
2
|
import { n as parseResourceMappings, r as planResourceMappings, t as applyResourceMappingPlan } from "./src-BlKlpg0J.js";
|
|
3
3
|
import { mkdir, rm, writeFile } from "node:fs/promises";
|
|
4
4
|
import { dirname, join } from "node:path";
|
|
@@ -3,8 +3,9 @@ import { readFile, readdir, realpath, stat } from "node:fs/promises";
|
|
|
3
3
|
import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
4
4
|
//#region ../resource-core/src/xnl-loader.ts
|
|
5
5
|
async function buildXnlResourceTree(options) {
|
|
6
|
+
const requestedRoot = resolve(options.rootDir);
|
|
6
7
|
const context = {
|
|
7
|
-
rootDir:
|
|
8
|
+
rootDir: await realpath(requestedRoot).catch(() => requestedRoot),
|
|
8
9
|
diagnostics: [],
|
|
9
10
|
kindDefinitions: /* @__PURE__ */ new Map(),
|
|
10
11
|
resources: [],
|
|
@@ -22,7 +23,10 @@ async function buildXnlResourceTree(options) {
|
|
|
22
23
|
diagnostics: [],
|
|
23
24
|
tree: {
|
|
24
25
|
manifest,
|
|
25
|
-
registry: {
|
|
26
|
+
registry: {
|
|
27
|
+
byKind,
|
|
28
|
+
kindDefinitions: context.kindDefinitions
|
|
29
|
+
},
|
|
26
30
|
diagnostics: []
|
|
27
31
|
}
|
|
28
32
|
};
|
|
@@ -88,6 +92,7 @@ async function loadCatalog(catalog, manifestDir, context) {
|
|
|
88
92
|
context.diagnostics.push(kindMismatch(record.kind, catalog.kind, record.documentUri));
|
|
89
93
|
continue;
|
|
90
94
|
}
|
|
95
|
+
validateResourceApiVersion(record, definition, context.diagnostics);
|
|
91
96
|
await validateRequiredFiles(dirname(file), record, definition, context.diagnostics);
|
|
92
97
|
validateIdentity(record, context);
|
|
93
98
|
context.resources.push(record);
|
|
@@ -95,15 +100,25 @@ async function loadCatalog(catalog, manifestDir, context) {
|
|
|
95
100
|
for (const nested of catalogs.filter((item) => item.kind !== "KindDefinition")) await loadCatalog(nested, dirname(file), context);
|
|
96
101
|
continue;
|
|
97
102
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
103
|
+
if (definition.documentCardinality === "many" && catalog.shape !== "single-file") {
|
|
104
|
+
context.diagnostics.push({
|
|
105
|
+
code: "RESOURCE_DOCUMENT_CARDINALITY_UNSUPPORTED",
|
|
106
|
+
location: catalog.location,
|
|
107
|
+
message: `Kind '${catalog.kind}' allows multiple document roots only in a single-file catalog.`
|
|
108
|
+
});
|
|
102
109
|
continue;
|
|
103
110
|
}
|
|
104
|
-
await
|
|
105
|
-
|
|
106
|
-
|
|
111
|
+
const records = await loadXnlRecords(file, catalog.shape, context, definition.documentCardinality);
|
|
112
|
+
for (const record of records) {
|
|
113
|
+
if (record.kind !== catalog.kind) {
|
|
114
|
+
context.diagnostics.push(kindMismatch(record.kind, catalog.kind, record.documentUri));
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
validateResourceApiVersion(record, definition, context.diagnostics);
|
|
118
|
+
await validateRequiredFiles(dirname(file), record, definition, context.diagnostics);
|
|
119
|
+
validateIdentity(record, context);
|
|
120
|
+
context.resources.push(record);
|
|
121
|
+
}
|
|
107
122
|
}
|
|
108
123
|
}
|
|
109
124
|
async function catalogFiles(catalog, manifestDir, context) {
|
|
@@ -130,6 +145,9 @@ async function catalogFiles(catalog, manifestDir, context) {
|
|
|
130
145
|
return entries.filter((entry) => entry.isDirectory()).sort((left, right) => left.name.localeCompare(right.name)).map((entry) => join(root, entry.name, catalog.entry));
|
|
131
146
|
}
|
|
132
147
|
async function loadXnlRecord(filePath, sourceShape, context) {
|
|
148
|
+
return (await loadXnlRecords(filePath, sourceShape, context, "one"))[0];
|
|
149
|
+
}
|
|
150
|
+
async function loadXnlRecords(filePath, sourceShape, context, documentCardinality) {
|
|
133
151
|
const documentUri = documentUriFor(context.rootDir, filePath);
|
|
134
152
|
const source = await readFile(filePath, "utf8").catch(() => void 0);
|
|
135
153
|
if (source === void 0) {
|
|
@@ -138,9 +156,9 @@ async function loadXnlRecord(filePath, sourceShape, context) {
|
|
|
138
156
|
location: documentUri,
|
|
139
157
|
message: "Resource file does not exist."
|
|
140
158
|
});
|
|
141
|
-
return;
|
|
159
|
+
return [];
|
|
142
160
|
}
|
|
143
|
-
let
|
|
161
|
+
let roots;
|
|
144
162
|
try {
|
|
145
163
|
const parsed = parseXnl(source, { textBlockStyle: true });
|
|
146
164
|
if (parsed.warnings?.length) {
|
|
@@ -149,25 +167,32 @@ async function loadXnlRecord(filePath, sourceShape, context) {
|
|
|
149
167
|
location: documentUri,
|
|
150
168
|
message: parsed.warnings.map((warning) => warning.message).join("; ")
|
|
151
169
|
});
|
|
152
|
-
return;
|
|
170
|
+
return [];
|
|
153
171
|
}
|
|
154
|
-
if (parsed.nodes.length
|
|
172
|
+
if (parsed.nodes.length === 0 || parsed.nodes.some((node) => !isDataElement(node)) || documentCardinality === "one" && parsed.nodes.length !== 1) {
|
|
155
173
|
context.diagnostics.push({
|
|
156
174
|
code: "RESOURCE_XNL_ROOT_INVALID",
|
|
157
175
|
location: documentUri,
|
|
158
|
-
message: "XNL resource documents must contain exactly one data-element root."
|
|
176
|
+
message: documentCardinality === "one" ? "XNL resource documents must contain exactly one data-element root." : "XNL resource forests must contain one or more data-element roots."
|
|
159
177
|
});
|
|
160
|
-
return;
|
|
178
|
+
return [];
|
|
161
179
|
}
|
|
162
|
-
|
|
180
|
+
roots = parsed.nodes;
|
|
163
181
|
} catch (error) {
|
|
164
182
|
context.diagnostics.push({
|
|
165
183
|
code: "RESOURCE_XNL_SYNTAX",
|
|
166
184
|
location: documentUri,
|
|
167
185
|
message: `Invalid XNL resource document: ${error instanceof Error ? error.message : String(error)}`
|
|
168
186
|
});
|
|
169
|
-
return;
|
|
187
|
+
return [];
|
|
170
188
|
}
|
|
189
|
+
return roots.flatMap((root) => {
|
|
190
|
+
const record = resourceRecordFromRoot(root, filePath, sourceShape, context);
|
|
191
|
+
return record ? [record] : [];
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
function resourceRecordFromRoot(root, filePath, sourceShape, context) {
|
|
195
|
+
const documentUri = documentUriFor(context.rootDir, filePath);
|
|
171
196
|
const node = normalizeNode(root);
|
|
172
197
|
const resourceId = node.resourceId;
|
|
173
198
|
const apiVersion = asString(node.metadata.apiVersion);
|
|
@@ -265,20 +290,55 @@ function normalizeKindDefinition(record, diagnostics) {
|
|
|
265
290
|
const resourceKind = asString(record.node.properties.resourceKind) ?? record.resourceId.split(".").at(-1);
|
|
266
291
|
const shapes = record.node.properties.sourceShapes;
|
|
267
292
|
const sourceShapes = Array.isArray(shapes) ? shapes.filter(isXnlShape) : [];
|
|
268
|
-
|
|
293
|
+
const currentApiVersion = asString(record.node.properties.currentApiVersion);
|
|
294
|
+
const versions = record.node.properties.supportedApiVersions;
|
|
295
|
+
const supportedApiVersions = Array.isArray(versions) ? versions.filter((value) => typeof value === "string" && Boolean(value.trim())) : [];
|
|
296
|
+
const cardinalityValue = asString(record.node.properties.documentCardinality) ?? "one";
|
|
297
|
+
if (!resourceKind || sourceShapes.length === 0 || !currentApiVersion || supportedApiVersions.length === 0 || !isDocumentCardinality(cardinalityValue)) {
|
|
269
298
|
diagnostics.push({
|
|
270
299
|
code: "KIND_DEFINITION_INVALID",
|
|
271
300
|
location: record.documentUri,
|
|
272
|
-
message: "KindDefinition requires resourceKind (or an id suffix) and
|
|
301
|
+
message: "KindDefinition requires resourceKind (or an id suffix), sourceShapes, currentApiVersion, and supportedApiVersions."
|
|
302
|
+
});
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
if (!supportedApiVersions.includes(currentApiVersion)) {
|
|
306
|
+
diagnostics.push({
|
|
307
|
+
code: "KIND_DEFINITION_VERSION_INVALID",
|
|
308
|
+
location: record.documentUri,
|
|
309
|
+
message: `Kind '${resourceKind}' currentApiVersion '${currentApiVersion}' must be included in supportedApiVersions.`
|
|
273
310
|
});
|
|
274
311
|
return;
|
|
275
312
|
}
|
|
313
|
+
if (cardinalityValue === "many" && sourceShapes.some((shape) => shape !== "single-file")) {
|
|
314
|
+
diagnostics.push({
|
|
315
|
+
code: "KIND_DEFINITION_CARDINALITY_INVALID",
|
|
316
|
+
location: record.documentUri,
|
|
317
|
+
message: `Kind '${resourceKind}' documentCardinality 'many' requires only the single-file source shape.`
|
|
318
|
+
});
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
const requiredFiles = ((record.node.subdomains.DescriptorContract?.subdomains.RequiredFiles)?.body ?? []).filter(isResourceNode).filter((node) => node.tag === "File").map((node) => asString(node.properties.name)).filter((value) => Boolean(value));
|
|
276
322
|
return {
|
|
323
|
+
resourceId: record.resourceId,
|
|
277
324
|
resourceKind,
|
|
278
|
-
sourceShapes,
|
|
279
|
-
requiredFiles: (
|
|
325
|
+
sourceShapes: Object.freeze([...sourceShapes]),
|
|
326
|
+
requiredFiles: Object.freeze([...requiredFiles]),
|
|
327
|
+
currentApiVersion,
|
|
328
|
+
supportedApiVersions: Object.freeze([...new Set(supportedApiVersions)]),
|
|
329
|
+
documentCardinality: cardinalityValue,
|
|
330
|
+
documentUri: record.documentUri
|
|
280
331
|
};
|
|
281
332
|
}
|
|
333
|
+
function validateResourceApiVersion(record, definition, diagnostics) {
|
|
334
|
+
if (definition.supportedApiVersions.includes(record.metadata.apiVersion)) return;
|
|
335
|
+
diagnostics.push({
|
|
336
|
+
code: "RESOURCE_API_VERSION_UNSUPPORTED",
|
|
337
|
+
location: record.documentUri,
|
|
338
|
+
message: `Kind '${record.kind}' does not support apiVersion '${record.metadata.apiVersion}'.`,
|
|
339
|
+
hint: `Current apiVersion is '${definition.currentApiVersion}'.`
|
|
340
|
+
});
|
|
341
|
+
}
|
|
282
342
|
async function validateRequiredFiles(resourceDir, record, definition, diagnostics) {
|
|
283
343
|
for (const name of definition.requiredFiles) {
|
|
284
344
|
if (!isPlainEntry(name)) {
|
|
@@ -366,6 +426,9 @@ function kindMismatch(actual, expected, location) {
|
|
|
366
426
|
function isXnlShape(value) {
|
|
367
427
|
return value === "single-file" || value === "directory" || value === "manifest";
|
|
368
428
|
}
|
|
429
|
+
function isDocumentCardinality(value) {
|
|
430
|
+
return value === "one" || value === "many";
|
|
431
|
+
}
|
|
369
432
|
function isPlainEntry(value) {
|
|
370
433
|
return Boolean(value) && !value.includes("/") && !value.includes("\\") && !value.includes("..");
|
|
371
434
|
}
|