@detergent-software/atk 8.9.0-dev.3 → 8.9.0-dev.31

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 (275) hide show
  1. package/CHANGELOG.md +211 -0
  2. package/README.md +22 -12
  3. package/build/cli.js +18 -6
  4. package/build/cli.js.map +1 -1
  5. package/build/command-manifest.json +1507 -0
  6. package/build/commands/_app.d.ts.map +1 -1
  7. package/build/commands/_app.js +8 -4
  8. package/build/commands/_app.js.map +1 -1
  9. package/build/commands/audit.d.ts.map +1 -1
  10. package/build/commands/audit.js +1 -1
  11. package/build/commands/audit.js.map +1 -1
  12. package/build/commands/browse.js +2 -2
  13. package/build/commands/browse.js.map +1 -1
  14. package/build/commands/cache.d.ts +1 -1
  15. package/build/commands/cache.d.ts.map +1 -1
  16. package/build/commands/cache.js +1 -16
  17. package/build/commands/cache.js.map +1 -1
  18. package/build/commands/config.d.ts.map +1 -1
  19. package/build/commands/config.js +1 -1
  20. package/build/commands/config.js.map +1 -1
  21. package/build/commands/diff.d.ts.map +1 -1
  22. package/build/commands/diff.js +4 -0
  23. package/build/commands/diff.js.map +1 -1
  24. package/build/commands/drift.d.ts.map +1 -1
  25. package/build/commands/drift.js +4 -0
  26. package/build/commands/drift.js.map +1 -1
  27. package/build/commands/index.d.ts.map +1 -1
  28. package/build/commands/index.js +5 -40
  29. package/build/commands/index.js.map +1 -1
  30. package/build/commands/info.d.ts.map +1 -1
  31. package/build/commands/info.js +50 -33
  32. package/build/commands/info.js.map +1 -1
  33. package/build/commands/init.d.ts.map +1 -1
  34. package/build/commands/init.js +4 -2
  35. package/build/commands/init.js.map +1 -1
  36. package/build/commands/install.d.ts.map +1 -1
  37. package/build/commands/install.js +28 -7
  38. package/build/commands/install.js.map +1 -1
  39. package/build/commands/list.js +2 -2
  40. package/build/commands/list.js.map +1 -1
  41. package/build/commands/login.d.ts.map +1 -1
  42. package/build/commands/login.js +12 -2
  43. package/build/commands/login.js.map +1 -1
  44. package/build/commands/logout.d.ts.map +1 -1
  45. package/build/commands/logout.js +9 -1
  46. package/build/commands/logout.js.map +1 -1
  47. package/build/commands/outdated.js +1 -1
  48. package/build/commands/outdated.js.map +1 -1
  49. package/build/commands/prune.d.ts.map +1 -1
  50. package/build/commands/prune.js +4 -2
  51. package/build/commands/prune.js.map +1 -1
  52. package/build/commands/publish.d.ts +1 -1
  53. package/build/commands/publish.d.ts.map +1 -1
  54. package/build/commands/publish.js +31 -36
  55. package/build/commands/publish.js.map +1 -1
  56. package/build/commands/release-notes.d.ts.map +1 -1
  57. package/build/commands/release-notes.js +4 -0
  58. package/build/commands/release-notes.js.map +1 -1
  59. package/build/commands/schema.d.ts +3 -3
  60. package/build/commands/search.js +1 -1
  61. package/build/commands/search.js.map +1 -1
  62. package/build/commands/sync.d.ts +1 -1
  63. package/build/commands/sync.d.ts.map +1 -1
  64. package/build/commands/sync.js +27 -12
  65. package/build/commands/sync.js.map +1 -1
  66. package/build/commands/update.d.ts.map +1 -1
  67. package/build/commands/update.js +58 -9
  68. package/build/commands/update.js.map +1 -1
  69. package/build/commands/whoami.d.ts.map +1 -1
  70. package/build/commands/whoami.js +16 -4
  71. package/build/commands/whoami.js.map +1 -1
  72. package/build/commands/why.js +3 -4
  73. package/build/commands/why.js.map +1 -1
  74. package/build/components/Header.d.ts +2 -3
  75. package/build/components/Header.d.ts.map +1 -1
  76. package/build/components/Header.js +2 -9
  77. package/build/components/Header.js.map +1 -1
  78. package/build/components/LocalEditsHint.d.ts +16 -0
  79. package/build/components/LocalEditsHint.d.ts.map +1 -0
  80. package/build/components/LocalEditsHint.js +18 -0
  81. package/build/components/LocalEditsHint.js.map +1 -0
  82. package/build/components/SyncAllInSync.d.ts +5 -1
  83. package/build/components/SyncAllInSync.d.ts.map +1 -1
  84. package/build/components/SyncAllInSync.js +2 -2
  85. package/build/components/SyncAllInSync.js.map +1 -1
  86. package/build/components/header-art.d.ts +7 -0
  87. package/build/components/header-art.d.ts.map +1 -0
  88. package/build/components/header-art.js +14 -0
  89. package/build/components/header-art.js.map +1 -0
  90. package/build/components/index.d.ts +1 -0
  91. package/build/components/index.d.ts.map +1 -1
  92. package/build/components/index.js +1 -0
  93. package/build/components/index.js.map +1 -1
  94. package/build/hooks/useListActions.d.ts.map +1 -1
  95. package/build/hooks/useListActions.js +4 -0
  96. package/build/hooks/useListActions.js.map +1 -1
  97. package/build/hooks/usePruneState.d.ts +1 -7
  98. package/build/hooks/usePruneState.d.ts.map +1 -1
  99. package/build/hooks/usePruneState.js +18 -62
  100. package/build/hooks/usePruneState.js.map +1 -1
  101. package/build/hooks/usePublishState.d.ts +43 -8
  102. package/build/hooks/usePublishState.d.ts.map +1 -1
  103. package/build/hooks/usePublishState.js +82 -565
  104. package/build/hooks/usePublishState.js.map +1 -1
  105. package/build/lib/adapter.d.ts +10 -1
  106. package/build/lib/adapter.d.ts.map +1 -1
  107. package/build/lib/adapter.js +46 -3
  108. package/build/lib/adapter.js.map +1 -1
  109. package/build/lib/api-client.d.ts +9 -5
  110. package/build/lib/api-client.d.ts.map +1 -1
  111. package/build/lib/api-client.js +35 -8
  112. package/build/lib/api-client.js.map +1 -1
  113. package/build/lib/atk-api/generated/types.gen.d.ts +4 -4
  114. package/build/lib/auth.d.ts +12 -2
  115. package/build/lib/auth.d.ts.map +1 -1
  116. package/build/lib/auth.js +38 -3
  117. package/build/lib/auth.js.map +1 -1
  118. package/build/lib/checksum.d.ts +40 -14
  119. package/build/lib/checksum.d.ts.map +1 -1
  120. package/build/lib/checksum.js +110 -57
  121. package/build/lib/checksum.js.map +1 -1
  122. package/build/lib/config.d.ts +4 -4
  123. package/build/lib/config.d.ts.map +1 -1
  124. package/build/lib/config.js +31 -8
  125. package/build/lib/config.js.map +1 -1
  126. package/build/lib/diagnostics.d.ts.map +1 -1
  127. package/build/lib/diagnostics.js +10 -7
  128. package/build/lib/diagnostics.js.map +1 -1
  129. package/build/lib/diff-command.js +1 -1
  130. package/build/lib/diff-command.js.map +1 -1
  131. package/build/lib/errors.d.ts +4 -1
  132. package/build/lib/errors.d.ts.map +1 -1
  133. package/build/lib/errors.js.map +1 -1
  134. package/build/lib/format-age.d.ts +3 -0
  135. package/build/lib/format-age.d.ts.map +1 -0
  136. package/build/lib/format-age.js +18 -0
  137. package/build/lib/format-age.js.map +1 -0
  138. package/build/lib/installer.d.ts +8 -11
  139. package/build/lib/installer.d.ts.map +1 -1
  140. package/build/lib/installer.js +83 -28
  141. package/build/lib/installer.js.map +1 -1
  142. package/build/lib/local-edits.d.ts +72 -0
  143. package/build/lib/local-edits.d.ts.map +1 -0
  144. package/build/lib/local-edits.js +145 -0
  145. package/build/lib/local-edits.js.map +1 -0
  146. package/build/lib/lockfile.d.ts +12 -8
  147. package/build/lib/lockfile.d.ts.map +1 -1
  148. package/build/lib/lockfile.js +209 -59
  149. package/build/lib/lockfile.js.map +1 -1
  150. package/build/lib/mover.d.ts.map +1 -1
  151. package/build/lib/mover.js +11 -12
  152. package/build/lib/mover.js.map +1 -1
  153. package/build/lib/multi-tool-install.d.ts +4 -2
  154. package/build/lib/multi-tool-install.d.ts.map +1 -1
  155. package/build/lib/multi-tool-install.js +12 -2
  156. package/build/lib/multi-tool-install.js.map +1 -1
  157. package/build/lib/offline.d.ts +19 -0
  158. package/build/lib/offline.d.ts.map +1 -0
  159. package/build/lib/offline.js +26 -0
  160. package/build/lib/offline.js.map +1 -0
  161. package/build/lib/owned-paths.d.ts +7 -4
  162. package/build/lib/owned-paths.d.ts.map +1 -1
  163. package/build/lib/owned-paths.js +23 -8
  164. package/build/lib/owned-paths.js.map +1 -1
  165. package/build/lib/parse-json.d.ts +12 -0
  166. package/build/lib/parse-json.d.ts.map +1 -1
  167. package/build/lib/parse-json.js +15 -2
  168. package/build/lib/parse-json.js.map +1 -1
  169. package/build/lib/pastel/commander-specs.d.ts +7 -0
  170. package/build/lib/pastel/commander-specs.d.ts.map +1 -0
  171. package/build/lib/pastel/commander-specs.js +50 -0
  172. package/build/lib/pastel/commander-specs.js.map +1 -0
  173. package/build/lib/pastel/generate-arguments.d.ts +3 -3
  174. package/build/lib/pastel/generate-arguments.d.ts.map +1 -1
  175. package/build/lib/pastel/generate-arguments.js +25 -22
  176. package/build/lib/pastel/generate-arguments.js.map +1 -1
  177. package/build/lib/pastel/generate-command.d.ts +7 -5
  178. package/build/lib/pastel/generate-command.d.ts.map +1 -1
  179. package/build/lib/pastel/generate-command.js +32 -67
  180. package/build/lib/pastel/generate-command.js.map +1 -1
  181. package/build/lib/pastel/generate-commands.d.ts +3 -5
  182. package/build/lib/pastel/generate-commands.d.ts.map +1 -1
  183. package/build/lib/pastel/generate-commands.js +6 -10
  184. package/build/lib/pastel/generate-commands.js.map +1 -1
  185. package/build/lib/pastel/generate-options.d.ts +3 -3
  186. package/build/lib/pastel/generate-options.d.ts.map +1 -1
  187. package/build/lib/pastel/generate-options.js +16 -13
  188. package/build/lib/pastel/generate-options.js.map +1 -1
  189. package/build/lib/pastel/index.d.ts +26 -4
  190. package/build/lib/pastel/index.d.ts.map +1 -1
  191. package/build/lib/pastel/index.js +104 -18
  192. package/build/lib/pastel/index.js.map +1 -1
  193. package/build/lib/pastel/internal-types.d.ts +39 -8
  194. package/build/lib/pastel/internal-types.d.ts.map +1 -1
  195. package/build/lib/pastel/manifest.d.ts +8 -0
  196. package/build/lib/pastel/manifest.d.ts.map +1 -0
  197. package/build/lib/pastel/manifest.js +7 -0
  198. package/build/lib/pastel/manifest.js.map +1 -0
  199. package/build/lib/pastel/read-commands.d.ts +7 -2
  200. package/build/lib/pastel/read-commands.d.ts.map +1 -1
  201. package/build/lib/pastel/read-commands.js +51 -30
  202. package/build/lib/pastel/read-commands.js.map +1 -1
  203. package/build/lib/pastel/render-command.d.ts +13 -0
  204. package/build/lib/pastel/render-command.d.ts.map +1 -0
  205. package/build/lib/pastel/render-command.js +56 -0
  206. package/build/lib/pastel/render-command.js.map +1 -0
  207. package/build/lib/process-alive.d.ts +8 -0
  208. package/build/lib/process-alive.d.ts.map +1 -0
  209. package/build/lib/process-alive.js +16 -0
  210. package/build/lib/process-alive.js.map +1 -0
  211. package/build/lib/pruner.d.ts +26 -0
  212. package/build/lib/pruner.d.ts.map +1 -0
  213. package/build/lib/pruner.js +42 -0
  214. package/build/lib/pruner.js.map +1 -0
  215. package/build/lib/publish-flow.d.ts +7 -15
  216. package/build/lib/publish-flow.d.ts.map +1 -1
  217. package/build/lib/publish-flow.js +634 -178
  218. package/build/lib/publish-flow.js.map +1 -1
  219. package/build/lib/publish-run.d.ts +55 -0
  220. package/build/lib/publish-run.d.ts.map +1 -0
  221. package/build/lib/publish-run.js +169 -0
  222. package/build/lib/publish-run.js.map +1 -0
  223. package/build/lib/publisher.d.ts +23 -16
  224. package/build/lib/publisher.d.ts.map +1 -1
  225. package/build/lib/publisher.js +34 -35
  226. package/build/lib/publisher.js.map +1 -1
  227. package/build/lib/registrar.d.ts.map +1 -1
  228. package/build/lib/registrar.js +2 -2
  229. package/build/lib/registrar.js.map +1 -1
  230. package/build/lib/registry.d.ts +18 -7
  231. package/build/lib/registry.d.ts.map +1 -1
  232. package/build/lib/registry.js +113 -32
  233. package/build/lib/registry.js.map +1 -1
  234. package/build/lib/root-path.d.ts +11 -0
  235. package/build/lib/root-path.d.ts.map +1 -1
  236. package/build/lib/root-path.js +15 -1
  237. package/build/lib/root-path.js.map +1 -1
  238. package/build/lib/schemas/config.d.ts +3 -1
  239. package/build/lib/schemas/config.d.ts.map +1 -1
  240. package/build/lib/schemas/config.js +1 -1
  241. package/build/lib/schemas/config.js.map +1 -1
  242. package/build/lib/schemas/lockfile.d.ts +156 -23
  243. package/build/lib/schemas/lockfile.d.ts.map +1 -1
  244. package/build/lib/schemas/lockfile.js +100 -79
  245. package/build/lib/schemas/lockfile.js.map +1 -1
  246. package/build/lib/setup.d.ts.map +1 -1
  247. package/build/lib/setup.js +53 -48
  248. package/build/lib/setup.js.map +1 -1
  249. package/build/lib/sync.d.ts +22 -6
  250. package/build/lib/sync.d.ts.map +1 -1
  251. package/build/lib/sync.js +59 -7
  252. package/build/lib/sync.js.map +1 -1
  253. package/build/lib/uninstaller.d.ts.map +1 -1
  254. package/build/lib/uninstaller.js +8 -5
  255. package/build/lib/uninstaller.js.map +1 -1
  256. package/build/lib/update-check.d.ts +4 -0
  257. package/build/lib/update-check.d.ts.map +1 -1
  258. package/build/lib/update-check.js +55 -56
  259. package/build/lib/update-check.js.map +1 -1
  260. package/build/lib/updater.d.ts +31 -1
  261. package/build/lib/updater.d.ts.map +1 -1
  262. package/build/lib/updater.js +143 -4
  263. package/build/lib/updater.js.map +1 -1
  264. package/build/lib/usage-error.d.ts +20 -0
  265. package/build/lib/usage-error.d.ts.map +1 -0
  266. package/build/lib/usage-error.js +41 -0
  267. package/build/lib/usage-error.js.map +1 -0
  268. package/build/lib/user-setup.d.ts.map +1 -1
  269. package/build/lib/user-setup.js +62 -59
  270. package/build/lib/user-setup.js.map +1 -1
  271. package/build/lib/write-file.d.ts +5 -0
  272. package/build/lib/write-file.d.ts.map +1 -1
  273. package/build/lib/write-file.js +68 -13
  274. package/build/lib/write-file.js.map +1 -1
  275. package/package.json +81 -81
