@shapeshift-labs/frontier-lang-compiler 0.2.111 → 0.2.113
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 +31 -0
- package/dist/declarations/js-ts-safe-project-merge.d.ts +3 -0
- package/dist/declarations/native-project-module-resolution.d.ts +28 -0
- package/dist/declarations/native-project.d.ts +10 -10
- package/dist/index.d.ts +1 -0
- package/dist/internal/index-impl/createNativeProjectImportResult.js +9 -8
- package/dist/internal/index-impl/projectSymbolGraphModuleResolution.js +165 -1
- package/dist/js-ts-safe-project-merge-graph.js +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -198,6 +198,7 @@ import { safeMergeJsTsProject } from '@shapeshift-labs/frontier-lang-compiler';
|
|
|
198
198
|
|
|
199
199
|
const project = safeMergeJsTsProject({
|
|
200
200
|
language: 'typescript',
|
|
201
|
+
moduleResolution: { baseUrl: '.', paths: { '@app/*': ['src/*'] } },
|
|
201
202
|
baseFiles: { 'src/index.ts': 'export const stable = 1;\n' },
|
|
202
203
|
workerFiles: { 'src/index.ts': 'export const stable = 1;\nexport const workerOnly = 1;\n' },
|
|
203
204
|
headFiles: { 'src/index.ts': 'export const stable = 1;\n' }
|
|
@@ -208,6 +209,35 @@ console.log(project.outputFiles[0].sourcePath); // "src/index.ts"
|
|
|
208
209
|
console.log(project.files[0].semanticArtifacts.status); // "verified"
|
|
209
210
|
```
|
|
210
211
|
|
|
212
|
+
When `includeOutputProjectSymbolGraph` is enabled, the same
|
|
213
|
+
`moduleResolution` shape is used for output graph artifacts. Resolution is
|
|
214
|
+
runtime-neutral: `baseUrl`, `paths`, `aliases`, and `compilerOptions.paths`
|
|
215
|
+
are matched against the supplied project files, not the host filesystem.
|
|
216
|
+
Bare package imports also get explicit package identity. If `packages` is
|
|
217
|
+
provided, package export maps can resolve back to supplied workspace sources
|
|
218
|
+
and record the selected export condition:
|
|
219
|
+
|
|
220
|
+
```js
|
|
221
|
+
const project = safeMergeJsTsProject({
|
|
222
|
+
includeOutputProjectSymbolGraph: true,
|
|
223
|
+
moduleResolution: {
|
|
224
|
+
packages: {
|
|
225
|
+
'@pkg/core': {
|
|
226
|
+
root: 'packages/core',
|
|
227
|
+
exports: { './utils': { import: './src/utils.ts', default: './dist/utils.js' } }
|
|
228
|
+
}
|
|
229
|
+
},
|
|
230
|
+
packageExportConditions: ['import', 'default']
|
|
231
|
+
},
|
|
232
|
+
baseFiles,
|
|
233
|
+
workerFiles,
|
|
234
|
+
headFiles
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
console.log(project.outputProjectSymbolGraph.importEdges[0].packageName); // "@pkg/core"
|
|
238
|
+
console.log(project.outputProjectSymbolGraph.importEdges[0].packageExportCondition); // "import"
|
|
239
|
+
```
|
|
240
|
+
|
|
211
241
|
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.
|
|
212
242
|
|
|
213
243
|
```js
|
|
@@ -817,6 +847,7 @@ const imported = await runNativeImporterAdapter(babelAdapter, {
|
|
|
817
847
|
|
|
818
848
|
const project = await importNativeProject({
|
|
819
849
|
projectRoot: 'src',
|
|
850
|
+
moduleResolution: { baseUrl: '.', paths: { '@app/*': ['src/*'] } },
|
|
820
851
|
adapters: [babelAdapter, pythonAstAdapter, rustSynAdapter, clangAstAdapter, goAstAdapter, javaAstAdapter, kotlinPsiAdapter, csharpRoslynAdapter, swiftSyntaxAdapter],
|
|
821
852
|
sources: [
|
|
822
853
|
{ language: 'typescript', adapter: babelAdapter.id, sourcePath: 'src/todo.ts', sourceText },
|
|
@@ -8,6 +8,7 @@ import type {
|
|
|
8
8
|
} from './js-ts-safe-merge.js';
|
|
9
9
|
import type { JsTsSafeMemberMergePolicy, JsTsSafeMemberMergePolicyRegion } from './js-ts-safe-member-merge.js';
|
|
10
10
|
import type { NativeProjectImportResult, NativeProjectSymbolGraphSummary } from './native-project.js';
|
|
11
|
+
import type { NativeProjectModuleResolutionOptions } from './native-project-module-resolution.js';
|
|
11
12
|
|
|
12
13
|
export type JsTsProjectSafeMergeStatus = 'merged' | 'blocked';
|
|
13
14
|
export type JsTsProjectSafeMergeFileStatus = 'merged' | 'blocked';
|
|
@@ -55,6 +56,8 @@ export interface JsTsProjectSafeMergeInput {
|
|
|
55
56
|
readonly allowFileAdditions?: boolean;
|
|
56
57
|
readonly allowFileDeletes?: boolean;
|
|
57
58
|
readonly includeOutputProjectSymbolGraph?: boolean;
|
|
59
|
+
readonly moduleResolution?: NativeProjectModuleResolutionOptions;
|
|
60
|
+
readonly tsconfig?: NativeProjectModuleResolutionOptions;
|
|
58
61
|
readonly workerChangeSetId?: string;
|
|
59
62
|
readonly headChangeSetId?: string;
|
|
60
63
|
readonly policy?: JsTsSafeMemberMergePolicy | readonly JsTsSafeMemberMergePolicyRegion[];
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export type NativeProjectModuleResolutionPaths = Readonly<Record<string, readonly string[] | string>>;
|
|
2
|
+
export type NativeProjectPackageExportTarget = string | readonly string[] | NativeProjectPackageConditionalExports;
|
|
3
|
+
export type NativeProjectPackageExports = NativeProjectPackageExportTarget | Readonly<Record<string, NativeProjectPackageExportTarget>>;
|
|
4
|
+
|
|
5
|
+
export interface NativeProjectPackageConditionalExports {
|
|
6
|
+
readonly [condition: string]: NativeProjectPackageExportTarget;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface NativeProjectPackageResolutionOptions {
|
|
10
|
+
readonly root?: string;
|
|
11
|
+
readonly sourceRoot?: string;
|
|
12
|
+
readonly main?: string;
|
|
13
|
+
readonly types?: string;
|
|
14
|
+
readonly exports?: NativeProjectPackageExports;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface NativeProjectModuleResolutionOptions {
|
|
18
|
+
readonly baseUrl?: string;
|
|
19
|
+
readonly paths?: NativeProjectModuleResolutionPaths;
|
|
20
|
+
readonly aliases?: NativeProjectModuleResolutionPaths;
|
|
21
|
+
readonly packages?: Readonly<Record<string, NativeProjectPackageResolutionOptions>>;
|
|
22
|
+
readonly conditions?: readonly string[];
|
|
23
|
+
readonly packageExportConditions?: readonly string[];
|
|
24
|
+
readonly compilerOptions?: {
|
|
25
|
+
readonly baseUrl?: string;
|
|
26
|
+
readonly paths?: NativeProjectModuleResolutionPaths;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
@@ -49,11 +49,11 @@ import type { JavaScriptNativeImporterAdapterOptions, TypeScriptCompilerNativeIm
|
|
|
49
49
|
import type { JavaAstNativeImporterAdapterOptions, KotlinPsiNativeImporterAdapterOptions, CSharpRoslynNativeImporterAdapterOptions, SwiftSyntaxNativeImporterAdapterOptions, TreeSitterNativeImporterAdapterOptions } from './import-adapter-options-platform.js';
|
|
50
50
|
import type { NativeTargetProjectionAdapterCoverageInput, NativeTargetProjectionAdapterSummary, NativeTargetProjectionAdapterInput, NativeTargetProjectionAdapterResult, NativeTargetProjectionAdapter, NativeTargetProjectionAdapterResolverInput, NativeTargetProjectionResult } from './target-adapters.js';
|
|
51
51
|
import type { NativeImportRoundtripReadinessStatus, NativeImportRoundtripReadinessOptions, NativeImportRoundtripReadinessClassification } from './roundtrip.js';
|
|
52
|
+
import type { NativeProjectModuleResolutionOptions } from './native-project-module-resolution.js';
|
|
52
53
|
|
|
53
54
|
export interface NativeProjectSourceInput extends ImportNativeSourceOptions {
|
|
54
55
|
readonly adapter?: NativeImporterAdapter | string;
|
|
55
|
-
readonly adapterOptions?: Record<string, unknown>;
|
|
56
|
-
readonly adapterMetadata?: Record<string, unknown>;
|
|
56
|
+
readonly adapterOptions?: Record<string, unknown>; readonly adapterMetadata?: Record<string, unknown>;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
export interface ImportNativeProjectOptions {
|
|
@@ -70,17 +70,15 @@ export interface ImportNativeProjectOptions {
|
|
|
70
70
|
readonly patchId?: string;
|
|
71
71
|
readonly author?: string;
|
|
72
72
|
readonly metadata?: Record<string, unknown>;
|
|
73
|
-
readonly
|
|
74
|
-
readonly
|
|
73
|
+
readonly moduleResolution?: NativeProjectModuleResolutionOptions;
|
|
74
|
+
readonly tsconfig?: NativeProjectModuleResolutionOptions;
|
|
75
|
+
readonly adapterOptions?: Record<string, unknown>; readonly adapterMetadata?: Record<string, unknown>;
|
|
75
76
|
readonly adapters?: readonly NativeImporterAdapter[];
|
|
76
77
|
readonly adapterResolver?: (source: NativeProjectSourceInput, adapters: readonly NativeImporterAdapter[]) => NativeImporterAdapter | undefined;
|
|
77
78
|
readonly sources: readonly NativeProjectSourceInput[];
|
|
78
79
|
}
|
|
79
80
|
|
|
80
81
|
export type NativeProjectSymbolGraphRemainingField =
|
|
81
|
-
| 'moduleEdges[].resolutionKind'
|
|
82
|
-
| 'moduleEdges[].packageName'
|
|
83
|
-
| 'moduleEdges[].packageExportCondition'
|
|
84
82
|
| 'reExportIdentities[].originSymbolId'
|
|
85
83
|
| 'reExportIdentities[].exportedSymbolId'
|
|
86
84
|
| 'reExportIdentities[].localSymbolId'
|
|
@@ -112,13 +110,15 @@ export interface NativeProjectSymbolGraphModuleEdgeRecord {
|
|
|
112
110
|
readonly resolvedModulePath?: string;
|
|
113
111
|
readonly targetDocumentId?: string;
|
|
114
112
|
readonly resolvedTargetSymbolId?: string;
|
|
115
|
-
readonly resolutionKind?: 'relative-source' | 'relative-missing' | string;
|
|
113
|
+
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;
|
|
114
|
+
readonly packageName?: string;
|
|
115
|
+
readonly packageSubpath?: string;
|
|
116
|
+
readonly packageExportCondition?: string;
|
|
116
117
|
readonly importKind?: string;
|
|
117
118
|
readonly exportKind?: string;
|
|
118
119
|
readonly importedName?: string;
|
|
119
120
|
readonly exportedName?: string;
|
|
120
|
-
readonly localName?: string;
|
|
121
|
-
readonly namespace?: string;
|
|
121
|
+
readonly localName?: string; readonly namespace?: string;
|
|
122
122
|
readonly isTypeOnly?: boolean;
|
|
123
123
|
readonly isReExport?: boolean;
|
|
124
124
|
readonly publicContract?: boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -40,6 +40,7 @@ export * from './declarations/import-adapter-options-native.js';
|
|
|
40
40
|
export * from './declarations/import-adapter-options-platform.js';
|
|
41
41
|
export * from './declarations/target-adapters.js';
|
|
42
42
|
export * from './declarations/native-project-admission.js';
|
|
43
|
+
export * from './declarations/native-project-module-resolution.js';
|
|
43
44
|
export * from './declarations/native-project.js';
|
|
44
45
|
export * from './declarations/roundtrip.js';
|
|
45
46
|
export * from './declarations/runtime.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
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{createProjectModuleSymbolResolver,
|
|
3
|
+
import{createProjectModuleSymbolResolver,resolveProjectModule}from'./projectSymbolGraphModuleResolution.js';
|
|
4
4
|
export function createNativeProjectImportResult(input, imports) {
|
|
5
5
|
const idPart = idFragment(input.id ?? input.projectRoot ?? 'native_project');
|
|
6
6
|
const nodes = {};
|
|
@@ -141,9 +141,6 @@ export function createNativeProjectImportResult(input, imports) {
|
|
|
141
141
|
}
|
|
142
142
|
|
|
143
143
|
const PROJECT_SYMBOL_GRAPH_REMAINING_FIELDS = Object.freeze([
|
|
144
|
-
'moduleEdges[].resolutionKind',
|
|
145
|
-
'moduleEdges[].packageName',
|
|
146
|
-
'moduleEdges[].packageExportCondition',
|
|
147
144
|
'reExportIdentities[].originSymbolId',
|
|
148
145
|
'reExportIdentities[].exportedSymbolId',
|
|
149
146
|
'reExportIdentities[].localSymbolId',
|
|
@@ -157,6 +154,7 @@ function createProjectSymbolGraphSummary(semanticIndex, imports, input) {
|
|
|
157
154
|
const symbolsById = new Map((semanticIndex?.symbols ?? []).map((symbol) => [symbol.id, symbol]));
|
|
158
155
|
const documentsById = new Map(documents.map((document) => [document.id, document]));
|
|
159
156
|
const documentsByPath = new Map(documents.filter((document) => document.path).map((document) => [document.path, document]));
|
|
157
|
+
const moduleResolution = input.moduleResolution ?? input.tsconfig;
|
|
160
158
|
const resolveTargetSymbolId = createProjectModuleSymbolResolver(semanticIndex?.symbols ?? [], documents);
|
|
161
159
|
const facts = semanticIndex?.facts ?? [];
|
|
162
160
|
const moduleEdgeFacts = facts.filter((fact) => fact.predicate === 'moduleEdge');
|
|
@@ -164,10 +162,10 @@ function createProjectSymbolGraphSummary(semanticIndex, imports, input) {
|
|
|
164
162
|
const relations = semanticIndex?.relations ?? [];
|
|
165
163
|
const importEdges = relations
|
|
166
164
|
.filter((relation) => relation.predicate === 'imports')
|
|
167
|
-
.map((relation) => moduleEdgeRecord(relation, moduleEdgeByRelation, symbolsById, documentsById, documentsByPath, resolveTargetSymbolId));
|
|
165
|
+
.map((relation) => moduleEdgeRecord(relation, moduleEdgeByRelation, symbolsById, documentsById, documentsByPath, moduleResolution, resolveTargetSymbolId));
|
|
168
166
|
const exportEdges = relations
|
|
169
167
|
.filter((relation) => relation.predicate === 'exports')
|
|
170
|
-
.map((relation) => moduleEdgeRecord(relation, moduleEdgeByRelation, symbolsById, documentsById, documentsByPath, resolveTargetSymbolId));
|
|
168
|
+
.map((relation) => moduleEdgeRecord(relation, moduleEdgeByRelation, symbolsById, documentsById, documentsByPath, moduleResolution, resolveTargetSymbolId));
|
|
171
169
|
const reExportIdentities = uniqueRecords([
|
|
172
170
|
...facts
|
|
173
171
|
.filter((fact) => fact.predicate === 'reExportIdentity' && fact.value)
|
|
@@ -213,7 +211,7 @@ function createProjectSymbolGraphSummary(semanticIndex, imports, input) {
|
|
|
213
211
|
};
|
|
214
212
|
}
|
|
215
213
|
|
|
216
|
-
function moduleEdgeRecord(relation, moduleEdgeByRelation, symbolsById, documentsById, documentsByPath, resolveTargetSymbolId) {
|
|
214
|
+
function moduleEdgeRecord(relation, moduleEdgeByRelation, symbolsById, documentsById, documentsByPath, moduleResolution, resolveTargetSymbolId) {
|
|
217
215
|
const fact = moduleEdgeByRelation.get(relation.id);
|
|
218
216
|
const value = objectValue(fact?.value);
|
|
219
217
|
const metadata = objectValue(relation.metadata);
|
|
@@ -231,7 +229,7 @@ function moduleEdgeRecord(relation, moduleEdgeByRelation, symbolsById, documents
|
|
|
231
229
|
symbolMetadata.source,
|
|
232
230
|
symbol?.kind === 'module' ? symbol.name : undefined
|
|
233
231
|
);
|
|
234
|
-
const resolution =
|
|
232
|
+
const resolution = resolveProjectModule(document?.path, moduleSpecifier, documentsByPath, moduleResolution);
|
|
235
233
|
const record = {
|
|
236
234
|
id: relation.id,
|
|
237
235
|
sourceDocumentId: relation.sourceId,
|
|
@@ -244,6 +242,9 @@ function moduleEdgeRecord(relation, moduleEdgeByRelation, symbolsById, documents
|
|
|
244
242
|
resolvedModulePath: resolution?.path,
|
|
245
243
|
targetDocumentId: resolution?.documentId,
|
|
246
244
|
resolutionKind: resolution?.kind,
|
|
245
|
+
packageName: resolution?.packageName,
|
|
246
|
+
packageSubpath: resolution?.packageSubpath,
|
|
247
|
+
packageExportCondition: resolution?.packageExportCondition,
|
|
247
248
|
importKind: firstString(moduleEdge.importKind, value.importKind, symbolMetadata.importKind),
|
|
248
249
|
exportKind: firstString(moduleEdge.exportKind, value.exportKind, symbolMetadata.exportKind),
|
|
249
250
|
importedName: firstString(moduleEdge.importedName, value.importedName, symbolMetadata.importedName),
|
|
@@ -10,6 +10,12 @@ export function resolveRelativeProjectModule(sourcePath, moduleSpecifier, docume
|
|
|
10
10
|
};
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
export function resolveProjectModule(sourcePath, moduleSpecifier, documentsByPath, moduleResolution) {
|
|
14
|
+
if (!sourcePath || !moduleSpecifier) return undefined;
|
|
15
|
+
if (String(moduleSpecifier).startsWith('.')) return resolveRelativeProjectModule(sourcePath, moduleSpecifier, documentsByPath);
|
|
16
|
+
return resolveConfiguredProjectModule(moduleSpecifier, documentsByPath, moduleResolution);
|
|
17
|
+
}
|
|
18
|
+
|
|
13
19
|
export function createProjectModuleSymbolResolver(symbols, documents) {
|
|
14
20
|
const documentsByPath = new Map(documents.filter((document) => document.path).map((document) => [document.path, document]));
|
|
15
21
|
const exportedByDocumentAndName = new Map();
|
|
@@ -27,6 +33,115 @@ export function createProjectModuleSymbolResolver(symbols, documents) {
|
|
|
27
33
|
};
|
|
28
34
|
}
|
|
29
35
|
|
|
36
|
+
function resolveConfiguredProjectModule(moduleSpecifier, documentsByPath, moduleResolution) {
|
|
37
|
+
const packageInfo = packageSpecifierInfo(moduleSpecifier);
|
|
38
|
+
const candidates = configuredModuleCandidates(moduleSpecifier, moduleResolution, packageInfo);
|
|
39
|
+
let firstMissing;
|
|
40
|
+
for (const candidate of candidates) {
|
|
41
|
+
const target = moduleTargetDocument(candidate.path, documentsByPath);
|
|
42
|
+
const packageFields = packageResolutionFields(candidate, packageInfo);
|
|
43
|
+
if (target) return { path: target.path, documentId: target.id, kind: `${candidate.kind}-source`, ...packageFields };
|
|
44
|
+
firstMissing ??= { path: candidate.path, kind: `${candidate.kind}-missing`, ...packageFields };
|
|
45
|
+
}
|
|
46
|
+
return firstMissing ?? (packageInfo ? { kind: 'package-external', ...packageInfo } : undefined);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function configuredModuleCandidates(moduleSpecifier, moduleResolution = {}, packageInfo) {
|
|
50
|
+
const compilerOptions = moduleResolution.compilerOptions ?? {};
|
|
51
|
+
const baseUrl = normalizeProjectPath(moduleResolution.baseUrl ?? compilerOptions.baseUrl ?? '');
|
|
52
|
+
return uniquePaths([
|
|
53
|
+
...aliasCandidates(moduleSpecifier, moduleResolution.aliases, 'alias', baseUrl),
|
|
54
|
+
...aliasCandidates(moduleSpecifier, moduleResolution.paths ?? compilerOptions.paths, 'path-alias', baseUrl),
|
|
55
|
+
...packageCandidates(packageInfo, moduleResolution),
|
|
56
|
+
...baseUrlCandidates(moduleSpecifier, baseUrl)
|
|
57
|
+
]);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function aliasCandidates(moduleSpecifier, aliases, kind, baseUrl) {
|
|
61
|
+
return Object.entries(aliases ?? {}).flatMap(([pattern, targetPatterns]) => {
|
|
62
|
+
const capture = patternCapture(moduleSpecifier, pattern);
|
|
63
|
+
if (capture === undefined) return [];
|
|
64
|
+
const targets = Array.isArray(targetPatterns) ? targetPatterns : [targetPatterns];
|
|
65
|
+
return targets.map((targetPattern) => ({
|
|
66
|
+
kind,
|
|
67
|
+
path: normalizeProjectPath(joinProjectPath(baseUrl, String(targetPattern).replace('*', capture)))
|
|
68
|
+
}));
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function baseUrlCandidates(moduleSpecifier, baseUrl) {
|
|
73
|
+
if (!baseUrl || String(moduleSpecifier).startsWith('@')) return [];
|
|
74
|
+
return [{ kind: 'base-url', path: normalizeProjectPath(joinProjectPath(baseUrl, moduleSpecifier)) }];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function packageCandidates(packageInfo, moduleResolution = {}) {
|
|
78
|
+
if (!packageInfo) return [];
|
|
79
|
+
const options = moduleResolution.packages?.[packageInfo.packageName];
|
|
80
|
+
if (!options) return [];
|
|
81
|
+
const root = normalizeProjectPath(options.root ?? '');
|
|
82
|
+
const subpath = packageInfo.packageSubpath === '.' ? '' : packageInfo.packageSubpath.slice(2);
|
|
83
|
+
return uniquePaths([
|
|
84
|
+
...packageExportCandidates(packageInfo, options, moduleResolution).map((candidate) => ({
|
|
85
|
+
...candidate,
|
|
86
|
+
path: normalizeProjectPath(joinProjectPath(root, candidate.path))
|
|
87
|
+
})),
|
|
88
|
+
...packageFallbackTargets(options, subpath).map((path) => ({
|
|
89
|
+
kind: 'package',
|
|
90
|
+
path: normalizeProjectPath(joinProjectPath(root, path)),
|
|
91
|
+
...packageInfo
|
|
92
|
+
}))
|
|
93
|
+
]);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function packageExportCandidates(packageInfo, options, moduleResolution) {
|
|
97
|
+
const targets = packageExportTargets(options.exports, packageInfo.packageSubpath, packageConditions(moduleResolution));
|
|
98
|
+
return targets.map((target) => ({
|
|
99
|
+
kind: 'package',
|
|
100
|
+
path: target.path,
|
|
101
|
+
packageExportCondition: target.condition,
|
|
102
|
+
...packageInfo
|
|
103
|
+
}));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function packageExportTargets(exportsValue, subpath, conditions) {
|
|
107
|
+
if (!exportsValue) return [];
|
|
108
|
+
return exportTargetsForValue(exportMapValue(exportsValue, subpath), conditions);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function exportMapValue(exportsValue, subpath) {
|
|
112
|
+
if (!isRecord(exportsValue) || !Object.keys(exportsValue).some((key) => key.startsWith('.'))) return subpath === '.' ? exportsValue : undefined;
|
|
113
|
+
return exportsValue[subpath] ?? patternExportMapValue(exportsValue, subpath);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function patternExportMapValue(exportsValue, subpath) {
|
|
117
|
+
for (const [pattern, target] of Object.entries(exportsValue)) {
|
|
118
|
+
const capture = patternCapture(subpath, pattern);
|
|
119
|
+
if (capture !== undefined) return replaceExportTargetCapture(target, capture);
|
|
120
|
+
}
|
|
121
|
+
return undefined;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function replaceExportTargetCapture(target, capture) {
|
|
125
|
+
if (typeof target === 'string') return target.replace('*', capture);
|
|
126
|
+
if (Array.isArray(target)) return target.map((entry) => replaceExportTargetCapture(entry, capture));
|
|
127
|
+
if (!isRecord(target)) return target;
|
|
128
|
+
return Object.fromEntries(Object.entries(target).map(([key, value]) => [key, replaceExportTargetCapture(value, capture)]));
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function exportTargetsForValue(value, conditions, condition) {
|
|
132
|
+
if (!value) return [];
|
|
133
|
+
if (typeof value === 'string') return [{ path: value, condition }];
|
|
134
|
+
if (Array.isArray(value)) return value.flatMap((entry) => exportTargetsForValue(entry, conditions, condition));
|
|
135
|
+
if (!isRecord(value)) return [];
|
|
136
|
+
return conditions.flatMap((key) => exportTargetsForValue(value[key], conditions, key));
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function packageFallbackTargets(options, subpath) {
|
|
140
|
+
const sourceRoot = normalizeProjectPath(options.sourceRoot ?? 'src');
|
|
141
|
+
if (subpath) return [joinProjectPath(sourceRoot, subpath), subpath];
|
|
142
|
+
return [options.types, options.main, joinProjectPath(sourceRoot, 'index')].filter(Boolean);
|
|
143
|
+
}
|
|
144
|
+
|
|
30
145
|
function moduleTargetDocument(path, documentsByPath) {
|
|
31
146
|
for (const candidate of modulePathCandidates(path)) {
|
|
32
147
|
const document = documentsByPath.get(candidate);
|
|
@@ -36,7 +151,7 @@ function moduleTargetDocument(path, documentsByPath) {
|
|
|
36
151
|
}
|
|
37
152
|
|
|
38
153
|
function modulePathCandidates(path) {
|
|
39
|
-
return [path, `${path}.js`, `${path}.ts`, `${path}.tsx`, `${path}.jsx`, `${path}/index.js`, `${path}/index.ts`];
|
|
154
|
+
return [path, `${path}.js`, `${path}.ts`, `${path}.tsx`, `${path}.jsx`, `${path}.d.ts`, `${path}/index.js`, `${path}/index.ts`, `${path}/index.d.ts`];
|
|
40
155
|
}
|
|
41
156
|
|
|
42
157
|
function targetExportName(edge) {
|
|
@@ -49,6 +164,55 @@ function symbolKey(documentId, name) {
|
|
|
49
164
|
return `${documentId}\u0000${name}`;
|
|
50
165
|
}
|
|
51
166
|
|
|
167
|
+
function patternCapture(value, pattern) {
|
|
168
|
+
if (pattern === value) return '';
|
|
169
|
+
if (!String(pattern).includes('*')) return undefined;
|
|
170
|
+
const [prefix, suffix = ''] = String(pattern).split('*');
|
|
171
|
+
if (!String(value).startsWith(prefix) || !String(value).endsWith(suffix)) return undefined;
|
|
172
|
+
return String(value).slice(prefix.length, String(value).length - suffix.length);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function uniquePaths(candidates) {
|
|
176
|
+
const seen = new Set();
|
|
177
|
+
return candidates.filter((candidate) => {
|
|
178
|
+
if (!candidate.path || seen.has(candidate.path)) return false;
|
|
179
|
+
seen.add(candidate.path);
|
|
180
|
+
return true;
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function joinProjectPath(left, right) {
|
|
185
|
+
return left ? `${left}/${right}` : String(right);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function packageSpecifierInfo(moduleSpecifier) {
|
|
189
|
+
if (!moduleSpecifier || String(moduleSpecifier).startsWith('#')) return undefined;
|
|
190
|
+
const parts = String(moduleSpecifier).split('/');
|
|
191
|
+
if (!parts[0] || parts[0] === '.' || parts[0] === '..') return undefined;
|
|
192
|
+
const scoped = parts[0].startsWith('@');
|
|
193
|
+
if (scoped && parts.length < 2) return undefined;
|
|
194
|
+
const packageName = scoped ? `${parts[0]}/${parts[1]}` : parts[0];
|
|
195
|
+
const rest = parts.slice(scoped ? 2 : 1).join('/');
|
|
196
|
+
return { packageName, packageSubpath: rest ? `./${rest}` : '.' };
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function packageResolutionFields(candidate, packageInfo) {
|
|
200
|
+
if (!candidate.packageName && candidate.kind !== 'package') return {};
|
|
201
|
+
return {
|
|
202
|
+
packageName: candidate.packageName ?? packageInfo?.packageName,
|
|
203
|
+
packageSubpath: candidate.packageSubpath ?? packageInfo?.packageSubpath,
|
|
204
|
+
packageExportCondition: candidate.packageExportCondition
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function packageConditions(moduleResolution = {}) {
|
|
209
|
+
return moduleResolution.packageExportConditions ?? moduleResolution.conditions ?? ['types', 'import', 'module', 'require', 'default'];
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function isRecord(value) {
|
|
213
|
+
return value && typeof value === 'object' && !Array.isArray(value);
|
|
214
|
+
}
|
|
215
|
+
|
|
52
216
|
function normalizeProjectPath(path) {
|
|
53
217
|
const parts = [];
|
|
54
218
|
for (const part of String(path).split('/')) {
|
|
@@ -14,6 +14,7 @@ function createJsTsProjectSafeMergeGraphArtifacts(input, outputFiles, mergeId) {
|
|
|
14
14
|
const projectImport = createNativeProjectImportResult({
|
|
15
15
|
id: `${mergeId}_output_project_import`,
|
|
16
16
|
projectRoot: input.projectRoot,
|
|
17
|
+
moduleResolution: input.moduleResolution ?? input.tsconfig,
|
|
17
18
|
sources,
|
|
18
19
|
metadata: {
|
|
19
20
|
projectSafeMergeId: mergeId,
|
package/package.json
CHANGED