diff --git a/src/db.ts b/src/db.ts index 1f9fc3a..06cbf4e 100644 --- a/src/db.ts +++ b/src/db.ts @@ -28,6 +28,14 @@ export async function insertWorkspace(workspace: Workspace) { await db.write(); } +export async function deleteWorkspace(workspacePath: string) { + const db = await getDb(); + db.data.workspaces = db.data.workspaces.filter( + (v) => v.workspace !== workspacePath + ); + await db.write(); +} + export async function dropWorkspaces() { const db = await getDb(); db.data.workspaces = []; diff --git a/src/index.ts b/src/index.ts index bcb8e50..60b65b9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -10,6 +10,7 @@ import { checkDir } from './operations/check-dir'; import { createWorkspace } from './operations/create-workspace'; import { getWorkspace } from './operations/get-workspace'; import { openWorkspace } from './operations/open-workspace'; +import { validateWorkspace } from './operations/validate-workspace'; cli( { @@ -35,7 +36,8 @@ cli( await checkDir(path); const workspace = await getWorkspace(path); - if (workspace) { + + if (workspace && (await validateWorkspace(workspace))) { await openWorkspace(workspace); } else { const workspace = await createWorkspace(path); diff --git a/src/operations/get-workspace.ts b/src/operations/get-workspace.ts index 17e4d51..e556f7f 100644 --- a/src/operations/get-workspace.ts +++ b/src/operations/get-workspace.ts @@ -9,5 +9,9 @@ export async function getWorkspace(dir: string): Promise { (w) => w.path === filepath )?.workspace; + if (!workspacePath) { + return; + } + return workspacePath; } diff --git a/src/operations/validate-workspace.ts b/src/operations/validate-workspace.ts new file mode 100644 index 0000000..80beb74 --- /dev/null +++ b/src/operations/validate-workspace.ts @@ -0,0 +1,21 @@ +import { existsSync } from 'node:fs'; + +import { deleteWorkspace } from '../db'; + +/** + * validateor + * a. returns false if not a valid workspace there, and continue to subsquent steps + * b. throw error if unexpected, and stop process + * + * also, it's do much though, some extra operations. + */ +export async function validateWorkspace(workspace: string): Promise { + // When user accidentally delete .code-workspace + if (!existsSync(workspace)) { + // delete from db and continue + await deleteWorkspace(workspace); + return false; + } + + return true; +} diff --git a/test/operations/get-workspace.test.ts b/test/operations/get-workspace.test.ts index 1f82222..8f373bb 100644 --- a/test/operations/get-workspace.test.ts +++ b/test/operations/get-workspace.test.ts @@ -1,5 +1,5 @@ import { existsSync } from 'node:fs'; -import { mkdir, readFile, rm } from 'node:fs/promises'; +import { mkdir, rm } from 'node:fs/promises'; import { basename, resolve } from 'node:path'; import { afterEach, beforeEach, expect, test, vi } from 'vitest'; @@ -34,7 +34,9 @@ test('getWorkspace', async () => { expect(await getWorkspace('dir-1')).toBeUndefined(); await createWorkspace('dir-1'); - expect(await getWorkspace('dir-1')).toBe( + + const workspace = await getWorkspace('dir-1'); + expect(workspace).toBe( resolve(mocks.testHomedir(), '.codew/workspaces/dir-1.code-workspace') ); }); diff --git a/test/operations/validate-workspace.test.ts b/test/operations/validate-workspace.test.ts new file mode 100644 index 0000000..fb3e912 --- /dev/null +++ b/test/operations/validate-workspace.test.ts @@ -0,0 +1,48 @@ +import { existsSync } from 'node:fs'; +import { mkdir, rm } from 'node:fs/promises'; +import { basename, resolve } from 'node:path'; + +import { afterEach, beforeEach, expect, test, vi } from 'vitest'; + +import { createWorkspace } from '../../src/operations/create-workspace'; +import { validateWorkspace } from '../../src/operations/validate-workspace'; + +const mocks = vi.hoisted(() => { + return { + testHomedir: () => resolve('test-tmp', basename(import.meta.url)), + }; +}); + +beforeEach(async () => { + if (existsSync(mocks.testHomedir())) { + await rm(mocks.testHomedir(), { recursive: true, force: true }); + } + await mkdir(mocks.testHomedir(), { recursive: true }); + + vi.mock('node:os', () => { + return { + homedir: () => mocks.testHomedir(), + }; + }); +}); + +afterEach(async () => { + vi.restoreAllMocks(); +}); + +test('validateWorkspace', async () => { + await createWorkspace('dir-1'); + + const codeWorkspace = resolve( + mocks.testHomedir(), + '.codew/workspaces/dir-1.code-workspace' + ); + + expect(await validateWorkspace(codeWorkspace)).toBe(true); + + // // remove .code-workspace directly + await rm(codeWorkspace, { recursive: true, force: true }); + + expect(await validateWorkspace(codeWorkspace)).toBe(false); + expect(existsSync(codeWorkspace)).toBe(false); +});