@tsonic/cli 0.0.71 → 0.0.73

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/aikya/bindings.d.ts +1 -0
  3. package/dist/aikya/bindings.d.ts.map +1 -1
  4. package/dist/aikya/bindings.js +23 -0
  5. package/dist/aikya/bindings.js.map +1 -1
  6. package/dist/commands/add-npm.d.ts +1 -0
  7. package/dist/commands/add-npm.d.ts.map +1 -1
  8. package/dist/commands/add-npm.js +8 -1
  9. package/dist/commands/add-npm.js.map +1 -1
  10. package/dist/commands/add-npm.test.js +32 -0
  11. package/dist/commands/add-npm.test.js.map +1 -1
  12. package/dist/commands/build-library-bindings-aliases.test.js +63 -7
  13. package/dist/commands/build-library-bindings-aliases.test.js.map +1 -1
  14. package/dist/commands/library-bindings-augment.d.ts.map +1 -1
  15. package/dist/commands/library-bindings-augment.js +0 -3
  16. package/dist/commands/library-bindings-augment.js.map +1 -1
  17. package/dist/commands/library-bindings-augment.test.js +46 -0
  18. package/dist/commands/library-bindings-augment.test.js.map +1 -1
  19. package/dist/commands/library-bindings-firstparty-regressions.test.js +2420 -0
  20. package/dist/commands/library-bindings-firstparty-regressions.test.js.map +1 -1
  21. package/dist/commands/library-bindings-firstparty.d.ts.map +1 -1
  22. package/dist/commands/library-bindings-firstparty.js +1609 -306
  23. package/dist/commands/library-bindings-firstparty.js.map +1 -1
  24. package/dist/surface/profiles.d.ts.map +1 -1
  25. package/dist/surface/profiles.js +12 -0
  26. package/dist/surface/profiles.js.map +1 -1
  27. package/dist/surface/profiles.test.js +45 -1
  28. package/dist/surface/profiles.test.js.map +1 -1
  29. package/package.json +5 -5
  30. package/runtime/Tsonic.JSRuntime.dll +0 -0
  31. package/runtime/nodejs.dll +0 -0
@@ -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,149 @@ 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
+ };
245
+ const typeNeedsAnonymousCanonicalization = (candidate) => {
246
+ if (!candidate)
247
+ return false;
248
+ switch (candidate.kind) {
249
+ case "objectType":
250
+ return anonymousStructuralAliases.has(renderPortableShapeType(candidate, typeParametersInScope));
251
+ case "arrayType":
252
+ return typeNeedsAnonymousCanonicalization(candidate.elementType);
253
+ case "tupleType":
254
+ return candidate.elementTypes.some(typeNeedsAnonymousCanonicalization);
255
+ case "unionType":
256
+ case "intersectionType":
257
+ return candidate.types.some(typeNeedsAnonymousCanonicalization);
258
+ case "dictionaryType":
259
+ return (typeNeedsAnonymousCanonicalization(candidate.keyType) ||
260
+ typeNeedsAnonymousCanonicalization(candidate.valueType));
261
+ case "functionType":
262
+ return (candidate.parameters.some((parameter) => typeNeedsAnonymousCanonicalization(parameter.type)) || typeNeedsAnonymousCanonicalization(candidate.returnType));
263
+ case "referenceType":
264
+ return (candidate.typeArguments?.some(typeNeedsAnonymousCanonicalization) ??
265
+ false);
266
+ default:
267
+ return false;
268
+ }
269
+ };
93
270
  if (!type)
94
271
  return "object";
95
272
  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;
273
+ case "objectType": {
274
+ const shape = renderPortableShapeType(type, typeParametersInScope);
275
+ const alias = anonymousStructuralAliases.get(shape);
276
+ if (alias) {
277
+ const typeArgs = alias.typeParameters.length > 0
278
+ ? `<${alias.typeParameters.join(", ")}>`
279
+ : "";
280
+ return `${alias.name}${typeArgs}`;
281
+ }
282
+ return shape;
283
+ }
111
284
  case "arrayType":
112
- return `${renderPortableType(type.elementType, typeParametersInScope)}[]`;
285
+ return `${renderPortableType(type.elementType, typeParametersInScope, localTypeNameRemaps, anonymousStructuralAliases)}[]`;
113
286
  case "tupleType":
114
287
  return `[${type.elementTypes
115
- .map((item) => renderPortableType(item, typeParametersInScope))
288
+ .map((item) => renderPortableType(item, typeParametersInScope, localTypeNameRemaps, anonymousStructuralAliases))
116
289
  .join(", ")}]`;
117
290
  case "unionType":
118
291
  return type.types
119
- .map((item) => renderPortableType(item, typeParametersInScope))
292
+ .map((item) => renderPortableType(item, typeParametersInScope, localTypeNameRemaps, anonymousStructuralAliases))
120
293
  .join(" | ");
121
294
  case "intersectionType":
122
295
  return type.types
123
- .map((item) => renderPortableType(item, typeParametersInScope))
296
+ .map((item) => renderPortableType(item, typeParametersInScope, localTypeNameRemaps, anonymousStructuralAliases))
124
297
  .join(" & ");
125
298
  case "dictionaryType":
126
- return `Record<${renderPortableType(type.keyType, typeParametersInScope)}, ${renderPortableType(type.valueType, typeParametersInScope)}>`;
299
+ return `Record<${renderPortableType(type.keyType, typeParametersInScope, localTypeNameRemaps, anonymousStructuralAliases)}, ${renderPortableType(type.valueType, typeParametersInScope, localTypeNameRemaps, anonymousStructuralAliases)}>`;
127
300
  case "functionType":
128
301
  return `(${type.parameters
129
302
  .map((parameter, index) => {
130
303
  const parameterName = parameter.pattern.kind === "identifierPattern"
131
304
  ? parameter.pattern.name
132
305
  : `p${index + 1}`;
133
- return `${parameterName}: ${renderPortableType(parameter.type, typeParametersInScope)}`;
306
+ return `${parameterName}: ${renderPortableType(parameter.type, typeParametersInScope, localTypeNameRemaps, anonymousStructuralAliases)}`;
134
307
  })
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
- }
308
+ .join(", ")}) => ${renderPortableType(type.returnType, typeParametersInScope, localTypeNameRemaps, anonymousStructuralAliases)}`;
158
309
  default:
159
- return "object";
310
+ return renderPortableShapeType(type, typeParametersInScope);
160
311
  }
161
312
  };
