@shapeshift-labs/frontier-lang-compiler 0.2.115 → 0.2.117

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
@@ -238,12 +238,38 @@ console.log(project.outputProjectSymbolGraph.importEdges[0].packageName); // "@p
238
238
  console.log(project.outputProjectSymbolGraph.importEdges[0].packageExportCondition); // "import"
239
239
  ```
240
240
 
241
+ Package `imports` maps are also modeled for `#internal` specifiers. Top-level
242
+ `moduleResolution.imports` applies from `packageRoot`/`root`, while
243
+ `packages[name].imports` applies to the nearest configured package root. Graph
244
+ edges record `packageImportKey`, `packageImportCondition`, and
245
+ `packageImportTarget` so merge admission can distinguish private aliases from
246
+ external or unresolved imports:
247
+
248
+ ```js
249
+ const project = safeMergeJsTsProject({
250
+ includeOutputProjectSymbolGraph: true,
251
+ moduleResolution: {
252
+ imports: { '#internal/*': { import: './src/internal/*.ts', default: './src/internal/*.js' } },
253
+ packageExportConditions: ['import', 'default']
254
+ },
255
+ baseFiles,
256
+ workerFiles,
257
+ headFiles
258
+ });
259
+
260
+ console.log(project.outputProjectSymbolGraph.importEdges[0].resolutionKind); // "package-import-source"
261
+ console.log(project.outputProjectSymbolGraph.importEdges[0].packageImportKey); // "#internal/*"
262
+ ```
263
+
241
264
  Named re-export identities also include symbol links when the project graph has
242
265
  enough evidence. For `export { thing as renamedThing } from './thing.js'`,
243
266
  `reExportIdentities[]` records the source module, imported/exported names,
244
267
  `originSymbolId`, `exportedSymbolId`, and `localSymbolId`.
245
268
  Public contract regions include `apiSurfaceKind`, `signatureHash`, and
246
269
  `contractHash`, giving merge admission a stable API surface fingerprint.
270
+ For `export * from './module.js'`, project graphs fan out re-export identities
271
+ for each named export in the resolved target document and omit `default`, which
272
+ matches JavaScript module semantics.
247
273
 
248
274
  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.
249
275
 
@@ -1,6 +1,7 @@
1
1
  export type NativeProjectModuleResolutionPaths = Readonly<Record<string, readonly string[] | string>>;
2
2
  export type NativeProjectPackageExportTarget = string | readonly string[] | NativeProjectPackageConditionalExports;
3
3
  export type NativeProjectPackageExports = NativeProjectPackageExportTarget | Readonly<Record<string, NativeProjectPackageExportTarget>>;
4
+ export type NativeProjectPackageImports = Readonly<Record<string, NativeProjectPackageExportTarget>>;
4
5
 
