@solarains/va-cli 0.1.3 → 0.1.5

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.
@@ -0,0 +1,488 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EXPLICIT_UPDATE_TARGET_VERSION_ENV = exports.EXPLICIT_UPDATE_REEXEC_ENV = exports.PREFLIGHT_GUARD_ENV = void 0;
4
+ exports.shouldSkipManagedSync = shouldSkipManagedSync;
5
+ exports.shouldSkipCliUpdate = shouldSkipCliUpdate;
6
+ exports.canPromptForUpdate = canPromptForUpdate;
7
+ exports.fetchLatestPublishedVersion = fetchLatestPublishedVersion;
8
+ exports.performSelfUpdate = performSelfUpdate;
9
+ exports.reexecCommand = reexecCommand;
10
+ exports.resolveUpdateAction = resolveUpdateAction;
11
+ exports.runExplicitUpdate = runExplicitUpdate;
12
+ exports.runStartupPreflight = runStartupPreflight;
13
+ const node_child_process_1 = require("node:child_process");
14
+ const paths_1 = require("../../state/paths");
15
+ const runtime_config_1 = require("../../config/runtime-config");
16
+ const update_state_store_1 = require("../../state/stores/update-state-store");
17
+ const prompt_1 = require("../init/prompt");
18
+ const managed_pack_1 = require("../init/managed-pack");
19
+ const package_metadata_1 = require("../runtime/package-metadata");
20
+ const version_1 = require("./version");
21
+ const UPDATE_CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
22
+ exports.PREFLIGHT_GUARD_ENV = 'VAONE_SKIP_PREFLIGHT';
23
+ exports.EXPLICIT_UPDATE_REEXEC_ENV = 'VAONE_EXPLICIT_UPDATE_REEXEC';
24
+ exports.EXPLICIT_UPDATE_TARGET_VERSION_ENV = 'VAONE_EXPLICIT_UPDATE_TARGET_VERSION';
25
+ const UPDATE_COPY = {
26
+ en: {
27
+ promptTitle(currentVersion, latestVersion) {
28
+ return `A newer VAOne CLI is available (${currentVersion} -> ${latestVersion}).`;
29
+ },
30
+ updateNow: 'Update now',
31
+ updateNowDescription: 'Run npm global install immediately',
32
+ skip: 'Skip this run',
33
+ skipDescription: 'Continue without updating',
34
+ defer: 'Wait for next release',
35
+ deferDescription: 'Hide this prompt until a newer version appears',
36
+ timeoutNotice(latestVersion) {
37
+ return `No response after 5 seconds. Updating VAOne CLI to ${latestVersion}.`;
38
+ },
39
+ updatingNotice(latestVersion) {
40
+ return `Updating VAOne CLI to ${latestVersion}...`;
41
+ },
42
+ restartingNotice: 'Restarting the requested command with the updated CLI.',
43
+ },
44
+ 'zh-CN': {
45
+ promptTitle(currentVersion, latestVersion) {
46
+ return `检测到更高版本的 VAOne CLI(${currentVersion} -> ${latestVersion})。`;
47
+ },
48
+ updateNow: '立即更新',
49
+ updateNowDescription: '马上执行 npm 全局安装',
50
+ skip: '本次跳过',
51
+ skipDescription: '继续执行当前命令,不更新',
52
+ defer: '下个版本再提醒',
53
+ deferDescription: '在出现更新版本前不再提示',
54
+ timeoutNotice(latestVersion) {
55
+ return `5 秒内未收到响应,开始将 VAOne CLI 更新到 ${latestVersion}。`;
56
+ },
57
+ updatingNotice(latestVersion) {
58
+ return `正在将 VAOne CLI 更新到 ${latestVersion}...`;
59
+ },
60
+ restartingNotice: '正在使用更新后的 CLI 重新执行原命令。',
61
+ },
62
+ };
63
+ function isAutomationContext(env) {
64
+ return env.CI === '1' || env.CI === 'true';
65
+ }
66
+ function shouldSkipManagedSync(commandPath) {
67
+ return (commandPath.length === 0 ||
68
+ commandPath[0] === 'init' ||
69
+ commandPath[0] === 'doctor' ||
70
+ commandPath[0] === 'uninstall' ||
71
+ commandPath[0] === 'update' ||
72
+ commandPath[0] === 'version');
73
+ }
74
+ function shouldSkipCliUpdate(commandPath) {
75
+ return (commandPath[0] === 'doctor' ||
76
+ commandPath[0] === 'update' ||
77
+ commandPath[0] === 'version');
78
+ }
79
+ function canPromptForUpdate(env) {
80
+ return (process.stdin.isTTY === true &&
81
+ process.stdout.isTTY === true &&
82
+ !isAutomationContext(env));
83
+ }
84
+ async function fetchLatestPublishedVersion(packageName) {
85
+ const response = await fetch(`https://registry.npmjs.org/${encodeURIComponent(packageName)}/latest`, {
86
+ headers: {
87
+ accept: 'application/json',
88
+ },
89
+ });
90
+ if (!response.ok) {
91
+ throw new Error(`npm registry returned ${response.status} while checking ${packageName}.`);
92
+ }
93
+ const payload = (await response.json());
94
+ if (!payload.version) {
95
+ throw new Error(`npm registry did not return a version for ${packageName}.`);
96
+ }
97
+ return payload.version;
98
+ }
99
+ function runUpdateCommand(packageName, version) {
100
+ const command = process.platform === 'win32' ? 'npm.cmd' : 'npm';
101
+ return (0, node_child_process_1.spawnSync)(command, ['install', '--global', `${packageName}@${version}`], {
102
+ encoding: 'utf8',
103
+ stdio: 'pipe',
104
+ env: process.env,
105
+ });
106
+ }
107
+ async function performSelfUpdate(packageName, version) {
108
+ const result = runUpdateCommand(packageName, version);
109
+ if (result.status === 0) {
110
+ return { success: true };
111
+ }
112
+ return {
113
+ success: false,
114
+ failureCode: result.status === null ? 'npm_update_signal' : 'npm_update_failed',
115
+ failureMessage: result.stderr?.trim() || result.stdout?.trim() || 'npm update failed.',
116
+ };
117
+ }
118
+ async function reexecCommand(argv, extraEnv) {
119
+ if (!process.argv[1]) {
120
+ return null;
121
+ }
122
+ const result = (0, node_child_process_1.spawnSync)(process.execPath, [process.argv[1], ...argv], {
123
+ stdio: 'inherit',
124
+ env: {
125
+ ...process.env,
126
+ [exports.PREFLIGHT_GUARD_ENV]: '1',
127
+ ...extraEnv,
128
+ },
129
+ });
130
+ if (typeof result.status === 'number') {
131
+ return result.status;
132
+ }
133
+ return null;
134
+ }
135
+ async function resolveUpdateAction(input) {
136
+ const copy = UPDATE_COPY[input.locale];
137
+ const prompt = (input.promptFactory ?? prompt_1.createTerminalPrompt)();
138
+ const selectionPromise = prompt
139
+ .select({
140
+ message: copy.promptTitle(input.currentVersion, input.latestVersion),
141
+ defaultValue: 'update',
142
+ locale: input.locale,
143
+ choices: [
144
+ {
145
+ value: 'update',
146
+ label: copy.updateNow,
147
+ description: copy.updateNowDescription,
148
+ },
149
+ {
150
+ value: 'skip',
151
+ label: copy.skip,
152
+ description: copy.skipDescription,
153
+ },
154
+ {
155
+ value: 'defer',
156
+ label: copy.defer,
157
+ description: copy.deferDescription,
158
+ },
159
+ ],
160
+ })
161
+ .then((choice) => ({ kind: 'choice', choice }), (error) => ({ kind: 'error', error }));
162
+ const result = input.timeoutMs === null
163
+ ? await selectionPromise
164
+ : await Promise.race([
165
+ selectionPromise,
166
+ new Promise((resolve) => {
167
+ setTimeout(() => {
168
+ void prompt.close().catch(() => undefined);
169
+ resolve({ kind: 'timeout' });
170
+ }, input.timeoutMs ?? 5_000);
171
+ }),
172
+ ]);
173
+ if (result.kind === 'timeout') {
174
+ input.logger.info(copy.timeoutNotice(input.latestVersion));
175
+ return 'update';
176
+ }
177
+ if (result.kind === 'error') {
178
+ throw result.error;
179
+ }
180
+ return result.choice;
181
+ }
182
+ function createUpdateStateStore(paths) {
183
+ return new update_state_store_1.UpdateStateStore((0, paths_1.resolveUpdateStateFile)(paths));
184
+ }
185
+ function formatManagedPackRefreshSummary(refreshed) {
186
+ return refreshed
187
+ .map((entry) => `${entry.target.displayName} (${entry.scope})`)
188
+ .join(', ');
189
+ }
190
+ async function syncManagedPacksForVersion(input) {
191
+ const refreshed = await (input.syncManagedPacksImpl ?? managed_pack_1.syncManagedPacks)({
192
+ cwd: input.cwd,
193
+ homeDir: input.homeDir,
194
+ currentVersion: input.currentVersion,
195
+ });
196
+ if (refreshed.length > 0) {
197
+ input.logger.info(`Refreshed stale managed skill packs: ${formatManagedPackRefreshSummary(refreshed)}.`);
198
+ }
199
+ return refreshed;
200
+ }
201
+ async function resolvePublishedUpdate(input) {
202
+ const updateStateStore = createUpdateStateStore(input.paths);
203
+ const updateState = (await updateStateStore.read()) ?? {};
204
+ try {
205
+ const latestVersion = await (input.fetchLatestVersionImpl ?? fetchLatestPublishedVersion)(input.packageName);
206
+ return {
207
+ latestVersion,
208
+ updateStateStore,
209
+ updateState,
210
+ nextState: {
211
+ ...updateState,
212
+ lastCheckedAt: new Date(input.now()).toISOString(),
213
+ lastKnownLatestVersion: latestVersion,
214
+ },
215
+ };
216
+ }
217
+ catch (error) {
218
+ await updateStateStore.save({
219
+ ...updateState,
220
+ lastCheckedAt: new Date(input.now()).toISOString(),
221
+ lastFailureCode: 'version_check_failed',
222
+ lastFailureMessage: error instanceof Error ? error.message : 'Version check failed.',
223
+ });
224
+ throw error;
225
+ }
226
+ }
227
+ function createExplicitRestartEnv(latestVersion) {
228
+ return {
229
+ [exports.EXPLICIT_UPDATE_REEXEC_ENV]: '1',
230
+ [exports.EXPLICIT_UPDATE_TARGET_VERSION_ENV]: latestVersion,
231
+ };
232
+ }
233
+ async function runExplicitUpdate(input, deps = {}) {
234
+ const runtimePackage = (await deps.resolvePackageInfo?.()) ?? (await (0, package_metadata_1.resolveRuntimePackageInfo)());
235
+ if (input.env[exports.EXPLICIT_UPDATE_REEXEC_ENV] === '1') {
236
+ const updatedVersion = input.env[exports.EXPLICIT_UPDATE_TARGET_VERSION_ENV] ?? runtimePackage.version;
237
+ input.logger.info(`VAOne CLI updated to ${updatedVersion}.`);
238
+ try {
239
+ const refreshed = await syncManagedPacksForVersion({
240
+ logger: input.logger,
241
+ cwd: input.cwd,
242
+ homeDir: input.homeDir,
243
+ currentVersion: runtimePackage.version,
244
+ syncManagedPacksImpl: deps.syncManagedPacks,
245
+ });
246
+ if (refreshed.length === 0) {
247
+ input.logger.info('No stale VA-managed skill packs were found.');
248
+ }
249
+ return 0;
250
+ }
251
+ catch (error) {
252
+ input.logger.error(`Managed skill-pack sync failed after CLI update: ${error instanceof Error ? error.message : 'unknown error'}`);
253
+ return 1;
254
+ }
255
+ }
256
+ if (!runtimePackage.isPackagedInstall) {
257
+ input.logger.error('`vaone update` only works from the packaged npm install. Local repository runs must update dependencies manually.');
258
+ return 1;
259
+ }
260
+ const now = deps.now ?? Date.now;
261
+ let publishedUpdate;
262
+ try {
263
+ publishedUpdate = await resolvePublishedUpdate({
264
+ now,
265
+ logger: input.logger,
266
+ paths: input.paths,
267
+ packageName: runtimePackage.name,
268
+ fetchLatestVersionImpl: deps.fetchLatestVersion,
269
+ });
270
+ }
271
+ catch (error) {
272
+ input.logger.error(`CLI update check failed: ${error instanceof Error ? error.message : 'unknown error'}`);
273
+ return 1;
274
+ }
275
+ const { latestVersion, nextState, updateStateStore } = publishedUpdate;
276
+ if ((0, version_1.isVersionNewer)(latestVersion, runtimePackage.version)) {
277
+ const interactive = canPromptForUpdate(input.env);
278
+ const action = interactive
279
+ ? await resolveUpdateAction({
280
+ currentVersion: runtimePackage.version,
281
+ latestVersion,
282
+ locale: input.runtimeConfig.locale,
283
+ logger: input.logger,
284
+ promptFactory: deps.promptFactory,
285
+ timeoutMs: null,
286
+ })
287
+ : 'update';
288
+ if (!interactive) {
289
+ input.logger.info(`No interactive terminal detected. Updating VAOne CLI to ${latestVersion}.`);
290
+ }
291
+ if (action === 'defer') {
292
+ await (0, runtime_config_1.saveRuntimeConfig)(input.paths, {
293
+ updateDeferredUntilVersion: latestVersion,
294
+ });
295
+ input.runtimeConfig.updateDeferredUntilVersion = latestVersion;
296
+ await updateStateStore.save({
297
+ ...nextState,
298
+ lastFailureCode: undefined,
299
+ lastFailureMessage: undefined,
300
+ });
301
+ input.logger.info(`Deferred CLI self-update until a version newer than ${latestVersion} is published.`);
302
+ }
303
+ else if (action === 'skip') {
304
+ await updateStateStore.save({
305
+ ...nextState,
306
+ lastFailureCode: undefined,
307
+ lastFailureMessage: undefined,
308
+ });
309
+ input.logger.info('Skipped CLI self-update for this run.');
310
+ }
311
+ else {
312
+ const copy = UPDATE_COPY[input.runtimeConfig.locale];
313
+ input.logger.info(copy.updatingNotice(latestVersion));
314
+ const result = await (deps.performSelfUpdate ?? performSelfUpdate)(runtimePackage.name, latestVersion);
315
+ if (!result.success) {
316
+ await updateStateStore.save({
317
+ ...nextState,
318
+ lastAttemptedUpdateAt: new Date(now()).toISOString(),
319
+ lastAttemptedTargetVersion: latestVersion,
320
+ lastFailureCode: result.failureCode,
321
+ lastFailureMessage: result.failureMessage,
322
+ });
323
+ input.logger.error(result.failureMessage ?? 'CLI update failed.');
324
+ return 1;
325
+ }
326
+ await (0, runtime_config_1.saveRuntimeConfig)(input.paths, {
327
+ updateDeferredUntilVersion: undefined,
328
+ });
329
+ input.runtimeConfig.updateDeferredUntilVersion = undefined;
330
+ await updateStateStore.save({
331
+ ...nextState,
332
+ lastAttemptedUpdateAt: new Date(now()).toISOString(),
333
+ lastAttemptedTargetVersion: latestVersion,
334
+ lastFailureCode: undefined,
335
+ lastFailureMessage: undefined,
336
+ });
337
+ input.logger.info(copy.restartingNotice);
338
+ const exitCode = await (deps.reexecCommand ?? reexecCommand)(input.argv, createExplicitRestartEnv(latestVersion));
339
+ if (typeof exitCode === 'number') {
340
+ return exitCode;
341
+ }
342
+ input.logger.error('CLI update completed, but restarting `vaone update` did not return an exit code.');
343
+ return 1;
344
+ }
345
+ }
346
+ else {
347
+ await updateStateStore.save({
348
+ ...nextState,
349
+ lastFailureCode: undefined,
350
+ lastFailureMessage: undefined,
351
+ });
352
+ input.logger.info(`VAOne CLI is already up to date (${runtimePackage.version}).`);
353
+ }
354
+ try {
355
+ const refreshed = await syncManagedPacksForVersion({
356
+ logger: input.logger,
357
+ cwd: input.cwd,
358
+ homeDir: input.homeDir,
359
+ currentVersion: runtimePackage.version,
360
+ syncManagedPacksImpl: deps.syncManagedPacks,
361
+ });
362
+ if (refreshed.length === 0) {
363
+ input.logger.info('No stale VA-managed skill packs were found.');
364
+ }
365
+ return 0;
366
+ }
367
+ catch (error) {
368
+ input.logger.error(`Managed skill-pack sync failed: ${error instanceof Error ? error.message : 'unknown error'}`);
369
+ return 1;
370
+ }
371
+ }
372
+ async function runStartupPreflight(input, deps = {}) {
373
+ if (input.env[exports.PREFLIGHT_GUARD_ENV] === '1') {
374
+ return null;
375
+ }
376
+ const now = deps.now ?? Date.now;
377
+ const runtimePackage = (await deps.resolvePackageInfo?.()) ?? (await (0, package_metadata_1.resolveRuntimePackageInfo)());
378
+ if (!shouldSkipManagedSync(input.commandPath)) {
379
+ try {
380
+ await syncManagedPacksForVersion({
381
+ logger: input.logger,
382
+ cwd: input.cwd,
383
+ homeDir: input.homeDir,
384
+ currentVersion: runtimePackage.version,
385
+ syncManagedPacksImpl: deps.syncManagedPacks,
386
+ });
387
+ }
388
+ catch (error) {
389
+ input.logger.warn(`Managed skill-pack sync failed: ${error instanceof Error ? error.message : 'unknown error'}`);
390
+ }
391
+ }
392
+ if (shouldSkipCliUpdate(input.commandPath)) {
393
+ return null;
394
+ }
395
+ if (!runtimePackage.isPackagedInstall || !canPromptForUpdate(input.env)) {
396
+ return null;
397
+ }
398
+ const updateStateStore = createUpdateStateStore(input.paths);
399
+ const updateState = (await updateStateStore.read()) ?? {};
400
+ const lastCheckedAt = updateState.lastCheckedAt
401
+ ? Date.parse(updateState.lastCheckedAt)
402
+ : NaN;
403
+ if (Number.isFinite(lastCheckedAt) &&
404
+ now() - lastCheckedAt < UPDATE_CHECK_INTERVAL_MS) {
405
+ return null;
406
+ }
407
+ let latestVersion;
408
+ try {
409
+ latestVersion = (await resolvePublishedUpdate({
410
+ now,
411
+ logger: input.logger,
412
+ paths: input.paths,
413
+ packageName: runtimePackage.name,
414
+ fetchLatestVersionImpl: deps.fetchLatestVersion,
415
+ })).latestVersion;
416
+ }
417
+ catch (error) {
418
+ input.logger.warn(`CLI update check failed: ${error instanceof Error ? error.message : 'unknown error'}`);
419
+ return null;
420
+ }
421
+ const nextState = {
422
+ ...updateState,
423
+ lastCheckedAt: new Date(now()).toISOString(),
424
+ lastKnownLatestVersion: latestVersion,
425
+ };
426
+ if (!(0, version_1.isVersionNewer)(latestVersion, runtimePackage.version)) {
427
+ await updateStateStore.save({
428
+ ...nextState,
429
+ lastFailureCode: undefined,
430
+ lastFailureMessage: undefined,
431
+ });
432
+ return null;
433
+ }
434
+ const deferredBoundary = input.runtimeConfig.updateDeferredUntilVersion;
435
+ if (deferredBoundary &&
436
+ !(0, version_1.isVersionNewer)(latestVersion, deferredBoundary)) {
437
+ await updateStateStore.save(nextState);
438
+ return null;
439
+ }
440
+ const action = await resolveUpdateAction({
441
+ currentVersion: runtimePackage.version,
442
+ latestVersion,
443
+ locale: input.runtimeConfig.locale,
444
+ logger: input.logger,
445
+ promptFactory: deps.promptFactory,
446
+ timeoutMs: deps.promptTimeoutMs,
447
+ });
448
+ if (action === 'skip') {
449
+ await updateStateStore.save(nextState);
450
+ return null;
451
+ }
452
+ if (action === 'defer') {
453
+ await (0, runtime_config_1.saveRuntimeConfig)(input.paths, {
454
+ updateDeferredUntilVersion: latestVersion,
455
+ });
456
+ input.runtimeConfig.updateDeferredUntilVersion = latestVersion;
457
+ await updateStateStore.save(nextState);
458
+ return null;
459
+ }
460
+ const copy = UPDATE_COPY[input.runtimeConfig.locale];
461
+ input.logger.info(copy.updatingNotice(latestVersion));
462
+ const result = await (deps.performSelfUpdate ?? performSelfUpdate)(runtimePackage.name, latestVersion);
463
+ if (!result.success) {
464
+ await updateStateStore.save({
465
+ ...nextState,
466
+ lastAttemptedUpdateAt: new Date(now()).toISOString(),
467
+ lastAttemptedTargetVersion: latestVersion,
468
+ lastFailureCode: result.failureCode,
469
+ lastFailureMessage: result.failureMessage,
470
+ });
471
+ input.logger.warn(result.failureMessage ?? 'CLI update failed.');
472
+ return null;
473
+ }
474
+ await (0, runtime_config_1.saveRuntimeConfig)(input.paths, {
475
+ updateDeferredUntilVersion: undefined,
476
+ });
477
+ input.runtimeConfig.updateDeferredUntilVersion = undefined;
478
+ await updateStateStore.save({
479
+ ...nextState,
480
+ lastAttemptedUpdateAt: new Date(now()).toISOString(),
481
+ lastAttemptedTargetVersion: latestVersion,
482
+ lastFailureCode: undefined,
483
+ lastFailureMessage: undefined,
484
+ });
485
+ input.logger.info(copy.restartingNotice);
486
+ const exitCode = await (deps.reexecCommand ?? reexecCommand)(input.argv);
487
+ return exitCode;
488
+ }
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.compareVersions = compareVersions;
4
+ exports.isVersionNewer = isVersionNewer;
5
+ function parseVersion(raw) {
6
+ const trimmed = raw.trim();
7
+ const [core, prerelease] = trimmed.split('-', 2);
8
+ const segments = core.split('.').map((value) => {
9
+ if (!/^\d+$/.test(value)) {
10
+ throw new Error(`Invalid version segment "${value}" in "${raw}".`);
11
+ }
12
+ return Number(value);
13
+ });
14
+ return {
15
+ segments,
16
+ prerelease,
17
+ };
18
+ }
19
+ function compareVersions(left, right) {
20
+ const parsedLeft = parseVersion(left);
21
+ const parsedRight = parseVersion(right);
22
+ const maxLength = Math.max(parsedLeft.segments.length, parsedRight.segments.length);
23
+ for (let index = 0; index < maxLength; index += 1) {
24
+ const leftValue = parsedLeft.segments[index] ?? 0;
25
+ const rightValue = parsedRight.segments[index] ?? 0;
26
+ if (leftValue !== rightValue) {
27
+ return leftValue > rightValue ? 1 : -1;
28
+ }
29
+ }
30
+ if (parsedLeft.prerelease && !parsedRight.prerelease) {
31
+ return -1;
32
+ }
33
+ if (!parsedLeft.prerelease && parsedRight.prerelease) {
34
+ return 1;
35
+ }
36
+ if (parsedLeft.prerelease === parsedRight.prerelease) {
37
+ return 0;
38
+ }
39
+ return (parsedLeft.prerelease ?? '').localeCompare(parsedRight.prerelease ?? '');
40
+ }
41
+ function isVersionNewer(candidate, baseline) {
42
+ return compareVersions(candidate, baseline) > 0;
43
+ }
@@ -15,6 +15,9 @@ class Logger {
15
15
  info(message) {
16
16
  this.plain(message);
17
17
  }
18
+ warn(message) {
19
+ this.plain(`Warning: ${message}`);
20
+ }
18
21
  error(message) {
19
22
  process.stderr.write(`Error: ${message}\n`);
20
23
  }
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createCliPaths = createCliPaths;
4
4
  exports.ensureCliDirectories = ensureCliDirectories;
5
+ exports.resolveUpdateStateFile = resolveUpdateStateFile;
5
6
  const promises_1 = require("node:fs/promises");
6
7
  const node_os_1 = require("node:os");
7
8
  const node_path_1 = require("node:path");
@@ -30,3 +31,6 @@ async function ensureCliDirectories(paths) {
30
31
  await (0, promises_1.mkdir)(paths.rootDir, { recursive: true });
31
32
  await (0, promises_1.mkdir)(paths.stateDir, { recursive: true });
32
33
  }
34
+ function resolveUpdateStateFile(paths) {
35
+ return (0, node_path_1.join)(paths.stateDir, 'update.json');
36
+ }
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UpdateStateStore = void 0;
4
+ const file_json_store_1 = require("./file-json-store");
5
+ class UpdateStateStore {
6
+ store;
7
+ constructor(filePath) {
8
+ this.store = new file_json_store_1.FileJsonStore(filePath);
9
+ }
10
+ async read() {
11
+ return this.store.read();
12
+ }
13
+ async save(state) {
14
+ await this.store.write(state);
15
+ }
16
+ async clear() {
17
+ await this.store.clear();
18
+ }
19
+ }
20
+ exports.UpdateStateStore = UpdateStateStore;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solarains/va-cli",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Bootstrap CLI for the VAOne product.",
5
5
  "bin": {
6
6
  "vaone": "dist/main.js"