@@ -5,10 +5,13 @@ import { gt as semverGt, valid as semverValid } from 'semver';
5
5
  import { getCacheDir, loadConfig } from './config.js';
6
6
  import { fetchWithRetry } from './fetch-retry.js';
7
7
  import { addNotice } from './notices.js';
8
+ import { isOffline } from './offline.js';
8
9
  import { CLI_VERSION, isPreRelease, upgradeCommand } from './version.js';
9
- const NPM_REGISTRY_URL = 'https://registry.npmjs.org/@detergent-software/atk';
10
+ /** The package's dist-tags alone (about 40 bytes), not its packument (over 1 MB). */
11
+ export const NPM_DIST_TAGS_URL = 'https://registry.npmjs.org/-/package/@detergent-software%2fatk/dist-tags';
10
12
  const NPM_CACHE_FILE = 'npm-version.json';
11
- const DEFAULT_TTL_MINUTES = 60;
13
+ /** How long the cached dist-tags stand before the check asks npm again; not the registry's `cacheTtlMinutes`. */
14
+ export const UPDATE_CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
12
15
  /** The JSON-mode refresh makes one attempt and gives up after this long, so it barely delays exit. */
13
16
  export const BACKGROUND_REFRESH_TIMEOUT_MS = 1_500;
14
17
  /**
@@ -28,17 +31,17 @@ export async function getUpdateInfo() {
28
31
  const channel = isPreRelease() ? 'dev' : 'latest';
29
32
  const cacheDir = getCacheDir(config);
30
33
  const cachePath = join(cacheDir, NPM_CACHE_FILE);
31
- const ttlMinutes = config.cacheTtlMinutes ?? DEFAULT_TTL_MINUTES;
32
- let latestVersion = await readCachedNpmVersion(cachePath, ttlMinutes, channel);
33
- if (!latestVersion) {
34
- const fetched = await fetchLatestFromNpm(channel);
35
- if (!fetched) {
34
+ const cached = await readNpmCache(cachePath);
35
+ let tags = cached && cached.ageMs <= UPDATE_CHECK_INTERVAL_MS ? cached.tags : null;
36
+ if (!tags) {
37
+ tags = await fetchDistTags();
38
+ if (!tags) {
36
39
  return null;
37
40
  }
38
- latestVersion = fetched;
39
- await writeNpmCache(cachePath, cacheDir, channel, fetched);
41
+ await writeNpmCache(cachePath, cacheDir, tags);
40
42
  }
41
- if (!semverValid(CLI_VERSION) || !semverValid(latestVersion)) {
43
+ const latestVersion = tags[channel];
44
+ if (!latestVersion || !semverValid(CLI_VERSION) || !semverValid(latestVersion)) {
42
45
  return null;
43
46
  }
44
47
  if (!semverGt(latestVersion, CLI_VERSION)) {
@@ -73,20 +76,20 @@ export async function noteCachedUpdate() {
73
76
  const channel = isPreRelease() ? 'dev' : 'latest';
74
77
  const cacheDir = getCacheDir(config);
75
78
  const cachePath = join(cacheDir, NPM_CACHE_FILE);
76
- const ttlMs = (config.cacheTtlMinutes ?? DEFAULT_TTL_MINUTES) * 60 * 1000;
77
- const cached = await readNpmCache(cachePath, channel);
78
- if (cached && semverValid(CLI_VERSION) && semverValid(cached.version) && semverGt(cached.version, CLI_VERSION)) {
79
+ const cached = await readNpmCache(cachePath);
80
+ const version = cached?.tags[channel];
81
+ if (version && semverValid(CLI_VERSION) && semverValid(version) && semverGt(version, CLI_VERSION)) {
79
82
  const command = upgradeCommand(channel);
80
83
  addNotice({
81
84
  command,
82
85
  kind: 'update-available',
83
- text: `ATK ${cached.version} is available (this is ${CLI_VERSION}). Run \`${command}\` to update.`,
86
+ text: `ATK ${version} is available (this is ${CLI_VERSION}). Run \`${command}\` to update.`,
84
87
  });
85
88
  }
86
- if (!cached || cached.ageMs > ttlMs) {
87
- void fetchLatestFromNpm(channel, 'once').then(async (fetched) => {
88
- if (fetched) {
89
- await writeNpmCache(cachePath, cacheDir, channel, fetched);
89
+ if (!cached || cached.ageMs > UPDATE_CHECK_INTERVAL_MS) {
90
+ void fetchDistTags('once').then(async (tags) => {
91
+ if (tags) {
92
+ await writeNpmCache(cachePath, cacheDir, tags);
90
93
  }
91
94
  });
92
95
  }
@@ -96,71 +99,67 @@ export async function noteCachedUpdate() {
96
99
  }
97
100
  }
98
101
  /**
99
- * The channel's dist-tag from npm, or null on any failure. `'retry'` uses the
100
- * shared retry policy; `'once'` makes a single attempt that is aborted after
101
- * {@link BACKGROUND_REFRESH_TIMEOUT_MS}.
102
+ * The `dev` and `latest` dist-tags from npm (either may be missing), or null on any failure
103
+ * or offline. `'retry'` uses the shared retry policy; `'once'` makes a single attempt that is
104
+ * aborted after {@link BACKGROUND_REFRESH_TIMEOUT_MS}.
102
105
  */
