@hey-api/codegen-core 0.3.3 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,431 +1,575 @@
1
- //#region src/bimap/types.d.ts
1
+
2
+ import colors from "ansi-colors";
3
+
4
+ //#region src/refs/types.d.ts
5
+
2
6
  /**
3
- * Bi-directional map interface.
7
+ * Ref wrapper which ensures a stable reference for a value.
4
8
  *
5
- * Keys map to values and values map back to keys.
9
+ * @example
10
+ * ```ts
11
+ * type NumRef = Ref<number>; // { '~ref': number }
12
+ * const num: NumRef = { '~ref': 42 };
13
+ * console.log(num['~ref']); // 42
14
+ * ```
15
+ */
16
+ type Ref<T> = T extends {
17
+ ['~ref']: unknown;
18
+ } ? T : {
19
+ '~ref': T;
20
+ };
21
+ /**
22
+ * Maps every property of `T` to a `Ref` of that property.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * type Foo = { a: number; b: string };
27
+ * type Refs = Refs<Foo>; // { a: Ref<number>; b: Ref<string> }
28
+ * const refs: Refs = { a: { '~ref': 1 }, b: { '~ref': 'x' } };
29
+ * console.log(refs.a['~ref'], refs.b['~ref']); // 1 'x'
30
+ * ```
31
+ */
32
+ type Refs<T> = { [K in keyof T]: Ref<T[K]> };
33
+ /**
34
+ * Unwraps a Ref to its value type.
35
+ *
36
+ * @example
37
+ * ```ts
38
+ * type N = FromRef<{ '~ref': number }>; // number
39
+ * ```
40
+ */
41
+ type FromRef<T> = T extends {
42
+ '~ref': infer U;
43
+ } ? U : T;
44
+ /**
45
+ * Maps every property of a Ref-wrapped object back to its plain value.
46
+ *
47
+ * @example
48
+ * ```ts
49
+ * type Foo = { a: number; b: string };
50
+ * type Refs = Refs<Foo>; // { a: Ref<number>; b: Ref<string> }
51
+ * type Foo2 = FromRefs<Refs>; // { a: number; b: string }
52
+ * ```
53
+ */
54
+ type FromRefs<T> = { [K in keyof T]: T[K] extends Ref<infer U> ? U : T[K] };
55
+ //#endregion
56
+ //#region src/extensions.d.ts
57
+ /**
58
+ * Arbitrary metadata passed to the project's render function.
6
59
  *
7
- * @template Key Type of the map keys
8
- * @template Value Type of the map values
60
+ * Implementers should extend this interface for their own needs.
9
61
  */
