halfcode-compiler.xnl 0.2.8 → 0.2.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/dist/authoring-runtime.d.ts +163 -1
- package/dist/authoring-runtime.js +2 -2
- package/dist/effective-content-identities-CSVFi-N5.d.ts +14 -0
- package/dist/effective-content-identities-DV5fTr5Q.js +118 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/resource-core-C0Fj-VJA.d.ts +29 -0
- package/dist/resource-core.d.ts +2 -1
- package/dist/resource-core.js +17 -132
- package/dist/src-3MZLm339.js +588 -0
- package/dist/testing.js +1 -1
- package/package.json +6 -2
- package/dist/resource-core-C8IonwKw.d.ts +0 -41
- package/dist/src-B87eJQat.js +0 -39
|
@@ -1,2 +1,164 @@
|
|
|
1
|
+
import { I as EffectiveResourceRegistry, n as LoadedResourceTree } from "./index-CDIT65pI.js";
|
|
2
|
+
import { n as ResourceLayerContentIdentityInput } from "./effective-content-identities-CSVFi-N5.js";
|
|
1
3
|
import { a as createAuthoringBindings, c as logger, i as RuntimeEffects, l as runWithRuntime, n as AuthoringRuntime, o as currentRuntime, r as Logger, s as invokeEffect, t as AuthoringBindings, u as runtimeAuthoringPackage } from "./index-Dg0imcjf.js";
|
|
2
|
-
|
|
4
|
+
//#region ../runtime-authoring/src/resource-authoring.d.ts
|
|
5
|
+
declare const RESOURCE_AUTHORING_SCHEMA_VERSION: "halfcode.resource-authoring/v1";
|
|
6
|
+
type ResourceAuthoringOperation = "create" | "update";
|
|
7
|
+
type ResourceAuthoringSourceShape = "single-file";
|
|
8
|
+
type ResourceAuthoringDocumentUri = `vfs://@/${string}`;
|
|
9
|
+
interface ResourceAuthoringExpectedAbsent {
|
|
10
|
+
readonly state: "absent";
|
|
11
|
+
readonly registryRevision: string;
|
|
12
|
+
}
|
|
13
|
+
interface ResourceAuthoringExpectedPresent {
|
|
14
|
+
readonly state: "present";
|
|
15
|
+
readonly authorityDigest: string;
|
|
16
|
+
readonly registryRevision: string;
|
|
17
|
+
}
|
|
18
|
+
type ResourceAuthoringExpectedState = ResourceAuthoringExpectedAbsent | ResourceAuthoringExpectedPresent;
|
|
19
|
+
interface ResourceAuthoringProposal {
|
|
20
|
+
readonly schemaVersion: typeof RESOURCE_AUTHORING_SCHEMA_VERSION;
|
|
21
|
+
readonly operation: ResourceAuthoringOperation;
|
|
22
|
+
readonly catalogId: string;
|
|
23
|
+
readonly resourceId: string;
|
|
24
|
+
readonly kind: string;
|
|
25
|
+
readonly apiVersion: string;
|
|
26
|
+
readonly sourceShape: ResourceAuthoringSourceShape;
|
|
27
|
+
readonly documentUri: ResourceAuthoringDocumentUri;
|
|
28
|
+
readonly authorityText: string;
|
|
29
|
+
readonly expected: ResourceAuthoringExpectedState;
|
|
30
|
+
}
|
|
31
|
+
interface ResourceAuthoringKindDefinition {
|
|
32
|
+
readonly kind: string;
|
|
33
|
+
readonly supportedApiVersions: readonly string[];
|
|
34
|
+
readonly sourceShapes: readonly ResourceAuthoringSourceShape[];
|
|
35
|
+
readonly documentCardinality: "one" | "many";
|
|
36
|
+
}
|
|
37
|
+
interface ResourceAuthoringCatalogBinding {
|
|
38
|
+
readonly catalogId: string;
|
|
39
|
+
readonly resourceKind: string;
|
|
40
|
+
readonly sourceShape: ResourceAuthoringSourceShape;
|
|
41
|
+
readonly rootUri: ResourceAuthoringDocumentUri;
|
|
42
|
+
readonly entry?: string;
|
|
43
|
+
}
|
|
44
|
+
interface ResourceAuthoringPlanningAuthority {
|
|
45
|
+
readonly registryRevision: string;
|
|
46
|
+
readonly kindDefinitions: readonly ResourceAuthoringKindDefinition[];
|
|
47
|
+
readonly catalogs: readonly ResourceAuthoringCatalogBinding[];
|
|
48
|
+
}
|
|
49
|
+
type ResourceAuthoringPlanningConfig = Readonly<Record<never, never>>;
|
|
50
|
+
interface ResourceAuthoringInspectedRoot {
|
|
51
|
+
readonly resourceId: string;
|
|
52
|
+
readonly kind: string;
|
|
53
|
+
readonly apiVersion: string;
|
|
54
|
+
}
|
|
55
|
+
interface ResourceAuthoringAuthorityInspection {
|
|
56
|
+
readonly documentUri: ResourceAuthoringDocumentUri;
|
|
57
|
+
readonly resources: readonly ResourceAuthoringInspectedRoot[];
|
|
58
|
+
}
|
|
59
|
+
interface ResourceAuthoringAuthorityInspector {
|
|
60
|
+
inspectAuthority(input: {
|
|
61
|
+
readonly documentUri: ResourceAuthoringDocumentUri;
|
|
62
|
+
readonly sourceShape: ResourceAuthoringSourceShape;
|
|
63
|
+
readonly authorityText: string;
|
|
64
|
+
}): ResourceAuthoringAuthorityInspection;
|
|
65
|
+
}
|
|
66
|
+
interface ResourceAuthoringPlanningRuntime extends ResourceAuthoringAuthorityInspector {
|
|
67
|
+
/** Long-lived authentic registry/catalog snapshot; never supplied as per-call config. */
|
|
68
|
+
readonly planningAuthority: ResourceAuthoringPlanningAuthority;
|
|
69
|
+
}
|
|
70
|
+
interface ResourceAuthoringPlan {
|
|
71
|
+
readonly schemaVersion: typeof RESOURCE_AUTHORING_SCHEMA_VERSION;
|
|
72
|
+
readonly proposal: ResourceAuthoringProposal;
|
|
73
|
+
readonly kindDefinition: ResourceAuthoringKindDefinition;
|
|
74
|
+
readonly catalog: ResourceAuthoringCatalogBinding;
|
|
75
|
+
readonly resources: readonly ResourceAuthoringInspectedRoot[];
|
|
76
|
+
readonly authorityDigest: string;
|
|
77
|
+
readonly planDigest: string;
|
|
78
|
+
}
|
|
79
|
+
interface ResourceAuthoringPreparedWrite {
|
|
80
|
+
readonly transactionId: string;
|
|
81
|
+
readonly planDigest: string;
|
|
82
|
+
readonly authorityDigestBefore: string | null;
|
|
83
|
+
readonly registryRevisionBefore: string;
|
|
84
|
+
}
|
|
85
|
+
interface ResourceAuthoringRefreshCandidate {
|
|
86
|
+
readonly transactionId: string;
|
|
87
|
+
readonly candidateId: string;
|
|
88
|
+
readonly targetLayerId: string;
|
|
89
|
+
readonly tree: LoadedResourceTree;
|
|
90
|
+
readonly registry: EffectiveResourceRegistry;
|
|
91
|
+
readonly layers: readonly ResourceLayerContentIdentityInput[];
|
|
92
|
+
}
|
|
93
|
+
interface ResourceAuthoringEffectiveOriginReceipt {
|
|
94
|
+
readonly layerId: string;
|
|
95
|
+
readonly layerIndex: number;
|
|
96
|
+
readonly packageId: string;
|
|
97
|
+
readonly documentUri: string;
|
|
98
|
+
readonly logicalPath?: string;
|
|
99
|
+
}
|
|
100
|
+
interface ResourceAuthoringReceipt {
|
|
101
|
+
readonly schemaVersion: typeof RESOURCE_AUTHORING_SCHEMA_VERSION;
|
|
102
|
+
readonly planDigest: string;
|
|
103
|
+
readonly transactionId: string;
|
|
104
|
+
readonly operation: ResourceAuthoringOperation;
|
|
105
|
+
readonly catalogId: string;
|
|
106
|
+
readonly resourceId: string;
|
|
107
|
+
readonly kind: string;
|
|
108
|
+
readonly apiVersion: string;
|
|
109
|
+
readonly sourceShape: ResourceAuthoringSourceShape;
|
|
110
|
+
readonly documentUri: ResourceAuthoringDocumentUri;
|
|
111
|
+
readonly authorityDigestBefore: string | null;
|
|
112
|
+
readonly authorityDigestAfter: string;
|
|
113
|
+
readonly registryRevisionBefore: string;
|
|
114
|
+
readonly registryRevisionAfter: string;
|
|
115
|
+
readonly contentDigest: string;
|
|
116
|
+
readonly effectiveOrigin: ResourceAuthoringEffectiveOriginReceipt;
|
|
117
|
+
readonly authorityResourceIds: readonly string[];
|
|
118
|
+
/** Content address of every preceding receipt field; the transaction port persists it immutably. */
|
|
119
|
+
readonly receiptDigest: string;
|
|
120
|
+
}
|
|
121
|
+
interface ResourceAuthoringTransactionPort {
|
|
122
|
+
loadReceipt(planDigest: string): Promise<ResourceAuthoringReceipt | undefined>;
|
|
123
|
+
prepare(input: {
|
|
124
|
+
readonly planDigest: string;
|
|
125
|
+
readonly operation: ResourceAuthoringOperation;
|
|
126
|
+
readonly documentUri: ResourceAuthoringDocumentUri;
|
|
127
|
+
readonly expected: ResourceAuthoringExpectedState;
|
|
128
|
+
readonly authorityDigest: string;
|
|
129
|
+
readonly authorityText: string;
|
|
130
|
+
}): Promise<ResourceAuthoringPreparedWrite>;
|
|
131
|
+
refreshCandidate(input: {
|
|
132
|
+
readonly transactionId: string;
|
|
133
|
+
readonly planDigest: string;
|
|
134
|
+
}): Promise<ResourceAuthoringRefreshCandidate>;
|
|
135
|
+
commit(input: {
|
|
136
|
+
readonly transactionId: string;
|
|
137
|
+
readonly candidateId: string;
|
|
138
|
+
readonly receipt: ResourceAuthoringReceipt;
|
|
139
|
+
}): Promise<ResourceAuthoringReceipt>;
|
|
140
|
+
rollback(input: {
|
|
141
|
+
readonly transactionId: string;
|
|
142
|
+
readonly planDigest: string;
|
|
143
|
+
}): Promise<void>;
|
|
144
|
+
}
|
|
145
|
+
interface ResourceAuthoringRuntime extends ResourceAuthoringPlanningRuntime {
|
|
146
|
+
readonly transaction: ResourceAuthoringTransactionPort;
|
|
147
|
+
}
|
|
148
|
+
type ApplyResourceAuthoringConfig = ResourceAuthoringPlanningConfig;
|
|
149
|
+
interface ResourceAuthoringRegistryRevisionInput {
|
|
150
|
+
readonly registry: EffectiveResourceRegistry;
|
|
151
|
+
readonly layers: readonly ResourceLayerContentIdentityInput[];
|
|
152
|
+
}
|
|
153
|
+
type ResourceAuthoringErrorCode = "RESOURCE_AUTHORING_INPUT_INVALID" | "RESOURCE_AUTHORING_KIND_UNKNOWN" | "RESOURCE_AUTHORING_API_VERSION_UNSUPPORTED" | "RESOURCE_AUTHORING_SOURCE_SHAPE_UNSUPPORTED" | "RESOURCE_AUTHORING_CATALOG_UNKNOWN" | "RESOURCE_AUTHORING_CATALOG_MISMATCH" | "RESOURCE_AUTHORING_TARGET_UNSAFE" | "RESOURCE_AUTHORING_EXPECTED_STATE_INVALID" | "RESOURCE_AUTHORING_AUTHORITY_INVALID" | "RESOURCE_AUTHORING_PLAN_FORGED" | "RESOURCE_AUTHORING_CAS_CONFLICT" | "RESOURCE_AUTHORING_PREPARE_INVALID" | "RESOURCE_AUTHORING_REFRESH_INVALID" | "RESOURCE_AUTHORING_COMMIT_INVALID" | "RESOURCE_AUTHORING_ROLLBACK_FAILED";
|
|
154
|
+
declare class ResourceAuthoringError extends Error {
|
|
155
|
+
readonly code: ResourceAuthoringErrorCode;
|
|
156
|
+
readonly cause?: unknown | undefined;
|
|
157
|
+
constructor(code: ResourceAuthoringErrorCode, message: string, cause?: unknown | undefined);
|
|
158
|
+
}
|
|
159
|
+
/** Derives the content-sensitive revision used by planning and CAS from canonical projections. */
|
|
160
|
+
declare function deriveResourceAuthoringRegistryRevision(input: ResourceAuthoringRegistryRevisionInput): string;
|
|
161
|
+
declare function planResourceAuthoring(runtime: ResourceAuthoringPlanningRuntime, input: ResourceAuthoringProposal, _config: ResourceAuthoringPlanningConfig): ResourceAuthoringPlan;
|
|
162
|
+
declare function applyResourceAuthoring(runtime: ResourceAuthoringRuntime, input: ResourceAuthoringPlan, config: ApplyResourceAuthoringConfig): Promise<ResourceAuthoringReceipt>;
|
|
163
|
+
//#endregion
|
|
164
|
+
export { ApplyResourceAuthoringConfig, AuthoringBindings, AuthoringRuntime, Logger, RESOURCE_AUTHORING_SCHEMA_VERSION, ResourceAuthoringAuthorityInspection, ResourceAuthoringAuthorityInspector, ResourceAuthoringCatalogBinding, ResourceAuthoringDocumentUri, ResourceAuthoringEffectiveOriginReceipt, ResourceAuthoringError, ResourceAuthoringErrorCode, ResourceAuthoringExpectedAbsent, ResourceAuthoringExpectedPresent, ResourceAuthoringExpectedState, ResourceAuthoringInspectedRoot, ResourceAuthoringKindDefinition, ResourceAuthoringOperation, ResourceAuthoringPlan, ResourceAuthoringPlanningAuthority, ResourceAuthoringPlanningConfig, ResourceAuthoringPlanningRuntime, ResourceAuthoringPreparedWrite, ResourceAuthoringProposal, ResourceAuthoringReceipt, ResourceAuthoringRefreshCandidate, ResourceAuthoringRegistryRevisionInput, ResourceAuthoringRuntime, ResourceAuthoringSourceShape, ResourceAuthoringTransactionPort, RuntimeEffects, applyResourceAuthoring, createAuthoringBindings, currentRuntime, deriveResourceAuthoringRegistryRevision, invokeEffect, logger, planResourceAuthoring, runWithRuntime, runtimeAuthoringPackage };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as runWithRuntime, i as logger, n as currentRuntime, o as runtimeAuthoringPackage, r as invokeEffect, t as createAuthoringBindings } from "./src-
|
|
2
|
-
export { createAuthoringBindings, currentRuntime, invokeEffect, logger, runWithRuntime, runtimeAuthoringPackage };
|
|
1
|
+
import { a as runWithRuntime, c as ResourceAuthoringError, d as planResourceAuthoring, i as logger, l as applyResourceAuthoring, n as currentRuntime, o as runtimeAuthoringPackage, r as invokeEffect, s as RESOURCE_AUTHORING_SCHEMA_VERSION, t as createAuthoringBindings, u as deriveResourceAuthoringRegistryRevision } from "./src-3MZLm339.js";
|
|
2
|
+
export { RESOURCE_AUTHORING_SCHEMA_VERSION, ResourceAuthoringError, applyResourceAuthoring, createAuthoringBindings, currentRuntime, deriveResourceAuthoringRegistryRevision, invokeEffect, logger, planResourceAuthoring, runWithRuntime, runtimeAuthoringPackage };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { I as EffectiveResourceRegistry, O as ResourceDigestContribution, T as ResourceContentIdentity, n as LoadedResourceTree } from "./index-CDIT65pI.js";
|
|
2
|
+
//#region ../resource-core/src/effective-content-identities.d.ts
|
|
3
|
+
interface ResourceLayerContentIdentityInput {
|
|
4
|
+
readonly id: string;
|
|
5
|
+
readonly tree: LoadedResourceTree;
|
|
6
|
+
}
|
|
7
|
+
interface ResolveEffectiveResourceContentIdentitiesInput {
|
|
8
|
+
readonly registry: EffectiveResourceRegistry;
|
|
9
|
+
readonly layers: readonly ResourceLayerContentIdentityInput[];
|
|
10
|
+
readonly contributions?: ReadonlyMap<string, readonly ResourceDigestContribution[]>;
|
|
11
|
+
}
|
|
12
|
+
declare function resolveEffectiveResourceContentIdentities(input: ResolveEffectiveResourceContentIdentitiesInput): ReadonlyMap<string, ResourceContentIdentity>;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { ResourceLayerContentIdentityInput as n, resolveEffectiveResourceContentIdentities as r, ResolveEffectiveResourceContentIdentitiesInput as t };
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { a as isLoadedResourceTreeAuthentic, f as ResourceCompositionError, i as readonlyMap, l as effectiveRegistryLayerBindings, p as compareCodeUnits, s as createResourceContentIdentity, u as isEffectiveRegistryAuthentic } from "./src-D3qSzGFn.js";
|
|
2
|
+
//#region ../resource-core/src/effective-content-identities.ts
|
|
3
|
+
function resolveEffectiveResourceContentIdentities(input) {
|
|
4
|
+
const diagnostics = [];
|
|
5
|
+
if (!isEffectiveRegistryAuthentic(input.registry)) throw compositionError(diagnostic("RESOURCE_CONTENT_IDENTITY_REGISTRY_UNTRUSTED", "content-projector:registry", "Effective content identities require an authentic registry returned by composeLayeredResourceRegistry()."));
|
|
6
|
+
const bindings = effectiveRegistryLayerBindings(input.registry) ?? [];
|
|
7
|
+
if (input.layers.length !== input.registry.layers.length || bindings.length !== input.registry.layers.length) diagnostics.push(diagnostic("RESOURCE_CONTENT_IDENTITY_LAYER_COUNT_MISMATCH", "content-projector:layers", "Effective content identity layers must exactly match the composed registry layers."));
|
|
8
|
+
const loadedById = /* @__PURE__ */ new Map();
|
|
9
|
+
for (let index = 0; index < input.registry.layers.length; index += 1) {
|
|
10
|
+
const descriptor = input.registry.layers[index];
|
|
11
|
+
const layer = input.layers[index];
|
|
12
|
+
const binding = bindings[index];
|
|
13
|
+
if (!layer) continue;
|
|
14
|
+
if (!isLoadedResourceTreeAuthentic(layer.tree)) {
|
|
15
|
+
diagnostics.push(diagnostic("RESOURCE_CONTENT_IDENTITY_LAYER_UNTRUSTED", layerLocation(index, layer.id), `Layer '${layer.id}' must use an authentic LoadedResourceTree returned by loadResourceTree().`));
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
if (layer.id !== descriptor.id || binding?.id !== descriptor.id) {
|
|
19
|
+
diagnostics.push(diagnostic("RESOURCE_CONTENT_IDENTITY_LAYER_ID_MISMATCH", layerLocation(index, layer.id), `Layer at index ${index} must retain exact id '${descriptor.id}'.`));
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
if (descriptor.index !== index) {
|
|
23
|
+
diagnostics.push(diagnostic("RESOURCE_CONTENT_IDENTITY_LAYER_INDEX_MISMATCH", layerLocation(index, layer.id), `Layer '${layer.id}' has inconsistent registry index ${descriptor.index}.`));
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
if (layer.tree.manifest.resourceId !== descriptor.packageId) {
|
|
27
|
+
diagnostics.push(diagnostic("RESOURCE_CONTENT_IDENTITY_LAYER_PACKAGE_MISMATCH", layerLocation(index, layer.id), `Layer '${layer.id}' must retain package '${descriptor.packageId}'.`));
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
if (binding?.tree !== layer.tree) {
|
|
31
|
+
diagnostics.push(diagnostic("RESOURCE_CONTENT_IDENTITY_LAYER_BINDING_MISMATCH", layerLocation(index, layer.id), `Layer '${layer.id}' must use the exact loaded tree composed into the registry.`));
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
validateLoadedIdentityCoverage(layer.tree, layer.id, diagnostics);
|
|
35
|
+
loadedById.set(layer.id, layer.tree);
|
|
36
|
+
}
|
|
37
|
+
const effectiveEntries = [...input.registry.byId.values()].filter((entry) => entry.resource !== void 0).sort((left, right) => compareCodeUnits(left.resourceId, right.resourceId));
|
|
38
|
+
const effectiveIds = new Set(effectiveEntries.map((entry) => entry.resourceId));
|
|
39
|
+
for (const resourceId of input.contributions?.keys() ?? []) if (!effectiveIds.has(resourceId)) diagnostics.push(diagnostic("RESOURCE_DIGEST_CONTRIBUTION_OWNER_UNKNOWN", contentLocation(resourceId), `Digest contributions target unknown effective resource '${resourceId}'.`));
|
|
40
|
+
const output = [];
|
|
41
|
+
for (const entry of effectiveEntries) {
|
|
42
|
+
const tree = entry.effectiveLayerId === void 0 ? void 0 : loadedById.get(entry.effectiveLayerId);
|
|
43
|
+
if (!tree || !entry.effectiveOrigin) {
|
|
44
|
+
diagnostics.push(diagnostic("RESOURCE_CONTENT_IDENTITY_EFFECTIVE_ORIGIN_MISSING", contentLocation(entry.resourceId), `Effective resource '${entry.resourceId}' has no exact loaded layer origin.`));
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
validateEffectiveOrigin(entry, input.registry, tree, diagnostics);
|
|
48
|
+
const authorityIdentity = tree.contentIdentities.get(entry.resourceId);
|
|
49
|
+
if (!authorityIdentity) {
|
|
50
|
+
diagnostics.push(diagnostic("RESOURCE_CONTENT_IDENTITY_MISSING", contentLocation(entry.resourceId), `Effective resource '${entry.resourceId}' is missing its loader authority identity.`));
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
const identity = createResourceContentIdentity({
|
|
55
|
+
resourceId: entry.resourceId,
|
|
56
|
+
authorityDigest: authorityIdentity.authorityDigest,
|
|
57
|
+
contributions: [...authorityIdentity.contributions, ...input.contributions?.get(entry.resourceId) ?? []]
|
|
58
|
+
});
|
|
59
|
+
output.push([entry.resourceId, identity]);
|
|
60
|
+
} catch (error) {
|
|
61
|
+
if (error instanceof ResourceCompositionError) diagnostics.push(...error.diagnostics);
|
|
62
|
+
else throw error;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (diagnostics.length > 0) throw new ResourceCompositionError(stableDiagnostics(diagnostics));
|
|
66
|
+
return readonlyMap(output.sort(([left], [right]) => compareCodeUnits(left, right)));
|
|
67
|
+
}
|
|
68
|
+
function validateLoadedIdentityCoverage(tree, layerId, diagnostics) {
|
|
69
|
+
const resources = [...tree.registry.byKind.values()].flatMap((records) => [...records]).sort((left, right) => compareCodeUnits(left.resourceId, right.resourceId));
|
|
70
|
+
const resourcesById = new Map(resources.map((resource) => [resource.resourceId, resource]));
|
|
71
|
+
for (const resource of resources) {
|
|
72
|
+
const identity = tree.contentIdentities.get(resource.resourceId);
|
|
73
|
+
if (!identity) {
|
|
74
|
+
diagnostics.push(diagnostic("RESOURCE_CONTENT_IDENTITY_MISSING", layerLocation(void 0, layerId, resource.resourceId), `Loaded resource '${resource.resourceId}' has no authority identity.`));
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
const normalized = createResourceContentIdentity({
|
|
78
|
+
resourceId: identity.resourceId,
|
|
79
|
+
authorityDigest: identity.authorityDigest,
|
|
80
|
+
contributions: identity.contributions
|
|
81
|
+
});
|
|
82
|
+
if (identity.resourceId !== resource.resourceId || identity.contentDigest !== normalized.contentDigest) diagnostics.push(diagnostic("RESOURCE_CONTENT_IDENTITY_INVALID", layerLocation(void 0, layerId, resource.resourceId), `Loaded resource '${resource.resourceId}' has an inconsistent authority identity.`));
|
|
83
|
+
}
|
|
84
|
+
for (const resourceId of tree.contentIdentities.keys()) if (!resourcesById.has(resourceId)) diagnostics.push(diagnostic("RESOURCE_CONTENT_IDENTITY_EXTRA", layerLocation(void 0, layerId, resourceId), `Loaded tree contains an extra authority identity '${resourceId}'.`));
|
|
85
|
+
}
|
|
86
|
+
function validateEffectiveOrigin(entry, registry, tree, diagnostics) {
|
|
87
|
+
const origin = entry.effectiveOrigin;
|
|
88
|
+
const descriptor = registry.layers[origin.layerIndex];
|
|
89
|
+
const loadedRecord = findResource(tree, entry.resourceId);
|
|
90
|
+
if (!descriptor || descriptor.id !== origin.layerId || descriptor.packageId !== origin.packageId || tree.manifest.resourceId !== origin.packageId || !loadedRecord || loadedRecord.documentUri !== origin.documentUri || loadedRecord.logicalPath !== origin.logicalPath) diagnostics.push(diagnostic("RESOURCE_CONTENT_IDENTITY_EFFECTIVE_ORIGIN_MISMATCH", contentLocation(entry.resourceId), `Effective resource '${entry.resourceId}' does not match its exact layer/package/origin facts.`));
|
|
91
|
+
}
|
|
92
|
+
function findResource(tree, resourceId) {
|
|
93
|
+
for (const records of tree.registry.byKind.values()) {
|
|
94
|
+
const resource = records.find((record) => record.resourceId === resourceId);
|
|
95
|
+
if (resource) return resource;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
function stableDiagnostics(diagnostics) {
|
|
99
|
+
return Object.freeze([...diagnostics].sort((left, right) => compareCodeUnits(left.location, right.location) || compareCodeUnits(left.code, right.code)));
|
|
100
|
+
}
|
|
101
|
+
function compositionError(diagnosticValue) {
|
|
102
|
+
return new ResourceCompositionError(Object.freeze([diagnosticValue]));
|
|
103
|
+
}
|
|
104
|
+
function diagnostic(code, location, message) {
|
|
105
|
+
return Object.freeze({
|
|
106
|
+
code,
|
|
107
|
+
location,
|
|
108
|
+
message
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
function layerLocation(index, layerId, resourceId) {
|
|
112
|
+
return `content-layer:${index ?? "unknown"}:${layerId}${resourceId === void 0 ? "" : `:${resourceId}`}`;
|
|
113
|
+
}
|
|
114
|
+
function contentLocation(resourceId) {
|
|
115
|
+
return `content:${resourceId || "unnamed"}`;
|
|
116
|
+
}
|
|
117
|
+
//#endregion
|
|
118
|
+
export { resolveEffectiveResourceContentIdentities as t };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { A as ObjectTargets, B as applicationAssemblyPackage, C as ObjectOperationDefinition, D as ObjectOperationTargetDeclaration, E as ObjectOperationOwnerKind, F as ResourceSource, G as loadApplicationAssembly, H as assertObjectOperationCall, I as SkillCapsuleDependency, K as resolveApplicationAssembly, L as SkillCapsuleResource, M as ResolveApplicationAssemblyOptions, N as ResolvedAssemblyPortBinding, O as ObjectTargetKindDefinition, P as ResourceInclude, R as TextMaterial, S as ObjectOperationContractError, T as ObjectOperationHandler, U as assertObjectOperationCatalog, V as assertExecuteObjectOperationRequest, W as assertObjectOperationDefinition, _ 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, q as resourceRefToFqn, 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 TextResource } from "./index-Cqh9pEBa.js";
|
|
2
2
|
import { A as buildResourceDependencySnapshot, B as ResourceTombstone, C as BuildResourceDependencySnapshotInput, D as ResourceDependencySnapshot, E as ResourceDependencyEdge, F as EffectiveResourceEntry, H as composeLayeredResourceRegistry, I as EffectiveResourceRegistry, L as ResourceLayerDescriptor, M as sha256Digest, N as ComposeLayeredResourceRegistryInput, O as ResourceDigestContribution, P as EffectiveKindDefinition, R as ResourceLayerInput, S as validateResourceTree, T as ResourceContentIdentity, U as Sha256Digest, V as ResourceTombstoneOrigin, _ as ResourceValue, a as ResourceDescriptor, b as SourceShape, c as ResourceKindContract, d as ResourceRecord, f as ResourceRegistry, g as ResourceValidationError, h as ResourceTreeBuildResult, i as RegisteredKindDefinition, j as createResourceContentIdentity, k as SnapshotResource, l as ResourceMetadata, m as ResourceTree, n as LoadedResourceTree, o as ResourceDiagnostic, p as ResourceScalar, r as LoadedResourceTreeBuildResult, s as ResourceIdentity, t as LoadResourceTreeOptions, u as ResourceNode, v as ResourceValueList, w as CreateResourceContentIdentityInput, x as loadResourceTree, y as ResourceValueMap, z as ResourceOrigin } from "./index-CDIT65pI.js";
|
|
3
|
-
import { a as
|
|
3
|
+
import { a as ResourceCompositionError, i as readResourceMaterial, n as ResourceMaterial, r as ResourceMaterialError, t as ReadResourceMaterialInput } from "./resource-core-C0Fj-VJA.js";
|
|
4
|
+
import { n as ResourceLayerContentIdentityInput, r as resolveEffectiveResourceContentIdentities, t as ResolveEffectiveResourceContentIdentitiesInput } from "./effective-content-identities-CSVFi-N5.js";
|
|
4
5
|
import { S as skillCapsuleDistributionProjection, _ as applySkillCapsuleDistributionPlan, a as PlannedSkillCapsule, b as compilerSkillPackage, c as SkillCapsuleContentDigest, d as SkillCapsuleDistributionReceipt, f as SkillCapsuleIdentity, g as SkillReference, h as SkillDescriptor, i as PlanSkillCapsuleDistributionInput, l as SkillCapsuleDistributionError, m as SkillCapsuleProvenanceManifest, n as CompileResourceSkillCapsuleInput, o as PlannedSkillFile, p as SkillCapsulePlan, r as CompileSkillCapsuleInput, s as SkillCapsuleApplyStep, t as ApplySkillCapsuleDistributionOptions, u as SkillCapsuleDistributionPlan, v as compileResourceSkillCapsule, x as planSkillCapsuleDistribution, y as compileSkillCapsule } from "./index-B515mMkO.js";
|
|
5
6
|
//#region src/bundled-system-skills.d.ts
|
|
6
7
|
declare function loadHalfcodeResourceDslSystemSkillModule(): AuthoringModuleDescriptor;
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { c as sha256Digest, f as ResourceCompositionError, n as loadResourceTree, o as buildResourceDependencySnapshot, r as validateResourceTree, s as createResourceContentIdentity, t as ResourceValidationError } from "./src-D3qSzGFn.js";
|
|
2
|
+
import { t as resolveEffectiveResourceContentIdentities } from "./effective-content-identities-DV5fTr5Q.js";
|
|
2
3
|
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-3pnDAjBD.js";
|
|
3
4
|
import "./application-assembly.js";
|
|
4
|
-
import { ResourceMaterialError, composeLayeredResourceRegistry, readResourceMaterial
|
|
5
|
+
import { ResourceMaterialError, composeLayeredResourceRegistry, readResourceMaterial } from "./resource-core.js";
|
|
5
6
|
import { a as compilerSkillPackage, i as compileSkillCapsule, n as applySkillCapsuleDistributionPlan, o as planSkillCapsuleDistribution, r as compileResourceSkillCapsule, s as skillCapsuleDistributionProjection, t as SkillCapsuleDistributionError } from "./src-CaQ25rMj.js";
|
|
6
7
|
import { fileURLToPath } from "node:url";
|
|
7
8
|
//#region src/bundled-system-skills.ts
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { O as ResourceDigestContribution, n as LoadedResourceTree, o as ResourceDiagnostic } from "./index-CDIT65pI.js";
|
|
2
|
+
//#region ../resource-core/src/composition-error.d.ts
|
|
3
|
+
declare class ResourceCompositionError extends Error {
|
|
4
|
+
readonly diagnostics: readonly ResourceDiagnostic[];
|
|
5
|
+
constructor(diagnostics: readonly ResourceDiagnostic[]);
|
|
6
|
+
}
|
|
7
|
+
//#endregion
|
|
8
|
+
//#region ../resource-core/src/resource-material.d.ts
|
|
9
|
+
interface ReadResourceMaterialInput {
|
|
10
|
+
readonly tree: LoadedResourceTree;
|
|
11
|
+
readonly rootDir: string;
|
|
12
|
+
readonly resourceId: string;
|
|
13
|
+
readonly uri: string;
|
|
14
|
+
}
|
|
15
|
+
interface ResourceMaterial {
|
|
16
|
+
readonly resourceId: string;
|
|
17
|
+
readonly uri: string;
|
|
18
|
+
readonly sourceUri: string;
|
|
19
|
+
readonly digest: string;
|
|
20
|
+
readonly contribution: ResourceDigestContribution;
|
|
21
|
+
bytes(): Uint8Array;
|
|
22
|
+
}
|
|
23
|
+
declare class ResourceMaterialError extends Error {
|
|
24
|
+
readonly diagnostics: readonly ResourceDiagnostic[];
|
|
25
|
+
constructor(diagnostics: readonly ResourceDiagnostic[]);
|
|
26
|
+
}
|
|
27
|
+
declare function readResourceMaterial(input: ReadResourceMaterialInput): Promise<ResourceMaterial>;
|
|
28
|
+
//#endregion
|
|
29
|
+
export { ResourceCompositionError as a, readResourceMaterial as i, ResourceMaterial as n, ResourceMaterialError as r, ReadResourceMaterialInput as t };
|
package/dist/resource-core.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { A as buildResourceDependencySnapshot, B as ResourceTombstone, C as BuildResourceDependencySnapshotInput, D as ResourceDependencySnapshot, E as ResourceDependencyEdge, F as EffectiveResourceEntry, H as composeLayeredResourceRegistry, I as EffectiveResourceRegistry, L as ResourceLayerDescriptor, M as sha256Digest, N as ComposeLayeredResourceRegistryInput, O as ResourceDigestContribution, P as EffectiveKindDefinition, R as ResourceLayerInput, S as validateResourceTree, T as ResourceContentIdentity, U as Sha256Digest, V as ResourceTombstoneOrigin, _ as ResourceValue, a as ResourceDescriptor, b as SourceShape, c as ResourceKindContract, d as ResourceRecord, f as ResourceRegistry, g as ResourceValidationError, h as ResourceTreeBuildResult, i as RegisteredKindDefinition, j as createResourceContentIdentity, k as SnapshotResource, l as ResourceMetadata, m as ResourceTree, n as LoadedResourceTree, o as ResourceDiagnostic, p as ResourceScalar, r as LoadedResourceTreeBuildResult, s as ResourceIdentity, t as LoadResourceTreeOptions, u as ResourceNode, v as ResourceValueList, w as CreateResourceContentIdentityInput, x as loadResourceTree, y as ResourceValueMap, z as ResourceOrigin } from "./index-CDIT65pI.js";
|
|
2
|
-
import { a as
|
|
2
|
+
import { a as ResourceCompositionError, i as readResourceMaterial, n as ResourceMaterial, r as ResourceMaterialError, t as ReadResourceMaterialInput } from "./resource-core-C0Fj-VJA.js";
|
|
3
|
+
import { n as ResourceLayerContentIdentityInput, r as resolveEffectiveResourceContentIdentities, t as ResolveEffectiveResourceContentIdentitiesInput } from "./effective-content-identities-CSVFi-N5.js";
|
|
3
4
|
export { BuildResourceDependencySnapshotInput, ComposeLayeredResourceRegistryInput, CreateResourceContentIdentityInput, EffectiveKindDefinition, EffectiveResourceEntry, EffectiveResourceRegistry, LoadResourceTreeOptions, LoadedResourceTree, LoadedResourceTreeBuildResult, ReadResourceMaterialInput, RegisteredKindDefinition, ResolveEffectiveResourceContentIdentitiesInput, ResourceCompositionError, ResourceContentIdentity, ResourceDependencyEdge, ResourceDependencySnapshot, ResourceDescriptor, ResourceDiagnostic, ResourceDigestContribution, ResourceIdentity, ResourceKindContract, ResourceLayerContentIdentityInput, ResourceLayerDescriptor, ResourceLayerInput, ResourceMaterial, ResourceMaterialError, ResourceMetadata, ResourceNode, ResourceOrigin, ResourceRecord, ResourceRegistry, ResourceScalar, ResourceTombstone, ResourceTombstoneOrigin, ResourceTree, ResourceTreeBuildResult, ResourceValidationError, ResourceValue, ResourceValueList, ResourceValueMap, type Sha256Digest, SnapshotResource, SourceShape, buildResourceDependencySnapshot, composeLayeredResourceRegistry, createResourceContentIdentity, loadResourceTree, readResourceMaterial, resolveEffectiveResourceContentIdentities, sha256Digest, validateResourceTree };
|
package/dist/resource-core.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { a as isLoadedResourceTreeAuthentic, c as sha256Digest, d as markEffectiveRegistryAuthentic, f as ResourceCompositionError, i as readonlyMap,
|
|
1
|
+
import { a as isLoadedResourceTreeAuthentic, c as sha256Digest, d as markEffectiveRegistryAuthentic, f as ResourceCompositionError, i as readonlyMap, m as digestCanonical, n as loadResourceTree, o as buildResourceDependencySnapshot, p as compareCodeUnits, r as validateResourceTree, s as createResourceContentIdentity, t as ResourceValidationError } from "./src-D3qSzGFn.js";
|
|
2
|
+
import { t as resolveEffectiveResourceContentIdentities } from "./effective-content-identities-DV5fTr5Q.js";
|
|
2
3
|
import { lstat, readFile, realpath } from "node:fs/promises";
|
|
3
4
|
import { dirname, isAbsolute, relative, resolve, sep } from "node:path";
|
|
4
5
|
//#region ../resource-core/src/layered-registry.ts
|
|
@@ -12,11 +13,11 @@ function composeLayeredResourceRegistry(input) {
|
|
|
12
13
|
const layerId = layer.id.trim();
|
|
13
14
|
const packageId = layer.tree.manifest.resourceId;
|
|
14
15
|
if (layerId.length === 0) {
|
|
15
|
-
diagnostics.push(diagnostic
|
|
16
|
+
diagnostics.push(diagnostic("RESOURCE_LAYER_ID_EMPTY", layerLocation(layerIndex), "Resource layer id must be a non-empty explicit value."));
|
|
16
17
|
return;
|
|
17
18
|
}
|
|
18
19
|
if (layerIds.has(layerId)) {
|
|
19
|
-
diagnostics.push(diagnostic
|
|
20
|
+
diagnostics.push(diagnostic("RESOURCE_LAYER_ID_DUPLICATE", layerLocation(layerIndex, layerId), `Resource layer id '${layerId}' is declared more than once.`));
|
|
20
21
|
return;
|
|
21
22
|
}
|
|
22
23
|
layerIds.add(layerId);
|
|
@@ -29,7 +30,7 @@ function composeLayeredResourceRegistry(input) {
|
|
|
29
30
|
mergeResources(layer.tree, layerId, layerIndex, packageId, entries, diagnostics);
|
|
30
31
|
applyTombstones(layer, layerId, layerIndex, packageId, entries, diagnostics);
|
|
31
32
|
});
|
|
32
|
-
if (diagnostics.length > 0) throw new ResourceCompositionError(stableDiagnostics
|
|
33
|
+
if (diagnostics.length > 0) throw new ResourceCompositionError(stableDiagnostics(diagnostics));
|
|
33
34
|
const frozenEntries = [...entries.values()].sort((left, right) => compareCodeUnits(left.resourceId, right.resourceId)).map((entry) => freezeEntry(entry));
|
|
34
35
|
const byId = readonlyMap(frozenEntries.map((entry) => [entry.resourceId, entry]));
|
|
35
36
|
const byKindValues = /* @__PURE__ */ new Map();
|
|
@@ -75,7 +76,7 @@ function composeLayeredResourceRegistry(input) {
|
|
|
75
76
|
function mergeKindDefinitions(tree, layerId, layerIndex, packageId, definitions, diagnostics) {
|
|
76
77
|
for (const [kind, inputDefinition] of [...tree.registry.kindDefinitions.entries()].sort(([left], [right]) => compareCodeUnits(left, right))) {
|
|
77
78
|
if (!isCanonicalVfsDocumentUri(inputDefinition.documentUri)) {
|
|
78
|
-
diagnostics.push(diagnostic
|
|
79
|
+
diagnostics.push(diagnostic("RESOURCE_LAYER_PROVENANCE_INVALID", layerLocation(layerIndex, layerId, kind), `Resource kind '${kind}' must use canonical VFS document provenance.`));
|
|
79
80
|
continue;
|
|
80
81
|
}
|
|
81
82
|
const definition = cloneRegisteredKindDefinition(inputDefinition);
|
|
@@ -89,7 +90,7 @@ function mergeKindDefinitions(tree, layerId, layerIndex, packageId, definitions,
|
|
|
89
90
|
continue;
|
|
90
91
|
}
|
|
91
92
|
if (JSON.stringify(normalizedKindContract(current.definition)) !== JSON.stringify(normalizedKindContract(definition))) {
|
|
92
|
-
diagnostics.push(diagnostic
|
|
93
|
+
diagnostics.push(diagnostic("RESOURCE_LAYER_KIND_DEFINITION_CONFLICT", layerLocation(layerIndex, layerId, kind), `Resource kind '${kind}' has incompatible KindDefinition contracts across layers.`));
|
|
93
94
|
continue;
|
|
94
95
|
}
|
|
95
96
|
current.origins.push(origin);
|
|
@@ -100,12 +101,12 @@ function mergeResources(tree, layerId, layerIndex, packageId, entries, diagnosti
|
|
|
100
101
|
const seenInLayer = /* @__PURE__ */ new Set();
|
|
101
102
|
for (const resource of records) {
|
|
102
103
|
if (seenInLayer.has(resource.resourceId)) {
|
|
103
|
-
diagnostics.push(diagnostic
|
|
104
|
+
diagnostics.push(diagnostic("RESOURCE_LAYER_RESOURCE_DUPLICATE", layerLocation(layerIndex, layerId, resource.resourceId), `Resource '${resource.resourceId}' occurs more than once in layer '${layerId}'.`));
|
|
104
105
|
continue;
|
|
105
106
|
}
|
|
106
107
|
seenInLayer.add(resource.resourceId);
|
|
107
108
|
if (!isSafeLogicalPath(resource.logicalPath) || resource.documentUri !== `vfs://@/${resource.logicalPath}`) {
|
|
108
|
-
diagnostics.push(diagnostic
|
|
109
|
+
diagnostics.push(diagnostic("RESOURCE_LAYER_PROVENANCE_INVALID", layerLocation(layerIndex, layerId, resource.resourceId), `Resource '${resource.resourceId}' must use matching canonical VFS documentUri and safe logicalPath provenance.`));
|
|
109
110
|
continue;
|
|
110
111
|
}
|
|
111
112
|
const immutableResource = cloneResourceRecord(resource);
|
|
@@ -124,7 +125,7 @@ function mergeResources(tree, layerId, layerIndex, packageId, entries, diagnosti
|
|
|
124
125
|
continue;
|
|
125
126
|
}
|
|
126
127
|
if (current.kind !== resource.kind) {
|
|
127
|
-
diagnostics.push(diagnostic
|
|
128
|
+
diagnostics.push(diagnostic("RESOURCE_LAYER_IDENTITY_KIND_CONFLICT", layerLocation(layerIndex, layerId, resource.resourceId), `Resource '${resource.resourceId}' changes kind from '${current.kind}' to '${resource.kind}' across layers.`));
|
|
128
129
|
continue;
|
|
129
130
|
}
|
|
130
131
|
if (current.effectiveOrigin) current.shadowed.push(current.effectiveOrigin);
|
|
@@ -140,25 +141,25 @@ function applyTombstones(layer, layerId, layerIndex, packageId, entries, diagnos
|
|
|
140
141
|
for (const tombstone of tombstones) {
|
|
141
142
|
const resourceId = tombstone.resourceId.trim();
|
|
142
143
|
if (resourceId.length === 0) {
|
|
143
|
-
diagnostics.push(diagnostic
|
|
144
|
+
diagnostics.push(diagnostic("RESOURCE_LAYER_TOMBSTONE_ID_EMPTY", layerLocation(layerIndex, layerId), "Resource tombstone target must be a non-empty resource id."));
|
|
144
145
|
continue;
|
|
145
146
|
}
|
|
146
147
|
if (seen.has(resourceId)) {
|
|
147
|
-
diagnostics.push(diagnostic
|
|
148
|
+
diagnostics.push(diagnostic("RESOURCE_LAYER_TOMBSTONE_DUPLICATE", layerLocation(layerIndex, layerId, resourceId), `Resource '${resourceId}' has more than one tombstone in layer '${layerId}'.`));
|
|
148
149
|
continue;
|
|
149
150
|
}
|
|
150
151
|
seen.add(resourceId);
|
|
151
152
|
const current = entries.get(resourceId);
|
|
152
153
|
if (!current) {
|
|
153
|
-
diagnostics.push(diagnostic
|
|
154
|
+
diagnostics.push(diagnostic("RESOURCE_LAYER_TOMBSTONE_TARGET_MISSING", layerLocation(layerIndex, layerId, resourceId), `Tombstone target '${resourceId}' does not exist in a lower or current layer.`));
|
|
154
155
|
continue;
|
|
155
156
|
}
|
|
156
157
|
if (current.effectiveLayerId === layerId) {
|
|
157
|
-
diagnostics.push(diagnostic
|
|
158
|
+
diagnostics.push(diagnostic("RESOURCE_LAYER_TOMBSTONE_RESOURCE_CONFLICT", layerLocation(layerIndex, layerId, resourceId), `Resource '${resourceId}' cannot be both effective and tombstoned in layer '${layerId}'.`));
|
|
158
159
|
continue;
|
|
159
160
|
}
|
|
160
161
|
if (tombstone.expectedKind !== void 0 && tombstone.expectedKind !== current.kind) {
|
|
161
|
-
diagnostics.push(diagnostic
|
|
162
|
+
diagnostics.push(diagnostic("RESOURCE_LAYER_TOMBSTONE_KIND_MISMATCH", layerLocation(layerIndex, layerId, resourceId), `Tombstone for '${resourceId}' expects kind '${tombstone.expectedKind}', but the target kind is '${current.kind}'.`));
|
|
162
163
|
continue;
|
|
163
164
|
}
|
|
164
165
|
const origin = Object.freeze({
|
|
@@ -301,122 +302,9 @@ function compareOrigins(left, right) {
|
|
|
301
302
|
function compareTombstones(left, right) {
|
|
302
303
|
return left.layerIndex - right.layerIndex || compareCodeUnits(left.resourceId, right.resourceId);
|
|
303
304
|
}
|
|
304
|
-
function stableDiagnostics$1(diagnostics) {
|
|
305
|
-
return Object.freeze([...diagnostics].sort((left, right) => compareCodeUnits(left.location, right.location) || compareCodeUnits(left.code, right.code)));
|
|
306
|
-
}
|
|
307
|
-
function diagnostic$1(code, location, message) {
|
|
308
|
-
return Object.freeze({
|
|
309
|
-
code,
|
|
310
|
-
location,
|
|
311
|
-
message
|
|
312
|
-
});
|
|
313
|
-
}
|
|
314
|
-
function layerLocation$1(index, layerId, subject) {
|
|
315
|
-
return `layer:${index}:${layerId ?? "unnamed"}${subject === void 0 ? "" : `:${subject}`}`;
|
|
316
|
-
}
|
|
317
|
-
//#endregion
|
|
318
|
-
//#region ../resource-core/src/effective-content-identities.ts
|
|
319
|
-
function resolveEffectiveResourceContentIdentities(input) {
|
|
320
|
-
const diagnostics = [];
|
|
321
|
-
if (!isEffectiveRegistryAuthentic(input.registry)) throw compositionError(diagnostic("RESOURCE_CONTENT_IDENTITY_REGISTRY_UNTRUSTED", "content-projector:registry", "Effective content identities require an authentic registry returned by composeLayeredResourceRegistry()."));
|
|
322
|
-
const bindings = effectiveRegistryLayerBindings(input.registry) ?? [];
|
|
323
|
-
if (input.layers.length !== input.registry.layers.length || bindings.length !== input.registry.layers.length) diagnostics.push(diagnostic("RESOURCE_CONTENT_IDENTITY_LAYER_COUNT_MISMATCH", "content-projector:layers", "Effective content identity layers must exactly match the composed registry layers."));
|
|
324
|
-
const loadedById = /* @__PURE__ */ new Map();
|
|
325
|
-
for (let index = 0; index < input.registry.layers.length; index += 1) {
|
|
326
|
-
const descriptor = input.registry.layers[index];
|
|
327
|
-
const layer = input.layers[index];
|
|
328
|
-
const binding = bindings[index];
|
|
329
|
-
if (!layer) continue;
|
|
330
|
-
if (!isLoadedResourceTreeAuthentic(layer.tree)) {
|
|
331
|
-
diagnostics.push(diagnostic("RESOURCE_CONTENT_IDENTITY_LAYER_UNTRUSTED", layerLocation(index, layer.id), `Layer '${layer.id}' must use an authentic LoadedResourceTree returned by loadResourceTree().`));
|
|
332
|
-
continue;
|
|
333
|
-
}
|
|
334
|
-
if (layer.id !== descriptor.id || binding?.id !== descriptor.id) {
|
|
335
|
-
diagnostics.push(diagnostic("RESOURCE_CONTENT_IDENTITY_LAYER_ID_MISMATCH", layerLocation(index, layer.id), `Layer at index ${index} must retain exact id '${descriptor.id}'.`));
|
|
336
|
-
continue;
|
|
337
|
-
}
|
|
338
|
-
if (descriptor.index !== index) {
|
|
339
|
-
diagnostics.push(diagnostic("RESOURCE_CONTENT_IDENTITY_LAYER_INDEX_MISMATCH", layerLocation(index, layer.id), `Layer '${layer.id}' has inconsistent registry index ${descriptor.index}.`));
|
|
340
|
-
continue;
|
|
341
|
-
}
|
|
342
|
-
if (layer.tree.manifest.resourceId !== descriptor.packageId) {
|
|
343
|
-
diagnostics.push(diagnostic("RESOURCE_CONTENT_IDENTITY_LAYER_PACKAGE_MISMATCH", layerLocation(index, layer.id), `Layer '${layer.id}' must retain package '${descriptor.packageId}'.`));
|
|
344
|
-
continue;
|
|
345
|
-
}
|
|
346
|
-
if (binding?.tree !== layer.tree) {
|
|
347
|
-
diagnostics.push(diagnostic("RESOURCE_CONTENT_IDENTITY_LAYER_BINDING_MISMATCH", layerLocation(index, layer.id), `Layer '${layer.id}' must use the exact loaded tree composed into the registry.`));
|
|
348
|
-
continue;
|
|
349
|
-
}
|
|
350
|
-
validateLoadedIdentityCoverage(layer.tree, layer.id, diagnostics);
|
|
351
|
-
loadedById.set(layer.id, layer.tree);
|
|
352
|
-
}
|
|
353
|
-
const effectiveEntries = [...input.registry.byId.values()].filter((entry) => entry.resource !== void 0).sort((left, right) => compareCodeUnits(left.resourceId, right.resourceId));
|
|
354
|
-
const effectiveIds = new Set(effectiveEntries.map((entry) => entry.resourceId));
|
|
355
|
-
for (const resourceId of input.contributions?.keys() ?? []) if (!effectiveIds.has(resourceId)) diagnostics.push(diagnostic("RESOURCE_DIGEST_CONTRIBUTION_OWNER_UNKNOWN", contentLocation(resourceId), `Digest contributions target unknown effective resource '${resourceId}'.`));
|
|
356
|
-
const output = [];
|
|
357
|
-
for (const entry of effectiveEntries) {
|
|
358
|
-
const tree = entry.effectiveLayerId === void 0 ? void 0 : loadedById.get(entry.effectiveLayerId);
|
|
359
|
-
if (!tree || !entry.effectiveOrigin) {
|
|
360
|
-
diagnostics.push(diagnostic("RESOURCE_CONTENT_IDENTITY_EFFECTIVE_ORIGIN_MISSING", contentLocation(entry.resourceId), `Effective resource '${entry.resourceId}' has no exact loaded layer origin.`));
|
|
361
|
-
continue;
|
|
362
|
-
}
|
|
363
|
-
validateEffectiveOrigin(entry, input.registry, tree, diagnostics);
|
|
364
|
-
const authorityIdentity = tree.contentIdentities.get(entry.resourceId);
|
|
365
|
-
if (!authorityIdentity) {
|
|
366
|
-
diagnostics.push(diagnostic("RESOURCE_CONTENT_IDENTITY_MISSING", contentLocation(entry.resourceId), `Effective resource '${entry.resourceId}' is missing its loader authority identity.`));
|
|
367
|
-
continue;
|
|
368
|
-
}
|
|
369
|
-
try {
|
|
370
|
-
const identity = createResourceContentIdentity({
|
|
371
|
-
resourceId: entry.resourceId,
|
|
372
|
-
authorityDigest: authorityIdentity.authorityDigest,
|
|
373
|
-
contributions: [...authorityIdentity.contributions, ...input.contributions?.get(entry.resourceId) ?? []]
|
|
374
|
-
});
|
|
375
|
-
output.push([entry.resourceId, identity]);
|
|
376
|
-
} catch (error) {
|
|
377
|
-
if (error instanceof ResourceCompositionError) diagnostics.push(...error.diagnostics);
|
|
378
|
-
else throw error;
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
if (diagnostics.length > 0) throw new ResourceCompositionError(stableDiagnostics(diagnostics));
|
|
382
|
-
return readonlyMap(output.sort(([left], [right]) => compareCodeUnits(left, right)));
|
|
383
|
-
}
|
|
384
|
-
function validateLoadedIdentityCoverage(tree, layerId, diagnostics) {
|
|
385
|
-
const resources = [...tree.registry.byKind.values()].flatMap((records) => [...records]).sort((left, right) => compareCodeUnits(left.resourceId, right.resourceId));
|
|
386
|
-
const resourcesById = new Map(resources.map((resource) => [resource.resourceId, resource]));
|
|
387
|
-
for (const resource of resources) {
|
|
388
|
-
const identity = tree.contentIdentities.get(resource.resourceId);
|
|
389
|
-
if (!identity) {
|
|
390
|
-
diagnostics.push(diagnostic("RESOURCE_CONTENT_IDENTITY_MISSING", layerLocation(void 0, layerId, resource.resourceId), `Loaded resource '${resource.resourceId}' has no authority identity.`));
|
|
391
|
-
continue;
|
|
392
|
-
}
|
|
393
|
-
const normalized = createResourceContentIdentity({
|
|
394
|
-
resourceId: identity.resourceId,
|
|
395
|
-
authorityDigest: identity.authorityDigest,
|
|
396
|
-
contributions: identity.contributions
|
|
397
|
-
});
|
|
398
|
-
if (identity.resourceId !== resource.resourceId || identity.contentDigest !== normalized.contentDigest) diagnostics.push(diagnostic("RESOURCE_CONTENT_IDENTITY_INVALID", layerLocation(void 0, layerId, resource.resourceId), `Loaded resource '${resource.resourceId}' has an inconsistent authority identity.`));
|
|
399
|
-
}
|
|
400
|
-
for (const resourceId of tree.contentIdentities.keys()) if (!resourcesById.has(resourceId)) diagnostics.push(diagnostic("RESOURCE_CONTENT_IDENTITY_EXTRA", layerLocation(void 0, layerId, resourceId), `Loaded tree contains an extra authority identity '${resourceId}'.`));
|
|
401
|
-
}
|
|
402
|
-
function validateEffectiveOrigin(entry, registry, tree, diagnostics) {
|
|
403
|
-
const origin = entry.effectiveOrigin;
|
|
404
|
-
const descriptor = registry.layers[origin.layerIndex];
|
|
405
|
-
const loadedRecord = findResource$1(tree, entry.resourceId);
|
|
406
|
-
if (!descriptor || descriptor.id !== origin.layerId || descriptor.packageId !== origin.packageId || tree.manifest.resourceId !== origin.packageId || !loadedRecord || loadedRecord.documentUri !== origin.documentUri || loadedRecord.logicalPath !== origin.logicalPath) diagnostics.push(diagnostic("RESOURCE_CONTENT_IDENTITY_EFFECTIVE_ORIGIN_MISMATCH", contentLocation(entry.resourceId), `Effective resource '${entry.resourceId}' does not match its exact layer/package/origin facts.`));
|
|
407
|
-
}
|
|
408
|
-
function findResource$1(tree, resourceId) {
|
|
409
|
-
for (const records of tree.registry.byKind.values()) {
|
|
410
|
-
const resource = records.find((record) => record.resourceId === resourceId);
|
|
411
|
-
if (resource) return resource;
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
305
|
function stableDiagnostics(diagnostics) {
|
|
415
306
|
return Object.freeze([...diagnostics].sort((left, right) => compareCodeUnits(left.location, right.location) || compareCodeUnits(left.code, right.code)));
|
|
416
307
|
}
|
|
417
|
-
function compositionError(diagnosticValue) {
|
|
418
|
-
return new ResourceCompositionError(Object.freeze([diagnosticValue]));
|
|
419
|
-
}
|
|
420
308
|
function diagnostic(code, location, message) {
|
|
421
309
|
return Object.freeze({
|
|
422
310
|
code,
|
|
@@ -424,11 +312,8 @@ function diagnostic(code, location, message) {
|
|
|
424
312
|
message
|
|
425
313
|
});
|
|
426
314
|
}
|
|
427
|
-
function layerLocation(index, layerId,
|
|
428
|
-
return `
|
|
429
|
-
}
|
|
430
|
-
function contentLocation(resourceId) {
|
|
431
|
-
return `content:${resourceId || "unnamed"}`;
|
|
315
|
+
function layerLocation(index, layerId, subject) {
|
|
316
|
+
return `layer:${index}:${layerId ?? "unnamed"}${subject === void 0 ? "" : `:${subject}`}`;
|
|
432
317
|
}
|
|
433
318
|
//#endregion
|
|
434
319
|
//#region ../resource-core/src/resource-material.ts
|