@contentful/experience-design-system-types 2.42.1-dev-build-f69db6bf.0 → 2.43.0-alpha.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.
Files changed (94) hide show
  1. package/README.md +15 -0
  2. package/dist/package.json +1 -1
  3. package/dist/src/agent-process-lifecycle.d.ts +26 -0
  4. package/dist/src/agent-process-lifecycle.js +171 -0
  5. package/dist/src/agent-prompt-artifact.d.ts +8 -0
  6. package/dist/src/agent-prompt-artifact.js +37 -0
  7. package/dist/src/agent-prompt-transport.d.ts +1 -0
  8. package/dist/src/agent-prompt-transport.js +4 -0
  9. package/dist/src/cdf/build.d.ts +9 -2
  10. package/dist/src/cdf/build.js +134 -17
  11. package/dist/src/cdf/finite-values.d.ts +8 -0
  12. package/dist/src/cdf/finite-values.js +21 -0
  13. package/dist/src/cdf/index.d.ts +2 -1
  14. package/dist/src/cdf/index.js +1 -0
  15. package/dist/src/cdf/property-validation.d.ts +16 -0
  16. package/dist/src/cdf/property-validation.js +211 -0
  17. package/dist/src/cdf/representation-validation.d.ts +6 -0
  18. package/dist/src/cdf/representation-validation.js +182 -0
  19. package/dist/src/cdf/schema.d.ts +778 -20
  20. package/dist/src/cdf/schema.js +362 -5
  21. package/dist/src/cdf/types.d.ts +57 -59
  22. package/dist/src/cdf/types.js +72 -15
  23. package/dist/src/cdf/validate.js +31 -1
  24. package/dist/src/cdf/vocabularies.d.ts +1 -1
  25. package/dist/src/cdf/vocabularies.js +9 -1
  26. package/dist/src/config/index.js +6 -3
  27. package/dist/src/exploration/constants.d.ts +10 -0
  28. package/dist/src/exploration/constants.js +18 -0
  29. package/dist/src/exploration/index.d.ts +3 -0
  30. package/dist/src/exploration/index.js +3 -0
  31. package/dist/src/exploration/schemas.d.ts +201 -0
  32. package/dist/src/exploration/schemas.js +126 -0
  33. package/dist/src/exploration/types.d.ts +393 -0
  34. package/dist/src/exploration/types.js +1 -0
  35. package/dist/src/handoff/index.d.ts +1 -1
  36. package/dist/src/index.d.ts +15 -1
  37. package/dist/src/index.js +12 -4
  38. package/dist/src/property-contract/analysis-representation-candidates.d.ts +19 -0
  39. package/dist/src/property-contract/analysis-representation-candidates.js +45 -0
  40. package/dist/src/property-contract/classification.d.ts +38 -0
  41. package/dist/src/property-contract/classification.js +84 -0
  42. package/dist/src/property-contract/compact-model-components.d.ts +16 -0
  43. package/dist/src/property-contract/compact-model-components.js +113 -0
  44. package/dist/src/property-contract/content-digest.d.ts +2 -0
  45. package/dist/src/property-contract/content-digest.js +69 -0
  46. package/dist/src/property-contract/decision-protocol.d.ts +45 -0
  47. package/dist/src/property-contract/decision-protocol.js +251 -0
  48. package/dist/src/property-contract/definition-import-rules.d.ts +10 -0
  49. package/dist/src/property-contract/definition-import-rules.js +105 -0
  50. package/dist/src/property-contract/definition-import.d.ts +13 -0
  51. package/dist/src/property-contract/definition-import.js +52 -0
  52. package/dist/src/property-contract/discriminated-union-source.d.ts +17 -0
  53. package/dist/src/property-contract/discriminated-union-source.js +180 -0
  54. package/dist/src/property-contract/import-prerequisites.d.ts +70 -0
  55. package/dist/src/property-contract/import-prerequisites.js +208 -0
  56. package/dist/src/property-contract/index.d.ts +18 -1
  57. package/dist/src/property-contract/index.js +18 -6
  58. package/dist/src/property-contract/logical-source-graph.d.ts +36 -0
  59. package/dist/src/property-contract/logical-source-graph.js +240 -0
  60. package/dist/src/property-contract/mapper-readiness.d.ts +6 -0
  61. package/dist/src/property-contract/mapper-readiness.js +34 -0
  62. package/dist/src/property-contract/model-exploration.d.ts +42 -0
  63. package/dist/src/property-contract/model-exploration.js +94 -0
  64. package/dist/src/property-contract/native-source-region.d.ts +5 -0
  65. package/dist/src/property-contract/native-source-region.js +125 -0
  66. package/dist/src/property-contract/null-handling.d.ts +10 -0
  67. package/dist/src/property-contract/null-handling.js +45 -0
  68. package/dist/src/property-contract/physical-property-import.d.ts +6 -0
  69. package/dist/src/property-contract/physical-property-import.js +55 -0
  70. package/dist/src/property-contract/property-decision.d.ts +14 -0
  71. package/dist/src/property-contract/property-decision.js +155 -0
  72. package/dist/src/property-contract/property-model.d.ts +197 -0
  73. package/dist/src/property-contract/property-model.js +833 -0
  74. package/dist/src/property-contract/representation-plan.d.ts +133 -0
  75. package/dist/src/property-contract/representation-plan.js +756 -0
  76. package/dist/src/property-contract/representation-proposal.d.ts +65 -0
  77. package/dist/src/property-contract/representation-proposal.js +204 -0
  78. package/dist/src/property-contract/resource-link-schema.d.ts +55 -0
  79. package/dist/src/property-contract/resource-link-schema.js +28 -0
  80. package/dist/src/property-contract/source-representation.d.ts +9 -0
  81. package/dist/src/property-contract/source-representation.js +79 -0
  82. package/dist/src/property-contract/target-definition.d.ts +17 -16
  83. package/dist/src/property-contract/target-definition.js +4 -26
  84. package/dist/src/schema-export.d.ts +30 -0
  85. package/dist/src/schema-export.js +285 -0
  86. package/dist/src/shared-source.d.ts +105 -0
  87. package/dist/src/shared-source.js +1 -0
  88. package/dist/src/source-input-association.d.ts +23 -0
  89. package/dist/src/source-input-association.js +52 -0
  90. package/dist/src/sources-api/preview/index.d.ts +37 -3
  91. package/dist/src/sources-api/preview/index.js +39 -1
  92. package/dist/src/sources-api/preview/schema.d.ts +2 -0
  93. package/dist/src/sources-api/preview/schema.js +74 -0
  94. package/package.json +1 -1
