mirror of
https://github.com/tiennm99/ccs.git
synced 2026-09-02 08:19:59 +00:00
fix(update): align no-update dependency injection
This commit is contained in:
@@ -15,7 +15,7 @@ import {
|
|||||||
type CurrentInstall,
|
type CurrentInstall,
|
||||||
type InstalledPackageState,
|
type InstalledPackageState,
|
||||||
} from '../utils/package-manager-detector';
|
} from '../utils/package-manager-detector';
|
||||||
import { compareVersionsWithPrerelease } from '../utils/update-checker';
|
import { compareVersionsWithPrerelease, type UpdateResult } from '../utils/update-checker';
|
||||||
import { getVersion } from '../utils/version';
|
import { getVersion } from '../utils/version';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,29 +28,6 @@ export interface UpdateOptions {
|
|||||||
|
|
||||||
type TargetTag = 'latest' | 'dev';
|
type TargetTag = 'latest' | 'dev';
|
||||||
|
|
||||||
type UpdateCheckResult =
|
|
||||||
| {
|
|
||||||
status: 'update_available';
|
|
||||||
current?: string;
|
|
||||||
latest?: string;
|
|
||||||
message?: string;
|
|
||||||
reason?: string;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
status: 'check_failed';
|
|
||||||
message?: string;
|
|
||||||
latest?: string;
|
|
||||||
current?: string;
|
|
||||||
reason?: string;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
status: 'no_update';
|
|
||||||
reason?: string;
|
|
||||||
latest?: string;
|
|
||||||
current?: string;
|
|
||||||
message?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface UpdateCommandDeps {
|
export interface UpdateCommandDeps {
|
||||||
initUI: typeof initUI;
|
initUI: typeof initUI;
|
||||||
getVersion: typeof getVersion;
|
getVersion: typeof getVersion;
|
||||||
@@ -64,7 +41,7 @@ export interface UpdateCommandDeps {
|
|||||||
interactive: boolean,
|
interactive: boolean,
|
||||||
channel: 'npm' | 'direct',
|
channel: 'npm' | 'direct',
|
||||||
targetTag: TargetTag
|
targetTag: TargetTag
|
||||||
) => Promise<UpdateCheckResult>;
|
) => Promise<UpdateResult>;
|
||||||
spawn: typeof spawn;
|
spawn: typeof spawn;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,14 +50,9 @@ async function loadCheckForUpdates(
|
|||||||
interactive: boolean,
|
interactive: boolean,
|
||||||
channel: 'npm' | 'direct',
|
channel: 'npm' | 'direct',
|
||||||
targetTag: TargetTag
|
targetTag: TargetTag
|
||||||
): Promise<UpdateCheckResult> {
|
): Promise<UpdateResult> {
|
||||||
const { checkForUpdates } = await import('../utils/update-checker');
|
const { checkForUpdates } = await import('../utils/update-checker');
|
||||||
return checkForUpdates(
|
return checkForUpdates(currentVersion, interactive, channel, targetTag);
|
||||||
currentVersion,
|
|
||||||
interactive,
|
|
||||||
channel,
|
|
||||||
targetTag
|
|
||||||
) as Promise<UpdateCheckResult>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultDeps: UpdateCommandDeps = {
|
const defaultDeps: UpdateCommandDeps = {
|
||||||
@@ -150,7 +122,7 @@ export async function handleUpdateCommand(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (updateResult.status === 'no_update') {
|
if (updateResult.status === 'no_update') {
|
||||||
handleNoUpdate(updateResult.reason);
|
handleNoUpdate(updateResult.reason, currentVersion);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,9 +187,7 @@ function handleCheckFailed(
|
|||||||
/**
|
/**
|
||||||
* Handle no update available
|
* Handle no update available
|
||||||
*/
|
*/
|
||||||
function handleNoUpdate(reason: string | undefined): void {
|
function handleNoUpdate(reason: string | undefined, version: string): void {
|
||||||
const version = getVersion();
|
|
||||||
|
|
||||||
let message = `You are already on the latest version (${version})`;
|
let message = `You are already on the latest version (${version})`;
|
||||||
|
|
||||||
switch (reason) {
|
switch (reason) {
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ interface UpdateCache {
|
|||||||
dismissed_version: string | null;
|
dismissed_version: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UpdateResult {
|
export interface UpdateResult {
|
||||||
status: 'update_available' | 'no_update' | 'check_failed';
|
status: 'update_available' | 'no_update' | 'check_failed';
|
||||||
reason?: string;
|
reason?: string;
|
||||||
latest?: string;
|
latest?: string;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { afterEach, beforeEach, describe, expect, it } from 'bun:test';
|
import { afterEach, beforeEach, describe, expect, it } from 'bun:test';
|
||||||
import { handleUpdateCommand, type UpdateCommandDeps } from '../../../src/commands/update-command';
|
import { handleUpdateCommand, type UpdateCommandDeps } from '../../../src/commands/update-command';
|
||||||
|
import type { UpdateResult } from '../../../src/utils/update-checker';
|
||||||
|
|
||||||
let logLines: string[] = [];
|
let logLines: string[] = [];
|
||||||
let spawnCalls: Array<{ command: string; args: string[]; env?: NodeJS.ProcessEnv }> = [];
|
let spawnCalls: Array<{ command: string; args: string[]; env?: NodeJS.ProcessEnv }> = [];
|
||||||
@@ -18,13 +19,8 @@ type Scenario = {
|
|||||||
afterState: InstalledState;
|
afterState: InstalledState;
|
||||||
};
|
};
|
||||||
|
|
||||||
type UpdateCheckResult =
|
|
||||||
| { status: 'update_available'; current: string; latest: string }
|
|
||||||
| { status: 'no_update' }
|
|
||||||
| { status: 'check_failed'; message: string };
|
|
||||||
|
|
||||||
let scenario: Scenario;
|
let scenario: Scenario;
|
||||||
let updateCheckResult: UpdateCheckResult;
|
let updateCheckResult: UpdateResult;
|
||||||
let currentInstallOverride: ReturnType<typeof installDescriptor>;
|
let currentInstallOverride: ReturnType<typeof installDescriptor>;
|
||||||
let stateReads = 0;
|
let stateReads = 0;
|
||||||
|
|
||||||
@@ -39,7 +35,7 @@ function installDescriptor() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function createDeps(): UpdateCommandDeps {
|
function createDeps(overrides: Partial<UpdateCommandDeps> = {}): UpdateCommandDeps {
|
||||||
return {
|
return {
|
||||||
initUI: async () => {},
|
initUI: async () => {},
|
||||||
getVersion: () => '7.67.0-dev.5',
|
getVersion: () => '7.67.0-dev.5',
|
||||||
@@ -95,6 +91,7 @@ function createDeps(): UpdateCommandDeps {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
}) as typeof UpdateCommandDeps.prototype.spawn,
|
}) as typeof UpdateCommandDeps.prototype.spawn,
|
||||||
|
...overrides,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,6 +193,20 @@ describe('update-command current install handling', () => {
|
|||||||
expect(exitCodes).toContain(0);
|
expect(exitCodes).toContain(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('uses the injected version in the no-update message', async () => {
|
||||||
|
updateCheckResult = { status: 'no_update' };
|
||||||
|
|
||||||
|
await handleUpdateCommand(
|
||||||
|
{},
|
||||||
|
createDeps({
|
||||||
|
getVersion: () => '9.9.9-test.1',
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(logLines.join('\n')).toContain('latest version (9.9.9-test.1)');
|
||||||
|
expect(exitCodes).toContain(0);
|
||||||
|
});
|
||||||
|
|
||||||
it('accepts a newer installed version when the dist-tag moves during update', async () => {
|
it('accepts a newer installed version when the dist-tag moves during update', async () => {
|
||||||
scenario = {
|
scenario = {
|
||||||
beforeState: { version: '7.67.0-dev.5', packageJsonMtimeMs: 100, scriptMtimeMs: 100 },
|
beforeState: { version: '7.67.0-dev.5', packageJsonMtimeMs: 100, scriptMtimeMs: 100 },
|
||||||
|
|||||||
Reference in New Issue
Block a user