craftdesk 0.2.0 → 0.4.0
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.
- package/CHANGELOG.md +57 -0
- package/README.md +968 -92
- package/dist/commands/add.d.ts +5 -0
- package/dist/commands/add.d.ts.map +1 -1
- package/dist/commands/add.js +303 -7
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/convert.d.ts +8 -0
- package/dist/commands/convert.d.ts.map +1 -0
- package/dist/commands/convert.js +146 -0
- package/dist/commands/convert.js.map +1 -0
- package/dist/commands/info.d.ts +8 -0
- package/dist/commands/info.d.ts.map +1 -0
- package/dist/commands/info.js +66 -0
- package/dist/commands/info.js.map +1 -0
- package/dist/commands/init.d.ts +5 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +9 -3
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/install.d.ts +5 -0
- package/dist/commands/install.d.ts.map +1 -1
- package/dist/commands/install.js +24 -4
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/list.d.ts +5 -0
- package/dist/commands/list.d.ts.map +1 -1
- package/dist/commands/list.js +72 -7
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/login.d.ts +8 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +158 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/logout.d.ts +8 -0
- package/dist/commands/logout.d.ts.map +1 -0
- package/dist/commands/logout.js +51 -0
- package/dist/commands/logout.js.map +1 -0
- package/dist/commands/outdated.d.ts +23 -0
- package/dist/commands/outdated.d.ts.map +1 -0
- package/dist/commands/outdated.js +268 -0
- package/dist/commands/outdated.js.map +1 -0
- package/dist/commands/publish.d.ts +8 -0
- package/dist/commands/publish.d.ts.map +1 -0
- package/dist/commands/publish.js +198 -0
- package/dist/commands/publish.js.map +1 -0
- package/dist/commands/remove.d.ts +5 -0
- package/dist/commands/remove.d.ts.map +1 -1
- package/dist/commands/remove.js +52 -11
- package/dist/commands/remove.js.map +1 -1
- package/dist/commands/search.d.ts +8 -0
- package/dist/commands/search.d.ts.map +1 -0
- package/dist/commands/search.js +60 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/commands/update.d.ts +8 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +369 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/whoami.d.ts +8 -0
- package/dist/commands/whoami.d.ts.map +1 -0
- package/dist/commands/whoami.js +58 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/converters/base-converter.d.ts +89 -0
- package/dist/converters/base-converter.d.ts.map +1 -0
- package/dist/converters/base-converter.js +249 -0
- package/dist/converters/base-converter.js.map +1 -0
- package/dist/converters/continue-converter.d.ts +53 -0
- package/dist/converters/continue-converter.d.ts.map +1 -0
- package/dist/converters/continue-converter.js +243 -0
- package/dist/converters/continue-converter.js.map +1 -0
- package/dist/converters/cursor-converter.d.ts +70 -0
- package/dist/converters/cursor-converter.d.ts.map +1 -0
- package/dist/converters/cursor-converter.js +272 -0
- package/dist/converters/cursor-converter.js.map +1 -0
- package/dist/index.js +35 -4
- package/dist/index.js.map +1 -1
- package/dist/services/config-manager.d.ts +128 -10
- package/dist/services/config-manager.d.ts.map +1 -1
- package/dist/services/config-manager.js +189 -18
- package/dist/services/config-manager.js.map +1 -1
- package/dist/services/converter.d.ts +53 -0
- package/dist/services/converter.d.ts.map +1 -0
- package/dist/services/converter.js +185 -0
- package/dist/services/converter.js.map +1 -0
- package/dist/services/craft-wrapper.d.ts +108 -0
- package/dist/services/craft-wrapper.d.ts.map +1 -0
- package/dist/services/craft-wrapper.js +268 -0
- package/dist/services/craft-wrapper.js.map +1 -0
- package/dist/services/git-resolver.d.ts +9 -3
- package/dist/services/git-resolver.d.ts.map +1 -1
- package/dist/services/git-resolver.js +35 -10
- package/dist/services/git-resolver.js.map +1 -1
- package/dist/services/installer.d.ts +51 -1
- package/dist/services/installer.d.ts.map +1 -1
- package/dist/services/installer.js +245 -14
- package/dist/services/installer.js.map +1 -1
- package/dist/services/plugin-resolver.d.ts +80 -0
- package/dist/services/plugin-resolver.d.ts.map +1 -0
- package/dist/services/plugin-resolver.js +182 -0
- package/dist/services/plugin-resolver.js.map +1 -0
- package/dist/services/registry-client.d.ts +132 -5
- package/dist/services/registry-client.d.ts.map +1 -1
- package/dist/services/registry-client.js +239 -34
- package/dist/services/registry-client.js.map +1 -1
- package/dist/services/settings-manager.d.ts +151 -0
- package/dist/services/settings-manager.d.ts.map +1 -0
- package/dist/services/settings-manager.js +333 -0
- package/dist/services/settings-manager.js.map +1 -0
- package/dist/types/claude-settings.d.ts +155 -0
- package/dist/types/claude-settings.d.ts.map +1 -0
- package/dist/types/claude-settings.js +20 -0
- package/dist/types/claude-settings.js.map +1 -0
- package/dist/types/converter.d.ts +98 -0
- package/dist/types/converter.d.ts.map +1 -0
- package/dist/types/converter.js +6 -0
- package/dist/types/converter.js.map +1 -0
- package/dist/types/craftdesk-json.d.ts +63 -3
- package/dist/types/craftdesk-json.d.ts.map +1 -1
- package/dist/types/craftdesk-lock.d.ts +62 -1
- package/dist/types/craftdesk-lock.d.ts.map +1 -1
- package/dist/utils/crypto.d.ts +23 -0
- package/dist/utils/crypto.d.ts.map +1 -0
- package/dist/utils/crypto.js +52 -0
- package/dist/utils/crypto.js.map +1 -0
- package/dist/utils/file-system.d.ts +43 -0
- package/dist/utils/file-system.d.ts.map +1 -1
- package/dist/utils/file-system.js +45 -2
- package/dist/utils/file-system.js.map +1 -1
- package/dist/utils/logger.d.ts +75 -0
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +76 -1
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/version-utils.d.ts +63 -0
- package/dist/utils/version-utils.d.ts.map +1 -0
- package/dist/utils/version-utils.js +130 -0
- package/dist/utils/version-utils.js.map +1 -0
- package/package.json +36 -9
- package/.claude/settings.local.json +0 -17
- package/.github/workflows/ci.yml +0 -94
- package/API.md +0 -414
- package/TESTING.md +0 -263
- package/dist/commands/config.d.ts +0 -3
- package/dist/commands/config.d.ts.map +0 -1
- package/dist/commands/config.js +0 -56
- package/dist/commands/config.js.map +0 -1
- package/dist/types/config.d.ts +0 -17
- package/dist/types/config.d.ts.map +0 -1
- package/dist/types/config.js +0 -3
- package/dist/types/config.js.map +0 -1
- package/docs/DEPENDENCY_RESOLUTION.md +0 -237
- package/examples/craftdesk-all-sources.json +0 -79
- package/examples/craftdesk-git-monorepo.json +0 -41
- package/examples/craftdesk-multi-registry.json +0 -40
- package/examples/craftdesk-with-registries.json +0 -49
- package/examples/simple-craftdesk.json +0 -10
- package/src/commands/add.ts +0 -314
- package/src/commands/init.ts +0 -55
- package/src/commands/install.ts +0 -126
- package/src/commands/list.ts +0 -126
- package/src/commands/remove.ts +0 -82
- package/src/index.ts +0 -56
- package/src/services/config-manager.ts +0 -150
- package/src/services/git-resolver.ts +0 -370
- package/src/services/installer.ts +0 -314
- package/src/services/registry-client.ts +0 -163
- package/src/types/craftdesk-json.ts +0 -53
- package/src/types/craftdesk-lock.ts +0 -38
- package/src/utils/file-system.ts +0 -55
- package/src/utils/logger.ts +0 -82
- package/tests/fixtures/craftdesk-git.json +0 -17
- package/tests/fixtures/craftdesk.json +0 -15
- package/tests/helpers/test-utils.ts +0 -60
- package/tests/integration/init-command.test.ts +0 -70
- package/tests/integration/list-command.test.ts +0 -77
- package/tests/unit/config-manager.test.ts +0 -228
- package/tests/unit/git-resolver.test.ts +0 -303
- package/tests/unit/installer.test.ts +0 -105
- package/tsconfig.json +0 -20
- package/vitest.config.ts +0 -29
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "git-test-project",
|
|
3
|
-
"version": "1.0.0",
|
|
4
|
-
"type": "skill",
|
|
5
|
-
"description": "Test project with git dependencies",
|
|
6
|
-
"dependencies": {
|
|
7
|
-
"custom-auth": {
|
|
8
|
-
"git": "https://github.com/company/auth.git",
|
|
9
|
-
"branch": "main"
|
|
10
|
-
},
|
|
11
|
-
"monorepo-skill": {
|
|
12
|
-
"git": "https://github.com/company/monorepo.git",
|
|
13
|
-
"tag": "v3.0.0",
|
|
14
|
-
"path": "skills/auth"
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "test-project",
|
|
3
|
-
"version": "1.0.0",
|
|
4
|
-
"type": "skill",
|
|
5
|
-
"description": "Test project for unit tests",
|
|
6
|
-
"dependencies": {
|
|
7
|
-
"ruby-on-rails": "^7.0.0",
|
|
8
|
-
"postgres-expert": "^1.0.0"
|
|
9
|
-
},
|
|
10
|
-
"registries": {
|
|
11
|
-
"default": {
|
|
12
|
-
"url": "https://craftdesk.ai"
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import fs from 'fs-extra';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Creates a temporary test directory
|
|
6
|
-
*/
|
|
7
|
-
export async function createTempDir(prefix: string = 'test-'): Promise<string> {
|
|
8
|
-
const tmpDir = path.join(process.cwd(), '.test-tmp', `${prefix}${Date.now()}`);
|
|
9
|
-
await fs.ensureDir(tmpDir);
|
|
10
|
-
return tmpDir;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Cleans up a temporary directory
|
|
15
|
-
*/
|
|
16
|
-
export async function cleanupTempDir(dirPath: string): Promise<void> {
|
|
17
|
-
if (dirPath.includes('.test-tmp')) {
|
|
18
|
-
await fs.remove(dirPath);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Copies a fixture file to a target directory
|
|
24
|
-
*/
|
|
25
|
-
export async function copyFixture(fixtureName: string, targetDir: string): Promise<void> {
|
|
26
|
-
const fixturePath = path.join(__dirname, '..', 'fixtures', fixtureName);
|
|
27
|
-
const targetPath = path.join(targetDir, path.basename(fixtureName));
|
|
28
|
-
await fs.copy(fixturePath, targetPath);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Reads a JSON file and returns parsed content
|
|
33
|
-
*/
|
|
34
|
-
export async function readJsonFile<T = any>(filePath: string): Promise<T> {
|
|
35
|
-
const content = await fs.readFile(filePath, 'utf-8');
|
|
36
|
-
return JSON.parse(content);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Writes a JSON object to a file
|
|
41
|
-
*/
|
|
42
|
-
export async function writeJsonFile(filePath: string, data: any): Promise<void> {
|
|
43
|
-
await fs.writeFile(filePath, JSON.stringify(data, null, 2), 'utf-8');
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Mock registry response for testing
|
|
48
|
-
*/
|
|
49
|
-
export function createMockCraftInfo(name: string, version: string = '1.0.0') {
|
|
50
|
-
return {
|
|
51
|
-
name,
|
|
52
|
-
version,
|
|
53
|
-
type: 'skill',
|
|
54
|
-
author: 'test-author',
|
|
55
|
-
description: 'Test craft',
|
|
56
|
-
download_url: `https://craftdesk.ai/api/v1/crafts/test-author/${name}/versions/${version}/download`,
|
|
57
|
-
integrity: 'sha256-test123',
|
|
58
|
-
dependencies: {}
|
|
59
|
-
};
|
|
60
|
-
}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
-
import { execSync } from 'child_process';
|
|
3
|
-
import { createTempDir, cleanupTempDir, readJsonFile } from '../helpers/test-utils';
|
|
4
|
-
import path from 'path';
|
|
5
|
-
import fs from 'fs-extra';
|
|
6
|
-
|
|
7
|
-
describe('craftdesk init command', () => {
|
|
8
|
-
let tempDir: string;
|
|
9
|
-
let originalCwd: string;
|
|
10
|
-
const cliPath = path.join(__dirname, '../../dist/index.js');
|
|
11
|
-
|
|
12
|
-
beforeEach(async () => {
|
|
13
|
-
tempDir = await createTempDir('init-test-');
|
|
14
|
-
originalCwd = process.cwd();
|
|
15
|
-
process.chdir(tempDir);
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
afterEach(async () => {
|
|
19
|
-
process.chdir(originalCwd);
|
|
20
|
-
await cleanupTempDir(tempDir);
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it('should create a new craftdesk.json file', async () => {
|
|
24
|
-
// Run init command
|
|
25
|
-
execSync(`node ${cliPath} init --name test-project --project-version 1.0.0 --type skill`, {
|
|
26
|
-
stdio: 'pipe'
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
const craftdeskPath = path.join(tempDir, 'craftdesk.json');
|
|
30
|
-
const exists = await fs.pathExists(craftdeskPath);
|
|
31
|
-
expect(exists).toBe(true);
|
|
32
|
-
|
|
33
|
-
const config = await readJsonFile(craftdeskPath);
|
|
34
|
-
expect(config.name).toBe('test-project');
|
|
35
|
-
expect(config.version).toBe('1.0.0');
|
|
36
|
-
expect(config.type).toBe('skill');
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it('should include default registry configuration', async () => {
|
|
40
|
-
execSync(`node ${cliPath} init --name test --project-version 1.0.0 --type agent`, {
|
|
41
|
-
stdio: 'pipe'
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
const config = await readJsonFile(path.join(tempDir, 'craftdesk.json'));
|
|
45
|
-
expect(config.registries).toBeDefined();
|
|
46
|
-
expect(config.registries.default).toBeDefined();
|
|
47
|
-
expect(config.registries.default.url).toBe('https://craftdesk.ai');
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it('should not overwrite existing craftdesk.json', async () => {
|
|
51
|
-
// Create existing file
|
|
52
|
-
await fs.writeJson(path.join(tempDir, 'craftdesk.json'), {
|
|
53
|
-
name: 'existing',
|
|
54
|
-
version: '2.0.0'
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
// Try to init again
|
|
58
|
-
try {
|
|
59
|
-
execSync(`node ${cliPath} init --name test --project-version 1.0.0 --type skill`, {
|
|
60
|
-
stdio: 'pipe'
|
|
61
|
-
});
|
|
62
|
-
} catch (error) {
|
|
63
|
-
// Expected to fail
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const config = await readJsonFile(path.join(tempDir, 'craftdesk.json'));
|
|
67
|
-
expect(config.name).toBe('existing');
|
|
68
|
-
expect(config.version).toBe('2.0.0');
|
|
69
|
-
});
|
|
70
|
-
});
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
-
import { execSync } from 'child_process';
|
|
3
|
-
import { createTempDir, cleanupTempDir, writeJsonFile } from '../helpers/test-utils';
|
|
4
|
-
import path from 'path';
|
|
5
|
-
import fs from 'fs-extra';
|
|
6
|
-
|
|
7
|
-
describe('craftdesk list command', () => {
|
|
8
|
-
let tempDir: string;
|
|
9
|
-
let originalCwd: string;
|
|
10
|
-
const cliPath = path.join(__dirname, '../../dist/index.js');
|
|
11
|
-
|
|
12
|
-
beforeEach(async () => {
|
|
13
|
-
tempDir = await createTempDir('list-test-');
|
|
14
|
-
originalCwd = process.cwd();
|
|
15
|
-
process.chdir(tempDir);
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
afterEach(async () => {
|
|
19
|
-
process.chdir(originalCwd);
|
|
20
|
-
await cleanupTempDir(tempDir);
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it('should list installed crafts', async () => {
|
|
24
|
-
// Create craftdesk.json
|
|
25
|
-
await writeJsonFile(path.join(tempDir, 'craftdesk.json'), {
|
|
26
|
-
name: 'test-project',
|
|
27
|
-
version: '1.0.0',
|
|
28
|
-
dependencies: {
|
|
29
|
-
'ruby-on-rails': '^7.0.0',
|
|
30
|
-
'postgres-expert': '^1.0.0'
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
// Create mock installed crafts
|
|
35
|
-
const skillDir = path.join(tempDir, '.claude', 'skills', 'ruby-on-rails');
|
|
36
|
-
await fs.ensureDir(skillDir);
|
|
37
|
-
await writeJsonFile(path.join(skillDir, '.craftdesk-metadata.json'), {
|
|
38
|
-
name: 'ruby-on-rails',
|
|
39
|
-
version: '7.1.0',
|
|
40
|
-
type: 'skill',
|
|
41
|
-
installedAt: new Date().toISOString()
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
const agentDir = path.join(tempDir, '.claude', 'agents', 'postgres-expert');
|
|
45
|
-
await fs.ensureDir(agentDir);
|
|
46
|
-
await writeJsonFile(path.join(agentDir, '.craftdesk-metadata.json'), {
|
|
47
|
-
name: 'postgres-expert',
|
|
48
|
-
version: '1.2.0',
|
|
49
|
-
type: 'agent',
|
|
50
|
-
installedAt: new Date().toISOString()
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
const output = execSync(`node ${cliPath} list`, {
|
|
54
|
-
encoding: 'utf-8'
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
expect(output).toContain('ruby-on-rails');
|
|
58
|
-
expect(output).toContain('7.1.0');
|
|
59
|
-
expect(output).toContain('postgres-expert');
|
|
60
|
-
expect(output).toContain('1.2.0');
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
it('should handle no installed crafts', async () => {
|
|
64
|
-
// Create craftdesk.json first
|
|
65
|
-
await writeJsonFile(path.join(tempDir, 'craftdesk.json'), {
|
|
66
|
-
name: 'empty-project',
|
|
67
|
-
version: '1.0.0',
|
|
68
|
-
dependencies: {}
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
const output = execSync(`node ${cliPath} list`, {
|
|
72
|
-
encoding: 'utf-8'
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
expect(output).toContain('No crafts installed');
|
|
76
|
-
});
|
|
77
|
-
});
|
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
2
|
-
import { ConfigManager } from '../../src/services/config-manager';
|
|
3
|
-
import { createTempDir, cleanupTempDir, writeJsonFile } from '../helpers/test-utils';
|
|
4
|
-
import path from 'path';
|
|
5
|
-
|
|
6
|
-
describe('ConfigManager', () => {
|
|
7
|
-
let configManager: ConfigManager;
|
|
8
|
-
let tempDir: string;
|
|
9
|
-
let originalCwd: string;
|
|
10
|
-
|
|
11
|
-
beforeEach(async () => {
|
|
12
|
-
configManager = new ConfigManager();
|
|
13
|
-
tempDir = await createTempDir('config-test-');
|
|
14
|
-
originalCwd = process.cwd();
|
|
15
|
-
process.chdir(tempDir);
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
afterEach(async () => {
|
|
19
|
-
process.chdir(originalCwd);
|
|
20
|
-
await cleanupTempDir(tempDir);
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
describe('getRegistryForCraft', () => {
|
|
24
|
-
it('should return default registry when no craftdesk.json exists', async () => {
|
|
25
|
-
const registry = await configManager.getRegistryForCraft('test-craft');
|
|
26
|
-
expect(registry).toBe('https://craftdesk.ai');
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
it('should return default registry from craftdesk.json', async () => {
|
|
30
|
-
await writeJsonFile(path.join(tempDir, 'craftdesk.json'), {
|
|
31
|
-
name: 'test',
|
|
32
|
-
version: '1.0.0',
|
|
33
|
-
registries: {
|
|
34
|
-
default: {
|
|
35
|
-
url: 'https://custom-registry.com'
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
const registry = await configManager.getRegistryForCraft('test-craft');
|
|
41
|
-
expect(registry).toBe('https://custom-registry.com');
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
it('should return scoped registry for scoped craft', async () => {
|
|
45
|
-
await writeJsonFile(path.join(tempDir, 'craftdesk.json'), {
|
|
46
|
-
name: 'test',
|
|
47
|
-
version: '1.0.0',
|
|
48
|
-
registries: {
|
|
49
|
-
default: {
|
|
50
|
-
url: 'https://craftdesk.ai'
|
|
51
|
-
},
|
|
52
|
-
'company-private': {
|
|
53
|
-
url: 'https://company.internal',
|
|
54
|
-
scope: '@company'
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
const registry = await configManager.getRegistryForCraft('@company/auth');
|
|
60
|
-
expect(registry).toBe('https://company.internal');
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
it('should fallback to default registry for unmatched scoped craft', async () => {
|
|
64
|
-
await writeJsonFile(path.join(tempDir, 'craftdesk.json'), {
|
|
65
|
-
name: 'test',
|
|
66
|
-
version: '1.0.0',
|
|
67
|
-
registries: {
|
|
68
|
-
default: {
|
|
69
|
-
url: 'https://craftdesk.ai'
|
|
70
|
-
},
|
|
71
|
-
'company-private': {
|
|
72
|
-
url: 'https://company.internal',
|
|
73
|
-
scope: '@company'
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
const registry = await configManager.getRegistryForCraft('@other/craft');
|
|
79
|
-
expect(registry).toBe('https://craftdesk.ai');
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
it('should use final fallback when no registries configured', async () => {
|
|
83
|
-
await writeJsonFile(path.join(tempDir, 'craftdesk.json'), {
|
|
84
|
-
name: 'test',
|
|
85
|
-
version: '1.0.0'
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
const registry = await configManager.getRegistryForCraft('test-craft');
|
|
89
|
-
expect(registry).toBe('https://craftdesk.ai');
|
|
90
|
-
});
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
describe('getAuthToken', () => {
|
|
94
|
-
it('should return null when no craftdesk.json exists', async () => {
|
|
95
|
-
const token = await configManager.getAuthToken('default');
|
|
96
|
-
expect(token).toBeNull();
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
it('should return null when registry not configured', async () => {
|
|
100
|
-
await writeJsonFile(path.join(tempDir, 'craftdesk.json'), {
|
|
101
|
-
name: 'test',
|
|
102
|
-
version: '1.0.0',
|
|
103
|
-
registries: {
|
|
104
|
-
default: {
|
|
105
|
-
url: 'https://craftdesk.ai'
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
const token = await configManager.getAuthToken('nonexistent');
|
|
111
|
-
expect(token).toBeNull();
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
it('should return token from environment variable', async () => {
|
|
115
|
-
await writeJsonFile(path.join(tempDir, 'craftdesk.json'), {
|
|
116
|
-
name: 'test',
|
|
117
|
-
version: '1.0.0',
|
|
118
|
-
registries: {
|
|
119
|
-
'company-private': {
|
|
120
|
-
url: 'https://company.internal',
|
|
121
|
-
scope: '@company'
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
process.env.CRAFTDESK_AUTH_COMPANY_PRIVATE = 'test-token-123';
|
|
127
|
-
|
|
128
|
-
const token = await configManager.getAuthToken('company-private');
|
|
129
|
-
expect(token).toBe('test-token-123');
|
|
130
|
-
|
|
131
|
-
delete process.env.CRAFTDESK_AUTH_COMPANY_PRIVATE;
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
it('should handle registry names with hyphens', async () => {
|
|
135
|
-
await writeJsonFile(path.join(tempDir, 'craftdesk.json'), {
|
|
136
|
-
name: 'test',
|
|
137
|
-
version: '1.0.0',
|
|
138
|
-
registries: {
|
|
139
|
-
'my-custom-registry': {
|
|
140
|
-
url: 'https://custom.com'
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
process.env.CRAFTDESK_AUTH_MY_CUSTOM_REGISTRY = 'custom-token';
|
|
146
|
-
|
|
147
|
-
const token = await configManager.getAuthToken('my-custom-registry');
|
|
148
|
-
expect(token).toBe('custom-token');
|
|
149
|
-
|
|
150
|
-
delete process.env.CRAFTDESK_AUTH_MY_CUSTOM_REGISTRY;
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
it('should return null when environment variable not set', async () => {
|
|
154
|
-
await writeJsonFile(path.join(tempDir, 'craftdesk.json'), {
|
|
155
|
-
name: 'test',
|
|
156
|
-
version: '1.0.0',
|
|
157
|
-
registries: {
|
|
158
|
-
private: {
|
|
159
|
-
url: 'https://private.com'
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
const token = await configManager.getAuthToken('private');
|
|
165
|
-
expect(token).toBeNull();
|
|
166
|
-
});
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
describe('getInstallPath', () => {
|
|
170
|
-
it('should return .claude directory', () => {
|
|
171
|
-
const installPath = configManager.getInstallPath();
|
|
172
|
-
expect(installPath).toBe('.claude');
|
|
173
|
-
});
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
describe('getCraftDeskJson', () => {
|
|
177
|
-
it('should return null when craftdesk.json does not exist', async () => {
|
|
178
|
-
const result = await configManager.getCraftDeskJson();
|
|
179
|
-
expect(result).toBeNull();
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
it('should return parsed craftdesk.json', async () => {
|
|
183
|
-
const craftDeskData = {
|
|
184
|
-
name: 'test-project',
|
|
185
|
-
version: '1.0.0',
|
|
186
|
-
type: 'skill',
|
|
187
|
-
description: 'Test project'
|
|
188
|
-
};
|
|
189
|
-
|
|
190
|
-
await writeJsonFile(path.join(tempDir, 'craftdesk.json'), craftDeskData);
|
|
191
|
-
|
|
192
|
-
const result = await configManager.getCraftDeskJson();
|
|
193
|
-
expect(result).toEqual(craftDeskData);
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
it('should cache craftdesk.json after first read', async () => {
|
|
197
|
-
const craftDeskData = {
|
|
198
|
-
name: 'test-project',
|
|
199
|
-
version: '1.0.0'
|
|
200
|
-
};
|
|
201
|
-
|
|
202
|
-
await writeJsonFile(path.join(tempDir, 'craftdesk.json'), craftDeskData);
|
|
203
|
-
|
|
204
|
-
// First call
|
|
205
|
-
const result1 = await configManager.getCraftDeskJson();
|
|
206
|
-
|
|
207
|
-
// Modify file on disk
|
|
208
|
-
await writeJsonFile(path.join(tempDir, 'craftdesk.json'), {
|
|
209
|
-
name: 'modified',
|
|
210
|
-
version: '2.0.0'
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
// Second call should return cached value
|
|
214
|
-
const result2 = await configManager.getCraftDeskJson();
|
|
215
|
-
|
|
216
|
-
expect(result1).toEqual(craftDeskData);
|
|
217
|
-
expect(result2).toEqual(craftDeskData);
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
it('should return null for malformed JSON', async () => {
|
|
221
|
-
const fs = await import('fs-extra');
|
|
222
|
-
await fs.writeFile(path.join(tempDir, 'craftdesk.json'), 'not valid json', 'utf-8');
|
|
223
|
-
|
|
224
|
-
const result = await configManager.getCraftDeskJson();
|
|
225
|
-
expect(result).toBeNull();
|
|
226
|
-
});
|
|
227
|
-
});
|
|
228
|
-
});
|