@@ -0,0 +1,52 @@
1
+ import { CDF_SCHEMA_URL } from '../cdf/schema.js';
2
+ import { validateCDF } from '../cdf/validate.js';
3
+ import { childPath, jsonEqual } from './json-value.js';
4
+ import { componentDefinitionImportIssues } from './definition-import-rules.js';
5
+ export * from './definition-import-rules.js';
6
+ /** Model slots require an exact plan owner even on an otherwise ordinary component. */
7
+ export function componentModelFamilyIssues(components) {
8
+ if (!components.some(({ entry }) => entry.$model ||
9
+ entry.$representationPlans ||
10
+ Object.values(entry.$slots ?? {}).some((slot) => slot.$modelBinding)))
11
+ return [];
12
+ if (new Set(components.map(({ key }) => key)).size !== components.length)
13
+ return [{ path: '/', message: 'Duplicate complete component identity' }];
14
+ const validation = validateCDF({
15
+ $schema: CDF_SCHEMA_URL,
16
+ ...Object.fromEntries(components.map(({ key, entry }) => [key, entry])),
17
+ });
18
+ if (!validation.valid)
19
+ return validation.errors.map(({ path, message }) => ({ path, message }));
20
+ const expectedSlots = new Map();
21
+ for (const { key, entry } of components)
22
+ for (const plan of Object.values(entry.$representationPlans ?? {})) {
23
+ if (plan.attachment)
24
+ expectedSlots.set(JSON.stringify([key, plan.attachment.slot]), plan.attachment.definition);
25
+ for (const generated of plan.models)
26
+ for (const [name, slot] of Object.entries(generated.entry.$slots ?? {}))
27
+ expectedSlots.set(JSON.stringify([generated.key, name]), slot);
28
+ }
29
+ const issues = [];
30
+ for (const { key, entry } of components)
31
+ for (const [name, slot] of Object.entries(entry.$slots ?? {}))
32
+ if (slot.$modelBinding && !jsonEqual(slot, expectedSlots.get(JSON.stringify([key, name]))))
33
+ issues.push({
34
+ path: childPath(childPath('', key) + '/$slots', name),
35
+ message: 'Model slot has no exact source-plan owner',
36
+ });
37
+ return issues;
38
+ }
39
+ /** Data-model relationships do not instantiate a composition tree. Keep ordinary edges intact. */
40
+ export function componentCompositionDefinitions(components) {
41
+ if (!components.some(({ entry }) => Object.values(entry.$slots ?? {}).some((slot) => slot.$modelBinding)) ||
42
+ componentModelFamilyIssues(components).length ||
43
+ components.some(({ entry }) => componentDefinitionImportIssues(entry).length))
44
+ return [...components];
45
+ return components.map((component) => ({
46
+ ...component,
47
+ entry: {
48
+ ...component.entry,
49
+ $slots: Object.fromEntries(Object.entries(component.entry.$slots ?? {}).filter(([, slot]) => !slot.$modelBinding)),
50
+ },
51
+ }));
52
+ }
@@ -0,0 +1,17 @@
1
+ import { type TargetDefinition } from './target-definition.js';
2
+ import { type PropertyIssue } from './json-value.js';
3
+ import { type PropertySourceGraph, type SourceGraphNode } from './property-model.js';
4
+ export interface SourceUnionBranch {
5
+ memberIndex: number;
6
+ nodeId: string;
7
+ tagNodeId: string;
8
+ tag: string | number | boolean;
9
+ }
10
+ export interface SourceDiscriminatedUnion {
11
+ discriminator: string;
12
+ branches: SourceUnionBranch[];
13
+ }
14
+ /** Complete compiler field edges establish tags independently of observed callers. */
15
+ export declare function sourceDiscriminatedUnion(node: SourceGraphNode, nodes: ReadonlyMap<string, SourceGraphNode>, discriminator?: string): SourceDiscriminatedUnion | undefined;
16
+ /** Match each target branch to the original compiler member through its exact typed tag. */
17
+ export declare function validateDiscriminatedUnionSourceDefinition(definition: TargetDefinition, graph: PropertySourceGraph, nodeId?: string): PropertyIssue[];
@@ -0,0 +1,180 @@
1
+ import { discriminatedUnionTag } from './discriminated-union.js';
2
+ import { validateTargetDefinition } from './target-definition.js';
3
+ import { childPath, jsonEqual, own } from './json-value.js';
4
+ import { validateSourceGraph, validateSourceValue, } from './property-model.js';
5
+ import { finiteSourceValueDomain } from './source-representation.js';
6
+ function referenceValue(node, nodes) {
7
+ const active = new Set();
8
+ let current = node;
9
+ while (current?.kind === 'reference') {
10
+ if (active.has(current.id) || current.alternatives?.length !== 1)
11
+ return;
12
+ active.add(current.id);
13
+ current = nodes.get(current.alternatives[0]);
14
+ }
15
+ return current;
16
+ }
17
+ /** Complete compiler field edges establish tags independently of observed callers. */
18
+ export function sourceDiscriminatedUnion(node, nodes, discriminator) {
19
+ if (node.kind !== 'union' || node.coverage !== 'complete-within-declared-bound')
20
+ return;
21
+ const members = (node.alternatives ?? []).map((id, memberIndex) => ({ node: nodes.get(id), memberIndex }));
22
+ if (members.length < 2)
23
+ return;
24
+ if (members.some((member) => !member.node || ['null', 'undefined', 'never'].includes(member.node.kind)))
25
+ return;
26
+ const first = referenceValue(members[0].node, nodes);
27
+ if (!first)
28
+ return;
29
+ const keys = discriminator === undefined ? (first.fields ?? []).map((field) => field.key).sort() : [discriminator];
30
+ for (const key of keys) {
31
+ const branches = [];
32
+ const tags = [];
33
+ for (const member of members) {
34
+ const branch = referenceValue(member.node, nodes);
35
+ if (!branch)
36
+ break;
37
+ const field = branch.fields?.find((edge) => edge.key === key);
38
+ const originalTag = field && nodes.get(field.nodeId);
39
+ const tag = originalTag && referenceValue(originalTag, nodes);
40
+ const value = tag?.domain.declaredValues[0];
41
+ if (!['record', 'intersection'].includes(branch.kind) ||
42
+ branch.coverage !== 'complete-within-declared-bound' ||
43
+ !field?.required ||
44
+ !tag ||
45
+ tag.domain.provenance !== 'compiler' ||
46
+ tag.coverage !== 'complete-within-declared-bound' ||
47
+ tag.kind !== typeof value ||
48
+ tag.domain.openness !== 'closed' ||
49
+ tag.domain.unrepresentedValues?.length ||
50
+ tag.domain.declaredValues.length !== 1 ||
51
+ !(typeof value === 'string' ||
52
+ typeof value === 'boolean' ||
53
+ (typeof value === 'number' && Number.isFinite(value))) ||
54
+ tags.some((other) => jsonEqual(other, value)))
55
+ break;
56
+ tags.push(value);
57
+ branches.push({ memberIndex: member.memberIndex, nodeId: member.node.id, tagNodeId: field.nodeId, tag: value });
58
+ }
59
+ if (branches.length === members.length)
60
+ return { discriminator: key, branches };
61
+ }
62
+ return;
63
+ }
64
+ /** Match each target branch to the original compiler member through its exact typed tag. */
65
+ export function validateDiscriminatedUnionSourceDefinition(definition, graph, nodeId = graph.rootId) {
66
+ const validation = validateTargetDefinition(definition);
67
+ const issues = [...validation.issues, ...validateSourceGraph(graph)];
68
+ if (issues.length)
69
+ return issues;
70
+ if (graph.coverage !== 'complete-within-declared-bound' || graph.omittedCount)
71
+ return [{ path: '/source', message: 'Union requires a complete original compiler graph' }];
72
+ const nodes = new Map(graph.nodes.map((node) => [node.id, node]));
73
+ const match = (desired, id, path, active, required) => {
74
+ const node = nodes.get(id);
75
+ const fail = (message) => {
76
+ issues.push({ path, message });
77
+ };
78
+ if (!node || active.has(id)) {
79
+ fail('Union source relationship is missing or recursive');
80
+ return;
81
+ }
82
+ if (node.coverage !== 'complete-within-declared-bound' ||
83
+ node.nullability?.compilerMode !== 'enabled' ||
84
+ node.nullability.null.state !== 'absent' ||
85
+ node.nullability.undefined.state !== 'absent' ||
86
+ node.domain.unrepresentedValues?.length) {
87
+ fail('Union requires established complete non-nullish compiler value states');
88
+ return;
89
+ }
90
+ const next = new Set(active).add(id);
91
+ const expectedRequired = required ?? node.required;
92
+ if (desired.required !== undefined && desired.required !== expectedRequired)
93
+ fail('Union field requiredness differs from its compiler occurrence');
94
+ if (desired.values?.length && !['String', 'Number', 'Boolean', 'Literal'].includes(desired.type))
95
+ fail('Union structure cannot add unproven whole-value constraints');
96
+ if (own(desired, 'defaultValue'))
97
+ issues.push(...validateSourceValue(graph, desired.defaultValue, childPath(path, 'defaultValue'), id));
98
+ if (node.kind === 'reference' && node.alternatives?.length === 1) {
99
+ match(desired, node.alternatives[0], path, next, expectedRequired);
100
+ return;
101
+ }
102
+ if (desired.type === 'DiscriminatedUnion') {
103
+ const binding = sourceDiscriminatedUnion(node, nodes, desired.discriminator);
104
+ if (!binding || binding.branches.length !== desired.members.length) {
105
+ fail('Union must retain the exact complete compiler discriminator and member set');
106
+ return;
107
+ }
108
+ const selected = new Set();
109
+ desired.members.forEach((member, index) => {
110
+ const tag = discriminatedUnionTag(member, desired.discriminator, 'target');
111
+ const branch = binding.branches.find((candidate) => jsonEqual(candidate.tag, tag.value));
112
+ if (!branch || selected.has(branch.memberIndex)) {
113
+ fail('Union member requires one unique matching compiler tag');
114
+ return;
115
+ }
116
+ selected.add(branch.memberIndex);
117
+ match(member, branch.nodeId, childPath(childPath(path, 'members'), index), next, expectedRequired);
118
+ });
119
+ return;
120
+ }
121
+ if (desired.type === 'Record') {
122
+ const fields = node.fields;
123
+ if (!['record', 'intersection'].includes(node.kind) ||
124
+ node.callSignatures?.length ||
125
+ node.indexSignatures?.length ||
126
+ !fields ||
127
+ fields.length !== Object.keys(desired.fields).length) {
128
+ fail('Union Record must retain every exact compiler field');
129
+ return;
130
+ }
131
+ for (const field of fields) {
132
+ const target = desired.fields[field.key];
133
+ if (!Object.hasOwn(desired.fields, field.key) || target.required !== field.required) {
134
+ fail('Union field name and requiredness must match its compiler occurrence');
135
+ continue;
136
+ }
137
+ match(target, field.nodeId, childPath(childPath(path, 'fields'), field.key), next, field.required);
138
+ }
139
+ return;
140
+ }
141
+ if (desired.type === 'Array') {
142
+ if (node.kind !== 'array' || node.items?.length !== 1)
143
+ fail('Union Array must retain its exact compiler item');
144
+ else
145
+ match(desired.items, node.items[0], childPath(path, 'items'), next);
146
+ return;
147
+ }
148
+ if (desired.type === 'Literal') {
149
+ const type = typeof desired.value;
150
+ if (node.domain.provenance !== 'compiler' ||
151
+ node.domain.openness !== 'closed' ||
152
+ node.domain.declaredValues.length !== 1 ||
153
+ !jsonEqual(node.domain.declaredValues[0], desired.value) ||
154
+ node.kind !== type ||
155
+ !['string', 'number', 'boolean'].includes(type) ||
156
+ (desired.valueType.type !==
157
+ { string: 'String', number: 'Number', boolean: 'Boolean' }[type] &&
158
+ !(type === 'number' && desired.valueType.type === 'Integer' && Number.isSafeInteger(desired.value))))
159
+ fail('Union Literal must retain its exact typed compiler singleton');
160
+ return;
161
+ }
162
+ const type = { String: 'string', Number: 'number', Boolean: 'boolean' }[desired.type];
163
+ const values = finiteSourceValueDomain(graph, id);
164
+ const intrinsicBoolean = type === 'boolean' && values?.length === 2 && values.includes(false) && values.includes(true);
165
+ const finitePrimitive = type && values?.length && values.every((value) => typeof value === type);
166
+ if (!type || (node.kind !== type && !finitePrimitive))
167
+ fail('Union branch must preserve its exact compiler type');
168
+ if (values?.length &&
169
+ !intrinsicBoolean &&
170
+ (!desired.values?.length ||
171
+ values.length !== desired.values.length ||
172
+ values.some((value) => !desired.values.some((allowed) => jsonEqual(allowed, value)))))
173
+ fail('Union branch must preserve its complete compiler domain');
174
+ if (desired.values?.length &&
175
+ (!values?.length || desired.values.some((allowed) => !values.some((value) => jsonEqual(allowed, value)))))
176
+ fail('Union branch cannot narrow an unproven or open compiler domain');
177
+ };
178
+ match(definition, nodeId, '', new Set());
179
+ return issues;
180
+ }
@@ -0,0 +1,70 @@
1
+ import { type CDFComponentEntry, type CDFTokenEntry } from '../cdf/types.js';
2
+ import { type DesignTokenType } from '../dtcg/token-types.js';
3
+ export type ResourceDependencyKey = {
4
+ kind: 'DesignToken';
5
+ namespace: 'dtcg-path';
6
+ value: string;
7
+ } | {
8
+ kind: 'Component';
9
+ namespace: 'cdf-key';
10
+ value: string;
11
+ };
12
+ export interface ImportPrerequisiteManifest {
13
+ components: readonly {
14
+ key: string;
15
+ entry: CDFComponentEntry;
16
+ }[];
17
+ tokens: readonly {
18
+ path: string;
19
+ entry: CDFTokenEntry;
20
+ }[];
21
+ }
22
+ export interface ImportPrerequisiteEdge {
23
+ owner: ResourceDependencyKey;
24
+ dependency: ResourceDependencyKey;
25
+ }
26
+ export interface ImportPrerequisiteObligation {
27
+ owner: ResourceDependencyKey;
28
+ path: string;
29
+ reference: {
30
+ namespace: 'dtcg-path';
31
+ value: string;
32
+ };
33
+ expectedKind: DesignTokenType;
34
+ resolution: 'planned' | 'unknown';
35
+ definitionIdentity?: string;
36
+ }
37
+ export interface ImportPrerequisitePlan {
38
+ revision: 1;
39
+ manifestIdentity: string;
40
+ tokenManifestIdentity: string;
41
+ graphIdentity: string;
42
+ orderedKeys: string[];
43
+ edges: ImportPrerequisiteEdge[];
44
+ obligations: ImportPrerequisiteObligation[];
45
+ capabilityRequirements: Array<{
46
+ owner: ResourceDependencyKey;
47
+ path: string;
48
+ capability: string;
49
+ }>;
50
+ }
51
+ export interface ImportPrerequisiteIssue {
52
+ code: string;
53
+ path: string;
54
+ message: string;
55
+ }
56
+ export type ImportPrerequisiteValidation = {
57
+ valid: true;
58
+ plan: Readonly<ImportPrerequisitePlan>;
59
+ errors: [];
60
+ } | {
61
+ valid: false;
62
+ errors: ImportPrerequisiteIssue[];
63
+ };
64
+ export declare function importTokenDefinitionIdentity(path: string, entry: CDFTokenEntry): string;
65
+ export declare function importTokenManifestIdentity(tokens: ImportPrerequisiteManifest['tokens']): string;
66
+ export declare function importDependencyKey(key: ResourceDependencyKey): string;
67
+ /** Local plans establish dependencies; absent target resources remain unknown. */
68
+ export declare function createImportPrerequisitePlan(input: ImportPrerequisiteManifest): ImportPrerequisiteValidation;
69
+ /** @alias Validation and planning use the same prerequisite checks. */
70
+ export declare const validateImportPrerequisites: typeof createImportPrerequisitePlan;
@@ -0,0 +1,208 @@
1
+ import { CDFComponentSchema, CDFTokenSchema, } from '../cdf/types.js';
2
+ import { DESIGN_TOKEN_TYPES } from '../dtcg/token-types.js';
3
+ import { contentDigest } from './content-digest.js';
4
+ import { validateRepresentationClosure } from '../cdf/representation-validation.js';
5
+ import { childPath, freezeJson, cloneJson, jsonValueIssue } from './json-value.js';
6
+ import { componentDefinitionImportIssues } from './definition-import-rules.js';
7
+ export function importTokenDefinitionIdentity(path, entry) {
8
+ return contentDigest({ path, entry });
9
+ }
10
+ export function importTokenManifestIdentity(tokens) {
11
+ return contentDigest([...tokens].sort((left, right) => left.path.localeCompare(right.path)));
12
+ }
13
+ export function importDependencyKey(key) {
14
+ return `${key.kind}:${JSON.stringify([key.namespace, key.value])}`;
15
+ }
16
+ /** Local plans establish dependencies; absent target resources remain unknown. */
17
+ export function createImportPrerequisitePlan(input) {
18
+ const errors = [];
19
+ const components = new Map();
20
+ const tokens = new Map();
21
+ const edges = new Map();
22
+ const obligations = [];
23
+ const capabilityRequirements = [];
24
+ const nodes = new Set();
25
+ const issue = (code, path, message) => {
26
+ errors.push({ code, path, message });
27
+ };
28
+ const componentKey = (value) => ({ kind: 'Component', namespace: 'cdf-key', value });
29
+ const tokenKey = (value) => ({ kind: 'DesignToken', namespace: 'dtcg-path', value });
30
+ const addEdge = (owner, dependency) => {
31
+ edges.set(JSON.stringify([importDependencyKey(owner), importDependencyKey(dependency)]), { owner, dependency });
32
+ };
33
+ for (const [index, component] of input.components.entries()) {
34
+ if (!component.key || components.has(component.key)) {
35
+ issue('component-owner-duplicate', `/components/${index}/key`, 'Duplicate or empty Component key');
36
+ continue;
37
+ }
38
+ if (!CDFComponentSchema.safeParse(component.entry).success) {
39
+ issue('component-definition-invalid', `/components/${index}`, 'Invalid Component definition');
40
+ continue;
41
+ }
42
+ for (const finding of componentDefinitionImportIssues(component.entry))
43
+ issue('component-import-invalid', `/components/${index}${finding.path}`, finding.message);
44
+ components.set(component.key, component.entry);
45
+ nodes.add(importDependencyKey(componentKey(component.key)));
46
+ }
47
+ for (const [index, token] of input.tokens.entries()) {
48
+ if (!token.path || tokens.has(token.path)) {
49
+ issue('token-definition-duplicate', `/tokens/${index}/path`, 'Duplicate or empty DesignToken path');
50
+ continue;
51
+ }
52
+ if (jsonValueIssue(token.entry) || !CDFTokenSchema.safeParse(token.entry).success) {
53
+ issue('token-definition-invalid', `/tokens/${index}`, 'Invalid DesignToken definition');
54
+ continue;
55
+ }
56
+ tokens.set(token.path, token.entry);
57
+ nodes.add(importDependencyKey(tokenKey(token.path)));
58
+ }
59
+ if (errors.length)
60
+ return { valid: false, errors };
61
+ const visit = (owner, definition, path, category) => {
62
+ if (category === 'design' && definition.$type === 'token') {
63
+ const kind = definition['$token.kind'];
64
+ if (!DESIGN_TOKEN_TYPES.includes(kind)) {
65
+ issue('token-kind-invalid', `${path}/$token.kind`, 'Token properties require a recognized token kind');
66
+ }
67
+ else {
68
+ const references = (definition['$token.allowed'] ?? []).map((value, index) => ({
69
+ value,
70
+ path: `${path}/$token.allowed/${index}`,
71
+ }));
72
+ if (typeof definition.$default === 'string')
73
+ references.push({ value: definition.$default, path: `${path}/$default` });
74
+ for (const reference of references) {
75
+ if (!reference.value.trim()) {
76
+ issue('token-reference-invalid', reference.path, 'Token reference must not be empty');
77
+ continue;
78
+ }
79
+ const planned = tokens.get(reference.value);
80
+ if (planned && planned.$type !== kind) {
81
+ issue('token-kind-mismatch', reference.path, 'Planned token kind differs from the property kind');
82
+ continue;
83
+ }
84
+ obligations.push({
85
+ owner,
86
+ path: reference.path,
87
+ reference: { namespace: 'dtcg-path', value: reference.value },
88
+ expectedKind: kind,
89
+ resolution: planned ? 'planned' : 'unknown',
90
+ ...(planned ? { definitionIdentity: importTokenDefinitionIdentity(reference.value, planned) } : {}),
91
+ });
92
+ if (planned)
93
+ addEdge(owner, tokenKey(reference.value));
94
+ }
95
+ }
96
+ }
97
+ if (definition.$items)
98
+ visit(owner, definition.$items, `${path}/$items`, category);
99
+ if (definition.valueType)
100
+ visit(owner, definition.valueType, `${path}/valueType`, category);
101
+ for (const [index, member] of (definition.members ?? []).entries())
102
+ visit(owner, member, `${path}/members/${index}`, category);
103
+ for (const [key, field] of Object.entries(definition.$fields ?? {}))
104
+ visit(owner, field, childPath(`${path}/$fields`, key), category);
105
+ };
106
+ for (const [key, component] of components) {
107
+ const owner = componentKey(key);
108
+ for (const [name, definition] of Object.entries(component.$properties))
109
+ visit(owner, definition, childPath(`${childPath('', key)}/$properties`, name), definition.$category);
110
+ for (const [name, slot] of Object.entries(component.$slots ?? {})) {
111
+ for (const allowed of slot.$allowedComponents ?? []) {
112
+ if (components.has(allowed))
113
+ addEdge(owner, componentKey(allowed));
114
+ else if (slot.$modelBinding)
115
+ issue('prerequisite-node-missing', childPath(`${childPath('', key)}/$slots`, name), 'Generated model dependency is missing');
116
+ }
117
+ }
118
+ for (const [name, plan] of Object.entries(component.$representationPlans ?? {})) {
119
+ if (!Array.isArray(plan.requirements)) {
120
+ issue('import-model-invalid', childPath(`${childPath('', key)}/$representationPlans`, name), 'Representation requirements are missing');
121
+ continue;
122
+ }
123
+ for (const requirement of plan.requirements)
124
+ capabilityRequirements.push({ owner, path: requirement.path, capability: requirement.capability });
125
+ for (const allowed of plan.attachment?.definition.$allowedComponents ?? []) {
126
+ if (!components.has(allowed))
127
+ issue('prerequisite-node-missing', childPath(`${childPath('', key)}/$representationPlans`, name), 'Representation model dependency is missing');
128
+ else
129
+ addEdge(owner, componentKey(allowed));
130
+ }
131
+ }
132
+ }
133
+ const orderedEdges = [...edges.values()].sort((a, b) => importDependencyKey(a.owner).localeCompare(importDependencyKey(b.owner)) ||
134
+ importDependencyKey(a.dependency).localeCompare(importDependencyKey(b.dependency)));
135
+ const remaining = new Map([...nodes].map((node) => [node, new Set()]));
136
+ for (const edge of orderedEdges)
137
+ remaining.get(importDependencyKey(edge.owner)).add(importDependencyKey(edge.dependency));
138
+ const orderedKeys = [];
139
+ while (remaining.size) {
140
+ let ready = [...remaining]
141
+ .filter(([, dependencies]) => dependencies.size === 0)
142
+ .map(([key]) => key)
143
+ .sort();
144
+ if (!ready.length) {
145
+ const groups = new Map();
146
+ for (const [key, component] of components) {
147
+ if (!component.$model)
148
+ continue;
149
+ const identity = component.$model;
150
+ const groupId = JSON.stringify([identity.planId, identity.componentId, identity.propertyId]);
151
+ const node = importDependencyKey(componentKey(key));
152
+ if (!remaining.has(node))
153
+ continue;
154
+ const group = groups.get(groupId) ?? new Set();
155
+ group.add(node);
156
+ groups.set(groupId, group);
157
+ }
158
+ // Recursive definitions form a finite model group; instances remain ordinary finite trees.
159
+ // Such a group requires staged downstream creation rather than dependency-first creation.
160
+ const group = [...groups.values()].find((members) => [...members].every((node) => [...remaining.get(node)].every((dependency) => members.has(dependency))));
161
+ if (group && !validateRepresentationClosure(input.components.map((component) => ({ ...component }))).length)
162
+ ready = [...group].sort();
163
+ }
164
+ if (!ready.length) {
165
+ issue('prerequisite-cycle', '', 'Import prerequisite graph contains a cycle');
166
+ break;
167
+ }
168
+ for (const key of ready) {
169
+ orderedKeys.push(key);
170
+ remaining.delete(key);
171
+ }
172
+ for (const dependencies of remaining.values())
173
+ for (const key of ready)
174
+ dependencies.delete(key);
175
+ }
176
+ if (errors.length)
177
+ return { valid: false, errors };
178
+ const manifestIdentity = contentDigest({
179
+ components: [...input.components].sort((a, b) => a.key.localeCompare(b.key)),
180
+ tokens: [...input.tokens].sort((a, b) => a.path.localeCompare(b.path)),
181
+ });
182
+ obligations.sort((a, b) => a.path.localeCompare(b.path));
183
+ capabilityRequirements.sort((a, b) => importDependencyKey(a.owner).localeCompare(importDependencyKey(b.owner)) ||
184
+ a.path.localeCompare(b.path) ||
185
+ a.capability.localeCompare(b.capability));
186
+ return {
187
+ valid: true,
188
+ errors: [],
189
+ plan: freezeJson(cloneJson({
190
+ revision: 1,
191
+ manifestIdentity,
192
+ tokenManifestIdentity: importTokenManifestIdentity(input.tokens),
193
+ graphIdentity: contentDigest({
194
+ manifestIdentity,
195
+ orderedKeys,
196
+ edges: orderedEdges,
197
+ obligations,
198
+ capabilityRequirements,
199
+ }),
200
+ orderedKeys,
201
+ edges: orderedEdges,
202
+ obligations,
203
+ capabilityRequirements,
204
+ })),
205
+ };
206
+ }
207
+ /** @alias Validation and planning use the same prerequisite checks. */
208
+ export const validateImportPrerequisites = createImportPrerequisitePlan;
@@ -1,4 +1,21 @@
1
1
  export * from './json-value.js';
