diff --git a/src/commands/schema.ts b/src/commands/schema.ts index ead29a100..27c31875f 100644 --- a/src/commands/schema.ts +++ b/src/commands/schema.ts @@ -23,6 +23,7 @@ import { addAliasToType, addLinkTypeToPack, addPrefixToType, + BUNDLED_PACK_NAMES, addTypeToPack, invalidatePackCache, loadActivePack, @@ -179,7 +180,7 @@ async function runActive(_args: string[]): Promise { } function runList(_args: string[]): void { - const bundled = ['gbrain-base', 'gbrain-recommended']; + const bundled = [...BUNDLED_PACK_NAMES]; const installedDir = gbrainPath('schema-packs'); const installed: string[] = []; if (existsSync(installedDir)) { @@ -366,12 +367,12 @@ function runUse(args: string[]): void { } function packPathByName(name: string): string | null { - if (name === 'gbrain-base') { + if (BUNDLED_PACK_NAMES.has(name)) { // Resolve bundled YAML — try a few locations. const here = dirname(new URL(import.meta.url).pathname); const candidates = [ - join(here, '..', 'core', 'schema-pack', 'base', 'gbrain-base.yaml'), - join(here, '..', '..', 'src', 'core', 'schema-pack', 'base', 'gbrain-base.yaml'), + join(here, '..', 'core', 'schema-pack', 'base', `${name}.yaml`), + join(here, '..', '..', 'src', 'core', 'schema-pack', 'base', `${name}.yaml`), ]; for (const c of candidates) { if (existsSync(c)) return c; diff --git a/test/commands/schema-packpath.test.ts b/test/commands/schema-packpath.test.ts new file mode 100644 index 000000000..fffb2aeaa --- /dev/null +++ b/test/commands/schema-packpath.test.ts @@ -0,0 +1,50 @@ +import { afterEach, describe, expect, test } from 'bun:test'; +import { existsSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import { join } from 'node:path'; +import { _testHelpers } from '../../src/commands/schema.ts'; +import { withEnv } from '../helpers/with-env.ts'; + +const tempDirs: string[] = []; + +function tempDir(prefix: string): string { + const dir = mkdtempSync(join(tmpdir(), prefix)); + tempDirs.push(dir); + return dir; +} + +afterEach(() => { + for (const dir of tempDirs.splice(0)) { + rmSync(dir, { recursive: true, force: true }); + } +}); + +describe('schema packPathByName', () => { + test('resolves all bundled schema pack names to bundled YAML files', () => { + for (const name of ['gbrain-base', 'gbrain-recommended', 'gbrain-base-v2']) { + const path = _testHelpers.packPathByName(name); + expect(path).toBeTruthy(); + expect(path!.endsWith(`src/core/schema-pack/base/${name}.yaml`)).toBe(true); + expect(existsSync(path!)).toBe(true); + } + }); + + test('returns null for an unknown non-bundled pack name', async () => { + const home = tempDir('gbrain-packpath-home-'); + await withEnv({ GBRAIN_HOME: home }, async () => { + expect(_testHelpers.packPathByName('definitely-not-a-pack')).toBeNull(); + }); + }); + + test('resolves a user-installed pack by name', async () => { + const home = tempDir('gbrain-packpath-home-'); + await withEnv({ GBRAIN_HOME: home }, async () => { + const packDir = join(home, '.gbrain', 'schema-packs', 'custom-pack'); + mkdirSync(packDir, { recursive: true }); + const packPath = join(packDir, 'pack.yaml'); + writeFileSync(packPath, 'name: custom-pack\n', 'utf-8'); + + expect(_testHelpers.packPathByName('custom-pack')).toBe(packPath); + }); + }); +});