@beignet/cli 0.0.48 → 0.0.49
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/CHANGELOG.md +34 -0
- package/README.md +76 -21
- package/dist/analysis/contract-factories.d.ts +17 -0
- package/dist/analysis/contract-factories.d.ts.map +1 -0
- package/dist/analysis/contract-factories.js +176 -0
- package/dist/analysis/contract-factories.js.map +1 -0
- package/dist/analysis/layers.d.ts +5 -0
- package/dist/analysis/layers.d.ts.map +1 -0
- package/dist/analysis/layers.js +172 -0
- package/dist/analysis/layers.js.map +1 -0
- package/dist/analysis/port-wiring.d.ts +23 -0
- package/dist/analysis/port-wiring.d.ts.map +1 -0
- package/dist/analysis/port-wiring.js +379 -0
- package/dist/analysis/port-wiring.js.map +1 -0
- package/dist/analysis/source-index.d.ts +5 -0
- package/dist/analysis/source-index.d.ts.map +1 -1
- package/dist/analysis/source-index.js +171 -42
- package/dist/analysis/source-index.js.map +1 -1
- package/dist/analysis/workspace.d.ts +10 -4
- package/dist/analysis/workspace.d.ts.map +1 -1
- package/dist/analysis/workspace.js +66 -6
- package/dist/analysis/workspace.js.map +1 -1
- package/dist/app-map.d.ts.map +1 -1
- package/dist/app-map.js +311 -92
- package/dist/app-map.js.map +1 -1
- package/dist/check.js +37 -3
- package/dist/check.js.map +1 -1
- package/dist/explain.js +4 -4
- package/dist/explain.js.map +1 -1
- package/dist/inspect.d.ts.map +1 -1
- package/dist/inspect.js +415 -168
- package/dist/inspect.js.map +1 -1
- package/dist/lint.d.ts.map +1 -1
- package/dist/lint.js +309 -487
- package/dist/lint.js.map +1 -1
- package/dist/make/inbox.d.ts.map +1 -1
- package/dist/make/inbox.js +11 -4
- package/dist/make/inbox.js.map +1 -1
- package/dist/make/payments.js +2 -2
- package/dist/make.d.ts.map +1 -1
- package/dist/make.js +144 -8
- package/dist/make.js.map +1 -1
- package/dist/mcp.d.ts +1 -1
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +19 -19
- package/dist/mcp.js.map +1 -1
- package/dist/provider-add.d.ts.map +1 -1
- package/dist/provider-add.js +142 -7
- package/dist/provider-add.js.map +1 -1
- package/dist/registry-edits.d.ts +7 -0
- package/dist/registry-edits.d.ts.map +1 -1
- package/dist/registry-edits.js +237 -53
- package/dist/registry-edits.js.map +1 -1
- package/dist/templates/agents.d.ts.map +1 -1
- package/dist/templates/agents.js +16 -0
- package/dist/templates/agents.js.map +1 -1
- package/dist/templates/base.d.ts.map +1 -1
- package/dist/templates/base.js +9 -1
- package/dist/templates/base.js.map +1 -1
- package/dist/templates/server.d.ts.map +1 -1
- package/dist/templates/server.js +2 -0
- package/dist/templates/server.js.map +1 -1
- package/dist/templates/shared.d.ts +1 -0
- package/dist/templates/shared.d.ts.map +1 -1
- package/dist/templates/shared.js +3 -2
- package/dist/templates/shared.js.map +1 -1
- package/package.json +7 -6
- package/skills/app-structure/SKILL.md +46 -5
- package/src/analysis/contract-factories.ts +256 -0
- package/src/analysis/layers.ts +266 -0
- package/src/analysis/port-wiring.ts +506 -0
- package/src/analysis/source-index.ts +225 -57
- package/src/analysis/workspace.ts +115 -6
- package/src/app-map.ts +418 -109
- package/src/check.ts +51 -3
- package/src/explain.ts +4 -4
- package/src/inspect.ts +583 -215
- package/src/lint.ts +393 -643
- package/src/make/inbox.ts +11 -4
- package/src/make/payments.ts +2 -2
- package/src/make.ts +225 -8
- package/src/mcp.ts +19 -22
- package/src/provider-add.ts +186 -7
- package/src/registry-edits.ts +313 -63
- package/src/templates/agents.ts +16 -0
- package/src/templates/base.ts +9 -1
- package/src/templates/server.ts +2 -0
- package/src/templates/shared.ts +3 -2
|
@@ -27,12 +27,19 @@ export type LocalImportReference = {
|
|
|
27
27
|
column: number;
|
|
28
28
|
};
|
|
29
29
|
|
|
30
|
+
export type ModuleReference = LocalImportReference & {
|
|
31
|
+
syntax: "dynamic-import" | "export" | "import" | "import-equals" | "require";
|
|
32
|
+
staticallyResolvable: boolean;
|
|
33
|
+
};
|
|
34
|
+
|
|
30
35
|
type ImportBinding =
|
|
31
36
|
| { kind: "named"; file: string; exportName: string }
|
|
32
37
|
| { kind: "namespace"; file: string };
|
|
33
38
|
|
|
34
39
|
type FileIndex = {
|
|
35
40
|
declarations: Map<string, ts.Declaration>;
|
|
41
|
+
localExports: Map<string, string>;
|
|
42
|
+
locals: Map<string, ts.Declaration>;
|
|
36
43
|
imports: Map<string, ImportBinding>;
|
|
37
44
|
reexports: Map<string, { file: string; exportName: string }>;
|
|
38
45
|
exportStars: string[];
|
|
@@ -68,6 +75,8 @@ export function createSourceIndex(workspace: AnalysisWorkspace): SourceIndex {
|
|
|
68
75
|
const sourceFile = await workspace.readSourceFile(file);
|
|
69
76
|
const index: FileIndex = {
|
|
70
77
|
declarations: new Map(),
|
|
78
|
+
localExports: new Map(),
|
|
79
|
+
locals: new Map(),
|
|
71
80
|
imports: new Map(),
|
|
72
81
|
reexports: new Map(),
|
|
73
82
|
exportStars: [],
|
|
@@ -115,6 +124,22 @@ export function createSourceIndex(workspace: AnalysisWorkspace): SourceIndex {
|
|
|
115
124
|
const target = source
|
|
116
125
|
? resolveLocalSourceFile(workspace, file, source)
|
|
117
126
|
: undefined;
|
|
127
|
+
|
|
128
|
+
if (!statement.moduleSpecifier) {
|
|
129
|
+
if (
|
|
130
|
+
statement.exportClause &&
|
|
131
|
+
ts.isNamedExports(statement.exportClause)
|
|
132
|
+
) {
|
|
133
|
+
for (const element of statement.exportClause.elements) {
|
|
134
|
+
if (statement.isTypeOnly || element.isTypeOnly) continue;
|
|
135
|
+
index.localExports.set(
|
|
136
|
+
element.name.text,
|
|
137
|
+
element.propertyName?.text ?? element.name.text,
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
118
143
|
if (!target) continue;
|
|
119
144
|
|
|
120
145
|
if (!statement.exportClause) {
|
|
@@ -133,10 +158,13 @@ export function createSourceIndex(workspace: AnalysisWorkspace): SourceIndex {
|
|
|
133
158
|
continue;
|
|
134
159
|
}
|
|
135
160
|
|
|
136
|
-
if (ts.isVariableStatement(statement)
|
|
161
|
+
if (ts.isVariableStatement(statement)) {
|
|
137
162
|
for (const declaration of statement.declarationList.declarations) {
|
|
138
163
|
if (ts.isIdentifier(declaration.name)) {
|
|
139
|
-
index.
|
|
164
|
+
index.locals.set(declaration.name.text, declaration);
|
|
165
|
+
if (hasExportModifier(statement)) {
|
|
166
|
+
index.declarations.set(declaration.name.text, declaration);
|
|
167
|
+
}
|
|
140
168
|
}
|
|
141
169
|
}
|
|
142
170
|
continue;
|
|
@@ -148,10 +176,12 @@ export function createSourceIndex(workspace: AnalysisWorkspace): SourceIndex {
|
|
|
148
176
|
ts.isInterfaceDeclaration(statement) ||
|
|
149
177
|
ts.isTypeAliasDeclaration(statement) ||
|
|
150
178
|
ts.isEnumDeclaration(statement)) &&
|
|
151
|
-
hasExportModifier(statement) &&
|
|
152
179
|
statement.name
|
|
153
180
|
) {
|
|
154
|
-
index.
|
|
181
|
+
index.locals.set(statement.name.text, statement);
|
|
182
|
+
if (hasExportModifier(statement)) {
|
|
183
|
+
index.declarations.set(statement.name.text, statement);
|
|
184
|
+
}
|
|
155
185
|
}
|
|
156
186
|
}
|
|
157
187
|
|
|
@@ -171,6 +201,14 @@ export function createSourceIndex(workspace: AnalysisWorkspace): SourceIndex {
|
|
|
171
201
|
const declaration = index.declarations.get(exportName);
|
|
172
202
|
if (declaration) return { file, exportName, declaration };
|
|
173
203
|
|
|
204
|
+
const localName = index.localExports.get(exportName);
|
|
205
|
+
const localDeclaration = localName
|
|
206
|
+
? index.locals.get(localName)
|
|
207
|
+
: undefined;
|
|
208
|
+
if (localDeclaration) {
|
|
209
|
+
return { file, exportName, declaration: localDeclaration };
|
|
210
|
+
}
|
|
211
|
+
|
|
174
212
|
const reexport = index.reexports.get(exportName);
|
|
175
213
|
if (reexport) {
|
|
176
214
|
return (
|
|
@@ -192,7 +230,7 @@ export function createSourceIndex(workspace: AnalysisWorkspace): SourceIndex {
|
|
|
192
230
|
return {
|
|
193
231
|
async resolveName(file, name) {
|
|
194
232
|
const index = await readIndex(file);
|
|
195
|
-
const local = index.
|
|
233
|
+
const local = index.locals.get(name);
|
|
196
234
|
if (local) {
|
|
197
235
|
return { file, exportName: name, declaration: local };
|
|
198
236
|
}
|
|
@@ -267,20 +305,48 @@ export function exportedVariableDeclarations(
|
|
|
267
305
|
declaration: ts.VariableDeclaration;
|
|
268
306
|
}> = [];
|
|
269
307
|
|
|
308
|
+
const locals = new Map<string, ts.VariableDeclaration>();
|
|
309
|
+
const seen = new Set<string>();
|
|
310
|
+
const addDeclaration = (
|
|
311
|
+
exportName: string,
|
|
312
|
+
declaration: ts.VariableDeclaration,
|
|
313
|
+
) => {
|
|
314
|
+
const key = `${exportName}:${declaration.pos}`;
|
|
315
|
+
if (seen.has(key)) return;
|
|
316
|
+
seen.add(key);
|
|
317
|
+
declarations.push({ exportName, declaration });
|
|
318
|
+
};
|
|
319
|
+
|
|
270
320
|
for (const statement of sourceFile.statements) {
|
|
271
|
-
if (!ts.isVariableStatement(statement)
|
|
272
|
-
continue;
|
|
273
|
-
}
|
|
321
|
+
if (!ts.isVariableStatement(statement)) continue;
|
|
274
322
|
for (const declaration of statement.declarationList.declarations) {
|
|
275
323
|
if (ts.isIdentifier(declaration.name)) {
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
declaration,
|
|
279
|
-
}
|
|
324
|
+
locals.set(declaration.name.text, declaration);
|
|
325
|
+
if (hasExportModifier(statement)) {
|
|
326
|
+
addDeclaration(declaration.name.text, declaration);
|
|
327
|
+
}
|
|
280
328
|
}
|
|
281
329
|
}
|
|
282
330
|
}
|
|
283
331
|
|
|
332
|
+
for (const statement of sourceFile.statements) {
|
|
333
|
+
if (
|
|
334
|
+
!ts.isExportDeclaration(statement) ||
|
|
335
|
+
statement.moduleSpecifier ||
|
|
336
|
+
statement.isTypeOnly ||
|
|
337
|
+
!statement.exportClause ||
|
|
338
|
+
!ts.isNamedExports(statement.exportClause)
|
|
339
|
+
) {
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
342
|
+
for (const element of statement.exportClause.elements) {
|
|
343
|
+
if (element.isTypeOnly) continue;
|
|
344
|
+
const localName = element.propertyName?.text ?? element.name.text;
|
|
345
|
+
const declaration = locals.get(localName);
|
|
346
|
+
if (declaration) addDeclaration(element.name.text, declaration);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
284
350
|
return declarations;
|
|
285
351
|
}
|
|
286
352
|
|
|
@@ -321,64 +387,166 @@ export async function localImportReferences(
|
|
|
321
387
|
workspace: AnalysisWorkspace,
|
|
322
388
|
file: string,
|
|
323
389
|
): Promise<LocalImportReference[]> {
|
|
324
|
-
const
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
? resolveLocalSourceFile(workspace, file, importPath)
|
|
339
|
-
: undefined;
|
|
340
|
-
if (
|
|
341
|
-
!importPath ||
|
|
342
|
-
(!resolvedFile && !isLocalModuleSpecifier(workspace, file, importPath))
|
|
343
|
-
) {
|
|
344
|
-
continue;
|
|
345
|
-
}
|
|
390
|
+
const references = await moduleReferences(workspace, file);
|
|
391
|
+
|
|
392
|
+
return references
|
|
393
|
+
.filter(
|
|
394
|
+
(reference) =>
|
|
395
|
+
reference.staticallyResolvable &&
|
|
396
|
+
(reference.resolvedFile ||
|
|
397
|
+
isLocalModuleSpecifier(workspace, file, reference.importPath)),
|
|
398
|
+
)
|
|
399
|
+
.map(
|
|
400
|
+
({ syntax: _syntax, staticallyResolvable: _static, ...reference }) =>
|
|
401
|
+
reference,
|
|
402
|
+
);
|
|
403
|
+
}
|
|
346
404
|
|
|
405
|
+
export async function moduleReferences(
|
|
406
|
+
workspace: AnalysisWorkspace,
|
|
407
|
+
file: string,
|
|
408
|
+
): Promise<ModuleReference[]> {
|
|
409
|
+
const sourceFile = await workspace.readSourceFile(file);
|
|
410
|
+
const references: ModuleReference[] = [];
|
|
411
|
+
|
|
412
|
+
const addReference = ({
|
|
413
|
+
importPath,
|
|
414
|
+
kind,
|
|
415
|
+
node,
|
|
416
|
+
staticallyResolvable,
|
|
417
|
+
syntax,
|
|
418
|
+
}: {
|
|
419
|
+
importPath: string;
|
|
420
|
+
kind: "type" | "value";
|
|
421
|
+
node: ts.Node;
|
|
422
|
+
staticallyResolvable: boolean;
|
|
423
|
+
syntax: ModuleReference["syntax"];
|
|
424
|
+
}) => {
|
|
347
425
|
const position = sourceFile.getLineAndCharacterOfPosition(
|
|
348
|
-
|
|
426
|
+
node.getStart(sourceFile),
|
|
349
427
|
);
|
|
350
|
-
const typeOnly = ts.isImportDeclaration(statement)
|
|
351
|
-
? Boolean(
|
|
352
|
-
statement.importClause?.isTypeOnly ||
|
|
353
|
-
(statement.importClause?.namedBindings &&
|
|
354
|
-
ts.isNamedImports(statement.importClause.namedBindings) &&
|
|
355
|
-
statement.importClause.namedBindings.elements.length > 0 &&
|
|
356
|
-
statement.importClause.namedBindings.elements.every(
|
|
357
|
-
(element) => element.isTypeOnly,
|
|
358
|
-
)),
|
|
359
|
-
)
|
|
360
|
-
: statement.isTypeOnly ||
|
|
361
|
-
(statement.exportClause &&
|
|
362
|
-
ts.isNamedExports(statement.exportClause) &&
|
|
363
|
-
statement.exportClause.elements.length > 0 &&
|
|
364
|
-
statement.exportClause.elements.every(
|
|
365
|
-
(element) => element.isTypeOnly,
|
|
366
|
-
));
|
|
367
428
|
references.push({
|
|
368
429
|
file,
|
|
369
430
|
importPath,
|
|
370
|
-
|
|
371
|
-
|
|
431
|
+
...(staticallyResolvable
|
|
432
|
+
? { resolvedFile: resolveLocalSourceFile(workspace, file, importPath) }
|
|
433
|
+
: {}),
|
|
434
|
+
kind,
|
|
372
435
|
line: position.line + 1,
|
|
373
436
|
column: position.character + 1,
|
|
437
|
+
syntax,
|
|
438
|
+
staticallyResolvable,
|
|
374
439
|
});
|
|
375
|
-
}
|
|
440
|
+
};
|
|
441
|
+
|
|
442
|
+
const visit = (node: ts.Node) => {
|
|
443
|
+
if (ts.isImportDeclaration(node) && node.moduleSpecifier) {
|
|
444
|
+
const importPath = moduleText(node.moduleSpecifier);
|
|
445
|
+
if (importPath) {
|
|
446
|
+
addReference({
|
|
447
|
+
importPath,
|
|
448
|
+
kind: importDeclarationKind(node),
|
|
449
|
+
node,
|
|
450
|
+
staticallyResolvable: true,
|
|
451
|
+
syntax: "import",
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
} else if (ts.isExportDeclaration(node) && node.moduleSpecifier) {
|
|
455
|
+
const importPath = moduleText(node.moduleSpecifier);
|
|
456
|
+
if (importPath) {
|
|
457
|
+
addReference({
|
|
458
|
+
importPath,
|
|
459
|
+
kind: exportDeclarationKind(node),
|
|
460
|
+
node,
|
|
461
|
+
staticallyResolvable: true,
|
|
462
|
+
syntax: "export",
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
} else if (
|
|
466
|
+
ts.isImportEqualsDeclaration(node) &&
|
|
467
|
+
ts.isExternalModuleReference(node.moduleReference) &&
|
|
468
|
+
node.moduleReference.expression
|
|
469
|
+
) {
|
|
470
|
+
const importPath = moduleText(node.moduleReference.expression);
|
|
471
|
+
if (importPath) {
|
|
472
|
+
addReference({
|
|
473
|
+
importPath,
|
|
474
|
+
kind: node.isTypeOnly ? "type" : "value",
|
|
475
|
+
node,
|
|
476
|
+
staticallyResolvable: true,
|
|
477
|
+
syntax: "import-equals",
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
} else if (ts.isCallExpression(node)) {
|
|
481
|
+
const syntax =
|
|
482
|
+
node.expression.kind === ts.SyntaxKind.ImportKeyword
|
|
483
|
+
? "dynamic-import"
|
|
484
|
+
: ts.isIdentifier(node.expression) &&
|
|
485
|
+
node.expression.text === "require"
|
|
486
|
+
? "require"
|
|
487
|
+
: undefined;
|
|
488
|
+
if (syntax) {
|
|
489
|
+
const argument = node.arguments[0];
|
|
490
|
+
const importPath = moduleText(argument);
|
|
491
|
+
addReference({
|
|
492
|
+
importPath:
|
|
493
|
+
importPath ?? argument?.getText(sourceFile) ?? "<missing>",
|
|
494
|
+
kind: "value",
|
|
495
|
+
node,
|
|
496
|
+
staticallyResolvable: importPath !== undefined,
|
|
497
|
+
syntax,
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
ts.forEachChild(node, visit);
|
|
503
|
+
};
|
|
504
|
+
|
|
505
|
+
visit(sourceFile);
|
|
376
506
|
|
|
377
507
|
return references;
|
|
378
508
|
}
|
|
379
509
|
|
|
380
|
-
function
|
|
381
|
-
|
|
510
|
+
function importDeclarationKind(
|
|
511
|
+
declaration: ts.ImportDeclaration,
|
|
512
|
+
): "type" | "value" {
|
|
513
|
+
const clause = declaration.importClause;
|
|
514
|
+
if (!clause) return "value";
|
|
515
|
+
if (clause.isTypeOnly) return "type";
|
|
516
|
+
if (clause.name) return "value";
|
|
517
|
+
|
|
518
|
+
const bindings = clause.namedBindings;
|
|
519
|
+
if (
|
|
520
|
+
bindings &&
|
|
521
|
+
ts.isNamedImports(bindings) &&
|
|
522
|
+
bindings.elements.length > 0 &&
|
|
523
|
+
bindings.elements.every((element) => element.isTypeOnly)
|
|
524
|
+
) {
|
|
525
|
+
return "type";
|
|
526
|
+
}
|
|
527
|
+
return "value";
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
function exportDeclarationKind(
|
|
531
|
+
declaration: ts.ExportDeclaration,
|
|
532
|
+
): "type" | "value" {
|
|
533
|
+
if (declaration.isTypeOnly) return "type";
|
|
534
|
+
if (
|
|
535
|
+
declaration.exportClause &&
|
|
536
|
+
ts.isNamedExports(declaration.exportClause) &&
|
|
537
|
+
declaration.exportClause.elements.length > 0 &&
|
|
538
|
+
declaration.exportClause.elements.every((element) => element.isTypeOnly)
|
|
539
|
+
) {
|
|
540
|
+
return "type";
|
|
541
|
+
}
|
|
542
|
+
return "value";
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
function moduleText(node: ts.Expression | undefined): string | undefined {
|
|
546
|
+
return node &&
|
|
547
|
+
(ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node))
|
|
548
|
+
? node.text
|
|
549
|
+
: undefined;
|
|
382
550
|
}
|
|
383
551
|
|
|
384
552
|
function hasExportModifier(node: ts.Node): boolean {
|
|
@@ -2,9 +2,11 @@ import { readdir, readFile, stat } from "node:fs/promises";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import ts from "typescript";
|
|
4
4
|
import {
|
|
5
|
+
type BeignetConfig,
|
|
5
6
|
loadBeignetConfig,
|
|
6
7
|
normalizePath,
|
|
7
8
|
type ResolvedBeignetConfig,
|
|
9
|
+
resolveConfig,
|
|
8
10
|
} from "../config.js";
|
|
9
11
|
|
|
10
12
|
const ignoredDirectoryNames = new Set([
|
|
@@ -22,19 +24,34 @@ export type AnalysisWorkspace = {
|
|
|
22
24
|
fileSet: Set<string>;
|
|
23
25
|
config: ResolvedBeignetConfig;
|
|
24
26
|
compilerOptions: ts.CompilerOptions;
|
|
27
|
+
moduleResolutionCache: ts.ModuleResolutionCache;
|
|
25
28
|
readSource(file: string): Promise<string>;
|
|
26
29
|
readSourceFile(file: string): Promise<ts.SourceFile>;
|
|
27
30
|
};
|
|
28
31
|
|
|
32
|
+
type AnalysisWorkspaceOptions = {
|
|
33
|
+
config?: BeignetConfig;
|
|
34
|
+
};
|
|
35
|
+
|
|
29
36
|
export async function createAnalysisWorkspace(
|
|
30
37
|
cwd = process.cwd(),
|
|
38
|
+
options: AnalysisWorkspaceOptions = {},
|
|
31
39
|
): Promise<AnalysisWorkspace> {
|
|
32
40
|
const targetDir = path.resolve(cwd);
|
|
33
41
|
await assertDirectory(targetDir);
|
|
34
42
|
const files = await listProjectFiles(targetDir);
|
|
35
43
|
const fileSet = new Set(files);
|
|
36
|
-
const config =
|
|
44
|
+
const config = options.config
|
|
45
|
+
? resolveConfig(options.config)
|
|
46
|
+
: await loadBeignetConfig(targetDir, files);
|
|
37
47
|
const compilerOptions = resolveCompilerOptions(targetDir);
|
|
48
|
+
const moduleResolutionCache = ts.createModuleResolutionCache(
|
|
49
|
+
targetDir,
|
|
50
|
+
ts.sys.useCaseSensitiveFileNames
|
|
51
|
+
? (fileName) => fileName
|
|
52
|
+
: (fileName) => fileName.toLowerCase(),
|
|
53
|
+
compilerOptions,
|
|
54
|
+
);
|
|
38
55
|
const sources = new Map<string, string>();
|
|
39
56
|
const sourceFiles = new Map<string, ts.SourceFile>();
|
|
40
57
|
|
|
@@ -53,6 +70,7 @@ export async function createAnalysisWorkspace(
|
|
|
53
70
|
fileSet,
|
|
54
71
|
config,
|
|
55
72
|
compilerOptions,
|
|
73
|
+
moduleResolutionCache,
|
|
56
74
|
readSource,
|
|
57
75
|
async readSourceFile(file) {
|
|
58
76
|
const cached = sourceFiles.get(file);
|
|
@@ -111,7 +129,7 @@ export async function listProjectFiles(targetDir: string): Promise<string[]> {
|
|
|
111
129
|
export function resolveLocalSourceFile(
|
|
112
130
|
workspace: Pick<
|
|
113
131
|
AnalysisWorkspace,
|
|
114
|
-
"compilerOptions" | "fileSet" | "targetDir"
|
|
132
|
+
"compilerOptions" | "fileSet" | "moduleResolutionCache" | "targetDir"
|
|
115
133
|
>,
|
|
116
134
|
importerFile: string,
|
|
117
135
|
importPath: string,
|
|
@@ -126,10 +144,62 @@ export function resolveLocalSourceFile(
|
|
|
126
144
|
return workspace.fileSet.has(file) ? file : undefined;
|
|
127
145
|
}
|
|
128
146
|
|
|
147
|
+
export function resolveLocalModulePath(
|
|
148
|
+
workspace: Pick<
|
|
149
|
+
AnalysisWorkspace,
|
|
150
|
+
"compilerOptions" | "fileSet" | "moduleResolutionCache" | "targetDir"
|
|
151
|
+
>,
|
|
152
|
+
importerFile: string,
|
|
153
|
+
importPath: string,
|
|
154
|
+
): string | undefined {
|
|
155
|
+
const resolvedFile = resolveLocalSourceFile(
|
|
156
|
+
workspace,
|
|
157
|
+
importerFile,
|
|
158
|
+
importPath,
|
|
159
|
+
);
|
|
160
|
+
if (resolvedFile) return resolvedFile;
|
|
161
|
+
|
|
162
|
+
if (!isLocalModuleSpecifier(workspace, importerFile, importPath)) {
|
|
163
|
+
return undefined;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (importPath.startsWith(".")) {
|
|
167
|
+
return normalizePath(path.join(path.dirname(importerFile), importPath));
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const baseUrl = compilerPathsBase(
|
|
171
|
+
workspace.compilerOptions,
|
|
172
|
+
workspace.targetDir,
|
|
173
|
+
);
|
|
174
|
+
for (const [pattern, targets] of Object.entries(
|
|
175
|
+
workspace.compilerOptions.paths ?? {},
|
|
176
|
+
)) {
|
|
177
|
+
if (pattern === "*") continue;
|
|
178
|
+
const wildcardValue = modulePatternWildcard(pattern, importPath);
|
|
179
|
+
if (wildcardValue === undefined) continue;
|
|
180
|
+
|
|
181
|
+
for (const target of targets) {
|
|
182
|
+
const substituted = target.replace("*", wildcardValue);
|
|
183
|
+
const absolute = path.resolve(baseUrl, substituted);
|
|
184
|
+
const relative = normalizePath(
|
|
185
|
+
path.relative(workspace.targetDir, absolute),
|
|
186
|
+
);
|
|
187
|
+
if (relative !== ".." && !relative.startsWith("../")) return relative;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const relative = normalizePath(
|
|
192
|
+
path.relative(workspace.targetDir, path.resolve(baseUrl, importPath)),
|
|
193
|
+
);
|
|
194
|
+
return relative !== ".." && !relative.startsWith("../")
|
|
195
|
+
? relative
|
|
196
|
+
: undefined;
|
|
197
|
+
}
|
|
198
|
+
|
|
129
199
|
export function isLocalModuleSpecifier(
|
|
130
200
|
workspace: Pick<
|
|
131
201
|
AnalysisWorkspace,
|
|
132
|
-
"compilerOptions" | "fileSet" | "targetDir"
|
|
202
|
+
"compilerOptions" | "fileSet" | "moduleResolutionCache" | "targetDir"
|
|
133
203
|
>,
|
|
134
204
|
importerFile: string,
|
|
135
205
|
importPath: string,
|
|
@@ -180,7 +250,10 @@ export function isLocalModuleSpecifier(
|
|
|
180
250
|
}
|
|
181
251
|
|
|
182
252
|
function resolveModule(
|
|
183
|
-
workspace: Pick<
|
|
253
|
+
workspace: Pick<
|
|
254
|
+
AnalysisWorkspace,
|
|
255
|
+
"compilerOptions" | "moduleResolutionCache" | "targetDir"
|
|
256
|
+
>,
|
|
184
257
|
importerFile: string,
|
|
185
258
|
importPath: string,
|
|
186
259
|
): ts.ResolvedModuleFull | undefined {
|
|
@@ -189,6 +262,7 @@ function resolveModule(
|
|
|
189
262
|
path.join(workspace.targetDir, importerFile),
|
|
190
263
|
workspace.compilerOptions,
|
|
191
264
|
ts.sys,
|
|
265
|
+
workspace.moduleResolutionCache,
|
|
192
266
|
).resolvedModule;
|
|
193
267
|
}
|
|
194
268
|
|
|
@@ -201,8 +275,23 @@ function modulePatternMatches(pattern: string, importPath: string): boolean {
|
|
|
201
275
|
);
|
|
202
276
|
}
|
|
203
277
|
|
|
278
|
+
function modulePatternWildcard(
|
|
279
|
+
pattern: string,
|
|
280
|
+
importPath: string,
|
|
281
|
+
): string | undefined {
|
|
282
|
+
const wildcard = pattern.indexOf("*");
|
|
283
|
+
if (wildcard === -1) return pattern === importPath ? "" : undefined;
|
|
284
|
+
|
|
285
|
+
const prefix = pattern.slice(0, wildcard);
|
|
286
|
+
const suffix = pattern.slice(wildcard + 1);
|
|
287
|
+
if (!importPath.startsWith(prefix) || !importPath.endsWith(suffix)) {
|
|
288
|
+
return undefined;
|
|
289
|
+
}
|
|
290
|
+
return importPath.slice(prefix.length, importPath.length - suffix.length);
|
|
291
|
+
}
|
|
292
|
+
|
|
204
293
|
function resolveCompilerOptions(targetDir: string): ts.CompilerOptions {
|
|
205
|
-
|
|
294
|
+
const compilerOptions =
|
|
206
295
|
ts.getParsedCommandLineOfConfigFile(
|
|
207
296
|
path.join(targetDir, "tsconfig.json"),
|
|
208
297
|
{},
|
|
@@ -210,7 +299,27 @@ function resolveCompilerOptions(targetDir: string): ts.CompilerOptions {
|
|
|
210
299
|
...ts.sys,
|
|
211
300
|
onUnRecoverableConfigFileDiagnostic: () => {},
|
|
212
301
|
},
|
|
213
|
-
)?.options ?? {}
|
|
302
|
+
)?.options ?? {};
|
|
303
|
+
|
|
304
|
+
if (compilerOptions.paths) return compilerOptions;
|
|
305
|
+
return {
|
|
306
|
+
...compilerOptions,
|
|
307
|
+
baseUrl: compilerOptions.baseUrl ?? targetDir,
|
|
308
|
+
paths: {
|
|
309
|
+
"@/*": ["*"],
|
|
310
|
+
},
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
function compilerPathsBase(
|
|
315
|
+
compilerOptions: ts.CompilerOptions,
|
|
316
|
+
targetDir: string,
|
|
317
|
+
): string {
|
|
318
|
+
const optionsWithPathBase = compilerOptions as ts.CompilerOptions & {
|
|
319
|
+
pathsBasePath?: string;
|
|
320
|
+
};
|
|
321
|
+
return (
|
|
322
|
+
compilerOptions.baseUrl ?? optionsWithPathBase.pathsBasePath ?? targetDir
|
|
214
323
|
);
|
|
215
324
|
}
|
|
216
325
|
|