ima2-gen 1.1.8 → 1.1.9

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.
Files changed (230) hide show
  1. package/README.md +56 -27
  2. package/bin/commands/annotate.js +137 -0
  3. package/bin/commands/annotate.ts +118 -0
  4. package/bin/commands/cancel.js +37 -33
  5. package/bin/commands/cancel.ts +45 -0
  6. package/bin/commands/canvas-versions.js +91 -0
  7. package/bin/commands/canvas-versions.ts +80 -0
  8. package/bin/commands/cardnews.js +293 -0
  9. package/bin/commands/cardnews.ts +248 -0
  10. package/bin/commands/comfy.js +63 -0
  11. package/bin/commands/comfy.ts +54 -0
  12. package/bin/commands/config.js +270 -0
  13. package/bin/commands/config.ts +265 -0
  14. package/bin/commands/edit.js +97 -72
  15. package/bin/commands/edit.ts +116 -0
  16. package/bin/commands/gen.js +140 -118
  17. package/bin/commands/gen.ts +176 -0
  18. package/bin/commands/history.js +164 -0
  19. package/bin/commands/history.ts +145 -0
  20. package/bin/commands/ls.js +60 -42
  21. package/bin/commands/ls.ts +60 -0
  22. package/bin/commands/metadata.js +45 -0
  23. package/bin/commands/metadata.ts +36 -0
  24. package/bin/commands/multimode.js +159 -0
  25. package/bin/commands/multimode.ts +146 -0
  26. package/bin/commands/node.js +176 -0
  27. package/bin/commands/node.ts +157 -0
  28. package/bin/commands/observability.js +201 -0
  29. package/bin/commands/observability.ts +176 -0
  30. package/bin/commands/ping.js +26 -20
  31. package/bin/commands/ping.ts +29 -0
  32. package/bin/commands/prompt.js +506 -0
  33. package/bin/commands/prompt.ts +421 -0
  34. package/bin/commands/ps.js +78 -71
  35. package/bin/commands/ps.ts +78 -0
  36. package/bin/commands/session.js +308 -0
  37. package/bin/commands/session.ts +265 -0
  38. package/bin/commands/show.js +75 -40
  39. package/bin/commands/show.ts +69 -0
  40. package/bin/ima2.js +324 -310
  41. package/bin/ima2.ts +444 -0
  42. package/bin/lib/args.js +75 -66
  43. package/bin/lib/args.ts +73 -0
  44. package/bin/lib/browser-id.js +15 -0
  45. package/bin/lib/browser-id.ts +16 -0
  46. package/bin/lib/client.js +91 -83
  47. package/bin/lib/client.ts +109 -0
  48. package/bin/lib/error-hints.js +14 -17
  49. package/bin/lib/error-hints.ts +23 -0
  50. package/bin/lib/files.js +26 -28
  51. package/bin/lib/files.ts +39 -0
  52. package/bin/lib/output.js +44 -42
  53. package/bin/lib/output.ts +58 -0
  54. package/bin/lib/platform.js +60 -56
  55. package/bin/lib/platform.ts +97 -0
  56. package/bin/lib/sse.js +73 -0
  57. package/bin/lib/sse.ts +73 -0
  58. package/bin/lib/star-prompt.js +69 -76
  59. package/bin/lib/star-prompt.ts +97 -0
  60. package/bin/lib/storage-doctor.js +34 -35
  61. package/bin/lib/storage-doctor.ts +38 -0
  62. package/config.js +147 -243
  63. package/config.ts +331 -0
  64. package/docs/API.md +48 -8
  65. package/docs/CLI.md +190 -0
  66. package/docs/FAQ.ko.md +5 -5
  67. package/docs/FAQ.md +5 -5
  68. package/docs/README.ja.md +71 -25
  69. package/docs/README.ko.md +61 -24
  70. package/docs/README.zh-CN.md +73 -27
  71. package/lib/assetLifecycle.js +130 -130
  72. package/lib/assetLifecycle.ts +142 -0
  73. package/lib/canvasVersionStore.js +135 -153
  74. package/lib/canvasVersionStore.ts +181 -0
  75. package/lib/cardNewsGenerator.js +127 -142
  76. package/lib/cardNewsGenerator.ts +162 -0
  77. package/lib/cardNewsJobStore.js +78 -84
  78. package/lib/cardNewsJobStore.ts +107 -0
  79. package/lib/cardNewsManifestStore.js +88 -93
  80. package/lib/cardNewsManifestStore.ts +112 -0
  81. package/lib/cardNewsPlanner.js +157 -152
  82. package/lib/cardNewsPlanner.ts +180 -0
  83. package/lib/cardNewsPlannerClient.js +101 -98
  84. package/lib/cardNewsPlannerClient.ts +114 -0
  85. package/lib/cardNewsPlannerPrompt.js +56 -56
  86. package/lib/cardNewsPlannerPrompt.ts +60 -0
  87. package/lib/cardNewsPlannerSchema.js +231 -223
  88. package/lib/cardNewsPlannerSchema.ts +259 -0
  89. package/lib/cardNewsRoleTemplateStore.js +39 -41
  90. package/lib/cardNewsRoleTemplateStore.ts +47 -0
  91. package/lib/cardNewsTemplateStore.js +171 -175
  92. package/lib/cardNewsTemplateStore.ts +210 -0
  93. package/lib/codexDetect.js +44 -47
  94. package/lib/codexDetect.ts +69 -0
  95. package/lib/comfyBridge.js +164 -184
  96. package/lib/comfyBridge.ts +214 -0
  97. package/lib/db.js +41 -51
  98. package/lib/db.ts +166 -0
  99. package/lib/errorClassify.js +62 -78
  100. package/lib/errorClassify.ts +100 -0
  101. package/lib/generationErrors.js +140 -103
  102. package/lib/generationErrors.ts +125 -0
  103. package/lib/historyList.js +149 -147
  104. package/lib/historyList.ts +164 -0
  105. package/lib/imageMetadata.js +86 -89
  106. package/lib/imageMetadata.ts +111 -0
  107. package/lib/imageMetadataStore.js +46 -51
  108. package/lib/imageMetadataStore.ts +67 -0
  109. package/lib/imageModels.js +38 -45
  110. package/lib/imageModels.ts +52 -0
  111. package/lib/inflight.js +131 -150
  112. package/lib/inflight.ts +204 -0
  113. package/lib/localImportStore.js +87 -93
  114. package/lib/localImportStore.ts +111 -0
  115. package/lib/logger.js +105 -112
  116. package/lib/logger.ts +150 -0
  117. package/lib/nodeStore.js +65 -64
  118. package/lib/nodeStore.ts +81 -0
  119. package/lib/oauthLauncher.js +61 -59
  120. package/lib/oauthLauncher.ts +64 -0
  121. package/lib/oauthNormalize.js +15 -19
  122. package/lib/oauthNormalize.ts +30 -0
  123. package/lib/oauthProxy.js +834 -832
  124. package/lib/oauthProxy.ts +995 -0
  125. package/lib/openDirectory.js +41 -40
  126. package/lib/openDirectory.ts +45 -0
  127. package/lib/pngInfo.js +18 -20
  128. package/lib/pngInfo.ts +26 -0
  129. package/lib/promptImport/curatedSources.js +125 -129
  130. package/lib/promptImport/curatedSources.ts +139 -0
  131. package/lib/promptImport/discoveryRegistry.js +185 -203
  132. package/lib/promptImport/discoveryRegistry.ts +236 -0
  133. package/lib/promptImport/errors.js +10 -10
  134. package/lib/promptImport/errors.ts +18 -0
  135. package/lib/promptImport/githubDiscovery.js +209 -219
  136. package/lib/promptImport/githubDiscovery.ts +248 -0
  137. package/lib/promptImport/githubFolder.js +253 -259
  138. package/lib/promptImport/githubFolder.ts +308 -0
  139. package/lib/promptImport/githubSource.js +189 -200
  140. package/lib/promptImport/githubSource.ts +239 -0
  141. package/lib/promptImport/gptImageHints.js +49 -56
  142. package/lib/promptImport/gptImageHints.ts +68 -0
  143. package/lib/promptImport/parsePromptCandidates.js +108 -123
  144. package/lib/promptImport/parsePromptCandidates.ts +153 -0
  145. package/lib/promptImport/promptIndex.js +190 -208
  146. package/lib/promptImport/promptIndex.ts +248 -0
  147. package/lib/promptImport/rankPromptCandidates.js +46 -43
  148. package/lib/promptImport/rankPromptCandidates.ts +49 -0
  149. package/lib/providerOptions.js +31 -0
  150. package/lib/providerOptions.ts +41 -0
  151. package/lib/referenceImageCompress.js +51 -62
  152. package/lib/referenceImageCompress.ts +75 -0
  153. package/lib/refs.js +93 -81
  154. package/lib/refs.ts +117 -0
  155. package/lib/requestLogger.js +32 -38
  156. package/lib/requestLogger.ts +48 -0
  157. package/lib/responsesImageAdapter.js +351 -0
  158. package/lib/responsesImageAdapter.ts +352 -0
  159. package/lib/runtimePorts.js +71 -73
  160. package/lib/runtimePorts.ts +93 -0
  161. package/lib/sessionStore.js +179 -230
  162. package/lib/sessionStore.ts +272 -0
  163. package/lib/storageMigration.js +247 -245
  164. package/lib/storageMigration.ts +284 -0
  165. package/lib/styleSheet.js +86 -90
  166. package/lib/styleSheet.ts +128 -0
  167. package/lib/systemTrash.js +18 -0
  168. package/lib/systemTrash.ts +20 -0
  169. package/package.json +26 -10
  170. package/routes/annotations.js +76 -79
  171. package/routes/annotations.ts +95 -0
  172. package/routes/canvasVersions.js +50 -54
  173. package/routes/canvasVersions.ts +64 -0
  174. package/routes/cardNews.js +158 -171
  175. package/routes/cardNews.ts +183 -0
  176. package/routes/comfy.js +23 -31
  177. package/routes/comfy.ts +39 -0
  178. package/routes/edit.js +183 -214
  179. package/routes/edit.ts +230 -0
  180. package/routes/generate.js +269 -291
  181. package/routes/generate.ts +309 -0
  182. package/routes/health.js +102 -107
  183. package/routes/health.ts +114 -0
  184. package/routes/history.js +136 -144
  185. package/routes/history.ts +153 -0
  186. package/routes/imageImport.js +27 -27
  187. package/routes/imageImport.ts +33 -0
  188. package/routes/index.js +17 -17
  189. package/routes/index.ts +35 -0
  190. package/routes/metadata.js +60 -64
  191. package/routes/metadata.ts +71 -0
  192. package/routes/multimode.js +228 -263
  193. package/routes/multimode.ts +280 -0
  194. package/routes/nodes.js +378 -424
  195. package/routes/nodes.ts +455 -0
  196. package/routes/promptImport.js +284 -324
  197. package/routes/promptImport.ts +354 -0
  198. package/routes/prompts.js +333 -360
  199. package/routes/prompts.ts +379 -0
  200. package/routes/sessions.js +277 -285
  201. package/routes/sessions.ts +292 -0
  202. package/routes/storage.js +29 -31
  203. package/routes/storage.ts +39 -0
  204. package/server.js +189 -196
  205. package/server.ts +235 -0
  206. package/ui/dist/.vite/manifest.json +101 -0
  207. package/ui/dist/assets/CardNewsWorkspace-BJOCey7Z.js +2 -0
  208. package/ui/dist/assets/NodeCanvas-BZV40eAE.css +1 -0
  209. package/ui/dist/assets/NodeCanvas-C3dzYNsk.js +7 -0
  210. package/ui/dist/assets/PromptImportDialog-Dqu1VpUh.js +2 -0
  211. package/ui/dist/assets/PromptImportDiscoverySection-Dg8T9X0L.js +1 -0
  212. package/ui/dist/assets/PromptImportFolderSection-DBaqsFO4.js +1 -0
  213. package/ui/dist/assets/PromptLibraryPanel-p5QqR97M.js +2 -0
  214. package/ui/dist/assets/SettingsWorkspace-B5bSAZ6u.js +1 -0
  215. package/ui/dist/assets/index-C9cXwiWE.js +25 -0
  216. package/ui/dist/assets/index-CGMIkZXn.css +1 -0
  217. package/ui/dist/assets/index-Cvld7dUZ.js +1 -0
  218. package/ui/dist/index.html +2 -2
  219. package/assets/phase-a-bg-cleanup-test.png +0 -0
  220. package/assets/screenshot.png +0 -0
  221. package/assets/screenshots/classic-generate-light.png +0 -0
  222. package/assets/screenshots/node-graph-branching.png +0 -0
  223. package/assets/screenshots/settings-oauth-generation.png +0 -0
  224. package/assets/screenshots/settings-workspace.png +0 -0
  225. package/assets/screenshots/style-sheet-editor.png +0 -0
  226. package/integrations/comfyui/ima2_gen_bridge/__pycache__/__init__.cpython-313.pyc +0 -0
  227. package/integrations/comfyui/ima2_gen_bridge/__pycache__/nodes.cpython-313.pyc +0 -0
  228. package/ui/dist/assets/index-BDffwmLs.css +0 -1
  229. package/ui/dist/assets/index-D0fdHLkJ.js +0 -31
  230. package/ui/dist/assets/index-D0fdHLkJ.js.map +0 -1