162
- const renderUnknownParameters = (parameters, typeParametersInScope) => {
313
+ const renderUnknownParameters = (parameters, typeParametersInScope, localTypeNameRemaps = new Map(), anonymousStructuralAliases = new Map()) => {
163
314
  return parameters
164
315
  .map((parameter, index) => {
165
316
  const baseName = parameter.pattern.kind === "identifierPattern"
@@ -167,7 +318,7 @@ const renderUnknownParameters = (parameters, typeParametersInScope) => {
167
318
  : `p${index + 1}`;
168
319
  const restPrefix = parameter.isRest ? "..." : "";
169
320
  const optionalMark = parameter.isOptional && !parameter.isRest ? "?" : "";
170
- const parameterType = renderPortableType(parameter.type, typeParametersInScope);
321
+ const parameterType = renderPortableType(parameter.type, typeParametersInScope, localTypeNameRemaps, anonymousStructuralAliases);
171
322
  const typeSuffix = parameter.isRest
172
323
  ? `${parameterType}[]`
173
324
  : parameterType;
@@ -175,13 +326,397 @@ const renderUnknownParameters = (parameters, typeParametersInScope) => {
175
326
  })
176
327
  .join(", ");
177
328
  };
178
- const renderMethodSignature = (name, typeParameters, parameters, returnType) => {
329
+ const renderMethodSignature = (name, typeParameters, parameters, returnType, localTypeNameRemaps = new Map(), anonymousStructuralAliases = new Map()) => {
179
330
  const typeParametersText = printTypeParameters(typeParameters);
180
331
  const typeParameterNames = typeParameters?.map((typeParameter) => typeParameter.name) ?? [];
181
- const parametersText = renderUnknownParameters(parameters, typeParameterNames);
182
- const returnTypeText = renderPortableType(returnType, typeParameterNames);
332
+ const parametersText = renderUnknownParameters(parameters, typeParameterNames, localTypeNameRemaps, anonymousStructuralAliases);
333
+ const returnTypeText = renderPortableType(returnType, typeParameterNames, localTypeNameRemaps, anonymousStructuralAliases);
183
334
  return `${name}${typeParametersText}(${parametersText}): ${returnTypeText};`;
184
335
  };
336
+ const renderSourceTypeNodeForAliasLookup = (node, localTypeNameRemaps) => {
337
+ switch (node.kind) {
338
+ case ts.SyntaxKind.StringKeyword:
339
+ return "string";
340
+ case ts.SyntaxKind.NumberKeyword:
341
+ return "number";
342
+ case ts.SyntaxKind.BooleanKeyword:
343
+ return "boolean";
344
+ case ts.SyntaxKind.VoidKeyword:
345
+ return "void";
346
+ case ts.SyntaxKind.NeverKeyword:
347
+ return "never";
348
+ case ts.SyntaxKind.UnknownKeyword:
349
+ return "unknown";
350
+ case ts.SyntaxKind.AnyKeyword:
351
+ return "unknown";
352
+ case ts.SyntaxKind.NullKeyword:
353
+ return "null";
354
+ case ts.SyntaxKind.UndefinedKeyword:
355
+ return "undefined";
356
+ }
357
+ if (ts.isParenthesizedTypeNode(node)) {
358
+ return `(${renderSourceTypeNodeForAliasLookup(node.type, localTypeNameRemaps)})`;
359
+ }
360
+ if (ts.isArrayTypeNode(node)) {
361
+ return `${renderSourceTypeNodeForAliasLookup(node.elementType, localTypeNameRemaps)}[]`;
362
+ }
363
+ if (ts.isTupleTypeNode(node)) {
364
+ return `[${node.elements
365
+ .map((element) => renderSourceTypeNodeForAliasLookup(element, localTypeNameRemaps))
366
+ .join(", ")}]`;
367
+ }
368
+ if (ts.isUnionTypeNode(node)) {
369
+ return node.types
370
+ .map((part) => renderSourceTypeNodeForAliasLookup(part, localTypeNameRemaps))
371
+ .join(" | ");
372
+ }
373
+ if (ts.isIntersectionTypeNode(node)) {
374
+ return node.types
375
+ .map((part) => renderSourceTypeNodeForAliasLookup(part, localTypeNameRemaps))
376
+ .join(" & ");
377
+ }
378
+ if (ts.isLiteralTypeNode(node)) {
379
+ return node.getText();
380
+ }
381
+ if (ts.isTypeReferenceNode(node)) {
382
+ const typeNameText = node.typeName.getText();
383
+ const rewrittenTypeName = rewriteSourceTypeText(typeNameText, localTypeNameRemaps);
384
+ if (!node.typeArguments || node.typeArguments.length === 0) {
385
+ return rewrittenTypeName;
386
+ }
387
+ return `${rewrittenTypeName}<${node.typeArguments
388
+ .map((argument) => renderSourceTypeNodeForAliasLookup(argument, localTypeNameRemaps))
389
+ .join(", ")}>`;
390
+ }
391
+ if (ts.isTypeLiteralNode(node)) {
392
+ return `{ ${node.members
393
+ .flatMap((member) => {
394
+ if (ts.isPropertySignature(member)) {
395
+ const propertyName = ts.isIdentifier(member.name)
396
+ ? member.name.text
397
+ : ts.isStringLiteral(member.name)
398
+ ? member.name.text
399
+ : undefined;
400
+ if (!propertyName || !member.type)
401
+ return [];
402
+ const readonlyMark = member.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ReadonlyKeyword) ?? false
403
+ ? "readonly "
404
+ : "";
405
+ const propertyTypeText = member.questionToken
406
+ ? ensureUndefinedInType(renderSourceTypeNodeForAliasLookup(member.type, localTypeNameRemaps))
407
+ : renderSourceTypeNodeForAliasLookup(member.type, localTypeNameRemaps);
408
+ return [
409
+ `${readonlyMark}${propertyName}: ${propertyTypeText}`,
410
+ ];
411
+ }
412
+ if (ts.isMethodSignature(member)) {
413
+ const methodName = ts.isIdentifier(member.name)
414
+ ? member.name.text
415
+ : ts.isStringLiteral(member.name)
416
+ ? member.name.text
417
+ : undefined;
418
+ if (!methodName)
419
+ return [];
420
+ const typeParametersText = member.typeParameters
421
+ ? `<${member.typeParameters
422
+ .map((typeParameter) => typeParameter.name.text)
423
+ .join(", ")}>`
424
+ : "";
425
+ const parametersText = member.parameters
426
+ .map((parameter, index) => {
427
+ const parameterName = ts.isIdentifier(parameter.name)
428
+ ? parameter.name.text
429
+ : `p${index + 1}`;
430
+ const optionalMark = parameter.questionToken ? "?" : "";
431
+ const restPrefix = parameter.dotDotDotToken ? "..." : "";
432
+ const parameterType = parameter.type
433
+ ? renderSourceTypeNodeForAliasLookup(parameter.type, localTypeNameRemaps)
434
+ : "unknown";
435
+ return `${restPrefix}${parameterName}${optionalMark}: ${parameterType}`;
436
+ })
437
+ .join(", ");
438
+ const returnType = member.type
439
+ ? renderSourceTypeNodeForAliasLookup(member.type, localTypeNameRemaps)
440
+ : "void";
441
+ return [`${methodName}${typeParametersText}(${parametersText}): ${returnType}`];
442
+ }
443
+ return [];
444
+ })
445
+ .join("; ")} }`;
446
+ }
447
+ return node.getText();
448
+ };
449
+ const rewriteSourceTypeText = (typeText, localTypeNameRemaps, anonymousStructuralAliases = new Map()) => {
450
+ const sourceFile = ts.createSourceFile("__tsonic_source_type__.ts", `type __T = ${typeText};`, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
451
+ const statement = sourceFile.statements[0];
452
+ if (!statement || !ts.isTypeAliasDeclaration(statement))
453
+ return typeText;
454
+ const transformer = (context) => {
455
+ const visit = (node) => {
456
+ if (ts.isTypeReferenceNode(node) && ts.isIdentifier(node.typeName)) {
457
+ const remappedName = localTypeNameRemaps.get(node.typeName.text);
458
+ if (remappedName) {
459
+ return ts.factory.updateTypeReferenceNode(node, ts.factory.createIdentifier(remappedName), node.typeArguments);
460
+ }
461
+ }
462
+ if (anonymousStructuralAliases.size > 0 && ts.isTypeLiteralNode(node)) {
463
+ const alias = anonymousStructuralAliases.get(renderSourceTypeNodeForAliasLookup(node, localTypeNameRemaps));
464
+ if (alias) {
465
+ return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(alias.name), alias.typeParameters.map((typeParameter) => ts.factory.createTypeReferenceNode(typeParameter)));
466
+ }
467
+ }
468
+ return ts.visitEachChild(node, visit, context);
469
+ };
470
+ return (node) => ts.visitNode(node, visit);
471
+ };
472
+ const transformed = ts.transform(statement.type, [transformer]).transformed[0];
473
+ if (!transformed)
474
+ return typeText;
475
+ const printer = ts.createPrinter({ removeComments: true });
476
+ return printer.printNode(ts.EmitHint.Unspecified, transformed, sourceFile);
477
+ };
478
+ const selectPreferredSourceFunctionSignature = (opts) => {
479
+ const targetTypeParameterCount = opts.declaration.typeParameters?.length ?? 0;
480
+ const targetParameterCount = opts.declaration.parameters.length;
481
+ const exact = opts.sourceSignatures.find((signature) => {
482
+ return (signature.parameters.length === targetParameterCount &&
483
+ signature.typeParameterCount === targetTypeParameterCount);
484
+ });
485
+ return exact ?? opts.sourceSignatures[0];
486
+ };
487
+ const renderSourceFunctionSignature = (opts) => {
488
+ const sourceSignature = selectPreferredSourceFunctionSignature({
489
+ declaration: opts.declaration,
490
+ sourceSignatures: opts.sourceSignatures,
491
+ });
492
+ if (!sourceSignature)
493
+ return undefined;
494
+ const parametersText = sourceSignature.parameters
495
+ .map((parameter) => `${parameter.prefixText}${rewriteSourceTypeText(parameter.typeText, opts.localTypeNameRemaps, opts.anonymousStructuralAliases)}`)
496
+ .join(", ");
497
+ return {
498
+ typeParametersText: sourceSignature.typeParametersText,
499
+ parametersText,
500
+ returnTypeText: rewriteSourceTypeText(sourceSignature.returnTypeText, opts.localTypeNameRemaps, opts.anonymousStructuralAliases),
501
+ };
502
+ };
503
+ const renderSourceValueType = (sourceType, localTypeNameRemaps, anonymousStructuralAliases = new Map()) => !sourceType
504
+ ? undefined
505
+ : rewriteSourceTypeText(sourceType.typeText, localTypeNameRemaps, anonymousStructuralAliases);
506
+ const renderSourceFunctionType = (opts) => {
507
+ const sourceSignature = opts.sourceSignatures[0];
508
+ if (!sourceSignature)
509
+ return undefined;
510
+ const parametersText = sourceSignature.parameters
511
+ .map((parameter) => `${parameter.prefixText}${rewriteSourceTypeText(parameter.typeText, opts.localTypeNameRemaps, opts.anonymousStructuralAliases)}`)
512
+ .join(", ");
513
+ return `${sourceSignature.typeParametersText}(${parametersText}) => ${rewriteSourceTypeText(sourceSignature.returnTypeText, opts.localTypeNameRemaps, opts.anonymousStructuralAliases)}`;
514
+ };
515
+ const isGeneratedStructuralHelperName = (name) => name.startsWith("__Anon_") || /__\d+$/.test(name);
516
+ const buildAnonymousStructuralAliasMap = (plan) => {
517
+ const aliases = new Map();
518
+ const registerAnonymousClass = (localName, declaration) => {
519
+ if (!isGeneratedStructuralHelperName(localName))
520
+ return;
521
+ const members = [];
522
+ for (const member of declaration.members) {
523
+ if (member.kind === "propertyDeclaration") {
524
+ if (isPortableMarkerMemberName(member.name))
525
+ continue;
526
+ members.push({
527
+ kind: "propertySignature",
528
+ name: member.name,
529
+ type: member.type ?? { kind: "unknownType" },
530
+ isOptional: false,
531
+ isReadonly: member.isReadonly,
532
+ });
533
+ continue;
534
+ }
535
+ if (member.kind === "methodDeclaration") {
536
+ if (isPortableMarkerMemberName(member.name))
537
+ continue;
538
+ members.push({
539
+ kind: "methodSignature",
540
+ name: member.name,
541
+ parameters: member.parameters,
542
+ returnType: member.returnType,
543
+ typeParameters: member.typeParameters,
544
+ });
545
+ }
546
+ }
547
+ const shape = renderPortableType({ kind: "objectType", members }, declaration.typeParameters?.map((typeParameter) => typeParameter.name) ?? [], new Map(), new Map());
548
+ const existing = aliases.get(shape) ?? [];
549
+ existing.push({
550
+ name: localName,
551
+ typeParameters: declaration.typeParameters?.map((typeParameter) => typeParameter.name) ??
552
+ [],
553
+ });
554
+ aliases.set(shape, existing);
555
+ };
556
+ for (const symbol of plan.typeDeclarations) {
557
+ if (symbol.kind !== "class" || symbol.declaration.kind !== "classDeclaration") {
558
+ continue;
559
+ }
560
+ registerAnonymousClass(symbol.localName, symbol.declaration);
561
+ }
562
+ for (const helper of plan.internalHelperTypeDeclarations) {
563
+ if (helper.kind !== "class")
564
+ continue;
565
+ registerAnonymousClass(helper.emittedName, helper.declaration);
566
+ }
567
+ const uniqueAliases = new Map();
568
+ for (const [shape, candidates] of aliases.entries()) {
569
+ if (candidates.length !== 1)
570
+ continue;
571
+ const onlyCandidate = candidates[0];
572
+ if (!onlyCandidate)
573
+ continue;
574
+ uniqueAliases.set(shape, onlyCandidate);
575
+ }
576
+ return uniqueAliases;
577
+ };
578
+ const collectReferencedPortableTypeNames = (type, typeParametersInScope, out) => {
579
+ if (!type)
580
+ return;
581
+ switch (type.kind) {
582
+ case "primitiveType":
583
+ case "literalType":
584
+ case "voidType":
585
+ case "neverType":
586
+ case "unknownType":
587
+ case "anyType":
588
+ return;
589
+ case "typeParameterType":
590
+ if (!typeParametersInScope.has(type.name)) {
591
+ out.add(type.name);
592
+ }
593
+ return;
594
+ case "arrayType":
595
+ collectReferencedPortableTypeNames(type.elementType, typeParametersInScope, out);
596
+ return;
597
+ case "tupleType":
598
+ for (const element of type.elementTypes) {
599
+ collectReferencedPortableTypeNames(element, typeParametersInScope, out);
600
+ }
601
+ return;
602
+ case "unionType":
603
+ case "intersectionType":
604
+ for (const member of type.types) {
605
+ collectReferencedPortableTypeNames(member, typeParametersInScope, out);
606
+ }
607
+ return;
608
+ case "dictionaryType":
609
+ collectReferencedPortableTypeNames(type.keyType, typeParametersInScope, out);
610
+ collectReferencedPortableTypeNames(type.valueType, typeParametersInScope, out);
611
+ return;
612
+ case "functionType":
613
+ for (const parameter of type.parameters) {
614
+ collectReferencedPortableTypeNames(parameter.type, typeParametersInScope, out);
615
+ }
616
+ collectReferencedPortableTypeNames(type.returnType, typeParametersInScope, out);
617
+ return;
618
+ case "objectType":
619
+ for (const member of type.members) {
620
+ if (member.kind === "propertySignature") {
621
+ collectReferencedPortableTypeNames(member.type, typeParametersInScope, out);
622
+ continue;
623
+ }
624
+ const nestedTypeParameters = new Set(typeParametersInScope);
625
+ for (const typeParameter of member.typeParameters ?? []) {
626
+ nestedTypeParameters.add(typeParameter.name);
627
+ }
628
+ for (const parameter of member.parameters) {
629
+ collectReferencedPortableTypeNames(parameter.type, nestedTypeParameters, out);
630
+ }
631
+ collectReferencedPortableTypeNames(member.returnType, nestedTypeParameters, out);
632
+ }
633
+ return;
634
+ case "referenceType":
635
+ out.add(renderReferenceType(type.name, type.typeArguments, []).split("<")[0]);
636
+ for (const typeArgument of type.typeArguments ?? []) {
637
+ collectReferencedPortableTypeNames(typeArgument, typeParametersInScope, out);
638
+ }
639
+ return;
640
+ }
641
+ };
642
+ const collectReferencedPortableTypesFromParameters = (parameters, typeParametersInScope, out) => {
643
+ for (const parameter of parameters) {
644
+ collectReferencedPortableTypeNames(parameter.type, typeParametersInScope, out);
645
+ }
646
+ };
647
+ const collectReferencedPortableTypeNamesFromDeclaration = (declaration, out) => {
648
+ switch (declaration.kind) {
649
+ case "enumDeclaration":
650
+ return;
651
+ case "typeAliasDeclaration": {
652
+ const typeParametersInScope = new Set((declaration.typeParameters ?? []).map((typeParameter) => typeParameter.name));
653
+ collectReferencedPortableTypeNames(declaration.type, typeParametersInScope, out);
654
+ return;
655
+ }
656
+ case "interfaceDeclaration": {
657
+ const typeParametersInScope = new Set((declaration.typeParameters ?? []).map((typeParameter) => typeParameter.name));
658
+ for (const baseType of declaration.extends) {
659
+ collectReferencedPortableTypeNames(baseType, typeParametersInScope, out);
660
+ }
661
+ for (const member of declaration.members) {
662
+ if (member.kind === "propertySignature") {
663
+ collectReferencedPortableTypeNames(member.type, typeParametersInScope, out);
664
+ continue;
665
+ }
666
+ const nestedTypeParameters = new Set(typeParametersInScope);
667
+ for (const typeParameter of member.typeParameters ?? []) {
668
+ nestedTypeParameters.add(typeParameter.name);
669
+ }
670
+ collectReferencedPortableTypesFromParameters(member.parameters, nestedTypeParameters, out);
671
+ collectReferencedPortableTypeNames(member.returnType, nestedTypeParameters, out);
672
+ }
673
+ return;
674
+ }
675
+ case "classDeclaration": {
676
+ const typeParametersInScope = new Set((declaration.typeParameters ?? []).map((typeParameter) => typeParameter.name));
677
+ if (declaration.superClass) {
678
+ collectReferencedPortableTypeNames(declaration.superClass, typeParametersInScope, out);
679
+ }
680
+ for (const implementedType of declaration.implements) {
681
+ collectReferencedPortableTypeNames(implementedType, typeParametersInScope, out);
682
+ }
683
+ for (const member of declaration.members) {
684
+ switch (member.kind) {
685
+ case "constructorDeclaration":
686
+ collectReferencedPortableTypesFromParameters(member.parameters, typeParametersInScope, out);
687
+ continue;
688
+ case "propertyDeclaration":
689
+ collectReferencedPortableTypeNames(member.type, typeParametersInScope, out);
690
+ continue;
691
+ case "methodDeclaration": {
692
+ const nestedTypeParameters = new Set(typeParametersInScope);
693
+ for (const typeParameter of member.typeParameters ?? []) {
694
+ nestedTypeParameters.add(typeParameter.name);
695
+ }
696
+ collectReferencedPortableTypesFromParameters(member.parameters, nestedTypeParameters, out);
697
+ collectReferencedPortableTypeNames(member.returnType, nestedTypeParameters, out);
698
+ continue;
699
+ }
700
+ }
701
+ }
702
+ return;
703
+ }
704
+ }
705
+ };
706
+ const classifyLocalTypeDeclarationKind = (statement) => {
707
+ switch (statement.kind) {
708
+ case "classDeclaration":
709
+ return "class";
710
+ case "interfaceDeclaration":
711
+ return "interface";
712
+ case "enumDeclaration":
713
+ return "enum";
714
+ case "typeAliasDeclaration":
715
+ return "typeAlias";
716
+ default:
717
+ return undefined;
718
+ }
719
+ };
185
720
  const declarationNameOf = (statement) => {
186
721
  switch (statement.kind) {
187
722
  case "functionDeclaration":
@@ -328,6 +863,22 @@ const collectModuleExports = (module, modulesByFileKey) => {
328
863
  value: exportedSymbols.sort((left, right) => left.exportName.localeCompare(right.exportName)),
329
864
  };
330
865
  };
866
+ const finalizeCrossNamespaceReexports = (grouped) => {
867
+ const dtsStatements = [];
868
+ const jsValueStatements = [];
869
+ for (const [key, specs] of Array.from(grouped.entries()).sort((a, b) => a[0].localeCompare(b[0]))) {
870
+ const [moduleSpecifier, kind] = key.split("|");
871
+ const unique = Array.from(new Set(specs)).sort((a, b) => a.localeCompare(b));
872
+ if (kind === "type") {
873
+ dtsStatements.push(`export type { ${unique.join(", ")} } from '${moduleSpecifier}';`);
874
+ continue;
875
+ }
876
+ const statement = `export { ${unique.join(", ")} } from '${moduleSpecifier}';`;
877
+ dtsStatements.push(statement);
878
+ jsValueStatements.push(statement);
879
+ }
880
+ return { dtsStatements, jsValueStatements };
881
+ };
331
882
  const moduleNamespacePath = (namespace) => {
332
883
  return namespace.length > 0 ? namespace : "index";
333
884
  };
@@ -512,27 +1063,62 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
512
1063
  const wrapperImportsByLocalName = new Map();
513
1064
  const typeImportsByLocalName = new Map();
514
1065
  const typeAliasesByName = new Map();
1066
+ const exportedTypeDeclarationNames = new Set();
515
1067
  const exportedFunctionSignaturesByName = new Map();
1068
+ const exportedValueTypesByName = new Map();
516
1069
  const memberTypesByClassAndMember = new Map();
1070
+ const anonymousTypeLiteralsByShape = new Map();
517
1071
  const printTypeParametersText = (typeParameters) => {
518
1072
  if (!typeParameters || typeParameters.length === 0)
519
1073
  return "";
520
1074
  return `<${typeParameters.map((tp) => tp.getText(sourceFile)).join(", ")}>`;
521
1075
  };
522
- const printParameterText = (param) => {
1076
+ const printParameterSignature = (param) => {
523
1077
  const rest = param.dotDotDotToken ? "..." : "";
524
1078
  const name = param.name.getText(sourceFile);
525
1079
  const optional = param.questionToken ? "?" : "";
526
- const type = param.type
527
- ? printTypeNodeText(param.type, sourceFile)
528
- : "unknown";
529
- return `${rest}${name}${optional}: ${type}`;
1080
+ return {
1081
+ prefixText: `${rest}${name}${optional}: `,
1082
+ typeText: param.type ? printTypeNodeText(param.type, sourceFile) : "unknown",
1083
+ };
530
1084
  };
531
1085
  const addExportedFunctionSignature = (name, signature) => {
532
1086
  const signatures = exportedFunctionSignaturesByName.get(name) ?? [];
533
1087
  signatures.push(signature);
534
1088
  exportedFunctionSignaturesByName.set(name, signatures);
535
1089
  };
1090
+ const registerAnonymousTypeLiteralsInTypeNode = (typeNode) => {
1091
+ if (!typeNode)
1092
+ return;
1093
+ const visit = (current) => {
1094
+ if (ts.isTypeLiteralNode(current)) {
1095
+ const shape = renderSourceTypeNodeForAliasLookup(current, new Map());
1096
+ if (!anonymousTypeLiteralsByShape.has(shape)) {
1097
+ const members = new Map();
1098
+ for (const member of current.members) {
1099
+ if (!ts.isPropertySignature(member))
1100
+ continue;
1101
+ if (!member.name || !member.type)
1102
+ continue;
1103
+ const memberName = getPropertyNameText(member.name);
1104
+ if (!memberName)
1105
+ continue;
1106
+ members.set(memberName, {
1107
+ typeNode: member.type,
1108
+ typeText: printTypeNodeText(member.type, sourceFile),
1109
+ isOptional: member.questionToken !== undefined,
1110
+ });
1111
+ }
1112
+ anonymousTypeLiteralsByShape.set(shape, {
1113
+ typeText: printTypeNodeText(current, sourceFile),
1114
+ members,
1115
+ });
1116
+ }
1117
+ }
1118
+ ts.forEachChild(current, visit);
1119
+ };
1120
+ visit(typeNode);
1121
+ };
536
1122
  for (const stmt of sourceFile.statements) {
537
1123
  if (ts.isImportDeclaration(stmt)) {
538
1124
  const moduleSpecifier = ts.isStringLiteral(stmt.moduleSpecifier)
@@ -549,9 +1135,6 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
549
1135
  for (const spec of namedBindings.elements) {
550
1136
  const localName = spec.name.text;
551
1137
  const importedName = (spec.propertyName ?? spec.name).text;
552
- const isTypeOnly = clause.isTypeOnly || spec.isTypeOnly;
553
- if (!isTypeOnly)
554
- continue;
555
1138
  typeImportsByLocalName.set(localName, {
556
1139
  source: moduleSpecifier,
557
1140
  importedName,
@@ -567,6 +1150,7 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
567
1150
  }
568
1151
  if (ts.isTypeAliasDeclaration(stmt)) {
569
1152
  const aliasName = stmt.name.text;
1153
+ const hasExport = stmt.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword);
570
1154
  const typeParameterNames = (stmt.typeParameters ?? []).map((tp) => tp.name.text);
571
1155
  typeAliasesByName.set(aliasName, {
572
1156
  typeParametersText: printTypeParametersText(stmt.typeParameters),
@@ -574,16 +1158,25 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
574
1158
  type: stmt.type,
575
1159
  typeText: printTypeNodeText(stmt.type, sourceFile),
576
1160
  });
1161
+ registerAnonymousTypeLiteralsInTypeNode(stmt.type);
1162
+ if (hasExport) {
1163
+ exportedTypeDeclarationNames.add(aliasName);
1164
+ }
577
1165
  continue;
578
1166
  }
579
1167
  if (ts.isFunctionDeclaration(stmt)) {
580
1168
  const hasExport = stmt.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword);
581
1169
  if (!hasExport || !stmt.name || !stmt.type)
582
1170
  continue;
583
- const parametersText = stmt.parameters.map(printParameterText).join(", ");
1171
+ for (const parameter of stmt.parameters) {
1172
+ registerAnonymousTypeLiteralsInTypeNode(parameter.type);
1173
+ }
1174
+ registerAnonymousTypeLiteralsInTypeNode(stmt.type);
1175
+ const parameters = stmt.parameters.map(printParameterSignature);
584
1176
  addExportedFunctionSignature(stmt.name.text, {
585
1177
  typeParametersText: printTypeParametersText(stmt.typeParameters),
586
- parametersText,
1178
+ typeParameterCount: stmt.typeParameters?.length ?? 0,
1179
+ parameters,
587
1180
  returnTypeText: printTypeNodeText(stmt.type, sourceFile),
588
1181
  });
589
1182
  continue;
@@ -601,16 +1194,25 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
601
1194
  continue;
602
1195
  if (!ts.isArrowFunction(initializer) &&
603
1196
  !ts.isFunctionExpression(initializer)) {
1197
+ if (declaration.type) {
1198
+ registerAnonymousTypeLiteralsInTypeNode(declaration.type);
1199
+ exportedValueTypesByName.set(exportName, {
1200
+ typeText: printTypeNodeText(declaration.type, sourceFile),
1201
+ });
1202
+ }
604
1203
  continue;
605
1204
  }
606
1205
  if (!initializer.type)
607
1206
  continue;
608
- const parametersText = initializer.parameters
609
- .map(printParameterText)
610
- .join(", ");
1207
+ for (const parameter of initializer.parameters) {
1208
+ registerAnonymousTypeLiteralsInTypeNode(parameter.type);
1209
+ }
1210
+ registerAnonymousTypeLiteralsInTypeNode(initializer.type);
1211
+ const parameters = initializer.parameters.map(printParameterSignature);
611
1212
  addExportedFunctionSignature(exportName, {
612
1213
  typeParametersText: printTypeParametersText(initializer.typeParameters),
613
- parametersText,
1214
+ typeParameterCount: initializer.typeParameters?.length ?? 0,
1215
+ parameters,
614
1216
  returnTypeText: printTypeNodeText(initializer.type, sourceFile),
615
1217
  });
616
1218
  }
@@ -618,6 +1220,10 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
618
1220
  }
619
1221
  if (ts.isClassDeclaration(stmt) && stmt.name) {
620
1222
  const className = stmt.name.text;
1223
+ const hasExport = stmt.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword);
1224
+ if (hasExport) {
1225
+ exportedTypeDeclarationNames.add(className);
1226
+ }
621
1227
  const members = memberTypesByClassAndMember.get(className) ??
622
1228
  new Map();
623
1229
  for (const member of stmt.members) {
@@ -640,6 +1246,7 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
640
1246
  const name = getPropertyNameText(member.name);
641
1247
  if (!name)
642
1248
  continue;
1249
+ registerAnonymousTypeLiteralsInTypeNode(member.type);
643
1250
  members.set(name, {
644
1251
  typeNode: member.type,
645
1252
  typeText: printTypeNodeText(member.type, sourceFile),
@@ -654,6 +1261,10 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
654
1261
  }
655
1262
  if (ts.isInterfaceDeclaration(stmt)) {
656
1263
  const interfaceName = stmt.name.text;
1264
+ const hasExport = stmt.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword);
1265
+ if (hasExport) {
1266
+ exportedTypeDeclarationNames.add(interfaceName);
1267
+ }
657
1268
  const members = memberTypesByClassAndMember.get(interfaceName) ??
658
1269
  new Map();
659
1270
  for (const member of stmt.members) {
@@ -664,6 +1275,7 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
664
1275
  const name = getPropertyNameText(member.name);
665
1276
  if (!name)
666
1277
  continue;
1278
+ registerAnonymousTypeLiteralsInTypeNode(member.type);
667
1279
  members.set(name, {
668
1280
  typeNode: member.type,
669
1281
  typeText: printTypeNodeText(member.type, sourceFile),
@@ -673,6 +1285,13 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
673
1285
  if (members.size > 0) {
674
1286
  memberTypesByClassAndMember.set(interfaceName, members);
675
1287
  }
1288
+ continue;
1289
+ }
1290
+ if (ts.isEnumDeclaration(stmt)) {
1291
+ const hasExport = stmt.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword);
1292
+ if (hasExport) {
1293
+ exportedTypeDeclarationNames.add(stmt.name.text);
1294
+ }
676
1295
  }
677
1296
  }
678
1297
  return {
@@ -682,8 +1301,11 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
682
1301
  wrapperImportsByLocalName,
683
1302
  typeImportsByLocalName,
684
1303
  typeAliasesByName,
1304
+ exportedTypeDeclarationNames,
685
1305
  exportedFunctionSignaturesByName,
1306
+ exportedValueTypesByName,
686
1307
  memberTypesByClassAndMember,
1308
+ anonymousTypeLiteralsByShape,
687
1309
  },
688
1310
  };
689
1311
  };
@@ -798,42 +1420,6 @@ const collectExtensionWrapperImportsFromSourceType = (opts) => {
798
1420
  }
799
1421
  return { ok: true, value: wrappers };
800
1422
  };
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
1423
  const moduleNamespaceToInternalSpecifier = (namespace) => {
838
1424
  const nsPath = moduleNamespacePath(namespace);
839
1425
  return `./${nsPath}/internal/index.js`;
@@ -842,6 +1428,10 @@ const toClrTypeName = (namespace, typeName, arity) => {
842
1428
  const suffix = arity && arity > 0 ? `\`${arity}` : "";
843
1429
  return `${namespace}.${typeName}${suffix}`;
844
1430
  };
1431
+ const toBindingTypeAlias = (namespace, typeName, arity) => {
1432
+ const normalizedName = normalizeTypeReferenceName(typeName, arity);
1433
+ return namespace.length > 0 ? `${namespace}.${normalizedName}` : normalizedName;
1434
+ };
845
1435
  const toStableId = (assemblyName, clrName) => {
846
1436
  return `${assemblyName}:${clrName}`;
847
1437
  };
@@ -870,7 +1460,111 @@ const isNumericValueType = (name) => {
870
1460
  name === "System.Byte" ||
871
1461
  name === "System.SByte");
872
1462
  };
873
- const toSignatureType = (type, typeParametersInScope) => {
1463
+ const rewriteBindingSemanticParameter = (parameter, localTypeNameRemaps) => ({
1464
+ ...parameter,
1465
+ type: rewriteBindingSemanticType(parameter.type, localTypeNameRemaps),
1466
+ });
1467
+ const rewriteBindingSemanticMember = (member, localTypeNameRemaps) => {
1468
+ if (member.kind === "propertySignature") {
1469
+ return {
1470
+ ...member,
1471
+ type: rewriteBindingSemanticType(member.type, localTypeNameRemaps) ??
1472
+ member.type,
1473
+ };
1474
+ }
1475
+ return {
1476
+ ...member,
1477
+ parameters: member.parameters.map((parameter) => rewriteBindingSemanticParameter(parameter, localTypeNameRemaps)),
1478
+ returnType: rewriteBindingSemanticType(member.returnType, localTypeNameRemaps) ??
1479
+ member.returnType,
1480
+ };
1481
+ };
1482
+ const rewriteBindingSemanticType = (type, localTypeNameRemaps) => {
1483
+ if (!type)
1484
+ return undefined;
1485
+ switch (type.kind) {
1486
+ case "referenceType": {
1487
+ const rewrittenName = normalizeTypeReferenceName(localTypeNameRemaps.get(type.name) ?? type.name, type.typeArguments?.length);
1488
+ return {
1489
+ ...type,
1490
+ name: rewrittenName,
1491
+ typeArguments: type.typeArguments?.map((arg) => rewriteBindingSemanticType(arg, localTypeNameRemaps)),
1492
+ structuralMembers: type.structuralMembers?.map((member) => rewriteBindingSemanticMember(member, localTypeNameRemaps)),
1493
+ };
1494
+ }
1495
+ case "arrayType":
1496
+ return {
1497
+ ...type,
1498
+ elementType: rewriteBindingSemanticType(type.elementType, localTypeNameRemaps) ??
1499
+ type.elementType,
1500
+ };
1501
+ case "tupleType":
1502
+ return {
1503
+ ...type,
1504
+ elementTypes: type.elementTypes.map((elementType) => rewriteBindingSemanticType(elementType, localTypeNameRemaps)),
1505
+ };
1506
+ case "functionType":
1507
+ return {
1508
+ ...type,
1509
+ parameters: type.parameters.map((parameter) => rewriteBindingSemanticParameter(parameter, localTypeNameRemaps)),
1510
+ returnType: rewriteBindingSemanticType(type.returnType, localTypeNameRemaps) ??
1511
+ type.returnType,
1512
+ };
1513
+ case "objectType":
1514
+ return {
1515
+ ...type,
1516
+ members: type.members.map((member) => rewriteBindingSemanticMember(member, localTypeNameRemaps)),
1517
+ };
1518
+ case "dictionaryType":
1519
+ return {
1520
+ ...type,
1521
+ keyType: rewriteBindingSemanticType(type.keyType, localTypeNameRemaps) ??
1522
+ type.keyType,
1523
+ valueType: rewriteBindingSemanticType(type.valueType, localTypeNameRemaps) ??
1524
+ type.valueType,
1525
+ };
1526
+ case "unionType":
1527
+ case "intersectionType":
1528
+ return {
1529
+ ...type,
1530
+ types: type.types.map((candidate) => rewriteBindingSemanticType(candidate, localTypeNameRemaps)),
1531
+ };
1532
+ default:
1533
+ return type;
1534
+ }
1535
+ };
1536
+ const buildSemanticSignature = (opts) => {
1537
+ return {
1538
+ typeParameters: opts.typeParameters?.map((typeParameter) => typeParameter.name),
1539
+ parameters: opts.parameters.map((parameter) => rewriteBindingSemanticParameter(parameter, opts.localTypeNameRemaps)),
1540
+ returnType: rewriteBindingSemanticType(opts.returnType, opts.localTypeNameRemaps),
1541
+ };
1542
+ };
1543
+ const buildSemanticSignatureFromFunctionType = (type, localTypeNameRemaps) => ({
1544
+ typeParameters: undefined,
1545
+ parameters: type.parameters.map((parameter) => rewriteBindingSemanticParameter(parameter, localTypeNameRemaps)),
1546
+ returnType: rewriteBindingSemanticType(type.returnType, localTypeNameRemaps),
1547
+ });
1548
+ const resolveFunctionTypeFromValueDeclarator = (declarator) => {
1549
+ if (declarator?.type?.kind === "functionType") {
1550
+ return declarator.type;
1551
+ }
1552
+ const initializerType = declarator?.initializer?.inferredType;
1553
+ if (initializerType?.kind === "functionType") {
1554
+ return initializerType;
1555
+ }
1556
+ return undefined;
1557
+ };
1558
+ const areBindingSemanticSignaturesEqual = (left, right) => JSON.stringify(left ?? null) === JSON.stringify(right ?? null);
1559
+ const areBindingSemanticsEqual = (left, right) => left.kind === right.kind &&
1560
+ left.clrName === right.clrName &&
1561
+ left.declaringClrType === right.declaringClrType &&
1562
+ left.declaringAssemblyName === right.declaringAssemblyName &&
1563
+ left.semanticOptional === right.semanticOptional &&
1564
+ JSON.stringify(left.semanticType ?? null) ===
1565
+ JSON.stringify(right.semanticType ?? null) &&
1566
+ areBindingSemanticSignaturesEqual(left.semanticSignature, right.semanticSignature);
1567
+ const toSignatureType = (type, typeParametersInScope, localTypeNameRemaps = new Map()) => {
874
1568
  if (!type)
875
1569
  return "System.Object";
876
1570
  switch (type.kind) {
@@ -893,20 +1587,20 @@ const toSignatureType = (type, typeParametersInScope) => {
893
1587
  case "typeParameterType":
894
1588
  return type.name;
895
1589
  case "arrayType":
896
- return `${toSignatureType(type.elementType, typeParametersInScope)}[]`;
1590
+ return `${toSignatureType(type.elementType, typeParametersInScope, localTypeNameRemaps)}[]`;
897
1591
  case "tupleType":
898
1592
  case "objectType":
899
1593
  case "functionType":
900
1594
  case "dictionaryType":
901
1595
  return "System.Object";
902
1596
  case "intersectionType":
903
- return toSignatureType(type.types[0], typeParametersInScope);
1597
+ return toSignatureType(type.types[0], typeParametersInScope, localTypeNameRemaps);
904
1598
  case "unionType": {
905
1599
  const nonUndefined = type.types.filter((candidate) => {
906
1600
  return !(candidate.kind === "primitiveType" && candidate.name === "undefined");
907
1601
  });
908
1602
  if (nonUndefined.length === 1 && nonUndefined[0]) {
909
- const single = toSignatureType(nonUndefined[0], typeParametersInScope);
1603
+ const single = toSignatureType(nonUndefined[0], typeParametersInScope, localTypeNameRemaps);
910
1604
  if (isNumericValueType(single)) {
911
1605
  return `System.Nullable\`1[[${single}]]`;
912
1606
  }
@@ -917,12 +1611,12 @@ const toSignatureType = (type, typeParametersInScope) => {
917
1611
  case "referenceType": {
918
1612
  if (typeParametersInScope.includes(type.name))
919
1613
  return type.name;
920
- const normalizedName = normalizeTypeReferenceName(type.name, type.typeArguments?.length);
1614
+ const normalizedName = normalizeTypeReferenceName(localTypeNameRemaps.get(type.name) ?? type.name, type.typeArguments?.length);
921
1615
  if (!type.typeArguments || type.typeArguments.length === 0) {
922
1616
  return normalizedName;
923
1617
  }
924
1618
  const args = type.typeArguments
925
- .map((arg) => toSignatureType(arg, typeParametersInScope))
1619
+ .map((arg) => toSignatureType(arg, typeParametersInScope, localTypeNameRemaps))
926
1620
  .join(",");
927
1621
  return `${normalizedName}[[${args}]]`;
928
1622
  }
@@ -947,13 +1641,19 @@ const makeMethodBinding = (opts) => {
947
1641
  : undefined)
948
1642
  .filter((name) => name !== undefined)));
949
1643
  const normalizedSignature = `${opts.methodName}|(${opts.parameters
950
- .map((parameter) => toSignatureType(parameter.type, typeParameterScope))
951
- .join(",")}):${toSignatureType(opts.returnType, typeParameterScope)}|static=${opts.isStatic ? "true" : "false"}`;
1644
+ .map((parameter) => toSignatureType(parameter.type, typeParameterScope, opts.localTypeNameRemaps))
1645
+ .join(",")}):${toSignatureType(opts.returnType, typeParameterScope, opts.localTypeNameRemaps)}|static=${opts.isStatic ? "true" : "false"}`;
952
1646
  const stableId = `${toStableId(opts.declaringAssemblyName, opts.declaringClrType)}::method:${opts.methodName}|${normalizedSignature}`;
953
1647
  return {
954
1648
  stableId,
955
1649
  clrName: opts.methodName,
956
1650
  normalizedSignature,
1651
+ semanticSignature: buildSemanticSignature({
1652
+ typeParameters: opts.typeParameters,
1653
+ parameters: opts.parameters,
1654
+ returnType: opts.returnType,
1655
+ localTypeNameRemaps: opts.localTypeNameRemaps ?? new Map(),
1656
+ }),
957
1657
  arity: opts.arity,
958
1658
  parameterCount: opts.parameters.length,
959
1659
  isStatic: opts.isStatic,
@@ -967,16 +1667,17 @@ const makeMethodBinding = (opts) => {
967
1667
  isExtensionMethod: false,
968
1668
  };
969
1669
  };
970
- const renderClassInternal = (declaration, namespace, memberOverrides) => {
1670
+ const renderClassInternal = (declaration, namespace, memberOverrides, emittedName = declaration.name, localTypeNameRemaps = new Map(), brandName = declaration.name, bindingAlias = declaration.name) => {
971
1671
  const lines = [];
1672
+ const isSyntheticAnonymousStructuralClass = emittedName.startsWith("__Anon_") || brandName.startsWith("__Anon_");
972
1673
  const typeParameterScope = (declaration.typeParameters ?? []).map((typeParameter) => typeParameter.name);
973
1674
  const typeParameters = printTypeParameters(declaration.typeParameters);
974
- const markerName = `__tsonic_type_${sanitizeForBrand(namespace)}_${sanitizeForBrand(declaration.name)}`;
1675
+ const markerName = `__tsonic_type_${sanitizeForBrand(namespace)}_${sanitizeForBrand(brandName)}`;
975
1676
  const heritageNames = [
976
1677
  declaration.superClass
977
- ? renderPortableType(declaration.superClass, typeParameterScope)
1678
+ ? renderPortableType(declaration.superClass, typeParameterScope, localTypeNameRemaps)
978
1679
  : undefined,
979
- ...declaration.implements.map((implementedType) => renderPortableType(implementedType, typeParameterScope)),
1680
+ ...declaration.implements.map((implementedType) => renderPortableType(implementedType, typeParameterScope, localTypeNameRemaps)),
980
1681
  ]
981
1682
  .filter((name) => name !== undefined)
982
1683
  .map((name) => name.trim())
@@ -987,8 +1688,11 @@ const renderClassInternal = (declaration, namespace, memberOverrides) => {
987
1688
  const extendsClause = heritageNames.length > 0
988
1689
  ? ` extends ${Array.from(new Set(heritageNames)).join(", ")}`
989
1690
  : "";
990
- lines.push(`export interface ${declaration.name}$instance${typeParameters}${extendsClause} {`);
991
- lines.push(` readonly ${markerName}: never;`);
1691
+ lines.push(`export interface ${emittedName}$instance${typeParameters}${extendsClause} {`);
1692
+ if (!isSyntheticAnonymousStructuralClass) {
1693
+ lines.push(` readonly ${markerName}: never;`);
1694
+ }
1695
+ lines.push(renderBindingAliasMarker(namespace, bindingAlias));
992
1696
  const instanceMembers = declaration.members.filter((member) => {
993
1697
  if (member.kind === "constructorDeclaration")
994
1698
  return false;
@@ -998,7 +1702,7 @@ const renderClassInternal = (declaration, namespace, memberOverrides) => {
998
1702
  });
999
1703
  for (const member of instanceMembers) {
1000
1704
  if (member.kind === "methodDeclaration") {
1001
- lines.push(` ${renderMethodSignature(member.name, member.typeParameters, member.parameters, member.returnType)}`);
1705
+ lines.push(` ${renderMethodSignature(member.name, member.typeParameters, member.parameters, member.returnType, localTypeNameRemaps)}`);
1002
1706
  continue;
1003
1707
  }
1004
1708
  if (member.kind === "propertyDeclaration") {
@@ -1010,24 +1714,33 @@ const renderClassInternal = (declaration, namespace, memberOverrides) => {
1010
1714
  const hasSetter = hasAccessorBody
1011
1715
  ? member.setterBody !== undefined
1012
1716
  : !member.isReadonly;
1717
+ const optionalBySource = memberOverride?.emitOptionalPropertySyntax === true &&
1718
+ memberOverride.isOptional === true &&
1719
+ !member.name.startsWith("__tsonic_type_");
1720
+ const optionalMark = optionalBySource ? "?" : "";
1013
1721
  const baseType = (memberOverride?.replaceWithSourceType
1014
1722
  ? memberOverride.sourceTypeText
1015
- : undefined) ?? renderPortableType(member.type);
1723
+ : undefined) ??
1724
+ renderPortableType(member.type, typeParameterScope, localTypeNameRemaps);
1016
1725
  const wrappedType = applyWrappersToBaseType(baseType, memberOverride?.wrappers ?? []);
1017
- const memberType = memberOverride?.isOptional === true
1726
+ const memberType = memberOverride?.isOptional === true && !optionalBySource
1018
1727
  ? ensureUndefinedInType(wrappedType)
1019
1728
  : wrappedType;
1020
1729
  if (hasGetter && !hasSetter) {
1021
- lines.push(` readonly ${member.name}: ${memberType};`);
1730
+ lines.push(` readonly ${member.name}${optionalMark}: ${memberType};`);
1022
1731
  continue;
1023
1732
  }
1024
- lines.push(` ${member.name}: ${memberType};`);
1733
+ lines.push(` ${member.name}${optionalMark}: ${memberType};`);
1025
1734
  }
1026
1735
  }
1027
1736
  lines.push("}");
1028
1737
  lines.push("");
1029
- lines.push(`export const ${declaration.name}: {`);
1030
- lines.push(` new(...args: unknown[]): ${declaration.name}${typeParameters};`);
1738
+ if (isSyntheticAnonymousStructuralClass) {
1739
+ lines.push(`export type ${emittedName}${typeParameters} = ${emittedName}$instance${typeParameters};`);
1740
+ return lines;
1741
+ }
1742
+ lines.push(`export const ${emittedName}: {`);
1743
+ lines.push(` new(...args: unknown[]): ${emittedName}${typeParameters};`);
1031
1744
  const staticMembers = declaration.members.filter((member) => {
1032
1745
  if (member.kind === "constructorDeclaration")
1033
1746
  return false;
@@ -1035,26 +1748,26 @@ const renderClassInternal = (declaration, namespace, memberOverrides) => {
1035
1748
  });
1036
1749
  for (const member of staticMembers) {
1037
1750
  if (member.kind === "methodDeclaration") {
1038
- lines.push(` ${renderMethodSignature(member.name, member.typeParameters, member.parameters, member.returnType)}`);
1751
+ lines.push(` ${renderMethodSignature(member.name, member.typeParameters, member.parameters, member.returnType, localTypeNameRemaps)}`);
1039
1752
  continue;
1040
1753
  }
1041
1754
  if (member.kind === "propertyDeclaration") {
1042
- lines.push(` ${member.name}: ${renderPortableType(member.type)};`);
1755
+ lines.push(` ${member.name}: ${renderPortableType(member.type, typeParameterScope, localTypeNameRemaps)};`);
1043
1756
  }
1044
1757
  }
1045
1758
  lines.push("};");
1046
1759
  lines.push("");
1047
- lines.push(`export type ${declaration.name}${typeParameters} = ${declaration.name}$instance${typeParameters};`);
1760
+ lines.push(`export type ${emittedName}${typeParameters} = ${emittedName}$instance${typeParameters};`);
1048
1761
  lines.push("");
1049
1762
  return lines;
1050
1763
  };
1051
- const renderInterfaceInternal = (declaration, namespace, memberOverrides) => {
1764
+ const renderInterfaceInternal = (declaration, namespace, memberOverrides, emittedName = declaration.name, localTypeNameRemaps = new Map(), brandName = declaration.name, bindingAlias = declaration.name) => {
1052
1765
  const lines = [];
1053
1766
  const typeParameterScope = (declaration.typeParameters ?? []).map((typeParameter) => typeParameter.name);
1054
1767
  const typeParameters = printTypeParameters(declaration.typeParameters);
1055
- const markerName = `__tsonic_type_${sanitizeForBrand(namespace)}_${sanitizeForBrand(declaration.name)}`;
1768
+ const markerName = `__tsonic_type_${sanitizeForBrand(namespace)}_${sanitizeForBrand(brandName)}`;
1056
1769
  const extendsNames = declaration.extends
1057
- .map((baseType) => renderPortableType(baseType, typeParameterScope).trim())
1770
+ .map((baseType) => renderPortableType(baseType, typeParameterScope, localTypeNameRemaps).trim())
1058
1771
  .filter((name) => name.length > 0 &&
1059
1772
  name !== "unknown" &&
1060
1773
  name !== "never" &&
@@ -1062,11 +1775,12 @@ const renderInterfaceInternal = (declaration, namespace, memberOverrides) => {
1062
1775
  const extendsClause = extendsNames.length > 0
1063
1776
  ? ` extends ${Array.from(new Set(extendsNames)).join(", ")}`
1064
1777
  : "";
1065
- lines.push(`export interface ${declaration.name}$instance${typeParameters}${extendsClause} {`);
1778
+ lines.push(`export interface ${emittedName}$instance${typeParameters}${extendsClause} {`);
1066
1779
  lines.push(` readonly ${markerName}?: never;`);
1780
+ lines.push(renderBindingAliasMarker(namespace, bindingAlias));
1067
1781
  for (const member of declaration.members) {
1068
1782
  if (member.kind === "methodSignature") {
1069
- lines.push(` ${renderMethodSignature(member.name, member.typeParameters, member.parameters, member.returnType)}`);
1783
+ lines.push(` ${renderMethodSignature(member.name, member.typeParameters, member.parameters, member.returnType, localTypeNameRemaps)}`);
1070
1784
  continue;
1071
1785
  }
1072
1786
  if (member.kind === "propertySignature") {
@@ -1077,7 +1791,8 @@ const renderInterfaceInternal = (declaration, namespace, memberOverrides) => {
1077
1791
  const optionalMark = optionalBySource || member.isOptional ? "?" : "";
1078
1792
  const baseType = (memberOverride?.replaceWithSourceType
1079
1793
  ? memberOverride.sourceTypeText
1080
- : undefined) ?? renderPortableType(member.type);
1794
+ : undefined) ??
1795
+ renderPortableType(member.type, typeParameterScope, localTypeNameRemaps);
1081
1796
  const wrappedType = applyWrappersToBaseType(baseType, memberOverride?.wrappers ?? []);
1082
1797
  const memberType = memberOverride?.isOptional && !optionalBySource
1083
1798
  ? ensureUndefinedInType(wrappedType)
@@ -1087,13 +1802,13 @@ const renderInterfaceInternal = (declaration, namespace, memberOverrides) => {
1087
1802
  }
1088
1803
  lines.push("}");
1089
1804
  lines.push("");
1090
- lines.push(`export type ${declaration.name}${typeParameters} = ${declaration.name}$instance${typeParameters};`);
1805
+ lines.push(`export type ${emittedName}${typeParameters} = ${emittedName}$instance${typeParameters};`);
1091
1806
  lines.push("");
1092
1807
  return lines;
1093
1808
  };
1094
- const renderEnumInternal = (declaration) => {
1809
+ const renderEnumInternal = (declaration, emittedName = declaration.name) => {
1095
1810
  const lines = [];
1096
- lines.push(`export enum ${declaration.name} {`);
1811
+ lines.push(`export enum ${emittedName} {`);
1097
1812
  declaration.members.forEach((member, index) => {
1098
1813
  lines.push(` ${member.name} = ${index},`);
1099
1814
  });
@@ -1101,16 +1816,22 @@ const renderEnumInternal = (declaration) => {
1101
1816
  lines.push("");
1102
1817
  return lines;
1103
1818
  };
1104
- const renderStructuralAliasInternal = (declaration, namespace, memberOverrides) => {
1819
+ const renderStructuralAliasInternal = (declaration, namespace, memberOverrides, emittedName = declaration.name, localTypeNameRemaps = new Map(), brandAliasName = `${declaration.name}__Alias${(declaration.typeParameters?.length ?? 0) > 0
1820
+ ? `_${declaration.typeParameters?.length ?? 0}`
1821
+ : ""}`, bindingAlias = `${declaration.name}__Alias${(declaration.typeParameters?.length ?? 0) > 0
1822
+ ? `_${declaration.typeParameters?.length ?? 0}`
1823
+ : ""}`) => {
1105
1824
  if (declaration.type.kind !== "objectType")
1106
1825
  return [];
1107
1826
  const lines = [];
1108
1827
  const arity = declaration.typeParameters?.length ?? 0;
1109
1828
  const typeParameters = printTypeParameters(declaration.typeParameters);
1110
- const internalAliasName = `${declaration.name}__Alias${arity > 0 ? `_${arity}` : ""}`;
1111
- const markerName = `__tsonic_type_${sanitizeForBrand(namespace)}_${sanitizeForBrand(internalAliasName)}`;
1829
+ const typeParameterScope = (declaration.typeParameters ?? []).map((typeParameter) => typeParameter.name);
1830
+ const internalAliasName = `${emittedName}__Alias${arity > 0 ? `_${arity}` : ""}`;
1831
+ const markerName = `__tsonic_type_${sanitizeForBrand(namespace)}_${sanitizeForBrand(brandAliasName)}`;
1112
1832
  lines.push(`export interface ${internalAliasName}$instance${typeParameters} {`);
1113
1833
  lines.push(` readonly ${markerName}?: never;`);
1834
+ lines.push(renderBindingAliasMarker(namespace, bindingAlias));
1114
1835
  for (const member of declaration.type.members) {
1115
1836
  if (member.kind === "methodSignature") {
1116
1837
  lines.push(` ${renderMethodSignature(member.name, member.typeParameters, member.parameters, member.returnType)}`);
@@ -1121,7 +1842,8 @@ const renderStructuralAliasInternal = (declaration, namespace, memberOverrides)
1121
1842
  const optionalMark = member.isOptional ? "?" : "";
1122
1843
  const baseType = (memberOverride?.replaceWithSourceType
1123
1844
  ? memberOverride.sourceTypeText
1124
- : undefined) ?? renderPortableType(member.type);
1845
+ : undefined) ??
1846
+ renderPortableType(member.type, typeParameterScope, localTypeNameRemaps);
1125
1847
  const wrappedType = applyWrappersToBaseType(baseType, memberOverride?.wrappers ?? []);
1126
1848
  const memberType = memberOverride?.isOptional === true
1127
1849
  ? ensureUndefinedInType(wrappedType)
@@ -1135,14 +1857,67 @@ const renderStructuralAliasInternal = (declaration, namespace, memberOverrides)
1135
1857
  lines.push("");
1136
1858
  return lines;
1137
1859
  };
1138
- const renderContainerInternal = (entry) => {
1860
+ const renderTypeAliasInternal = (declaration, emittedName = declaration.name, localTypeNameRemaps = new Map(), anonymousStructuralAliases = new Map()) => {
1861
+ if (declaration.type.kind === "objectType")
1862
+ return [];
1863
+ const typeParameterScope = (declaration.typeParameters ?? []).map((typeParameter) => typeParameter.name);
1864
+ const typeParameters = printTypeParameters(declaration.typeParameters);
1865
+ return [
1866
+ `export type ${emittedName}${typeParameters} = ${renderPortableType(declaration.type, typeParameterScope, localTypeNameRemaps, anonymousStructuralAliases)};`,
1867
+ "",
1868
+ ];
1869
+ };
1870
+ const renderSourceAliasPlan = (plan, anonymousStructuralAliases) => {
1871
+ const sourceTypeParams = plan.sourceAlias?.typeParametersText ??
1872
+ printTypeParameters(plan.declaration.typeParameters);
1873
+ if (plan.declaration.type.kind === "objectType") {
1874
+ const arity = plan.declaration.typeParameters?.length ?? 0;
1875
+ const internalName = `${plan.declaration.name}__Alias${arity > 0 ? `_${arity}` : ""}`;
1876
+ const typeArgs = plan.sourceAlias && plan.sourceAlias.typeParameterNames.length > 0
1877
+ ? `<${plan.sourceAlias.typeParameterNames.join(", ")}>`
1878
+ : plan.declaration.typeParameters &&
1879
+ plan.declaration.typeParameters.length > 0
1880
+ ? `<${plan.declaration.typeParameters.map((tp) => tp.name).join(", ")}>`
1881
+ : "";
1882
+ return {
1883
+ line: `export type ${plan.declaration.name}${sourceTypeParams} = ${internalName}${typeArgs};`,
1884
+ internalImport: internalName,
1885
+ };
1886
+ }
1887
+ const rhs = renderPortableType(plan.declaration.type, plan.declaration.typeParameters?.map((tp) => tp.name) ?? [], new Map(), anonymousStructuralAliases);
1888
+ const shouldPreferSourceAliasText = plan.sourceAlias !== undefined &&
1889
+ !typeNodeUsesImportedTypeNames(plan.sourceAlias.type, plan.typeImportsByLocalName) &&
1890
+ /__\d+\b|\$instance\b/.test(rhs);
1891
+ return {
1892
+ line: `export type ${plan.declaration.name}${sourceTypeParams} = ${shouldPreferSourceAliasText
1893
+ ? rewriteSourceTypeText(plan.sourceAlias.typeText, new Map(), anonymousStructuralAliases)
1894
+ : rhs};`,
1895
+ };
1896
+ };
1897
+ const renderContainerInternal = (entry, anonymousStructuralAliases) => {
1139
1898
  const lines = [];
1140
1899
  lines.push(`export abstract class ${entry.module.className}$instance {`);
1141
1900
  for (const method of entry.methods) {
1142
- lines.push(` static ${renderMethodSignature(method.localName, method.declaration.typeParameters, method.declaration.parameters, method.declaration.returnType)}`);
1901
+ const sourceSignature = renderSourceFunctionSignature({
1902
+ declaration: method.declaration,
1903
+ sourceSignatures: method.sourceSignatures,
1904
+ localTypeNameRemaps: method.localTypeNameRemaps,
1905
+ anonymousStructuralAliases,
1906
+ });
1907
+ lines.push(` static ${sourceSignature
1908
+ ? `${method.localName}${sourceSignature.typeParametersText}(${sourceSignature.parametersText}): ${sourceSignature.returnTypeText};`
1909
+ : renderMethodSignature(method.localName, method.declaration.typeParameters, method.declaration.parameters, method.declaration.returnType, method.localTypeNameRemaps, anonymousStructuralAliases)}`);
1143
1910
  }
1144
1911
  for (const variable of entry.variables) {
1145
- lines.push(` static ${variable.localName}: ${renderPortableType(variable.declarator?.type)};`);
1912
+ const sourceFunctionTypeText = renderSourceFunctionType({
1913
+ sourceSignatures: variable.sourceSignatures,
1914
+ localTypeNameRemaps: variable.localTypeNameRemaps,
1915
+ anonymousStructuralAliases,
1916
+ });
1917
+ const sourceTypeText = sourceFunctionTypeText ??
1918
+ renderSourceValueType(variable.sourceType, variable.localTypeNameRemaps, anonymousStructuralAliases);
1919
+ lines.push(` static ${variable.localName}: ${sourceTypeText ??
1920
+ renderPortableType(variable.declarator?.type, [], variable.localTypeNameRemaps, anonymousStructuralAliases)};`);
1146
1921
  }
1147
1922
  lines.push("}");
1148
1923
  lines.push("");
@@ -1150,7 +1925,7 @@ const renderContainerInternal = (entry) => {
1150
1925
  lines.push("");
1151
1926
  return lines;
1152
1927
  };
1153
- const buildTypeBindingFromClass = (declaration, namespace, assemblyName) => {
1928
+ const buildTypeBindingFromClass = (declaration, namespace, assemblyName, localTypeNameRemaps = new Map()) => {
1154
1929
  const declaringClrType = toClrTypeName(namespace, declaration.name, declaration.typeParameters?.length ?? 0);
1155
1930
  const typeStableId = toStableId(assemblyName, declaringClrType);
1156
1931
  const typeParameterScope = declaration.typeParameters?.map((typeParameter) => typeParameter.name) ??
@@ -1162,7 +1937,7 @@ const buildTypeBindingFromClass = (declaration, namespace, assemblyName) => {
1162
1937
  if (member.kind === "constructorDeclaration") {
1163
1938
  constructors.push({
1164
1939
  normalizedSignature: `.ctor|(${member.parameters
1165
- .map((parameter) => toSignatureType(parameter.type, typeParameterScope))
1940
+ .map((parameter) => toSignatureType(parameter.type, typeParameterScope, localTypeNameRemaps))
1166
1941
  .join(",")})|static=false`,
1167
1942
  isStatic: false,
1168
1943
  parameterCount: member.parameters.length,
@@ -1176,12 +1951,14 @@ const buildTypeBindingFromClass = (declaration, namespace, assemblyName) => {
1176
1951
  methodName: member.name,
1177
1952
  parameters: member.parameters,
1178
1953
  returnType: member.returnType,
1954
+ typeParameters: member.typeParameters,
1179
1955
  arity: member.typeParameters?.length ?? 0,
1180
1956
  parameterModifiers: buildParameterModifiers(member.parameters),
1181
1957
  isStatic: member.isStatic,
1182
1958
  isAbstract: member.body === undefined,
1183
1959
  isVirtual: member.isVirtual,
1184
1960
  isOverride: member.isOverride,
1961
+ localTypeNameRemaps,
1185
1962
  }));
1186
1963
  continue;
1187
1964
  }
@@ -1193,11 +1970,12 @@ const buildTypeBindingFromClass = (declaration, namespace, assemblyName) => {
1193
1970
  const hasSetter = hasAccessorBody
1194
1971
  ? member.setterBody !== undefined
1195
1972
  : !member.isReadonly;
1196
- const propertyType = toSignatureType(member.type, typeParameterScope);
1973
+ const propertyType = toSignatureType(member.type, typeParameterScope, localTypeNameRemaps);
1197
1974
  properties.push({
1198
1975
  stableId: `${typeStableId}::property:${member.name}`,
1199
1976
  clrName: member.name,
1200
1977
  normalizedSignature: `${member.name}|:${propertyType}|static=${member.isStatic ? "true" : "false"}|accessor=${hasGetter && hasSetter ? "getset" : hasSetter ? "set" : "get"}`,
1978
+ semanticType: rewriteBindingSemanticType(member.type, localTypeNameRemaps),
1201
1979
  isStatic: member.isStatic,
1202
1980
  isAbstract: member.getterBody === undefined && member.setterBody === undefined
1203
1981
  ? false
@@ -1215,6 +1993,7 @@ const buildTypeBindingFromClass = (declaration, namespace, assemblyName) => {
1215
1993
  return {
1216
1994
  stableId: typeStableId,
1217
1995
  clrName: declaringClrType,
1996
+ alias: toBindingTypeAlias(namespace, declaration.name, declaration.typeParameters?.length ?? 0),
1218
1997
  assemblyName,
1219
1998
  kind: declaration.isStruct ? "Struct" : "Class",
1220
1999
  accessibility: "Public",
@@ -1239,7 +2018,7 @@ const buildTypeBindingFromClass = (declaration, namespace, assemblyName) => {
1239
2018
  ],
1240
2019
  };
1241
2020
  };
1242
- const buildTypeBindingFromInterface = (declaration, namespace, assemblyName) => {
2021
+ const buildTypeBindingFromInterface = (declaration, namespace, assemblyName, localTypeNameRemaps = new Map()) => {
1243
2022
  const declaringClrType = toClrTypeName(namespace, declaration.name, declaration.typeParameters?.length ?? 0);
1244
2023
  const typeStableId = toStableId(assemblyName, declaringClrType);
1245
2024
  const typeParameterScope = declaration.typeParameters?.map((typeParameter) => typeParameter.name) ??
@@ -1254,17 +2033,21 @@ const buildTypeBindingFromInterface = (declaration, namespace, assemblyName) =>
1254
2033
  methodName: member.name,
1255
2034
  parameters: member.parameters,
1256
2035
  returnType: member.returnType,
2036
+ typeParameters: member.typeParameters,
1257
2037
  arity: member.typeParameters?.length ?? 0,
1258
2038
  parameterModifiers: buildParameterModifiers(member.parameters),
1259
2039
  isStatic: false,
1260
2040
  isAbstract: true,
2041
+ localTypeNameRemaps,
1261
2042
  }));
1262
2043
  continue;
1263
2044
  }
1264
2045
  properties.push({
1265
2046
  stableId: `${typeStableId}::property:${member.name}`,
1266
2047
  clrName: member.name,
1267
- normalizedSignature: `${member.name}|:${toSignatureType(member.type, typeParameterScope)}|static=false|accessor=${member.isReadonly ? "get" : "getset"}`,
2048
+ normalizedSignature: `${member.name}|:${toSignatureType(member.type, typeParameterScope, localTypeNameRemaps)}|static=false|accessor=${member.isReadonly ? "get" : "getset"}`,
2049
+ semanticType: rewriteBindingSemanticType(member.type, localTypeNameRemaps),
2050
+ semanticOptional: member.isOptional,
1268
2051
  isStatic: false,
1269
2052
  isAbstract: true,
1270
2053
  isVirtual: false,
@@ -1279,6 +2062,7 @@ const buildTypeBindingFromInterface = (declaration, namespace, assemblyName) =>
1279
2062
  return {
1280
2063
  stableId: typeStableId,
1281
2064
  clrName: declaringClrType,
2065
+ alias: toBindingTypeAlias(namespace, declaration.name, declaration.typeParameters?.length ?? 0),
1282
2066
  assemblyName,
1283
2067
  kind: declaration.isStruct ? "Struct" : "Interface",
1284
2068
  accessibility: "Public",
@@ -1311,6 +2095,7 @@ const buildTypeBindingFromEnum = (declaration, namespace, assemblyName) => {
1311
2095
  return {
1312
2096
  stableId: typeStableId,
1313
2097
  clrName: declaringClrType,
2098
+ alias: toBindingTypeAlias(namespace, declaration.name),
1314
2099
  assemblyName,
1315
2100
  kind: "Enum",
1316
2101
  accessibility: "Public",
@@ -1326,7 +2111,7 @@ const buildTypeBindingFromEnum = (declaration, namespace, assemblyName) => {
1326
2111
  constructors: [],
1327
2112
  };
1328
2113
  };
1329
- const buildTypeBindingFromStructuralAlias = (declaration, namespace, assemblyName) => {
2114
+ const buildTypeBindingFromStructuralAlias = (declaration, namespace, assemblyName, localTypeNameRemaps = new Map()) => {
1330
2115
  if (declaration.type.kind !== "objectType")
1331
2116
  return undefined;
1332
2117
  const arity = declaration.typeParameters?.length ?? 0;
@@ -1345,17 +2130,21 @@ const buildTypeBindingFromStructuralAlias = (declaration, namespace, assemblyNam
1345
2130
  methodName: member.name,
1346
2131
  parameters: member.parameters,
1347
2132
  returnType: member.returnType,
2133
+ typeParameters: member.typeParameters,
1348
2134
  arity: member.typeParameters?.length ?? 0,
1349
2135
  parameterModifiers: buildParameterModifiers(member.parameters),
1350
2136
  isStatic: false,
1351
2137
  isAbstract: true,
2138
+ localTypeNameRemaps,
1352
2139
  }));
1353
2140
  continue;
1354
2141
  }
1355
2142
  properties.push({
1356
2143
  stableId: `${typeStableId}::property:${member.name}`,
1357
2144
  clrName: member.name,
1358
- normalizedSignature: `${member.name}|:${toSignatureType(member.type, typeParameterScope)}|static=false|accessor=${member.isReadonly ? "get" : "getset"}`,
2145
+ normalizedSignature: `${member.name}|:${toSignatureType(member.type, typeParameterScope, localTypeNameRemaps)}|static=false|accessor=${member.isReadonly ? "get" : "getset"}`,
2146
+ semanticType: rewriteBindingSemanticType(member.type, localTypeNameRemaps),
2147
+ semanticOptional: member.isOptional,
1359
2148
  isStatic: false,
1360
2149
  isAbstract: true,
1361
2150
  isVirtual: false,
@@ -1370,6 +2159,7 @@ const buildTypeBindingFromStructuralAlias = (declaration, namespace, assemblyNam
1370
2159
  return {
1371
2160
  stableId: typeStableId,
1372
2161
  clrName: declaringClrType,
2162
+ alias: toBindingTypeAlias(namespace, internalAliasName, arity),
1373
2163
  assemblyName,
1374
2164
  kind: declaration.isStruct ? "Struct" : "Class",
1375
2165
  accessibility: "Public",
@@ -1398,11 +2188,13 @@ const buildTypeBindingFromContainer = (entry, namespace, assemblyName) => {
1398
2188
  arity: method.declaration.typeParameters?.length ?? 0,
1399
2189
  parameterModifiers: buildParameterModifiers(method.declaration.parameters),
1400
2190
  isStatic: true,
2191
+ localTypeNameRemaps: method.localTypeNameRemaps,
1401
2192
  }));
1402
2193
  const properties = entry.variables.map((variable) => ({
1403
2194
  stableId: `${typeStableId}::property:${variable.localName}`,
1404
2195
  clrName: variable.localName,
1405
- normalizedSignature: `${variable.localName}|:${toSignatureType(variable.declarator?.type, [])}|static=true|accessor=getset`,
2196
+ normalizedSignature: `${variable.localName}|:${toSignatureType(variable.declarator?.type, [], variable.localTypeNameRemaps)}|static=true|accessor=getset`,
2197
+ semanticType: rewriteBindingSemanticType(variable.declarator?.type, variable.localTypeNameRemaps),
1406
2198
  isStatic: true,
1407
2199
  isAbstract: false,
1408
2200
  isVirtual: false,
@@ -1416,6 +2208,7 @@ const buildTypeBindingFromContainer = (entry, namespace, assemblyName) => {
1416
2208
  return {
1417
2209
  stableId: typeStableId,
1418
2210
  clrName: declaringClrType,
2211
+ alias: toBindingTypeAlias(namespace, entry.module.className),
1419
2212
  assemblyName,
1420
2213
  kind: "Class",
1421
2214
  accessibility: "Public",
@@ -1451,37 +2244,105 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
1451
2244
  for (const [namespace, moduleList] of Array.from(modulesByNamespace.entries())) {
1452
2245
  const typeDeclarations = [];
1453
2246
  const moduleContainers = [];
2247
+ const crossNamespaceReexportsGrouped = new Map();
2248
+ const crossNamespaceTypeDeclarations = [];
2249
+ const seenCrossNamespaceTypeDeclarationKeys = new Set();
1454
2250
  const valueExportsMap = new Map();
1455
2251
  const seenTypeDeclarationKeys = new Set();
1456
- const sourceAliasLines = new Set();
1457
- const sourceAliasInternalImports = new Set();
2252
+ const sourceAliasPlans = [];
1458
2253
  const memberOverrides = [];
2254
+ const internalTypeImportByAlias = new Map();
2255
+ const facadeTypeImportByAlias = new Map();
1459
2256
  const wrapperImportByAlias = new Map();
2257
+ const internalHelperTypeDeclarationsByKey = new Map();
2258
+ const internalHelperTypeRemapsByModuleKey = new Map();
2259
+ const getInternalHelperTypeName = (moduleFileKey, localName) => {
2260
+ return `__Local_${sanitizeForBrand(moduleFileKey)}_${sanitizeForBrand(localName)}`;
2261
+ };
2262
+ const registerInternalHelperTypeClosure = (opts) => {
2263
+ if (!opts.sourceIndex)
2264
+ return { ok: true, value: new Map() };
2265
+ const moduleFileKey = normalizeModuleFileKey(opts.declarationModule.filePath);
2266
+ const remaps = internalHelperTypeRemapsByModuleKey.get(moduleFileKey) ?? new Map();
2267
+ if (!internalHelperTypeRemapsByModuleKey.has(moduleFileKey)) {
2268
+ internalHelperTypeRemapsByModuleKey.set(moduleFileKey, remaps);
2269
+ }
2270
+ const visiting = new Set();
2271
+ const visitLocalType = (localName) => {
2272
+ if (opts.sourceIndex?.exportedTypeDeclarationNames.has(localName)) {
2273
+ return { ok: true, value: undefined };
2274
+ }
2275
+ const declaration = resolveModuleLocalDeclaration(opts.declarationModule, localName);
2276
+ if (!declaration)
2277
+ return { ok: true, value: undefined };
2278
+ const kind = classifyLocalTypeDeclarationKind(declaration);
2279
+ if (!kind)
2280
+ return { ok: true, value: undefined };
2281
+ const localTypeDeclaration = declaration;
2282
+ const key = `${moduleFileKey}::${localName}`;
2283
+ if (!remaps.has(localName)) {
2284
+ remaps.set(localName, getInternalHelperTypeName(moduleFileKey, localName));
2285
+ }
2286
+ if (internalHelperTypeDeclarationsByKey.has(key)) {
2287
+ return { ok: true, value: undefined };
2288
+ }
2289
+ if (visiting.has(key))
2290
+ return { ok: true, value: undefined };
2291
+ visiting.add(key);
2292
+ const nestedReferencedNames = new Set();
2293
+ collectReferencedPortableTypeNamesFromDeclaration(localTypeDeclaration, nestedReferencedNames);
2294
+ for (const nestedName of nestedReferencedNames) {
2295
+ const visited = visitLocalType(nestedName);
2296
+ if (!visited.ok)
2297
+ return visited;
2298
+ }
2299
+ visiting.delete(key);
2300
+ internalHelperTypeDeclarationsByKey.set(key, {
2301
+ key,
2302
+ moduleFileKey,
2303
+ declaringNamespace: opts.declarationModule.namespace,
2304
+ emittedName: remaps.get(localName),
2305
+ originalName: localName,
2306
+ kind,
2307
+ declaration: localTypeDeclaration,
2308
+ });
2309
+ return { ok: true, value: undefined };
2310
+ };
2311
+ for (const referencedName of opts.referencedNames) {
2312
+ const visited = visitLocalType(referencedName);
2313
+ if (!visited.ok)
2314
+ return visited;
2315
+ }
2316
+ return { ok: true, value: new Map(remaps) };
2317
+ };
1460
2318
  const registerValueExport = (valueExport) => {
1461
2319
  const existing = valueExportsMap.get(valueExport.exportName);
1462
2320
  if (!existing) {
1463
2321
  valueExportsMap.set(valueExport.exportName, valueExport);
1464
2322
  return { ok: true, value: undefined };
1465
2323
  }
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;
2324
+ const sameBinding = areBindingSemanticsEqual(existing.binding, valueExport.binding);
1472
2325
  const normalizeFunctionFacade = (facade) => {
1473
2326
  const declaration = facade.declaration;
1474
2327
  const typeParametersText = printTypeParameters(declaration.typeParameters);
1475
2328
  const typeParameterNames = declaration.typeParameters?.map((typeParameter) => typeParameter.name) ?? [];
1476
- const parametersText = renderUnknownParameters(declaration.parameters, typeParameterNames);
1477
- const returnTypeText = renderPortableType(declaration.returnType, typeParameterNames);
2329
+ const parametersText = renderUnknownParameters(declaration.parameters, typeParameterNames, facade.localTypeNameRemaps);
2330
+ const returnTypeText = renderPortableType(declaration.returnType, typeParameterNames, facade.localTypeNameRemaps);
1478
2331
  const sourceSignatures = (facade.sourceSignatures ?? [])
1479
- .map((signature) => `${signature.typeParametersText}(${signature.parametersText}):${signature.returnTypeText}`)
2332
+ .map((signature) => `${signature.typeParametersText}(${signature.parameters
2333
+ .map((parameter) => `${parameter.prefixText}${parameter.typeText}`)
2334
+ .join(", ")}):${signature.returnTypeText}`)
1480
2335
  .sort((left, right) => left.localeCompare(right))
1481
2336
  .join("||");
1482
2337
  return `${typeParametersText}(${parametersText}):${returnTypeText}|source=${sourceSignatures}`;
1483
2338
  };
1484
- const normalizeVariableFacade = (declarator) => renderPortableType(declarator?.type);
2339
+ const normalizeVariableFacade = (declarator, localTypeNameRemaps) => {
2340
+ const functionType = resolveFunctionTypeFromValueDeclarator(declarator);
2341
+ if (functionType) {
2342
+ return JSON.stringify(buildSemanticSignatureFromFunctionType(functionType, localTypeNameRemaps));
2343
+ }
2344
+ return renderPortableType(declarator?.type, [], localTypeNameRemaps);
2345
+ };
1485
2346
  const sameFacade = (() => {
1486
2347
  if (existing.facade.kind !== valueExport.facade.kind)
1487
2348
  return false;
@@ -1492,8 +2353,8 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
1492
2353
  }
1493
2354
  if (existing.facade.kind === "variable" &&
1494
2355
  valueExport.facade.kind === "variable") {
1495
- return (normalizeVariableFacade(existing.facade.declarator) ===
1496
- normalizeVariableFacade(valueExport.facade.declarator));
2356
+ return (normalizeVariableFacade(existing.facade.declarator, existing.facade.localTypeNameRemaps) ===
2357
+ normalizeVariableFacade(valueExport.facade.declarator, valueExport.facade.localTypeNameRemaps));
1497
2358
  }
1498
2359
  return false;
1499
2360
  })();
@@ -1526,32 +2387,113 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
1526
2387
  }
1527
2388
  return { ok: true, value: undefined };
1528
2389
  };
2390
+ const registerCrossNamespaceReexport = (opts) => {
2391
+ if (opts.declaringNamespace === namespace)
2392
+ return;
2393
+ const moduleSpecifier = `./${moduleNamespacePath(opts.declaringNamespace)}.js`;
2394
+ const key = `${moduleSpecifier}|${opts.kind}`;
2395
+ const specifier = opts.exportName === opts.localName
2396
+ ? opts.exportName
2397
+ : `${opts.localName} as ${opts.exportName}`;
2398
+ const existing = crossNamespaceReexportsGrouped.get(key) ?? [];
2399
+ existing.push(specifier);
2400
+ crossNamespaceReexportsGrouped.set(key, existing);
2401
+ };
2402
+ const registerCrossNamespaceTypeDeclaration = (symbol) => {
2403
+ if (symbol.declaringNamespace === namespace)
2404
+ return;
2405
+ const key = `${symbol.declaringNamespace}|${symbol.declaringClassName}|${symbol.localName}|${symbol.kind}`;
2406
+ if (seenCrossNamespaceTypeDeclarationKeys.has(key))
2407
+ return;
2408
+ seenCrossNamespaceTypeDeclarationKeys.add(key);
2409
+ crossNamespaceTypeDeclarations.push(symbol);
2410
+ };
2411
+ const registerSourceTypeImportCandidates = (sourceIndex, moduleKey, moduleFilePath) => {
2412
+ for (const [localName, imported] of sourceIndex.typeImportsByLocalName) {
2413
+ if (sourceIndex.wrapperImportsByLocalName.has(localName))
2414
+ continue;
2415
+ const internalImport = resolveSourceTypeImportBinding({
2416
+ context: "internal",
2417
+ currentNamespace: namespace,
2418
+ currentModuleKey: moduleKey,
2419
+ localName,
2420
+ imported,
2421
+ modulesByFileKey,
2422
+ });
2423
+ if (!internalImport.ok)
2424
+ return internalImport;
2425
+ if (internalImport.value) {
2426
+ const registered = registerSourceTypeImportBinding(internalTypeImportByAlias, internalImport.value, namespace, moduleFilePath);
2427
+ if (!registered.ok)
2428
+ return registered;
2429
+ }
2430
+ const facadeImport = resolveSourceTypeImportBinding({
2431
+ context: "facade",
2432
+ currentNamespace: namespace,
2433
+ currentModuleKey: moduleKey,
2434
+ localName,
2435
+ imported,
2436
+ modulesByFileKey,
2437
+ });
2438
+ if (!facadeImport.ok)
2439
+ return facadeImport;
2440
+ if (facadeImport.value) {
2441
+ const registered = registerSourceTypeImportBinding(facadeTypeImportByAlias, facadeImport.value, namespace, moduleFilePath);
2442
+ if (!registered.ok)
2443
+ return registered;
2444
+ }
2445
+ }
2446
+ return { ok: true, value: undefined };
2447
+ };
2448
+ const registerFacadeLocalTypeReferenceImports = (opts) => {
2449
+ const typeParameterNames = new Set((opts.typeParameters ?? []).map((typeParameter) => typeParameter.name));
2450
+ const referencedNames = new Set();
2451
+ for (const parameterType of opts.parameterTypes) {
2452
+ collectReferencedPortableTypeNames(parameterType, typeParameterNames, referencedNames);
2453
+ }
2454
+ collectReferencedPortableTypeNames(opts.returnType, typeParameterNames, referencedNames);
2455
+ const helperTypeRemaps = registerInternalHelperTypeClosure({
2456
+ declarationModule: opts.declarationModule,
2457
+ sourceIndex: opts.sourceIndex,
2458
+ referencedNames,
2459
+ });
2460
+ if (!helperTypeRemaps.ok)
2461
+ return helperTypeRemaps;
2462
+ if (!opts.sourceIndex)
2463
+ return helperTypeRemaps;
2464
+ if (opts.declarationNamespace === namespace) {
2465
+ return helperTypeRemaps;
2466
+ }
2467
+ const moduleSpecifier = `./${moduleNamespacePath(opts.declarationNamespace)}.js`;
2468
+ for (const referencedName of referencedNames) {
2469
+ if (!opts.sourceIndex.exportedTypeDeclarationNames.has(referencedName)) {
2470
+ continue;
2471
+ }
2472
+ const registered = registerSourceTypeImportBinding(facadeTypeImportByAlias, {
2473
+ importedName: referencedName,
2474
+ localName: referencedName,
2475
+ source: moduleSpecifier,
2476
+ }, namespace, opts.declarationFilePath);
2477
+ if (!registered.ok)
2478
+ return registered;
2479
+ }
2480
+ return helperTypeRemaps;
2481
+ };
1529
2482
  for (const module of moduleList.sort((left, right) => left.filePath.localeCompare(right.filePath))) {
1530
2483
  const moduleKey = normalizeModuleFileKey(module.filePath);
1531
2484
  const sourceIndex = sourceIndexByFileKey.get(moduleKey);
1532
2485
  if (sourceIndex) {
2486
+ const registered = registerSourceTypeImportCandidates(sourceIndex, moduleKey, module.filePath);
2487
+ if (!registered.ok)
2488
+ return registered;
1533
2489
  const exportedAliasDecls = module.body.filter((stmt) => stmt.kind === "typeAliasDeclaration" && stmt.isExported);
1534
2490
  for (const alias of exportedAliasDecls) {
1535
2491
  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};`);
2492
+ sourceAliasPlans.push({
2493
+ declaration: alias,
2494
+ sourceAlias,
2495
+ typeImportsByLocalName: sourceIndex.typeImportsByLocalName,
2496
+ });
1555
2497
  }
1556
2498
  const exportedClasses = module.body.filter((stmt) => stmt.kind === "classDeclaration" && stmt.isExported);
1557
2499
  const exportedInterfaces = module.body.filter((stmt) => stmt.kind === "interfaceDeclaration" && stmt.isExported);
@@ -1692,6 +2634,16 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
1692
2634
  const exportKind = classifyDeclarationKind(declaration, declarationModule.filePath, exportItem.name);
1693
2635
  if (!exportKind.ok)
1694
2636
  return exportKind;
2637
+ if (declarationModule.namespace !== namespace) {
2638
+ registerCrossNamespaceReexport({
2639
+ declaringNamespace: declarationModule.namespace,
2640
+ exportName: exportItem.name,
2641
+ localName: resolved.value.clrName,
2642
+ kind: exportKind.value === "interface" || exportKind.value === "typeAlias"
2643
+ ? "type"
2644
+ : "value",
2645
+ });
2646
+ }
1695
2647
  if (exportKind.value === "function") {
1696
2648
  const functionDeclaration = declaration.kind === "functionDeclaration"
1697
2649
  ? declaration
@@ -1702,6 +2654,24 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
1702
2654
  error: `Invalid function export '${exportItem.name}' in ${declarationModule.filePath}: expected function declaration.`,
1703
2655
  };
1704
2656
  }
2657
+ const declarationModuleKey = normalizeModuleFileKey(declarationModule.filePath);
2658
+ const declarationSourceIndex = sourceIndexByFileKey.get(declarationModuleKey);
2659
+ if (declarationSourceIndex) {
2660
+ const registered = registerSourceTypeImportCandidates(declarationSourceIndex, declarationModuleKey, declarationModule.filePath);
2661
+ if (!registered.ok)
2662
+ return registered;
2663
+ }
2664
+ const registeredLocalTypeRefs = registerFacadeLocalTypeReferenceImports({
2665
+ declarationModule,
2666
+ declarationNamespace: declarationModule.namespace,
2667
+ declarationFilePath: declarationModule.filePath,
2668
+ sourceIndex: declarationSourceIndex,
2669
+ typeParameters: functionDeclaration.typeParameters,
2670
+ parameterTypes: functionDeclaration.parameters.map((parameter) => parameter.type),
2671
+ returnType: functionDeclaration.returnType,
2672
+ });
2673
+ if (!registeredLocalTypeRefs.ok)
2674
+ return registeredLocalTypeRefs;
1705
2675
  const registered = registerValueExport({
1706
2676
  exportName: exportItem.name,
1707
2677
  binding: {
@@ -1713,6 +2683,7 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
1713
2683
  facade: {
1714
2684
  kind: "function",
1715
2685
  declaration: functionDeclaration,
2686
+ localTypeNameRemaps: registeredLocalTypeRefs.value,
1716
2687
  sourceSignatures: sourceIndexByFileKey
1717
2688
  .get(normalizeModuleFileKey(declarationModule.filePath))
1718
2689
  ?.exportedFunctionSignaturesByName.get(resolved.value.clrName) ?? [],
@@ -1732,23 +2703,63 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
1732
2703
  error: `Invalid variable export '${exportItem.name}' in ${declarationModule.filePath}: expected variable declaration.`,
1733
2704
  };
1734
2705
  }
2706
+ const declarationModuleKey = normalizeModuleFileKey(declarationModule.filePath);
2707
+ const declarationSourceIndex = sourceIndexByFileKey.get(declarationModuleKey);
2708
+ if (declarationSourceIndex) {
2709
+ const registered = registerSourceTypeImportCandidates(declarationSourceIndex, declarationModuleKey, declarationModule.filePath);
2710
+ if (!registered.ok)
2711
+ return registered;
2712
+ }
1735
2713
  const declarator = declarationStatement.declarations.find((candidate) => candidate.name.kind === "identifierPattern" &&
1736
2714
  candidate.name.name === resolved.value.clrName);
2715
+ const exportedFunctionType = resolveFunctionTypeFromValueDeclarator(declarator && declarator.name.kind === "identifierPattern"
2716
+ ? {
2717
+ kind: declarator.kind,
2718
+ name: declarator.name,
2719
+ type: declarator.type,
2720
+ initializer: declarator.initializer,
2721
+ }
2722
+ : undefined);
2723
+ const registeredLocalTypeRefs = registerFacadeLocalTypeReferenceImports({
2724
+ declarationModule,
2725
+ declarationNamespace: declarationModule.namespace,
2726
+ declarationFilePath: declarationModule.filePath,
2727
+ sourceIndex: declarationSourceIndex,
2728
+ typeParameters: undefined,
2729
+ parameterTypes: exportedFunctionType
2730
+ ? [exportedFunctionType]
2731
+ : declarator?.type
2732
+ ? [declarator.type]
2733
+ : [],
2734
+ returnType: undefined,
2735
+ });
2736
+ if (!registeredLocalTypeRefs.ok)
2737
+ return registeredLocalTypeRefs;
1737
2738
  const registered = registerValueExport({
1738
2739
  exportName: exportItem.name,
1739
2740
  binding: {
1740
- kind: "field",
2741
+ kind: exportedFunctionType ? "functionType" : "field",
1741
2742
  clrName: resolved.value.clrName,
1742
2743
  declaringClrType: toClrTypeName(declarationModule.namespace, declarationModule.className),
1743
2744
  declaringAssemblyName: assemblyName,
2745
+ semanticType: exportedFunctionType
2746
+ ? undefined
2747
+ : rewriteBindingSemanticType(declarator?.type, registeredLocalTypeRefs.value),
2748
+ semanticSignature: exportedFunctionType
2749
+ ? buildSemanticSignatureFromFunctionType(exportedFunctionType, registeredLocalTypeRefs.value)
2750
+ : undefined,
1744
2751
  },
1745
2752
  facade: {
1746
2753
  kind: "variable",
2754
+ localTypeNameRemaps: registeredLocalTypeRefs.value,
2755
+ sourceType: declarationSourceIndex?.exportedValueTypesByName.get(resolved.value.clrName),
2756
+ sourceSignatures: declarationSourceIndex?.exportedFunctionSignaturesByName.get(resolved.value.clrName) ?? [],
1747
2757
  declarator: declarator && declarator.name.kind === "identifierPattern"
1748
2758
  ? {
1749
2759
  kind: declarator.kind,
1750
2760
  name: declarator.name,
1751
2761
  type: declarator.type,
2762
+ initializer: declarator.initializer,
1752
2763
  }
1753
2764
  : undefined,
1754
2765
  },
@@ -1761,6 +2772,25 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
1761
2772
  exportKind.value === "interface" ||
1762
2773
  exportKind.value === "enum" ||
1763
2774
  exportKind.value === "typeAlias") {
2775
+ if (declarationModule.namespace !== namespace) {
2776
+ registerCrossNamespaceTypeDeclaration({
2777
+ exportName: exportItem.name,
2778
+ localName: resolved.value.clrName,
2779
+ kind: exportKind.value,
2780
+ declaration,
2781
+ declaringNamespace: declarationModule.namespace,
2782
+ declaringClassName: declarationModule.className,
2783
+ declaringFilePath: declarationModule.filePath,
2784
+ });
2785
+ continue;
2786
+ }
2787
+ const declarationModuleKey = normalizeModuleFileKey(declarationModule.filePath);
2788
+ const declarationSourceIndex = sourceIndexByFileKey.get(declarationModuleKey);
2789
+ if (declarationSourceIndex) {
2790
+ const registered = registerSourceTypeImportCandidates(declarationSourceIndex, declarationModuleKey, declarationModule.filePath);
2791
+ if (!registered.ok)
2792
+ return registered;
2793
+ }
1764
2794
  if (exportKind.value === "typeAlias" &&
1765
2795
  declaration.kind === "typeAliasDeclaration" &&
1766
2796
  declaration.type.kind !== "objectType") {
@@ -1812,6 +2842,18 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
1812
2842
  symbol.kind === "interface" ||
1813
2843
  symbol.kind === "enum" ||
1814
2844
  symbol.kind === "typeAlias") {
2845
+ if (symbol.declaringNamespace !== namespace) {
2846
+ registerCrossNamespaceReexport({
2847
+ declaringNamespace: symbol.declaringNamespace,
2848
+ exportName: symbol.exportName,
2849
+ localName: symbol.localName,
2850
+ kind: symbol.kind === "interface" || symbol.kind === "typeAlias"
2851
+ ? "type"
2852
+ : "value",
2853
+ });
2854
+ registerCrossNamespaceTypeDeclaration(symbol);
2855
+ continue;
2856
+ }
1815
2857
  if (symbol.kind === "typeAlias" &&
1816
2858
  symbol.declaration.kind === "typeAliasDeclaration" &&
1817
2859
  symbol.declaration.type.kind !== "objectType") {
@@ -1824,11 +2866,45 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
1824
2866
  }
1825
2867
  }
1826
2868
  if (symbol.kind === "function") {
2869
+ if (symbol.declaringNamespace !== namespace) {
2870
+ registerCrossNamespaceReexport({
2871
+ declaringNamespace: symbol.declaringNamespace,
2872
+ exportName: symbol.exportName,
2873
+ localName: symbol.localName,
2874
+ kind: "value",
2875
+ });
2876
+ }
1827
2877
  const functionDeclaration = symbol.declaration.kind === "functionDeclaration"
1828
2878
  ? symbol.declaration
1829
2879
  : undefined;
1830
2880
  if (!functionDeclaration)
1831
2881
  continue;
2882
+ const symbolModuleKey = normalizeModuleFileKey(symbol.declaringFilePath);
2883
+ const symbolSourceIndex = sourceIndexByFileKey.get(symbolModuleKey);
2884
+ const symbolDeclarationModule = modulesByFileKey.get(symbolModuleKey);
2885
+ if (!symbolDeclarationModule) {
2886
+ return {
2887
+ ok: false,
2888
+ error: `Unable to resolve declaring module for '${symbol.exportName}' while generating ${symbol.declaringFilePath}.\n` +
2889
+ "First-party bindings generation requires a stable source module for each exported value.",
2890
+ };
2891
+ }
2892
+ if (symbolSourceIndex) {
2893
+ const registered = registerSourceTypeImportCandidates(symbolSourceIndex, symbolModuleKey, symbol.declaringFilePath);
2894
+ if (!registered.ok)
2895
+ return registered;
2896
+ }
2897
+ const registeredLocalTypeRefs = registerFacadeLocalTypeReferenceImports({
2898
+ declarationModule: symbolDeclarationModule,
2899
+ declarationNamespace: symbol.declaringNamespace,
2900
+ declarationFilePath: symbol.declaringFilePath,
2901
+ sourceIndex: symbolSourceIndex,
2902
+ typeParameters: functionDeclaration.typeParameters,
2903
+ parameterTypes: functionDeclaration.parameters.map((parameter) => parameter.type),
2904
+ returnType: functionDeclaration.returnType,
2905
+ });
2906
+ if (!registeredLocalTypeRefs.ok)
2907
+ return registeredLocalTypeRefs;
1832
2908
  const isLocalContainerMember = symbol.declaringNamespace === module.namespace &&
1833
2909
  symbol.declaringClassName === module.className;
1834
2910
  if (isLocalContainerMember) {
@@ -1836,6 +2912,11 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
1836
2912
  exportName: symbol.exportName,
1837
2913
  localName: symbol.localName,
1838
2914
  declaration: functionDeclaration,
2915
+ localTypeNameRemaps: registeredLocalTypeRefs.value,
2916
+ sourceSignatures: sourceIndexByFileKey
2917
+ .get(normalizeModuleFileKey(symbol.declaringFilePath))
2918
+ ?.exportedFunctionSignaturesByName.get(symbol.localName) ??
2919
+ [],
1839
2920
  });
1840
2921
  }
1841
2922
  const registered = registerValueExport({
@@ -1849,6 +2930,7 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
1849
2930
  facade: {
1850
2931
  kind: "function",
1851
2932
  declaration: functionDeclaration,
2933
+ localTypeNameRemaps: registeredLocalTypeRefs.value,
1852
2934
  sourceSignatures: sourceIndexByFileKey
1853
2935
  .get(normalizeModuleFileKey(symbol.declaringFilePath))
1854
2936
  ?.exportedFunctionSignaturesByName.get(symbol.localName) ??
@@ -1860,13 +2942,60 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
1860
2942
  continue;
1861
2943
  }
1862
2944
  if (symbol.kind === "variable") {
2945
+ if (symbol.declaringNamespace !== namespace) {
2946
+ registerCrossNamespaceReexport({
2947
+ declaringNamespace: symbol.declaringNamespace,
2948
+ exportName: symbol.exportName,
2949
+ localName: symbol.localName,
2950
+ kind: "value",
2951
+ });
2952
+ }
1863
2953
  const declaration = symbol.declaration.kind === "variableDeclaration"
1864
2954
  ? symbol.declaration
1865
2955
  : undefined;
1866
2956
  if (!declaration)
1867
2957
  continue;
2958
+ const symbolModuleKey = normalizeModuleFileKey(symbol.declaringFilePath);
2959
+ const symbolSourceIndex = sourceIndexByFileKey.get(symbolModuleKey);
2960
+ const symbolDeclarationModule = modulesByFileKey.get(symbolModuleKey);
2961
+ if (!symbolDeclarationModule) {
2962
+ return {
2963
+ ok: false,
2964
+ error: `Unable to resolve declaring module for '${symbol.exportName}' while generating ${symbol.declaringFilePath}.\n` +
2965
+ "First-party bindings generation requires a stable source module for each exported value.",
2966
+ };
2967
+ }
2968
+ if (symbolSourceIndex) {
2969
+ const registered = registerSourceTypeImportCandidates(symbolSourceIndex, symbolModuleKey, symbol.declaringFilePath);
2970
+ if (!registered.ok)
2971
+ return registered;
2972
+ }
1868
2973
  const declarator = declaration.declarations.find((candidate) => candidate.name.kind === "identifierPattern" &&
1869
2974
  candidate.name.name === symbol.localName);
2975
+ const exportDeclarator = declarator && declarator.name.kind === "identifierPattern"
2976
+ ? {
2977
+ kind: declarator.kind,
2978
+ name: declarator.name,
2979
+ type: declarator.type,
2980
+ initializer: declarator.initializer,
2981
+ }
2982
+ : undefined;
2983
+ const exportedFunctionType = resolveFunctionTypeFromValueDeclarator(exportDeclarator);
2984
+ const registeredLocalTypeRefs = registerFacadeLocalTypeReferenceImports({
2985
+ declarationModule: symbolDeclarationModule,
2986
+ declarationNamespace: symbol.declaringNamespace,
2987
+ declarationFilePath: symbol.declaringFilePath,
2988
+ sourceIndex: symbolSourceIndex,
2989
+ typeParameters: undefined,
2990
+ parameterTypes: exportedFunctionType
2991
+ ? [exportedFunctionType]
2992
+ : declarator?.type
2993
+ ? [declarator.type]
2994
+ : [],
2995
+ returnType: undefined,
2996
+ });
2997
+ if (!registeredLocalTypeRefs.ok)
2998
+ return registeredLocalTypeRefs;
1870
2999
  const isLocalContainerMember = symbol.declaringNamespace === module.namespace &&
1871
3000
  symbol.declaringClassName === module.className;
1872
3001
  if (isLocalContainerMember) {
@@ -1874,32 +3003,37 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
1874
3003
  exportName: symbol.exportName,
1875
3004
  localName: symbol.localName,
1876
3005
  declaration,
1877
- declarator: declarator && declarator.name.kind === "identifierPattern"
1878
- ? {
1879
- kind: declarator.kind,
1880
- name: declarator.name,
1881
- type: declarator.type,
1882
- }
1883
- : undefined,
3006
+ declarator: exportDeclarator,
3007
+ localTypeNameRemaps: registeredLocalTypeRefs.value,
3008
+ sourceType: sourceIndexByFileKey
3009
+ .get(normalizeModuleFileKey(symbol.declaringFilePath))
3010
+ ?.exportedValueTypesByName.get(symbol.localName),
3011
+ sourceSignatures: sourceIndexByFileKey
3012
+ .get(normalizeModuleFileKey(symbol.declaringFilePath))
3013
+ ?.exportedFunctionSignaturesByName.get(symbol.localName) ??
3014
+ [],
1884
3015
  });
1885
3016
  }
1886
3017
  const registered = registerValueExport({
1887
3018
  exportName: symbol.exportName,
1888
3019
  binding: {
1889
- kind: "field",
3020
+ kind: exportedFunctionType ? "functionType" : "field",
1890
3021
  clrName: symbol.localName,
1891
3022
  declaringClrType: toClrTypeName(symbol.declaringNamespace, symbol.declaringClassName),
1892
3023
  declaringAssemblyName: assemblyName,
3024
+ semanticType: exportedFunctionType
3025
+ ? undefined
3026
+ : rewriteBindingSemanticType(exportDeclarator?.type, registeredLocalTypeRefs.value),
3027
+ semanticSignature: exportedFunctionType
3028
+ ? buildSemanticSignatureFromFunctionType(exportedFunctionType, registeredLocalTypeRefs.value)
3029
+ : undefined,
1893
3030
  },
1894
3031
  facade: {
1895
3032
  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,
3033
+ localTypeNameRemaps: registeredLocalTypeRefs.value,
3034
+ sourceType: symbolSourceIndex?.exportedValueTypesByName.get(symbol.localName),
3035
+ sourceSignatures: symbolSourceIndex?.exportedFunctionSignaturesByName.get(symbol.localName) ?? [],
3036
+ declarator: exportDeclarator,
1903
3037
  },
1904
3038
  });
1905
3039
  if (!registered.ok)
@@ -1914,18 +3048,114 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
1914
3048
  });
1915
3049
  }
1916
3050
  }
3051
+ const anonymousHelperClassNamesByShape = new Map();
3052
+ const registerAnonymousHelperClass = (emittedName, declaration) => {
3053
+ if (!emittedName.startsWith("__Anon_") &&
3054
+ !declaration.name.startsWith("__Anon_")) {
3055
+ return;
3056
+ }
3057
+ const members = [];
3058
+ for (const member of declaration.members) {
3059
+ if (member.kind === "propertyDeclaration") {
3060
+ if (isPortableMarkerMemberName(member.name))
3061
+ continue;
3062
+ members.push({
3063
+ kind: "propertySignature",
3064
+ name: member.name,
3065
+ type: member.type ?? { kind: "unknownType" },
3066
+ isOptional: false,
3067
+ isReadonly: member.isReadonly,
3068
+ });
3069
+ continue;
3070
+ }
3071
+ if (member.kind === "methodDeclaration") {
3072
+ if (isPortableMarkerMemberName(member.name))
3073
+ continue;
3074
+ members.push({
3075
+ kind: "methodSignature",
3076
+ name: member.name,
3077
+ parameters: member.parameters,
3078
+ returnType: member.returnType,
3079
+ typeParameters: member.typeParameters,
3080
+ });
3081
+ }
3082
+ }
3083
+ const shape = renderPortableType({ kind: "objectType", members }, declaration.typeParameters?.map((typeParameter) => typeParameter.name) ??
3084
+ [], new Map(), new Map());
3085
+ anonymousHelperClassNamesByShape.set(shape, emittedName);
3086
+ };
3087
+ for (const symbol of typeDeclarations) {
3088
+ if (symbol.kind === "class" &&
3089
+ symbol.declaration.kind === "classDeclaration") {
3090
+ registerAnonymousHelperClass(symbol.localName, symbol.declaration);
3091
+ }
3092
+ }
3093
+ for (const helper of internalHelperTypeDeclarationsByKey.values()) {
3094
+ if (helper.kind === "class") {
3095
+ registerAnonymousHelperClass(helper.emittedName, helper.declaration);
3096
+ }
3097
+ }
3098
+ for (const [moduleKey, sourceIndex] of sourceIndexByFileKey) {
3099
+ const sourceModule = modulesByFileKey.get(moduleKey);
3100
+ if (!sourceModule)
3101
+ continue;
3102
+ for (const [shape, anonymousType] of sourceIndex.anonymousTypeLiteralsByShape) {
3103
+ const className = anonymousHelperClassNamesByShape.get(shape);
3104
+ if (!className)
3105
+ continue;
3106
+ for (const [memberName, sourceMember] of anonymousType.members) {
3107
+ const wrappersResult = collectExtensionWrapperImportsFromSourceType({
3108
+ startModuleKey: moduleKey,
3109
+ typeNode: sourceMember.typeNode,
3110
+ sourceIndexByFileKey,
3111
+ modulesByFileKey,
3112
+ });
3113
+ if (!wrappersResult.ok)
3114
+ return wrappersResult;
3115
+ const wrappers = wrappersResult.value;
3116
+ const canUseSourceTypeText = !typeNodeUsesImportedTypeNames(sourceMember.typeNode, sourceIndex.typeImportsByLocalName);
3117
+ if (!canUseSourceTypeText &&
3118
+ wrappers.length === 0 &&
3119
+ !sourceMember.isOptional) {
3120
+ continue;
3121
+ }
3122
+ const wrapperRegistered = registerWrapperImports(wrappers, sourceModule.filePath);
3123
+ if (!wrapperRegistered.ok)
3124
+ return wrapperRegistered;
3125
+ memberOverrides.push({
3126
+ className,
3127
+ memberName,
3128
+ sourceTypeText: canUseSourceTypeText
3129
+ ? sourceMember.typeText
3130
+ : undefined,
3131
+ replaceWithSourceType: canUseSourceTypeText,
3132
+ isOptional: sourceMember.isOptional,
3133
+ emitOptionalPropertySyntax: true,
3134
+ wrappers,
3135
+ });
3136
+ }
3137
+ }
3138
+ }
1917
3139
  plans.push({
1918
3140
  namespace,
1919
3141
  typeDeclarations: typeDeclarations.sort((left, right) => left.exportName.localeCompare(right.exportName)),
3142
+ internalHelperTypeDeclarations: Array.from(internalHelperTypeDeclarationsByKey.values()).sort((left, right) => left.key.localeCompare(right.key)),
1920
3143
  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)),
3144
+ crossNamespaceReexports: finalizeCrossNamespaceReexports(crossNamespaceReexportsGrouped),
3145
+ crossNamespaceTypeDeclarations: crossNamespaceTypeDeclarations.sort((left, right) => {
3146
+ const leftKey = `${left.exportName}|${left.declaringNamespace}|${left.localName}|${left.kind}`;
3147
+ const rightKey = `${right.exportName}|${right.declaringNamespace}|${right.localName}|${right.kind}`;
3148
+ return leftKey.localeCompare(rightKey);
3149
+ }),
3150
+ sourceAliases: sourceAliasPlans.sort((left, right) => left.declaration.name.localeCompare(right.declaration.name)),
1923
3151
  memberOverrides: memberOverrides.sort((left, right) => {
1924
3152
  const classCmp = left.className.localeCompare(right.className);
1925
3153
  if (classCmp !== 0)
1926
3154
  return classCmp;
1927
3155
  return left.memberName.localeCompare(right.memberName);
1928
3156
  }),
3157
+ internalTypeImports: Array.from(internalTypeImportByAlias.values()).sort((left, right) => left.localName.localeCompare(right.localName)),
3158
+ facadeTypeImports: Array.from(facadeTypeImportByAlias.values()).sort((left, right) => left.localName.localeCompare(right.localName)),
1929
3159
  wrapperImports: Array.from(wrapperImportByAlias.values()).sort((left, right) => left.aliasName.localeCompare(right.aliasName)),
1930
3160
  valueExports: Array.from(valueExportsMap.values()).sort((left, right) => left.exportName.localeCompare(right.exportName)),
1931
3161
  });
@@ -1935,55 +3165,7 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
1935
3165
  value: plans.sort((left, right) => left.namespace.localeCompare(right.namespace)),
1936
3166
  };
1937
3167
  };
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) => {
3168
+ const writeNamespaceArtifacts = (config, outDir, plan) => {
1987
3169
  const namespacePath = moduleNamespacePath(plan.namespace);
1988
3170
  const namespaceDir = join(outDir, namespacePath);
1989
3171
  const internalDir = join(namespaceDir, "internal");
@@ -1992,7 +3174,8 @@ const writeNamespaceArtifacts = (config, outDir, plan, entrypointReexports) => {
1992
3174
  const facadeDtsPath = join(outDir, `${namespacePath}.d.ts`);
1993
3175
  const facadeJsPath = join(outDir, `${namespacePath}.js`);
1994
3176
  const bindingsPath = join(namespaceDir, "bindings.json");
1995
- const internalLines = [];
3177
+ const anonymousStructuralAliases = buildAnonymousStructuralAliasMap(plan);
3178
+ const internalBodyLines = [];
1996
3179
  const memberOverridesByClass = new Map();
1997
3180
  for (const override of plan.memberOverrides) {
1998
3181
  const byMember = memberOverridesByClass.get(override.className) ??
@@ -2000,47 +3183,29 @@ const writeNamespaceArtifacts = (config, outDir, plan, entrypointReexports) => {
2000
3183
  byMember.set(override.memberName, override);
2001
3184
  memberOverridesByClass.set(override.className, byMember);
2002
3185
  }
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
3186
  const typeBindings = [];
2022
3187
  for (const symbol of plan.typeDeclarations) {
2023
3188
  if (symbol.kind === "class" &&
2024
3189
  symbol.declaration.kind === "classDeclaration") {
2025
- internalLines.push(...renderClassInternal(symbol.declaration, plan.namespace, memberOverridesByClass.get(symbol.declaration.name) ?? new Map()));
3190
+ internalBodyLines.push(...renderClassInternal(symbol.declaration, plan.namespace, memberOverridesByClass.get(symbol.declaration.name) ?? new Map()));
2026
3191
  typeBindings.push(buildTypeBindingFromClass(symbol.declaration, plan.namespace, config.outputName));
2027
3192
  continue;
2028
3193
  }
2029
3194
  if (symbol.kind === "interface" &&
2030
3195
  symbol.declaration.kind === "interfaceDeclaration") {
2031
- internalLines.push(...renderInterfaceInternal(symbol.declaration, plan.namespace, memberOverridesByClass.get(symbol.declaration.name) ?? new Map()));
3196
+ internalBodyLines.push(...renderInterfaceInternal(symbol.declaration, plan.namespace, memberOverridesByClass.get(symbol.declaration.name) ?? new Map()));
2032
3197
  typeBindings.push(buildTypeBindingFromInterface(symbol.declaration, plan.namespace, config.outputName));
2033
3198
  continue;
2034
3199
  }
2035
3200
  if (symbol.kind === "enum" &&
2036
3201
  symbol.declaration.kind === "enumDeclaration") {
2037
- internalLines.push(...renderEnumInternal(symbol.declaration));
3202
+ internalBodyLines.push(...renderEnumInternal(symbol.declaration));
2038
3203
  typeBindings.push(buildTypeBindingFromEnum(symbol.declaration, plan.namespace, config.outputName));
2039
3204
  continue;
2040
3205
  }
2041
3206
  if (symbol.kind === "typeAlias" &&
2042
3207
  symbol.declaration.kind === "typeAliasDeclaration") {
2043
- internalLines.push(...renderStructuralAliasInternal(symbol.declaration, plan.namespace, memberOverridesByClass.get(`${symbol.declaration.name}__Alias${(symbol.declaration.typeParameters?.length ?? 0) > 0
3208
+ internalBodyLines.push(...renderStructuralAliasInternal(symbol.declaration, plan.namespace, memberOverridesByClass.get(`${symbol.declaration.name}__Alias${(symbol.declaration.typeParameters?.length ?? 0) > 0
2044
3209
  ? `_${symbol.declaration.typeParameters?.length ?? 0}`
2045
3210
  : ""}`) ?? new Map()));
2046
3211
  const binding = buildTypeBindingFromStructuralAlias(symbol.declaration, plan.namespace, config.outputName);
@@ -2048,10 +3213,137 @@ const writeNamespaceArtifacts = (config, outDir, plan, entrypointReexports) => {
2048
3213
  typeBindings.push(binding);
2049
3214
  }
2050
3215
  }
3216
+ const helperRemapsByModuleKey = new Map();
3217
+ for (const helper of plan.internalHelperTypeDeclarations) {
3218
+ const current = new Map(helperRemapsByModuleKey.get(helper.moduleFileKey) ?? []);
3219
+ current.set(helper.originalName, helper.emittedName);
3220
+ helperRemapsByModuleKey.set(helper.moduleFileKey, current);
3221
+ }
3222
+ for (const helper of plan.internalHelperTypeDeclarations) {
3223
+ const localTypeNameRemaps = helperRemapsByModuleKey.get(helper.moduleFileKey) ?? new Map();
3224
+ switch (helper.kind) {
3225
+ case "class":
3226
+ internalBodyLines.push(...renderClassInternal(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(buildTypeBindingFromClass(helper.declaration, helper.declaringNamespace, config.outputName, localTypeNameRemaps));
3230
+ continue;
3231
+ case "interface":
3232
+ internalBodyLines.push(...renderInterfaceInternal(helper.declaration, helper.declaringNamespace, memberOverridesByClass.get(helper.emittedName) ??
3233
+ memberOverridesByClass.get(helper.declaration.name) ??
3234
+ new Map(), helper.emittedName, localTypeNameRemaps, helper.declaration.name, helper.declaration.name));
3235
+ typeBindings.push(buildTypeBindingFromInterface(helper.declaration, helper.declaringNamespace, config.outputName, localTypeNameRemaps));
3236
+ continue;
3237
+ case "enum":
3238
+ internalBodyLines.push(...renderEnumInternal(helper.declaration, helper.emittedName));
3239
+ typeBindings.push(buildTypeBindingFromEnum(helper.declaration, helper.declaringNamespace, config.outputName));
3240
+ continue;
3241
+ case "typeAlias": {
3242
+ const structuralLines = renderStructuralAliasInternal(helper.declaration, helper.declaringNamespace, memberOverridesByClass.get(helper.emittedName) ??
3243
+ memberOverridesByClass.get(`${helper.declaration.name}__Alias${(helper.declaration.typeParameters
3244
+ ?.length ?? 0) > 0
3245
+ ? `_${helper.declaration
3246
+ .typeParameters?.length ?? 0}`
3247
+ : ""}`) ??
3248
+ new Map(), helper.emittedName, localTypeNameRemaps, `${helper.declaration.name}__Alias${(helper.declaration.typeParameters
3249
+ ?.length ?? 0) > 0
3250
+ ? `_${helper.declaration.typeParameters
3251
+ ?.length ?? 0}`
3252
+ : ""}`, `${helper.declaration.name}__Alias${(helper.declaration.typeParameters
3253
+ ?.length ?? 0) > 0
3254
+ ? `_${helper.declaration.typeParameters
3255
+ ?.length ?? 0}`
3256
+ : ""}`);
3257
+ if (structuralLines.length > 0) {
3258
+ internalBodyLines.push(...structuralLines);
3259
+ const binding = buildTypeBindingFromStructuralAlias(helper.declaration, helper.declaringNamespace, config.outputName, localTypeNameRemaps);
3260
+ if (binding)
3261
+ typeBindings.push(binding);
3262
+ continue;
3263
+ }
3264
+ internalBodyLines.push(...renderTypeAliasInternal(helper.declaration, helper.emittedName, localTypeNameRemaps, anonymousStructuralAliases));
3265
+ continue;
3266
+ }
3267
+ }
3268
+ }
3269
+ const renderedSourceAliases = plan.sourceAliases.map((sourceAliasPlan) => renderSourceAliasPlan(sourceAliasPlan, anonymousStructuralAliases));
3270
+ const sourceAliasLines = renderedSourceAliases.map((entry) => entry.line);
3271
+ const sourceAliasInternalImports = renderedSourceAliases
3272
+ .map((entry) => entry.internalImport)
3273
+ .filter((entry) => entry !== undefined)
3274
+ .sort((left, right) => left.localeCompare(right));
2051
3275
  for (const container of plan.moduleContainers) {
2052
- internalLines.push(...renderContainerInternal(container));
3276
+ internalBodyLines.push(...renderContainerInternal(container, anonymousStructuralAliases));
2053
3277
  typeBindings.push(buildTypeBindingFromContainer(container, plan.namespace, config.outputName));
2054
3278
  }
3279
+ for (const symbol of plan.crossNamespaceTypeDeclarations) {
3280
+ if (symbol.kind === "class" &&
3281
+ symbol.declaration.kind === "classDeclaration") {
3282
+ typeBindings.push(buildTypeBindingFromClass(symbol.declaration, symbol.declaringNamespace, config.outputName));
3283
+ continue;
3284
+ }
3285
+ if (symbol.kind === "interface" &&
3286
+ symbol.declaration.kind === "interfaceDeclaration") {
3287
+ typeBindings.push(buildTypeBindingFromInterface(symbol.declaration, symbol.declaringNamespace, config.outputName));
3288
+ continue;
3289
+ }
3290
+ if (symbol.kind === "enum" &&
3291
+ symbol.declaration.kind === "enumDeclaration") {
3292
+ typeBindings.push(buildTypeBindingFromEnum(symbol.declaration, symbol.declaringNamespace, config.outputName));
3293
+ continue;
3294
+ }
3295
+ if (symbol.kind === "typeAlias" &&
3296
+ symbol.declaration.kind === "typeAliasDeclaration") {
3297
+ const binding = buildTypeBindingFromStructuralAlias(symbol.declaration, symbol.declaringNamespace, config.outputName);
3298
+ if (binding)
3299
+ typeBindings.push(binding);
3300
+ }
3301
+ }
3302
+ const internalSourceAliasLines = sourceAliasLines.length > 0
3303
+ ? [
3304
+ "",
3305
+ "// Tsonic source type aliases (generated)",
3306
+ ...sourceAliasLines,
3307
+ "// End Tsonic source type aliases",
3308
+ ]
3309
+ : [];
3310
+ const requiredInternalTypeImports = selectSourceTypeImportsForRenderedText([...internalSourceAliasLines, ...internalBodyLines].join("\n"), plan.internalTypeImports);
3311
+ const internalLines = [];
3312
+ internalLines.push("// Generated by Tsonic - Source bindings");
3313
+ internalLines.push(`// Namespace: ${plan.namespace}`);
3314
+ internalLines.push(`// Assembly: ${config.outputName}`);
3315
+ internalLines.push("");
3316
+ internalLines.push(primitiveImportLine);
3317
+ if (requiredInternalTypeImports.length > 0) {
3318
+ internalLines.push("");
3319
+ internalLines.push("// Tsonic source type imports (generated)");
3320
+ for (const typeImport of requiredInternalTypeImports) {
3321
+ if (typeImport.importedName === typeImport.localName) {
3322
+ internalLines.push(`import type { ${typeImport.importedName} } from '${typeImport.source}';`);
3323
+ continue;
3324
+ }
3325
+ internalLines.push(`import type { ${typeImport.importedName} as ${typeImport.localName} } from '${typeImport.source}';`);
3326
+ }
3327
+ internalLines.push("// End Tsonic source type imports");
3328
+ }
3329
+ if (plan.wrapperImports.length > 0) {
3330
+ internalLines.push("");
3331
+ internalLines.push("// Tsonic source member type imports (generated)");
3332
+ for (const wrapperImport of plan.wrapperImports) {
3333
+ if (wrapperImport.importedName === wrapperImport.aliasName) {
3334
+ internalLines.push(`import type { ${wrapperImport.importedName} } from '${wrapperImport.source}';`);
3335
+ continue;
3336
+ }
3337
+ internalLines.push(`import type { ${wrapperImport.importedName} as ${wrapperImport.aliasName} } from '${wrapperImport.source}';`);
3338
+ }
3339
+ internalLines.push("// End Tsonic source member type imports");
3340
+ }
3341
+ internalLines.push("");
3342
+ if (internalSourceAliasLines.length > 0) {
3343
+ internalLines.push(...internalSourceAliasLines);
3344
+ internalLines.push("");
3345
+ }
3346
+ internalLines.push(...internalBodyLines);
2055
3347
  writeFileSync(internalIndexPath, internalLines.join("\n").trimEnd() + "\n", "utf-8");
2056
3348
  const internalSpecifier = moduleNamespaceToInternalSpecifier(plan.namespace);
2057
3349
  const facadeLines = [];
@@ -2100,9 +3392,12 @@ const writeNamespaceArtifacts = (config, outDir, plan, entrypointReexports) => {
2100
3392
  localTypeImports.add(`${symbol.localName}$instance`);
2101
3393
  }
2102
3394
  }
2103
- for (const internalImport of plan.sourceAliasInternalImports) {
3395
+ for (const internalImport of sourceAliasInternalImports) {
2104
3396
  localTypeImports.add(internalImport);
2105
3397
  }
3398
+ for (const helper of plan.internalHelperTypeDeclarations) {
3399
+ localTypeImports.add(helper.emittedName);
3400
+ }
2106
3401
  if (localTypeImports.size > 0) {
2107
3402
  facadeLines.push("");
2108
3403
  facadeLines.push("// Tsonic source alias imports (generated)");
@@ -2111,35 +3406,53 @@ const writeNamespaceArtifacts = (config, outDir, plan, entrypointReexports) => {
2111
3406
  .join(", ")} } from '${internalSpecifier}';`);
2112
3407
  facadeLines.push("// End Tsonic source alias imports");
2113
3408
  }
2114
- if (plan.sourceAliasLines.length > 0) {
3409
+ if (sourceAliasLines.length > 0) {
2115
3410
  facadeLines.push("");
2116
3411
  facadeLines.push("// Tsonic source type aliases (generated)");
2117
- facadeLines.push(...plan.sourceAliasLines);
3412
+ facadeLines.push(...sourceAliasLines);
2118
3413
  facadeLines.push("// End Tsonic source type aliases");
2119
3414
  }
2120
- if (entrypointReexports && entrypointReexports.dtsStatements.length > 0) {
3415
+ if (plan.crossNamespaceReexports.dtsStatements.length > 0) {
2121
3416
  facadeLines.push("");
2122
- facadeLines.push("// Tsonic entrypoint re-exports (generated)");
2123
- facadeLines.push(...entrypointReexports.dtsStatements);
2124
- facadeLines.push("// End Tsonic entrypoint re-exports");
3417
+ facadeLines.push("// Tsonic cross-namespace re-exports (generated)");
3418
+ facadeLines.push(...plan.crossNamespaceReexports.dtsStatements);
3419
+ facadeLines.push("// End Tsonic cross-namespace re-exports");
2125
3420
  }
2126
3421
  for (const valueExport of plan.valueExports) {
2127
3422
  valueBindings.set(valueExport.exportName, valueExport.binding);
2128
3423
  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};`);
3424
+ const sourceSignature = renderSourceFunctionSignature({
3425
+ declaration: valueExport.facade.declaration,
3426
+ sourceSignatures: valueExport.facade.sourceSignatures ?? [],
3427
+ localTypeNameRemaps: valueExport.facade.localTypeNameRemaps,
3428
+ anonymousStructuralAliases,
3429
+ });
3430
+ facadeLines.push(sourceSignature
3431
+ ? `export declare function ${valueExport.exportName}${sourceSignature.typeParametersText}(${sourceSignature.parametersText}): ${sourceSignature.returnTypeText};`
3432
+ : `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
3433
  continue;
2135
3434
  }
2136
- facadeLines.push(`export declare const ${valueExport.exportName}: ${renderPortableType(valueExport.facade.declarator?.type)};`);
3435
+ const sourceFunctionTypeText = renderSourceFunctionType({
3436
+ sourceSignatures: valueExport.facade.sourceSignatures ?? [],
3437
+ localTypeNameRemaps: valueExport.facade.localTypeNameRemaps,
3438
+ anonymousStructuralAliases,
3439
+ });
3440
+ const sourceTypeText = sourceFunctionTypeText ??
3441
+ renderSourceValueType(valueExport.facade.sourceType, valueExport.facade.localTypeNameRemaps, anonymousStructuralAliases);
3442
+ facadeLines.push(`export declare const ${valueExport.exportName}: ${sourceTypeText ??
3443
+ renderPortableType(valueExport.facade.declarator?.type, [], valueExport.facade.localTypeNameRemaps, anonymousStructuralAliases)};`);
3444
+ }
3445
+ const requiredFacadeTypeImports = selectSourceTypeImportsForRenderedText(facadeLines.join("\n"), plan.facadeTypeImports);
3446
+ if (requiredFacadeTypeImports.length > 0) {
3447
+ facadeLines.splice(4, 0, "", "// Tsonic source type imports (generated)", ...requiredFacadeTypeImports.map((typeImport) => typeImport.importedName === typeImport.localName
3448
+ ? `import type { ${typeImport.importedName} } from '${typeImport.source}';`
3449
+ : `import type { ${typeImport.importedName} as ${typeImport.localName} } from '${typeImport.source}';`), "// End Tsonic source type imports");
2137
3450
  }
2138
3451
  if (plan.typeDeclarations.length === 0 &&
2139
3452
  plan.moduleContainers.length === 0 &&
2140
3453
  plan.valueExports.length === 0 &&
2141
- plan.sourceAliasLines.length === 0 &&
2142
- (!entrypointReexports || entrypointReexports.dtsStatements.length === 0)) {
3454
+ sourceAliasLines.length === 0 &&
3455
+ plan.crossNamespaceReexports.dtsStatements.length === 0) {
2143
3456
  facadeLines.push("export {};");
2144
3457
  }
2145
3458
  writeFileSync(facadeDtsPath, facadeLines.join("\n").trimEnd() + "\n", "utf-8");
@@ -2148,12 +3461,11 @@ const writeNamespaceArtifacts = (config, outDir, plan, entrypointReexports) => {
2148
3461
  "// Generated by Tsonic - Source bindings",
2149
3462
  "// Module Stub - Do Not Execute",
2150
3463
  "",
2151
- ...(entrypointReexports &&
2152
- entrypointReexports.jsValueStatements.length > 0
3464
+ ...(plan.crossNamespaceReexports.jsValueStatements.length > 0
2153
3465
  ? [
2154
- "// Tsonic entrypoint value re-exports (generated)",
2155
- ...entrypointReexports.jsValueStatements,
2156
- "// End Tsonic entrypoint value re-exports",
3466
+ "// Tsonic cross-namespace value re-exports (generated)",
3467
+ ...plan.crossNamespaceReexports.jsValueStatements,
3468
+ "// End Tsonic cross-namespace value re-exports",
2157
3469
  "",
2158
3470
  ]
2159
3471
  : []),
@@ -2216,10 +3528,6 @@ export const generateFirstPartyLibraryBindings = (config, bindingsOutDir) => {
2216
3528
  }
2217
3529
  rmSync(bindingsOutDir, { recursive: true, force: true });
2218
3530
  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
3531
  const sourceIndexByFileKey = new Map();
2224
3532
  for (const module of graphResult.value.modules) {
2225
3533
  if (module.filePath.startsWith("__tsonic/"))
@@ -2234,13 +3542,8 @@ export const generateFirstPartyLibraryBindings = (config, bindingsOutDir) => {
2234
3542
  const plansResult = collectNamespacePlans(graphResult.value.modules, config.outputName, config.rootNamespace, sourceIndexByFileKey);
2235
3543
  if (!plansResult.ok)
2236
3544
  return plansResult;
2237
- const entrypointReexportsResult = collectEntrypointReexports(graphResult.value.entryModule, modulesByFileKey);
2238
- if (!entrypointReexportsResult.ok)
2239
- return entrypointReexportsResult;
2240
3545
  for (const plan of plansResult.value) {
2241
- const result = writeNamespaceArtifacts(config, bindingsOutDir, plan, plan.namespace === graphResult.value.entryModule.namespace
2242
- ? entrypointReexportsResult.value
2243
- : undefined);
3546
+ const result = writeNamespaceArtifacts(config, bindingsOutDir, plan);
2244
3547
  if (!result.ok)
2245
3548
  return result;
2246
3549
  }