2
+ export * from './target-definition.js';
2
3
  export * from './date-time-value.js';
4
+ export * from './source-representation.js';
5
+ export * from './mapper-readiness.js';
6
+ export * from './definition-import.js';
7
+ export * from './property-model.js';
8
+ export * from './representation-proposal.js';
9
+ export * from './classification.js';
10
+ export * from './null-handling.js';
11
+ export * from './decision-protocol.js';
12
+ export * from './property-decision.js';
13
+ export * from './representation-plan.js';
14
+ export * from './model-exploration.js';
15
+ export { contentDigest } from './content-digest.js';
16
+ export * from './import-prerequisites.js';
17
+ export * from './logical-source-graph.js';
18
+ export * from './analysis-representation-candidates.js';
19
+ export { nativeSourceRegion } from './native-source-region.js';
3
20
  export * from './discriminated-union.js';
4
- export * from './target-definition.js';
21
+ export * from './discriminated-union-source.js';
@@ -1,9 +1,21 @@
1
- // Pillar #4 foundation — property-contract target types + validators.
2
- // Dormant on `development` until downstream consumers (new extractors,
3
- // generation, review UI) activate them. Shape is deliberately verbatim
4
- // with the upstream work on feat/import-pipeline-evidence-and-reasoning
5
- // so the two merge without drift. See INTEG-5147 (spike) / INTEG-4927.
6
1
  export * from './json-value.js';