@@ -1,284 +1,286 @@
1
1
  import { mkdir, readdir, copyFile, stat, constants } from "node:fs/promises";
2
2
  import { dirname, isAbsolute, join, resolve, sep } from "node:path";
3
3
  import { homedir } from "node:os";
4
-
5
4
  const PACKAGE_NAME = "ima2-gen";
6
5
  const RECOVERY_DOCS_PATH = "docs/RECOVER_OLD_IMAGES.md";
7
-
8
6
  function addStats(a, b) {
9
- return {
10
- copied: a.copied + b.copied,
11
- skippedExisting: a.skippedExisting + b.skippedExisting,
12
- };
7
+ return {
8
+ copied: a.copied + b.copied,
9
+ skippedExisting: a.skippedExisting + b.skippedExisting,
10
+ };
13
11
  }
14
-
15
12
  async function copyMissingTree(srcDir, dstDir) {
16
- await mkdir(dstDir, { recursive: true });
17
- const entries = await readdir(srcDir, { withFileTypes: true });
18
- let stats = { copied: 0, skippedExisting: 0 };
19
- for (const entry of entries) {
20
- const src = join(srcDir, entry.name);
21
- const dst = join(dstDir, entry.name);
22
- if (entry.isDirectory()) {
23
- stats = addStats(stats, await copyMissingTree(src, dst));
24
- continue;
25
- }
26
- if (!entry.isFile()) continue;
27
- try {
28
- await copyFile(src, dst, constants.COPYFILE_EXCL);
29
- stats.copied += 1;
30
- } catch (err) {
31
- if (err?.code !== "EEXIST") throw err;
32
- stats.skippedExisting += 1;
13
+ await mkdir(dstDir, { recursive: true });
14
+ const entries = await readdir(srcDir, { withFileTypes: true });
15
+ let stats = { copied: 0, skippedExisting: 0 };
16
+ for (const entry of entries) {
17
+ const src = join(srcDir, entry.name);
18
+ const dst = join(dstDir, entry.name);
19
+ if (entry.isDirectory()) {
20
+ stats = addStats(stats, await copyMissingTree(src, dst));
21
+ continue;
22
+ }
23
+ if (!entry.isFile())
24
+ continue;
25
+ try {
26
+ await copyFile(src, dst, constants.COPYFILE_EXCL);
27
+ stats.copied += 1;
28
+ }
29
+ catch (err) {
30
+ if (err?.code !== "EEXIST")
31
+ throw err;
32
+ stats.skippedExisting += 1;
33
+ }
33
34
  }
34
- }
35
- return stats;
35
+ return stats;
36
36
  }
37
-
38
37
  function isSameOrInside(child, parent) {
39
- const a = resolve(child);
40
- const b = resolve(parent);
41
- return a === b || a.startsWith(b + sep);
38
+ const a = resolve(child);
39
+ const b = resolve(parent);
40
+ return a === b || a.startsWith(b + sep);
42
41
  }
43
-
44
42
  export async function migrateGeneratedStorage(ctx, options = {}) {
45
- const targetDir = ctx.config.storage.generatedDir;
46
- const candidates = options.legacyDirs || await getLegacyGeneratedCandidates(ctx, options.env);
47
- const result = {
48
- copied: 0,
49
- skippedExisting: 0,
50
- sourcesScanned: 0,
51
- sourcesSkipped: 0,
52
- };
53
- try {
54
- for (const legacyDir of candidates) {
55
- if (isSameOrInside(legacyDir, targetDir) || isSameOrInside(targetDir, legacyDir)) {
56
- result.sourcesSkipped += 1;
57
- continue;
58
- }
59
- try {
60
- const legacyStat = await stat(legacyDir);
61
- if (!legacyStat.isDirectory()) continue;
62
- result.sourcesScanned += 1;
63
- const copyStats = await copyMissingTree(legacyDir, targetDir);
64
- result.copied += copyStats.copied;
65
- result.skippedExisting += copyStats.skippedExisting;
66
- } catch (err) {
67
- if (err?.code !== "ENOENT") {
68
- console.warn("[storage] generated asset migration source skipped:", legacyDir, err.message);
43
+ const targetDir = ctx.config.storage.generatedDir;
44
+ const candidates = options.legacyDirs || await getLegacyGeneratedCandidates(ctx, options.env);
45
+ const result = {
46
+ copied: 0,
47
+ skippedExisting: 0,
48
+ sourcesScanned: 0,
49
+ sourcesSkipped: 0,
50
+ };
51
+ try {
52
+ for (const legacyDir of candidates) {
53
+ if (isSameOrInside(legacyDir, targetDir) || isSameOrInside(targetDir, legacyDir)) {
54
+ result.sourcesSkipped += 1;
55
+ continue;
56
+ }
57
+ try {
58
+ const legacyStat = await stat(legacyDir);
59
+ if (!legacyStat.isDirectory())
60
+ continue;
61
+ result.sourcesScanned += 1;
62
+ const copyStats = await copyMissingTree(legacyDir, targetDir);
63
+ result.copied += copyStats.copied;
64
+ result.skippedExisting += copyStats.skippedExisting;
65
+ }
66
+ catch (err) {
67
+ if (err?.code !== "ENOENT") {
68
+ console.warn("[storage] generated asset migration source skipped:", legacyDir, err.message);
69
+ }
70
+ }
69
71
  }
70
- }
72
+ if (result.copied > 0)
73
+ console.log(`[storage] migrated ${result.copied} generated assets to ${targetDir}`);
71
74
  }
72
- if (result.copied > 0) console.log(`[storage] migrated ${result.copied} generated assets to ${targetDir}`);
73
- } catch (err) {
74
- console.warn("[storage] generated asset migration skipped:", err.message);
75
- }
76
- return result;
75
+ catch (err) {
76
+ console.warn("[storage] generated asset migration skipped:", err.message);
77
+ }
78
+ return result;
77
79
  }
78
-
79
80
  export async function getLegacyGeneratedCandidates(ctx, env = process.env) {
80
- const home = env.IMA2_TEST_HOME || homedir();
81
- const execPath = env.IMA2_TEST_EXEC_PATH || process.execPath;
82
- const argv1 = env.IMA2_TEST_ARGV1 || process.argv[1] || "";
83
- const nodePrefix = dirname(dirname(execPath));
84
- const prefixes = getGlobalPrefixCandidates({ env, execPath, argv1 });
85
- const appData = env.APPDATA || join(home, "AppData", "Roaming");
86
- const localAppData = env.LOCALAPPDATA || join(home, "AppData", "Local");
87
- const npmCache = env.npm_config_cache || join(home, ".npm");
88
- const xdgDataHome = env.XDG_DATA_HOME || join(home, ".local", "share");
89
- const pnpmHome = env.PNPM_HOME || "";
90
- const nvmHome = env.NVM_HOME || join(appData, "nvm");
91
-
92
- const candidates = [
93
- join(ctx.rootDir, "generated"),
94
- join(appData, "npm", "node_modules", PACKAGE_NAME, "generated"),
95
- join(home, ".npm-global", "lib", "node_modules", PACKAGE_NAME, "generated"),
96
- join(home, ".nvm", "versions", "node", process.version, "lib", "node_modules", PACKAGE_NAME, "generated"),
97
- join(home, ".volta", "tools", "image", "packages", PACKAGE_NAME, "lib", "node_modules", PACKAGE_NAME, "generated"),
98
- join(home, ".fnm", "node-versions", process.version, "installation", "lib", "node_modules", PACKAGE_NAME, "generated"),
99
- join(home, ".bun", "install", "global", "node_modules", PACKAGE_NAME, "generated"),
100
- join(home, ".config", "yarn", "global", "node_modules", PACKAGE_NAME, "generated"),
101
- join(localAppData, "Yarn", "Data", "global", "node_modules", PACKAGE_NAME, "generated"),
102
- join(localAppData, "Volta", "tools", "image", "packages", PACKAGE_NAME, "lib", "node_modules", PACKAGE_NAME, "generated"),
103
- join(nvmHome, process.version, "node_modules", PACKAGE_NAME, "generated"),
104
- join(dirname(execPath), "node_modules", PACKAGE_NAME, "generated"),
105
- ];
106
-
107
- for (const prefix of prefixes) {
108
- candidates.push(join(prefix, "lib", "node_modules", PACKAGE_NAME, "generated"));
109
- candidates.push(join(prefix, "node_modules", PACKAGE_NAME, "generated"));
110
- }
111
-
112
- candidates.push(join(nodePrefix, "lib", "node_modules", PACKAGE_NAME, "generated"));
113
- candidates.push(
114
- ...await expandOneLevelCandidates([
115
- [join(home, ".nvm", "versions", "node"), ["*", "lib", "node_modules", PACKAGE_NAME, "generated"]],
116
- [join(home, ".fnm", "node-versions"), ["*", "installation", "lib", "node_modules", PACKAGE_NAME, "generated"]],
117
- [join(home, ".asdf", "installs", "nodejs"), ["*", "lib", "node_modules", PACKAGE_NAME, "generated"]],
118
- [join(home, ".local", "share", "mise", "installs", "node"), ["*", "lib", "node_modules", PACKAGE_NAME, "generated"]],
119
- [join(home, "Library", "pnpm", "global"), ["*", "node_modules", PACKAGE_NAME, "generated"]],
120
- [join(xdgDataHome, "pnpm", "global"), ["*", "node_modules", PACKAGE_NAME, "generated"]],
121
- [join(localAppData, "pnpm", "global"), ["*", "node_modules", PACKAGE_NAME, "generated"]],
122
- [pnpmHome ? join(pnpmHome, "global") : "", ["*", "node_modules", PACKAGE_NAME, "generated"]],
123
- [join(npmCache, "_npx"), ["*", "node_modules", PACKAGE_NAME, "generated"]],
124
- [join(localAppData, "npm-cache", "_npx"), ["*", "node_modules", PACKAGE_NAME, "generated"]],
125
- [join(appData, "npm-cache", "_npx"), ["*", "node_modules", PACKAGE_NAME, "generated"]],
126
- [nvmHome, ["*", "node_modules", PACKAGE_NAME, "generated"]],
127
- ]),
128
- );
129
- return uniqueResolvedCandidates(candidates);
81
+ const home = env.IMA2_TEST_HOME || homedir();
82
+ const execPath = env.IMA2_TEST_EXEC_PATH || process.execPath;
83
+ const argv1 = env.IMA2_TEST_ARGV1 || process.argv[1] || "";
84
+ const nodePrefix = dirname(dirname(execPath));
85
+ const prefixes = getGlobalPrefixCandidates({ env, execPath, argv1 });
86
+ const appData = env.APPDATA || join(home, "AppData", "Roaming");
87
+ const localAppData = env.LOCALAPPDATA || join(home, "AppData", "Local");
88
+ const npmCache = env.npm_config_cache || join(home, ".npm");
89
+ const xdgDataHome = env.XDG_DATA_HOME || join(home, ".local", "share");
90
+ const pnpmHome = env.PNPM_HOME || "";
91
+ const nvmHome = env.NVM_HOME || join(appData, "nvm");
92
+ const candidates = [
93
+ join(ctx.rootDir, "generated"),
94
+ join(appData, "npm", "node_modules", PACKAGE_NAME, "generated"),
95
+ join(home, ".npm-global", "lib", "node_modules", PACKAGE_NAME, "generated"),
96
+ join(home, ".nvm", "versions", "node", process.version, "lib", "node_modules", PACKAGE_NAME, "generated"),
97
+ join(home, ".volta", "tools", "image", "packages", PACKAGE_NAME, "lib", "node_modules", PACKAGE_NAME, "generated"),
98
+ join(home, ".fnm", "node-versions", process.version, "installation", "lib", "node_modules", PACKAGE_NAME, "generated"),
99
+ join(home, ".bun", "install", "global", "node_modules", PACKAGE_NAME, "generated"),
100
+ join(home, ".config", "yarn", "global", "node_modules", PACKAGE_NAME, "generated"),
101
+ join(localAppData, "Yarn", "Data", "global", "node_modules", PACKAGE_NAME, "generated"),
102
+ join(localAppData, "Volta", "tools", "image", "packages", PACKAGE_NAME, "lib", "node_modules", PACKAGE_NAME, "generated"),
103
+ join(nvmHome, process.version, "node_modules", PACKAGE_NAME, "generated"),
104
+ join(dirname(execPath), "node_modules", PACKAGE_NAME, "generated"),
105
+ ];
106
+ for (const prefix of prefixes) {
107
+ candidates.push(join(prefix, "lib", "node_modules", PACKAGE_NAME, "generated"));
108
+ candidates.push(join(prefix, "node_modules", PACKAGE_NAME, "generated"));
109
+ }
110
+ candidates.push(join(nodePrefix, "lib", "node_modules", PACKAGE_NAME, "generated"));
111
+ candidates.push(...await expandOneLevelCandidates([
112
+ [join(home, ".nvm", "versions", "node"), ["*", "lib", "node_modules", PACKAGE_NAME, "generated"]],
113
+ [join(home, ".fnm", "node-versions"), ["*", "installation", "lib", "node_modules", PACKAGE_NAME, "generated"]],
114
+ [join(home, ".asdf", "installs", "nodejs"), ["*", "lib", "node_modules", PACKAGE_NAME, "generated"]],
115
+ [join(home, ".local", "share", "mise", "installs", "node"), ["*", "lib", "node_modules", PACKAGE_NAME, "generated"]],
116
+ [join(home, "Library", "pnpm", "global"), ["*", "node_modules", PACKAGE_NAME, "generated"]],
117
+ [join(xdgDataHome, "pnpm", "global"), ["*", "node_modules", PACKAGE_NAME, "generated"]],
118
+ [join(localAppData, "pnpm", "global"), ["*", "node_modules", PACKAGE_NAME, "generated"]],
119
+ [pnpmHome ? join(pnpmHome, "global") : "", ["*", "node_modules", PACKAGE_NAME, "generated"]],
120
+ [join(npmCache, "_npx"), ["*", "node_modules", PACKAGE_NAME, "generated"]],
121
+ [join(localAppData, "npm-cache", "_npx"), ["*", "node_modules", PACKAGE_NAME, "generated"]],
122
+ [join(appData, "npm-cache", "_npx"), ["*", "node_modules", PACKAGE_NAME, "generated"]],
123
+ [nvmHome, ["*", "node_modules", PACKAGE_NAME, "generated"]],
124
+ ]));
125
+ return uniqueResolvedCandidates(candidates);
130
126
  }
131
-
132
127
  export async function inspectGeneratedStorage(ctx, options = {}) {
133
- const env = options.env || process.env;
134
- const targetDir = ctx.config.storage.generatedDir;
135
- try {
136
- const candidates = options.legacyDirs || await getLegacyGeneratedCandidates(ctx, env);
137
- const targetFileCount = await countFiles(targetDir);
138
- const legacySources = [];
139
-
140
- for (const candidate of candidates) {
141
- if (isSameOrInside(candidate, targetDir) || isSameOrInside(targetDir, candidate)) continue;
142
- try {
143
- const candidateStat = await stat(candidate);
144
- if (!candidateStat.isDirectory()) continue;
145
- const fileCount = await countFiles(candidate);
146
- if (fileCount > 0) legacySources.push({ path: candidate, fileCount });
147
- } catch (err) {
148
- if (err?.code !== "ENOENT") {
149
- console.warn("[storage] legacy candidate inspect skipped:", candidate, err.message);
128
+ const env = options.env || process.env;
129
+ const targetDir = ctx.config.storage.generatedDir;
130
+ try {
131
+ const candidates = options.legacyDirs || await getLegacyGeneratedCandidates(ctx, env);
132
+ const targetFileCount = await countFiles(targetDir);
133
+ const legacySources = [];
134
+ for (const candidate of candidates) {
135
+ if (isSameOrInside(candidate, targetDir) || isSameOrInside(targetDir, candidate))
136
+ continue;
137
+ try {
138
+ const candidateStat = await stat(candidate);
139
+ if (!candidateStat.isDirectory())
140
+ continue;
141
+ const fileCount = await countFiles(candidate);
142
+ if (fileCount > 0)
143
+ legacySources.push({ path: candidate, fileCount });
144
+ }
145
+ catch (err) {
146
+ if (err?.code !== "ENOENT") {
147
+ console.warn("[storage] legacy candidate inspect skipped:", candidate, err.message);
148
+ }
149
+ }
150
150
  }
151
- }
151
+ const legacyFilesFound = legacySources.reduce((sum, source) => sum + source.fileCount, 0);
152
+ const state = targetFileCount > 0 ? "ok"
153
+ : legacyFilesFound > 0 ? "recoverable"
154
+ : "not_found";
155
+ return {
156
+ ok: true,
157
+ targetDir,
158
+ generatedDirLabel: labelPath(targetDir, env),
159
+ targetExists: await isDirectory(targetDir),
160
+ targetFileCount,
161
+ legacyCandidatesScanned: candidates.length,
162
+ legacySourcesFound: legacySources.length,
163
+ legacyFilesFound,
164
+ legacySources,
165
+ overrides: {
166
+ generatedDir: Boolean(env.IMA2_GENERATED_DIR),
167
+ configDir: Boolean(env.IMA2_CONFIG_DIR),
168
+ },
169
+ state,
170
+ messageKind: state === "not_found" ? "apology" : state,
171
+ recoveryDocsPath: RECOVERY_DOCS_PATH,
172
+ doctorCommand: "ima2 doctor",
173
+ };
174
+ }
175
+ catch (err) {
176
+ return {
177
+ ok: false,
178
+ targetDir,
179
+ generatedDirLabel: labelPath(targetDir, env),
180
+ targetExists: false,
181
+ targetFileCount: 0,
182
+ legacyCandidatesScanned: 0,
183
+ legacySourcesFound: 0,
184
+ legacyFilesFound: 0,
185
+ legacySources: [],
186
+ overrides: {
187
+ generatedDir: Boolean(env.IMA2_GENERATED_DIR),
188
+ configDir: Boolean(env.IMA2_CONFIG_DIR),
189
+ },
190
+ state: "unknown",
191
+ messageKind: "unknown",
192
+ recoveryDocsPath: RECOVERY_DOCS_PATH,
193
+ doctorCommand: "ima2 doctor",
194
+ error: err?.message || String(err),
195
+ };
152
196
  }
153
-
154
- const legacyFilesFound = legacySources.reduce((sum, source) => sum + source.fileCount, 0);
155
- const state =
156
- targetFileCount > 0 ? "ok"
157
- : legacyFilesFound > 0 ? "recoverable"
158
- : "not_found";
159
-
160
- return {
161
- ok: true,
162
- targetDir,
163
- generatedDirLabel: labelPath(targetDir, env),
164
- targetExists: await isDirectory(targetDir),
165
- targetFileCount,
166
- legacyCandidatesScanned: candidates.length,
167
- legacySourcesFound: legacySources.length,
168
- legacyFilesFound,
169
- legacySources,
170
- overrides: {
171
- generatedDir: Boolean(env.IMA2_GENERATED_DIR),
172
- configDir: Boolean(env.IMA2_CONFIG_DIR),
173
- },
174
- state,
175
- messageKind: state === "not_found" ? "apology" : state,
176
- recoveryDocsPath: RECOVERY_DOCS_PATH,
177
- doctorCommand: "ima2 doctor",
178
- };
179
- } catch (err) {
180
- return {
181
- ok: false,
182
- targetDir,
183
- generatedDirLabel: labelPath(targetDir, env),
184
- targetExists: false,
185
- targetFileCount: 0,
186
- legacyCandidatesScanned: 0,
187
- legacySourcesFound: 0,
188
- legacyFilesFound: 0,
189
- legacySources: [],
190
- overrides: {
191
- generatedDir: Boolean(env.IMA2_GENERATED_DIR),
192
- configDir: Boolean(env.IMA2_CONFIG_DIR),
193
- },
194
- state: "unknown",
195
- messageKind: "unknown",
196
- recoveryDocsPath: RECOVERY_DOCS_PATH,
197
- doctorCommand: "ima2 doctor",
198
- error: err?.message || String(err),
199
- };
200
- }
201
197
  }
202
-
203
198
  async function expandOneLevelCandidates(patterns) {
204
- const candidates = [];
205
- for (const [baseDir, segments] of patterns) {
206
- if (!baseDir) continue;
207
- candidates.push(...await expandOneLevelPattern(baseDir, segments));
208
- }
209
- return candidates;
199
+ const candidates = [];
200
+ for (const [baseDir, segments] of patterns) {
201
+ if (!baseDir)
202
+ continue;
203
+ candidates.push(...await expandOneLevelPattern(baseDir, segments));
204
+ }
205
+ return candidates;
210
206
  }
211
-
212
207
  async function expandOneLevelPattern(baseDir, segments) {
213
- const wildcardIndex = segments.indexOf("*");
214
- if (wildcardIndex < 0) return [join(baseDir, ...segments)];
215
-
216
- const before = segments.slice(0, wildcardIndex);
217
- const after = segments.slice(wildcardIndex + 1);
218
- const wildcardBase = join(baseDir, ...before);
219
- try {
220
- const entries = await readdir(wildcardBase, { withFileTypes: true });
221
- return entries
222
- .filter((entry) => entry.isDirectory())
223
- .map((entry) => join(wildcardBase, entry.name, ...after));
224
- } catch (err) {
225
- if (err?.code === "ENOENT") return [];
226
- console.warn("[storage] legacy candidate scan skipped:", wildcardBase, err.message);
227
- return [];
228
- }
208
+ const wildcardIndex = segments.indexOf("*");
209
+ if (wildcardIndex < 0)
210
+ return [join(baseDir, ...segments)];
211
+ const before = segments.slice(0, wildcardIndex);
212
+ const after = segments.slice(wildcardIndex + 1);
213
+ const wildcardBase = join(baseDir, ...before);
214
+ try {
215
+ const entries = await readdir(wildcardBase, { withFileTypes: true });
216
+ return entries
217
+ .filter((entry) => entry.isDirectory())
218
+ .map((entry) => join(wildcardBase, entry.name, ...after));
219
+ }
220
+ catch (err) {
221
+ if (err?.code === "ENOENT")
222
+ return [];
223
+ console.warn("[storage] legacy candidate scan skipped:", wildcardBase, err.message);
224
+ return [];
225
+ }
229
226
  }
230
-
231
227
  async function countFiles(dir) {
232
- try {
233
- const entries = await readdir(dir, { withFileTypes: true });
234
- let count = 0;
235
- for (const entry of entries) {
236
- if (entry.name === ".trash") continue;
237
- const fullPath = join(dir, entry.name);
238
- if (entry.isDirectory()) count += await countFiles(fullPath);
239
- else if (entry.isFile()) count += 1;
228
+ try {
229
+ const entries = await readdir(dir, { withFileTypes: true });
230
+ let count = 0;
231
+ for (const entry of entries) {
232
+ if (entry.name === ".trash")
233
+ continue;
234
+ const fullPath = join(dir, entry.name);
235
+ if (entry.isDirectory())
236
+ count += await countFiles(fullPath);
237
+ else if (entry.isFile())
238
+ count += 1;
239
+ }
240
+ return count;
241
+ }
242
+ catch (err) {
243
+ if (err?.code === "ENOENT")
244
+ return 0;
245
+ throw err;
240
246
  }
241
- return count;
242
- } catch (err) {
243
- if (err?.code === "ENOENT") return 0;
244
- throw err;
245
- }
246
247
  }
247
-
248
248
  async function isDirectory(dir) {
249
- try {
250
- return (await stat(dir)).isDirectory();
251
- } catch {
252
- return false;
253
- }
249
+ try {
250
+ return (await stat(dir)).isDirectory();
251
+ }
252
+ catch {
253
+ return false;
254
+ }
254
255
  }
255
-
256
256
  function uniqueResolvedCandidates(candidates) {
257
- return Array.from(new Set(candidates.filter(Boolean).map((p) => resolve(p))));
257
+ return Array.from(new Set(candidates.filter(Boolean).map((p) => resolve(p))));
258
258
  }
259
-
260
259
  function labelPath(targetPath, env = process.env) {
261
- const home = env.IMA2_TEST_HOME || homedir();
262
- const resolved = resolve(targetPath);
263
- const resolvedHome = resolve(home);
264
- if (resolved === resolvedHome) return "~";
265
- if (resolved.startsWith(resolvedHome + sep)) return `~${sep}${resolved.slice(resolvedHome.length + 1)}`;
266
- return resolved;
260
+ const home = env.IMA2_TEST_HOME || homedir();
261
+ const resolved = resolve(targetPath);
262
+ const resolvedHome = resolve(home);
263
+ if (resolved === resolvedHome)
264
+ return "~";
265
+ if (resolved.startsWith(resolvedHome + sep))
266
+ return `~${sep}${resolved.slice(resolvedHome.length + 1)}`;
267
+ return resolved;
267
268
  }
268
-
269
269
  function getGlobalPrefixCandidates({ env, execPath, argv1 }) {
270
- const prefixes = new Set();
271
- if (env.npm_config_prefix) prefixes.add(env.npm_config_prefix);
272
- if (isAbsolute(argv1)) prefixes.add(dirname(dirname(argv1)));
273
- prefixes.add(dirname(dirname(execPath)));
274
- addHomebrewPrefix(prefixes, execPath);
275
- prefixes.add("/opt/homebrew");
276
- prefixes.add("/usr/local");
277
- return Array.from(prefixes);
270
+ const prefixes = new Set();
271
+ if (env.npm_config_prefix)
272
+ prefixes.add(env.npm_config_prefix);
273
+ if (isAbsolute(argv1))
274
+ prefixes.add(dirname(dirname(argv1)));
275
+ prefixes.add(dirname(dirname(execPath)));
276
+ addHomebrewPrefix(prefixes, execPath);
277
+ prefixes.add("/opt/homebrew");
278
+ prefixes.add("/usr/local");
279
+ return Array.from(prefixes);
278
280
  }
279
-
280
281
  function addHomebrewPrefix(prefixes, execPath) {
281
- const marker = `${sep}Cellar${sep}node`;
282
- const idx = execPath.indexOf(marker);
283
- if (idx > 0) prefixes.add(execPath.slice(0, idx));
282
+ const marker = `${sep}Cellar${sep}node`;
283
+ const idx = execPath.indexOf(marker);
284
+ if (idx > 0)
285
+ prefixes.add(execPath.slice(0, idx));
284
286
  }