@agent-native/core 0.111.2 → 0.111.3

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.
@@ -1,5 +1,11 @@
1
1
  # @agent-native/core
2
2
 
3
+ ## 0.111.3
4
+
5
+ ### Patch Changes
6
+
7
+ - 7843f92: Apply active import migrations to starter-owned source and install newly introduced migration dependencies before rewriting imports.
8
+
3
9
  ## 0.111.2
4
10
 
5
11
  ### Patch Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/core",
3
- "version": "0.111.2",
3
+ "version": "0.111.3",
4
4
  "description": "Framework for agent-native application development — where AI agents and UI share SQL state, actions, and context",
5
5
  "homepage": "https://github.com/BuilderIO/agent-native#readme",
6
6
  "bugs": {
@@ -48,7 +48,7 @@ export interface RunMigrationCodemodsOptions {
48
48
  root: string;
49
49
  manifests?: MigrationManifest[];
50
50
  apply?: boolean;
51
- targetExists?: (specifier: string) => boolean;
51
+ targetExists?: (specifier: string, sourceFile?: string) => boolean;
52
52
  }
53
53
 
54
54
  interface PendingDependency {
@@ -104,6 +104,34 @@ function packageNameFromSpecifier(specifier: string): string | null {
104
104
  return name && !name.startsWith(".") ? name : null;
105
105
  }
106
106
 
107
+ function isPackageInstalled(
108
+ requireFromProject: ReturnType<typeof createRequire>,
109
+ packageName: string,
110
+ ): boolean {
111
+ const searchPaths = requireFromProject.resolve.paths(packageName) ?? [];
112
+ return searchPaths.some((searchPath) =>
113
+ fs.existsSync(path.join(searchPath, packageName, "package.json")),
114
+ );
115
+ }
116
+
117
+ export function createMigrationPlanningTargetResolver(
118
+ projectRoot: string,
119
+ ): (specifier: string, sourceFile?: string) => boolean {
120
+ const fallbackPath = path.join(path.resolve(projectRoot), "package.json");
121
+ return (specifier: string, sourceFile = fallbackPath): boolean => {
122
+ const requireFromSource = createRequire(sourceFile);
123
+ try {
124
+ requireFromSource.resolve(specifier);
125
+ return true;
126
+ } catch {
127
+ const packageName = packageNameFromSpecifier(specifier);
128
+ return Boolean(
129
+ packageName && !isPackageInstalled(requireFromSource, packageName),
130
+ );
131
+ }
132
+ };
133
+ }
134
+
107
135
  function nearestPackageFile(file: string, root: string): string | null {
108
136
  let directory = path.dirname(file);
109
137
  const boundary = path.resolve(root);
@@ -175,7 +203,7 @@ function rewriteImportDeclaration(
175
203
  root: string,
176
204
  pendingDependencies: PendingDependency[],
177
205
  warnings: string[],
178
- targetExists: (specifier: string) => boolean,
206
+ targetExists: (specifier: string, sourceFile?: string) => boolean,
179
207
  ): boolean {
180
208
  const originalSpecifier = declaration.getModuleSpecifierValue();
181
209
  const sourceFile = declaration.getSourceFile();
@@ -186,7 +214,7 @@ function rewriteImportDeclaration(
186
214
  warnSkippedTarget(warnings, sourceFile.getFilePath(), move.to, "planned");
187
215
  return false;
188
216
  }
189
- if (!targetExists(move.to)) {
217
+ if (!targetExists(move.to, sourceFile.getFilePath())) {
190
218
  warnSkippedTarget(
191
219
  warnings,
192
220
  sourceFile.getFilePath(),
@@ -228,7 +256,7 @@ function rewriteImportDeclaration(
228
256
  );
229
257
  continue;
230
258
  }
231
- if (!targetExists(resolved.to)) {
259
+ if (!targetExists(resolved.to, sourceFile.getFilePath())) {
232
260
  warnSkippedTarget(
233
261
  warnings,
234
262
  sourceFile.getFilePath(),
@@ -286,7 +314,7 @@ function rewriteExportDeclarations(
286
314
  root: string,
287
315
  pendingDependencies: PendingDependency[],
288
316
  warnings: string[],
289
- targetExists: (specifier: string) => boolean,
317
+ targetExists: (specifier: string, sourceFile?: string) => boolean,
290
318
  ): void {
291
319
  for (const declaration of [...sourceFile.getExportDeclarations()]) {
292
320
  const originalSpecifier = declaration.getModuleSpecifierValue();
@@ -305,7 +333,7 @@ function rewriteExportDeclarations(
305
333
  );
306
334
  continue;
307
335
  }
308
- if (!targetExists(move.to)) {
336
+ if (!targetExists(move.to, sourceFile.getFilePath())) {
309
337
  warnSkippedTarget(
310
338
  warnings,
311
339
  sourceFile.getFilePath(),
@@ -349,7 +377,7 @@ function rewriteExportDeclarations(
349
377
  );
350
378
  continue;
351
379
  }
352
- if (!targetExists(resolved.to)) {
380
+ if (!targetExists(resolved.to, sourceFile.getFilePath())) {
353
381
  warnSkippedTarget(
354
382
  warnings,
355
383
  sourceFile.getFilePath(),
@@ -469,12 +497,11 @@ export function runMigrationCodemods(
469
497
  const root = path.resolve(options.root);
470
498
  const manifests = options.manifests ?? loadMigrationManifests(root);
471
499
  const moves = mergeManifestMoves(manifests);
472
- const requireFromProject = createRequire(path.join(root, "package.json"));
473
500
  const targetExists =
474
501
  options.targetExists ??
475
- ((specifier: string): boolean => {
502
+ ((specifier: string, sourceFile = path.join(root, "package.json")) => {
476
503
  try {
477
- requireFromProject.resolve(specifier);
504
+ createRequire(sourceFile).resolve(specifier);
478
505
  return true;
479
506
  } catch {
480
507
  return false;
@@ -3,7 +3,12 @@ import os from "node:os";
3
3
  import path from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
5
 
6
+ import {
7
+ isMigrationManifestActive,
8
+ readMigrationManifest,
9
+ } from "../package-lifecycle/migration-manifest.js";
6
10
  import { _postProcessStandalone } from "./create.js";
11
+ import { runMigrationCodemods } from "./migration-codemod.js";
7
12
 
8
13
  export const STARTER_APP_NAME = "builder-agent-native-starter";
9
14
  export const CHAT_TEMPLATE = "chat";
@@ -25,6 +30,11 @@ export const STARTER_TOOLCHAIN_SYNC_PATHS = [
25
30
  "netlify.toml",
26
31
  ] as const;
27
32
 
33
+ export const STARTER_SOURCE_MIGRATION_PATHS = [
34
+ ":(glob)**/*.ts",
35
+ ":(glob)**/*.tsx",
36
+ ] as const;
37
+
28
38
  const STANDALONE_SNAPSHOT_EXCLUDED_TOP_LEVEL = new Set([
29
39
  ".deploy-tmp",
30
40
  ".env",
@@ -58,9 +68,79 @@ export function listStarterSyncPaths(): string[] {
58
68
  "pnpm-lock.yaml",
59
69
  "pnpm-workspace.yaml",
60
70
  ...STARTER_TOOLCHAIN_SYNC_PATHS,
71
+ ...STARTER_SOURCE_MIGRATION_PATHS,
61
72
  ];
62
73
  }
63
74
 
75
+ export function migrateStarterSources(options: {
76
+ starterDir: string;
77
+ repoRoot: string;
78
+ coreVersion: string | null;
79
+ write?: boolean;
80
+ }): { changedPaths: string[]; warnings: string[] } {
81
+ const manifestPath = path.join(
82
+ options.repoRoot,
83
+ "packages/core/migration-manifest.json",
84
+ );
85
+ const manifest = readMigrationManifest(manifestPath);
86
+ if (!manifest) {
87
+ throw new Error(`Could not read migration manifest at ${manifestPath}.`);
88
+ }
89
+ if (!isMigrationManifestActive(manifest, options.coreVersion)) {
90
+ return { changedPaths: [], warnings: [] };
91
+ }
92
+
93
+ const result = runMigrationCodemods({
94
+ root: options.starterDir,
95
+ manifests: [manifest],
96
+ apply: options.write,
97
+ // Checked-in migration targets are validated by the manifest guard before
98
+ // this source sync runs; starter dependencies are installed afterward.
99
+ targetExists: () => true,
100
+ });
101
+
102
+ return {
103
+ changedPaths: [
104
+ ...new Set(
105
+ result.changes.map((change) =>
106
+ path.relative(options.starterDir, change.file),
107
+ ),
108
+ ),
109
+ ].sort(),
110
+ warnings: result.warnings,
111
+ };
112
+ }
113
+
114
+ export function resolveStarterCoreVersion(
115
+ starterPackageJson: PackageJson,
116
+ repoRoot: string,
117
+ ): string | null {
118
+ const dependencies = starterPackageJson.dependencies;
119
+ if (dependencies && typeof dependencies === "object") {
120
+ const declared = (dependencies as Record<string, unknown>)[
121
+ "@agent-native/core"
122
+ ];
123
+ if (typeof declared === "string") {
124
+ const version = declared.match(/\d+\.\d+\.\d+/)?.[0];
125
+ if (version) return version;
126
+ }
127
+ }
128
+
129
+ try {
130
+ const corePackageJson = JSON.parse(
131
+ fs.readFileSync(
132
+ path.join(repoRoot, "packages/core/package.json"),
133
+ "utf-8",
134
+ ),
135
+ ) as { version?: unknown };
136
+ return typeof corePackageJson.version === "string"
137
+ ? corePackageJson.version
138
+ : null;
139
+ } catch {
140
+ return null;
141
+ }
142
+ }
143
+
64
144
  export function findAgentNativeRoot(startDir = process.cwd()): string {
65
145
  let dir = path.resolve(startDir);
66
146
  for (let i = 0; i < 12; i++) {
@@ -296,6 +376,8 @@ export type SyncStarterManifestResult = {
296
376
  pnpmWorkspaceYaml: string | null;
297
377
  toolchainChanges: StarterToolchainSyncChange[];
298
378
  changedToolchainPaths: StarterToolchainSyncPath[];
379
+ changedSourceMigrationPaths: string[];
380
+ sourceMigrationWarnings: string[];
299
381
  };
300
382
 
301
383
  export function resolveStarterPaths(options: {
@@ -345,6 +427,19 @@ export function syncStarterManifestFiles(options: {
345
427
  const snapshot = createStandaloneChatSnapshot(options.repoRoot);
346
428
 
347
429
  try {
430
+ const repoRoot = options.repoRoot ?? findAgentNativeRoot();
431
+ const initialStarterPackageJson = JSON.parse(
432
+ fs.readFileSync(starterPackageJsonPath, "utf-8"),
433
+ ) as PackageJson;
434
+ const sourceMigration = migrateStarterSources({
435
+ starterDir,
436
+ repoRoot,
437
+ coreVersion: resolveStarterCoreVersion(
438
+ initialStarterPackageJson,
439
+ repoRoot,
440
+ ),
441
+ write: options.write,
442
+ });
348
443
  const starterPackageJson = JSON.parse(
349
444
  fs.readFileSync(starterPackageJsonPath, "utf-8"),
350
445
  ) as PackageJson;
@@ -371,7 +466,10 @@ export function syncStarterManifestFiles(options: {
371
466
  .filter((change) => change.changed)
372
467
  .map((change) => change.relativePath);
373
468
  const changed =
374
- packageChanged || workspaceChanged || changedToolchainPaths.length > 0;
469
+ packageChanged ||
470
+ workspaceChanged ||
471
+ changedToolchainPaths.length > 0 ||
472
+ sourceMigration.changedPaths.length > 0;
375
473
 
376
474
  if (options.write && changed) {
377
475
  if (packageChanged) {
@@ -396,6 +494,8 @@ export function syncStarterManifestFiles(options: {
396
494
  pnpmWorkspaceYaml: snapshot.pnpmWorkspaceYaml,
397
495
  toolchainChanges,
398
496
  changedToolchainPaths,
497
+ changedSourceMigrationPaths: sourceMigration.changedPaths,
498
+ sourceMigrationWarnings: sourceMigration.warnings,
399
499
  };
400
500
  } finally {
401
501
  snapshot.cleanup();
@@ -494,11 +594,18 @@ export function runSyncStarterManifestCli(argv: string[]): number {
494
594
  write: args.write,
495
595
  });
496
596
 
597
+ for (const warning of result.sourceMigrationWarnings) {
598
+ console.warn(`[starter migration] ${warning}`);
599
+ }
600
+
497
601
  if (result.changed) {
498
602
  const updatedPaths = [
499
- ...(result.packageChanged ? ["package.json"] : []),
500
- ...(result.workspaceChanged ? ["pnpm-workspace.yaml"] : []),
501
- ...result.changedToolchainPaths,
603
+ ...new Set([
604
+ ...(result.packageChanged ? ["package.json"] : []),
605
+ ...(result.workspaceChanged ? ["pnpm-workspace.yaml"] : []),
606
+ ...result.changedToolchainPaths,
607
+ ...result.changedSourceMigrationPaths,
608
+ ]),
502
609
  ];
503
610
  const summary = updatedPaths.length ? ` (${updatedPaths.join(", ")})` : "";
504
611
  console.log(
@@ -18,6 +18,8 @@ import fs from "node:fs";
18
18
  import path from "node:path";
19
19
  import { fileURLToPath } from "node:url";
20
20
 
21
+ import type { MigrationCodemodResult } from "./migration-codemod.js";
22
+
21
23
  const AGENT_NATIVE_SCOPE = "@agent-native/";
22
24
  const PINNABLE_VERSION = "latest";
23
25
 
@@ -541,6 +543,19 @@ const FAILURE_GUIDANCE = [
541
543
  " npx @agent-native/core@latest upgrade",
542
544
  ].join("\n");
543
545
 
546
+ function applyCodemodDependencyPlan(
547
+ codemodResult: MigrationCodemodResult,
548
+ ): MigrationCodemodResult["changes"] {
549
+ const dependencyFiles = new Set(codemodResult.dependencyFiles);
550
+ const applied: MigrationCodemodResult["changes"] = [];
551
+ for (const change of codemodResult.changes) {
552
+ if (!dependencyFiles.has(change.file)) continue;
553
+ fs.writeFileSync(change.file, change.after);
554
+ applied.push(change);
555
+ }
556
+ return applied;
557
+ }
558
+
544
559
  export async function runUpgrade(
545
560
  argv: string[],
546
561
  io: UpgradeIo = defaultIo,
@@ -659,39 +674,57 @@ export async function runUpgrade(
659
674
  });
660
675
  }
661
676
 
677
+ let codemodPlan:
678
+ | {
679
+ module: typeof import("./migration-codemod.js");
680
+ dependencyChanges: MigrationCodemodResult["changes"];
681
+ }
682
+ | undefined;
683
+
662
684
  if (opts.codemods) {
663
- const { formatMigrationCodemodDiff, runMigrationCodemods } =
664
- await import("./migration-codemod.js");
665
- const codemodResult = runMigrationCodemods({
685
+ const codemodModule = await import("./migration-codemod.js");
686
+ const codemodResult = codemodModule.runMigrationCodemods({
666
687
  root: project.root,
667
- apply: !dryRun,
668
- });
669
- const diff = formatMigrationCodemodDiff(codemodResult, project.root);
670
- result.codemod = {
671
- files: codemodResult.changes.map((change) =>
672
- relativeTo(project.root, change.file),
688
+ targetExists: codemodModule.createMigrationPlanningTargetResolver(
689
+ project.root,
673
690
  ),
674
- warnings: codemodResult.warnings,
675
- diff,
676
- };
677
- result.steps.push({
678
- id: "codemods",
679
- status:
680
- codemodResult.changes.length === 0
681
- ? "skipped"
682
- : dryRun
683
- ? "planned"
684
- : "ok",
685
- detail:
686
- codemodResult.changes.length === 0
687
- ? "No manifest migrations found"
688
- : `${dryRun ? "Would update" : "Updated"} ${codemodResult.changes.length} file(s)`,
689
691
  });
690
- if (!opts.json && diff) {
692
+ const diff = codemodModule.formatMigrationCodemodDiff(
693
+ codemodResult,
694
+ project.root,
695
+ );
696
+ const dependencyChanges = dryRun
697
+ ? []
698
+ : applyCodemodDependencyPlan(codemodResult);
699
+ codemodPlan = {
700
+ module: codemodModule,
701
+ dependencyChanges,
702
+ };
703
+
704
+ if (dryRun) {
705
+ result.codemod = {
706
+ files: codemodResult.changes.map((change) =>
707
+ relativeTo(project.root, change.file),
708
+ ),
709
+ warnings: codemodResult.warnings,
710
+ diff,
711
+ };
712
+ }
713
+ if (dryRun) {
714
+ result.steps.push({
715
+ id: "codemods",
716
+ status: codemodResult.changes.length === 0 ? "skipped" : "planned",
717
+ detail:
718
+ codemodResult.changes.length === 0
719
+ ? "No manifest migrations found"
720
+ : `Would update ${codemodResult.changes.length} file(s)`,
721
+ });
722
+ }
723
+ if (dryRun && !opts.json && diff) {
691
724
  io.log(diff);
692
725
  io.log("");
693
726
  }
694
- if (!opts.json) {
727
+ if (dryRun && !opts.json) {
695
728
  for (const warning of codemodResult.warnings) {
696
729
  io.err(`[codemods] ${warning}`);
697
730
  }
@@ -721,6 +754,30 @@ export async function runUpgrade(
721
754
  result.ok = false;
722
755
  result.exitCode = spawned.status ?? 1;
723
756
  result.message = `${pm} install failed`;
757
+ if (codemodPlan && codemodPlan.dependencyChanges.length > 0) {
758
+ const dependencyResult: MigrationCodemodResult = {
759
+ changes: codemodPlan.dependencyChanges,
760
+ dependencyFiles: codemodPlan.dependencyChanges.map(
761
+ (change) => change.file,
762
+ ),
763
+ warnings: [],
764
+ };
765
+ const diff = codemodPlan.module.formatMigrationCodemodDiff(
766
+ dependencyResult,
767
+ project.root,
768
+ );
769
+ result.codemod = {
770
+ files: dependencyResult.changes.map((change) =>
771
+ relativeTo(project.root, change.file),
772
+ ),
773
+ warnings: [],
774
+ diff,
775
+ };
776
+ if (!opts.json && diff) {
777
+ io.log(diff);
778
+ io.log("");
779
+ }
780
+ }
724
781
  result.steps.push({
725
782
  id: "install",
726
783
  status: "failed",
@@ -732,6 +789,51 @@ export async function runUpgrade(
732
789
  result.steps.push({ id: "install", status: "ok", detail: `${pm} install` });
733
790
  }
734
791
 
792
+ if (codemodPlan && !dryRun) {
793
+ const applied = codemodPlan.module.runMigrationCodemods({
794
+ root: project.root,
795
+ apply: true,
796
+ });
797
+ const actualResult: MigrationCodemodResult = {
798
+ changes: [...codemodPlan.dependencyChanges, ...applied.changes],
799
+ dependencyFiles: codemodPlan.dependencyChanges.map(
800
+ (change) => change.file,
801
+ ),
802
+ warnings: applied.warnings,
803
+ };
804
+ const diff = codemodPlan.module.formatMigrationCodemodDiff(
805
+ actualResult,
806
+ project.root,
807
+ );
808
+ const files = [
809
+ ...new Set(actualResult.changes.map((change) => change.file)),
810
+ ];
811
+ result.codemod = {
812
+ files: files.map((file) => relativeTo(project.root, file)),
813
+ warnings: actualResult.warnings,
814
+ diff,
815
+ };
816
+ result.steps.push({
817
+ id: "codemods",
818
+ status: files.length === 0 ? "skipped" : "ok",
819
+ detail:
820
+ files.length === 0
821
+ ? "No resolvable manifest migrations found"
822
+ : opts.skipInstall
823
+ ? `Updated ${files.length} file(s) without installing dependencies`
824
+ : `Updated ${files.length} file(s) after dependency installation`,
825
+ });
826
+ if (!opts.json && diff) {
827
+ io.log(diff);
828
+ io.log("");
829
+ }
830
+ if (!opts.json) {
831
+ for (const warning of actualResult.warnings) {
832
+ io.err(`[codemods] ${warning}`);
833
+ }
834
+ }
835
+ }
836
+
735
837
  // Skills refresh.
736
838
  if (opts.skipSkills) {
737
839
  result.steps.push({
@@ -13,9 +13,10 @@ export interface RunMigrationCodemodsOptions {
13
13
  root: string;
14
14
  manifests?: MigrationManifest[];
15
15
  apply?: boolean;
16
- targetExists?: (specifier: string) => boolean;
16
+ targetExists?: (specifier: string, sourceFile?: string) => boolean;
17
17
  }
18
18
  export declare function loadMigrationManifests(projectRoot: string): MigrationManifest[];
19
+ export declare function createMigrationPlanningTargetResolver(projectRoot: string): (specifier: string, sourceFile?: string) => boolean;
19
20
  export declare function runMigrationCodemods(options: RunMigrationCodemodsOptions): MigrationCodemodResult;
20
21
  export declare function formatMigrationCodemodDiff(result: MigrationCodemodResult, root: string): string;
21
22
  //# sourceMappingURL=migration-codemod.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"migration-codemod.d.ts","sourceRoot":"","sources":["../../src/cli/migration-codemod.ts"],"names":[],"mappings":"AAYA,OAAO,EAML,KAAK,iBAAiB,EAEvB,MAAM,4CAA4C,CAAC;AAcpD,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,0BAA0B,EAAE,CAAC;IACtC,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,2BAA2B;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAChC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,YAAY,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;CAC/C;AAqCD,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,MAAM,GAClB,iBAAiB,EAAE,CAKrB;AAkXD,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,2BAA2B,GACnC,sBAAsB,CA6DxB;AAiCD,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,sBAAsB,EAC9B,IAAI,EAAE,MAAM,GACX,MAAM,CAIR"}
1
+ {"version":3,"file":"migration-codemod.d.ts","sourceRoot":"","sources":["../../src/cli/migration-codemod.ts"],"names":[],"mappings":"AAYA,OAAO,EAML,KAAK,iBAAiB,EAEvB,MAAM,4CAA4C,CAAC;AAcpD,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,0BAA0B,EAAE,CAAC;IACtC,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,2BAA2B;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAChC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,YAAY,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;CACpE;AAqCD,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,MAAM,GAClB,iBAAiB,EAAE,CAKrB;AAqBD,wBAAgB,qCAAqC,CACnD,WAAW,EAAE,MAAM,GAClB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,KAAK,OAAO,CAcrD;AAyWD,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,2BAA2B,GACnC,sBAAsB,CA4DxB;AAiCD,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,sBAAsB,EAC9B,IAAI,EAAE,MAAM,GACX,MAAM,CAIR"}
@@ -52,6 +52,24 @@ function packageNameFromSpecifier(specifier) {
52
52
  const [name] = specifier.split("/");
53
53
  return name && !name.startsWith(".") ? name : null;
54
54
  }
55
+ function isPackageInstalled(requireFromProject, packageName) {
56
+ const searchPaths = requireFromProject.resolve.paths(packageName) ?? [];
57
+ return searchPaths.some((searchPath) => fs.existsSync(path.join(searchPath, packageName, "package.json")));
58
+ }
59
+ export function createMigrationPlanningTargetResolver(projectRoot) {
60
+ const fallbackPath = path.join(path.resolve(projectRoot), "package.json");
61
+ return (specifier, sourceFile = fallbackPath) => {
62
+ const requireFromSource = createRequire(sourceFile);
63
+ try {
64
+ requireFromSource.resolve(specifier);
65
+ return true;
66
+ }
67
+ catch {
68
+ const packageName = packageNameFromSpecifier(specifier);
69
+ return Boolean(packageName && !isPackageInstalled(requireFromSource, packageName));
70
+ }
71
+ };
72
+ }
55
73
  function nearestPackageFile(file, root) {
56
74
  let directory = path.dirname(file);
57
75
  const boundary = path.resolve(root);
@@ -104,7 +122,7 @@ function rewriteImportDeclaration(declaration, move, root, pendingDependencies,
104
122
  warnSkippedTarget(warnings, sourceFile.getFilePath(), move.to, "planned");
105
123
  return false;
106
124
  }
107
- if (!targetExists(move.to)) {
125
+ if (!targetExists(move.to, sourceFile.getFilePath())) {
108
126
  warnSkippedTarget(warnings, sourceFile.getFilePath(), move.to, "unresolved");
109
127
  return false;
110
128
  }
@@ -127,7 +145,7 @@ function rewriteImportDeclaration(declaration, move, root, pendingDependencies,
127
145
  warnSkippedTarget(warnings, sourceFile.getFilePath(), resolved.to, "planned");
128
146
  continue;
129
147
  }
130
- if (!targetExists(resolved.to)) {
148
+ if (!targetExists(resolved.to, sourceFile.getFilePath())) {
131
149
  warnSkippedTarget(warnings, sourceFile.getFilePath(), resolved.to, "unresolved");
132
150
  continue;
133
151
  }
@@ -173,7 +191,7 @@ function rewriteExportDeclarations(sourceFile, moves, root, pendingDependencies,
173
191
  warnSkippedTarget(warnings, sourceFile.getFilePath(), move.to, "planned");
174
192
  continue;
175
193
  }
176
- if (!targetExists(move.to)) {
194
+ if (!targetExists(move.to, sourceFile.getFilePath())) {
177
195
  warnSkippedTarget(warnings, sourceFile.getFilePath(), move.to, "unresolved");
178
196
  continue;
179
197
  }
@@ -196,7 +214,7 @@ function rewriteExportDeclarations(sourceFile, moves, root, pendingDependencies,
196
214
  warnSkippedTarget(warnings, sourceFile.getFilePath(), resolved.to, "planned");
197
215
  continue;
198
216
  }
199
- if (!targetExists(resolved.to)) {
217
+ if (!targetExists(resolved.to, sourceFile.getFilePath())) {
200
218
  warnSkippedTarget(warnings, sourceFile.getFilePath(), resolved.to, "unresolved");
201
219
  continue;
202
220
  }
@@ -287,11 +305,10 @@ export function runMigrationCodemods(options) {
287
305
  const root = path.resolve(options.root);
288
306
  const manifests = options.manifests ?? loadMigrationManifests(root);
289
307
  const moves = mergeManifestMoves(manifests);
290
- const requireFromProject = createRequire(path.join(root, "package.json"));
291
308
  const targetExists = options.targetExists ??
292
- ((specifier) => {
309
+ ((specifier, sourceFile = path.join(root, "package.json")) => {
293
310
  try {
294
- requireFromProject.resolve(specifier);
311
+ createRequire(sourceFile).resolve(specifier);
295
312
  return true;
296
313
  }
297
314
  catch {