2
+ export * from './target-definition.js';
7
3
  export * from './date-time-value.js';
4
+ export * from './source-representation.js';
5
+ export * from './mapper-readiness.js';
6
+ export * from './definition-import.js';
7
+ export * from './property-model.js';
8
+ export * from './representation-proposal.js';
9
+ export * from './classification.js';
10
+ export * from './null-handling.js';
11
+ export * from './decision-protocol.js';
12
+ export * from './property-decision.js';
13
+ export * from './representation-plan.js';
14
+ export * from './model-exploration.js';
15
+ export { contentDigest } from './content-digest.js';
16
+ export * from './import-prerequisites.js';
17
+ export * from './logical-source-graph.js';
18
+ export * from './analysis-representation-candidates.js';
19
+ export { nativeSourceRegion } from './native-source-region.js';
8
20
  export * from './discriminated-union.js';
9
- export * from './target-definition.js';
21
+ export * from './discriminated-union-source.js';
@@ -0,0 +1,36 @@
1
+ import { type DefaultIntent, type PropertyModel, type SourceGraphNode } from './property-model.js';
2
+ export interface LogicalBranchCondition {
3
+ unionNodeId: string;
4
+ memberIndex: number;
5
+ sourceMemberNodeId: string;
6
+ discriminator: string;
7
+ tag: string | number | boolean;
8
+ }
9
+ export interface LogicalSourceNode extends SourceGraphNode {
10
+ sourceNodeId: string;
11
+ path: NonNullable<SourceGraphNode['path']>;
12
+ readonly: boolean;
13
+ occurrenceReadonly: boolean;
14
+ intrinsicReadonly: boolean;
15
+ defaultIntent?: DefaultIntent;
16
+ branchConditions?: LogicalBranchCondition[];
17
+ unionBranches?: {
18
+ discriminator: string;
19
+ branches: Array<{
20
+ memberIndex: number;
21
+ nodeId: string;
22
+ sourceNodeId: string;
23
+ tag: string | number | boolean;
24
+ }>;
25
+ };
26
+ }
27
+ export interface LogicalSourceGraph {
28
+ authority: 'compiler';
29
+ rootId: string;
30
+ nodes: LogicalSourceNode[];
31
+ coverage: PropertyModel['source']['graph']['coverage'];
32
+ }
33
+ /** Only own record fields identify a default; an array sample cannot establish item defaults. */
34
+ export declare function sourceDefaultAtPath(model: Pick<PropertyModel, 'source'>, path: LogicalSourceNode['path']): DefaultIntent | undefined;
35
+ /** Retain shared references while expanding finite occurrences with distinct branch ownership. */
36
+ export declare function prepareLogicalSourceGraph(model: Pick<PropertyModel, 'identity' | 'source'>): LogicalSourceGraph;