@codama/spec 1.6.0-rc.1 → 1.6.0-rc.3
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/api.browser.cjs +305 -0
- package/dist/api.browser.cjs.map +1 -0
- package/dist/api.browser.mjs +267 -0
- package/dist/api.browser.mjs.map +1 -0
- package/dist/api.node.cjs +305 -0
- package/dist/api.node.cjs.map +1 -0
- package/dist/api.node.mjs +267 -0
- package/dist/api.node.mjs.map +1 -0
- package/dist/api.react-native.mjs +267 -0
- package/dist/api.react-native.mjs.map +1 -0
- package/dist/index.browser.cjs +1 -1
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.mjs +1905 -1
- package/dist/index.browser.mjs.map +1 -1
- package/dist/index.node.cjs +1 -1
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.mjs +1905 -1
- package/dist/index.node.mjs.map +1 -1
- package/dist/index.react-native.mjs +1905 -1
- package/dist/index.react-native.mjs.map +1 -1
- package/dist/types/api/primitives.d.ts.map +1 -1
- package/dist/types/api/semanticAliases.d.ts +17 -7
- package/dist/types/api/semanticAliases.d.ts.map +1 -1
- package/dist/types/api/types.d.ts +15 -3
- package/dist/types/api/types.d.ts.map +1 -1
- package/dist/types/api/validate.d.ts +3 -0
- package/dist/types/api/validate.d.ts.map +1 -1
- package/dist/v1.browser.cjs +1 -1
- package/dist/v1.browser.cjs.map +1 -1
- package/dist/v1.browser.mjs +1905 -1
- package/dist/v1.browser.mjs.map +1 -1
- package/dist/v1.node.cjs +1 -1
- package/dist/v1.node.cjs.map +1 -1
- package/dist/v1.node.mjs +1905 -1
- package/dist/v1.node.mjs.map +1 -1
- package/dist/v1.react-native.mjs +1905 -1
- package/dist/v1.react-native.mjs.map +1 -1
- package/package.json +13 -1
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/api/attribute.ts
|
|
4
|
+
function attribute(name, type, options = {}) {
|
|
5
|
+
return Object.freeze({
|
|
6
|
+
name,
|
|
7
|
+
type,
|
|
8
|
+
...options.optional ? { optional: true } : {},
|
|
9
|
+
...options.docs !== void 0 ? { docs: options.docs } : {}
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
function optionalAttribute(name, type, options = {}) {
|
|
13
|
+
return attribute(name, type, { ...options, optional: true });
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// src/api/compounds.ts
|
|
17
|
+
function array(inner) {
|
|
18
|
+
return Object.freeze({ kind: "array", of: inner });
|
|
19
|
+
}
|
|
20
|
+
function tuple(...items) {
|
|
21
|
+
return Object.freeze({ kind: "tuple", items: Object.freeze([...items]) });
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// src/api/defineEnumeration.ts
|
|
25
|
+
function variant(name, options = {}) {
|
|
26
|
+
return Object.freeze({
|
|
27
|
+
name,
|
|
28
|
+
...options.docs !== void 0 ? { docs: options.docs } : {}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
function defineEnumeration(name, options) {
|
|
32
|
+
if (options.variants.length === 0) {
|
|
33
|
+
throw new Error(`defineEnumeration("${name}"): variants must be non-empty`);
|
|
34
|
+
}
|
|
35
|
+
const seen = /* @__PURE__ */ new Set();
|
|
36
|
+
for (const v of options.variants) {
|
|
37
|
+
if (seen.has(v.name)) {
|
|
38
|
+
throw new Error(`defineEnumeration("${name}"): duplicate variant "${v.name}"`);
|
|
39
|
+
}
|
|
40
|
+
seen.add(v.name);
|
|
41
|
+
}
|
|
42
|
+
return Object.freeze({
|
|
43
|
+
name,
|
|
44
|
+
variants: Object.freeze([...options.variants]),
|
|
45
|
+
...options.docs !== void 0 ? { docs: options.docs } : {}
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// src/api/defineNode.ts
|
|
50
|
+
function defineNode(kind, options) {
|
|
51
|
+
return Object.freeze({
|
|
52
|
+
kind,
|
|
53
|
+
...options.docs !== void 0 ? { docs: options.docs } : {},
|
|
54
|
+
attributes: Object.freeze([...options.attributes]),
|
|
55
|
+
examples: Object.freeze([...options.examples ?? []])
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// src/api/defineUnion.ts
|
|
60
|
+
function defineUnion(name, options) {
|
|
61
|
+
const normalised = options.members.map(normaliseMember);
|
|
62
|
+
return Object.freeze({
|
|
63
|
+
name,
|
|
64
|
+
members: Object.freeze(normalised),
|
|
65
|
+
...options.docs !== void 0 ? { docs: options.docs } : {}
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
function normaliseMember(input) {
|
|
69
|
+
if (typeof input === "string") {
|
|
70
|
+
return Object.freeze({ kind: "node", name: input });
|
|
71
|
+
}
|
|
72
|
+
if (input.kind === "node") return Object.freeze({ kind: "node", name: input.name });
|
|
73
|
+
if (input.kind === "union") return Object.freeze({ kind: "union", name: input.name });
|
|
74
|
+
throw new Error(
|
|
75
|
+
`defineUnion: members must be node kind strings, node(...) or union(...) references; got ${JSON.stringify(input)}`
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// src/api/primitives.ts
|
|
80
|
+
function string() {
|
|
81
|
+
return Object.freeze({ kind: "string" });
|
|
82
|
+
}
|
|
83
|
+
function stringIdentifier() {
|
|
84
|
+
return Object.freeze({ kind: "string", constraint: "identifier" });
|
|
85
|
+
}
|
|
86
|
+
function stringVersion() {
|
|
87
|
+
return Object.freeze({ kind: "string", constraint: "version" });
|
|
88
|
+
}
|
|
89
|
+
function codamaVersion() {
|
|
90
|
+
return Object.freeze({ kind: "codamaVersion" });
|
|
91
|
+
}
|
|
92
|
+
var integer = (width) => Object.freeze({ kind: "integer", width });
|
|
93
|
+
var u8 = () => integer("u8");
|
|
94
|
+
var u16 = () => integer("u16");
|
|
95
|
+
var u32 = () => integer("u32");
|
|
96
|
+
var u64 = () => integer("u64");
|
|
97
|
+
var u128 = () => integer("u128");
|
|
98
|
+
var i8 = () => integer("i8");
|
|
99
|
+
var i16 = () => integer("i16");
|
|
100
|
+
var i32 = () => integer("i32");
|
|
101
|
+
var i64 = () => integer("i64");
|
|
102
|
+
var i128 = () => integer("i128");
|
|
103
|
+
var float = (width) => Object.freeze({ kind: "float", width });
|
|
104
|
+
var f32 = () => float("f32");
|
|
105
|
+
var f64 = () => float("f64");
|
|
106
|
+
function boolean() {
|
|
107
|
+
return Object.freeze({ kind: "boolean" });
|
|
108
|
+
}
|
|
109
|
+
function literal(value) {
|
|
110
|
+
return Object.freeze({ kind: "literal", value });
|
|
111
|
+
}
|
|
112
|
+
function literalUnion(...values) {
|
|
113
|
+
if (values.length === 0) {
|
|
114
|
+
throw new Error("literalUnion: at least one value required");
|
|
115
|
+
}
|
|
116
|
+
const seen = /* @__PURE__ */ new Set();
|
|
117
|
+
for (const v of values) {
|
|
118
|
+
if (seen.has(v)) {
|
|
119
|
+
throw new Error(`literalUnion: duplicate value ${JSON.stringify(v)}`);
|
|
120
|
+
}
|
|
121
|
+
seen.add(v);
|
|
122
|
+
}
|
|
123
|
+
return Object.freeze({ kind: "literalUnion", values: Object.freeze([...values]) });
|
|
124
|
+
}
|
|
125
|
+
function enumeration(name) {
|
|
126
|
+
return Object.freeze({ kind: "enumeration", name });
|
|
127
|
+
}
|
|
128
|
+
function node(name) {
|
|
129
|
+
return Object.freeze({ kind: "node", name });
|
|
130
|
+
}
|
|
131
|
+
function union(name) {
|
|
132
|
+
return Object.freeze({ kind: "union", name });
|
|
133
|
+
}
|
|
134
|
+
function nestedTypeNode(name) {
|
|
135
|
+
return Object.freeze({ kind: "nestedTypeNode", name });
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// src/api/semanticAliases.ts
|
|
139
|
+
function byteSize() {
|
|
140
|
+
return u64();
|
|
141
|
+
}
|
|
142
|
+
function byteOffset() {
|
|
143
|
+
return i64();
|
|
144
|
+
}
|
|
145
|
+
function count() {
|
|
146
|
+
return u32();
|
|
147
|
+
}
|
|
148
|
+
function docs() {
|
|
149
|
+
return Object.freeze({ kind: "docs" });
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// src/api/validate.ts
|
|
153
|
+
function validate(spec) {
|
|
154
|
+
const errors = [];
|
|
155
|
+
const nodeKinds = new Set(spec.nodes.map((n) => n.kind));
|
|
156
|
+
const unionNames = new Set(spec.unions.map((u) => u.name));
|
|
157
|
+
const enumerationNames = new Set(spec.enumerations.map((e) => e.name));
|
|
158
|
+
const wrappers = new Set(spec.nestedTypeNodeWrappers);
|
|
159
|
+
const registrations = /* @__PURE__ */ new Map();
|
|
160
|
+
const record = (name, kind) => {
|
|
161
|
+
const list = registrations.get(name);
|
|
162
|
+
if (list) list.push(kind);
|
|
163
|
+
else registrations.set(name, [kind]);
|
|
164
|
+
};
|
|
165
|
+
for (const n of spec.nodes) record(n.kind, "node");
|
|
166
|
+
for (const u of spec.unions) record(u.name, "union");
|
|
167
|
+
for (const e of spec.enumerations) record(e.name, "enumeration");
|
|
168
|
+
for (const [name, kinds] of registrations) {
|
|
169
|
+
if (kinds.length > 1) errors.push(formatCollisionError(name, kinds));
|
|
170
|
+
}
|
|
171
|
+
for (const n of spec.nodes) {
|
|
172
|
+
if (!/^[a-z][A-Za-z0-9]*Node$/.test(n.kind)) {
|
|
173
|
+
errors.push(`Node kind "${n.kind}" does not match the camelCase ...Node naming convention.`);
|
|
174
|
+
}
|
|
175
|
+
const seenAttrs = /* @__PURE__ */ new Set();
|
|
176
|
+
for (const a of n.attributes) {
|
|
177
|
+
if (seenAttrs.has(a.name)) {
|
|
178
|
+
errors.push(`Node "${n.kind}" declares attribute "${a.name}" more than once.`);
|
|
179
|
+
}
|
|
180
|
+
seenAttrs.add(a.name);
|
|
181
|
+
walkTypeExpr(
|
|
182
|
+
a.type,
|
|
183
|
+
(expr) => checkRef(expr, n.kind, a.name, errors, nodeKinds, unionNames, enumerationNames)
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
for (const u of spec.unions) {
|
|
188
|
+
if (u.members.length === 0) {
|
|
189
|
+
errors.push(`Union "${u.name}" has no members.`);
|
|
190
|
+
}
|
|
191
|
+
const seenMembers = /* @__PURE__ */ new Set();
|
|
192
|
+
for (const m of u.members) {
|
|
193
|
+
const key = `${m.kind}:${m.name}`;
|
|
194
|
+
if (seenMembers.has(key)) {
|
|
195
|
+
errors.push(`Union "${u.name}" lists member ${key} more than once.`);
|
|
196
|
+
}
|
|
197
|
+
seenMembers.add(key);
|
|
198
|
+
if (m.kind === "node" && !nodeKinds.has(m.name)) {
|
|
199
|
+
errors.push(`Union "${u.name}" references undefined node "${m.name}".`);
|
|
200
|
+
}
|
|
201
|
+
if (m.kind === "union" && !unionNames.has(m.name)) {
|
|
202
|
+
errors.push(`Union "${u.name}" references undefined union "${m.name}".`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
for (const wrapper of wrappers) {
|
|
207
|
+
if (!nodeKinds.has(wrapper)) {
|
|
208
|
+
errors.push(`Nested-type-node wrapper "${wrapper}" is not a defined node.`);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return errors;
|
|
212
|
+
}
|
|
213
|
+
function formatCollisionError(name, kinds) {
|
|
214
|
+
const counts = /* @__PURE__ */ new Map();
|
|
215
|
+
for (const k of kinds) counts.set(k, (counts.get(k) ?? 0) + 1);
|
|
216
|
+
const breakdown = [...counts.entries()].sort((a, b) => a[0].localeCompare(b[0])).map(([k, n]) => `${n} ${k}${n > 1 ? "s" : ""}`).join(", ");
|
|
217
|
+
return `Name "${name}" is registered ${kinds.length} times (${breakdown}); names must be unique across nodes, unions, and enumerations.`;
|
|
218
|
+
}
|
|
219
|
+
function walkTypeExpr(expr, visit) {
|
|
220
|
+
visit(expr);
|
|
221
|
+
if (expr.kind === "array") {
|
|
222
|
+
walkTypeExpr(expr.of, visit);
|
|
223
|
+
} else if (expr.kind === "tuple") {
|
|
224
|
+
for (const item of expr.items) walkTypeExpr(item, visit);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
function checkRef(expr, nodeKind, attrName, errors, nodeKinds, unionNames, enumerationNames) {
|
|
228
|
+
const where = `Node "${nodeKind}", attribute "${attrName}":`;
|
|
229
|
+
switch (expr.kind) {
|
|
230
|
+
case "node":
|
|
231
|
+
if (!nodeKinds.has(expr.name)) {
|
|
232
|
+
errors.push(`${where} references undefined node "${expr.name}".`);
|
|
233
|
+
}
|
|
234
|
+
break;
|
|
235
|
+
case "union":
|
|
236
|
+
if (!unionNames.has(expr.name)) {
|
|
237
|
+
errors.push(`${where} references undefined union "${expr.name}".`);
|
|
238
|
+
}
|
|
239
|
+
break;
|
|
240
|
+
case "enumeration":
|
|
241
|
+
if (!enumerationNames.has(expr.name)) {
|
|
242
|
+
errors.push(`${where} references undefined enumeration "${expr.name}".`);
|
|
243
|
+
}
|
|
244
|
+
break;
|
|
245
|
+
case "nestedTypeNode":
|
|
246
|
+
if (!nodeKinds.has(expr.name)) {
|
|
247
|
+
errors.push(`${where} nestedTypeNode references undefined node "${expr.name}".`);
|
|
248
|
+
}
|
|
249
|
+
break;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
function isChildAttribute(type) {
|
|
253
|
+
switch (type.kind) {
|
|
254
|
+
case "node":
|
|
255
|
+
case "nestedTypeNode":
|
|
256
|
+
case "union":
|
|
257
|
+
return true;
|
|
258
|
+
case "array":
|
|
259
|
+
return isChildAttribute(type.of);
|
|
260
|
+
case "tuple":
|
|
261
|
+
return type.items.some(isChildAttribute);
|
|
262
|
+
default:
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
exports.array = array;
|
|
268
|
+
exports.attribute = attribute;
|
|
269
|
+
exports.boolean = boolean;
|
|
270
|
+
exports.byteOffset = byteOffset;
|
|
271
|
+
exports.byteSize = byteSize;
|
|
272
|
+
exports.codamaVersion = codamaVersion;
|
|
273
|
+
exports.count = count;
|
|
274
|
+
exports.defineEnumeration = defineEnumeration;
|
|
275
|
+
exports.defineNode = defineNode;
|
|
276
|
+
exports.defineUnion = defineUnion;
|
|
277
|
+
exports.docs = docs;
|
|
278
|
+
exports.enumeration = enumeration;
|
|
279
|
+
exports.f32 = f32;
|
|
280
|
+
exports.f64 = f64;
|
|
281
|
+
exports.i128 = i128;
|
|
282
|
+
exports.i16 = i16;
|
|
283
|
+
exports.i32 = i32;
|
|
284
|
+
exports.i64 = i64;
|
|
285
|
+
exports.i8 = i8;
|
|
286
|
+
exports.isChildAttribute = isChildAttribute;
|
|
287
|
+
exports.literal = literal;
|
|
288
|
+
exports.literalUnion = literalUnion;
|
|
289
|
+
exports.nestedTypeNode = nestedTypeNode;
|
|
290
|
+
exports.node = node;
|
|
291
|
+
exports.optionalAttribute = optionalAttribute;
|
|
292
|
+
exports.string = string;
|
|
293
|
+
exports.stringIdentifier = stringIdentifier;
|
|
294
|
+
exports.stringVersion = stringVersion;
|
|
295
|
+
exports.tuple = tuple;
|
|
296
|
+
exports.u128 = u128;
|
|
297
|
+
exports.u16 = u16;
|
|
298
|
+
exports.u32 = u32;
|
|
299
|
+
exports.u64 = u64;
|
|
300
|
+
exports.u8 = u8;
|
|
301
|
+
exports.union = union;
|
|
302
|
+
exports.validate = validate;
|
|
303
|
+
exports.variant = variant;
|
|
304
|
+
//# sourceMappingURL=api.browser.cjs.map
|
|
305
|
+
//# sourceMappingURL=api.browser.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/api/attribute.ts","../src/api/compounds.ts","../src/api/defineEnumeration.ts","../src/api/defineNode.ts","../src/api/defineUnion.ts","../src/api/primitives.ts","../src/api/semanticAliases.ts","../src/api/validate.ts"],"names":[],"mappings":"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","file":"api.browser.cjs","sourcesContent":["/**\n * Attribute factories — produce frozen `AttributeSpec` values directly.\n *\n * Every attribute of a node MUST be constructed via one of these helpers.\n * The returned value IS the encoded form; `defineNode` consumes them as-is.\n */\n\nimport type { AttributeSpec, TypeExpr } from './types';\n\nexport interface AttributeOptions {\n /** Free-form prose description for codegen / docs. */\n readonly docs?: string;\n /** When `true`, the attribute may be absent in encoded values. */\n readonly optional?: boolean;\n}\n\n/**\n * Declare an attribute. The default is a required attribute; pass\n * `{ optional: true }` (or use `optionalAttribute`) to mark it optional.\n */\nexport function attribute(name: string, type: TypeExpr, options: AttributeOptions = {}): AttributeSpec {\n return Object.freeze({\n name,\n type,\n ...(options.optional ? { optional: true as const } : {}),\n ...(options.docs !== undefined ? { docs: options.docs } : {}),\n });\n}\n\n/**\n * Sugar for `attribute(name, type, { optional: true, ...rest })` — the most\n * common attribute shape after required ones.\n */\nexport function optionalAttribute(\n name: string,\n type: TypeExpr,\n options: Omit<AttributeOptions, 'optional'> = {},\n): AttributeSpec {\n return attribute(name, type, { ...options, optional: true });\n}\n","/**\n * Compound type-expression constructors — wrap or combine other type\n * expressions. Returned values are frozen.\n *\n * Optionality is intentionally NOT a compound: it's an attribute-level\n * concern, expressed via `optionalAttribute(...)` or\n * `attribute(..., { optional: true })`.\n */\n\nimport type { TypeExpr } from './types';\n\n/** An array (homogeneous list) of `inner`. */\nexport function array(inner: TypeExpr): TypeExpr {\n return Object.freeze({ kind: 'array' as const, of: inner });\n}\n\n/**\n * A heterogeneous fixed-length tuple. Each positional slot has its own type.\n *\n * Tuples use `items` (plural) rather than `of` to signal cardinality > 1.\n */\nexport function tuple(...items: TypeExpr[]): TypeExpr {\n return Object.freeze({ kind: 'tuple' as const, items: Object.freeze([...items]) });\n}\n","/**\n * `defineEnumeration(name, options)` — declares a named enumeration.\n *\n * Codegen emits a string-literal union (TS), a real `enum` (Rust), a class\n * (Python), etc., according to each language's idiom. Per-variant docs are\n * carried through to language-native member documentation.\n */\n\nimport type { EnumerationSpec, EnumerationVariantSpec } from './types';\n\nexport interface VariantOptions {\n readonly docs?: string;\n}\n\n/** Construct a single enumeration variant. */\nexport function variant(name: string, options: VariantOptions = {}): EnumerationVariantSpec {\n return Object.freeze({\n name,\n ...(options.docs !== undefined ? { docs: options.docs } : {}),\n });\n}\n\nexport interface DefineEnumerationOptions {\n readonly docs?: string;\n readonly variants: readonly EnumerationVariantSpec[];\n}\n\nexport function defineEnumeration(name: string, options: DefineEnumerationOptions): EnumerationSpec {\n if (options.variants.length === 0) {\n throw new Error(`defineEnumeration(\"${name}\"): variants must be non-empty`);\n }\n const seen = new Set<string>();\n for (const v of options.variants) {\n if (seen.has(v.name)) {\n throw new Error(`defineEnumeration(\"${name}\"): duplicate variant \"${v.name}\"`);\n }\n seen.add(v.name);\n }\n return Object.freeze({\n name,\n variants: Object.freeze([...options.variants]),\n ...(options.docs !== undefined ? { docs: options.docs } : {}),\n });\n}\n","/**\n * `defineNode(kind, options)` — declares a single Codama node.\n *\n * The `kind` string is the discriminator value. By convention it ends in\n * `Node` and uses camelCase (e.g. `accountNode`, `arrayTypeNode`).\n *\n * `attributes` is an ordered array of values produced by `attribute(...)` or\n * `optionalAttribute(...)`. Order is preserved in the encoded spec and, by\n * extension, in generated code. The `kind: literal(<kind>)` discriminator\n * is implicit and is NOT declared by authors.\n *\n * The data-vs-children distinction is derived at codegen time from each\n * attribute's type tree (see `isChildAttribute` in `validate.ts`); the\n * meta-model itself just stores a flat list.\n */\n\nimport type { AttributeSpec, NodeSpec } from './types';\n\nexport interface DefineNodeOptions {\n /** Free-form prose description for codegen / docs. */\n readonly docs?: string;\n /**\n * Attributes of the node, in declaration order. Construct each entry\n * via `attribute(...)` or `optionalAttribute(...)`.\n */\n readonly attributes: readonly AttributeSpec[];\n /** Free-form examples (shape defined per spec major version). */\n readonly examples?: readonly unknown[];\n}\n\nexport function defineNode(kind: string, options: DefineNodeOptions): NodeSpec {\n return Object.freeze({\n kind,\n ...(options.docs !== undefined ? { docs: options.docs } : {}),\n attributes: Object.freeze([...options.attributes]),\n examples: Object.freeze([...(options.examples ?? [])]),\n });\n}\n","/**\n * `defineUnion(name, options)` — declares a named union of nodes.\n *\n * Members can be:\n * - a node kind string (e.g. `'arrayTypeNode'`), or\n * - a `node(...)` / `union(...)` reference (a `TypeExpr` produced by\n * `primitives.ts`).\n *\n * Nested unions are preserved structurally in the encoded spec rather than\n * flattened. This serves two purposes:\n * - DRY authoring (`union('StandaloneTypeNode')` instead of repeating 23\n * kind names).\n * - A signal to the Rust codegen to emit `From`/`Into` trait impls between\n * the parent union and each nested union.\n */\n\nimport type { TypeExpr, UnionMember, UnionSpec } from './types';\n\nexport type UnionMemberInput = TypeExpr | string;\n\nexport interface DefineUnionOptions {\n readonly docs?: string;\n readonly members: readonly UnionMemberInput[];\n}\n\nexport function defineUnion(name: string, options: DefineUnionOptions): UnionSpec {\n const normalised: UnionMember[] = options.members.map(normaliseMember);\n return Object.freeze({\n name,\n members: Object.freeze(normalised),\n ...(options.docs !== undefined ? { docs: options.docs } : {}),\n });\n}\n\nfunction normaliseMember(input: UnionMemberInput): UnionMember {\n if (typeof input === 'string') {\n // Bare strings are treated as node kinds (the most common case).\n return Object.freeze({ kind: 'node' as const, name: input });\n }\n if (input.kind === 'node') return Object.freeze({ kind: 'node' as const, name: input.name });\n if (input.kind === 'union') return Object.freeze({ kind: 'union' as const, name: input.name });\n throw new Error(\n `defineUnion: members must be node kind strings, node(...) or union(...) references; got ${JSON.stringify(input)}`,\n );\n}\n","/**\n * Type-expression primitives — the leaves of any attribute's type tree.\n *\n * Each function returns a frozen `TypeExpr` value. The encoded spec stores\n * those objects verbatim; codegen targets read them and emit native types.\n */\n\nimport type { FloatWidth, IntegerWidth, LiteralValue, StringConstraint, TypeExpr } from './types';\n\n// Strings.\n\n/** Plain UTF-8 string. */\nexport function string(): TypeExpr {\n return Object.freeze({ kind: 'string' as const });\n}\n\n/**\n * A string that must be a valid IDL identifier (stored canonically in\n * camelCase). Renderers may convert to other casings at output time.\n */\nexport function stringIdentifier(): TypeExpr {\n return Object.freeze({ kind: 'string' as const, constraint: 'identifier' as const });\n}\n\n/** A string that must be a valid version (e.g. `\"1.6.0\"`). */\nexport function stringVersion(): TypeExpr {\n return Object.freeze({ kind: 'string' as const, constraint: 'version' as const });\n}\n\n/**\n * The version string of the surrounding Codama spec. Treat as a brand on\n * top of `stringVersion()` — the value is always pinned to the spec\n * version of the IDL document. Codegen targets typically emit a literal\n * type or a constant.\n */\nexport function codamaVersion(): TypeExpr {\n return Object.freeze({ kind: 'codamaVersion' as const });\n}\n\n// Integers (explicit bit widths — no machine-dependent usize/isize).\n\nconst integer = (width: IntegerWidth): TypeExpr => Object.freeze({ kind: 'integer' as const, width });\n\nexport const u8 = (): TypeExpr => integer('u8');\nexport const u16 = (): TypeExpr => integer('u16');\nexport const u32 = (): TypeExpr => integer('u32');\nexport const u64 = (): TypeExpr => integer('u64');\nexport const u128 = (): TypeExpr => integer('u128');\nexport const i8 = (): TypeExpr => integer('i8');\nexport const i16 = (): TypeExpr => integer('i16');\nexport const i32 = (): TypeExpr => integer('i32');\nexport const i64 = (): TypeExpr => integer('i64');\nexport const i128 = (): TypeExpr => integer('i128');\n\n// Floats.\n\nconst float = (width: FloatWidth): TypeExpr => Object.freeze({ kind: 'float' as const, width });\n\nexport const f32 = (): TypeExpr => float('f32');\nexport const f64 = (): TypeExpr => float('f64');\n\n// Booleans and literals.\n\nexport function boolean(): TypeExpr {\n return Object.freeze({ kind: 'boolean' as const });\n}\n\n/** A single fixed value of a primitive type. */\nexport function literal(value: LiteralValue): TypeExpr {\n return Object.freeze({ kind: 'literal' as const, value });\n}\n\n/**\n * A heterogeneous union of literal values — for sum types like\n * `boolean | 'either'` that don't fit a string-only enumeration.\n *\n * Codegen targets render this as the appropriate language idiom (a literal\n * union in TS, a tagged enum with custom serde in Rust, etc.).\n */\nexport function literalUnion(...values: LiteralValue[]): TypeExpr {\n if (values.length === 0) {\n throw new Error('literalUnion: at least one value required');\n }\n const seen = new Set<LiteralValue>();\n for (const v of values) {\n if (seen.has(v)) {\n throw new Error(`literalUnion: duplicate value ${JSON.stringify(v)}`);\n }\n seen.add(v);\n }\n return Object.freeze({ kind: 'literalUnion' as const, values: Object.freeze([...values]) });\n}\n\n// Named references.\n\n/** Reference to a named enumeration declared via `defineEnumeration`. */\nexport function enumeration(name: string): TypeExpr {\n return Object.freeze({ kind: 'enumeration' as const, name });\n}\n\n/** Reference to a named node declared via `defineNode`. */\nexport function node(name: string): TypeExpr {\n return Object.freeze({ kind: 'node' as const, name });\n}\n\n/** Reference to a named union declared via `defineUnion`. */\nexport function union(name: string): TypeExpr {\n return Object.freeze({ kind: 'union' as const, name });\n}\n\n/**\n * Reference to a named node, with implicit `NestedTypeNode<…>` wrapping.\n * The list of recognised wrapper nodes is supplied per spec major version;\n * see `v1/nestedTypeNodeWrappers.ts`.\n */\nexport function nestedTypeNode(name: string): TypeExpr {\n return Object.freeze({ kind: 'nestedTypeNode' as const, name });\n}\n\n// Re-exports for type ergonomics.\nexport type { FloatWidth, IntegerWidth, LiteralValue, StringConstraint, TypeExpr };\n","/**\n * Author-side semantic aliases.\n *\n * Most aliases desugar at call time so the encoded spec only ever shows\n * the underlying primitive (e.g. `{ kind: \"integer\", width: \"u64\" }` for\n * both `u64()` and `byteSize()`). Each language's codegen may further\n * specialise rendering for these widths (e.g. Rust may render `u64` as\n * `usize` for byte-size fields if it wants). Those are codegen policies\n * — not spec content.\n *\n * `docs()` is the exception: it returns its own `'docs'` `TypeExpr` kind\n * so the documentation intent survives in the encoded spec rather than\n * collapsing to `array(string())`.\n */\n\nimport { i64, u32, u64 } from './primitives';\nimport type { TypeExpr } from './types';\n\n/** Number of bytes; non-negative. Encoded as `u64`. */\nexport function byteSize(): TypeExpr {\n return u64();\n}\n\n/** Signed byte offset. Encoded as `i64`. */\nexport function byteOffset(): TypeExpr {\n return i64();\n}\n\n/** Count of items in a collection; non-negative. Encoded as `u32`. */\nexport function count(): TypeExpr {\n return u32();\n}\n\n/**\n * Documentation for a node — semantically a list of paragraph strings,\n * but rendered per language at codegen time (e.g. `Array<string>` in\n * TypeScript, `Vec<String>` in Rust). Returns its own `'docs'` kind so\n * the intent isn't lost in the encoded spec.\n */\nexport function docs(): TypeExpr {\n return Object.freeze({ kind: 'docs' as const });\n}\n","/**\n * Self-consistency validation for an assembled spec.\n *\n * Returns an array of human-readable error strings. An empty array means\n * the spec is internally coherent — every reference resolves, no duplicate\n * names, naming conventions hold.\n */\n\nimport type { Spec, TypeExpr } from './types';\n\ntype RegistryKind = 'enumeration' | 'node' | 'union';\n\nexport function validate(spec: Spec): string[] {\n const errors: string[] = [];\n\n const nodeKinds = new Set(spec.nodes.map(n => n.kind));\n const unionNames = new Set(spec.unions.map(u => u.name));\n const enumerationNames = new Set(spec.enumerations.map(e => e.name));\n const wrappers = new Set(spec.nestedTypeNodeWrappers);\n\n // Single-pass name-collision check. Detects both within-kind duplicates\n // (\"two nodes called `accountNode`\") and cross-kind collisions (\"there's\n // a node and a union both called `TypeNode`\") in one report per\n // offending name.\n const registrations = new Map<string, RegistryKind[]>();\n const record = (name: string, kind: RegistryKind): void => {\n const list = registrations.get(name);\n if (list) list.push(kind);\n else registrations.set(name, [kind]);\n };\n for (const n of spec.nodes) record(n.kind, 'node');\n for (const u of spec.unions) record(u.name, 'union');\n for (const e of spec.enumerations) record(e.name, 'enumeration');\n\n for (const [name, kinds] of registrations) {\n if (kinds.length > 1) errors.push(formatCollisionError(name, kinds));\n }\n\n // Per-node validation.\n for (const n of spec.nodes) {\n if (!/^[a-z][A-Za-z0-9]*Node$/.test(n.kind)) {\n errors.push(`Node kind \"${n.kind}\" does not match the camelCase ...Node naming convention.`);\n }\n const seenAttrs = new Set<string>();\n for (const a of n.attributes) {\n if (seenAttrs.has(a.name)) {\n errors.push(`Node \"${n.kind}\" declares attribute \"${a.name}\" more than once.`);\n }\n seenAttrs.add(a.name);\n walkTypeExpr(a.type, expr =>\n checkRef(expr, n.kind, a.name, errors, nodeKinds, unionNames, enumerationNames),\n );\n }\n }\n\n // Union member resolution.\n for (const u of spec.unions) {\n if (u.members.length === 0) {\n errors.push(`Union \"${u.name}\" has no members.`);\n }\n const seenMembers = new Set<string>();\n for (const m of u.members) {\n const key = `${m.kind}:${m.name}`;\n if (seenMembers.has(key)) {\n errors.push(`Union \"${u.name}\" lists member ${key} more than once.`);\n }\n seenMembers.add(key);\n if (m.kind === 'node' && !nodeKinds.has(m.name)) {\n errors.push(`Union \"${u.name}\" references undefined node \"${m.name}\".`);\n }\n if (m.kind === 'union' && !unionNames.has(m.name)) {\n errors.push(`Union \"${u.name}\" references undefined union \"${m.name}\".`);\n }\n }\n }\n\n // nestedTypeNode wrapper sanity.\n for (const wrapper of wrappers) {\n if (!nodeKinds.has(wrapper)) {\n errors.push(`Nested-type-node wrapper \"${wrapper}\" is not a defined node.`);\n }\n }\n\n return errors;\n}\n\nfunction formatCollisionError(name: string, kinds: RegistryKind[]): string {\n const counts = new Map<RegistryKind, number>();\n for (const k of kinds) counts.set(k, (counts.get(k) ?? 0) + 1);\n const breakdown = [...counts.entries()]\n .sort((a, b) => a[0].localeCompare(b[0]))\n .map(([k, n]) => `${n} ${k}${n > 1 ? 's' : ''}`)\n .join(', ');\n return `Name \"${name}\" is registered ${kinds.length} times (${breakdown}); names must be unique across nodes, unions, and enumerations.`;\n}\n\nfunction walkTypeExpr(expr: TypeExpr, visit: (expr: TypeExpr) => void): void {\n visit(expr);\n if (expr.kind === 'array') {\n walkTypeExpr(expr.of, visit);\n } else if (expr.kind === 'tuple') {\n for (const item of expr.items) walkTypeExpr(item, visit);\n }\n}\n\nfunction checkRef(\n expr: TypeExpr,\n nodeKind: string,\n attrName: string,\n errors: string[],\n nodeKinds: Set<string>,\n unionNames: Set<string>,\n enumerationNames: Set<string>,\n): void {\n const where = `Node \"${nodeKind}\", attribute \"${attrName}\":`;\n switch (expr.kind) {\n case 'node':\n if (!nodeKinds.has(expr.name)) {\n errors.push(`${where} references undefined node \"${expr.name}\".`);\n }\n break;\n case 'union':\n if (!unionNames.has(expr.name)) {\n errors.push(`${where} references undefined union \"${expr.name}\".`);\n }\n break;\n case 'enumeration':\n if (!enumerationNames.has(expr.name)) {\n errors.push(`${where} references undefined enumeration \"${expr.name}\".`);\n }\n break;\n case 'nestedTypeNode':\n if (!nodeKinds.has(expr.name)) {\n errors.push(`${where} nestedTypeNode references undefined node \"${expr.name}\".`);\n }\n break;\n default:\n break;\n }\n}\n\n/**\n * Child-detection helper used by codegen, docs, and visitor-table\n * generators.\n *\n * A \"child\" attribute is one whose value contains another node. Specifically,\n * any attribute whose type tree includes a `node`, `nestedTypeNode`, or\n * `union` is treated as a child. Optionality (the `optional` flag on the\n * attribute itself) is orthogonal to this classification.\n */\nexport function isChildAttribute(type: TypeExpr): boolean {\n switch (type.kind) {\n case 'node':\n case 'nestedTypeNode':\n case 'union':\n return true;\n case 'array':\n return isChildAttribute(type.of);\n case 'tuple':\n return type.items.some(isChildAttribute);\n default:\n return false;\n }\n}\n"]}
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
// src/api/attribute.ts
|
|
2
|
+
function attribute(name, type, options = {}) {
|
|
3
|
+
return Object.freeze({
|
|
4
|
+
name,
|
|
5
|
+
type,
|
|
6
|
+
...options.optional ? { optional: true } : {},
|
|
7
|
+
...options.docs !== void 0 ? { docs: options.docs } : {}
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
function optionalAttribute(name, type, options = {}) {
|
|
11
|
+
return attribute(name, type, { ...options, optional: true });
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// src/api/compounds.ts
|
|
15
|
+
function array(inner) {
|
|
16
|
+
return Object.freeze({ kind: "array", of: inner });
|
|
17
|
+
}
|
|
18
|
+
function tuple(...items) {
|
|
19
|
+
return Object.freeze({ kind: "tuple", items: Object.freeze([...items]) });
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// src/api/defineEnumeration.ts
|
|
23
|
+
function variant(name, options = {}) {
|
|
24
|
+
return Object.freeze({
|
|
25
|
+
name,
|
|
26
|
+
...options.docs !== void 0 ? { docs: options.docs } : {}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
function defineEnumeration(name, options) {
|
|
30
|
+
if (options.variants.length === 0) {
|
|
31
|
+
throw new Error(`defineEnumeration("${name}"): variants must be non-empty`);
|
|
32
|
+
}
|
|
33
|
+
const seen = /* @__PURE__ */ new Set();
|
|
34
|
+
for (const v of options.variants) {
|
|
35
|
+
if (seen.has(v.name)) {
|
|
36
|
+
throw new Error(`defineEnumeration("${name}"): duplicate variant "${v.name}"`);
|
|
37
|
+
}
|
|
38
|
+
seen.add(v.name);
|
|
39
|
+
}
|
|
40
|
+
return Object.freeze({
|
|
41
|
+
name,
|
|
42
|
+
variants: Object.freeze([...options.variants]),
|
|
43
|
+
...options.docs !== void 0 ? { docs: options.docs } : {}
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// src/api/defineNode.ts
|
|
48
|
+
function defineNode(kind, options) {
|
|
49
|
+
return Object.freeze({
|
|
50
|
+
kind,
|
|
51
|
+
...options.docs !== void 0 ? { docs: options.docs } : {},
|
|
52
|
+
attributes: Object.freeze([...options.attributes]),
|
|
53
|
+
examples: Object.freeze([...options.examples ?? []])
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// src/api/defineUnion.ts
|
|
58
|
+
function defineUnion(name, options) {
|
|
59
|
+
const normalised = options.members.map(normaliseMember);
|
|
60
|
+
return Object.freeze({
|
|
61
|
+
name,
|
|
62
|
+
members: Object.freeze(normalised),
|
|
63
|
+
...options.docs !== void 0 ? { docs: options.docs } : {}
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
function normaliseMember(input) {
|
|
67
|
+
if (typeof input === "string") {
|
|
68
|
+
return Object.freeze({ kind: "node", name: input });
|
|
69
|
+
}
|
|
70
|
+
if (input.kind === "node") return Object.freeze({ kind: "node", name: input.name });
|
|
71
|
+
if (input.kind === "union") return Object.freeze({ kind: "union", name: input.name });
|
|
72
|
+
throw new Error(
|
|
73
|
+
`defineUnion: members must be node kind strings, node(...) or union(...) references; got ${JSON.stringify(input)}`
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// src/api/primitives.ts
|
|
78
|
+
function string() {
|
|
79
|
+
return Object.freeze({ kind: "string" });
|
|
80
|
+
}
|
|
81
|
+
function stringIdentifier() {
|
|
82
|
+
return Object.freeze({ kind: "string", constraint: "identifier" });
|
|
83
|
+
}
|
|
84
|
+
function stringVersion() {
|
|
85
|
+
return Object.freeze({ kind: "string", constraint: "version" });
|
|
86
|
+
}
|
|
87
|
+
function codamaVersion() {
|
|
88
|
+
return Object.freeze({ kind: "codamaVersion" });
|
|
89
|
+
}
|
|
90
|
+
var integer = (width) => Object.freeze({ kind: "integer", width });
|
|
91
|
+
var u8 = () => integer("u8");
|
|
92
|
+
var u16 = () => integer("u16");
|
|
93
|
+
var u32 = () => integer("u32");
|
|
94
|
+
var u64 = () => integer("u64");
|
|
95
|
+
var u128 = () => integer("u128");
|
|
96
|
+
var i8 = () => integer("i8");
|
|
97
|
+
var i16 = () => integer("i16");
|
|
98
|
+
var i32 = () => integer("i32");
|
|
99
|
+
var i64 = () => integer("i64");
|
|
100
|
+
var i128 = () => integer("i128");
|
|
101
|
+
var float = (width) => Object.freeze({ kind: "float", width });
|
|
102
|
+
var f32 = () => float("f32");
|
|
103
|
+
var f64 = () => float("f64");
|
|
104
|
+
function boolean() {
|
|
105
|
+
return Object.freeze({ kind: "boolean" });
|
|
106
|
+
}
|
|
107
|
+
function literal(value) {
|
|
108
|
+
return Object.freeze({ kind: "literal", value });
|
|
109
|
+
}
|
|
110
|
+
function literalUnion(...values) {
|
|
111
|
+
if (values.length === 0) {
|
|
112
|
+
throw new Error("literalUnion: at least one value required");
|
|
113
|
+
}
|
|
114
|
+
const seen = /* @__PURE__ */ new Set();
|
|
115
|
+
for (const v of values) {
|
|
116
|
+
if (seen.has(v)) {
|
|
117
|
+
throw new Error(`literalUnion: duplicate value ${JSON.stringify(v)}`);
|
|
118
|
+
}
|
|
119
|
+
seen.add(v);
|
|
120
|
+
}
|
|
121
|
+
return Object.freeze({ kind: "literalUnion", values: Object.freeze([...values]) });
|
|
122
|
+
}
|
|
123
|
+
function enumeration(name) {
|
|
124
|
+
return Object.freeze({ kind: "enumeration", name });
|
|
125
|
+
}
|
|
126
|
+
function node(name) {
|
|
127
|
+
return Object.freeze({ kind: "node", name });
|
|
128
|
+
}
|
|
129
|
+
function union(name) {
|
|
130
|
+
return Object.freeze({ kind: "union", name });
|
|
131
|
+
}
|
|
132
|
+
function nestedTypeNode(name) {
|
|
133
|
+
return Object.freeze({ kind: "nestedTypeNode", name });
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// src/api/semanticAliases.ts
|
|
137
|
+
function byteSize() {
|
|
138
|
+
return u64();
|
|
139
|
+
}
|
|
140
|
+
function byteOffset() {
|
|
141
|
+
return i64();
|
|
142
|
+
}
|
|
143
|
+
function count() {
|
|
144
|
+
return u32();
|
|
145
|
+
}
|
|
146
|
+
function docs() {
|
|
147
|
+
return Object.freeze({ kind: "docs" });
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// src/api/validate.ts
|
|
151
|
+
function validate(spec) {
|
|
152
|
+
const errors = [];
|
|
153
|
+
const nodeKinds = new Set(spec.nodes.map((n) => n.kind));
|
|
154
|
+
const unionNames = new Set(spec.unions.map((u) => u.name));
|
|
155
|
+
const enumerationNames = new Set(spec.enumerations.map((e) => e.name));
|
|
156
|
+
const wrappers = new Set(spec.nestedTypeNodeWrappers);
|
|
157
|
+
const registrations = /* @__PURE__ */ new Map();
|
|
158
|
+
const record = (name, kind) => {
|
|
159
|
+
const list = registrations.get(name);
|
|
160
|
+
if (list) list.push(kind);
|
|
161
|
+
else registrations.set(name, [kind]);
|
|
162
|
+
};
|
|
163
|
+
for (const n of spec.nodes) record(n.kind, "node");
|
|
164
|
+
for (const u of spec.unions) record(u.name, "union");
|
|
165
|
+
for (const e of spec.enumerations) record(e.name, "enumeration");
|
|
166
|
+
for (const [name, kinds] of registrations) {
|
|
167
|
+
if (kinds.length > 1) errors.push(formatCollisionError(name, kinds));
|
|
168
|
+
}
|
|
169
|
+
for (const n of spec.nodes) {
|
|
170
|
+
if (!/^[a-z][A-Za-z0-9]*Node$/.test(n.kind)) {
|
|
171
|
+
errors.push(`Node kind "${n.kind}" does not match the camelCase ...Node naming convention.`);
|
|
172
|
+
}
|
|
173
|
+
const seenAttrs = /* @__PURE__ */ new Set();
|
|
174
|
+
for (const a of n.attributes) {
|
|
175
|
+
if (seenAttrs.has(a.name)) {
|
|
176
|
+
errors.push(`Node "${n.kind}" declares attribute "${a.name}" more than once.`);
|
|
177
|
+
}
|
|
178
|
+
seenAttrs.add(a.name);
|
|
179
|
+
walkTypeExpr(
|
|
180
|
+
a.type,
|
|
181
|
+
(expr) => checkRef(expr, n.kind, a.name, errors, nodeKinds, unionNames, enumerationNames)
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
for (const u of spec.unions) {
|
|
186
|
+
if (u.members.length === 0) {
|
|
187
|
+
errors.push(`Union "${u.name}" has no members.`);
|
|
188
|
+
}
|
|
189
|
+
const seenMembers = /* @__PURE__ */ new Set();
|
|
190
|
+
for (const m of u.members) {
|
|
191
|
+
const key = `${m.kind}:${m.name}`;
|
|
192
|
+
if (seenMembers.has(key)) {
|
|
193
|
+
errors.push(`Union "${u.name}" lists member ${key} more than once.`);
|
|
194
|
+
}
|
|
195
|
+
seenMembers.add(key);
|
|
196
|
+
if (m.kind === "node" && !nodeKinds.has(m.name)) {
|
|
197
|
+
errors.push(`Union "${u.name}" references undefined node "${m.name}".`);
|
|
198
|
+
}
|
|
199
|
+
if (m.kind === "union" && !unionNames.has(m.name)) {
|
|
200
|
+
errors.push(`Union "${u.name}" references undefined union "${m.name}".`);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
for (const wrapper of wrappers) {
|
|
205
|
+
if (!nodeKinds.has(wrapper)) {
|
|
206
|
+
errors.push(`Nested-type-node wrapper "${wrapper}" is not a defined node.`);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return errors;
|
|
210
|
+
}
|
|
211
|
+
function formatCollisionError(name, kinds) {
|
|
212
|
+
const counts = /* @__PURE__ */ new Map();
|
|
213
|
+
for (const k of kinds) counts.set(k, (counts.get(k) ?? 0) + 1);
|
|
214
|
+
const breakdown = [...counts.entries()].sort((a, b) => a[0].localeCompare(b[0])).map(([k, n]) => `${n} ${k}${n > 1 ? "s" : ""}`).join(", ");
|
|
215
|
+
return `Name "${name}" is registered ${kinds.length} times (${breakdown}); names must be unique across nodes, unions, and enumerations.`;
|
|
216
|
+
}
|
|
217
|
+
function walkTypeExpr(expr, visit) {
|
|
218
|
+
visit(expr);
|
|
219
|
+
if (expr.kind === "array") {
|
|
220
|
+
walkTypeExpr(expr.of, visit);
|
|
221
|
+
} else if (expr.kind === "tuple") {
|
|
222
|
+
for (const item of expr.items) walkTypeExpr(item, visit);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
function checkRef(expr, nodeKind, attrName, errors, nodeKinds, unionNames, enumerationNames) {
|
|
226
|
+
const where = `Node "${nodeKind}", attribute "${attrName}":`;
|
|
227
|
+
switch (expr.kind) {
|
|
228
|
+
case "node":
|
|
229
|
+
if (!nodeKinds.has(expr.name)) {
|
|
230
|
+
errors.push(`${where} references undefined node "${expr.name}".`);
|
|
231
|
+
}
|
|
232
|
+
break;
|
|
233
|
+
case "union":
|
|
234
|
+
if (!unionNames.has(expr.name)) {
|
|
235
|
+
errors.push(`${where} references undefined union "${expr.name}".`);
|
|
236
|
+
}
|
|
237
|
+
break;
|
|
238
|
+
case "enumeration":
|
|
239
|
+
if (!enumerationNames.has(expr.name)) {
|
|
240
|
+
errors.push(`${where} references undefined enumeration "${expr.name}".`);
|
|
241
|
+
}
|
|
242
|
+
break;
|
|
243
|
+
case "nestedTypeNode":
|
|
244
|
+
if (!nodeKinds.has(expr.name)) {
|
|
245
|
+
errors.push(`${where} nestedTypeNode references undefined node "${expr.name}".`);
|
|
246
|
+
}
|
|
247
|
+
break;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
function isChildAttribute(type) {
|
|
251
|
+
switch (type.kind) {
|
|
252
|
+
case "node":
|
|
253
|
+
case "nestedTypeNode":
|
|
254
|
+
case "union":
|
|
255
|
+
return true;
|
|
256
|
+
case "array":
|
|
257
|
+
return isChildAttribute(type.of);
|
|
258
|
+
case "tuple":
|
|
259
|
+
return type.items.some(isChildAttribute);
|
|
260
|
+
default:
|
|
261
|
+
return false;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
export { array, attribute, boolean, byteOffset, byteSize, codamaVersion, count, defineEnumeration, defineNode, defineUnion, docs, enumeration, f32, f64, i128, i16, i32, i64, i8, isChildAttribute, literal, literalUnion, nestedTypeNode, node, optionalAttribute, string, stringIdentifier, stringVersion, tuple, u128, u16, u32, u64, u8, union, validate, variant };
|
|
266
|
+
//# sourceMappingURL=api.browser.mjs.map
|
|
267
|
+
//# sourceMappingURL=api.browser.mjs.map
|