5
6
  export interface NativeProjectPackageConditionalExports {
6
7
  readonly [condition: string]: NativeProjectPackageExportTarget;
@@ -12,12 +13,17 @@ export interface NativeProjectPackageResolutionOptions {
12
13
  readonly main?: string;
13
14
  readonly types?: string;
14
15
  readonly exports?: NativeProjectPackageExports;
16
+ readonly imports?: NativeProjectPackageImports;
15
17
  }
16
18
 
17
19
  export interface NativeProjectModuleResolutionOptions {
20
+ readonly root?: string;
21
+ readonly packageRoot?: string;
18
22
  readonly baseUrl?: string;
19
23
  readonly paths?: NativeProjectModuleResolutionPaths;
20
24
  readonly aliases?: NativeProjectModuleResolutionPaths;
25
+ readonly imports?: NativeProjectPackageImports;
26
+ readonly packageImports?: NativeProjectPackageImports;
21
27
  readonly packages?: Readonly<Record<string, NativeProjectPackageResolutionOptions>>;
22
28
  readonly conditions?: readonly string[];
23
29
  readonly packageExportConditions?: readonly string[];
@@ -107,16 +107,15 @@ export interface NativeProjectSymbolGraphModuleEdgeRecord {
107
107
  readonly resolvedModulePath?: string;
108
108
  readonly targetDocumentId?: string;
109
109
  readonly resolvedTargetSymbolId?: string;
110
- readonly resolutionKind?: 'relative-source' | 'relative-missing' | 'alias-source' | 'alias-missing' | 'path-alias-source' | 'path-alias-missing' | 'base-url-source' | 'base-url-missing' | 'package-source' | 'package-missing' | 'package-external' | string;
111
- readonly packageName?: string;
112
- readonly packageSubpath?: string;
113
- readonly packageExportCondition?: string;
110
+ readonly resolutionKind?: 'relative-source' | 'relative-missing' | 'alias-source' | 'alias-missing' | 'path-alias-source' | 'path-alias-missing' | 'base-url-source' | 'base-url-missing' | 'package-source' | 'package-missing' | 'package-external' | 'package-import-source' | 'package-import-missing' | 'package-import-external' | string;
111
+ readonly packageName?: string; readonly packageSubpath?: string; readonly packageExportCondition?: string;
112
+ readonly packageImportKey?: string; readonly packageImportCondition?: string; readonly packageImportTarget?: string;
114
113
  readonly importKind?: string;
115
114
  readonly exportKind?: string;
116
115
  readonly importedName?: string;
117
116
  readonly exportedName?: string;
118
117
  readonly localName?: string; readonly namespace?: string;
119
- readonly isTypeOnly?: boolean;
118
+ readonly exportStar?: boolean; readonly isTypeOnly?: boolean;
120
119
  readonly isReExport?: boolean;
121
120
  readonly publicContract?: boolean;
122
121
  readonly evidenceIds?: readonly string[];
@@ -133,8 +132,8 @@ export interface NativeProjectSymbolGraphReExportIdentityRecord {
133
132
  readonly exportedName?: string;
134
133
  readonly importedName?: string;
135
134
  readonly localName?: string;
136
- readonly namespace?: string;
137
- readonly isTypeOnly?: boolean;
135
+ readonly namespace?: string; readonly isTypeOnly?: boolean;
136
+ readonly isExportStar?: boolean;
138
137
  readonly symbolId?: string; readonly originSymbolId?: string;
139
138
  readonly exportedSymbolId?: string; readonly localSymbolId?: string;
140
139
  readonly relationId?: string;
@@ -1,8 +1,8 @@
1
1
  import{idFragment,uniqueByEvidenceId,uniqueByLossId,uniqueStrings}from'../../native-import-utils.js';import{createDocument,createPatch,createUniversalAstEnvelope}from'@shapeshift-labs/frontier-lang-kernel';
2
2
  import{createNativeImportResultContract}from'./createNativeImportResultContract.js';import{createProjectImportAdmissionRecord}from'./createProjectImportAdmissionRecord.js';import{mergeSemanticIndexes}from'./mergeSemanticIndexes.js';import{summarizeNativeImportLosses}from'./summarizeNativeImportLosses.js';import{summarizeProjectSourcePreservation}from'./summarizeProjectSourcePreservation.js';
3
- import{createProjectDocumentExportSymbolResolver,createProjectModuleSymbolResolver,resolveProjectModule}from'./projectSymbolGraphModuleResolution.js';
3
+ import{createProjectDocumentExportSymbolResolver,createProjectDocumentExportSymbolsResolver,createProjectModuleSymbolResolver,resolveProjectModule}from'./projectSymbolGraphModuleResolution.js';
4
4
  import{publicContractRegionRecord}from'./projectSymbolGraphPublicContracts.js';
5
- import{isReExportImportEdge,reExportIdentityInputFromEdge,reExportIdentityRecord}from'./projectSymbolGraphReExports.js';
5
+ import{exportStarReExportIdentityRecords,isReExportImportEdge,reExportIdentityInputFromEdge,reExportIdentityRecord}from'./projectSymbolGraphReExports.js';
6
6
  export function createNativeProjectImportResult(input, imports) {
7
7
  const idPart = idFragment(input.id ?? input.projectRoot ?? 'native_project');
8
8
  const nodes = {};
@@ -156,6 +156,7 @@ function createProjectSymbolGraphSummary(semanticIndex, imports, input) {
156
156
  const moduleResolution = input.moduleResolution ?? input.tsconfig;
157
157
  const resolveTargetSymbolId = createProjectModuleSymbolResolver(semanticIndex?.symbols ?? [], documents);
158
158
  const resolveDocumentExportSymbolId = createProjectDocumentExportSymbolResolver(semanticIndex?.symbols ?? [], documents);
159
+ const resolveDocumentExportSymbols = createProjectDocumentExportSymbolsResolver(semanticIndex?.symbols ?? [], documents);
159
160
  const facts = semanticIndex?.facts ?? [];
160
161
  const moduleEdgeFacts = facts.filter((fact) => fact.predicate === 'moduleEdge');
161
162
  const moduleEdgeByRelation = new Map(moduleEdgeFacts.map((fact) => [fact.subjectId, fact]));
@@ -176,7 +177,9 @@ function createProjectSymbolGraphSummary(semanticIndex, imports, input) {
176
177
  .map((edge) => reExportIdentityRecord(reExportIdentityInputFromEdge(edge, `reexport_${idFragment(edge.id)}`), edge, resolveDocumentExportSymbolId)),
177
178
  ...importEdges
178
179
  .filter((edge) => isReExportImportEdge(edge))
179
- .map((edge) => reExportIdentityRecord(reExportIdentityInputFromEdge(edge, `reexport_${idFragment(edge.id)}`), edge, resolveDocumentExportSymbolId))
180
+ .flatMap((edge) => edge.exportStar
181
+ ? exportStarReExportIdentityRecords(edge, resolveDocumentExportSymbols(edge.targetDocumentId))
182
+ : [reExportIdentityRecord(reExportIdentityInputFromEdge(edge, `reexport_${idFragment(edge.id)}`), edge, resolveDocumentExportSymbolId)])
180
183
  ]);
181
184
  const publicContractRegions = uniqueRecords(facts
182
185
  .filter((fact) => fact.predicate === 'publicContractRegion' && fact.value)
@@ -240,14 +243,18 @@ function moduleEdgeRecord(relation, moduleEdgeByRelation, symbolsById, documents
240
243
  packageName: resolution?.packageName,
241
244
  packageSubpath: resolution?.packageSubpath,
242
245
  packageExportCondition: resolution?.packageExportCondition,
246
+ packageImportKey: resolution?.packageImportKey,
247
+ packageImportCondition: resolution?.packageImportCondition,
248
+ packageImportTarget: resolution?.packageImportTarget,
243
249
  importKind: firstString(moduleEdge.importKind, value.importKind, symbolMetadata.importKind),
244
250
  exportKind: firstString(moduleEdge.exportKind, value.exportKind, symbolMetadata.exportKind),
245
251
  importedName: firstString(moduleEdge.importedName, value.importedName, symbolMetadata.importedName),
246
252
  exportedName: firstString(moduleEdge.exportedName, value.exportedName, symbolMetadata.exportedName),
247
253
  localName: firstString(moduleEdge.localName, value.localName, symbolMetadata.localName),
248
254
  namespace: firstString(moduleEdge.namespace, value.namespace, symbolMetadata.namespace),
255
+ exportStar: firstBoolean(moduleEdge.exportStar, value.exportStar, symbolMetadata.exportStar),
249
256
  isTypeOnly: firstBoolean(moduleEdge.isTypeOnly, value.isTypeOnly),
250
- isReExport: firstBoolean(moduleEdge.isReExport, value.isReExport) ?? (relation.predicate === 'exports' && Boolean(moduleSpecifier)),
257
+ isReExport: firstBoolean(moduleEdge.isReExport, value.isReExport, symbolMetadata.reexport) ?? (relation.predicate === 'exports' && Boolean(moduleSpecifier)),
251
258
  publicContract: firstBoolean(moduleEdge.publicContract, value.publicContract, metadata.publicContract),
252
259
  evidenceIds: uniqueStrings([...(relation.evidenceIds ?? []), ...(fact?.evidenceIds ?? [])])
253
260
  };
@@ -13,6 +13,7 @@ export function resolveRelativeProjectModule(sourcePath, moduleSpecifier, docume
13
13
  export function resolveProjectModule(sourcePath, moduleSpecifier, documentsByPath, moduleResolution) {
14
14
  if (!sourcePath || !moduleSpecifier) return undefined;
15
15
  if (String(moduleSpecifier).startsWith('.')) return resolveRelativeProjectModule(sourcePath, moduleSpecifier, documentsByPath);
16
+ if (String(moduleSpecifier).startsWith('#')) return resolvePackageImportProjectModule(sourcePath, moduleSpecifier, documentsByPath, moduleResolution);
16
17
  return resolveConfiguredProjectModule(moduleSpecifier, documentsByPath, moduleResolution);
17
18
  }
18
19
 
@@ -34,6 +35,22 @@ export function createProjectDocumentExportSymbolResolver(symbols, documents) {
34
35
  };
35
36
  }
36
37
 
38
+ export function createProjectDocumentExportSymbolsResolver(symbols, documents) {
39
+ const documentsByPath = new Map(documents.filter((document) => document.path).map((document) => [document.path, document]));
40
+ const exportsByDocumentId = new Map();
41
+ for (const symbol of symbols ?? []) {
42
+ if (symbol?.kind !== 'export' || !symbol.name) continue;
43
+ const document = documentsByPath.get(symbol.definitionSpan?.path);
44
+ if (!document) continue;
45
+ const exports = exportsByDocumentId.get(document.id) ?? [];
46
+ exports.push(symbol);
47
+ exportsByDocumentId.set(document.id, exports);
48
+ }
49
+ return function resolveDocumentExports(documentId) {
50
+ return exportsByDocumentId.get(documentId) ?? [];
51
+ };
52
+ }
53
+
37
54
  function projectExportSymbolMap(symbols, documents) {
38
55
  const documentsByPath = new Map(documents.filter((document) => document.path).map((document) => [document.path, document]));
39
56
  const exportedByDocumentAndName = new Map();
@@ -58,6 +75,32 @@ function resolveConfiguredProjectModule(moduleSpecifier, documentsByPath, module
58
75
  return firstMissing ?? (packageInfo ? { kind: 'package-external', ...packageInfo } : undefined);
59
76
  }
60
77
 
78
+ function resolvePackageImportProjectModule(sourcePath, moduleSpecifier, documentsByPath, moduleResolution = {}) {
79
+ const packageContext = packageImportContext(sourcePath, moduleResolution);
80
+ const importsValue = packageContext.imports;
81
+ if (!importsValue) return { kind: 'package-import-external', packageImportKey: moduleSpecifier };
82
+ const match = packageImportMapValue(importsValue, moduleSpecifier);
83
+ if (!match) return { kind: 'package-import-external', packageImportKey: moduleSpecifier };
84
+ let firstMissing;
85
+ for (const target of exportTargetsForValue(match.value, packageConditions(moduleResolution))) {
86
+ const packageImportTarget = target.path;
87
+ if (!packageImportTarget || !String(packageImportTarget).startsWith('.')) {
88
+ return { kind: 'package-import-external', packageImportKey: match.key, packageImportCondition: target.condition, packageImportTarget };
89
+ }
90
+ const candidatePath = normalizeProjectPath(joinProjectPath(packageContext.root, packageImportTarget));
91
+ const resolved = moduleTargetDocument(candidatePath, documentsByPath);
92
+ const record = {
93
+ packageImportKey: match.key,
94
+ packageImportCondition: target.condition,
95
+ packageImportTarget,
96
+ packageName: packageContext.packageName
97
+ };
98
+ if (resolved) return { path: resolved.path, documentId: resolved.id, kind: 'package-import-source', ...record };
99
+ firstMissing ??= { path: candidatePath, kind: 'package-import-missing', ...record };
100
+ }
101
+ return firstMissing ?? { kind: 'package-import-external', packageImportKey: match.key };
102
+ }
103
+
61
104
  function configuredModuleCandidates(moduleSpecifier, moduleResolution = {}, packageInfo) {
62
105
  const compilerOptions = moduleResolution.compilerOptions ?? {};
63
106
  const baseUrl = normalizeProjectPath(moduleResolution.baseUrl ?? compilerOptions.baseUrl ?? '');
@@ -120,6 +163,31 @@ function packageExportTargets(exportsValue, subpath, conditions) {
120
163
  return exportTargetsForValue(exportMapValue(exportsValue, subpath), conditions);
121
164
  }
122
165
 
166
+ function packageImportMapValue(importsValue, moduleSpecifier) {
167
+ if (!isRecord(importsValue)) return undefined;
168
+ if (Object.prototype.hasOwnProperty.call(importsValue, moduleSpecifier)) return { key: moduleSpecifier, value: importsValue[moduleSpecifier] };
169
+ for (const [pattern, value] of Object.entries(importsValue)) {
170
+ const capture = patternCapture(moduleSpecifier, pattern);
171
+ if (capture !== undefined) return { key: pattern, value: replaceExportTargetCapture(value, capture) };
172
+ }
173
+ return undefined;
174
+ }
175
+
176
+ function packageImportContext(sourcePath, moduleResolution = {}) {
177
+ const packages = Object.entries(moduleResolution.packages ?? {})
178
+ .map(([packageName, options]) => ({
179
+ packageName,
180
+ root: normalizeProjectPath(options.root ?? ''),
181
+ imports: options.imports
182
+ }))
183
+ .filter((entry) => entry.imports && pathInsideRoot(sourcePath, entry.root))
184
+ .sort((left, right) => right.root.length - left.root.length);
185
+ return packages[0] ?? {
186
+ root: normalizeProjectPath(moduleResolution.packageRoot ?? moduleResolution.root ?? ''),
187
+ imports: moduleResolution.imports ?? moduleResolution.packageImports
188
+ };
189
+ }
190
+
123
191
  function exportMapValue(exportsValue, subpath) {
124
192
  if (!isRecord(exportsValue) || !Object.keys(exportsValue).some((key) => key.startsWith('.'))) return subpath === '.' ? exportsValue : undefined;
125
193
  return exportsValue[subpath] ?? patternExportMapValue(exportsValue, subpath);
@@ -213,7 +281,10 @@ function packageResolutionFields(candidate, packageInfo) {
213
281
  return {
214
282
  packageName: candidate.packageName ?? packageInfo?.packageName,
215
283
  packageSubpath: candidate.packageSubpath ?? packageInfo?.packageSubpath,
216
- packageExportCondition: candidate.packageExportCondition
284
+ packageExportCondition: candidate.packageExportCondition,
285
+ packageImportKey: candidate.packageImportKey,
286
+ packageImportCondition: candidate.packageImportCondition,
287
+ packageImportTarget: candidate.packageImportTarget
217
288
  };
218
289
  }
219
290
 
@@ -234,3 +305,9 @@ function normalizeProjectPath(path) {
234
305
  }
235
306
  return parts.join('/');
236
307
  }
308
+
309
+ function pathInsideRoot(sourcePath, root) {
310
+ if (!root) return true;
311
+ const normalized = normalizeProjectPath(sourcePath);
312
+ return normalized === root || normalized.startsWith(`${root}/`);
313
+ }
@@ -15,7 +15,7 @@ export function reExportIdentityRecord(identity, edge, resolveDocumentExportSymb
15
15
  }
16
16
 
17
17
  export function isReExportImportEdge(edge) {
18
- return edge.importKind === 'reexport' || edge.importKind === 'namespace-reexport';
18
+ return edge.importKind === 'reexport' || edge.importKind === 'namespace-reexport' || edge.exportStar === true;
19
19
  }
20
20
 
21
21
  export function reExportIdentityInputFromEdge(edge, id) {
@@ -31,6 +31,32 @@ export function reExportIdentityInputFromEdge(edge, id) {
31
31
  });
32
32
  }
33
33
 
34
+ export function exportStarReExportIdentityRecords(edge, targetExports) {
35
+ if (!edge?.exportStar || !edge.targetDocumentId) return [];
36
+ return targetExports
37
+ .filter((symbol) => symbol.name && symbol.name !== 'default')
38
+ .map((symbol) => compactRecord({
39
+ id: `reexport_star_${idFragment(edge.id)}_${idFragment(symbol.id)}`,
40
+ sourceDocumentId: edge.sourceDocumentId,
41
+ sourcePath: edge.sourcePath,
42
+ sourceHash: edge.sourceHash,
43
+ moduleSpecifier: edge.moduleSpecifier,
44
+ symbolId: edge.targetSymbolId,
45
+ relationId: edge.id,
46
+ importedName: symbol.name,
47
+ exportedName: symbol.name,
48
+ originSymbolId: symbol.id,
49
+ exportedSymbolId: symbol.id,
50
+ localSymbolId: edge.targetSymbolId,
51
+ isExportStar: true,
52
+ publicContract: edge.publicContract
53
+ }));
54
+ }
55
+
56
+ function idFragment(value) {
57
+ return String(value ?? '').toLowerCase().replace(/[^a-z0-9]+/g, '_').replace(/^_+|_+$/g, '').slice(0, 80) || 'id';
58
+ }
59
+
34
60
  function compactRecord(record) {
35
61
  return Object.fromEntries(Object.entries(record).filter(([, value]) => value !== undefined));
36
62
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shapeshift-labs/frontier-lang-compiler",
3
- "version": "0.2.115",
3
+ "version": "0.2.117",
4
4
  "description": "Compiler facade for Frontier Lang source documents and language projection adapters.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",