@tsonic/cli 0.0.72 → 0.0.74

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.
@@ -17,6 +17,82 @@ const ensureUndefinedInType = (typeText) => {
17
17
  return trimmed;
18
18
  return `${trimmed} | undefined`;
19
19
  };
20
+ const textContainsIdentifier = (text, identifier) => {
21
+ const escaped = identifier.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
22
+ return new RegExp(`(^|[^A-Za-z0-9_$])${escaped}([^A-Za-z0-9_$]|$)`).test(text);
23
+ };
24
+ const toRelativeImportSpecifier = (fromFile, targetFile) => {
25
+ const relative = posix.relative(posix.dirname(fromFile), targetFile);
26
+ if (relative.startsWith("."))
27
+ return relative;
28
+ return `./${relative}`;
29
+ };
30
+ const namespaceInternalImportSpecifier = (fromNamespace, targetNamespace) => {
31
+ return toRelativeImportSpecifier(posix.join(moduleNamespacePath(fromNamespace), "internal", "index.js"), posix.join(moduleNamespacePath(targetNamespace), "internal", "index.js"));
32
+ };
33
+ const namespaceFacadeImportSpecifier = (fromNamespace, targetNamespace) => {
34
+ return toRelativeImportSpecifier(`${moduleNamespacePath(fromNamespace)}.js`, `${moduleNamespacePath(targetNamespace)}.js`);
35
+ };
36
+ const resolveSourceTypeImportBinding = (opts) => {
37
+ const source = opts.imported.source.trim();
38
+ if (source === "@tsonic/core/types.js") {
39
+ return { ok: true, value: undefined };
40
+ }
41
+ if (!isRelativeModuleSpecifier(source)) {
42
+ return {
43
+ ok: true,
44
+ value: {
45
+ source,
46
+ importedName: opts.imported.importedName,
47
+ localName: opts.localName,
48
+ },
49
+ };
50
+ }
51
+ const targetModule = resolveLocalModuleFile(source, opts.currentModuleKey, opts.modulesByFileKey);
52
+ if (!targetModule) {
53
+ return {
54
+ ok: false,
55
+ error: `Unable to resolve source type import '${opts.localName}' from '${source}' in ${opts.currentModuleKey}.\n` +
56
+ "First-party bindings generation requires public type dependencies to resolve deterministically.",
57
+ };
58
+ }
59
+ if (targetModule.namespace === opts.currentNamespace) {
60
+ return { ok: true, value: undefined };
61
+ }
62
+ return {
63
+ ok: true,
64
+ value: {
65
+ source: opts.context === "internal"
66
+ ? namespaceInternalImportSpecifier(opts.currentNamespace, targetModule.namespace)
67
+ : namespaceFacadeImportSpecifier(opts.currentNamespace, targetModule.namespace),
68
+ importedName: opts.imported.importedName,
69
+ localName: opts.localName,
70
+ },
71
+ };
72
+ };
73
+ const registerSourceTypeImportBinding = (registry, binding, namespace, moduleFilePath) => {
74
+ const existing = registry.get(binding.localName);
75
+ if (existing) {
76
+ if (existing.source !== binding.source ||
77
+ existing.importedName !== binding.importedName) {
78
+ return {
79
+ ok: false,
80
+ error: `Conflicting source type import alias '${binding.localName}' while generating namespace ${namespace} from ${moduleFilePath}.\n` +
81
+ `- ${existing.importedName} from '${existing.source}'\n` +
82
+ `- ${binding.importedName} from '${binding.source}'\n` +
83
+ "Disambiguate source type imports so generated bindings remain deterministic.",
84
+ };
85
+ }
86
+ return { ok: true, value: undefined };
87
+ }
88
+ registry.set(binding.localName, binding);
89
+ return { ok: true, value: undefined };
90
+ };
91
+ const selectSourceTypeImportsForRenderedText = (renderedText, candidates) => {
92
+ return candidates
93
+ .filter((candidate) => textContainsIdentifier(renderedText, candidate.localName))
94
+ .sort((left, right) => left.localName.localeCompare(right.localName));
95
+ };
20
96
  const applyWrappersToBaseType = (baseType, wrappers) => {
21
97
  let expr = baseType.trim();
22
98
  for (const w of wrappers.slice().reverse()) {
@@ -35,6 +111,11 @@ const sanitizeForBrand = (value) => {
35
111
  const normalized = value.replace(/[^A-Za-z0-9_]/g, "_");
36
112
  return normalized.length > 0 ? normalized : "_";
37
113
  };
114
+ const renderBindingAliasMarker = (namespace, bindingAlias) => ` readonly ${JSON.stringify(`__tsonic_binding_alias_${namespace}.${bindingAlias}`)}?: never;`;
115
+ const isPortableMarkerMemberName = (name) => name === "__brand" ||
116
+ name.startsWith("__tsonic_type_") ||
117
+ name.startsWith("__tsonic_iface_") ||
118
+ name.startsWith("__tsonic_binding_alias_");
38
119
  const printTypeParameters = (typeParameters) => {
39
120
  if (!typeParameters || typeParameters.length === 0)
40
121
  return "";
@@ -53,7 +134,7 @@ const normalizeTypeReferenceName = (name, arity) => {
53
134
  }
54
135
  return `${backtickNormalized}_${arity}`;
55
136
  };
56
- const renderReferenceType = (referenceName, typeArguments, typeParametersInScope) => {
137
+ const renderReferenceType = (referenceName, typeArguments, typeParametersInScope, localTypeNameRemaps = new Map()) => {
57
138
  if (typeParametersInScope.includes(referenceName))
58
139
  return referenceName;
59
140
  if (referenceName === "unknown")
@@ -68,7 +149,8 @@ const renderReferenceType = (referenceName, typeArguments, typeParametersInScope
68
149
  return "boolean";
69
150
  if (referenceName === "number")
70
151
  return "number";
71
- let normalizedName = normalizeTypeReferenceName(referenceName);
152
+ const effectiveReferenceName = localTypeNameRemaps.get(referenceName) ?? referenceName;
153
+ let normalizedName = normalizeTypeReferenceName(effectiveReferenceName);
72
154
  if (typeArguments && typeArguments.length > 0) {
73
155
  const arityMatch = normalizedName.match(/_(\d+)$/);
74
156
  if (arityMatch &&
@@ -86,80 +168,124 @@ const renderReferenceType = (referenceName, typeArguments, typeParametersInScope
86
168
  if (!typeArguments || typeArguments.length === 0)
87
169
  return normalizedName;
88
170
  return `${normalizedName}<${typeArguments
89
- .map((arg) => renderPortableType(arg, typeParametersInScope))
171
+ .map((arg) => renderPortableType(arg, typeParametersInScope, localTypeNameRemaps))
90
172
  .join(", ")}>`;
91
173
  };
92
- const renderPortableType = (type, typeParametersInScope = []) => {
174
+ const renderPortableType = (type, typeParametersInScope = [], localTypeNameRemaps = new Map(), anonymousStructuralAliases = new Map()) => {
175
+ const renderPortableShapeType = (shapeType, shapeTypeParametersInScope = []) => {
176
+ if (!shapeType)
177
+ return "object";
178
+ switch (shapeType.kind) {
179
+ case "primitiveType":
180
+ return shapeType.name;
181
+ case "literalType":
182
+ return typeof shapeType.value === "string"
183
+ ? JSON.stringify(shapeType.value)
184
+ : String(shapeType.value);
185
+ case "voidType":
186
+ return "void";
187
+ case "neverType":
188
+ return "never";
189
+ case "unknownType":
190
+ case "anyType":
191
+ return "unknown";
192
+ case "typeParameterType":
193
+ return shapeType.name;
194
+ case "arrayType":
195
+ return `${renderPortableShapeType(shapeType.elementType, shapeTypeParametersInScope)}[]`;
196
+ case "tupleType":
197
+ return `[${shapeType.elementTypes
198
+ .map((item) => renderPortableShapeType(item, shapeTypeParametersInScope))
199
+ .join(", ")}]`;
200
+ case "unionType":
201
+ return shapeType.types
202
+ .map((item) => renderPortableShapeType(item, shapeTypeParametersInScope))
203
+ .join(" | ");
204
+ case "intersectionType":
205
+ return shapeType.types
206
+ .map((item) => renderPortableShapeType(item, shapeTypeParametersInScope))
207
+ .join(" & ");
208
+ case "dictionaryType":
209
+ return `Record<${renderPortableShapeType(shapeType.keyType, shapeTypeParametersInScope)}, ${renderPortableShapeType(shapeType.valueType, shapeTypeParametersInScope)}>`;
210
+ case "functionType":
211
+ return `(${shapeType.parameters
212
+ .map((parameter, index) => {
213
+ const parameterName = parameter.pattern.kind === "identifierPattern"
214
+ ? parameter.pattern.name
215
+ : `p${index + 1}`;
216
+ return `${parameterName}: ${renderPortableShapeType(parameter.type, shapeTypeParametersInScope)}`;
217
+ })
218
+ .join(", ")}) => ${renderPortableShapeType(shapeType.returnType, shapeTypeParametersInScope)}`;
219
+ case "objectType":
220
+ return `{ ${shapeType.members
221
+ .filter((member) => !isPortableMarkerMemberName(member.name))
222
+ .map((member) => {
223
+ if (member.kind === "methodSignature") {
224
+ return `${member.name}${printTypeParameters(member.typeParameters)}(${member.parameters
225
+ .map((parameter, index) => {
226
+ const parameterName = parameter.pattern.kind === "identifierPattern"
227
+ ? parameter.pattern.name
228
+ : `p${index + 1}`;
229
+ const optionalMark = parameter.isOptional ? "?" : "";
230
+ return `${parameterName}${optionalMark}: ${renderPortableShapeType(parameter.type, shapeTypeParametersInScope)}`;
231
+ })
232
+ .join(", ")}): ${renderPortableShapeType(member.returnType, shapeTypeParametersInScope)}`;
233
+ }
234
+ const optionalMark = member.isOptional ? "?" : "";
235
+ const readonlyMark = member.isReadonly ? "readonly " : "";
236
+ return `${readonlyMark}${member.name}${optionalMark}: ${renderPortableShapeType(member.type, shapeTypeParametersInScope)}`;
237
+ })
238
+ .join("; ")} }`;
239
+ case "referenceType":
240
+ return renderReferenceType(shapeType.name, shapeType.typeArguments, shapeTypeParametersInScope, localTypeNameRemaps);
241
+ default:
242
+ return "object";
243
+ }
244
+ };
93
245
  if (!type)
94
246
  return "object";
95
247
  switch (type.kind) {
96
- case "primitiveType":
97
- return type.name;
98
- case "literalType":
99
- return typeof type.value === "string"
100
- ? JSON.stringify(type.value)
101
- : String(type.value);
102
- case "voidType":
103
- return "void";
104
- case "neverType":
105
- return "never";
106
- case "unknownType":
107
- case "anyType":
108
- return "unknown";
109
- case "typeParameterType":
110
- return type.name;
248
+ case "objectType": {
249
+ const shape = renderPortableShapeType(type, typeParametersInScope);
250
+ const alias = anonymousStructuralAliases.get(shape);
251
+ if (alias) {
252
+ const typeArgs = alias.typeParameters.length > 0
253
+ ? `<${alias.typeParameters.join(", ")}>`
254
+ : "";
255
+ return `${alias.name}${typeArgs}`;
256
+ }
257
+ return shape;
258
+ }
111
259
  case "arrayType":
112
- return `${renderPortableType(type.elementType, typeParametersInScope)}[]`;
260
+ return `${renderPortableType(type.elementType, typeParametersInScope, localTypeNameRemaps, anonymousStructuralAliases)}[]`;
113
261
  case "tupleType":
114
262
  return `[${type.elementTypes
115
- .map((item) => renderPortableType(item, typeParametersInScope))
263
+ .map((item) => renderPortableType(item, typeParametersInScope, localTypeNameRemaps, anonymousStructuralAliases))
116
264
  .join(", ")}]`;
117
265
  case "unionType":
118
266
  return type.types
119
- .map((item) => renderPortableType(item, typeParametersInScope))
267
+ .map((item) => renderPortableType(item, typeParametersInScope, localTypeNameRemaps, anonymousStructuralAliases))
120
268
  .join(" | ");
121
269
  case "intersectionType":
122
270
  return type.types
123
- .map((item) => renderPortableType(item, typeParametersInScope))
271
+ .map((item) => renderPortableType(item, typeParametersInScope, localTypeNameRemaps, anonymousStructuralAliases))
124
272
  .join(" & ");
125
273
  case "dictionaryType":
126
- return `Record<${renderPortableType(type.keyType, typeParametersInScope)}, ${renderPortableType(type.valueType, typeParametersInScope)}>`;
274
+ return `Record<${renderPortableType(type.keyType, typeParametersInScope, localTypeNameRemaps, anonymousStructuralAliases)}, ${renderPortableType(type.valueType, typeParametersInScope, localTypeNameRemaps, anonymousStructuralAliases)}>`;
127
275
  case "functionType":
128
276
  return `(${type.parameters
129
277
  .map((parameter, index) => {
130
278
  const parameterName = parameter.pattern.kind === "identifierPattern"
131
279
  ? parameter.pattern.name
132
280
  : `p${index + 1}`;
133
- return `${parameterName}: ${renderPortableType(parameter.type, typeParametersInScope)}`;
281
+ return `${parameterName}: ${renderPortableType(parameter.type, typeParametersInScope, localTypeNameRemaps, anonymousStructuralAliases)}`;
134
282
  })
135
- .join(", ")}) => ${renderPortableType(type.returnType, typeParametersInScope)}`;
136
- case "objectType":
137
- return `{ ${type.members
138
- .map((member) => {
139
- if (member.kind === "methodSignature") {
140
- return `${member.name}${printTypeParameters(member.typeParameters)}(${member.parameters
141
- .map((parameter, index) => {
142
- const parameterName = parameter.pattern.kind === "identifierPattern"
143
- ? parameter.pattern.name
144
- : `p${index + 1}`;
145
- const optionalMark = parameter.isOptional ? "?" : "";
146
- return `${parameterName}${optionalMark}: ${renderPortableType(parameter.type, typeParametersInScope)}`;
147
- })
148
- .join(", ")}): ${renderPortableType(member.returnType, typeParametersInScope)}`;
149
- }
150
- const optionalMark = member.isOptional ? "?" : "";
151
- const readonlyMark = member.isReadonly ? "readonly " : "";
152
- return `${readonlyMark}${member.name}${optionalMark}: ${renderPortableType(member.type, typeParametersInScope)}`;
153
- })
154
- .join("; ")} }`;
155
- case "referenceType": {
156
- return renderReferenceType(type.name, type.typeArguments, typeParametersInScope);
157
- }
283
+ .join(", ")}) => ${renderPortableType(type.returnType, typeParametersInScope, localTypeNameRemaps, anonymousStructuralAliases)}`;
158
284
  default:
159
- return "object";
285
+ return renderPortableShapeType(type, typeParametersInScope);
160
286
  }
161
287
  };
162
- const renderUnknownParameters = (parameters, typeParametersInScope) => {
288
+ const renderUnknownParameters = (parameters, typeParametersInScope, localTypeNameRemaps = new Map(), anonymousStructuralAliases = new Map()) => {
163
289
  return parameters
164
290
  .map((parameter, index) => {
165
291
  const baseName = parameter.pattern.kind === "identifierPattern"
@@ -167,7 +293,7 @@ const renderUnknownParameters = (parameters, typeParametersInScope) => {
167
293
  : `p${index + 1}`;
168
294
  const restPrefix = parameter.isRest ? "..." : "";
169
295
  const optionalMark = parameter.isOptional && !parameter.isRest ? "?" : "";
170
- const parameterType = renderPortableType(parameter.type, typeParametersInScope);
296
+ const parameterType = renderPortableType(parameter.type, typeParametersInScope, localTypeNameRemaps, anonymousStructuralAliases);
171
297
  const typeSuffix = parameter.isRest
172
298
  ? `${parameterType}[]`
173
299
  : parameterType;
@@ -175,13 +301,405 @@ const renderUnknownParameters = (parameters, typeParametersInScope) => {
175
301
  })
176
302
  .join(", ");
177
303
  };
178
- const renderMethodSignature = (name, typeParameters, parameters, returnType) => {
304
+ const renderMethodSignature = (name, typeParameters, parameters, returnType, localTypeNameRemaps = new Map(), anonymousStructuralAliases = new Map()) => {
179
305
  const typeParametersText = printTypeParameters(typeParameters);
180
306
  const typeParameterNames = typeParameters?.map((typeParameter) => typeParameter.name) ?? [];
181
- const parametersText = renderUnknownParameters(parameters, typeParameterNames);
182
- const returnTypeText = renderPortableType(returnType, typeParameterNames);
307
+ const parametersText = renderUnknownParameters(parameters, typeParameterNames, localTypeNameRemaps, anonymousStructuralAliases);
308
+ const returnTypeText = renderPortableType(returnType, typeParameterNames, localTypeNameRemaps, anonymousStructuralAliases);
183
309
  return `${name}${typeParametersText}(${parametersText}): ${returnTypeText};`;
184
310
  };
311
+ const renderSourceTypeNodeForAliasLookup = (node, localTypeNameRemaps) => {
312
+ switch (node.kind) {
313
+ case ts.SyntaxKind.StringKeyword:
314
+ return "string";
315
+ case ts.SyntaxKind.NumberKeyword:
316
+ return "number";
317
+ case ts.SyntaxKind.BooleanKeyword:
318
+ return "boolean";
319
+ case ts.SyntaxKind.VoidKeyword:
320
+ return "void";
321
+ case ts.SyntaxKind.NeverKeyword:
322
+ return "never";
323
+ case ts.SyntaxKind.UnknownKeyword:
324
+ return "unknown";
325
+ case ts.SyntaxKind.AnyKeyword:
326
+ return "unknown";
327
+ case ts.SyntaxKind.NullKeyword:
328
+ return "null";
329
+ case ts.SyntaxKind.UndefinedKeyword:
330
+ return "undefined";
331
+ }
332
+ if (ts.isParenthesizedTypeNode(node)) {
333
+ return `(${renderSourceTypeNodeForAliasLookup(node.type, localTypeNameRemaps)})`;
334
+ }
335
+ if (ts.isArrayTypeNode(node)) {
336
+ return `${renderSourceTypeNodeForAliasLookup(node.elementType, localTypeNameRemaps)}[]`;
337
+ }
338
+ if (ts.isTupleTypeNode(node)) {
339
+ return `[${node.elements
340
+ .map((element) => renderSourceTypeNodeForAliasLookup(element, localTypeNameRemaps))
341
+ .join(", ")}]`;
342
+ }
343
+ if (ts.isUnionTypeNode(node)) {
344
+ return node.types
345
+ .map((part) => renderSourceTypeNodeForAliasLookup(part, localTypeNameRemaps))
346
+ .join(" | ");
347
+ }
348
+ if (ts.isIntersectionTypeNode(node)) {
349
+ return node.types
350
+ .map((part) => renderSourceTypeNodeForAliasLookup(part, localTypeNameRemaps))
351
+ .join(" & ");
352
+ }
353
+ if (ts.isLiteralTypeNode(node)) {
354
+ return node.getText();
355
+ }
356
+ if (ts.isTypeReferenceNode(node)) {
357
+ const typeNameText = node.typeName.getText();
358
+ const rewrittenTypeName = rewriteSourceTypeText(typeNameText, localTypeNameRemaps);
359
+ if (!node.typeArguments || node.typeArguments.length === 0) {
360
+ return rewrittenTypeName;
361
+ }
362
+ return `${rewrittenTypeName}<${node.typeArguments
363
+ .map((argument) => renderSourceTypeNodeForAliasLookup(argument, localTypeNameRemaps))
364
+ .join(", ")}>`;
365
+ }
366
+ if (ts.isTypeLiteralNode(node)) {
367
+ return `{ ${node.members
368
+ .flatMap((member) => {
369
+ if (ts.isPropertySignature(member)) {
370
+ const propertyName = ts.isIdentifier(member.name)
371
+ ? member.name.text
372
+ : ts.isStringLiteral(member.name)
373
+ ? member.name.text
374
+ : undefined;
375
+ if (!propertyName || !member.type)
376
+ return [];
377
+ const readonlyMark = (member.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ReadonlyKeyword) ?? false)
378
+ ? "readonly "
379
+ : "";
380
+ const propertyTypeText = member.questionToken
381
+ ? ensureUndefinedInType(renderSourceTypeNodeForAliasLookup(member.type, localTypeNameRemaps))
382
+ : renderSourceTypeNodeForAliasLookup(member.type, localTypeNameRemaps);
383
+ return [`${readonlyMark}${propertyName}: ${propertyTypeText}`];
384
+ }
385
+ if (ts.isMethodSignature(member)) {
386
+ const methodName = ts.isIdentifier(member.name)
387
+ ? member.name.text
388
+ : ts.isStringLiteral(member.name)
389
+ ? member.name.text
390
+ : undefined;
391
+ if (!methodName)
392
+ return [];
393
+ const typeParametersText = member.typeParameters
394
+ ? `<${member.typeParameters
395
+ .map((typeParameter) => typeParameter.name.text)
396
+ .join(", ")}>`
397
+ : "";
398
+ const parametersText = member.parameters
399
+ .map((parameter, index) => {
400
+ const parameterName = ts.isIdentifier(parameter.name)
401
+ ? parameter.name.text
402
+ : `p${index + 1}`;
403
+ const optionalMark = parameter.questionToken ? "?" : "";
404
+ const restPrefix = parameter.dotDotDotToken ? "..." : "";
405
+ const parameterType = parameter.type
406
+ ? renderSourceTypeNodeForAliasLookup(parameter.type, localTypeNameRemaps)
407
+ : "unknown";
408
+ return `${restPrefix}${parameterName}${optionalMark}: ${parameterType}`;
409
+ })
410
+ .join(", ");
411
+ const returnType = member.type
412
+ ? renderSourceTypeNodeForAliasLookup(member.type, localTypeNameRemaps)
413
+ : "void";
414
+ return [
415
+ `${methodName}${typeParametersText}(${parametersText}): ${returnType}`,
416
+ ];
417
+ }
418
+ return [];
419
+ })
420
+ .join("; ")} }`;
421
+ }
422
+ return node.getText();
423
+ };
424
+ const rewriteSourceTypeText = (typeText, localTypeNameRemaps, anonymousStructuralAliases = new Map()) => {
425
+ const sourceFile = ts.createSourceFile("__tsonic_source_type__.ts", `type __T = ${typeText};`, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
426
+ const statement = sourceFile.statements[0];
427
+ if (!statement || !ts.isTypeAliasDeclaration(statement))
428
+ return typeText;
429
+ const transformer = (context) => {
430
+ const visit = (node) => {
431
+ if (ts.isTypeReferenceNode(node) && ts.isIdentifier(node.typeName)) {
432
+ const remappedName = localTypeNameRemaps.get(node.typeName.text);
433
+ if (remappedName) {
434
+ return ts.factory.updateTypeReferenceNode(node, ts.factory.createIdentifier(remappedName), node.typeArguments);
435
+ }
436
+ }
437
+ if (anonymousStructuralAliases.size > 0 && ts.isTypeLiteralNode(node)) {
438
+ const alias = anonymousStructuralAliases.get(renderSourceTypeNodeForAliasLookup(node, localTypeNameRemaps));
439
+ if (alias) {
440
+ return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(alias.name), alias.typeParameters.map((typeParameter) => ts.factory.createTypeReferenceNode(typeParameter)));
441
+ }
442
+ }
443
+ return ts.visitEachChild(node, visit, context);
444
+ };
445
+ return (node) => ts.visitNode(node, visit);
446
+ };
447
+ const transformed = ts.transform(statement.type, [transformer])
448
+ .transformed[0];
449
+ if (!transformed)
450
+ return typeText;
451
+ const printer = ts.createPrinter({ removeComments: true });
452
+ return printer.printNode(ts.EmitHint.Unspecified, transformed, sourceFile);
453
+ };
454
+ const selectPreferredSourceFunctionSignature = (opts) => {
455
+ const targetTypeParameterCount = opts.declaration.typeParameters?.length ?? 0;
456
+ const targetParameterCount = opts.declaration.parameters.length;
457
+ const exact = opts.sourceSignatures.find((signature) => {
458
+ return (signature.parameters.length === targetParameterCount &&
459
+ signature.typeParameterCount === targetTypeParameterCount);
460
+ });
461
+ return exact ?? opts.sourceSignatures[0];
462
+ };
463
+ const renderSourceFunctionSignature = (opts) => {
464
+ const sourceSignature = selectPreferredSourceFunctionSignature({
465
+ declaration: opts.declaration,
466
+ sourceSignatures: opts.sourceSignatures,
467
+ });
468
+ if (!sourceSignature)
469
+ return undefined;
470
+ const parametersText = sourceSignature.parameters
471
+ .map((parameter) => `${parameter.prefixText}${rewriteSourceTypeText(parameter.typeText, opts.localTypeNameRemaps, opts.anonymousStructuralAliases)}`)
472
+ .join(", ");
473
+ return {
474
+ typeParametersText: sourceSignature.typeParametersText,
475
+ parametersText,
476
+ returnTypeText: rewriteSourceTypeText(sourceSignature.returnTypeText, opts.localTypeNameRemaps, opts.anonymousStructuralAliases),
477
+ };
478
+ };
479
+ const renderSourceValueType = (sourceType, localTypeNameRemaps, anonymousStructuralAliases = new Map()) => !sourceType
480
+ ? undefined
481
+ : rewriteSourceTypeText(sourceType.typeText, localTypeNameRemaps, anonymousStructuralAliases);
482
+ const renderSourceFunctionType = (opts) => {
483
+ const sourceSignature = opts.sourceSignatures[0];
484
+ if (!sourceSignature)
485
+ return undefined;
486
+ const parametersText = sourceSignature.parameters
487
+ .map((parameter) => `${parameter.prefixText}${rewriteSourceTypeText(parameter.typeText, opts.localTypeNameRemaps, opts.anonymousStructuralAliases)}`)
488
+ .join(", ");
489
+ return `${sourceSignature.typeParametersText}(${parametersText}) => ${rewriteSourceTypeText(sourceSignature.returnTypeText, opts.localTypeNameRemaps, opts.anonymousStructuralAliases)}`;
490
+ };
491
+ const isGeneratedStructuralHelperName = (name) => name.startsWith("__Anon_") || /__\d+$/.test(name);
492
+ const buildAnonymousStructuralAliasMap = (plan) => {
493
+ const aliases = new Map();
494
+ const registerAnonymousClass = (localName, declaration) => {
495
+ if (!isGeneratedStructuralHelperName(localName))
496
+ return;
497
+ const members = [];
498
+ for (const member of declaration.members) {
499
+ if (member.kind === "propertyDeclaration") {
500
+ if (isPortableMarkerMemberName(member.name))
501
+ continue;
502
+ members.push({
503
+ kind: "propertySignature",
504
+ name: member.name,
505
+ type: member.type ?? { kind: "unknownType" },
506
+ isOptional: false,
507
+ isReadonly: member.isReadonly,
508
+ });
509
+ continue;
510
+ }
511
+ if (member.kind === "methodDeclaration") {
512
+ if (isPortableMarkerMemberName(member.name))
513
+ continue;
514
+ members.push({
515
+ kind: "methodSignature",
516
+ name: member.name,
517
+ parameters: member.parameters,
518
+ returnType: member.returnType,
519
+ typeParameters: member.typeParameters,
520
+ });
521
+ }
522
+ }
523
+ const shape = renderPortableType({ kind: "objectType", members }, declaration.typeParameters?.map((typeParameter) => typeParameter.name) ??
524
+ [], new Map(), new Map());
525
+ const existing = aliases.get(shape) ?? [];
526
+ existing.push({
527
+ name: localName,
528
+ typeParameters: declaration.typeParameters?.map((typeParameter) => typeParameter.name) ?? [],
529
+ });
530
+ aliases.set(shape, existing);
531
+ };
532
+ for (const symbol of plan.typeDeclarations) {
533
+ if (symbol.kind !== "class" ||
534
+ symbol.declaration.kind !== "classDeclaration") {
535
+ continue;
536
+ }
537
+ registerAnonymousClass(symbol.localName, symbol.declaration);
538
+ }
539
+ for (const helper of plan.internalHelperTypeDeclarations) {
540
+ if (helper.kind !== "class")
541
+ continue;
542
+ registerAnonymousClass(helper.emittedName, helper.declaration);
543
+ }
544
+ const uniqueAliases = new Map();
545
+ for (const [shape, candidates] of aliases.entries()) {
546
+ if (candidates.length !== 1)
547
+ continue;
548
+ const onlyCandidate = candidates[0];
549
+ if (!onlyCandidate)
550
+ continue;
551
+ uniqueAliases.set(shape, onlyCandidate);
552
+ }
553
+ return uniqueAliases;
554
+ };
555
+ const collectReferencedPortableTypeNames = (type, typeParametersInScope, out) => {
556
+ if (!type)
557
+ return;
558
+ switch (type.kind) {
559
+ case "primitiveType":
560
+ case "literalType":
561
+ case "voidType":
562
+ case "neverType":
563
+ case "unknownType":
564
+ case "anyType":
565
+ return;
566
+ case "typeParameterType":
567
+ if (!typeParametersInScope.has(type.name)) {
568
+ out.add(type.name);
569
+ }
570
+ return;
571
+ case "arrayType":
572
+ collectReferencedPortableTypeNames(type.elementType, typeParametersInScope, out);
573
+ return;
574
+ case "tupleType":
575
+ for (const element of type.elementTypes) {
576
+ collectReferencedPortableTypeNames(element, typeParametersInScope, out);
577
+ }
578
+ return;
579
+ case "unionType":
580
+ case "intersectionType":
581
+ for (const member of type.types) {
582
+ collectReferencedPortableTypeNames(member, typeParametersInScope, out);
583
+ }
584
+ return;
585
+ case "dictionaryType":
586
+ collectReferencedPortableTypeNames(type.keyType, typeParametersInScope, out);
587
+ collectReferencedPortableTypeNames(type.valueType, typeParametersInScope, out);
588
+ return;
589
+ case "functionType":
590
+ for (const parameter of type.parameters) {
591
+ collectReferencedPortableTypeNames(parameter.type, typeParametersInScope, out);
592
+ }
593
+ collectReferencedPortableTypeNames(type.returnType, typeParametersInScope, out);
594
+ return;
595
+ case "objectType":
596
+ for (const member of type.members) {
597
+ if (member.kind === "propertySignature") {
598
+ collectReferencedPortableTypeNames(member.type, typeParametersInScope, out);
599
+ continue;
600
+ }
601
+ const nestedTypeParameters = new Set(typeParametersInScope);
602
+ for (const typeParameter of member.typeParameters ?? []) {
603
+ nestedTypeParameters.add(typeParameter.name);
604
+ }
605
+ for (const parameter of member.parameters) {
606
+ collectReferencedPortableTypeNames(parameter.type, nestedTypeParameters, out);
607
+ }
608
+ collectReferencedPortableTypeNames(member.returnType, nestedTypeParameters, out);
609
+ }
610
+ return;
611
+ case "referenceType":
612
+ {
613
+ const renderedName = renderReferenceType(type.name, type.typeArguments, []);
614
+ const baseName = renderedName.split("<")[0];
615
+ if (!baseName)
616
+ return;
617
+ out.add(baseName);
618
+ }
619
+ for (const typeArgument of type.typeArguments ?? []) {
620
+ collectReferencedPortableTypeNames(typeArgument, typeParametersInScope, out);
621
+ }
622
+ return;
623
+ }
624
+ };
625
+ const collectReferencedPortableTypesFromParameters = (parameters, typeParametersInScope, out) => {
626
+ for (const parameter of parameters) {
627
+ collectReferencedPortableTypeNames(parameter.type, typeParametersInScope, out);
628
+ }
629
+ };
630
+ const collectReferencedPortableTypeNamesFromDeclaration = (declaration, out) => {
631
+ switch (declaration.kind) {
632
+ case "enumDeclaration":
633
+ return;
634
+ case "typeAliasDeclaration": {
635
+ const typeParametersInScope = new Set((declaration.typeParameters ?? []).map((typeParameter) => typeParameter.name));
636
+ collectReferencedPortableTypeNames(declaration.type, typeParametersInScope, out);
637
+ return;
638
+ }
639
+ case "interfaceDeclaration": {
640
+ const typeParametersInScope = new Set((declaration.typeParameters ?? []).map((typeParameter) => typeParameter.name));
641
+ for (const baseType of declaration.extends) {
642
+ collectReferencedPortableTypeNames(baseType, typeParametersInScope, out);
643
+ }
644
+ for (const member of declaration.members) {
645
+ if (member.kind === "propertySignature") {
646
+ collectReferencedPortableTypeNames(member.type, typeParametersInScope, out);
647
+ continue;
648
+ }
649
+ const nestedTypeParameters = new Set(typeParametersInScope);
650
+ for (const typeParameter of member.typeParameters ?? []) {
651
+ nestedTypeParameters.add(typeParameter.name);
652
+ }
653
+ collectReferencedPortableTypesFromParameters(member.parameters, nestedTypeParameters, out);
654
+ collectReferencedPortableTypeNames(member.returnType, nestedTypeParameters, out);
655
+ }
656
+ return;
657
+ }
658
+ case "classDeclaration": {
659
+ const typeParametersInScope = new Set((declaration.typeParameters ?? []).map((typeParameter) => typeParameter.name));
660
+ if (declaration.superClass) {
661
+ collectReferencedPortableTypeNames(declaration.superClass, typeParametersInScope, out);
662
+ }
663
+ for (const implementedType of declaration.implements) {
664
+ collectReferencedPortableTypeNames(implementedType, typeParametersInScope, out);
665
+ }
666
+ for (const member of declaration.members) {
667
+ switch (member.kind) {
668
+ case "constructorDeclaration":
669
+ collectReferencedPortableTypesFromParameters(member.parameters, typeParametersInScope, out);
670
+ continue;
671
+ case "propertyDeclaration":
672
+ collectReferencedPortableTypeNames(member.type, typeParametersInScope, out);
673
+ continue;
674
+ case "methodDeclaration": {
675
+ const nestedTypeParameters = new Set(typeParametersInScope);
676
+ for (const typeParameter of member.typeParameters ?? []) {
677
+ nestedTypeParameters.add(typeParameter.name);
678
+ }
679
+ collectReferencedPortableTypesFromParameters(member.parameters, nestedTypeParameters, out);
680
+ collectReferencedPortableTypeNames(member.returnType, nestedTypeParameters, out);
681
+ continue;
682
+ }
683
+ }
684
+ }
685
+ return;
686
+ }
687
+ }
688
+ };
689
+ const classifyLocalTypeDeclarationKind = (statement) => {
690
+ switch (statement.kind) {
691
+ case "classDeclaration":
692
+ return "class";
693
+ case "interfaceDeclaration":
694
+ return "interface";
695
+ case "enumDeclaration":
696
+ return "enum";
697
+ case "typeAliasDeclaration":
698
+ return "typeAlias";
699
+ default:
700
+ return undefined;
701
+ }
702
+ };
185
703
  const declarationNameOf = (statement) => {
186
704
  switch (statement.kind) {
187
705
  case "functionDeclaration":
@@ -328,6 +846,22 @@ const collectModuleExports = (module, modulesByFileKey) => {
328
846
  value: exportedSymbols.sort((left, right) => left.exportName.localeCompare(right.exportName)),
329
847
  };
330
848
  };
849
+ const finalizeCrossNamespaceReexports = (grouped) => {
850
+ const dtsStatements = [];
851
+ const jsValueStatements = [];
852
+ for (const [key, specs] of Array.from(grouped.entries()).sort((a, b) => a[0].localeCompare(b[0]))) {
853
+ const [moduleSpecifier, kind] = key.split("|");
854
+ const unique = Array.from(new Set(specs)).sort((a, b) => a.localeCompare(b));
855
+ if (kind === "type") {
856
+ dtsStatements.push(`export type { ${unique.join(", ")} } from '${moduleSpecifier}';`);
857
+ continue;
858
+ }
859
+ const statement = `export { ${unique.join(", ")} } from '${moduleSpecifier}';`;
860
+ dtsStatements.push(statement);
861
+ jsValueStatements.push(statement);
862
+ }
863
+ return { dtsStatements, jsValueStatements };
864
+ };
331
865
  const moduleNamespacePath = (namespace) => {
332
866
  return namespace.length > 0 ? namespace : "index";
333
867
  };
@@ -512,27 +1046,64 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
512
1046
  const wrapperImportsByLocalName = new Map();
513
1047
  const typeImportsByLocalName = new Map();
514
1048
  const typeAliasesByName = new Map();
1049
+ const exportedTypeDeclarationNames = new Set();
515
1050
  const exportedFunctionSignaturesByName = new Map();
1051
+ const exportedValueTypesByName = new Map();
516
1052
  const memberTypesByClassAndMember = new Map();
1053
+ const anonymousTypeLiteralsByShape = new Map();
517
1054
  const printTypeParametersText = (typeParameters) => {
518
1055
  if (!typeParameters || typeParameters.length === 0)
519
1056
  return "";
520
1057
  return `<${typeParameters.map((tp) => tp.getText(sourceFile)).join(", ")}>`;
521
1058
  };
522
- const printParameterText = (param) => {
1059
+ const printParameterSignature = (param) => {
523
1060
  const rest = param.dotDotDotToken ? "..." : "";
524
1061
  const name = param.name.getText(sourceFile);
525
1062
  const optional = param.questionToken ? "?" : "";
526
- const type = param.type
527
- ? printTypeNodeText(param.type, sourceFile)
528
- : "unknown";
529
- return `${rest}${name}${optional}: ${type}`;
1063
+ return {
1064
+ prefixText: `${rest}${name}${optional}: `,
1065
+ typeText: param.type
1066
+ ? printTypeNodeText(param.type, sourceFile)
1067
+ : "unknown",
1068
+ };
530
1069
  };
531
1070
  const addExportedFunctionSignature = (name, signature) => {
532
1071
  const signatures = exportedFunctionSignaturesByName.get(name) ?? [];
533
1072
  signatures.push(signature);
534
1073
  exportedFunctionSignaturesByName.set(name, signatures);
535
1074
  };
1075
+ const registerAnonymousTypeLiteralsInTypeNode = (typeNode) => {
1076
+ if (!typeNode)
1077
+ return;
1078
+ const visit = (current) => {
1079
+ if (ts.isTypeLiteralNode(current)) {
1080
+ const shape = renderSourceTypeNodeForAliasLookup(current, new Map());
1081
+ if (!anonymousTypeLiteralsByShape.has(shape)) {
1082
+ const members = new Map();
1083
+ for (const member of current.members) {
1084
+ if (!ts.isPropertySignature(member))
1085
+ continue;
1086
+ if (!member.name || !member.type)
1087
+ continue;
1088
+ const memberName = getPropertyNameText(member.name);
1089
+ if (!memberName)
1090
+ continue;
1091
+ members.set(memberName, {
1092
+ typeNode: member.type,
1093
+ typeText: printTypeNodeText(member.type, sourceFile),
1094
+ isOptional: member.questionToken !== undefined,
1095
+ });
1096
+ }
1097
+ anonymousTypeLiteralsByShape.set(shape, {
1098
+ typeText: printTypeNodeText(current, sourceFile),
1099
+ members,
1100
+ });
1101
+ }
1102
+ }
1103
+ ts.forEachChild(current, visit);
1104
+ };
1105
+ visit(typeNode);
1106
+ };
536
1107
  for (const stmt of sourceFile.statements) {
537
1108
  if (ts.isImportDeclaration(stmt)) {
538
1109
  const moduleSpecifier = ts.isStringLiteral(stmt.moduleSpecifier)
@@ -549,9 +1120,6 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
549
1120
  for (const spec of namedBindings.elements) {
550
1121
  const localName = spec.name.text;
551
1122
  const importedName = (spec.propertyName ?? spec.name).text;
552
- const isTypeOnly = clause.isTypeOnly || spec.isTypeOnly;
553
- if (!isTypeOnly)
554
- continue;
555
1123
  typeImportsByLocalName.set(localName, {
556
1124
  source: moduleSpecifier,
557
1125
  importedName,
@@ -567,6 +1135,7 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
567
1135
  }
568
1136
  if (ts.isTypeAliasDeclaration(stmt)) {
569
1137
  const aliasName = stmt.name.text;
1138
+ const hasExport = stmt.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword);
570
1139
  const typeParameterNames = (stmt.typeParameters ?? []).map((tp) => tp.name.text);
571
1140
  typeAliasesByName.set(aliasName, {
572
1141
  typeParametersText: printTypeParametersText(stmt.typeParameters),
@@ -574,16 +1143,25 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
574
1143
  type: stmt.type,
575
1144
  typeText: printTypeNodeText(stmt.type, sourceFile),
576
1145
  });
1146
+ registerAnonymousTypeLiteralsInTypeNode(stmt.type);
1147
+ if (hasExport) {
1148
+ exportedTypeDeclarationNames.add(aliasName);
1149
+ }
577
1150
  continue;
578
1151
  }
579
1152
  if (ts.isFunctionDeclaration(stmt)) {
580
1153
  const hasExport = stmt.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword);
581
1154
  if (!hasExport || !stmt.name || !stmt.type)
582
1155
  continue;
583
- const parametersText = stmt.parameters.map(printParameterText).join(", ");
1156
+ for (const parameter of stmt.parameters) {
1157
+ registerAnonymousTypeLiteralsInTypeNode(parameter.type);
1158
+ }
1159
+ registerAnonymousTypeLiteralsInTypeNode(stmt.type);
1160
+ const parameters = stmt.parameters.map(printParameterSignature);
584
1161
  addExportedFunctionSignature(stmt.name.text, {
585
1162
  typeParametersText: printTypeParametersText(stmt.typeParameters),
586
- parametersText,
1163
+ typeParameterCount: stmt.typeParameters?.length ?? 0,
1164
+ parameters,
587
1165
  returnTypeText: printTypeNodeText(stmt.type, sourceFile),
588
1166
  });
589
1167
  continue;
@@ -601,16 +1179,25 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
601
1179
  continue;
602
1180
  if (!ts.isArrowFunction(initializer) &&
603
1181
  !ts.isFunctionExpression(initializer)) {
1182
+ if (declaration.type) {
1183
+ registerAnonymousTypeLiteralsInTypeNode(declaration.type);
1184
+ exportedValueTypesByName.set(exportName, {
1185
+ typeText: printTypeNodeText(declaration.type, sourceFile),
1186
+ });
1187
+ }
604
1188
  continue;
605
1189
  }
606
1190
  if (!initializer.type)
607
1191
  continue;
608
- const parametersText = initializer.parameters
609
- .map(printParameterText)
610
- .join(", ");
1192
+ for (const parameter of initializer.parameters) {
1193
+ registerAnonymousTypeLiteralsInTypeNode(parameter.type);
1194
+ }
1195
+ registerAnonymousTypeLiteralsInTypeNode(initializer.type);
1196
+ const parameters = initializer.parameters.map(printParameterSignature);
611
1197
  addExportedFunctionSignature(exportName, {
612
1198
  typeParametersText: printTypeParametersText(initializer.typeParameters),
613
- parametersText,
1199
+ typeParameterCount: initializer.typeParameters?.length ?? 0,
1200
+ parameters,
614
1201
  returnTypeText: printTypeNodeText(initializer.type, sourceFile),
615
1202
  });
616
1203
  }
@@ -618,6 +1205,10 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
618
1205
  }
619
1206
  if (ts.isClassDeclaration(stmt) && stmt.name) {
620
1207
  const className = stmt.name.text;
1208
+ const hasExport = stmt.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword);
1209
+ if (hasExport) {
1210
+ exportedTypeDeclarationNames.add(className);
1211
+ }
621
1212
  const members = memberTypesByClassAndMember.get(className) ??
622
1213
  new Map();
623
1214
  for (const member of stmt.members) {
@@ -640,6 +1231,7 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
640
1231
  const name = getPropertyNameText(member.name);
641
1232
  if (!name)
642
1233
  continue;
1234
+ registerAnonymousTypeLiteralsInTypeNode(member.type);
643
1235
  members.set(name, {
644
1236
  typeNode: member.type,
645
1237
  typeText: printTypeNodeText(member.type, sourceFile),
@@ -654,6 +1246,10 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
654
1246
  }
655
1247
  if (ts.isInterfaceDeclaration(stmt)) {
656
1248
  const interfaceName = stmt.name.text;
1249
+ const hasExport = stmt.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword);
1250
+ if (hasExport) {
1251
+ exportedTypeDeclarationNames.add(interfaceName);
1252
+ }
657
1253
  const members = memberTypesByClassAndMember.get(interfaceName) ??
658
1254
  new Map();
659
1255
  for (const member of stmt.members) {
@@ -664,6 +1260,7 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
664
1260
  const name = getPropertyNameText(member.name);
665
1261
  if (!name)
666
1262
  continue;
1263
+ registerAnonymousTypeLiteralsInTypeNode(member.type);
667
1264
  members.set(name, {
668
1265
  typeNode: member.type,
669
1266
  typeText: printTypeNodeText(member.type, sourceFile),
@@ -673,6 +1270,13 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
673
1270
  if (members.size > 0) {
674
1271
  memberTypesByClassAndMember.set(interfaceName, members);
675
1272
  }
1273
+ continue;
1274
+ }
1275
+ if (ts.isEnumDeclaration(stmt)) {
1276
+ const hasExport = stmt.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword);
1277
+ if (hasExport) {
1278
+ exportedTypeDeclarationNames.add(stmt.name.text);
1279
+ }
676
1280
  }
677
1281
  }
678
1282
  return {
@@ -682,8 +1286,11 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
682
1286
  wrapperImportsByLocalName,
683
1287
  typeImportsByLocalName,
684
1288
  typeAliasesByName,
1289
+ exportedTypeDeclarationNames,
685
1290
  exportedFunctionSignaturesByName,
1291
+ exportedValueTypesByName,
686
1292
  memberTypesByClassAndMember,
1293
+ anonymousTypeLiteralsByShape,
687
1294
  },
688
1295
  };
689
1296
  };
@@ -798,42 +1405,6 @@ const collectExtensionWrapperImportsFromSourceType = (opts) => {
798
1405
  }
799
1406
  return { ok: true, value: wrappers };
800
1407
  };
801
- const classifyExportKind = (module, name) => {
802
- const isNamed = (stmt) => typeof stmt.name === "string";
803
- const findDecl = () => {
804
- for (const stmt of module.body) {
805
- if (!("isExported" in stmt) ||
806
- stmt.isExported !== true)
807
- continue;
808
- if (isNamed(stmt) && stmt.name === name)
809
- return stmt;
810
- if (stmt.kind === "variableDeclaration") {
811
- for (const decl of stmt.declarations) {
812
- if (decl.name.kind === "identifierPattern" &&
813
- decl.name.name === name) {
814
- return stmt;
815
- }
816
- }
817
- }
818
- }
819
- return undefined;
820
- };
821
- const decl = findDecl();
822
- if (!decl)
823
- return "unknown";
824
- switch (decl.kind) {
825
- case "typeAliasDeclaration":
826
- case "interfaceDeclaration":
827
- return "type";
828
- case "classDeclaration":
829
- case "enumDeclaration":
830
- case "functionDeclaration":
831
- case "variableDeclaration":
832
- return "value";
833
- default:
834
- return "unknown";
835
- }
836
- };
837
1408
  const moduleNamespaceToInternalSpecifier = (namespace) => {
838
1409
  const nsPath = moduleNamespacePath(namespace);
839
1410
  return `./${nsPath}/internal/index.js`;
@@ -842,6 +1413,12 @@ const toClrTypeName = (namespace, typeName, arity) => {
842
1413
  const suffix = arity && arity > 0 ? `\`${arity}` : "";
843
1414
  return `${namespace}.${typeName}${suffix}`;
844
1415
  };
1416
+ const toBindingTypeAlias = (namespace, typeName, arity) => {
1417
+ const normalizedName = normalizeTypeReferenceName(typeName, arity);
1418
+ return namespace.length > 0
1419
+ ? `${namespace}.${normalizedName}`
1420
+ : normalizedName;
1421
+ };
845
1422
  const toStableId = (assemblyName, clrName) => {
846
1423
  return `${assemblyName}:${clrName}`;
847
1424
  };
@@ -870,7 +1447,111 @@ const isNumericValueType = (name) => {
870
1447
  name === "System.Byte" ||
871
1448
  name === "System.SByte");
872
1449
  };
873
- const toSignatureType = (type, typeParametersInScope) => {
1450
+ const rewriteBindingSemanticParameter = (parameter, localTypeNameRemaps) => ({
1451
+ ...parameter,
1452
+ type: rewriteBindingSemanticType(parameter.type, localTypeNameRemaps),
1453
+ });
1454
+ const rewriteBindingSemanticMember = (member, localTypeNameRemaps) => {
1455
+ if (member.kind === "propertySignature") {
1456
+ return {
1457
+ ...member,
1458
+ type: rewriteBindingSemanticType(member.type, localTypeNameRemaps) ??
1459
+ member.type,
1460
+ };
1461
+ }
1462
+ return {
1463
+ ...member,
1464
+ parameters: member.parameters.map((parameter) => rewriteBindingSemanticParameter(parameter, localTypeNameRemaps)),
1465
+ returnType: rewriteBindingSemanticType(member.returnType, localTypeNameRemaps) ??
1466
+ member.returnType,
1467
+ };
1468
+ };
1469
+ const rewriteBindingSemanticType = (type, localTypeNameRemaps) => {
1470
+ if (!type)
1471
+ return undefined;
1472
+ switch (type.kind) {
1473
+ case "referenceType": {
1474
+ const rewrittenName = normalizeTypeReferenceName(localTypeNameRemaps.get(type.name) ?? type.name, type.typeArguments?.length);
1475
+ return {
1476
+ ...type,
1477
+ name: rewrittenName,
1478
+ typeArguments: type.typeArguments?.map((arg) => rewriteBindingSemanticType(arg, localTypeNameRemaps)),
1479
+ structuralMembers: type.structuralMembers?.map((member) => rewriteBindingSemanticMember(member, localTypeNameRemaps)),
1480
+ };
1481
+ }
1482
+ case "arrayType":
1483
+ return {
1484
+ ...type,
1485
+ elementType: rewriteBindingSemanticType(type.elementType, localTypeNameRemaps) ??
1486
+ type.elementType,
1487
+ };
1488
+ case "tupleType":
1489
+ return {
1490
+ ...type,
1491
+ elementTypes: type.elementTypes.map((elementType) => rewriteBindingSemanticType(elementType, localTypeNameRemaps)),
1492
+ };
1493
+ case "functionType":
1494
+ return {
1495
+ ...type,
1496
+ parameters: type.parameters.map((parameter) => rewriteBindingSemanticParameter(parameter, localTypeNameRemaps)),
1497
+ returnType: rewriteBindingSemanticType(type.returnType, localTypeNameRemaps) ??
1498
+ type.returnType,
1499
+ };
1500
+ case "objectType":
1501
+ return {
1502
+ ...type,
1503
+ members: type.members.map((member) => rewriteBindingSemanticMember(member, localTypeNameRemaps)),
1504
+ };
1505
+ case "dictionaryType":
1506
+ return {
1507
+ ...type,
1508
+ keyType: rewriteBindingSemanticType(type.keyType, localTypeNameRemaps) ??
1509
+ type.keyType,
1510
+ valueType: rewriteBindingSemanticType(type.valueType, localTypeNameRemaps) ??
1511
+ type.valueType,
1512
+ };
1513
+ case "unionType":
1514
+ case "intersectionType":
1515
+ return {
1516
+ ...type,
1517
+ types: type.types.map((candidate) => rewriteBindingSemanticType(candidate, localTypeNameRemaps)),
1518
+ };
1519
+ default:
1520
+ return type;
1521
+ }
1522
+ };
1523
+ const buildSemanticSignature = (opts) => {
1524
+ return {
1525
+ typeParameters: opts.typeParameters?.map((typeParameter) => typeParameter.name),
1526
+ parameters: opts.parameters.map((parameter) => rewriteBindingSemanticParameter(parameter, opts.localTypeNameRemaps)),
1527
+ returnType: rewriteBindingSemanticType(opts.returnType, opts.localTypeNameRemaps),
1528
+ };
1529
+ };
1530
+ const buildSemanticSignatureFromFunctionType = (type, localTypeNameRemaps) => ({
1531
+ typeParameters: undefined,
1532
+ parameters: type.parameters.map((parameter) => rewriteBindingSemanticParameter(parameter, localTypeNameRemaps)),
1533
+ returnType: rewriteBindingSemanticType(type.returnType, localTypeNameRemaps),
1534
+ });
1535
+ const resolveFunctionTypeFromValueDeclarator = (declarator) => {
1536
+ if (declarator?.type?.kind === "functionType") {
1537
+ return declarator.type;
1538
+ }
1539
+ const initializerType = declarator?.initializer?.inferredType;
1540
+ if (initializerType?.kind === "functionType") {
1541
+ return initializerType;
1542
+ }
1543
+ return undefined;
1544
+ };
1545
+ const areBindingSemanticSignaturesEqual = (left, right) => JSON.stringify(left ?? null) === JSON.stringify(right ?? null);
1546
+ const areBindingSemanticsEqual = (left, right) => left.kind === right.kind &&
1547
+ left.clrName === right.clrName &&
1548
+ left.declaringClrType === right.declaringClrType &&
1549
+ left.declaringAssemblyName === right.declaringAssemblyName &&
1550
+ left.semanticOptional === right.semanticOptional &&
1551
+ JSON.stringify(left.semanticType ?? null) ===
1552
+ JSON.stringify(right.semanticType ?? null) &&
1553
+ areBindingSemanticSignaturesEqual(left.semanticSignature, right.semanticSignature);
1554
+ const toSignatureType = (type, typeParametersInScope, localTypeNameRemaps = new Map()) => {
874
1555
  if (!type)
875
1556
  return "System.Object";
876
1557
  switch (type.kind) {
@@ -893,20 +1574,20 @@ const toSignatureType = (type, typeParametersInScope) => {
893
1574
  case "typeParameterType":
894
1575
  return type.name;
895
1576
  case "arrayType":
896
- return `${toSignatureType(type.elementType, typeParametersInScope)}[]`;
1577
+ return `${toSignatureType(type.elementType, typeParametersInScope, localTypeNameRemaps)}[]`;
897
1578
  case "tupleType":
898
1579
  case "objectType":
899
1580
  case "functionType":
900
1581
  case "dictionaryType":
901
1582
  return "System.Object";
902
1583
  case "intersectionType":
903
- return toSignatureType(type.types[0], typeParametersInScope);
1584
+ return toSignatureType(type.types[0], typeParametersInScope, localTypeNameRemaps);
904
1585
  case "unionType": {
905
1586
  const nonUndefined = type.types.filter((candidate) => {
906
1587
  return !(candidate.kind === "primitiveType" && candidate.name === "undefined");
907
1588
  });
908
1589
  if (nonUndefined.length === 1 && nonUndefined[0]) {
909
- const single = toSignatureType(nonUndefined[0], typeParametersInScope);
1590
+ const single = toSignatureType(nonUndefined[0], typeParametersInScope, localTypeNameRemaps);
910
1591
  if (isNumericValueType(single)) {
911
1592
  return `System.Nullable\`1[[${single}]]`;
912
1593
  }
@@ -917,12 +1598,12 @@ const toSignatureType = (type, typeParametersInScope) => {
917
1598
  case "referenceType": {
918
1599
  if (typeParametersInScope.includes(type.name))
919
1600
  return type.name;
920
- const normalizedName = normalizeTypeReferenceName(type.name, type.typeArguments?.length);
1601
+ const normalizedName = normalizeTypeReferenceName(localTypeNameRemaps.get(type.name) ?? type.name, type.typeArguments?.length);
921
1602
  if (!type.typeArguments || type.typeArguments.length === 0) {
922
1603
  return normalizedName;
923
1604
  }
924
1605
  const args = type.typeArguments
925
- .map((arg) => toSignatureType(arg, typeParametersInScope))
1606
+ .map((arg) => toSignatureType(arg, typeParametersInScope, localTypeNameRemaps))
926
1607
  .join(",");
927
1608
  return `${normalizedName}[[${args}]]`;
928
1609
  }
@@ -947,13 +1628,19 @@ const makeMethodBinding = (opts) => {
947
1628
  : undefined)
948
1629
  .filter((name) => name !== undefined)));
949
1630
  const normalizedSignature = `${opts.methodName}|(${opts.parameters
950
- .map((parameter) => toSignatureType(parameter.type, typeParameterScope))
951
- .join(",")}):${toSignatureType(opts.returnType, typeParameterScope)}|static=${opts.isStatic ? "true" : "false"}`;
1631
+ .map((parameter) => toSignatureType(parameter.type, typeParameterScope, opts.localTypeNameRemaps))
1632
+ .join(",")}):${toSignatureType(opts.returnType, typeParameterScope, opts.localTypeNameRemaps)}|static=${opts.isStatic ? "true" : "false"}`;
952
1633
  const stableId = `${toStableId(opts.declaringAssemblyName, opts.declaringClrType)}::method:${opts.methodName}|${normalizedSignature}`;
953
1634
  return {
954
1635
  stableId,
955
1636
  clrName: opts.methodName,
956
1637
  normalizedSignature,
1638
+ semanticSignature: buildSemanticSignature({
1639
+ typeParameters: opts.typeParameters,
1640
+ parameters: opts.parameters,
1641
+ returnType: opts.returnType,
1642
+ localTypeNameRemaps: opts.localTypeNameRemaps ?? new Map(),
1643
+ }),
957
1644
  arity: opts.arity,
958
1645
  parameterCount: opts.parameters.length,
959
1646
  isStatic: opts.isStatic,
@@ -967,16 +1654,17 @@ const makeMethodBinding = (opts) => {
967
1654
  isExtensionMethod: false,
968
1655
  };
969
1656
  };
970
- const renderClassInternal = (declaration, namespace, memberOverrides) => {
1657
+ const renderClassInternal = (declaration, namespace, memberOverrides, emittedName = declaration.name, localTypeNameRemaps = new Map(), brandName = declaration.name, bindingAlias = declaration.name) => {
971
1658
  const lines = [];
1659
+ const isSyntheticAnonymousStructuralClass = emittedName.startsWith("__Anon_") || brandName.startsWith("__Anon_");
972
1660
  const typeParameterScope = (declaration.typeParameters ?? []).map((typeParameter) => typeParameter.name);
973
1661
  const typeParameters = printTypeParameters(declaration.typeParameters);
974
- const markerName = `__tsonic_type_${sanitizeForBrand(namespace)}_${sanitizeForBrand(declaration.name)}`;
1662
+ const markerName = `__tsonic_type_${sanitizeForBrand(namespace)}_${sanitizeForBrand(brandName)}`;
975
1663
  const heritageNames = [
976
1664
  declaration.superClass
977
- ? renderPortableType(declaration.superClass, typeParameterScope)
1665
+ ? renderPortableType(declaration.superClass, typeParameterScope, localTypeNameRemaps)
978
1666
  : undefined,
979
- ...declaration.implements.map((implementedType) => renderPortableType(implementedType, typeParameterScope)),
1667
+ ...declaration.implements.map((implementedType) => renderPortableType(implementedType, typeParameterScope, localTypeNameRemaps)),
980
1668
  ]
981
1669
  .filter((name) => name !== undefined)
982
1670
  .map((name) => name.trim())
@@ -987,8 +1675,11 @@ const renderClassInternal = (declaration, namespace, memberOverrides) => {
987
1675
  const extendsClause = heritageNames.length > 0
988
1676
  ? ` extends ${Array.from(new Set(heritageNames)).join(", ")}`
989
1677
  : "";
990
- lines.push(`export interface ${declaration.name}$instance${typeParameters}${extendsClause} {`);
991
- lines.push(` readonly ${markerName}: never;`);
1678
+ lines.push(`export interface ${emittedName}$instance${typeParameters}${extendsClause} {`);
1679
+ if (!isSyntheticAnonymousStructuralClass) {
1680
+ lines.push(` readonly ${markerName}: never;`);
1681
+ }
1682
+ lines.push(renderBindingAliasMarker(namespace, bindingAlias));
992
1683
  const instanceMembers = declaration.members.filter((member) => {
993
1684
  if (member.kind === "constructorDeclaration")
994
1685
  return false;
@@ -998,7 +1689,7 @@ const renderClassInternal = (declaration, namespace, memberOverrides) => {
998
1689
  });
999
1690
  for (const member of instanceMembers) {
1000
1691
  if (member.kind === "methodDeclaration") {
1001
- lines.push(` ${renderMethodSignature(member.name, member.typeParameters, member.parameters, member.returnType)}`);
1692
+ lines.push(` ${renderMethodSignature(member.name, member.typeParameters, member.parameters, member.returnType, localTypeNameRemaps)}`);
1002
1693
  continue;
1003
1694
  }
1004
1695
  if (member.kind === "propertyDeclaration") {
@@ -1010,24 +1701,33 @@ const renderClassInternal = (declaration, namespace, memberOverrides) => {
1010
1701
  const hasSetter = hasAccessorBody
1011
1702
  ? member.setterBody !== undefined
1012
1703
  : !member.isReadonly;
1704
+ const optionalBySource = memberOverride?.emitOptionalPropertySyntax === true &&
1705
+ memberOverride.isOptional === true &&
1706
+ !member.name.startsWith("__tsonic_type_");
1707
+ const optionalMark = optionalBySource ? "?" : "";
1013
1708
  const baseType = (memberOverride?.replaceWithSourceType
1014
1709
  ? memberOverride.sourceTypeText
1015
- : undefined) ?? renderPortableType(member.type);
1710
+ : undefined) ??
1711
+ renderPortableType(member.type, typeParameterScope, localTypeNameRemaps);
1016
1712
  const wrappedType = applyWrappersToBaseType(baseType, memberOverride?.wrappers ?? []);
1017
- const memberType = memberOverride?.isOptional === true
1713
+ const memberType = memberOverride?.isOptional === true && !optionalBySource
1018
1714
  ? ensureUndefinedInType(wrappedType)
1019
1715
  : wrappedType;
1020
1716
  if (hasGetter && !hasSetter) {
1021
- lines.push(` readonly ${member.name}: ${memberType};`);
1717
+ lines.push(` readonly ${member.name}${optionalMark}: ${memberType};`);
1022
1718
  continue;
1023
1719
  }
1024
- lines.push(` ${member.name}: ${memberType};`);
1720
+ lines.push(` ${member.name}${optionalMark}: ${memberType};`);
1025
1721
  }
1026
1722
  }
1027
1723
  lines.push("}");
1028
1724
  lines.push("");
1029
- lines.push(`export const ${declaration.name}: {`);
1030
- lines.push(` new(...args: unknown[]): ${declaration.name}${typeParameters};`);
1725
+ if (isSyntheticAnonymousStructuralClass) {
1726
+ lines.push(`export type ${emittedName}${typeParameters} = ${emittedName}$instance${typeParameters};`);
1727
+ return lines;
1728
+ }
1729
+ lines.push(`export const ${emittedName}: {`);
1730
+ lines.push(` new(...args: unknown[]): ${emittedName}${typeParameters};`);
1031
1731
  const staticMembers = declaration.members.filter((member) => {
1032
1732
  if (member.kind === "constructorDeclaration")
1033
1733
  return false;
@@ -1035,26 +1735,26 @@ const renderClassInternal = (declaration, namespace, memberOverrides) => {
1035
1735
  });
1036
1736
  for (const member of staticMembers) {
1037
1737
  if (member.kind === "methodDeclaration") {
1038
- lines.push(` ${renderMethodSignature(member.name, member.typeParameters, member.parameters, member.returnType)}`);
1738
+ lines.push(` ${renderMethodSignature(member.name, member.typeParameters, member.parameters, member.returnType, localTypeNameRemaps)}`);
1039
1739
  continue;
1040
1740
  }
1041
1741
  if (member.kind === "propertyDeclaration") {
1042
- lines.push(` ${member.name}: ${renderPortableType(member.type)};`);
1742
+ lines.push(` ${member.name}: ${renderPortableType(member.type, typeParameterScope, localTypeNameRemaps)};`);
1043
1743
  }
1044
1744
  }
1045
1745
  lines.push("};");
1046
1746
  lines.push("");
1047
- lines.push(`export type ${declaration.name}${typeParameters} = ${declaration.name}$instance${typeParameters};`);
1747
+ lines.push(`export type ${emittedName}${typeParameters} = ${emittedName}$instance${typeParameters};`);
1048
1748
  lines.push("");
1049
1749
  return lines;
1050
1750
  };
1051
- const renderInterfaceInternal = (declaration, namespace, memberOverrides) => {
1751
+ const renderInterfaceInternal = (declaration, namespace, memberOverrides, emittedName = declaration.name, localTypeNameRemaps = new Map(), brandName = declaration.name, bindingAlias = declaration.name) => {
1052
1752
  const lines = [];
1053
1753
  const typeParameterScope = (declaration.typeParameters ?? []).map((typeParameter) => typeParameter.name);
1054
1754
  const typeParameters = printTypeParameters(declaration.typeParameters);
1055
- const markerName = `__tsonic_type_${sanitizeForBrand(namespace)}_${sanitizeForBrand(declaration.name)}`;
1755
+ const markerName = `__tsonic_type_${sanitizeForBrand(namespace)}_${sanitizeForBrand(brandName)}`;
1056
1756
  const extendsNames = declaration.extends
1057
- .map((baseType) => renderPortableType(baseType, typeParameterScope).trim())
1757
+ .map((baseType) => renderPortableType(baseType, typeParameterScope, localTypeNameRemaps).trim())
1058
1758
  .filter((name) => name.length > 0 &&
1059
1759
  name !== "unknown" &&
1060
1760
  name !== "never" &&
@@ -1062,11 +1762,12 @@ const renderInterfaceInternal = (declaration, namespace, memberOverrides) => {
1062
1762
  const extendsClause = extendsNames.length > 0
1063
1763
  ? ` extends ${Array.from(new Set(extendsNames)).join(", ")}`
1064
1764
  : "";
1065
- lines.push(`export interface ${declaration.name}$instance${typeParameters}${extendsClause} {`);
1765
+ lines.push(`export interface ${emittedName}$instance${typeParameters}${extendsClause} {`);
1066
1766
  lines.push(` readonly ${markerName}?: never;`);
1767
+ lines.push(renderBindingAliasMarker(namespace, bindingAlias));
1067
1768
  for (const member of declaration.members) {
1068
1769
  if (member.kind === "methodSignature") {
1069
- lines.push(` ${renderMethodSignature(member.name, member.typeParameters, member.parameters, member.returnType)}`);
1770
+ lines.push(` ${renderMethodSignature(member.name, member.typeParameters, member.parameters, member.returnType, localTypeNameRemaps)}`);
1070
1771
  continue;
1071
1772
  }
1072
1773
  if (member.kind === "propertySignature") {
@@ -1077,7 +1778,8 @@ const renderInterfaceInternal = (declaration, namespace, memberOverrides) => {
1077
1778
  const optionalMark = optionalBySource || member.isOptional ? "?" : "";
1078
1779
  const baseType = (memberOverride?.replaceWithSourceType
1079
1780
  ? memberOverride.sourceTypeText
1080
- : undefined) ?? renderPortableType(member.type);
1781
+ : undefined) ??
1782
+ renderPortableType(member.type, typeParameterScope, localTypeNameRemaps);
1081
1783
  const wrappedType = applyWrappersToBaseType(baseType, memberOverride?.wrappers ?? []);
1082
1784
  const memberType = memberOverride?.isOptional && !optionalBySource
1083
1785
  ? ensureUndefinedInType(wrappedType)
@@ -1087,13 +1789,13 @@ const renderInterfaceInternal = (declaration, namespace, memberOverrides) => {
1087
1789
  }
1088
1790
  lines.push("}");
1089
1791
  lines.push("");
1090
- lines.push(`export type ${declaration.name}${typeParameters} = ${declaration.name}$instance${typeParameters};`);
1792
+ lines.push(`export type ${emittedName}${typeParameters} = ${emittedName}$instance${typeParameters};`);
1091
1793
  lines.push("");
1092
1794
  return lines;
1093
1795
  };
1094
- const renderEnumInternal = (declaration) => {
1796
+ const renderEnumInternal = (declaration, emittedName = declaration.name) => {
1095
1797
  const lines = [];
1096
- lines.push(`export enum ${declaration.name} {`);
1798
+ lines.push(`export enum ${emittedName} {`);
1097
1799
  declaration.members.forEach((member, index) => {
1098
1800
  lines.push(` ${member.name} = ${index},`);
1099
1801
  });
@@ -1101,16 +1803,22 @@ const renderEnumInternal = (declaration) => {
1101
1803
  lines.push("");
1102
1804
  return lines;
1103
1805
  };
1104
- const renderStructuralAliasInternal = (declaration, namespace, memberOverrides) => {
1806
+ const renderStructuralAliasInternal = (declaration, namespace, memberOverrides, emittedName = declaration.name, localTypeNameRemaps = new Map(), brandAliasName = `${declaration.name}__Alias${(declaration.typeParameters?.length ?? 0) > 0
1807
+ ? `_${declaration.typeParameters?.length ?? 0}`
1808
+ : ""}`, bindingAlias = `${declaration.name}__Alias${(declaration.typeParameters?.length ?? 0) > 0
1809
+ ? `_${declaration.typeParameters?.length ?? 0}`
1810
+ : ""}`) => {
1105
1811
  if (declaration.type.kind !== "objectType")
1106
1812
  return [];
1107
1813
  const lines = [];
1108
1814
  const arity = declaration.typeParameters?.length ?? 0;
1109
1815
  const typeParameters = printTypeParameters(declaration.typeParameters);
1110
- const internalAliasName = `${declaration.name}__Alias${arity > 0 ? `_${arity}` : ""}`;
1111
- const markerName = `__tsonic_type_${sanitizeForBrand(namespace)}_${sanitizeForBrand(internalAliasName)}`;
1816
+ const typeParameterScope = (declaration.typeParameters ?? []).map((typeParameter) => typeParameter.name);
1817
+ const internalAliasName = `${emittedName}__Alias${arity > 0 ? `_${arity}` : ""}`;
1818
+ const markerName = `__tsonic_type_${sanitizeForBrand(namespace)}_${sanitizeForBrand(brandAliasName)}`;
1112
1819
  lines.push(`export interface ${internalAliasName}$instance${typeParameters} {`);
1113
1820
  lines.push(` readonly ${markerName}?: never;`);
1821
+ lines.push(renderBindingAliasMarker(namespace, bindingAlias));
1114
1822
  for (const member of declaration.type.members) {
1115
1823
  if (member.kind === "methodSignature") {
1116
1824
  lines.push(` ${renderMethodSignature(member.name, member.typeParameters, member.parameters, member.returnType)}`);
@@ -1121,7 +1829,8 @@ const renderStructuralAliasInternal = (declaration, namespace, memberOverrides)
1121
1829
  const optionalMark = member.isOptional ? "?" : "";
1122
1830
  const baseType = (memberOverride?.replaceWithSourceType
1123
1831
  ? memberOverride.sourceTypeText
1124
- : undefined) ?? renderPortableType(member.type);
1832
+ : undefined) ??
1833
+ renderPortableType(member.type, typeParameterScope, localTypeNameRemaps);
1125
1834
  const wrappedType = applyWrappersToBaseType(baseType, memberOverride?.wrappers ?? []);
1126
1835
  const memberType = memberOverride?.isOptional === true
1127
1836
  ? ensureUndefinedInType(wrappedType)
@@ -1129,20 +1838,73 @@ const renderStructuralAliasInternal = (declaration, namespace, memberOverrides)
1129
1838
  lines.push(` ${member.name}${optionalMark}: ${memberType};`);
1130
1839
  }
1131
1840
  }
1132
- lines.push("}");
1133
- lines.push("");
1134
- lines.push(`export type ${internalAliasName}${typeParameters} = ${internalAliasName}$instance${typeParameters};`);
1135
- lines.push("");
1136
- return lines;
1841
+ lines.push("}");
1842
+ lines.push("");
1843
+ lines.push(`export type ${internalAliasName}${typeParameters} = ${internalAliasName}$instance${typeParameters};`);
1844
+ lines.push("");
1845
+ return lines;
1846
+ };
1847
+ const renderTypeAliasInternal = (declaration, emittedName = declaration.name, localTypeNameRemaps = new Map(), anonymousStructuralAliases = new Map()) => {
1848
+ if (declaration.type.kind === "objectType")
1849
+ return [];
1850
+ const typeParameterScope = (declaration.typeParameters ?? []).map((typeParameter) => typeParameter.name);
1851
+ const typeParameters = printTypeParameters(declaration.typeParameters);
1852
+ return [
1853
+ `export type ${emittedName}${typeParameters} = ${renderPortableType(declaration.type, typeParameterScope, localTypeNameRemaps, anonymousStructuralAliases)};`,
1854
+ "",
1855
+ ];
1856
+ };
1857
+ const renderSourceAliasPlan = (plan, anonymousStructuralAliases) => {
1858
+ const sourceTypeParams = plan.sourceAlias?.typeParametersText ??
1859
+ printTypeParameters(plan.declaration.typeParameters);
1860
+ if (plan.declaration.type.kind === "objectType") {
1861
+ const arity = plan.declaration.typeParameters?.length ?? 0;
1862
+ const internalName = `${plan.declaration.name}__Alias${arity > 0 ? `_${arity}` : ""}`;
1863
+ const typeArgs = plan.sourceAlias && plan.sourceAlias.typeParameterNames.length > 0
1864
+ ? `<${plan.sourceAlias.typeParameterNames.join(", ")}>`
1865
+ : plan.declaration.typeParameters &&
1866
+ plan.declaration.typeParameters.length > 0
1867
+ ? `<${plan.declaration.typeParameters.map((tp) => tp.name).join(", ")}>`
1868
+ : "";
1869
+ return {
1870
+ line: `export type ${plan.declaration.name}${sourceTypeParams} = ${internalName}${typeArgs};`,
1871
+ internalImport: internalName,
1872
+ };
1873
+ }
1874
+ const rhs = renderPortableType(plan.declaration.type, plan.declaration.typeParameters?.map((tp) => tp.name) ?? [], new Map(), anonymousStructuralAliases);
1875
+ const shouldPreferSourceAliasText = plan.sourceAlias !== undefined &&
1876
+ !typeNodeUsesImportedTypeNames(plan.sourceAlias.type, plan.typeImportsByLocalName) &&
1877
+ /__\d+\b|\$instance\b/.test(rhs);
1878
+ return {
1879
+ line: `export type ${plan.declaration.name}${sourceTypeParams} = ${shouldPreferSourceAliasText
1880
+ ? rewriteSourceTypeText(plan.sourceAlias.typeText, new Map(), anonymousStructuralAliases)
1881
+ : rhs};`,
1882
+ };
1137
1883
  };
1138
- const renderContainerInternal = (entry) => {
1884
+ const renderContainerInternal = (entry, anonymousStructuralAliases) => {
1139
1885
  const lines = [];
1140
1886
  lines.push(`export abstract class ${entry.module.className}$instance {`);
1141
1887
  for (const method of entry.methods) {
1142
- lines.push(` static ${renderMethodSignature(method.localName, method.declaration.typeParameters, method.declaration.parameters, method.declaration.returnType)}`);
1888
+ const sourceSignature = renderSourceFunctionSignature({
1889
+ declaration: method.declaration,
1890
+ sourceSignatures: method.sourceSignatures,
1891
+ localTypeNameRemaps: method.localTypeNameRemaps,
1892
+ anonymousStructuralAliases,
1893
+ });
1894
+ lines.push(` static ${sourceSignature
1895
+ ? `${method.localName}${sourceSignature.typeParametersText}(${sourceSignature.parametersText}): ${sourceSignature.returnTypeText};`
1896
+ : renderMethodSignature(method.localName, method.declaration.typeParameters, method.declaration.parameters, method.declaration.returnType, method.localTypeNameRemaps, anonymousStructuralAliases)}`);
1143
1897
  }
1144
1898
  for (const variable of entry.variables) {
1145
- lines.push(` static ${variable.localName}: ${renderPortableType(variable.declarator?.type)};`);
1899
+ const sourceFunctionTypeText = renderSourceFunctionType({
1900
+ sourceSignatures: variable.sourceSignatures,
1901
+ localTypeNameRemaps: variable.localTypeNameRemaps,
1902
+ anonymousStructuralAliases,
1903
+ });
1904
+ const sourceTypeText = sourceFunctionTypeText ??
1905
+ renderSourceValueType(variable.sourceType, variable.localTypeNameRemaps, anonymousStructuralAliases);
1906
+ lines.push(` static ${variable.localName}: ${sourceTypeText ??
1907
+ renderPortableType(variable.declarator?.type, [], variable.localTypeNameRemaps, anonymousStructuralAliases)};`);
1146
1908
  }
1147
1909
  lines.push("}");
1148
1910
  lines.push("");
@@ -1150,7 +1912,7 @@ const renderContainerInternal = (entry) => {
1150
1912
  lines.push("");
1151
1913
  return lines;
1152
1914
  };
1153
- const buildTypeBindingFromClass = (declaration, namespace, assemblyName) => {
1915
+ const buildTypeBindingFromClass = (declaration, namespace, assemblyName, localTypeNameRemaps = new Map()) => {
1154
1916
  const declaringClrType = toClrTypeName(namespace, declaration.name, declaration.typeParameters?.length ?? 0);
1155
1917
  const typeStableId = toStableId(assemblyName, declaringClrType);
1156
1918
  const typeParameterScope = declaration.typeParameters?.map((typeParameter) => typeParameter.name) ??
@@ -1162,7 +1924,7 @@ const buildTypeBindingFromClass = (declaration, namespace, assemblyName) => {
1162
1924
  if (member.kind === "constructorDeclaration") {
1163
1925
  constructors.push({
1164
1926
  normalizedSignature: `.ctor|(${member.parameters
1165
- .map((parameter) => toSignatureType(parameter.type, typeParameterScope))
1927
+ .map((parameter) => toSignatureType(parameter.type, typeParameterScope, localTypeNameRemaps))
1166
1928
  .join(",")})|static=false`,
1167
1929
  isStatic: false,
1168
1930
  parameterCount: member.parameters.length,
@@ -1176,12 +1938,14 @@ const buildTypeBindingFromClass = (declaration, namespace, assemblyName) => {
1176
1938
  methodName: member.name,
1177
1939
  parameters: member.parameters,
1178
1940
  returnType: member.returnType,
1941
+ typeParameters: member.typeParameters,
1179
1942
  arity: member.typeParameters?.length ?? 0,
1180
1943
  parameterModifiers: buildParameterModifiers(member.parameters),
1181
1944
  isStatic: member.isStatic,
1182
1945
  isAbstract: member.body === undefined,
1183
1946
  isVirtual: member.isVirtual,
1184
1947
  isOverride: member.isOverride,
1948
+ localTypeNameRemaps,
1185
1949
  }));
1186
1950
  continue;
1187
1951
  }
@@ -1193,11 +1957,12 @@ const buildTypeBindingFromClass = (declaration, namespace, assemblyName) => {
1193
1957
  const hasSetter = hasAccessorBody
1194
1958
  ? member.setterBody !== undefined
1195
1959
  : !member.isReadonly;
1196
- const propertyType = toSignatureType(member.type, typeParameterScope);
1960
+ const propertyType = toSignatureType(member.type, typeParameterScope, localTypeNameRemaps);
1197
1961
  properties.push({
1198
1962
  stableId: `${typeStableId}::property:${member.name}`,
1199
1963
  clrName: member.name,
1200
1964
  normalizedSignature: `${member.name}|:${propertyType}|static=${member.isStatic ? "true" : "false"}|accessor=${hasGetter && hasSetter ? "getset" : hasSetter ? "set" : "get"}`,
1965
+ semanticType: rewriteBindingSemanticType(member.type, localTypeNameRemaps),
1201
1966
  isStatic: member.isStatic,
1202
1967
  isAbstract: member.getterBody === undefined && member.setterBody === undefined
1203
1968
  ? false
@@ -1215,6 +1980,7 @@ const buildTypeBindingFromClass = (declaration, namespace, assemblyName) => {
1215
1980
  return {
1216
1981
  stableId: typeStableId,
1217
1982
  clrName: declaringClrType,
1983
+ alias: toBindingTypeAlias(namespace, declaration.name, declaration.typeParameters?.length ?? 0),
1218
1984
  assemblyName,
1219
1985
  kind: declaration.isStruct ? "Struct" : "Class",
1220
1986
  accessibility: "Public",
@@ -1239,7 +2005,7 @@ const buildTypeBindingFromClass = (declaration, namespace, assemblyName) => {
1239
2005
  ],
1240
2006
  };
1241
2007
  };
1242
- const buildTypeBindingFromInterface = (declaration, namespace, assemblyName) => {
2008
+ const buildTypeBindingFromInterface = (declaration, namespace, assemblyName, localTypeNameRemaps = new Map()) => {
1243
2009
  const declaringClrType = toClrTypeName(namespace, declaration.name, declaration.typeParameters?.length ?? 0);
1244
2010
  const typeStableId = toStableId(assemblyName, declaringClrType);
1245
2011
  const typeParameterScope = declaration.typeParameters?.map((typeParameter) => typeParameter.name) ??
@@ -1254,17 +2020,21 @@ const buildTypeBindingFromInterface = (declaration, namespace, assemblyName) =>
1254
2020
  methodName: member.name,
1255
2021
  parameters: member.parameters,
1256
2022
  returnType: member.returnType,
2023
+ typeParameters: member.typeParameters,
1257
2024
  arity: member.typeParameters?.length ?? 0,
1258
2025
  parameterModifiers: buildParameterModifiers(member.parameters),
1259
2026
  isStatic: false,
1260
2027
  isAbstract: true,
2028
+ localTypeNameRemaps,
1261
2029
  }));
1262
2030
  continue;
1263
2031
  }
1264
2032
  properties.push({
1265
2033
  stableId: `${typeStableId}::property:${member.name}`,
1266
2034
  clrName: member.name,
1267
- normalizedSignature: `${member.name}|:${toSignatureType(member.type, typeParameterScope)}|static=false|accessor=${member.isReadonly ? "get" : "getset"}`,
2035
+ normalizedSignature: `${member.name}|:${toSignatureType(member.type, typeParameterScope, localTypeNameRemaps)}|static=false|accessor=${member.isReadonly ? "get" : "getset"}`,
2036
+ semanticType: rewriteBindingSemanticType(member.type, localTypeNameRemaps),
2037
+ semanticOptional: member.isOptional,
1268
2038
  isStatic: false,
1269
2039
  isAbstract: true,
1270
2040
  isVirtual: false,
@@ -1279,6 +2049,7 @@ const buildTypeBindingFromInterface = (declaration, namespace, assemblyName) =>
1279
2049
  return {
1280
2050
  stableId: typeStableId,
1281
2051
  clrName: declaringClrType,
2052
+ alias: toBindingTypeAlias(namespace, declaration.name, declaration.typeParameters?.length ?? 0),
1282
2053
  assemblyName,
1283
2054
  kind: declaration.isStruct ? "Struct" : "Interface",
1284
2055
  accessibility: "Public",
@@ -1311,6 +2082,7 @@ const buildTypeBindingFromEnum = (declaration, namespace, assemblyName) => {
1311
2082
  return {
1312
2083
  stableId: typeStableId,
1313
2084
  clrName: declaringClrType,
2085
+ alias: toBindingTypeAlias(namespace, declaration.name),
1314
2086
  assemblyName,
1315
2087
  kind: "Enum",
1316
2088
  accessibility: "Public",
@@ -1326,7 +2098,7 @@ const buildTypeBindingFromEnum = (declaration, namespace, assemblyName) => {
1326
2098
  constructors: [],
1327
2099
  };
1328
2100
  };
1329
- const buildTypeBindingFromStructuralAlias = (declaration, namespace, assemblyName) => {
2101
+ const buildTypeBindingFromStructuralAlias = (declaration, namespace, assemblyName, localTypeNameRemaps = new Map()) => {
1330
2102
  if (declaration.type.kind !== "objectType")
1331
2103
  return undefined;
1332
2104
  const arity = declaration.typeParameters?.length ?? 0;
@@ -1345,17 +2117,21 @@ const buildTypeBindingFromStructuralAlias = (declaration, namespace, assemblyNam
1345
2117
  methodName: member.name,
1346
2118
  parameters: member.parameters,
1347
2119
  returnType: member.returnType,
2120
+ typeParameters: member.typeParameters,
1348
2121
  arity: member.typeParameters?.length ?? 0,
1349
2122
  parameterModifiers: buildParameterModifiers(member.parameters),
1350
2123
  isStatic: false,
1351
2124
  isAbstract: true,
2125
+ localTypeNameRemaps,
1352
2126
  }));
1353
2127
  continue;
1354
2128
  }
1355
2129
  properties.push({
1356
2130
  stableId: `${typeStableId}::property:${member.name}`,
1357
2131
  clrName: member.name,
1358
- normalizedSignature: `${member.name}|:${toSignatureType(member.type, typeParameterScope)}|static=false|accessor=${member.isReadonly ? "get" : "getset"}`,
2132
+ normalizedSignature: `${member.name}|:${toSignatureType(member.type, typeParameterScope, localTypeNameRemaps)}|static=false|accessor=${member.isReadonly ? "get" : "getset"}`,
2133
+ semanticType: rewriteBindingSemanticType(member.type, localTypeNameRemaps),
2134
+ semanticOptional: member.isOptional,
1359
2135
  isStatic: false,
1360
2136
  isAbstract: true,
1361
2137
  isVirtual: false,
@@ -1370,6 +2146,7 @@ const buildTypeBindingFromStructuralAlias = (declaration, namespace, assemblyNam
1370
2146
  return {
1371
2147
  stableId: typeStableId,
1372
2148
  clrName: declaringClrType,
2149
+ alias: toBindingTypeAlias(namespace, internalAliasName, arity),
1373
2150
  assemblyName,
1374
2151
  kind: declaration.isStruct ? "Struct" : "Class",
1375
2152
  accessibility: "Public",
@@ -1398,11 +2175,13 @@ const buildTypeBindingFromContainer = (entry, namespace, assemblyName) => {
1398
2175
  arity: method.declaration.typeParameters?.length ?? 0,
1399
2176
  parameterModifiers: buildParameterModifiers(method.declaration.parameters),
1400
2177
  isStatic: true,
2178
+ localTypeNameRemaps: method.localTypeNameRemaps,
1401
2179
  }));
1402
2180
  const properties = entry.variables.map((variable) => ({
1403
2181
  stableId: `${typeStableId}::property:${variable.localName}`,
1404
2182
  clrName: variable.localName,
1405
- normalizedSignature: `${variable.localName}|:${toSignatureType(variable.declarator?.type, [])}|static=true|accessor=getset`,
2183
+ normalizedSignature: `${variable.localName}|:${toSignatureType(variable.declarator?.type, [], variable.localTypeNameRemaps)}|static=true|accessor=getset`,
2184
+ semanticType: rewriteBindingSemanticType(variable.declarator?.type, variable.localTypeNameRemaps),
1406
2185
  isStatic: true,
1407
2186
  isAbstract: false,
1408
2187
  isVirtual: false,
@@ -1416,6 +2195,7 @@ const buildTypeBindingFromContainer = (entry, namespace, assemblyName) => {
1416
2195
  return {
1417
2196
  stableId: typeStableId,
1418
2197
  clrName: declaringClrType,
2198
+ alias: toBindingTypeAlias(namespace, entry.module.className),
1419
2199
  assemblyName,
1420
2200
  kind: "Class",
1421
2201
  accessibility: "Public",
@@ -1451,37 +2231,112 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
1451
2231
  for (const [namespace, moduleList] of Array.from(modulesByNamespace.entries())) {
1452
2232
  const typeDeclarations = [];
1453
2233
  const moduleContainers = [];
2234
+ const crossNamespaceReexportsGrouped = new Map();
2235
+ const crossNamespaceTypeDeclarations = [];
2236
+ const seenCrossNamespaceTypeDeclarationKeys = new Set();
1454
2237
  const valueExportsMap = new Map();
1455
2238
  const seenTypeDeclarationKeys = new Set();
1456
- const sourceAliasLines = new Set();
1457
- const sourceAliasInternalImports = new Set();
2239
+ const sourceAliasPlans = [];
1458
2240
  const memberOverrides = [];
2241
+ const internalTypeImportByAlias = new Map();
2242
+ const facadeTypeImportByAlias = new Map();
1459
2243
  const wrapperImportByAlias = new Map();
2244
+ const internalHelperTypeDeclarationsByKey = new Map();
2245
+ const internalHelperTypeRemapsByModuleKey = new Map();
2246
+ const getInternalHelperTypeName = (moduleFileKey, localName) => {
2247
+ return `__Local_${sanitizeForBrand(moduleFileKey)}_${sanitizeForBrand(localName)}`;
2248
+ };
2249
+ const registerInternalHelperTypeClosure = (opts) => {
2250
+ if (!opts.sourceIndex)
2251
+ return { ok: true, value: new Map() };
2252
+ const moduleFileKey = normalizeModuleFileKey(opts.declarationModule.filePath);
2253
+ const remaps = internalHelperTypeRemapsByModuleKey.get(moduleFileKey) ?? new Map();
2254
+ if (!internalHelperTypeRemapsByModuleKey.has(moduleFileKey)) {
2255
+ internalHelperTypeRemapsByModuleKey.set(moduleFileKey, remaps);
2256
+ }
2257
+ const visiting = new Set();
2258
+ const visitLocalType = (localName) => {
2259
+ if (opts.sourceIndex?.exportedTypeDeclarationNames.has(localName)) {
2260
+ return { ok: true, value: undefined };
2261
+ }
2262
+ const declaration = resolveModuleLocalDeclaration(opts.declarationModule, localName);
2263
+ if (!declaration)
2264
+ return { ok: true, value: undefined };
2265
+ const kind = classifyLocalTypeDeclarationKind(declaration);
2266
+ if (!kind)
2267
+ return { ok: true, value: undefined };
2268
+ const localTypeDeclaration = declaration;
2269
+ const key = `${moduleFileKey}::${localName}`;
2270
+ if (!remaps.has(localName)) {
2271
+ remaps.set(localName, getInternalHelperTypeName(moduleFileKey, localName));
2272
+ }
2273
+ if (internalHelperTypeDeclarationsByKey.has(key)) {
2274
+ return { ok: true, value: undefined };
2275
+ }
2276
+ if (visiting.has(key))
2277
+ return { ok: true, value: undefined };
2278
+ visiting.add(key);
2279
+ const nestedReferencedNames = new Set();
2280
+ collectReferencedPortableTypeNamesFromDeclaration(localTypeDeclaration, nestedReferencedNames);
2281
+ for (const nestedName of nestedReferencedNames) {
2282
+ const visited = visitLocalType(nestedName);
2283
+ if (!visited.ok)
2284
+ return visited;
2285
+ }
2286
+ visiting.delete(key);
2287
+ const emittedName = remaps.get(localName);
2288
+ if (!emittedName) {
2289
+ return {
2290
+ ok: false,
2291
+ error: `Internal error: missing emitted name remap for local helper '${localName}'.`,
2292
+ };
2293
+ }
2294
+ internalHelperTypeDeclarationsByKey.set(key, {
2295
+ key,
2296
+ moduleFileKey,
2297
+ declaringNamespace: opts.declarationModule.namespace,
2298
+ emittedName,
2299
+ originalName: localName,
2300
+ kind,
2301
+ declaration: localTypeDeclaration,
2302
+ });
2303
+ return { ok: true, value: undefined };
2304
+ };
2305
+ for (const referencedName of opts.referencedNames) {
2306
+ const visited = visitLocalType(referencedName);
2307
+ if (!visited.ok)
2308
+ return visited;
2309
+ }
2310
+ return { ok: true, value: new Map(remaps) };
2311
+ };
1460
2312
  const registerValueExport = (valueExport) => {
1461
2313
  const existing = valueExportsMap.get(valueExport.exportName);
1462
2314
  if (!existing) {
1463
2315
  valueExportsMap.set(valueExport.exportName, valueExport);
1464
2316
  return { ok: true, value: undefined };
1465
2317
  }
1466
- const sameBinding = existing.binding.kind === valueExport.binding.kind &&
1467
- existing.binding.clrName === valueExport.binding.clrName &&
1468
- existing.binding.declaringClrType ===
1469
- valueExport.binding.declaringClrType &&
1470
- existing.binding.declaringAssemblyName ===
1471
- valueExport.binding.declaringAssemblyName;
2318
+ const sameBinding = areBindingSemanticsEqual(existing.binding, valueExport.binding);
1472
2319
  const normalizeFunctionFacade = (facade) => {
1473
2320
  const declaration = facade.declaration;
1474
2321
  const typeParametersText = printTypeParameters(declaration.typeParameters);
1475
2322
  const typeParameterNames = declaration.typeParameters?.map((typeParameter) => typeParameter.name) ?? [];
1476
- const parametersText = renderUnknownParameters(declaration.parameters, typeParameterNames);
1477
- const returnTypeText = renderPortableType(declaration.returnType, typeParameterNames);
2323
+ const parametersText = renderUnknownParameters(declaration.parameters, typeParameterNames, facade.localTypeNameRemaps);
2324
+ const returnTypeText = renderPortableType(declaration.returnType, typeParameterNames, facade.localTypeNameRemaps);
1478
2325
  const sourceSignatures = (facade.sourceSignatures ?? [])
1479
- .map((signature) => `${signature.typeParametersText}(${signature.parametersText}):${signature.returnTypeText}`)
2326
+ .map((signature) => `${signature.typeParametersText}(${signature.parameters
2327
+ .map((parameter) => `${parameter.prefixText}${parameter.typeText}`)
2328
+ .join(", ")}):${signature.returnTypeText}`)
1480
2329
  .sort((left, right) => left.localeCompare(right))
1481
2330
  .join("||");
1482
2331
  return `${typeParametersText}(${parametersText}):${returnTypeText}|source=${sourceSignatures}`;
1483
2332
  };
1484
- const normalizeVariableFacade = (declarator) => renderPortableType(declarator?.type);
2333
+ const normalizeVariableFacade = (declarator, localTypeNameRemaps) => {
2334
+ const functionType = resolveFunctionTypeFromValueDeclarator(declarator);
2335
+ if (functionType) {
2336
+ return JSON.stringify(buildSemanticSignatureFromFunctionType(functionType, localTypeNameRemaps));
2337
+ }
2338
+ return renderPortableType(declarator?.type, [], localTypeNameRemaps);
2339
+ };
1485
2340
  const sameFacade = (() => {
1486
2341
  if (existing.facade.kind !== valueExport.facade.kind)
1487
2342
  return false;
@@ -1492,8 +2347,8 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
1492
2347
  }
1493
2348
  if (existing.facade.kind === "variable" &&
1494
2349
  valueExport.facade.kind === "variable") {
1495
- return (normalizeVariableFacade(existing.facade.declarator) ===
1496
- normalizeVariableFacade(valueExport.facade.declarator));
2350
+ return (normalizeVariableFacade(existing.facade.declarator, existing.facade.localTypeNameRemaps) ===
2351
+ normalizeVariableFacade(valueExport.facade.declarator, valueExport.facade.localTypeNameRemaps));
1497
2352
  }
1498
2353
  return false;
1499
2354
  })();
@@ -1526,32 +2381,113 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
1526
2381
  }
1527
2382
  return { ok: true, value: undefined };
1528
2383
  };
2384
+ const registerCrossNamespaceReexport = (opts) => {
2385
+ if (opts.declaringNamespace === namespace)
2386
+ return;
2387
+ const moduleSpecifier = `./${moduleNamespacePath(opts.declaringNamespace)}.js`;
2388
+ const key = `${moduleSpecifier}|${opts.kind}`;
2389
+ const specifier = opts.exportName === opts.localName
2390
+ ? opts.exportName
2391
+ : `${opts.localName} as ${opts.exportName}`;
2392
+ const existing = crossNamespaceReexportsGrouped.get(key) ?? [];
2393
+ existing.push(specifier);
2394
+ crossNamespaceReexportsGrouped.set(key, existing);
2395
+ };
2396
+ const registerCrossNamespaceTypeDeclaration = (symbol) => {
2397
+ if (symbol.declaringNamespace === namespace)
2398
+ return;
2399
+ const key = `${symbol.declaringNamespace}|${symbol.declaringClassName}|${symbol.localName}|${symbol.kind}`;
2400
+ if (seenCrossNamespaceTypeDeclarationKeys.has(key))
2401
+ return;
2402
+ seenCrossNamespaceTypeDeclarationKeys.add(key);
2403
+ crossNamespaceTypeDeclarations.push(symbol);
2404
+ };
2405
+ const registerSourceTypeImportCandidates = (sourceIndex, moduleKey, moduleFilePath) => {
2406
+ for (const [localName, imported] of sourceIndex.typeImportsByLocalName) {
2407
+ if (sourceIndex.wrapperImportsByLocalName.has(localName))
2408
+ continue;
2409
+ const internalImport = resolveSourceTypeImportBinding({
2410
+ context: "internal",
2411
+ currentNamespace: namespace,
2412
+ currentModuleKey: moduleKey,
2413
+ localName,
2414
+ imported,
2415
+ modulesByFileKey,
2416
+ });
2417
+ if (!internalImport.ok)
2418
+ return internalImport;
2419
+ if (internalImport.value) {
2420
+ const registered = registerSourceTypeImportBinding(internalTypeImportByAlias, internalImport.value, namespace, moduleFilePath);
2421
+ if (!registered.ok)
2422
+ return registered;
2423
+ }
2424
+ const facadeImport = resolveSourceTypeImportBinding({
2425
+ context: "facade",
2426
+ currentNamespace: namespace,
2427
+ currentModuleKey: moduleKey,
2428
+ localName,
2429
+ imported,
2430
+ modulesByFileKey,
2431
+ });
2432
+ if (!facadeImport.ok)
2433
+ return facadeImport;
2434
+ if (facadeImport.value) {
2435
+ const registered = registerSourceTypeImportBinding(facadeTypeImportByAlias, facadeImport.value, namespace, moduleFilePath);
2436
+ if (!registered.ok)
2437
+ return registered;
2438
+ }
2439
+ }
2440
+ return { ok: true, value: undefined };
2441
+ };
2442
+ const registerFacadeLocalTypeReferenceImports = (opts) => {
2443
+ const typeParameterNames = new Set((opts.typeParameters ?? []).map((typeParameter) => typeParameter.name));
2444
+ const referencedNames = new Set();
2445
+ for (const parameterType of opts.parameterTypes) {
2446
+ collectReferencedPortableTypeNames(parameterType, typeParameterNames, referencedNames);
2447
+ }
2448
+ collectReferencedPortableTypeNames(opts.returnType, typeParameterNames, referencedNames);
2449
+ const helperTypeRemaps = registerInternalHelperTypeClosure({
2450
+ declarationModule: opts.declarationModule,
2451
+ sourceIndex: opts.sourceIndex,
2452
+ referencedNames,
2453
+ });
2454
+ if (!helperTypeRemaps.ok)
2455
+ return helperTypeRemaps;
2456
+ if (!opts.sourceIndex)
2457
+ return helperTypeRemaps;
2458
+ if (opts.declarationNamespace === namespace) {
2459
+ return helperTypeRemaps;
2460
+ }
2461
+ const moduleSpecifier = `./${moduleNamespacePath(opts.declarationNamespace)}.js`;
2462
+ for (const referencedName of referencedNames) {
2463
+ if (!opts.sourceIndex.exportedTypeDeclarationNames.has(referencedName)) {
2464
+ continue;
2465
+ }
2466
+ const registered = registerSourceTypeImportBinding(facadeTypeImportByAlias, {
2467
+ importedName: referencedName,
2468
+ localName: referencedName,
2469
+ source: moduleSpecifier,
2470
+ }, namespace, opts.declarationFilePath);
2471
+ if (!registered.ok)
2472
+ return registered;
2473
+ }
2474
+ return helperTypeRemaps;
2475
+ };
1529
2476
  for (const module of moduleList.sort((left, right) => left.filePath.localeCompare(right.filePath))) {
1530
2477
  const moduleKey = normalizeModuleFileKey(module.filePath);
1531
2478
  const sourceIndex = sourceIndexByFileKey.get(moduleKey);
1532
2479
  if (sourceIndex) {
2480
+ const registered = registerSourceTypeImportCandidates(sourceIndex, moduleKey, module.filePath);
2481
+ if (!registered.ok)
2482
+ return registered;
1533
2483
  const exportedAliasDecls = module.body.filter((stmt) => stmt.kind === "typeAliasDeclaration" && stmt.isExported);
1534
2484
  for (const alias of exportedAliasDecls) {
1535
2485
  const sourceAlias = sourceIndex.typeAliasesByName.get(alias.name);
1536
- const sourceTypeParams = sourceAlias?.typeParametersText ??
1537
- printTypeParameters(alias.typeParameters);
1538
- if (alias.type.kind === "objectType") {
1539
- const arity = alias.typeParameters?.length ?? 0;
1540
- const internalName = `${alias.name}__Alias${arity > 0 ? `_${arity}` : ""}`;
1541
- const typeArgs = sourceAlias && sourceAlias.typeParameterNames.length > 0
1542
- ? `<${sourceAlias.typeParameterNames.join(", ")}>`
1543
- : alias.typeParameters && alias.typeParameters.length > 0
1544
- ? `<${alias.typeParameters.map((tp) => tp.name).join(", ")}>`
1545
- : "";
1546
- sourceAliasLines.add(`export type ${alias.name}${sourceTypeParams} = ${internalName}${typeArgs};`);
1547
- sourceAliasInternalImports.add(internalName);
1548
- continue;
1549
- }
1550
- const rhs = renderPortableType(alias.type, alias.typeParameters?.map((tp) => tp.name) ?? []);
1551
- const shouldPreferSourceAliasText = sourceAlias !== undefined &&
1552
- !typeNodeUsesImportedTypeNames(sourceAlias.type, sourceIndex.typeImportsByLocalName) &&
1553
- /__\d+\b|\$instance\b/.test(rhs);
1554
- sourceAliasLines.add(`export type ${alias.name}${sourceTypeParams} = ${shouldPreferSourceAliasText ? sourceAlias.typeText : rhs};`);
2486
+ sourceAliasPlans.push({
2487
+ declaration: alias,
2488
+ sourceAlias,
2489
+ typeImportsByLocalName: sourceIndex.typeImportsByLocalName,
2490
+ });
1555
2491
  }
1556
2492
  const exportedClasses = module.body.filter((stmt) => stmt.kind === "classDeclaration" && stmt.isExported);
1557
2493
  const exportedInterfaces = module.body.filter((stmt) => stmt.kind === "interfaceDeclaration" && stmt.isExported);
@@ -1692,6 +2628,17 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
1692
2628
  const exportKind = classifyDeclarationKind(declaration, declarationModule.filePath, exportItem.name);
1693
2629
  if (!exportKind.ok)
1694
2630
  return exportKind;
2631
+ if (declarationModule.namespace !== namespace) {
2632
+ registerCrossNamespaceReexport({
2633
+ declaringNamespace: declarationModule.namespace,
2634
+ exportName: exportItem.name,
2635
+ localName: resolved.value.clrName,
2636
+ kind: exportKind.value === "interface" ||
2637
+ exportKind.value === "typeAlias"
2638
+ ? "type"
2639
+ : "value",
2640
+ });
2641
+ }
1695
2642
  if (exportKind.value === "function") {
1696
2643
  const functionDeclaration = declaration.kind === "functionDeclaration"
1697
2644
  ? declaration
@@ -1702,6 +2649,24 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
1702
2649
  error: `Invalid function export '${exportItem.name}' in ${declarationModule.filePath}: expected function declaration.`,
1703
2650
  };
1704
2651
  }
2652
+ const declarationModuleKey = normalizeModuleFileKey(declarationModule.filePath);
2653
+ const declarationSourceIndex = sourceIndexByFileKey.get(declarationModuleKey);
2654
+ if (declarationSourceIndex) {
2655
+ const registered = registerSourceTypeImportCandidates(declarationSourceIndex, declarationModuleKey, declarationModule.filePath);
2656
+ if (!registered.ok)
2657
+ return registered;
2658
+ }
2659
+ const registeredLocalTypeRefs = registerFacadeLocalTypeReferenceImports({
2660
+ declarationModule,
2661
+ declarationNamespace: declarationModule.namespace,
2662
+ declarationFilePath: declarationModule.filePath,
2663
+ sourceIndex: declarationSourceIndex,
2664
+ typeParameters: functionDeclaration.typeParameters,
2665
+ parameterTypes: functionDeclaration.parameters.map((parameter) => parameter.type),
2666
+ returnType: functionDeclaration.returnType,
2667
+ });
2668
+ if (!registeredLocalTypeRefs.ok)
2669
+ return registeredLocalTypeRefs;
1705
2670
  const registered = registerValueExport({
1706
2671
  exportName: exportItem.name,
1707
2672
  binding: {
@@ -1713,6 +2678,7 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
1713
2678
  facade: {
1714
2679
  kind: "function",
1715
2680
  declaration: functionDeclaration,
2681
+ localTypeNameRemaps: registeredLocalTypeRefs.value,
1716
2682
  sourceSignatures: sourceIndexByFileKey
1717
2683
  .get(normalizeModuleFileKey(declarationModule.filePath))
1718
2684
  ?.exportedFunctionSignaturesByName.get(resolved.value.clrName) ?? [],
@@ -1732,23 +2698,63 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
1732
2698
  error: `Invalid variable export '${exportItem.name}' in ${declarationModule.filePath}: expected variable declaration.`,
1733
2699
  };
1734
2700
  }
2701
+ const declarationModuleKey = normalizeModuleFileKey(declarationModule.filePath);
2702
+ const declarationSourceIndex = sourceIndexByFileKey.get(declarationModuleKey);
2703
+ if (declarationSourceIndex) {
2704
+ const registered = registerSourceTypeImportCandidates(declarationSourceIndex, declarationModuleKey, declarationModule.filePath);
2705
+ if (!registered.ok)
2706
+ return registered;
2707
+ }
1735
2708
  const declarator = declarationStatement.declarations.find((candidate) => candidate.name.kind === "identifierPattern" &&
1736
2709
  candidate.name.name === resolved.value.clrName);
2710
+ const exportedFunctionType = resolveFunctionTypeFromValueDeclarator(declarator && declarator.name.kind === "identifierPattern"
2711
+ ? {
2712
+ kind: declarator.kind,
2713
+ name: declarator.name,
2714
+ type: declarator.type,
2715
+ initializer: declarator.initializer,
2716
+ }
2717
+ : undefined);
2718
+ const registeredLocalTypeRefs = registerFacadeLocalTypeReferenceImports({
2719
+ declarationModule,
2720
+ declarationNamespace: declarationModule.namespace,
2721
+ declarationFilePath: declarationModule.filePath,
2722
+ sourceIndex: declarationSourceIndex,
2723
+ typeParameters: undefined,
2724
+ parameterTypes: exportedFunctionType
2725
+ ? [exportedFunctionType]
2726
+ : declarator?.type
2727
+ ? [declarator.type]
2728
+ : [],
2729
+ returnType: undefined,
2730
+ });
2731
+ if (!registeredLocalTypeRefs.ok)
2732
+ return registeredLocalTypeRefs;
1737
2733
  const registered = registerValueExport({
1738
2734
  exportName: exportItem.name,
1739
2735
  binding: {
1740
- kind: "field",
2736
+ kind: exportedFunctionType ? "functionType" : "field",
1741
2737
  clrName: resolved.value.clrName,
1742
2738
  declaringClrType: toClrTypeName(declarationModule.namespace, declarationModule.className),
1743
2739
  declaringAssemblyName: assemblyName,
2740
+ semanticType: exportedFunctionType
2741
+ ? undefined
2742
+ : rewriteBindingSemanticType(declarator?.type, registeredLocalTypeRefs.value),
2743
+ semanticSignature: exportedFunctionType
2744
+ ? buildSemanticSignatureFromFunctionType(exportedFunctionType, registeredLocalTypeRefs.value)
2745
+ : undefined,
1744
2746
  },
1745
2747
  facade: {
1746
2748
  kind: "variable",
2749
+ localTypeNameRemaps: registeredLocalTypeRefs.value,
2750
+ sourceType: declarationSourceIndex?.exportedValueTypesByName.get(resolved.value.clrName),
2751
+ sourceSignatures: declarationSourceIndex?.exportedFunctionSignaturesByName.get(resolved.value.clrName) ?? [],
1747
2752
  declarator: declarator && declarator.name.kind === "identifierPattern"
1748
2753
  ? {
1749
2754
  kind: declarator.kind,
1750
2755
  name: declarator.name,
1751
2756
  type: declarator.type,
2757
+ initializer: declarator.initializer,
1752
2758
  }
1753
2759
  : undefined,
1754
2760
  },
@@ -1761,6 +2767,25 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
1761
2767
  exportKind.value === "interface" ||
1762
2768
  exportKind.value === "enum" ||
1763
2769
  exportKind.value === "typeAlias") {
2770
+ if (declarationModule.namespace !== namespace) {
2771
+ registerCrossNamespaceTypeDeclaration({
2772
+ exportName: exportItem.name,
2773
+ localName: resolved.value.clrName,
2774
+ kind: exportKind.value,
2775
+ declaration,
2776
+ declaringNamespace: declarationModule.namespace,
2777
+ declaringClassName: declarationModule.className,
2778
+ declaringFilePath: declarationModule.filePath,
2779
+ });
2780
+ continue;
2781
+ }
2782
+ const declarationModuleKey = normalizeModuleFileKey(declarationModule.filePath);
2783
+ const declarationSourceIndex = sourceIndexByFileKey.get(declarationModuleKey);
2784
+ if (declarationSourceIndex) {
2785
+ const registered = registerSourceTypeImportCandidates(declarationSourceIndex, declarationModuleKey, declarationModule.filePath);
2786
+ if (!registered.ok)
2787
+ return registered;
2788
+ }
1764
2789
  if (exportKind.value === "typeAlias" &&
1765
2790
  declaration.kind === "typeAliasDeclaration" &&
1766
2791
  declaration.type.kind !== "objectType") {
@@ -1812,6 +2837,18 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
1812
2837
  symbol.kind === "interface" ||
1813
2838
  symbol.kind === "enum" ||
1814
2839
  symbol.kind === "typeAlias") {
2840
+ if (symbol.declaringNamespace !== namespace) {
2841
+ registerCrossNamespaceReexport({
2842
+ declaringNamespace: symbol.declaringNamespace,
2843
+ exportName: symbol.exportName,
2844
+ localName: symbol.localName,
2845
+ kind: symbol.kind === "interface" || symbol.kind === "typeAlias"
2846
+ ? "type"
2847
+ : "value",
2848
+ });
2849
+ registerCrossNamespaceTypeDeclaration(symbol);
2850
+ continue;
2851
+ }
1815
2852
  if (symbol.kind === "typeAlias" &&
1816
2853
  symbol.declaration.kind === "typeAliasDeclaration" &&
1817
2854
  symbol.declaration.type.kind !== "objectType") {
@@ -1824,11 +2861,45 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
1824
2861
  }
1825
2862
  }
1826
2863
  if (symbol.kind === "function") {
2864
+ if (symbol.declaringNamespace !== namespace) {
2865
+ registerCrossNamespaceReexport({
2866
+ declaringNamespace: symbol.declaringNamespace,
2867
+ exportName: symbol.exportName,
2868
+ localName: symbol.localName,
2869
+ kind: "value",
2870
+ });
2871
+ }
1827
2872
  const functionDeclaration = symbol.declaration.kind === "functionDeclaration"
1828
2873
  ? symbol.declaration
1829
2874
  : undefined;
1830
2875
  if (!functionDeclaration)
1831
2876
  continue;
2877
+ const symbolModuleKey = normalizeModuleFileKey(symbol.declaringFilePath);
2878
+ const symbolSourceIndex = sourceIndexByFileKey.get(symbolModuleKey);
2879
+ const symbolDeclarationModule = modulesByFileKey.get(symbolModuleKey);
2880
+ if (!symbolDeclarationModule) {
2881
+ return {
2882
+ ok: false,
2883
+ error: `Unable to resolve declaring module for '${symbol.exportName}' while generating ${symbol.declaringFilePath}.\n` +
2884
+ "First-party bindings generation requires a stable source module for each exported value.",
2885
+ };
2886
+ }
2887
+ if (symbolSourceIndex) {
2888
+ const registered = registerSourceTypeImportCandidates(symbolSourceIndex, symbolModuleKey, symbol.declaringFilePath);
2889
+ if (!registered.ok)
2890
+ return registered;
2891
+ }
2892
+ const registeredLocalTypeRefs = registerFacadeLocalTypeReferenceImports({
2893
+ declarationModule: symbolDeclarationModule,
2894
+ declarationNamespace: symbol.declaringNamespace,
2895
+ declarationFilePath: symbol.declaringFilePath,
2896
+ sourceIndex: symbolSourceIndex,
2897
+ typeParameters: functionDeclaration.typeParameters,
2898
+ parameterTypes: functionDeclaration.parameters.map((parameter) => parameter.type),
2899
+ returnType: functionDeclaration.returnType,
2900
+ });
2901
+ if (!registeredLocalTypeRefs.ok)
2902
+ return registeredLocalTypeRefs;
1832
2903
  const isLocalContainerMember = symbol.declaringNamespace === module.namespace &&
1833
2904
  symbol.declaringClassName === module.className;
1834
2905
  if (isLocalContainerMember) {
@@ -1836,6 +2907,11 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
1836
2907
  exportName: symbol.exportName,
1837
2908
  localName: symbol.localName,
1838
2909
  declaration: functionDeclaration,
2910
+ localTypeNameRemaps: registeredLocalTypeRefs.value,
2911
+ sourceSignatures: sourceIndexByFileKey
2912
+ .get(normalizeModuleFileKey(symbol.declaringFilePath))
2913
+ ?.exportedFunctionSignaturesByName.get(symbol.localName) ??
2914
+ [],
1839
2915
  });
1840
2916
  }
1841
2917
  const registered = registerValueExport({
@@ -1849,6 +2925,7 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
1849
2925
  facade: {
1850
2926
  kind: "function",
1851
2927
  declaration: functionDeclaration,
2928
+ localTypeNameRemaps: registeredLocalTypeRefs.value,
1852
2929
  sourceSignatures: sourceIndexByFileKey
1853
2930
  .get(normalizeModuleFileKey(symbol.declaringFilePath))
1854
2931
  ?.exportedFunctionSignaturesByName.get(symbol.localName) ??
@@ -1860,13 +2937,60 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
1860
2937
  continue;
1861
2938
  }
1862
2939
  if (symbol.kind === "variable") {
2940
+ if (symbol.declaringNamespace !== namespace) {
2941
+ registerCrossNamespaceReexport({
2942
+ declaringNamespace: symbol.declaringNamespace,
2943
+ exportName: symbol.exportName,
2944
+ localName: symbol.localName,
2945
+ kind: "value",
2946
+ });
2947
+ }
1863
2948
  const declaration = symbol.declaration.kind === "variableDeclaration"
1864
2949
  ? symbol.declaration
1865
2950
  : undefined;
1866
2951
  if (!declaration)
1867
2952
  continue;
2953
+ const symbolModuleKey = normalizeModuleFileKey(symbol.declaringFilePath);
2954
+ const symbolSourceIndex = sourceIndexByFileKey.get(symbolModuleKey);
2955
+ const symbolDeclarationModule = modulesByFileKey.get(symbolModuleKey);
2956
+ if (!symbolDeclarationModule) {
2957
+ return {
2958
+ ok: false,
2959
+ error: `Unable to resolve declaring module for '${symbol.exportName}' while generating ${symbol.declaringFilePath}.\n` +
2960
+ "First-party bindings generation requires a stable source module for each exported value.",
2961
+ };
2962
+ }
2963
+ if (symbolSourceIndex) {
2964
+ const registered = registerSourceTypeImportCandidates(symbolSourceIndex, symbolModuleKey, symbol.declaringFilePath);
2965
+ if (!registered.ok)
2966
+ return registered;
2967
+ }
1868
2968
  const declarator = declaration.declarations.find((candidate) => candidate.name.kind === "identifierPattern" &&
1869
2969
  candidate.name.name === symbol.localName);
2970
+ const exportDeclarator = declarator && declarator.name.kind === "identifierPattern"
2971
+ ? {
2972
+ kind: declarator.kind,
2973
+ name: declarator.name,
2974
+ type: declarator.type,
2975
+ initializer: declarator.initializer,
2976
+ }
2977
+ : undefined;
2978
+ const exportedFunctionType = resolveFunctionTypeFromValueDeclarator(exportDeclarator);
2979
+ const registeredLocalTypeRefs = registerFacadeLocalTypeReferenceImports({
2980
+ declarationModule: symbolDeclarationModule,
2981
+ declarationNamespace: symbol.declaringNamespace,
2982
+ declarationFilePath: symbol.declaringFilePath,
2983
+ sourceIndex: symbolSourceIndex,
2984
+ typeParameters: undefined,
2985
+ parameterTypes: exportedFunctionType
2986
+ ? [exportedFunctionType]
2987
+ : declarator?.type
2988
+ ? [declarator.type]
2989
+ : [],
2990
+ returnType: undefined,
2991
+ });
2992
+ if (!registeredLocalTypeRefs.ok)
2993
+ return registeredLocalTypeRefs;
1870
2994
  const isLocalContainerMember = symbol.declaringNamespace === module.namespace &&
1871
2995
  symbol.declaringClassName === module.className;
1872
2996
  if (isLocalContainerMember) {
@@ -1874,32 +2998,37 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
1874
2998
  exportName: symbol.exportName,
1875
2999
  localName: symbol.localName,
1876
3000
  declaration,
1877
- declarator: declarator && declarator.name.kind === "identifierPattern"
1878
- ? {
1879
- kind: declarator.kind,
1880
- name: declarator.name,
1881
- type: declarator.type,
1882
- }
1883
- : undefined,
3001
+ declarator: exportDeclarator,
3002
+ localTypeNameRemaps: registeredLocalTypeRefs.value,
3003
+ sourceType: sourceIndexByFileKey
3004
+ .get(normalizeModuleFileKey(symbol.declaringFilePath))
3005
+ ?.exportedValueTypesByName.get(symbol.localName),
3006
+ sourceSignatures: sourceIndexByFileKey
3007
+ .get(normalizeModuleFileKey(symbol.declaringFilePath))
3008
+ ?.exportedFunctionSignaturesByName.get(symbol.localName) ??
3009
+ [],
1884
3010
  });
1885
3011
  }
1886
3012
  const registered = registerValueExport({
1887
3013
  exportName: symbol.exportName,
1888
3014
  binding: {
1889
- kind: "field",
3015
+ kind: exportedFunctionType ? "functionType" : "field",
1890
3016
  clrName: symbol.localName,
1891
3017
  declaringClrType: toClrTypeName(symbol.declaringNamespace, symbol.declaringClassName),
1892
3018
  declaringAssemblyName: assemblyName,
3019
+ semanticType: exportedFunctionType
3020
+ ? undefined
3021
+ : rewriteBindingSemanticType(exportDeclarator?.type, registeredLocalTypeRefs.value),
3022
+ semanticSignature: exportedFunctionType
3023
+ ? buildSemanticSignatureFromFunctionType(exportedFunctionType, registeredLocalTypeRefs.value)
3024
+ : undefined,
1893
3025
  },
1894
3026
  facade: {
1895
3027
  kind: "variable",
1896
- declarator: declarator && declarator.name.kind === "identifierPattern"
1897
- ? {
1898
- kind: declarator.kind,
1899
- name: declarator.name,
1900
- type: declarator.type,
1901
- }
1902
- : undefined,
3028
+ localTypeNameRemaps: registeredLocalTypeRefs.value,
3029
+ sourceType: symbolSourceIndex?.exportedValueTypesByName.get(symbol.localName),
3030
+ sourceSignatures: symbolSourceIndex?.exportedFunctionSignaturesByName.get(symbol.localName) ?? [],
3031
+ declarator: exportDeclarator,
1903
3032
  },
1904
3033
  });
1905
3034
  if (!registered.ok)
@@ -1914,18 +3043,113 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
1914
3043
  });
1915
3044
  }
1916
3045
  }
3046
+ const anonymousHelperClassNamesByShape = new Map();
3047
+ const registerAnonymousHelperClass = (emittedName, declaration) => {
3048
+ if (!emittedName.startsWith("__Anon_") &&
3049
+ !declaration.name.startsWith("__Anon_")) {
3050
+ return;
3051
+ }
3052
+ const members = [];
3053
+ for (const member of declaration.members) {
3054
+ if (member.kind === "propertyDeclaration") {
3055
+ if (isPortableMarkerMemberName(member.name))
3056
+ continue;
3057
+ members.push({
3058
+ kind: "propertySignature",
3059
+ name: member.name,
3060
+ type: member.type ?? { kind: "unknownType" },
3061
+ isOptional: false,
3062
+ isReadonly: member.isReadonly,
3063
+ });
3064
+ continue;
3065
+ }
3066
+ if (member.kind === "methodDeclaration") {
3067
+ if (isPortableMarkerMemberName(member.name))
3068
+ continue;
3069
+ members.push({
3070
+ kind: "methodSignature",
3071
+ name: member.name,
3072
+ parameters: member.parameters,
3073
+ returnType: member.returnType,
3074
+ typeParameters: member.typeParameters,
3075
+ });
3076
+ }
3077
+ }
3078
+ const shape = renderPortableType({ kind: "objectType", members }, declaration.typeParameters?.map((typeParameter) => typeParameter.name) ?? [], new Map(), new Map());
3079
+ anonymousHelperClassNamesByShape.set(shape, emittedName);
3080
+ };
3081
+ for (const symbol of typeDeclarations) {
3082
+ if (symbol.kind === "class" &&
3083
+ symbol.declaration.kind === "classDeclaration") {
3084
+ registerAnonymousHelperClass(symbol.localName, symbol.declaration);
3085
+ }
3086
+ }
3087
+ for (const helper of internalHelperTypeDeclarationsByKey.values()) {
3088
+ if (helper.kind === "class") {
3089
+ registerAnonymousHelperClass(helper.emittedName, helper.declaration);
3090
+ }
3091
+ }
3092
+ for (const [moduleKey, sourceIndex] of sourceIndexByFileKey) {
3093
+ const sourceModule = modulesByFileKey.get(moduleKey);
3094
+ if (!sourceModule)
3095
+ continue;
3096
+ for (const [shape, anonymousType,] of sourceIndex.anonymousTypeLiteralsByShape) {
3097
+ const className = anonymousHelperClassNamesByShape.get(shape);
3098
+ if (!className)
3099
+ continue;
3100
+ for (const [memberName, sourceMember] of anonymousType.members) {
3101
+ const wrappersResult = collectExtensionWrapperImportsFromSourceType({
3102
+ startModuleKey: moduleKey,
3103
+ typeNode: sourceMember.typeNode,
3104
+ sourceIndexByFileKey,
3105
+ modulesByFileKey,
3106
+ });
3107
+ if (!wrappersResult.ok)
3108
+ return wrappersResult;
3109
+ const wrappers = wrappersResult.value;
3110
+ const canUseSourceTypeText = !typeNodeUsesImportedTypeNames(sourceMember.typeNode, sourceIndex.typeImportsByLocalName);
3111
+ if (!canUseSourceTypeText &&
3112
+ wrappers.length === 0 &&
3113
+ !sourceMember.isOptional) {
3114
+ continue;
3115
+ }
3116
+ const wrapperRegistered = registerWrapperImports(wrappers, sourceModule.filePath);
3117
+ if (!wrapperRegistered.ok)
3118
+ return wrapperRegistered;
3119
+ memberOverrides.push({
3120
+ className,
3121
+ memberName,
3122
+ sourceTypeText: canUseSourceTypeText
3123
+ ? sourceMember.typeText
3124
+ : undefined,
3125
+ replaceWithSourceType: canUseSourceTypeText,
3126
+ isOptional: sourceMember.isOptional,
3127
+ emitOptionalPropertySyntax: true,
3128
+ wrappers,
3129
+ });
3130
+ }
3131
+ }
3132
+ }
1917
3133
  plans.push({
1918
3134
  namespace,
1919
3135
  typeDeclarations: typeDeclarations.sort((left, right) => left.exportName.localeCompare(right.exportName)),
3136
+ internalHelperTypeDeclarations: Array.from(internalHelperTypeDeclarationsByKey.values()).sort((left, right) => left.key.localeCompare(right.key)),
1920
3137
  moduleContainers: moduleContainers.sort((left, right) => left.module.className.localeCompare(right.module.className)),
1921
- sourceAliasLines: Array.from(sourceAliasLines.values()).sort((left, right) => left.localeCompare(right)),
1922
- sourceAliasInternalImports: Array.from(sourceAliasInternalImports.values()).sort((left, right) => left.localeCompare(right)),
3138
+ crossNamespaceReexports: finalizeCrossNamespaceReexports(crossNamespaceReexportsGrouped),
3139
+ crossNamespaceTypeDeclarations: crossNamespaceTypeDeclarations.sort((left, right) => {
3140
+ const leftKey = `${left.exportName}|${left.declaringNamespace}|${left.localName}|${left.kind}`;
3141
+ const rightKey = `${right.exportName}|${right.declaringNamespace}|${right.localName}|${right.kind}`;
3142
+ return leftKey.localeCompare(rightKey);
3143
+ }),
3144
+ sourceAliases: sourceAliasPlans.sort((left, right) => left.declaration.name.localeCompare(right.declaration.name)),
1923
3145
  memberOverrides: memberOverrides.sort((left, right) => {
1924
3146
  const classCmp = left.className.localeCompare(right.className);
1925
3147
  if (classCmp !== 0)
1926
3148
  return classCmp;
1927
3149
  return left.memberName.localeCompare(right.memberName);
1928
3150
  }),
3151
+ internalTypeImports: Array.from(internalTypeImportByAlias.values()).sort((left, right) => left.localName.localeCompare(right.localName)),
3152
+ facadeTypeImports: Array.from(facadeTypeImportByAlias.values()).sort((left, right) => left.localName.localeCompare(right.localName)),
1929
3153
  wrapperImports: Array.from(wrapperImportByAlias.values()).sort((left, right) => left.aliasName.localeCompare(right.aliasName)),
1930
3154
  valueExports: Array.from(valueExportsMap.values()).sort((left, right) => left.exportName.localeCompare(right.exportName)),
1931
3155
  });
@@ -1935,55 +3159,7 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
1935
3159
  value: plans.sort((left, right) => left.namespace.localeCompare(right.namespace)),
1936
3160
  };
1937
3161
  };
1938
- const collectEntrypointReexports = (entryModule, modulesByFileKey) => {
1939
- const grouped = new Map();
1940
- for (const exported of entryModule.exports) {
1941
- if (exported.kind !== "reexport")
1942
- continue;
1943
- const targetModule = resolveLocalModuleFile(exported.fromModule, entryModule.filePath, modulesByFileKey);
1944
- if (!targetModule) {
1945
- return {
1946
- ok: false,
1947
- error: `Failed to resolve re-export '${exported.name}' from '${exported.fromModule}' in ${entryModule.filePath}.`,
1948
- };
1949
- }
1950
- if (targetModule.namespace === entryModule.namespace)
1951
- continue;
1952
- const kind = classifyExportKind(targetModule, exported.originalName);
1953
- if (kind === "unknown") {
1954
- return {
1955
- ok: false,
1956
- error: `Failed to classify re-export '${exported.name}' from '${exported.fromModule}' in ${entryModule.filePath}.`,
1957
- };
1958
- }
1959
- const moduleSpecifier = `./${moduleNamespacePath(targetModule.namespace)}.js`;
1960
- const key = `${moduleSpecifier}|${kind}`;
1961
- const specifier = exported.name === exported.originalName
1962
- ? exported.name
1963
- : `${exported.originalName} as ${exported.name}`;
1964
- const list = grouped.get(key) ?? [];
1965
- list.push(specifier);
1966
- grouped.set(key, list);
1967
- }
1968
- const dtsStatements = [];
1969
- const jsValueStatements = [];
1970
- for (const [key, specs] of Array.from(grouped.entries()).sort((a, b) => a[0].localeCompare(b[0]))) {
1971
- const [moduleSpecifier, kind] = key.split("|");
1972
- const unique = Array.from(new Set(specs)).sort((a, b) => a.localeCompare(b));
1973
- if (kind === "type") {
1974
- dtsStatements.push(`export type { ${unique.join(", ")} } from '${moduleSpecifier}';`);
1975
- continue;
1976
- }
1977
- const statement = `export { ${unique.join(", ")} } from '${moduleSpecifier}';`;
1978
- dtsStatements.push(statement);
1979
- jsValueStatements.push(statement);
1980
- }
1981
- return {
1982
- ok: true,
1983
- value: { dtsStatements, jsValueStatements },
1984
- };
1985
- };
1986
- const writeNamespaceArtifacts = (config, outDir, plan, entrypointReexports) => {
3162
+ const writeNamespaceArtifacts = (config, outDir, plan) => {
1987
3163
  const namespacePath = moduleNamespacePath(plan.namespace);
1988
3164
  const namespaceDir = join(outDir, namespacePath);
1989
3165
  const internalDir = join(namespaceDir, "internal");
@@ -1992,7 +3168,8 @@ const writeNamespaceArtifacts = (config, outDir, plan, entrypointReexports) => {
1992
3168
  const facadeDtsPath = join(outDir, `${namespacePath}.d.ts`);
1993
3169
  const facadeJsPath = join(outDir, `${namespacePath}.js`);
1994
3170
  const bindingsPath = join(namespaceDir, "bindings.json");
1995
- const internalLines = [];
3171
+ const anonymousStructuralAliases = buildAnonymousStructuralAliasMap(plan);
3172
+ const internalBodyLines = [];
1996
3173
  const memberOverridesByClass = new Map();
1997
3174
  for (const override of plan.memberOverrides) {
1998
3175
  const byMember = memberOverridesByClass.get(override.className) ??
@@ -2000,47 +3177,29 @@ const writeNamespaceArtifacts = (config, outDir, plan, entrypointReexports) => {
2000
3177
  byMember.set(override.memberName, override);
2001
3178
  memberOverridesByClass.set(override.className, byMember);
2002
3179
  }
2003
- internalLines.push("// Generated by Tsonic - Source bindings");
2004
- internalLines.push(`// Namespace: ${plan.namespace}`);
2005
- internalLines.push(`// Assembly: ${config.outputName}`);
2006
- internalLines.push("");
2007
- internalLines.push(primitiveImportLine);
2008
- if (plan.wrapperImports.length > 0) {
2009
- internalLines.push("");
2010
- internalLines.push("// Tsonic source member type imports (generated)");
2011
- for (const wrapperImport of plan.wrapperImports) {
2012
- if (wrapperImport.importedName === wrapperImport.aliasName) {
2013
- internalLines.push(`import type { ${wrapperImport.importedName} } from '${wrapperImport.source}';`);
2014
- continue;
2015
- }
2016
- internalLines.push(`import type { ${wrapperImport.importedName} as ${wrapperImport.aliasName} } from '${wrapperImport.source}';`);
2017
- }
2018
- internalLines.push("// End Tsonic source member type imports");
2019
- }
2020
- internalLines.push("");
2021
3180
  const typeBindings = [];
2022
3181
  for (const symbol of plan.typeDeclarations) {
2023
3182
  if (symbol.kind === "class" &&
2024
3183
  symbol.declaration.kind === "classDeclaration") {
2025
- internalLines.push(...renderClassInternal(symbol.declaration, plan.namespace, memberOverridesByClass.get(symbol.declaration.name) ?? new Map()));
3184
+ internalBodyLines.push(...renderClassInternal(symbol.declaration, plan.namespace, memberOverridesByClass.get(symbol.declaration.name) ?? new Map()));
2026
3185
  typeBindings.push(buildTypeBindingFromClass(symbol.declaration, plan.namespace, config.outputName));
2027
3186
  continue;
2028
3187
  }
2029
3188
  if (symbol.kind === "interface" &&
2030
3189
  symbol.declaration.kind === "interfaceDeclaration") {
2031
- internalLines.push(...renderInterfaceInternal(symbol.declaration, plan.namespace, memberOverridesByClass.get(symbol.declaration.name) ?? new Map()));
3190
+ internalBodyLines.push(...renderInterfaceInternal(symbol.declaration, plan.namespace, memberOverridesByClass.get(symbol.declaration.name) ?? new Map()));
2032
3191
  typeBindings.push(buildTypeBindingFromInterface(symbol.declaration, plan.namespace, config.outputName));
2033
3192
  continue;
2034
3193
  }
2035
3194
  if (symbol.kind === "enum" &&
2036
3195
  symbol.declaration.kind === "enumDeclaration") {
2037
- internalLines.push(...renderEnumInternal(symbol.declaration));
3196
+ internalBodyLines.push(...renderEnumInternal(symbol.declaration));
2038
3197
  typeBindings.push(buildTypeBindingFromEnum(symbol.declaration, plan.namespace, config.outputName));
2039
3198
  continue;
2040
3199
  }
2041
3200
  if (symbol.kind === "typeAlias" &&
2042
3201
  symbol.declaration.kind === "typeAliasDeclaration") {
2043
- internalLines.push(...renderStructuralAliasInternal(symbol.declaration, plan.namespace, memberOverridesByClass.get(`${symbol.declaration.name}__Alias${(symbol.declaration.typeParameters?.length ?? 0) > 0
3202
+ internalBodyLines.push(...renderStructuralAliasInternal(symbol.declaration, plan.namespace, memberOverridesByClass.get(`${symbol.declaration.name}__Alias${(symbol.declaration.typeParameters?.length ?? 0) > 0
2044
3203
  ? `_${symbol.declaration.typeParameters?.length ?? 0}`
2045
3204
  : ""}`) ?? new Map()));
2046
3205
  const binding = buildTypeBindingFromStructuralAlias(symbol.declaration, plan.namespace, config.outputName);
@@ -2048,10 +3207,137 @@ const writeNamespaceArtifacts = (config, outDir, plan, entrypointReexports) => {
2048
3207
  typeBindings.push(binding);
2049
3208
  }
2050
3209
  }
3210
+ const helperRemapsByModuleKey = new Map();
3211
+ for (const helper of plan.internalHelperTypeDeclarations) {
3212
+ const current = new Map(helperRemapsByModuleKey.get(helper.moduleFileKey) ?? []);
3213
+ current.set(helper.originalName, helper.emittedName);
3214
+ helperRemapsByModuleKey.set(helper.moduleFileKey, current);
3215
+ }
3216
+ for (const helper of plan.internalHelperTypeDeclarations) {
3217
+ const localTypeNameRemaps = helperRemapsByModuleKey.get(helper.moduleFileKey) ?? new Map();
3218
+ switch (helper.kind) {
3219
+ case "class":
3220
+ internalBodyLines.push(...renderClassInternal(helper.declaration, helper.declaringNamespace, memberOverridesByClass.get(helper.emittedName) ??
3221
+ memberOverridesByClass.get(helper.declaration.name) ??
3222
+ new Map(), helper.emittedName, localTypeNameRemaps, helper.declaration.name, helper.declaration.name));
3223
+ typeBindings.push(buildTypeBindingFromClass(helper.declaration, helper.declaringNamespace, config.outputName, localTypeNameRemaps));
3224
+ continue;
3225
+ case "interface":
3226
+ internalBodyLines.push(...renderInterfaceInternal(helper.declaration, helper.declaringNamespace, memberOverridesByClass.get(helper.emittedName) ??
3227
+ memberOverridesByClass.get(helper.declaration.name) ??
3228
+ new Map(), helper.emittedName, localTypeNameRemaps, helper.declaration.name, helper.declaration.name));
3229
+ typeBindings.push(buildTypeBindingFromInterface(helper.declaration, helper.declaringNamespace, config.outputName, localTypeNameRemaps));
3230
+ continue;
3231
+ case "enum":
3232
+ internalBodyLines.push(...renderEnumInternal(helper.declaration, helper.emittedName));
3233
+ typeBindings.push(buildTypeBindingFromEnum(helper.declaration, helper.declaringNamespace, config.outputName));
3234
+ continue;
3235
+ case "typeAlias": {
3236
+ const structuralLines = renderStructuralAliasInternal(helper.declaration, helper.declaringNamespace, memberOverridesByClass.get(helper.emittedName) ??
3237
+ memberOverridesByClass.get(`${helper.declaration.name}__Alias${(helper.declaration.typeParameters
3238
+ ?.length ?? 0) > 0
3239
+ ? `_${helper.declaration
3240
+ .typeParameters?.length ?? 0}`
3241
+ : ""}`) ??
3242
+ new Map(), helper.emittedName, localTypeNameRemaps, `${helper.declaration.name}__Alias${(helper.declaration.typeParameters
3243
+ ?.length ?? 0) > 0
3244
+ ? `_${helper.declaration.typeParameters
3245
+ ?.length ?? 0}`
3246
+ : ""}`, `${helper.declaration.name}__Alias${(helper.declaration.typeParameters
3247
+ ?.length ?? 0) > 0
3248
+ ? `_${helper.declaration.typeParameters
3249
+ ?.length ?? 0}`
3250
+ : ""}`);
3251
+ if (structuralLines.length > 0) {
3252
+ internalBodyLines.push(...structuralLines);
3253
+ const binding = buildTypeBindingFromStructuralAlias(helper.declaration, helper.declaringNamespace, config.outputName, localTypeNameRemaps);
3254
+ if (binding)
3255
+ typeBindings.push(binding);
3256
+ continue;
3257
+ }
3258
+ internalBodyLines.push(...renderTypeAliasInternal(helper.declaration, helper.emittedName, localTypeNameRemaps, anonymousStructuralAliases));
3259
+ continue;
3260
+ }
3261
+ }
3262
+ }
3263
+ const renderedSourceAliases = plan.sourceAliases.map((sourceAliasPlan) => renderSourceAliasPlan(sourceAliasPlan, anonymousStructuralAliases));
3264
+ const sourceAliasLines = renderedSourceAliases.map((entry) => entry.line);
3265
+ const sourceAliasInternalImports = renderedSourceAliases
3266
+ .map((entry) => entry.internalImport)
3267
+ .filter((entry) => entry !== undefined)
3268
+ .sort((left, right) => left.localeCompare(right));
2051
3269
  for (const container of plan.moduleContainers) {
2052
- internalLines.push(...renderContainerInternal(container));
3270
+ internalBodyLines.push(...renderContainerInternal(container, anonymousStructuralAliases));
2053
3271
  typeBindings.push(buildTypeBindingFromContainer(container, plan.namespace, config.outputName));
2054
3272
  }
3273
+ for (const symbol of plan.crossNamespaceTypeDeclarations) {
3274
+ if (symbol.kind === "class" &&
3275
+ symbol.declaration.kind === "classDeclaration") {
3276
+ typeBindings.push(buildTypeBindingFromClass(symbol.declaration, symbol.declaringNamespace, config.outputName));
3277
+ continue;
3278
+ }
3279
+ if (symbol.kind === "interface" &&
3280
+ symbol.declaration.kind === "interfaceDeclaration") {
3281
+ typeBindings.push(buildTypeBindingFromInterface(symbol.declaration, symbol.declaringNamespace, config.outputName));
3282
+ continue;
3283
+ }
3284
+ if (symbol.kind === "enum" &&
3285
+ symbol.declaration.kind === "enumDeclaration") {
3286
+ typeBindings.push(buildTypeBindingFromEnum(symbol.declaration, symbol.declaringNamespace, config.outputName));
3287
+ continue;
3288
+ }
3289
+ if (symbol.kind === "typeAlias" &&
3290
+ symbol.declaration.kind === "typeAliasDeclaration") {
3291
+ const binding = buildTypeBindingFromStructuralAlias(symbol.declaration, symbol.declaringNamespace, config.outputName);
3292
+ if (binding)
3293
+ typeBindings.push(binding);
3294
+ }
3295
+ }
3296
+ const internalSourceAliasLines = sourceAliasLines.length > 0
3297
+ ? [
3298
+ "",
3299
+ "// Tsonic source type aliases (generated)",
3300
+ ...sourceAliasLines,
3301
+ "// End Tsonic source type aliases",
3302
+ ]
3303
+ : [];
3304
+ const requiredInternalTypeImports = selectSourceTypeImportsForRenderedText([...internalSourceAliasLines, ...internalBodyLines].join("\n"), plan.internalTypeImports);
3305
+ const internalLines = [];
3306
+ internalLines.push("// Generated by Tsonic - Source bindings");
3307
+ internalLines.push(`// Namespace: ${plan.namespace}`);
3308
+ internalLines.push(`// Assembly: ${config.outputName}`);
3309
+ internalLines.push("");
3310
+ internalLines.push(primitiveImportLine);
3311
+ if (requiredInternalTypeImports.length > 0) {
3312
+ internalLines.push("");
3313
+ internalLines.push("// Tsonic source type imports (generated)");
3314
+ for (const typeImport of requiredInternalTypeImports) {
3315
+ if (typeImport.importedName === typeImport.localName) {
3316
+ internalLines.push(`import type { ${typeImport.importedName} } from '${typeImport.source}';`);
3317
+ continue;
3318
+ }
3319
+ internalLines.push(`import type { ${typeImport.importedName} as ${typeImport.localName} } from '${typeImport.source}';`);
3320
+ }
3321
+ internalLines.push("// End Tsonic source type imports");
3322
+ }
3323
+ if (plan.wrapperImports.length > 0) {
3324
+ internalLines.push("");
3325
+ internalLines.push("// Tsonic source member type imports (generated)");
3326
+ for (const wrapperImport of plan.wrapperImports) {
3327
+ if (wrapperImport.importedName === wrapperImport.aliasName) {
3328
+ internalLines.push(`import type { ${wrapperImport.importedName} } from '${wrapperImport.source}';`);
3329
+ continue;
3330
+ }
3331
+ internalLines.push(`import type { ${wrapperImport.importedName} as ${wrapperImport.aliasName} } from '${wrapperImport.source}';`);
3332
+ }
3333
+ internalLines.push("// End Tsonic source member type imports");
3334
+ }
3335
+ internalLines.push("");
3336
+ if (internalSourceAliasLines.length > 0) {
3337
+ internalLines.push(...internalSourceAliasLines);
3338
+ internalLines.push("");
3339
+ }
3340
+ internalLines.push(...internalBodyLines);
2055
3341
  writeFileSync(internalIndexPath, internalLines.join("\n").trimEnd() + "\n", "utf-8");
2056
3342
  const internalSpecifier = moduleNamespaceToInternalSpecifier(plan.namespace);
2057
3343
  const facadeLines = [];
@@ -2100,9 +3386,12 @@ const writeNamespaceArtifacts = (config, outDir, plan, entrypointReexports) => {
2100
3386
  localTypeImports.add(`${symbol.localName}$instance`);
2101
3387
  }
2102
3388
  }
2103
- for (const internalImport of plan.sourceAliasInternalImports) {
3389
+ for (const internalImport of sourceAliasInternalImports) {
2104
3390
  localTypeImports.add(internalImport);
2105
3391
  }
3392
+ for (const helper of plan.internalHelperTypeDeclarations) {
3393
+ localTypeImports.add(helper.emittedName);
3394
+ }
2106
3395
  if (localTypeImports.size > 0) {
2107
3396
  facadeLines.push("");
2108
3397
  facadeLines.push("// Tsonic source alias imports (generated)");
@@ -2111,35 +3400,53 @@ const writeNamespaceArtifacts = (config, outDir, plan, entrypointReexports) => {
2111
3400
  .join(", ")} } from '${internalSpecifier}';`);
2112
3401
  facadeLines.push("// End Tsonic source alias imports");
2113
3402
  }
2114
- if (plan.sourceAliasLines.length > 0) {
3403
+ if (sourceAliasLines.length > 0) {
2115
3404
  facadeLines.push("");
2116
3405
  facadeLines.push("// Tsonic source type aliases (generated)");
2117
- facadeLines.push(...plan.sourceAliasLines);
3406
+ facadeLines.push(...sourceAliasLines);
2118
3407
  facadeLines.push("// End Tsonic source type aliases");
2119
3408
  }
2120
- if (entrypointReexports && entrypointReexports.dtsStatements.length > 0) {
3409
+ if (plan.crossNamespaceReexports.dtsStatements.length > 0) {
2121
3410
  facadeLines.push("");
2122
- facadeLines.push("// Tsonic entrypoint re-exports (generated)");
2123
- facadeLines.push(...entrypointReexports.dtsStatements);
2124
- facadeLines.push("// End Tsonic entrypoint re-exports");
3411
+ facadeLines.push("// Tsonic cross-namespace re-exports (generated)");
3412
+ facadeLines.push(...plan.crossNamespaceReexports.dtsStatements);
3413
+ facadeLines.push("// End Tsonic cross-namespace re-exports");
2125
3414
  }
2126
3415
  for (const valueExport of plan.valueExports) {
2127
3416
  valueBindings.set(valueExport.exportName, valueExport.binding);
2128
3417
  if (valueExport.facade.kind === "function") {
2129
- const typeParametersText = printTypeParameters(valueExport.facade.declaration.typeParameters);
2130
- const typeParameterNames = valueExport.facade.declaration.typeParameters?.map((typeParameter) => typeParameter.name) ?? [];
2131
- const parametersText = renderUnknownParameters(valueExport.facade.declaration.parameters, typeParameterNames);
2132
- const returnTypeText = renderPortableType(valueExport.facade.declaration.returnType, typeParameterNames);
2133
- facadeLines.push(`export declare function ${valueExport.exportName}${typeParametersText}(${parametersText}): ${returnTypeText};`);
3418
+ const sourceSignature = renderSourceFunctionSignature({
3419
+ declaration: valueExport.facade.declaration,
3420
+ sourceSignatures: valueExport.facade.sourceSignatures ?? [],
3421
+ localTypeNameRemaps: valueExport.facade.localTypeNameRemaps,
3422
+ anonymousStructuralAliases,
3423
+ });
3424
+ facadeLines.push(sourceSignature
3425
+ ? `export declare function ${valueExport.exportName}${sourceSignature.typeParametersText}(${sourceSignature.parametersText}): ${sourceSignature.returnTypeText};`
3426
+ : `export declare function ${valueExport.exportName}${printTypeParameters(valueExport.facade.declaration.typeParameters)}(${renderUnknownParameters(valueExport.facade.declaration.parameters, valueExport.facade.declaration.typeParameters?.map((typeParameter) => typeParameter.name) ?? [], valueExport.facade.localTypeNameRemaps, anonymousStructuralAliases)}): ${renderPortableType(valueExport.facade.declaration.returnType, valueExport.facade.declaration.typeParameters?.map((typeParameter) => typeParameter.name) ?? [], valueExport.facade.localTypeNameRemaps, anonymousStructuralAliases)};`);
2134
3427
  continue;
2135
3428
  }
2136
- facadeLines.push(`export declare const ${valueExport.exportName}: ${renderPortableType(valueExport.facade.declarator?.type)};`);
3429
+ const sourceFunctionTypeText = renderSourceFunctionType({
3430
+ sourceSignatures: valueExport.facade.sourceSignatures ?? [],
3431
+ localTypeNameRemaps: valueExport.facade.localTypeNameRemaps,
3432
+ anonymousStructuralAliases,
3433
+ });
3434
+ const sourceTypeText = sourceFunctionTypeText ??
3435
+ renderSourceValueType(valueExport.facade.sourceType, valueExport.facade.localTypeNameRemaps, anonymousStructuralAliases);
3436
+ facadeLines.push(`export declare const ${valueExport.exportName}: ${sourceTypeText ??
3437
+ renderPortableType(valueExport.facade.declarator?.type, [], valueExport.facade.localTypeNameRemaps, anonymousStructuralAliases)};`);
3438
+ }
3439
+ const requiredFacadeTypeImports = selectSourceTypeImportsForRenderedText(facadeLines.join("\n"), plan.facadeTypeImports);
3440
+ if (requiredFacadeTypeImports.length > 0) {
3441
+ facadeLines.splice(4, 0, "", "// Tsonic source type imports (generated)", ...requiredFacadeTypeImports.map((typeImport) => typeImport.importedName === typeImport.localName
3442
+ ? `import type { ${typeImport.importedName} } from '${typeImport.source}';`
3443
+ : `import type { ${typeImport.importedName} as ${typeImport.localName} } from '${typeImport.source}';`), "// End Tsonic source type imports");
2137
3444
  }
2138
3445
  if (plan.typeDeclarations.length === 0 &&
2139
3446
  plan.moduleContainers.length === 0 &&
2140
3447
  plan.valueExports.length === 0 &&
2141
- plan.sourceAliasLines.length === 0 &&
2142
- (!entrypointReexports || entrypointReexports.dtsStatements.length === 0)) {
3448
+ sourceAliasLines.length === 0 &&
3449
+ plan.crossNamespaceReexports.dtsStatements.length === 0) {
2143
3450
  facadeLines.push("export {};");
2144
3451
  }
2145
3452
  writeFileSync(facadeDtsPath, facadeLines.join("\n").trimEnd() + "\n", "utf-8");
@@ -2148,12 +3455,11 @@ const writeNamespaceArtifacts = (config, outDir, plan, entrypointReexports) => {
2148
3455
  "// Generated by Tsonic - Source bindings",
2149
3456
  "// Module Stub - Do Not Execute",
2150
3457
  "",
2151
- ...(entrypointReexports &&
2152
- entrypointReexports.jsValueStatements.length > 0
3458
+ ...(plan.crossNamespaceReexports.jsValueStatements.length > 0
2153
3459
  ? [
2154
- "// Tsonic entrypoint value re-exports (generated)",
2155
- ...entrypointReexports.jsValueStatements,
2156
- "// End Tsonic entrypoint value re-exports",
3460
+ "// Tsonic cross-namespace value re-exports (generated)",
3461
+ ...plan.crossNamespaceReexports.jsValueStatements,
3462
+ "// End Tsonic cross-namespace value re-exports",
2157
3463
  "",
2158
3464
  ]
2159
3465
  : []),
@@ -2216,10 +3522,6 @@ export const generateFirstPartyLibraryBindings = (config, bindingsOutDir) => {
2216
3522
  }
2217
3523
  rmSync(bindingsOutDir, { recursive: true, force: true });
2218
3524
  mkdirSync(bindingsOutDir, { recursive: true });
2219
- const modulesByFileKey = new Map();
2220
- for (const module of graphResult.value.modules) {
2221
- modulesByFileKey.set(normalizeModuleFileKey(module.filePath), module);
2222
- }
2223
3525
  const sourceIndexByFileKey = new Map();
2224
3526
  for (const module of graphResult.value.modules) {
2225
3527
  if (module.filePath.startsWith("__tsonic/"))
@@ -2234,13 +3536,8 @@ export const generateFirstPartyLibraryBindings = (config, bindingsOutDir) => {
2234
3536
  const plansResult = collectNamespacePlans(graphResult.value.modules, config.outputName, config.rootNamespace, sourceIndexByFileKey);
2235
3537
  if (!plansResult.ok)
2236
3538
  return plansResult;
2237
- const entrypointReexportsResult = collectEntrypointReexports(graphResult.value.entryModule, modulesByFileKey);
2238
- if (!entrypointReexportsResult.ok)
2239
- return entrypointReexportsResult;
2240
3539
  for (const plan of plansResult.value) {
2241
- const result = writeNamespaceArtifacts(config, bindingsOutDir, plan, plan.namespace === graphResult.value.entryModule.namespace
2242
- ? entrypointReexportsResult.value
2243
- : undefined);
3540
+ const result = writeNamespaceArtifacts(config, bindingsOutDir, plan);
2244
3541
  if (!result.ok)
2245
3542
  return result;
2246
3543
  }