@shapeshift-labs/frontier-lang-compiler 0.2.118 → 0.2.119

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -277,6 +277,13 @@ For `export * from './module.js'`, project graphs fan out re-export identities
277
277
  for each named export in the resolved target document and omit `default`, which
278
278
  matches JavaScript module semantics.
279
279
 
280
+ When using `createTypeScriptCompilerNativeImporterAdapter`, compiler AST imports
281
+ emit the same binding-level module facts instead of only statement-level module
282
+ edges. Default, namespace, named, type-only, side-effect, re-export, export-star,
283
+ local export, `export default`, and `export =` declarations carry `importKind`,
284
+ `exportKind`, `localName`, `importedName`, `exportedName`, `isTypeOnly`, and
285
+ public-contract metadata into the semantic index and project symbol graph.
286
+
280
287
  High-risk native features also have explicit evidence policies. These policies are advisory in this package: they tell a swarm or admission queue what evidence is missing without silently changing the existing readiness classification.
281
288
 
282
289
  ```js
@@ -254,7 +254,7 @@ function moduleEdgeRecord(relation, moduleEdgeByRelation, symbolsById, documents
254
254
  localName: firstString(moduleEdge.localName, value.localName, symbolMetadata.localName),
255
255
  namespace: firstString(moduleEdge.namespace, value.namespace, symbolMetadata.namespace),
256
256
  exportStar: firstBoolean(moduleEdge.exportStar, value.exportStar, symbolMetadata.exportStar),
257
- isTypeOnly: firstBoolean(moduleEdge.isTypeOnly, value.isTypeOnly),
257
+ isTypeOnly: firstBoolean(moduleEdge.isTypeOnly, value.isTypeOnly, symbolMetadata.isTypeOnly, symbolMetadata.typeOnly),
258
258
  isReExport: firstBoolean(moduleEdge.isReExport, value.isReExport, symbolMetadata.reexport) ?? (relation.predicate === 'exports' && Boolean(moduleSpecifier)),
259
259
  publicContract: firstBoolean(moduleEdge.publicContract, value.publicContract, metadata.publicContract),
260
260
  evidenceIds: uniqueStrings([...(relation.evidenceIds ?? []), ...(fact?.evidenceIds ?? [])])
@@ -15,7 +15,7 @@ export function semanticIndexFromNativeDeclarations(declarations, input, options
15
15
  symbolId,
16
16
  regionKind: declarationRegionKind(declaration)
17
17
  };
18
- const occurrenceId = `occ_${idFragment(declaration.nativeNode.id)}_${declaration.role ?? 'definition'}`;
18
+ const occurrenceId = `occ_${idFragment(declaration.nativeNode.id)}_${idFragment(symbolId)}_${declaration.role ?? 'definition'}`;
19
19
  const ownershipRegion = semanticOwnershipRegionForDeclaration(input, {
20
20
  ...normalizedDeclaration,
21
21
  nodeId: declaration.nativeNode.id,
@@ -24,7 +24,7 @@ export function semanticIndexFromNativeDeclarations(declarations, input, options
24
24
  span: declaration.nativeNode.span,
25
25
  symbolId
26
26
  }, documentId);
27
- const relationId = `rel_${idFragment(documentId)}_${idFragment(declaration.nativeNode.id)}`;
27
+ const relationId = `rel_${idFragment(documentId)}_${idFragment(declaration.nativeNode.id)}_${idFragment(symbolId)}`;
28
28
  const moduleEdge = moduleEdgeForDeclaration(normalizedDeclaration, input, documentId, relationId, ownershipRegion);
29
29
  const publicContractRegion = publicContractRegionForDeclaration(normalizedDeclaration, ownershipRegion, moduleEdge);
30
30
  const reExportIdentity = reExportIdentityForDeclaration(normalizedDeclaration, input, documentId, relationId, ownershipRegion, moduleEdge);
@@ -76,17 +76,17 @@ export function semanticIndexFromNativeDeclarations(declarations, input, options
76
76
  ...(Object.keys(graphMetadata).length ? { metadata: graphMetadata } : {})
77
77
  });
78
78
  facts.push({
79
- id: `fact_${idFragment(declaration.nativeNode.id)}_kind`,
79
+ id: `fact_${idFragment(declaration.nativeNode.id)}_${idFragment(symbolId)}_kind`,
80
80
  predicate: 'nativeKind',
81
81
  subjectId: symbolId,
82
82
  value: declaration.nativeNode.languageKind
83
83
  }, {
84
- id: `fact_${idFragment(declaration.nativeNode.id)}_ownership_region`,
84
+ id: `fact_${idFragment(declaration.nativeNode.id)}_${idFragment(symbolId)}_ownership_region`,
85
85
  predicate: 'semanticOwnershipRegion',
86
86
  subjectId: symbolId,
87
87
  value: ownershipRegion
88
88
  }, {
89
- id: `fact_${idFragment(declaration.nativeNode.id)}_ownership_region_taxonomy`,
89
+ id: `fact_${idFragment(declaration.nativeNode.id)}_${idFragment(symbolId)}_ownership_region_taxonomy`,
90
90
  predicate: 'semanticOwnershipRegionTaxonomy',
91
91
  subjectId: symbolId,
92
92
  value: {
@@ -96,7 +96,7 @@ export function semanticIndexFromNativeDeclarations(declarations, input, options
96
96
  }
97
97
  }, ...projectSymbolGraphFacts({ moduleEdge, publicContractRegion, reExportIdentity, relationId, symbolId, evidenceId }));
98
98
  mappings.push({
99
- id: `map_${idFragment(declaration.nativeNode.id)}`,
99
+ id: `map_${idFragment(declaration.nativeNode.id)}_${idFragment(symbolId)}`,
100
100
  nativeAstNodeId: declaration.nativeNode.id,
101
101
  semanticSymbolId: symbolId,
102
102
  semanticOccurrenceId: occurrenceId,
@@ -197,7 +197,8 @@ function moduleEdgeForDeclaration(declaration, input, documentId, relationId, ow
197
197
  exportedName: declaration.exportedName ?? declaration.metadata?.exportedName,
198
198
  localName: declaration.localName ?? declaration.metadata?.localName,
199
199
  namespace: declaration.namespace ?? declaration.metadata?.namespace,
200
- isTypeOnly: declaration.isTypeOnly ?? declaration.metadata?.isTypeOnly,
200
+ isTypeOnly: declaration.isTypeOnly ?? declaration.metadata?.isTypeOnly ?? declaration.metadata?.typeOnly,
201
+ exportStar: declaration.exportStar ?? declaration.metadata?.exportStar,
201
202
  isReExport: edgeKind === 're-export',
202
203
  publicContract: publicContractForDeclaration(declaration, edgeKind)
203
204
  });
@@ -255,7 +256,8 @@ function reExportIdentityForDeclaration(declaration, input, documentId, relation
255
256
  importedName: declaration.importedName ?? declaration.metadata?.importedName,
256
257
  localName: declaration.localName ?? declaration.metadata?.localName,
257
258
  namespace: declaration.namespace ?? declaration.metadata?.namespace,
258
- isTypeOnly: declaration.isTypeOnly ?? declaration.metadata?.isTypeOnly,
259
+ isTypeOnly: declaration.isTypeOnly ?? declaration.metadata?.isTypeOnly ?? declaration.metadata?.typeOnly,
260
+ exportStar: declaration.exportStar ?? declaration.metadata?.exportStar,
259
261
  symbolId: declaration.symbolId,
260
262
  relationId,
261
263
  ownershipRegionId: ownershipRegion.id,
@@ -267,7 +269,7 @@ function reExportIdentityForDeclaration(declaration, input, documentId, relation
267
269
  function projectSymbolGraphFacts({ moduleEdge, publicContractRegion, reExportIdentity, relationId, symbolId, evidenceId }) {
268
270
  return [
269
271
  moduleEdge ? {
270
- id: `fact_${idFragment(relationId)}_module_edge`,
272
+ id: graphFactId(relationId, symbolId, 'module_edge'),
271
273
  predicate: 'moduleEdge',
272
274
  subjectId: relationId,
273
275
  objectId: symbolId,
@@ -275,7 +277,7 @@ function projectSymbolGraphFacts({ moduleEdge, publicContractRegion, reExportIde
275
277
  evidenceIds: [evidenceId]
276
278
  } : undefined,
277
279
  reExportIdentity ? {
278
- id: `fact_${idFragment(relationId)}_re_export_identity`,
280
+ id: graphFactId(relationId, symbolId, 're_export_identity'),
279
281
  predicate: 'reExportIdentity',
280
282
  subjectId: symbolId,
281
283
  objectId: relationId,
@@ -283,7 +285,7 @@ function projectSymbolGraphFacts({ moduleEdge, publicContractRegion, reExportIde
283
285
  evidenceIds: [evidenceId]
284
286
  } : undefined,
285
287
  publicContractRegion ? {
286
- id: `fact_${idFragment(symbolId)}_public_contract_region`,
288
+ id: graphFactId(relationId, symbolId, 'public_contract_region'),
287
289
  predicate: 'publicContractRegion',
288
290
  subjectId: symbolId,
289
291
  objectId: publicContractRegion.id,
@@ -302,6 +304,10 @@ function hashParts(sourceHash) {
302
304
  };
303
305
  }
304
306
 
307
+ function graphFactId(relationId, symbolId, suffix) {
308
+ return `fact_${idFragment(hashSemanticValue([relationId, symbolId, suffix]))}_${suffix}`;
309
+ }
310
+
305
311
  function compactRecord(record) {
306
312
  return Object.fromEntries(Object.entries(record).filter(([, value]) => value !== undefined));
307
313
  }
@@ -1,20 +1,30 @@
1
1
  import{hashSemanticValue}from'@shapeshift-labs/frontier-lang-kernel';import{idFragment}from'../../native-import-utils.js';
2
- import{declarationRecord}from'./declarationRecord.js';import{identifierName}from'./identifierName.js';import{namedDeclaration}from'./namedDeclaration.js';import{stringFromTsExpression}from'./stringFromTsExpression.js';
2
+ import{declarationRecord}from'./declarationRecord.js';import{namedDeclaration}from'./namedDeclaration.js';import{stringFromTsExpression}from'./stringFromTsExpression.js';import{typeScriptExportedDeclarationEntries}from'./typeScriptExportedDeclarationEntries.js';import{typeScriptModuleDeclarationEntries}from'./typeScriptModuleDeclarationEntries.js';
3
3
  export function typeScriptDeclaration(node, kind, nativeNodeId, input, options = {}) {
4
4
  const enrich = (declaration, symbolNode = node.name ?? node) => enrichTypeScriptDeclaration(node, symbolNode, declaration, input, options);
5
+ const moduleEntries = typeScriptModuleDeclarationEntries(node, kind, nativeNodeId, input);
6
+ if (moduleEntries?.length) return moduleEntries.map((entry) => enrich(entry.declaration, entry.symbolNode ?? node));
7
+ const exportedEntries = typeScriptExportedDeclarationEntries(node, kind, nativeNodeId, input, options);
8
+ if (exportedEntries.length && Array.isArray(node.declarationList?.declarations)) return exportedEntries.map((entry) => enrich(entry.declaration, entry.symbolNode ?? node));
5
9
  if (kind === 'ImportDeclaration' || kind === 'ImportEqualsDeclaration') {
6
10
  const name = stringFromTsExpression(node.moduleSpecifier) ?? stringFromTsExpression(node.externalModuleReference?.expression);
7
11
  if (name) return enrich(declarationRecord(input, nativeNodeId, name, 'module', 'import'), node.moduleSpecifier ?? node.externalModuleReference?.expression ?? node);
8
12
  }
9
- if (kind === 'FunctionDeclaration') return enrich(namedDeclaration(input, nativeNodeId, node.name, 'function'));
10
- if (kind === 'ClassDeclaration') return enrich(namedDeclaration(input, nativeNodeId, node.name, 'class'));
11
- if (kind === 'InterfaceDeclaration') return enrich(namedDeclaration(input, nativeNodeId, node.name, 'interface'));
12
- if (kind === 'TypeAliasDeclaration' || kind === 'EnumDeclaration') return enrich(namedDeclaration(input, nativeNodeId, node.name, 'type'));
13
+ if (kind === 'FunctionDeclaration') return declarationWithExports(enrich(namedDeclaration(input, nativeNodeId, node.name, 'function')), exportedEntries, enrich, node);
14
+ if (kind === 'ClassDeclaration') return declarationWithExports(enrich(namedDeclaration(input, nativeNodeId, node.name, 'class')), exportedEntries, enrich, node);
15
+ if (kind === 'InterfaceDeclaration') return declarationWithExports(enrich(namedDeclaration(input, nativeNodeId, node.name, 'interface')), exportedEntries, enrich, node);
16
+ if (kind === 'TypeAliasDeclaration' || kind === 'EnumDeclaration') return declarationWithExports(enrich(namedDeclaration(input, nativeNodeId, node.name, 'type')), exportedEntries, enrich, node);
13
17
  if (kind === 'VariableDeclaration') return enrich(namedDeclaration(input, nativeNodeId, node.name, 'variable'));
14
18
  if (kind === 'MethodDeclaration' || kind === 'MethodSignature') return enrich(namedDeclaration(input, nativeNodeId, node.name, 'method'));
15
19
  return undefined;
16
20
  }
17
21
 
22
+ function declarationWithExports(declaration, exportedEntries, enrich, node) {
23
+ const exports = exportedEntries.map((entry) => enrich(entry.declaration, entry.symbolNode ?? node));
24
+ if (!declaration) return exports.length ? exports : undefined;
25
+ return exports.length ? [declaration, ...exports] : declaration;
26
+ }
27
+
18
28
  function enrichTypeScriptDeclaration(node, symbolNode, declaration, input, options) {
19
29
  if (!declaration) return declaration;
20
30
  const checker = options.typeChecker ?? options.checker ?? options.program?.getTypeChecker?.();
@@ -0,0 +1,104 @@
1
+ import{idFragment}from'../../native-import-utils.js';
2
+ import{declarationRecord}from'./declarationRecord.js';import{identifierName}from'./identifierName.js';
3
+ export function typeScriptExportedDeclarationEntries(node, kind, nativeNodeId, input, options = {}) {
4
+ const modifiers = declarationModifiers(node, options.ts);
5
+ if (!modifiers.exported) return [];
6
+ if (isVariableStatement(node, kind)) return variableStatementExportEntries(node, nativeNodeId, input, modifiers);
7
+ const localName = identifierName(node.name);
8
+ const symbolKind = exportedSymbolKind(kind);
9
+ if (!symbolKind && !modifiers.defaulted) return [];
10
+ return [exportEntry(input, nativeNodeId, {
11
+ localName,
12
+ exportedName: modifiers.defaulted ? 'default' : localName,
13
+ exportKind: modifiers.defaulted ? 'default' : exportKindForDeclaration(kind),
14
+ isTypeOnly: typeOnlyDeclarationKind(kind),
15
+ symbolNode: node.name ?? node
16
+ })];
17
+ }
18
+
19
+ function variableStatementExportEntries(node, nativeNodeId, input, modifiers) {
20
+ const declarations = node.declarationList?.declarations ?? [];
21
+ return declarations
22
+ .map((declaration) => {
23
+ const localName = identifierName(declaration.name);
24
+ if (!localName) return undefined;
25
+ return exportEntry(input, nativeNodeId, {
26
+ localName,
27
+ exportedName: modifiers.defaulted ? 'default' : localName,
28
+ exportKind: modifiers.defaulted ? 'default' : 'named',
29
+ isTypeOnly: false,
30
+ symbolNode: declaration.name
31
+ });
32
+ })
33
+ .filter(Boolean);
34
+ }
35
+
36
+ function exportEntry(input, nativeNodeId, binding) {
37
+ return {
38
+ declaration: {
39
+ ...declarationRecord(input, nativeNodeId, binding.exportedName, 'export', 'export'),
40
+ symbolId: `symbol:${input.language}:export:${idFragment(binding.exportedName)}`,
41
+ localName: binding.localName,
42
+ exportedName: binding.exportedName,
43
+ exportKind: binding.exportKind,
44
+ isTypeOnly: binding.isTypeOnly,
45
+ publicContract: true,
46
+ metadata: {
47
+ scan: 'typescript-exported-declaration',
48
+ localName: binding.localName,
49
+ exportedName: binding.exportedName,
50
+ exportKind: binding.exportKind,
51
+ isTypeOnly: binding.isTypeOnly,
52
+ typeOnly: binding.isTypeOnly,
53
+ publicContract: true
54
+ }
55
+ },
56
+ symbolNode: binding.symbolNode
57
+ };
58
+ }
59
+
60
+ function declarationModifiers(node, ts) {
61
+ const helperModifiers = safeModifiers(node, ts);
62
+ const names = new Set([...(node.modifiers ?? []), ...helperModifiers].map((modifier) => modifierName(modifier, ts)));
63
+ return {
64
+ exported: names.has('ExportKeyword') || names.has('export'),
65
+ defaulted: names.has('DefaultKeyword') || names.has('default')
66
+ };
67
+ }
68
+
69
+ function safeModifiers(node, ts) {
70
+ try {
71
+ if (typeof ts?.canHaveModifiers === 'function' && !ts.canHaveModifiers(node)) return [];
72
+ return typeof ts?.getModifiers === 'function' ? [...(ts.getModifiers(node) ?? [])] : [];
73
+ } catch {
74
+ return [];
75
+ }
76
+ }
77
+
78
+ function isVariableStatement(node, kind) {
79
+ return kind === 'VariableStatement' || Array.isArray(node.declarationList?.declarations);
80
+ }
81
+
82
+ function modifierName(modifier, ts) {
83
+ if (typeof modifier.kindName === 'string') return modifier.kindName;
84
+ if (ts?.SyntaxKind && modifier.kind !== undefined) return ts.SyntaxKind[modifier.kind] ?? String(modifier.kind);
85
+ if (typeof modifier.text === 'string') return modifier.text;
86
+ if (typeof modifier.name === 'string') return modifier.name;
87
+ return String(modifier.kind ?? '');
88
+ }
89
+
90
+ function exportedSymbolKind(kind) {
91
+ if (kind === 'FunctionDeclaration') return 'function';
92
+ if (kind === 'ClassDeclaration') return 'class';
93
+ if (kind === 'InterfaceDeclaration') return 'interface';
94
+ if (kind === 'TypeAliasDeclaration' || kind === 'EnumDeclaration') return 'type';
95
+ return undefined;
96
+ }
97
+
98
+ function exportKindForDeclaration(kind) {
99
+ return typeOnlyDeclarationKind(kind) ? 'type-named' : 'named';
100
+ }
101
+
102
+ function typeOnlyDeclarationKind(kind) {
103
+ return kind === 'InterfaceDeclaration' || kind === 'TypeAliasDeclaration';
104
+ }
@@ -0,0 +1,279 @@
1
+ import{idFragment}from'../../native-import-utils.js';
2
+ import{declarationRecord}from'./declarationRecord.js';import{identifierName}from'./identifierName.js';import{stringFromTsExpression}from'./stringFromTsExpression.js';
3
+ export function typeScriptModuleDeclarationEntries(node, kind, nativeNodeId, input) {
4
+ if (kind === 'ImportDeclaration') return importDeclarationEntries(node, nativeNodeId, input);
5
+ if (kind === 'ImportEqualsDeclaration') return importEqualsDeclarationEntries(node, nativeNodeId, input);
6
+ if (kind === 'ExportDeclaration') return exportDeclarationEntries(node, nativeNodeId, input);
7
+ if (kind === 'ExportAssignment') return exportAssignmentEntries(node, nativeNodeId, input);
8
+ return undefined;
9
+ }
10
+
11
+ function importDeclarationEntries(node, nativeNodeId, input) {
12
+ const moduleSpecifier = stringFromTsExpression(node.moduleSpecifier);
13
+ if (!moduleSpecifier) return [];
14
+ const typeOnly = Boolean(node.importClause?.isTypeOnly);
15
+ const bindings = importClauseBindings(node.importClause, typeOnly);
16
+ return importModuleEntries(input, nativeNodeId, moduleSpecifier, 'ImportDeclaration', bindings, {
17
+ typeOnly,
18
+ sideEffectOnly: bindings.length === 0,
19
+ importKind: bindings.length === 0 ? 'side-effect' : 'module'
20
+ });
21
+ }
22
+
23
+ function importEqualsDeclarationEntries(node, nativeNodeId, input) {
24
+ const moduleSpecifier = stringFromTsExpression(node.moduleReference?.expression ?? node.externalModuleReference?.expression);
25
+ const localName = identifierName(node.name);
26
+ if (!moduleSpecifier || !localName) return [];
27
+ const typeOnly = Boolean(node.isTypeOnly);
28
+ return importModuleEntries(input, nativeNodeId, moduleSpecifier, 'ImportEqualsDeclaration', [{
29
+ localName,
30
+ importedName: 'default',
31
+ importKind: 'commonjs-require',
32
+ isTypeOnly: typeOnly,
33
+ symbolNode: node.name
34
+ }], { typeOnly, importKind: 'commonjs-require' });
35
+ }
36
+
37
+ function exportDeclarationEntries(node, nativeNodeId, input) {
38
+ const moduleSpecifier = stringFromTsExpression(node.moduleSpecifier);
39
+ const typeOnly = Boolean(node.isTypeOnly);
40
+ const exportStar = moduleSpecifier && !node.exportClause;
41
+ const bindings = exportClauseBindings(node.exportClause, { typeOnly, reExport: Boolean(moduleSpecifier) });
42
+ return [
43
+ ...(moduleSpecifier ? importModuleEntries(input, nativeNodeId, moduleSpecifier, 'ExportFromDeclaration', reExportImportBindings(bindings, exportStar), {
44
+ typeOnly,
45
+ reexport: true,
46
+ exportStar,
47
+ importKind: exportStar ? 'reexport' : 'reexport'
48
+ }) : []),
49
+ ...exportModuleEntries(input, nativeNodeId, moduleSpecifier, bindings, {
50
+ typeOnly,
51
+ exportStar,
52
+ reExport: Boolean(moduleSpecifier),
53
+ exportKind: exportStar ? 'export-star' : 'named'
54
+ })
55
+ ];
56
+ }
57
+
58
+ function exportAssignmentEntries(node, nativeNodeId, input) {
59
+ const exportedName = node.isExportEquals ? 'module.exports' : 'default';
60
+ const localName = stringFromTsExpression(node.expression);
61
+ return [{
62
+ declaration: compactRecord({
63
+ ...declarationRecord(input, nativeNodeId, exportedName, 'export', 'export'),
64
+ exportedName,
65
+ localName,
66
+ exportKind: node.isExportEquals ? 'assignment' : 'default',
67
+ publicContract: true,
68
+ metadata: compactRecord({
69
+ exportKind: node.isExportEquals ? 'assignment' : 'default',
70
+ exportedName,
71
+ localName,
72
+ publicContract: true
73
+ })
74
+ }),
75
+ symbolNode: node.expression ?? node
76
+ }];
77
+ }
78
+
79
+ function importClauseBindings(importClause, typeOnly) {
80
+ if (!importClause) return [];
81
+ const bindings = [];
82
+ const defaultName = identifierName(importClause.name);
83
+ if (defaultName) bindings.push({
84
+ localName: defaultName,
85
+ importedName: 'default',
86
+ importKind: typeOnly ? 'type-default' : 'default',
87
+ isTypeOnly: typeOnly,
88
+ symbolNode: importClause.name
89
+ });
90
+ const named = importClause.namedBindings;
91
+ if (!named) return bindings;
92
+ if (Array.isArray(named.elements)) {
93
+ bindings.push(...named.elements.map((element) => importSpecifierBinding(element, typeOnly)).filter(Boolean));
94
+ } else {
95
+ const namespace = identifierName(named.name);
96
+ if (namespace) bindings.push({ localName: namespace, importedName: '*', namespace, importKind: 'namespace', isTypeOnly: typeOnly, symbolNode: named.name });
97
+ }
98
+ return bindings;
99
+ }
100
+
101
+ function importSpecifierBinding(element, parentTypeOnly) {
102
+ const localName = identifierName(element.name);
103
+ if (!localName) return undefined;
104
+ const typeOnly = Boolean(parentTypeOnly || element.isTypeOnly);
105
+ const importedName = identifierName(element.propertyName) ?? localName;
106
+ return {
107
+ localName,
108
+ importedName,
109
+ importKind: typeOnly ? 'type-named' : 'named',
110
+ isTypeOnly: typeOnly,
111
+ symbolNode: element.name
112
+ };
113
+ }
114
+
115
+ function exportClauseBindings(exportClause, options) {
116
+ if (!exportClause) return [];
117
+ if (Array.isArray(exportClause.elements)) {
118
+ return exportClause.elements.map((element) => exportSpecifierBinding(element, options)).filter(Boolean);
119
+ }
120
+ const exportedName = identifierName(exportClause.name);
121
+ if (!exportedName) return [];
122
+ return [{
123
+ localName: exportedName,
124
+ importedName: '*',
125
+ exportedName,
126
+ namespace: exportedName,
127
+ importKind: 'namespace-reexport',
128
+ exportKind: 'namespace-reexport',
129
+ isTypeOnly: Boolean(options.typeOnly),
130
+ reExport: Boolean(options.reExport),
131
+ symbolNode: exportClause.name
132
+ }];
133
+ }
134
+
135
+ function exportSpecifierBinding(element, options) {
136
+ const exportedName = identifierName(element.name);
137
+ if (!exportedName) return undefined;
138
+ const typeOnly = Boolean(options.typeOnly || element.isTypeOnly);
139
+ const localName = identifierName(element.propertyName) ?? exportedName;
140
+ return {
141
+ localName,
142
+ importedName: options.reExport ? localName : undefined,
143
+ exportedName,
144
+ importKind: options.reExport ? typeOnly ? 'type-reexport' : 'reexport' : undefined,
145
+ exportKind: typeOnly ? 'type-named' : 'named',
146
+ isTypeOnly: typeOnly,
147
+ reExport: Boolean(options.reExport),
148
+ symbolNode: element.name
149
+ };
150
+ }
151
+
152
+ function reExportImportBindings(bindings, exportStar) {
153
+ if (exportStar) return [];
154
+ return bindings.map((binding) => ({
155
+ localName: binding.exportedName ?? binding.localName,
156
+ importedName: binding.importedName ?? binding.localName,
157
+ exportedName: binding.exportedName,
158
+ namespace: binding.namespace,
159
+ importKind: binding.importKind ?? 'reexport',
160
+ isTypeOnly: binding.isTypeOnly,
161
+ symbolNode: binding.symbolNode
162
+ }));
163
+ }
164
+
165
+ function importModuleEntries(input, nativeNodeId, moduleSpecifier, _languageKind, bindings, metadata) {
166
+ const moduleEntry = {
167
+ declaration: compactRecord({
168
+ ...declarationRecord(input, nativeNodeId, moduleSpecifier, 'module', 'import'),
169
+ importPath: moduleSpecifier,
170
+ moduleSpecifier,
171
+ importKind: metadata.importKind,
172
+ isTypeOnly: metadata.typeOnly,
173
+ exportStar: metadata.exportStar,
174
+ metadata: moduleMetadata('typescript-import', bindings, metadata)
175
+ })
176
+ };
177
+ return [moduleEntry, ...bindings.map((binding) => importBindingEntry(input, nativeNodeId, moduleSpecifier, binding))];
178
+ }
179
+
180
+ function importBindingEntry(input, nativeNodeId, moduleSpecifier, binding) {
181
+ const declaration = compactRecord({
182
+ ...declarationRecord(input, nativeNodeId, binding.localName, 'import', 'import'),
183
+ symbolId: `symbol:${input.language}:import:${idFragment(`${moduleSpecifier}:${binding.localName}:${binding.importedName}`)}`,
184
+ importPath: moduleSpecifier,
185
+ moduleSpecifier,
186
+ localName: binding.localName,
187
+ importedName: binding.importedName,
188
+ exportedName: binding.exportedName,
189
+ namespace: binding.namespace,
190
+ importKind: binding.importKind,
191
+ isTypeOnly: binding.isTypeOnly,
192
+ metadata: compactRecord({
193
+ scan: 'typescript-import-binding',
194
+ moduleSpecifier,
195
+ importPath: moduleSpecifier,
196
+ localName: binding.localName,
197
+ importedName: binding.importedName,
198
+ exportedName: binding.exportedName,
199
+ namespace: binding.namespace,
200
+ importKind: binding.importKind,
201
+ isTypeOnly: binding.isTypeOnly,
202
+ typeOnly: binding.isTypeOnly
203
+ })
204
+ });
205
+ return { declaration, symbolNode: binding.symbolNode };
206
+ }
207
+
208
+ function exportModuleEntries(input, nativeNodeId, moduleSpecifier, bindings, metadata) {
209
+ const statementName = metadata.exportStar
210
+ ? `* from ${moduleSpecifier}`
211
+ : moduleSpecifier ? `{${bindings.map((binding) => binding.exportedName).join(',')}} from ${moduleSpecifier}` : `{${bindings.map((binding) => binding.exportedName).join(',')}}`;
212
+ const statement = {
213
+ declaration: compactRecord({
214
+ ...declarationRecord(input, nativeNodeId, statementName, 'module', 'export'),
215
+ exportPath: moduleSpecifier,
216
+ moduleSpecifier,
217
+ exportKind: metadata.exportKind,
218
+ exportStar: metadata.exportStar,
219
+ isTypeOnly: metadata.typeOnly,
220
+ reExport: metadata.reExport,
221
+ publicContract: true,
222
+ metadata: moduleMetadata('typescript-export', bindings, metadata)
223
+ })
224
+ };
225
+ return [statement, ...bindings.map((binding) => exportBindingEntry(input, nativeNodeId, moduleSpecifier, binding))];
226
+ }
227
+
228
+ function exportBindingEntry(input, nativeNodeId, moduleSpecifier, binding) {
229
+ const declaration = compactRecord({
230
+ ...declarationRecord(input, nativeNodeId, binding.exportedName, 'export', 'export'),
231
+ symbolId: `symbol:${input.language}:export:${idFragment(`${moduleSpecifier ?? 'local'}:${binding.exportedName}:${binding.localName}`)}`,
232
+ exportPath: moduleSpecifier,
233
+ moduleSpecifier,
234
+ localName: binding.localName,
235
+ importedName: binding.importedName,
236
+ exportedName: binding.exportedName,
237
+ namespace: binding.namespace,
238
+ exportKind: binding.exportKind,
239
+ isTypeOnly: binding.isTypeOnly,
240
+ reExport: binding.reExport,
241
+ publicContract: true,
242
+ metadata: compactRecord({
243
+ scan: 'typescript-export-binding',
244
+ moduleSpecifier,
245
+ exportPath: moduleSpecifier,
246
+ localName: binding.localName,
247
+ importedName: binding.importedName,
248
+ exportedName: binding.exportedName,
249
+ namespace: binding.namespace,
250
+ exportKind: binding.exportKind,
251
+ isTypeOnly: binding.isTypeOnly,
252
+ typeOnly: binding.isTypeOnly,
253
+ reExport: binding.reExport,
254
+ publicContract: true
255
+ })
256
+ });
257
+ return { declaration, symbolNode: binding.symbolNode };
258
+ }
259
+
260
+ function moduleMetadata(scan, bindings, metadata) {
261
+ return compactRecord({
262
+ scan,
263
+ moduleOnly: true,
264
+ bindingCount: bindings.length,
265
+ importKind: metadata.importKind,
266
+ exportKind: metadata.exportKind,
267
+ isTypeOnly: metadata.typeOnly,
268
+ typeOnly: metadata.typeOnly,
269
+ sideEffectOnly: metadata.sideEffectOnly,
270
+ reexport: metadata.reexport,
271
+ reExport: metadata.reExport,
272
+ exportStar: metadata.exportStar,
273
+ publicContract: metadata.reExport || metadata.exportKind
274
+ });
275
+ }
276
+
277
+ function compactRecord(record) {
278
+ return Object.fromEntries(Object.entries(record).filter(([, value]) => value !== undefined));
279
+ }
@@ -23,17 +23,20 @@ export function visitTypeScriptAstNode(node, sourceFile, context, propertyPath,
23
23
  } else if (Array.isArray(node.children)) {
24
24
  node.children.forEach(visitChild);
25
25
  }
26
- const declaration = typeScriptDeclaration(node, kind, id, context.input, context.options);
26
+ const declarationResult = typeScriptDeclaration(node, kind, id, context.input, context.options);
27
+ const declarations = Array.isArray(declarationResult) ? declarationResult.filter(Boolean) : declarationResult ? [declarationResult] : [];
28
+ const primaryDeclaration = declarations[0];
27
29
  const nativeNode = {
28
30
  id,
29
31
  kind,
30
32
  languageKind: `${context.input.language}.${kind}`,
31
33
  span,
32
- value: declaration?.name ?? typeScriptNodeValue(node),
34
+ value: primaryDeclaration?.name ?? typeScriptNodeValue(node),
33
35
  fields: primitiveTypeScriptFields(node, kind),
34
36
  children,
35
37
  metadata: {
36
- ...declaration?.metadata,
38
+ ...primaryDeclaration?.metadata,
39
+ ...(declarations.length > 1 ? { declarationCount: declarations.length } : {}),
37
40
  astFormat: context.options.astFormat,
38
41
  propertyPath,
39
42
  pos: numberOrUndefined(node.pos),
@@ -41,6 +44,6 @@ export function visitTypeScriptAstNode(node, sourceFile, context, propertyPath,
41
44
  }
42
45
  };
43
46
  context.nodes[id] = nativeNode;
44
- if (declaration) context.declarations.push({ ...declaration, nativeNode });
47
+ for (const declaration of declarations) context.declarations.push({ ...declaration, nativeNode });
45
48
  return id;
46
49
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shapeshift-labs/frontier-lang-compiler",
3
- "version": "0.2.118",
3
+ "version": "0.2.119",
4
4
  "description": "Compiler facade for Frontier Lang source documents and language projection adapters.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",