10
- interface IBiMap<Key, Value> {
62
+ interface IProjectRenderMeta {
63
+ [key: string]: unknown;
64
+ }
65
+ /**
66
+ * Additional metadata about the symbol.
67
+ *
68
+ * Implementers should extend this interface for their own needs.
69
+ */
70
+ interface ISymbolMeta {
71
+ [key: string]: unknown;
72
+ }
73
+ //#endregion
74
+ //#region src/nodes/node.d.ts
75
+ type MaybeRef<T> = T | Ref<T>;
76
+ type NodeName = MaybeRef<Symbol | string | number>;
77
+ type NodeNameSanitizer = (name: string) => string;
78
+ type NodeRelationship = 'container' | 'reference';
79
+ type NodeScope = 'type' | 'value';
80
+ interface INode<T = unknown> {
81
+ /** Perform semantic analysis. */
82
+ analyze(ctx: IAnalysisContext): void;
83
+ /** Create a shallow copy of this node. */
84
+ clone(): this;
85
+ /** Whether this node is exported from its file. */
86
+ exported?: boolean;
87
+ /** The file this node belongs to. */
88
+ file?: File;
89
+ /** The programming language associated with this node */
90
+ language: Language;
91
+ /** The display name of this node. */
92
+ readonly name: Ref<NodeName> & {
93
+ set(value: NodeName): void;
94
+ toString(): string;
95
+ };
96
+ /** Optional function to sanitize the node name. */
97
+ readonly nameSanitizer?: NodeNameSanitizer;
98
+ /** Whether this node is a root node in the file. */
99
+ root?: boolean;
100
+ /** The scope of this node. */
101
+ scope?: NodeScope;
102
+ /** Semantic children in the structure hierarchy. */
103
+ structuralChildren?: Map<INode, NodeRelationship>;
104
+ /** Semantic parents in the structure hierarchy. */
105
+ structuralParents?: Map<INode, NodeRelationship>;
106
+ /** The symbol associated with this node. */
107
+ symbol?: Symbol;
108
+ /** Convert this node into AST representation. */
109
+ toAst(): T;
110
+ /** Brand used for renderer dispatch. */
111
+ readonly '~brand': string;
112
+ }
113
+ //#endregion
114
+ //#region src/symbols/types.d.ts
115
+ type BindingKind = 'default' | 'named' | 'namespace';
116
+ type ISymbolIdentifier = number | ISymbolMeta;
117
+ type SymbolKind = 'class' | 'enum' | 'function' | 'interface' | 'namespace' | 'type' | 'var';
118
+ type ISymbolIn = {
11
119
  /**
12
- * Deletes a key and its associated value from the map.
120
+ * Array of file names (without extensions) from which this symbol is re-exported.
13
121
  *
14
- * @param key The key to delete.
122
+ * @default undefined
15
123
  */
16
- delete(key: Key): boolean;
124
+ exportFrom?: ReadonlyArray<string>;
17
125
  /**
18
- * Deletes a value and its associated key from the map.
126
+ * Whether this symbol is exported from its own file.
19
127
  *
20
- * @param value The value to delete.
128
+ * @default false
21
129
  */
22
- deleteValue(value: Value): boolean;
130
+ exported?: boolean;
23
131
  /**
24
- * Returns an iterator of [key, value] pairs.
132
+ * External module name if this symbol is imported from a module not managed
133
+ * by the project (e.g. "zod", "lodash").
134
+ *
135
+ * @default undefined
25
136
  */
26
- entries(): IterableIterator<[Key, Value]>;
137
+ external?: string;
27
138
  /**
28
- * Gets the value associated with a key.
139
+ * Optional output strategy to override default behavior.
29
140
  *
30
- * @param key The key to look up.
141
+ * @returns The file path to output the symbol to, or undefined to fallback to default behavior.
31
142
  */
32
- get(key: Key): Value | undefined;
143
+ getFilePath?: Symbol['getFilePath'];
33
144
  /**
34
- * Gets the key associated with a value.
145
+ * Kind of import if this symbol represents an import.
35
146
  *
36
- * @param value The value to look up.
147
+ * @default 'named'
37
148
  */
38
- getKey(value: Value): Key | undefined;
149
+ importKind?: BindingKind;
39
150
  /**
40
- * Checks if a key exists in the map.
151
+ * Kind of symbol.
41
152
  *
42
- * @param key The key to check.
153
+ * @default 'var'
43
154
  */
44
- hasKey(key: Key): boolean;
155
+ kind?: SymbolKind;
45
156
  /**
46
- * Checks if a value exists in the map.
157
+ * Arbitrary metadata about the symbol.
47
158
  *
48
- * @param value The value to check.
159
+ * @default undefined
49
160
  */
50
- hasValue(value: Value): boolean;
161
+ meta?: ISymbolMeta;
51
162
  /**
52
- * Returns an iterator of keys.
163
+ * The intended, user-facing name of the symbol before any conflict resolution.
164
+ * It is **not** guaranteed to be the final emitted name — aliasing may occur if the
165
+ * file contains conflicting local identifiers or other symbols with the same intended name.
166
+ *
167
+ * @example "UserModel"
53
168
  */
54
- keys(): IterableIterator<Key>;
169
+ name: string;
170
+ };
171
+ interface ISymbolRegistry {
55
172
  /**
56
- * Sets a key-value pair in the map.
173
+ * Get a symbol.
57
174
  *
58
- * @param key The key.
59
- * @param value The value.
60
- * @returns This instance for chaining.
175
+ * @param identifier Symbol identifier to reference.
176
+ * @returns The symbol, or undefined if not found.
61
177
  */
62
- set(key: Key, value: Value): this;
178
+ get(identifier: ISymbolIdentifier): Symbol | undefined;
63
179
  /**
64
- * Number of key-value pairs in the map.
180
+ * Returns whether a symbol is registered in the registry.
181
+ *
182
+ * @param identifier Symbol identifier to check.
183
+ * @returns True if the symbol is registered, false otherwise.
65
184
  */
66
- readonly size: number;
185
+ isRegistered(identifier: ISymbolIdentifier): boolean;
67
186
  /**
68
- * Returns an iterator of values.
187
+ * Returns the current symbol ID and increments it.
188
+ *
189
+ * @returns Symbol ID before being incremented.
69
190
  */
70
- values(): IterableIterator<Value>;
191
+ readonly nextId: number;
71
192
  /**
72
- * Enables iteration with `for...of`.
193
+ * Queries symbols by metadata filter.
194
+ *
195
+ * @param filter Metadata filter to query symbols by.
196
+ * @returns Array of symbols matching the filter.
73
197
  */
74
- [Symbol.iterator](): IterableIterator<[Key, Value]>;
75
- }
76
- //#endregion
77
- //#region src/bindings/types.d.ts
78
- interface IBinding {
198
+ query(filter: ISymbolMeta): ReadonlyArray<Symbol>;
79
199
  /**
80
- * Optional aliasing map for named symbols.
81
- *
82
- * Keys must be a subset of `names`, values are aliases.
200
+ * References a symbol.
83
201
  *
84
- * @example { User: "ImportedUser" }
202
+ * @param meta Metadata filter to reference symbol by.
203
+ * @returns The referenced symbol.
85
204
  */
86
- aliases?: Record<string, string>;
205
+ reference(meta: ISymbolMeta): Symbol;
87
206
  /**
88
- * Name of the default binding, if any.
207
+ * Register a symbol globally.
208
+ *
209
+ * Deduplicates identical symbols by ID.
89
210
  *
90
- * @example "React"
211
+ * @param symbol Symbol to register.
212
+ * @returns The registered symbol.
91
213
  */
92
- defaultBinding?: string;
214
+ register(symbol: ISymbolIn): Symbol;
93
215
  /**
94
- * Source file or external module from which symbols are imported.
216
+ * Get all symbols in the order they were registered.
95
217
  *
96
- * @example "./models/user"
97
- * @example "node:path"
218
+ * @returns Array of all registered symbols, in insert order.
98
219
  */
99
- from: string;
220
+ registered(): IterableIterator<Symbol>;
221
+ }
222
+ //#endregion
223
+ //#region src/symbols/symbol.d.ts
224
+ declare class Symbol<Node extends INode = INode> {
100
225
  /**
101
- * Names of the symbols imported from the source.
102
- *
103
- * Must be non-empty unless `namespaceBinding` is true.
104
- * All imported names, regardless of whether they are used as types or values.
226
+ * Canonical symbol this stub resolves to, if any.
105
227
  *
106
- * @example ["User", "UserDTO"]
228
+ * Stubs created during DSL construction may later be associated
229
+ * with a fully registered symbol. Once set, all property lookups
230
+ * should defer to the canonical symbol.
107
231
  */
108
- names?: ReadonlyArray<string>;
232
+ private _canonical?;
109
233
  /**
110
- * If this import is a namespace import (e.g. `import * as ns from "..."`),
111
- * this should be the namespace alias. Set to `true` if no alias is needed.
234
+ * True if this symbol is exported from its defining file.
112
235
  *
113
- * @example "utils"
114
- * @example true
236
+ * @default false
115
237
  */
116
- namespaceBinding?: boolean | string;
238
+ private _exported;
117
239
  /**
118
- * Whether the default binding is type-only.
240
+ * Names of files (without extension) from which this symbol is re-exported.
119
241
  *
120
- * @example true
242
+ * @default []
121
243
  */
122
- typeDefaultBinding?: boolean;
244
+ private _exportFrom;
123
245
  /**
124
- * Subset of `names` that are imported using the `type` modifier.
125
- * These symbols will be emitted as type-only imports in TypeScript.
246
+ * External module name if this symbol is imported from a module not managed
247
+ * by the project (e.g. "zod", "lodash").
126
248
  *
127
- * @example ["UserDTO"]
249
+ * @default undefined
128
250
  */
129
- typeNames?: ReadonlyArray<string>;
251
+ private _external?;
130
252
  /**
131
- * Whether the namespace binding is type-only.
253
+ * The file this symbol is ultimately emitted into.
132
254
  *
133
- * @example true
255
+ * Only top-level symbols have an assigned file.
134
256
  */
135
- typeNamespaceBinding?: boolean;
136
- }
137
- //#endregion
138
- //#region src/files/types.d.ts
139
- /**
140
- * Selector array used to reference files.
141
- *
142
- * @example ["foo", "bar"]
143
- */
144
- type IFileSelector = ReadonlyArray<string>;
145
- type IFileIdentifier = number | IFileSelector;
146
- type IFileIn = {
257
+ private _file?;
147
258
  /**
148
- * File extension, if any.
259
+ * The alias-resolved, conflict-free emitted name.
149
260
  */
150
- extension?: string;
261
+ private _finalName?;
151
262
  /**
152
- * Indicates whether the file is external, meaning it is not generated
153
- * as part of the project but is referenced (e.g., a module from
154
- * node_modules).
263
+ * Custom strategy to determine file output path.
155
264
  *
156
- * @example true
265
+ * @returns The file path to output the symbol to, or undefined to fallback to default behavior.
157
266
  */
158
- external?: boolean;
267
+ private _getFilePath?;
159
268
  /**
160
- * Unique file ID. If one is not provided, it will be auto-generated.
269
+ * How this symbol should be imported (namespace/default/named).
270
+ *
271
+ * @default 'named'
161
272
  */
162
- readonly id?: number;
273
+ private _importKind;
163
274
  /**
164
- * The desired name for the file within the project. If there are multiple files
165
- * with the same desired name, this might not end up being the actual name.
275
+ * Kind of symbol (class, type, alias, etc.).
166
276
  *
167
- * @example "UserModel"
277
+ * @default 'var'
168
278
  */
169
- name?: string;
279
+ private _kind;
170
280
  /**
171
- * Absolute logical output path for the file.
281
+ * Arbitrary user metadata.
172
282
  *
173
- * @example "/src/models/user.ts"
283
+ * @default undefined
174
284
  */
175
- path?: string;
285
+ private _meta?;
176
286
  /**
177
- * Selector array used to select this file.
287
+ * Intended user-facing name before conflict resolution.
178
288
  *
179
- * @example ["foo", "bar"]
289
+ * @example "UserModel"
180
290
  */
181
- readonly selector?: IFileSelector;
182
- };
183
- type IFileOut = IFileIn & {
291
+ private _name;
184
292
  /**
185
- * Unique file ID.
293
+ * Node that defines this symbol.
186
294
  */
295
+ private _node?;
296
+ /** Brand used for identifying symbols. */
297
+ readonly '~brand' = "heyapi.symbol";
298
+ /** Globally unique, stable symbol ID. */
187
299
  readonly id: number;
300
+ constructor(input: ISymbolIn, id: number);
188
301
  /**
189
- * Map holding resolved names for symbols in this file.
190
- */
191
- readonly resolvedNames: IBiMap<number, string>;
192
- /**
193
- * Symbols in this file, categorized by their role.
194
- */
195
- readonly symbols: {
196
- /**
197
- * Symbols declared in the body of this file.
198
- */
199
- body: Array<number>;
200
- /**
201
- * Symbols re-exported from other files.
202
- */
203
- exports: Array<number>;
204
- /**
205
- * Symbols imported from other files.
206
- */
207
- imports: Array<number>;
208
- };
209
- };
210
- interface IFileRegistry {
211
- /**
212
- * Get a file.
302
+ * Returns the canonical symbol for this instance.
213
303
  *
214
- * @param identifier File identifier to reference.
215
- * @returns The file, or undefined if not found.
304
+ * If this symbol was created as a stub, this getter returns
305
+ * the fully registered canonical symbol. Otherwise, it returns
306
+ * the symbol itself.
216
307
  */
217
- get(identifier: IFileIdentifier): IFileOut | undefined;
308
+ get canonical(): Symbol;
218
309
  /**
219
- * Returns the current file ID and increments it.
220
- *
221
- * @returns File ID before being incremented
310
+ * Indicates whether this symbol is exported from its defining file.
222
311
  */
223
- readonly id: number;
312
+ get exported(): boolean;
224
313
  /**
225
- * Returns whether a file is registered in the registry.
226
- *
227
- * @param identifier File identifier to check.
228
- * @returns True if the file is registered, false otherwise.
314
+ * Names of files (without extension) that re-export this symbol.
229
315
  */
230
- isRegistered(identifier: IFileIdentifier): boolean;
316
+ get exportFrom(): ReadonlyArray<string>;
231
317
  /**
232
- * Returns a file by identifier, registering it if it doesn't exist.
233
- *
234
- * @param identifier File identifier to reference.
235
- * @returns The referenced or newly registered file.
318
+ * External module from which this symbol originates, if any.
236
319
  */
237
- reference(identifier: IFileIdentifier): IFileOut;
320
+ get external(): string | undefined;
238
321
  /**
239
- * Get all unregistered files in the order they were referenced.
322
+ * Read‑only accessor for the assigned output file.
240
323
  *
241
- * @returns Array of all unregistered files, in reference order.
324
+ * Only top-level symbols have an assigned file.
242
325
  */
243
- referenced(): IterableIterator<IFileOut>;
326
+ get file(): File | undefined;
244
327
  /**
245
- * Register a file globally.
328
+ * Read‑only accessor for the resolved final emitted name.
329
+ */
330
+ get finalName(): string;
331
+ /**
332
+ * Custom file path resolver, if provided.
333
+ */
334
+ get getFilePath(): ((symbol: Symbol) => string | undefined) | undefined;
335
+ /**
336
+ * How this symbol should be imported (named/default/namespace).
337
+ */
338
+ get importKind(): BindingKind;
339
+ /**
340
+ * Indicates whether this is a canonical symbol (not a stub).
341
+ */
342
+ get isCanonical(): boolean;
343
+ /**
344
+ * The symbol's kind (class, type, alias, variable, etc.).
345
+ */
346
+ get kind(): SymbolKind;
347
+ /**
348
+ * Arbitrary user‑provided metadata associated with this symbol.
349
+ */
350
+ get meta(): ISymbolMeta | undefined;
351
+ /**
352
+ * User-intended name before aliasing or conflict resolution.
353
+ */
354
+ get name(): string;
355
+ /**
356
+ * Read‑only accessor for the defining node.
357
+ */
358
+ get node(): Node | undefined;
359
+ /**
360
+ * Marks this symbol as a stub and assigns its canonical symbol.
246
361
  *
247
- * Deduplicates identical files by ID.
362
+ * After calling this, all semantic queries (name, kind, file,
363
+ * meta, etc.) should reflect the canonical symbol's values.
248
364
  *
249
- * @param file File to register.
250
- * @returns true if added, false if duplicate.
365
+ * @param symbol The canonical symbol this stub should resolve to.
251
366
  */
252
- register(file: IFileIn): IFileOut;
367
+ setCanonical(symbol: Symbol): void;
253
368
  /**
254
- * Get all files in the order they were registered.
369
+ * Marks the symbol as exported from its file.
255
370
  *
256
- * @returns Array of all registered files, in insert order.
371
+ * @param exported Whether the symbol is exported.
257
372
  */
258
- registered(): IterableIterator<IFileOut>;
259
- }
260
- //#endregion
261
- //#region src/extensions/types.d.ts
262
- /**
263
- * Arbitrary metadata passed to the project's render function.
264
- *
265
- * Implementers should extend this interface for their own needs.
266
- */
267
- interface IProjectRenderMeta {
268
- [key: string]: unknown;
269
- }
270
- /**
271
- * Additional metadata about the symbol.
272
- *
273
- * Implementers should extend this interface for their own needs.
274
- */
275
- interface ISymbolMeta {
276
- [key: string]: unknown;
277
- }
278
- //#endregion
279
- //#region src/symbols/types.d.ts
280
- type ISymbolIdentifier = number | ISymbolMeta;
281
- type ISymbolIn = {
373
+ setExported(exported: boolean): void;
282
374
  /**
283
- * Array of file names (without extensions) from which this symbol is re-exported.
375
+ * Records file names that re‑export this symbol.
284
376
  *
285
- * @default undefined
377
+ * @param list — Source files re‑exporting this symbol.
286
378
  */
287
- exportFrom?: ReadonlyArray<string>;
379
+ setExportFrom(list: ReadonlyArray<string>): void;
288
380
  /**
289
- * Whether this symbol is exported from its own file.
381
+ * Assigns the output file this symbol will be emitted into.
290
382
  *
291
- * @default false
383
+ * This may only be set once.
292
384
  */
293
- exported?: boolean;
385
+ setFile(file: File): void;
294
386
  /**
295
- * External module name if this symbol is imported from a module not managed
296
- * by the project (e.g. "zod", "lodash").
387
+ * Assigns the conflict‑resolved final local name for this symbol.
297
388
  *
298
- * @default undefined
389
+ * This may only be set once.
299
390
  */
300
- external?: string;
391
+ setFinalName(name: string): void;
301
392
  /**
302
- * Optional output strategy to override default behavior.
393
+ * Sets how this symbol should be imported.
303
394
  *
304
- * @returns The file path to output the symbol to, or undefined to fallback to default behavior.
395
+ * @param kind The import strategy (named/default/namespace).
305
396
  */
306
- getFilePath?: (symbol: ISymbolOut) => string | undefined;
397
+ setImportKind(kind: BindingKind): void;
307
398
  /**
308
- * Unique symbol ID. If one is not provided, it will be auto-generated.
399
+ * Sets the symbol's kind (class, type, alias, variable, etc.).
400
+ *
401
+ * @param kind — The new symbol kind.
309
402
  */
310
- readonly id?: number;
403
+ setKind(kind: SymbolKind): void;
311
404
  /**
312
- * Kind of import if this symbol represents an import.
405
+ * Updates the intended user‑facing name for this symbol.
406
+ *
407
+ * @param name — The new name.
313
408
  */
314
- importKind?: 'namespace' | 'default' | 'named';
409
+ setName(name: string): void;
315
410
  /**
316
- * Kind of symbol.
411
+ * Binds the node that defines this symbol.
412
+ *
413
+ * This may only be set once.
317
414
  */
318
- kind?: 'class' | 'function' | 'type';
415
+ setNode(node: Node): void;
319
416
  /**
320
- * Arbitrary metadata about the symbol.
321
- *
322
- * @default undefined
417
+ * Returns a debug‑friendly string representation identifying the symbol.
323
418
  */
324
- meta?: ISymbolMeta;
419
+ toString(): string;
325
420
  /**
326
- * The desired name for the symbol within its file. If there are multiple symbols
327
- * with the same desired name, this might not end up being the actual name.
421
+ * Ensures this symbol is canonical before allowing mutation.
328
422
  *
329
- * @example "UserModel"
423
+ * A symbol that has been marked as a stub (i.e., its `_canonical` points
424
+ * to a different symbol) may not be mutated. This guard throws an error
425
+ * if any setter attempts to modify a stub, preventing accidental writes
426
+ * to non‑canonical instances.
427
+ *
428
+ * @throws {Error} If the symbol is a stub and is being mutated.
330
429
  */
331
- name?: string;
430
+ private assertCanonical;
431
+ }
432
+ //#endregion
433
+ //#region src/planner/scope.d.ts
434
+ type NameScopes = Map<string, Set<SymbolKind>>;
435
+ type Scope = {
436
+ /** Child scopes. */
437
+ children: Array<Scope>;
438
+ /** Resolved names in this scope. */
439
+ localNames: NameScopes;
440
+ /** Parent scope, if any. */
441
+ parent?: Scope;
442
+ /** Symbols registered in this scope. */
443
+ symbols: Array<Ref<Symbol>>;
444
+ };
445
+ //#endregion
446
+ //#region src/planner/types.d.ts
447
+ type Input = Ref<object> | object | string | number | undefined;
448
+ type NameConflictResolver = (args: {
449
+ attempt: number;
450
+ baseName: string;
451
+ }) => string | null;
452
+ interface IAnalysisContext {
453
+ /** Register a dependency on another symbol. */
454
+ addDependency(symbol: Ref<Symbol>): void;
455
+ /** Register a dependency on another symbol or analyze further. */
456
+ analyze(input: Input): void;
457
+ /** Get local names in the current scope. */
458
+ localNames(scope: Scope): NameScopes;
459
+ /** Pop the current local scope. */
460
+ popScope(): void;
461
+ /** Push a new local scope. */
462
+ pushScope(): void;
463
+ /** Current local scope. */
464
+ scope: Scope;
465
+ /** Stack of local name scopes. */
466
+ scopes: Scope;
467
+ /** Top-level symbol for the current analysis pass. */
468
+ symbol?: Symbol;
469
+ /** Walks all symbols in the scope tree in depth-first order. */
470
+ walkScopes(callback: (symbol: Ref<Symbol>, scope: Scope) => void, scope?: Scope): void;
471
+ }
472
+ //#endregion
473
+ //#region src/languages/types.d.ts
474
+ type Extensions = Partial<Record<Language, ReadonlyArray<string>>>;
475
+ type Language = 'c' | 'c#' | 'c++' | 'css' | 'dart' | 'go' | 'haskell' | 'html' | 'java' | 'javascript' | 'json' | 'kotlin' | 'lua' | 'markdown' | 'matlab' | 'perl' | 'php' | 'python' | 'r' | 'ruby' | 'rust' | 'scala' | 'shell' | 'sql' | 'swift' | 'typescript' | 'yaml' | (string & {});
476
+ // other/custom language
477
+
478
+ type NameConflictResolvers = Partial<Record<Language, NameConflictResolver>>;
479
+ //#endregion
480
+ //#region src/files/types.d.ts
481
+ type FileKeyArgs = Pick<Required<File>, 'logicalFilePath'> & Pick<Partial<File>, 'external' | 'language'>;
482
+ type IFileIn = {
332
483
  /**
333
- * Placeholder name for the symbol to be replaced later with the final value.
484
+ * Indicates whether the file is external, meaning it is not generated
485
+ * as part of the project but is referenced (e.g., a module from
486
+ * node_modules).
334
487
  *
335
- * @example "_heyapi_31_"
488
+ * @example true
336
489
  */
337
- readonly placeholder?: string;
338
- };
339
- type ISymbolOut = Omit<ISymbolIn, 'id' | 'placeholder'> & Pick<Required<ISymbolIn>, 'id' | 'placeholder'>;
340
- interface ISymbolRegistry {
490
+ external?: boolean;
341
491
  /**
342
- * Get a symbol.
492
+ * Language of the file.
343
493
  *
344
- * @param identifier Symbol identifier to reference.
345
- * @returns The symbol, or undefined if not found.
494
+ * @example "typescript"
346
495
  */
347
- get(identifier: ISymbolIdentifier): ISymbolOut | undefined;
496
+ language?: Language;
348
497
  /**
349
- * Returns the value associated with a symbol ID.
498
+ * Logical, extension-free path used for planning and routing.
350
499
  *
351
- * @param symbolId Symbol ID.
352
- * @return The value associated with the symbol ID, or undefined if not found.
500
+ * @example "src/models/user"
353
501
  */
354
- getValue(symbolId: number): unknown;
502
+ logicalFilePath: string;
355
503
  /**
356
- * Checks if the registry has a value associated with a symbol ID.
504
+ * The desired name for the file within the project. If there are multiple files
505
+ * with the same desired name, this might not end up being the actual name.
357
506
  *
358
- * @param symbolId Symbol ID.
359
- * @returns True if the registry has a value for symbol ID, false otherwise.
507
+ * @example "UserModel"
360
508
  */
361
- hasValue(symbolId: number): boolean;
509
+ name?: string;
510
+ };
511
+ interface IFileRegistry {
362
512
  /**
363
- * Returns the current symbol ID and increments it.
513
+ * Get a file.
364
514
  *
365
- * @returns Symbol ID before being incremented.
515
+ * @returns The file, or undefined if not found.
366
516
  */
367
- readonly id: number;
517
+ get(args: FileKeyArgs): File | undefined;
368
518
  /**
369
- * Returns whether a symbol is registered in the registry.
519
+ * Returns whether a file is registered in the registry.
370
520
  *
371
- * @param identifier Symbol identifier to check.
372
- * @returns True if the symbol is registered, false otherwise.
521
+ * @returns True if the file is registered, false otherwise.
373
522
  */
374
- isRegistered(identifier: ISymbolIdentifier): boolean;
523
+ isRegistered(args: FileKeyArgs): boolean;
375
524
  /**
376
- * Queries symbols by metadata filter.
525
+ * Returns the current file ID and increments it.
377
526
  *
378
- * @param filter Metadata filter to query symbols by.
379
- * @returns Array of symbols matching the filter.
527
+ * @returns File ID before being incremented
380
528
  */
381
- query(filter: ISymbolMeta): ReadonlyArray<ISymbolOut>;
529
+ readonly nextId: number;
382
530
  /**
383
- * References a symbol.
531
+ * Register a file globally.
384
532
  *
385
- * @param meta Metadata filter to reference symbol by.
386
- * @returns The referenced symbol.
533
+ * @param file File to register.
534
+ * @returns Newly registered file if created, merged file otherwise.
387
535
  */
388
- reference(meta: ISymbolMeta): ISymbolOut;
536
+ register(file: IFileIn): File;
389
537
  /**
390
- * Register a symbol globally.
538
+ * Get all files in the order they were registered.
391
539
  *
392
- * Deduplicates identical symbols by ID.
540
+ * @returns Array of all registered files, in insert order.
541
+ */
542
+ registered(): IterableIterator<File>;
543
+ }
544
+ //#endregion
545
+ //#region src/nodes/types.d.ts
546
+ interface INodeRegistry {
547
+ /**
548
+ * Register a syntax node.
393
549
  *
394
- * @param symbol Symbol to register.
395
- * @returns The registered symbol.
550
+ * @returns The index of the registered node.
396
551
  */
397
- register(symbol: ISymbolIn): ISymbolOut;
552
+ add(node: INode | null): number;
398
553
  /**
399
- * Get all symbols in the order they were registered.
554
+ * All nodes in insertion order.
555
+ */
556
+ all(): Iterable<INode>;
557
+ /**
558
+ * Remove a node by its index.
400
559
  *
401
- * @returns Array of all registered symbols, in insert order.
560
+ * @param index Index of the node to remove.
402
561
  */
403
- registered(): IterableIterator<ISymbolOut>;
562
+ remove(index: number): void;
404
563
  /**
405
- * Sets a value for a symbol by its ID.
564
+ * Update a node at the given index.
406
565
  *
407
- * @param symbolId Symbol ID.
408
- * @param value The value to set.
409
- * @returns void
566
+ * @param index Index of the node to update.
567
+ * @param node New node to set.
410
568
  */
411
- setValue(symbolId: number, value: unknown): Map<number, unknown>;
569
+ update(index: number, node: INode | null): void;
412
570
  }
413
571
  //#endregion
414
- //#region src/bindings/utils.d.ts
415
- declare const createBinding: ({
416
- file,
417
- modulePath,
418
- symbol,
419
- symbolFile
420
- }: {
421
- file: IFileOut;
422
- modulePath: string;
423
- symbol: ISymbolOut;
424
- symbolFile: IFileOut;
425
- }) => IBinding;
426
- declare const mergeBindings: (target: IBinding, source: IBinding) => void;
427
- //#endregion
428
- //#region src/output/types.d.ts
572
+ //#region src/output.d.ts
429
573
  interface IOutput {
430
574
  /**
431
575
  * The main content of the file to output.
@@ -443,26 +587,32 @@ interface IOutput {
443
587
  path: string;
444
588
  }
445
589
  //#endregion
446
- //#region src/files/registry.d.ts
447
- declare class FileRegistry implements IFileRegistry {
448
- private _id;
449
- private referenceOrder;
450
- private registerOrder;
451
- private selectorToId;
452
- private values;
453
- get(identifier: IFileIdentifier): IFileOut | undefined;
454
- get id(): number;
455
- private identifierToFile;
456
- isRegistered(identifier: IFileIdentifier): boolean;
457
- reference(identifier: IFileIdentifier): IFileOut;
458
- referenced(): IterableIterator<IFileOut>;
459
- register(file: IFileIn): IFileOut;
460
- registered(): IterableIterator<IFileOut>;
590
+ //#region src/renderer.d.ts
591
+ interface RenderContext<Node extends INode = INode> {
592
+ /**
593
+ * The current file.
594
+ */
595
+ file: File<Node>;
596
+ /**
597
+ * Arbitrary metadata.
598
+ */
599
+ meta?: IProjectRenderMeta;
600
+ /**
601
+ * The project the file belongs to.
602
+ */
603
+ project: IProject;
604
+ }
605
+ interface Renderer {
606
+ /** Renders the given file. */
607
+ render(ctx: RenderContext): string;
608
+ /** Returns whether this renderer can render the given file. */
609
+ supports(ctx: RenderContext): boolean;
461
610
  }
462
611
  //#endregion
463
612
  //#region src/project/types.d.ts
464
613
  /**
465
- * Represents a code generation project consisting of multiple codegen files.
614
+ * Represents a code generation project consisting of codegen files.
615
+ *
466
616
  * Manages imports, symbols, and output generation across the project.
467
617
  */
468
618
  interface IProject {
@@ -471,18 +621,24 @@ interface IProject {
471
621
  *
472
622
  * @default 'main'
473
623
  */
474
- readonly defaultFileName?: string;
624
+ readonly defaultFileName: string;
625
+ /** Default name conflict resolver used when a file has no specific resolver. */
626
+ readonly defaultNameConflictResolver: NameConflictResolver;
627
+ /** Maps language to array of extensions. First element is used by default. */
628
+ readonly extensions: Extensions;
475
629
  /**
476
- * Optional function to transform file names before they are used.
630
+ * Function to transform file names before they are used.
477
631
  *
478
632
  * @param name The original file name.
479
633
  * @returns The transformed file name.
480
634
  */
481
635
  readonly fileName?: (name: string) => string;
482
- /**
483
- * Centralized file registry for the project.
484
- */
636
+ /** Centralized file registry for the project. */
485
637
  readonly files: IFileRegistry;
638
+ /** Map of language-specific name conflict resolvers for files in the project. */
639
+ readonly nameConflictResolvers: NameConflictResolvers;
640
+ /** Centralized node registry for the project. */
641
+ readonly nodes: INodeRegistry;
486
642
  /**
487
643
  * Produces output representations for all files in the project.
488
644
  *
@@ -493,82 +649,297 @@ interface IProject {
493
649
  */
494
650
  render(meta?: IProjectRenderMeta): ReadonlyArray<IOutput>;
495
651
  /**
496
- * Map of available renderers by file extension.
652
+ * List of available renderers.
497
653
  *
498
654
  * @example
499
- * {
500
- * ".ts": tsRenderer,
501
- * ".js": jsRenderer,
502
- * }
655
+ * [new TypeScriptRenderer()]
503
656
  */
504
- readonly renderers: Record<string, IRenderer>;
657
+ readonly renderers: ReadonlyArray<Renderer>;
658
+ /** The absolute path to the root folder of the project. */
659
+ readonly root: string;
660
+ /** Centralized symbol registry for the project. */
661
+ readonly symbols: ISymbolRegistry;
662
+ }
663
+ //#endregion
664
+ //#region src/files/file.d.ts
665
+ declare class File<Node extends INode = INode> {
505
666
  /**
506
- * The absolute path to the root folder of the project.
667
+ * Exports from this file.
507
668
  */
508
- readonly root: string;
669
+ private _exports;
670
+ /**
671
+ * File extension (e.g. `.ts`).
672
+ */
673
+ private _extension?;
674
+ /**
675
+ * Actual emitted file path, including extension and directories.
676
+ */
677
+ private _finalPath?;
509
678
  /**
510
- * Retrieves files that include symbol ID. The first file is the one
511
- * where the symbol is declared, the rest are files that re-export it.
679
+ * Imports to this file.
680
+ */
681
+ private _imports;
682
+ /**
683
+ * Language of the file.
684
+ */
685
+ private _language?;
686
+ /**
687
+ * Logical, extension-free path used for planning and routing.
688
+ */
689
+ private _logicalFilePath;
690
+ /**
691
+ * Base name of the file (without extension).
692
+ */
693
+ private _name?;
694
+ /**
695
+ * Syntax nodes contained in this file.
696
+ */
697
+ private _nodes;
698
+ /**
699
+ * Renderer assigned to this file.
700
+ */
701
+ private _renderer?;
702
+ /** Brand used for identifying files. */
703
+ readonly '~brand' = "heyapi.file";
704
+ /** All names defined in this file, including local scopes. */
705
+ allNames: NameScopes;
706
+ /** Whether this file is external to the project. */
707
+ external: boolean;
708
+ /** Unique identifier for the file. */
709
+ readonly id: number;
710
+ /** The project this file belongs to. */
711
+ readonly project: IProject;
712
+ /** Names declared at the top level of the file. */
713
+ topLevelNames: NameScopes;
714
+ constructor(input: IFileIn, id: number, project: IProject);
715
+ /**
716
+ * Exports from this file.
717
+ */
718
+ get exports(): ReadonlyArray<ExportModule>;
719
+ /**
720
+ * Read-only accessor for the file extension.
721
+ */
722
+ get extension(): string | undefined;
723
+ /**
724
+ * Read-only accessor for the final emitted path.
512
725
  *
513
- * @param symbolId The symbol ID to find.
514
- * @returns An array of files containing the symbol.
515
- * @example
516
- * const files = project.symbolIdToFiles(31);
517
- * for (const file of files) {
518
- * console.log(file.path);
519
- * }
726
+ * If undefined, the file has not yet been assigned a final path
727
+ * or is external to the project and should not be emitted.
520
728
  */
521
- symbolIdToFiles(symbolId: number): ReadonlyArray<IFileOut>;
729
+ get finalPath(): string | undefined;
522
730
  /**
523
- * Centralized symbol registry for the project.
731
+ * Imports to this file.
524
732
  */
525
- readonly symbols: ISymbolRegistry;
733
+ get imports(): ReadonlyArray<ImportModule>;
734
+ /**
735
+ * Language of the file; inferred from nodes or fallback if not set explicitly.
736
+ */
737
+ get language(): Language | undefined;
738
+ /**
739
+ * Logical, extension-free path used for planning and routing.
740
+ */
741
+ get logicalFilePath(): string;
742
+ /**
743
+ * Base name of the file (without extension).
744
+ *
745
+ * If no name was set explicitly, it is inferred from the logical file path.
746
+ */
747
+ get name(): string;
748
+ /**
749
+ * Syntax nodes contained in this file.
750
+ */
751
+ get nodes(): ReadonlyArray<Node>;
752
+ /**
753
+ * Renderer assigned to this file.
754
+ */
755
+ get renderer(): Renderer | undefined;
756
+ /**
757
+ * Add an export group to the file.
758
+ */
759
+ addExport(group: ExportModule): void;
760
+ /**
761
+ * Add an import group to the file.
762
+ */
763
+ addImport(group: ImportModule): void;
764
+ /**
765
+ * Add a syntax node to the file.
766
+ */
767
+ addNode(node: Node): void;
768
+ /**
769
+ * Sets the file extension.
770
+ */
771
+ setExtension(extension: string): void;
772
+ /**
773
+ * Sets the final emitted path of the file.
774
+ */
775
+ setFinalPath(path: string): void;
776
+ /**
777
+ * Sets the language of the file.
778
+ */
779
+ setLanguage(lang: Language): void;
780
+ /**
781
+ * Sets the name of the file.
782
+ */
783
+ setName(name: string): void;
784
+ /**
785
+ * Sets the renderer assigned to this file.
786
+ */
787
+ setRenderer(renderer: Renderer): void;
788
+ /**
789
+ * Returns a debug‑friendly string representation identifying the file.
790
+ */
791
+ toString(): string;
526
792
  }
527
793
  //#endregion
528
- //#region src/renderer/types.d.ts
529
- interface IRenderer {
794
+ //#region src/bindings.d.ts
795
+ interface ExportMember {
530
796
  /**
531
- * Renders content with replaced symbols.
797
+ * Name under which the symbol is exported in this file.
532
798
  *
533
- * @param content Content to render.
534
- * @param file The file to render.
535
- * @param project The parent project the file belongs to.
536
- * @returns Rendered content.
537
- */
538
- renderFile(content: string, file: IFile, project: IProject, meta?: IProjectRenderMeta): string;
799
+ * export { Foo as Bar } from "./models"
800
+ *
801
+ * exportedName === "Bar"
802
+ */
803
+ exportedName: string;
804
+ /** Whether this export is type-only. */
805
+ isTypeOnly: boolean;
806
+ /** Export flavor. */
807
+ kind: BindingKind;
808
+ /** The exported name of the symbol in its source file. */
809
+ sourceName: string;
810
+ }
811
+ type ExportModule = Pick<ExportMember, 'isTypeOnly'> & {
812
+ /** Whether this module can export all symbols: `export * from 'module'`. */
813
+ canExportAll: boolean;
814
+ /** Members exported from this module. */
815
+ exports: Array<ExportMember>;
816
+ /** Source file. */
817
+ from: File;
818
+ /** Namespace export: `export * as ns from 'module'`. Mutually exclusive with `exports`. */
819
+ namespaceExport?: string;
820
+ };
821
+ interface ImportMember {
822
+ /** Whether this import is type-only. */
823
+ isTypeOnly: boolean;
539
824
  /**
540
- * Returns printable data containing symbols and exports.
825
+ * The name this symbol will have locally in this file.
826
+ * This is where aliasing is applied:
541
827
  *
542
- * @param file The file to render.
543
- * @param project The parent project the file belongs to.
544
- * @param meta Arbitrary metadata.
545
- * @returns Printable string containing symbols and exports.
828
+ * import { Foo as Foo$2 } from "./x"
829
+ *
830
+ * localName === "Foo$2"
546
831
  */
547
- renderSymbols(file: IFileOut, project: IProject, meta?: IProjectRenderMeta): string;
832
+ localName: string;
833
+ /** The exported name of the symbol in its source file. */
834
+ sourceName: string;
835
+ }
836
+ type ImportModule = Pick<ImportMember, 'isTypeOnly'> & Pick<Partial<ImportMember>, 'localName'> & {
837
+ /** Source file. */
838
+ from: File;
839
+ /** List of symbols imported from this module. */
840
+ imports: Array<ImportMember>;
841
+ /** Import flavor. */
842
+ kind: BindingKind;
843
+ };
844
+ //#endregion
845
+ //#region src/brands.d.ts
846
+ declare const nodeBrand = "heyapi.node";
847
+ declare const symbolBrand = "heyapi.symbol";
848
+ //#endregion
849
+ //#region src/guards.d.ts
850
+ declare function isNode(value: unknown): value is INode;
851
+ declare function isNodeRef(value: Ref<unknown>): value is Ref<INode>;
852
+ declare function isSymbol(value: unknown): value is Symbol;
853
+ declare function isSymbolRef(value: Ref<unknown>): value is Ref<Symbol>;
854
+ //#endregion
855
+ //#region src/languages/extensions.d.ts
856
+ declare const defaultExtensions: Extensions;
857
+ //#endregion
858
+ //#region src/languages/resolvers.d.ts
859
+ declare const defaultNameConflictResolvers: NameConflictResolvers;
860
+ //#endregion
861
+ //#region src/log.d.ts
862
+ /**
863
+ * Accepts a value or a readonly array of values of type T.
864
+ */
865
+ type MaybeArray<T> = T | ReadonlyArray<T>;
866
+ /**
867
+ * Accepts a value or a function returning a value.
868
+ */
869
+ type MaybeFunc<T extends (...args: Array<any>) => any> = T | ReturnType<T>;
870
+ declare const DebugGroups: {
871
+ readonly analyzer: colors.StyleFunction;
872
+ readonly dsl: colors.StyleFunction;
873
+ readonly file: colors.StyleFunction;
874
+ readonly registry: colors.StyleFunction;
875
+ readonly symbol: colors.StyleFunction;
876
+ };
877
+ declare const WarnGroups: {
878
+ readonly deprecated: colors.StyleFunction;
879
+ };
880
+ declare function debug(message: string, group: keyof typeof DebugGroups): void;
881
+ declare function warn(message: string, group: keyof typeof WarnGroups): void;
882
+ declare function warnDeprecated({
883
+ context,
884
+ field,
885
+ replacement
886
+ }: {
887
+ context?: string;
888
+ field: string;
889
+ replacement?: MaybeFunc<(field: string) => MaybeArray<string>>;
890
+ }): void;
891
+ declare const log: {
892
+ debug: typeof debug;
893
+ warn: typeof warn;
894
+ warnDeprecated: typeof warnDeprecated;
895
+ };
896
+ //#endregion
897
+ //#region src/planner/resolvers.d.ts
898
+ declare const simpleNameConflictResolver: NameConflictResolver;
899
+ declare const underscoreNameConflictResolver: NameConflictResolver;
900
+ //#endregion
901
+ //#region src/files/registry.d.ts
902
+ type FileId = number;
903
+ declare class FileRegistry implements IFileRegistry {
904
+ private _id;
905
+ private _values;
906
+ private readonly project;
907
+ constructor(project: IProject);
908
+ get(args: FileKeyArgs): File | undefined;
909
+ isRegistered(args: FileKeyArgs): boolean;
910
+ get nextId(): FileId;
911
+ register(file: IFileIn): File;
912
+ registered(): IterableIterator<File>;
913
+ private createFileKey;
914
+ }
915
+ //#endregion
916
+ //#region src/nodes/registry.d.ts
917
+ declare class NodeRegistry implements INodeRegistry {
918
+ private list;
919
+ add(node: INode | null): number;
920
+ all(): Iterable<INode>;
921
+ remove(index: number): void;
922
+ update(index: number, node: INode | null): void;
548
923
  }
549
924
  //#endregion
550
925
  //#region src/symbols/registry.d.ts
551
926
  type SymbolId = number;
552
927
  declare class SymbolRegistry implements ISymbolRegistry {
553
928
  private _id;
554
- private indices;
555
- private nodes;
556
- private queryCache;
557
- private queryCacheDependencies;
558
- private registerOrder;
559
- private stubCache;
560
- private stubs;
561
- private values;
562
- get(identifier: ISymbolIdentifier): ISymbolOut | undefined;
563
- getValue(symbolId: SymbolId): unknown;
564
- hasValue(symbolId: SymbolId): boolean;
565
- get id(): SymbolId;
929
+ private _indices;
930
+ private _queryCache;
931
+ private _queryCacheDependencies;
932
+ private _registered;
933
+ private _stubs;
934
+ private _stubCache;
935
+ private _values;
936
+ get(identifier: ISymbolIdentifier): Symbol | undefined;
566
937
  isRegistered(identifier: ISymbolIdentifier): boolean;
567
- query(filter: ISymbolMeta): ReadonlyArray<ISymbolOut>;
568
- reference(meta: ISymbolMeta): ISymbolOut;
569
- register(symbol: ISymbolIn): ISymbolOut;
570
- registered(): IterableIterator<ISymbolOut>;
571
- setValue(symbolId: SymbolId, value: unknown): Map<SymbolId, unknown>;
938
+ get nextId(): SymbolId;
939
+ query(filter: ISymbolMeta): ReadonlyArray<Symbol>;
940
+ reference(meta: ISymbolMeta): Symbol;
941
+ register(symbol: ISymbolIn): Symbol;
942
+ registered(): IterableIterator<Symbol>;
572
943
  private buildCacheKey;
573
944
  private buildIndexKeySpace;
574
945
  private indexSymbol;
@@ -580,34 +951,183 @@ declare class SymbolRegistry implements ISymbolRegistry {
580
951
  //#endregion
581
952
  //#region src/project/project.d.ts
582
953
  declare class Project implements IProject {
583
- private symbolIdToFileIds;
584
- readonly defaultFileName: string;
585
954
  readonly files: FileRegistry;
955
+ readonly nodes: NodeRegistry;
956
+ readonly symbols: SymbolRegistry;
957
+ readonly defaultFileName: string;
958
+ readonly defaultNameConflictResolver: NameConflictResolver;
959
+ readonly extensions: Extensions;
586
960
  readonly fileName?: (name: string) => string;
587
- readonly renderers: Record<string, IRenderer>;
961
+ readonly nameConflictResolvers: NameConflictResolvers;
962
+ readonly renderers: ReadonlyArray<Renderer>;
588
963
  readonly root: string;
589
- readonly symbols: SymbolRegistry;
590
- constructor({
591
- defaultFileName,
592
- fileName,
593
- renderers,
594
- root
595
- }: Pick<IProject, 'defaultFileName' | 'fileName' | 'renderers' | 'root'>);
596
- private getRenderer;
597
- private prepareFiles;
964
+ constructor(args: Pick<Partial<IProject>, 'defaultFileName' | 'defaultNameConflictResolver' | 'extensions' | 'fileName' | 'nameConflictResolvers' | 'renderers'> & Pick<IProject, 'root'>);
598
965
  render(meta?: IProjectRenderMeta): ReadonlyArray<IOutput>;
599
- symbolIdToFiles(symbolId: number): ReadonlyArray<IFileOut>;
600
- private symbolToFileSelector;
601
966
  }
602
967
  //#endregion
603
- //#region src/renderer/utils.d.ts
968
+ //#region src/refs/refs.d.ts
969
+ /**
970
+ * Wraps a single value in a Ref object.
971
+ *
972
+ * If the value is already a Ref, returns it as-is (idempotent).
973
+ *
974
+ * @example
975
+ * ```ts
976
+ * const r = ref(123); // { '~ref': 123 }
977
+ * console.log(r['~ref']); // 123
978
+ *
979
+ * const r2 = ref(r); // { '~ref': 123 } (not double-wrapped)
980
+ * ```
981
+ */
982
+ declare const ref: <T>(value: T) => Ref<T>;
983
+ /**
984
+ * Converts a plain object to an object of Refs (deep, per property).
985
+ *
986
+ * @example
987
+ * ```ts
988
+ * const obj = { a: 1, b: "x" };
989
+ * const refs = refs(obj); // { a: { '~ref': 1 }, b: { '~ref': "x" } }
990
+ * ```
991
+ */
992
+ declare const refs: <T extends Record<string, unknown>>(obj: T) => Refs<T>;
993
+ /**
994
+ * Unwraps a single Ref object to its value.
995
+ *
996
+ * @example
997
+ * ```ts
998
+ * const r = { '~ref': 42 };
999
+ * const n = fromRef(r); // 42
1000
+ * console.log(n); // 42
1001
+ * ```
1002
+ */
1003
+ declare const fromRef: <T extends Ref<unknown> | undefined>(ref: T) => FromRef<T>;
604
1004
  /**
1005
+ * Converts an object of Refs back to a plain object (unwraps all refs).
605
1006
  *
606
- * @param source The source string to replace.
607
- * @param replacerFn Accepts a symbol ID, returns resolved symbol name.
608
- * @returns The replaced source string.
1007
+ * @example
1008
+ * ```ts
1009
+ * const refs = { a: { '~ref': 1 }, b: { '~ref': "x" } };
1010
+ * const plain = fromRefs(refs); // { a: 1, b: "x" }
1011
+ * ```
609
1012
  */
610
- declare const renderIds: (source: string, replacerFn: (symbolId: number) => string | undefined) => string;
1013
+ declare const fromRefs: <T extends Refs<Record<string, unknown>>>(obj: T) => FromRefs<T>;
1014
+ /**
1015
+ * Checks whether a value is a Ref object.
1016
+ *
1017
+ * @param value Value to check
1018
+ * @returns True if the value is a Ref object.
1019
+ */
1020
+ declare const isRef: <T>(value: unknown) => value is Ref<T>;
1021
+ //#endregion
1022
+ //#region src/structure/types.d.ts
1023
+ interface StructureInsert {
1024
+ /** Inserted data. */
1025
+ data: unknown;
1026
+ /** Locations where the data should be inserted. */
1027
+ locations: ReadonlyArray<StructureLocation>;
1028
+ /** Source of the inserted data. */
1029
+ source: symbol;
1030
+ }
1031
+ interface StructureItem extends Pick<StructureInsert, 'data' | 'source'> {
1032
+ /** Location of this item within the structure. */
1033
+ location: ReadonlyArray<string>;
1034
+ }
1035
+ interface StructureLocation {
1036
+ /** Path within the structure where the data should be inserted. */
1037
+ path: ReadonlyArray<string>;
1038
+ /** Shell to apply at this location. */
1039
+ shell?: StructureShell;
1040
+ }
1041
+ interface StructureShell {
1042
+ define: (node: StructureNode) => StructureShellResult;
1043
+ }
1044
+ interface StructureShellResult {
1045
+ dependencies?: Array<INode>;
1046
+ node: INode;
1047
+ }
1048
+ //#endregion
1049
+ //#region src/structure/node.d.ts
1050
+ declare class StructureNode {
1051
+ /** Nested nodes within this node. */
1052
+ children: Map<string, StructureNode>;
1053
+ /** Items contained in this node. */
1054
+ items: Array<StructureItem>;
1055
+ /** The name of this node (e.g., "Users", "Accounts"). */
1056
+ name: string;
1057
+ /** Parent node in the hierarchy. Undefined if this is the root node. */
1058
+ parent?: StructureNode;
1059
+ /** Shell claimed for this node. */
1060
+ shell?: StructureShell;
1061
+ /** Source of the claimed shell. */
1062
+ shellSource?: symbol;
1063
+ /** True if this is a virtual root. */
1064
+ virtual: boolean;
1065
+ constructor(name: string, parent?: StructureNode, options?: {
1066
+ virtual?: boolean;
1067
+ });
1068
+ get isRoot(): boolean;
1069
+ /**
1070
+ * Gets or creates a child node.
1071
+ *
1072
+ * If the child doesn't exist, it's created automatically.
1073
+ *
1074
+ * @param name - The name of the child node
1075
+ * @returns The child node instance
1076
+ */
1077
+ child(name: string): StructureNode;
1078
+ /**
1079
+ * Gets the full path of this node in the hierarchy.
1080
+ *
1081
+ * @returns An array of node names from the root to this node
1082
+ */
1083
+ getPath(): ReadonlyArray<string>;
1084
+ /**
1085
+ * Yields items from a specific source with typed data.
1086
+ *
1087
+ * @param source - The source symbol to filter by
1088
+ * @returns Generator of items from that source
1089
+ */
1090
+ itemsFrom<T = unknown>(source: symbol): Generator<StructureItem & {
1091
+ data: T;
1092
+ }>;
1093
+ /**
1094
+ * Walk all nodes in the structure (depth-first, post-order).
1095
+ *
1096
+ * @returns Generator of all structure nodes
1097
+ */
1098
+ walk(): Generator<StructureNode>;
1099
+ }
1100
+ //#endregion
1101
+ //#region src/structure/model.d.ts
1102
+ declare class StructureModel {
1103
+ /** Root nodes mapped by their names. */
1104
+ private _roots;
1105
+ /** Node for data without a specific root. */
1106
+ private _virtualRoot?;
1107
+ /**
1108
+ * Get all root nodes.
1109
+ */
1110
+ get roots(): ReadonlyArray<StructureNode>;
1111
+ /**
1112
+ * Insert data into the structure.
1113
+ */
1114
+ insert(args: StructureInsert): void;
1115
+ /**
1116
+ * Gets or creates a root by name.
1117
+ *
1118
+ * If the root doesn't exist, it's created automatically.
1119
+ *
1120
+ * @param name - The name of the root
1121
+ * @returns The root instance
1122
+ */
1123
+ root(name: string | null): StructureNode;
1124
+ /**
1125
+ * Walk all nodes in the structure (depth-first, post-order).
1126
+ *
1127
+ * @returns Generator of all structure nodes
1128
+ */
1129
+ walk(): Generator<StructureNode>;
1130
+ }
611
1131
  //#endregion
612
- export { type IBiMap as BiMap, type IBinding as Binding, type IFileOut as File, type IFileIdentifier as FileIdentifier, type IFileIn as FileIn, type IProject, type IOutput as Output, Project, type IProjectRenderMeta as ProjectRenderMeta, type IRenderer as Renderer, type ISymbolOut as Symbol, type ISymbolIdentifier as SymbolIdentifier, type ISymbolIn as SymbolIn, type ISymbolMeta as SymbolMeta, createBinding, mergeBindings, renderIds };
1132
+ export { type IAnalysisContext as AnalysisContext, type BindingKind, type ExportMember, type ExportModule, type Extensions, File, type IFileIn as FileIn, type FromRef, type FromRefs, type IProject, type ImportMember, type ImportModule, type Language, type NameConflictResolver, type NameConflictResolvers, type INode as Node, type NodeName, type NodeNameSanitizer, type NodeRelationship, type NodeScope, type IOutput as Output, Project, type IProjectRenderMeta as ProjectRenderMeta, type Ref, type Refs, type RenderContext, type Renderer, type StructureInsert, type StructureItem, type StructureLocation, StructureModel, StructureNode, type StructureShell, type StructureShellResult, Symbol, type ISymbolIdentifier as SymbolIdentifier, type ISymbolIn as SymbolIn, type ISymbolMeta as SymbolMeta, defaultExtensions, defaultNameConflictResolvers, fromRef, fromRefs, isNode, isNodeRef, isRef, isSymbol, isSymbolRef, log, nodeBrand, ref, refs, simpleNameConflictResolver, symbolBrand, underscoreNameConflictResolver };
613
1133
  //# sourceMappingURL=index.d.cts.map