103
- async function fetchLatestFromNpm(channel, attempts = 'retry') {
106
+ async function fetchDistTags(attempts = 'retry') {
107
+ if (isOffline()) {
108
+ return null;
109
+ }
104
110
  try {
105
111
  const init = { headers: { accept: 'application/json' } };
106
112
  const response = attempts === 'retry'
107
- ? await fetchWithRetry(NPM_REGISTRY_URL, init)
108
- : await globalThis.fetch(NPM_REGISTRY_URL, {
113
+ ? await fetchWithRetry(NPM_DIST_TAGS_URL, init)
114
+ : await globalThis.fetch(NPM_DIST_TAGS_URL, {
109
115
  ...init,
110
116
  signal: AbortSignal.timeout(BACKGROUND_REFRESH_TIMEOUT_MS),
111
117
  });
112
118
  if (!response.ok) {
113
119
  return null;
114
120
  }
115
- const raw = await response.text();
116
- const body = JSON.parse(raw);
117
- const distTags = body['dist-tags'];
118
- if (!distTags || typeof distTags !== 'object') {
119
- return null;
120
- }
121
- const value = distTags[channel];
122
- return typeof value === 'string' ? value : null;
121
+ const tags = pickDistTags(JSON.parse(await response.text()));
122
+ return tags.dev || tags.latest ? tags : null;
123
123
  }
124
124
  catch {
125
125
  return null;
126
126
  }
127
127
  }
128
- async function readCachedNpmVersion(cachePath, ttlMinutes, channel) {
129
- const cached = await readNpmCache(cachePath, channel);
130
- return cached && cached.ageMs <= ttlMinutes * 60 * 1000 ? cached.version : null;
128
+ /** The string `dev` and `latest` entries of a dist-tags object; anything else is dropped. */
129
+ function pickDistTags(body) {
130
+ const tags = {};
131
+ if (body && typeof body === 'object') {
132
+ for (const channel of ['dev', 'latest']) {
133
+ const value = Reflect.get(body, channel);
134
+ if (typeof value === 'string') {
135
+ tags[channel] = value;
136
+ }
137
+ }
138
+ }
139
+ return tags;
131
140
  }
132
- /** The channel's cached version and the cache file's age, or null when there is none. */
133
- async function readNpmCache(cachePath, channel) {
141
+ /**
142
+ * The cached dist-tags and the cache file's age, or null when there is no readable cache.
143
+ * One fetch writes every tag, so the file's age holds for each of them, present or not.
144
+ */
145
+ async function readNpmCache(cachePath) {
134
146
  try {
135
147
  const fileStat = await stat(cachePath);
136
- const raw = await readFile(cachePath, 'utf-8');
137
- const parsed = JSON.parse(raw);
138
- const value = parsed[channel];
139
- return typeof value === 'string' ? { ageMs: Date.now() - fileStat.mtimeMs, version: value } : null;
148
+ const tags = pickDistTags(JSON.parse(await readFile(cachePath, 'utf-8')));
149
+ return { ageMs: Date.now() - fileStat.mtimeMs, tags };
140
150
  }
141
151
  catch {
142
152
  return null;
143
153
  }
144
154
  }
145
- async function writeNpmCache(cachePath, cacheDir, channel, version) {
155
+ /** Replaces the cache with npm's latest answer, so a tag npm no longer has goes too. */
156
+ async function writeNpmCache(cachePath, cacheDir, tags) {
146
157
  try {
147
- let existing = {};
148
- try {
149
- const raw = await readFile(cachePath, 'utf-8');
150
- existing = JSON.parse(raw);
151
- }
152
- catch {
153
- existing = {};
154
- }
155
- const merged = {
156
- ...existing,
157
- [channel]: version,
158
- fetchedAt: Date.now(),
159
- };
158
+ const file = { ...tags, fetchedAt: Date.now() };
160
159
  if (!existsSync(cacheDir)) {
161
160
  await mkdir(cacheDir, { recursive: true });
162
161
  }
163
- await writeFile(cachePath, JSON.stringify(merged), 'utf-8');
162
+ await writeFile(cachePath, JSON.stringify(file), 'utf-8');
164
163
  }
165
164
  catch {
166
165
  // Non-fatal — banner can still render without a write.
@@ -1 +1 @@
1
- {"version":3,"file":"update-check.js","sourceRoot":"","sources":["../../src/lib/update-check.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"update-check.js","sourceRoot":"","sources":["../../src/lib/update-check.ts"],"names":[],"mappings":"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"}
@@ -4,6 +4,7 @@ import type { Registry } from './schemas/index.js';
4
4
  import type { InstalledAsset, Lockfile } from './schemas/lockfile.js';
5
5
  import { ApiCodeError, type ErrorGuidance } from './errors.js';
6
6
  import { type InstallResult } from './installer.js';
7
+ import { type LocalEdits } from './local-edits.js';
7
8
  import { type Scope } from './scope.js';
8
9
  export interface OutdatedAsset {
9
10
  /** Whether the asset is frozen. */
@@ -40,6 +41,11 @@ export interface UndeclaredRemoval {
40
41
  }>;
41
42
  }
42
43
  export interface UpdateAssetsResult {
44
+ /**
45
+ * Assets skipped during bulk update because files they placed were edited (`localEdits`), with
46
+ * those files. `force` updates them.
47
+ */
48
+ editedSkipped?: Array<OutdatedAsset & Pick<LocalEdits, 'dependencies' | 'files' | 'unchecked'>>;
43
49
  /** Assets skipped because they were uninstalled for this tool (`excludedTools`). */
44
50
  excludedSkipped?: Array<{
45
51
  name: string;
@@ -105,10 +111,17 @@ export interface UpdateOptions {
105
111
  * every tool and the lockfile stay on the version they had.
106
112
  */
107
113
  failedFor?: Map<string, string>;
108
- /** Force update even if the asset is pinned. */
114
+ /** Force update even if the asset is pinned, and overwrite local edits. */
109
115
  force?: boolean;
110
116
  /** Set of frozen asset composite keys in format `${type}:${org ?? ''}:${name}`. */
111
117
  frozenAssets?: Set<string>;
118
+ /**
119
+ * The installed assets with local edits (`findLocalEdits`), keyed like `frozenAssets`: an update
120
+ * would overwrite them, so without `force` a bulk update skips them and a named one, or one whose
121
+ * plan replaces an edited dependency, is refused. Found once before a multi-tool run, so every
122
+ * tool skips the same assets and the lockfile keeps one version for them.
123
+ */
124
+ localEdits?: Map<string, LocalEdits>;
112
125
  /** Callback for progress updates. */
113
126
  onProgress?: (message: string) => void;
114
127
  /** Project root directory. */
@@ -146,6 +159,7 @@ export interface UpdateWarning {
146
159
  command: string;
147
160
  message: string;
148
161
  }
162
+ type AssetIdentity = Pick<InstalledAsset, 'name' | 'org' | 'type'>;
149
163
  export declare class UpdaterError extends ApiCodeError {
150
164
  name: string;
151
165
  }
@@ -215,4 +229,20 @@ export declare function updateAsset(assetName: string, installed: InstalledAsset
215
229
  * bypasses the outdated check and updates directly to the specified version.
216
230
  */
217
231
  export declare function updateAssets(assetNames: string[] | undefined, lockfile: Lockfile, registry: Registry, options: UpdateOptions): Promise<UpdateAssetsResult>;
232
+ /**
233
+ * `localEdits` plus, for each of `outdated` without edits of its own, the edits of the installed
234
+ * dependencies its update to `targetVersion` (else its `latestVersion`) would replace or remove for
235
+ * any of `adapters`, under the asset's key with those dependencies named. An update skips or
236
+ * refuses such an asset as it does one with its own edits. Found once, before a multi-tool run
237
+ * changes any files, and for the dry run the same way, so both list the same assets.
238
+ */
239
+ export declare function withDependencyEdits(outdated: Array<AssetIdentity & {
240
+ latestVersion: string;
241
+ }>, lockfile: Lockfile, registry: Registry, localEdits: Map<string, LocalEdits>, { adapters, projectDir, scope, targetVersion, }: {
242
+ adapters: Adapter[];
243
+ projectDir: string;
244
+ scope?: Scope;
245
+ targetVersion?: string;
246
+ }): Map<string, LocalEdits>;
247
+ export {};
218
248
  //# sourceMappingURL=updater.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"updater.d.ts","sourceRoot":"","sources":["../../src/lib/updater.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"updater.d.ts","sourceRoot":"","sources":["../../src/lib/updater.ts"],"names":[],"mappings":"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"}
@@ -6,14 +6,15 @@ import { getConfigEntriesForTool } from './config-entries.js';
6
6
  import { ApiCodeError, asSentence, errorGuidance, errorMessage, isRunWideFailure, } from './errors.js';
7
7
  import { restoreFiles, snapshotFiles } from './file-snapshot.js';
8
8
  import { executeInstallPlan, fetchPlanFiles, FileConflictError, InstallerError, installFailureMessage, InstallPlanError, } from './installer.js';
9
- import { addAssetToLockfile, findDependencyAsset, findDependents, findInstalledAsset, getLockfilePath, readLockfile, writeLockfile, } from './lockfile.js';
9
+ import {} from './local-edits.js';
10
+ import { addAssetToLockfile, findDependencyAsset, findDependents, findInstalledAsset, getLockfilePath, identityKey, readLockfile, writeLockfile, } from './lockfile.js';
10
11
  import { withoutKeptDependencies } from './multi-tool-install.js';
11
12
  import { formatOrgName, parseOrgFromName, scopeSwitchGuidance } from './org.js';
12
13
  import { findAsset } from './registry.js';
13
14
  import { resolveInstallPlan } from './resolver.js';
14
15
  import { fromRoot } from './root-path.js';
15
16
  import { scopedCommand, scopeLabel } from './scope.js';
16
- import { removeUndeclaredCopy, uninstallAsset } from './uninstaller.js';
17
+ import { planUninstall, removeUndeclaredCopy, uninstallAsset } from './uninstaller.js';
17
18
  export class UpdaterError extends ApiCodeError {
18
19
  name = 'UpdaterError';
19
20
  }
@@ -198,6 +199,9 @@ export async function updateAssets(assetNames, lockfile, registry, options) {
198
199
  if (installed.pinnedVersion && !options.force) {
199
200
  throw pinnedError(`Asset "${name}" is pinned to version "${installed.pinnedVersion}".`, spec, options.scope);
200
201
  }
202
+ const edits = options.force ? undefined : options.localEdits?.get(compositeKey);
203
+ if (edits)
204
+ throw localEditsError(name, [edits], spec, options.scope);
201
205
  // Uninstalled for this tool: leave it alone (updating would reinstall it here). The
202
206
  // other tools in a multi-tool update still get the new version.
203
207
  if (excludedAtVersion(registry, installed, options.targetVersion, options.adapter)) {
@@ -238,6 +242,7 @@ export async function updateAssets(assetNames, lockfile, registry, options) {
238
242
  }
239
243
  const outdated = checkOutdated(lockfile, registry, options.frozenAssets);
240
244
  let toUpdate;
245
+ const editedSkipped = [];
241
246
  const frozenSkipped = [];
242
247
  const skipped = [];
243
248
  if (assetNames && assetNames.length > 0) {
@@ -265,11 +270,17 @@ export async function updateAssets(assetNames, lockfile, registry, options) {
265
270
  throw pinnedError(`Asset "${asset.name}" is pinned.`, assetSpec(asset, options.type), options.scope);
266
271
  }
267
272
  }
273
+ for (const asset of toUpdate) {
274
+ const edits = options.force ? undefined : options.localEdits?.get(identityKey(asset));
275
+ if (edits)
276
+ throw localEditsError(asset.name, [edits], assetSpec(asset, options.type), options.scope);
277
+ }
268
278
  }
269
279
  else {
270
- // Bulk update: skip pinned and frozen assets without error
280
+ // Bulk update: skip pinned, frozen and edited assets without error
271
281
  toUpdate = [];
272
282
  for (const asset of outdated) {
283
+ const edits = options.force ? undefined : options.localEdits?.get(identityKey(asset));
273
284
  if (asset.frozen) {
274
285
  frozenSkipped.push(asset);
275
286
  const thaw = scopedCommand(`atk thaw ${asset.name}`, options.scope);
@@ -280,6 +291,17 @@ export async function updateAssets(assetNames, lockfile, registry, options) {
280
291
  const force = scopedCommand(`atk update ${asset.name} --force`, options.scope);
281
292
  options.onProgress?.(`Skipping pinned asset ${asset.name} (pinned, use "${force}" to override)`);
282
293
  }
294
+ else if (edits) {
295
+ const { dependencies, files, unchecked } = edits;
296
+ editedSkipped.push({
297
+ ...asset,
298
+ ...(dependencies ? { dependencies } : {}),
299
+ files,
300
+ ...(unchecked ? { unchecked } : {}),
301
+ });
302
+ const force = scopedCommand(`atk update ${assetSpec(asset, options.type)} --force`, options.scope);
303
+ options.onProgress?.(`Skipping ${asset.name}: it has local edits (use "${force}" to overwrite them)`);
304
+ }
283
305
  else {
284
306
  toUpdate.push(asset);
285
307
  }
@@ -320,6 +342,7 @@ export async function updateAssets(assetNames, lockfile, registry, options) {
320
342
  });
321
343
  if (toUpdate.length === 0) {
322
344
  return {
345
+ ...(editedSkipped.length > 0 ? { editedSkipped } : {}),
323
346
  ...(excludedSkipped.length > 0 ? { excludedSkipped } : {}),
324
347
  ...(failedSkipped.length > 0 ? { failedSkipped } : {}),
325
348
  failures: [],
@@ -382,6 +405,7 @@ export async function updateAssets(assetNames, lockfile, registry, options) {
382
405
  toolLockfile = await withInstalledEntries(toolLockfile, updated.plan, options).catch(() => toolLockfile);
383
406
  }
384
407
  return {
408
+ ...(editedSkipped.length > 0 ? { editedSkipped } : {}),
385
409
  ...(excludedSkipped.length > 0 ? { excludedSkipped } : {}),
386
410
  ...(failedSkipped.length > 0 ? { failedSkipped } : {}),
387
411
  failures,
@@ -392,10 +416,95 @@ export async function updateAssets(assetNames, lockfile, registry, options) {
392
416
  ...(undeclared.length > 0 ? { undeclared } : {}),
393
417
  };
394
418
  }
419
+ /**
420
+ * `localEdits` plus, for each of `outdated` without edits of its own, the edits of the installed
421
+ * dependencies its update to `targetVersion` (else its `latestVersion`) would replace or remove for
422
+ * any of `adapters`, under the asset's key with those dependencies named. An update skips or
423
+ * refuses such an asset as it does one with its own edits. Found once, before a multi-tool run
424
+ * changes any files, and for the dry run the same way, so both list the same assets.
425
+ */
426
+ export function withDependencyEdits(outdated, lockfile, registry, localEdits, { adapters, projectDir, scope, targetVersion, }) {
427
+ const withDependencies = new Map(localEdits);
428
+ if (localEdits.size === 0)
429
+ return withDependencies;
430
+ for (const asset of outdated) {
431
+ const installed = lockfileEntryFor(lockfile, asset);
432
+ if (!installed || localEdits.has(identityKey(installed)))
433
+ continue;
434
+ const version = targetVersion ?? asset.latestVersion;
435
+ const resolved = findAsset(registry, installed.name, installed.type, version, installed.org);
436
+ if (!resolved || resolved.asset.org !== installed.org)
437
+ continue;
438
+ const edited = new Map();
439
+ for (const adapter of adapters) {
440
+ if (!supportsType(adapter, installed.type) || isExcludedForTool(installed, adapter.tool))
441
+ continue;
442
+ let plan;
443
+ try {
444
+ plan = planFor(registry, installed, resolved.version, { adapter, lockfile, projectDir, scope });
445
+ }
446
+ catch {
447
+ // The update itself refuses it (a pinned dependency it would move) and says why.
448
+ continue;
449
+ }
450
+ const newDeps = resolved.versionData.dependencies ?? [];
451
+ for (const edits of editsReplacedBy(plan, installed, newDeps, lockfile, adapter, localEdits)) {
452
+ edited.set(identityKey(edits), edits);
453
+ }
454
+ }
455
+ if (edited.size === 0)
456
+ continue;
457
+ const deps = [...edited.values()];
458
+ withDependencies.set(identityKey(installed), {
459
+ dependencies: deps.map(({ name, org, type }) => ({ name, ...(org ? { org } : {}), type })),
460
+ files: deps.flatMap((e) => e.files),
461
+ name: installed.name,
462
+ ...(installed.org ? { org: installed.org } : {}),
463
+ type: installed.type,
464
+ ...(deps.some((e) => e.unchecked) ? { unchecked: true } : {}),
465
+ });
466
+ }
467
+ return withDependencies;
468
+ }
395
469
  /** How a command names an asset: `@org/name`, with `--type` when the run was given one. */
396
470
  function assetSpec(asset, type) {
397
471
  return `${formatOrgName(asset.org, asset.name)}${type ? ` --type ${asset.type}` : ''}`;
398
472
  }
473
+ /**
474
+ * The installed dependencies of `installed` an update to a version needing `newDeps` removes, as its
475
+ * cleanup does: dependencies it no longer declares, installed as dependencies, that no other asset
476
+ * the adapter's tool has depends on, and the dependencies only they needed.
477
+ */
478
+ function droppedDependencies(installed, newDeps, lockfile, adapter) {
479
+ const newDepKeys = new Set(newDeps.map((d) => `${d.type}:${d.name}`));
480
+ return (installed.dependencies ?? [])
481
+ .filter((d) => !newDepKeys.has(`${d.type}:${d.name}`))
482
+ .flatMap((d) => {
483
+ const dep = findDependencyAsset(lockfile, d, installed.org);
484
+ if (!dep || (dep.installReason ?? 'direct') !== 'dependency')
485
+ return [];
486
+ const others = findDependents(lockfile, dep.name, dep.type, dep.org).filter((other) => !isSameAsset(other, installed) && !isExcludedForTool(other, adapter.tool));
487
+ // The cleanup uninstalls it with cascade, which also removes the dependencies only it needed.
488
+ return others.length === 0
489
+ ? [dep, ...planUninstall(lockfile, dep.name, dep.org, dep.type, [adapter.tool]).orphanedDependencies]
490
+ : [];
491
+ });
492
+ }
493
+ /**
494
+ * The local edits of the installed dependencies an update of `installed` with `plan` replaces (the
495
+ * plan's other entries) or removes (see {@link droppedDependencies}). Entries `localEdits` holds for
496
+ * an asset because of its own dependencies (`dependencies` set) don't count.
497
+ */
498
+ function editsReplacedBy(plan, installed, newDeps, lockfile, adapter, localEdits) {
499
+ const keys = new Set([
500
+ ...plan.entries.filter((e) => !isSameAsset(e.asset, installed)).map((e) => identityKey(e.asset)),
501
+ ...droppedDependencies(installed, newDeps, lockfile, adapter).map(identityKey),
502
+ ]);
503
+ return [...keys].flatMap((key) => {
504
+ const edits = localEdits.get(key);
505
+ return edits && !edits.dependencies ? [edits] : [];
506
+ });
507
+ }
399
508
  /**
400
509
  * The skip record for an asset whose update would move a dependency whose own update failed for
401
510
  * an earlier tool in the run: that tool kept the version the lockfile records, so moving it here
@@ -499,6 +608,23 @@ function liftFailure(installed, error) {
499
608
  ...errorGuidance(error),
500
609
  };
501
610
  }
611
+ /**
612
+ * The refusal to update `assetName` over local edits: its own (`edits` is the asset's) or those
613
+ * of a dependency the update replaces. The command forces the update of `spec` in its scope.
614
+ */
615
+ function localEditsError(assetName, edits, spec, scope) {
616
+ const files = [...new Set(edits.flatMap((e) => e.files))].join(', ');
617
+ const own = edits.some((e) => e.name === assetName && !e.dependencies);
618
+ const dependencies = edits.flatMap((e) => e.dependencies ?? (e.name === assetName ? [] : [e]));
619
+ const names = [...new Set(dependencies.map((d) => `"${formatOrgName(d.org, d.name)}"`))].join(', ');
620
+ const command = scopedCommand(`atk update ${spec} --force`, scope);
621
+ const unchecked = edits.some((e) => e.unchecked)
622
+ ? " Some files couldn't be checked against the registry's versions, so they may only be an earlier version's."
623
+ : '';
624
+ return new UpdaterError(own
625
+ ? `Asset "${assetName}" has local edits (${files}), which updating it would overwrite. Use --force to overwrite them.`
626
+ : `Updating "${assetName}" would overwrite local edits in ${names} (${files}). Use --force to overwrite them.`, { command, hint: `Copy the edits somewhere else first, or pass --force to overwrite them.${unchecked}` });
627
+ }
502
628
  /** The lockfile entry of an outdated asset: same name, type and org. */
503
629
  function lockfileEntryFor(lockfile, asset) {
504
630
  return (lockfile.assets ?? []).find((a) => isSameAsset(a, asset));
@@ -591,14 +717,27 @@ async function updateAssetPlanned(assetName, installed, registry, options) {
591
717
  // Dependencies this tool already has at a version the new one accepts stay as they are, as in
592
718
  // `atk install`; moving a pinned one refuses the update before anything changes.
593
719
  let plan;
720
+ let kept;
594
721
  try {
595
- const kept = { ...options, lockfile: options.toolLockfile ?? (await readLockfile(projectDir)) };
722
+ kept = { ...options, lockfile: options.toolLockfile ?? (await readLockfile(projectDir)) };
596
723
  plan = planFor(registry, installed, toVersion, kept);
597
724
  }
598
725
  catch (planError) {
599
726
  throw new UpdaterError(`Failed to update "${assetName}" to v${toVersion}: ${failureReason(planError, installed)} ` +
600
727
  `v${fromVersion} is still installed.`, errorGuidance(planError));
601
728
  }
729
+ // The update replaces the asset and each installed dependency its plan moves, and removes the ones
730
+ // it drops: refuse before the download when one has local edits.
731
+ if (!options.force && options.localEdits) {
732
+ const own = options.localEdits.get(identityKey(installed));
733
+ const newDeps = resolved.versionData.dependencies ?? [];
734
+ const edited = [
735
+ ...(own ? [own] : []),
736
+ ...editsReplacedBy(plan, installed, newDeps, kept.lockfile, adapter, options.localEdits),
737
+ ];
738
+ if (edited.length > 0)
739
+ throw localEditsError(assetName, edited, assetSpec(installed, options.type), scope);
740
+ }
602
741
  // Download the target version before removing anything, so a refused download (an outdated
603
742
  // CLI, an expired sign-in, the API down) leaves the installed version in place.
604
743
  onProgress?.(`Downloading ${assetName}@${toVersion}...`);