@nimblebrain/mpak 0.1.0 → 0.2.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/LICENSE +10 -198
- package/README.md +50 -383
- package/dist/index.d.ts +0 -2
- package/dist/index.js +2113 -4
- package/dist/index.js.map +1 -1
- package/package.json +32 -29
- package/.claude/settings.local.json +0 -19
- package/.env.example +0 -13
- package/.github/workflows/ci.yml +0 -27
- package/CLAUDE.md +0 -283
- package/dist/commands/config.d.ts +0 -31
- package/dist/commands/config.d.ts.map +0 -1
- package/dist/commands/config.js +0 -129
- package/dist/commands/config.js.map +0 -1
- package/dist/commands/packages/pull.d.ts +0 -11
- package/dist/commands/packages/pull.d.ts.map +0 -1
- package/dist/commands/packages/pull.js +0 -72
- package/dist/commands/packages/pull.js.map +0 -1
- package/dist/commands/packages/run.d.ts +0 -47
- package/dist/commands/packages/run.d.ts.map +0 -1
- package/dist/commands/packages/run.js +0 -419
- package/dist/commands/packages/run.js.map +0 -1
- package/dist/commands/packages/search.d.ts +0 -12
- package/dist/commands/packages/search.d.ts.map +0 -1
- package/dist/commands/packages/search.js +0 -63
- package/dist/commands/packages/search.js.map +0 -1
- package/dist/commands/packages/show.d.ts +0 -8
- package/dist/commands/packages/show.d.ts.map +0 -1
- package/dist/commands/packages/show.js +0 -109
- package/dist/commands/packages/show.js.map +0 -1
- package/dist/commands/search.d.ts +0 -12
- package/dist/commands/search.d.ts.map +0 -1
- package/dist/commands/search.js +0 -144
- package/dist/commands/search.js.map +0 -1
- package/dist/commands/skills/index.d.ts +0 -8
- package/dist/commands/skills/index.d.ts.map +0 -1
- package/dist/commands/skills/index.js +0 -8
- package/dist/commands/skills/index.js.map +0 -1
- package/dist/commands/skills/install.d.ts +0 -9
- package/dist/commands/skills/install.d.ts.map +0 -1
- package/dist/commands/skills/install.js +0 -110
- package/dist/commands/skills/install.js.map +0 -1
- package/dist/commands/skills/list.d.ts +0 -8
- package/dist/commands/skills/list.d.ts.map +0 -1
- package/dist/commands/skills/list.js +0 -89
- package/dist/commands/skills/list.js.map +0 -1
- package/dist/commands/skills/pack.d.ts +0 -22
- package/dist/commands/skills/pack.d.ts.map +0 -1
- package/dist/commands/skills/pack.js +0 -116
- package/dist/commands/skills/pack.js.map +0 -1
- package/dist/commands/skills/pull.d.ts +0 -9
- package/dist/commands/skills/pull.d.ts.map +0 -1
- package/dist/commands/skills/pull.js +0 -68
- package/dist/commands/skills/pull.js.map +0 -1
- package/dist/commands/skills/search.d.ts +0 -14
- package/dist/commands/skills/search.d.ts.map +0 -1
- package/dist/commands/skills/search.js +0 -53
- package/dist/commands/skills/search.js.map +0 -1
- package/dist/commands/skills/show.d.ts +0 -8
- package/dist/commands/skills/show.d.ts.map +0 -1
- package/dist/commands/skills/show.js +0 -64
- package/dist/commands/skills/show.js.map +0 -1
- package/dist/commands/skills/validate.d.ts +0 -25
- package/dist/commands/skills/validate.d.ts.map +0 -1
- package/dist/commands/skills/validate.js +0 -191
- package/dist/commands/skills/validate.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/lib/api/registry-client.d.ts +0 -63
- package/dist/lib/api/registry-client.d.ts.map +0 -1
- package/dist/lib/api/registry-client.js +0 -167
- package/dist/lib/api/registry-client.js.map +0 -1
- package/dist/lib/api/skills-client.d.ts +0 -30
- package/dist/lib/api/skills-client.d.ts.map +0 -1
- package/dist/lib/api/skills-client.js +0 -110
- package/dist/lib/api/skills-client.js.map +0 -1
- package/dist/program.d.ts +0 -12
- package/dist/program.d.ts.map +0 -1
- package/dist/program.js +0 -186
- package/dist/program.js.map +0 -1
- package/dist/schemas/generated/api-responses.d.ts +0 -541
- package/dist/schemas/generated/api-responses.d.ts.map +0 -1
- package/dist/schemas/generated/api-responses.js +0 -313
- package/dist/schemas/generated/api-responses.js.map +0 -1
- package/dist/schemas/generated/auth.d.ts +0 -18
- package/dist/schemas/generated/auth.d.ts.map +0 -1
- package/dist/schemas/generated/auth.js +0 -18
- package/dist/schemas/generated/auth.js.map +0 -1
- package/dist/schemas/generated/index.d.ts +0 -5
- package/dist/schemas/generated/index.d.ts.map +0 -1
- package/dist/schemas/generated/index.js +0 -6
- package/dist/schemas/generated/index.js.map +0 -1
- package/dist/schemas/generated/package.d.ts +0 -43
- package/dist/schemas/generated/package.d.ts.map +0 -1
- package/dist/schemas/generated/package.js +0 -20
- package/dist/schemas/generated/package.js.map +0 -1
- package/dist/schemas/generated/skill.d.ts +0 -381
- package/dist/schemas/generated/skill.d.ts.map +0 -1
- package/dist/schemas/generated/skill.js +0 -216
- package/dist/schemas/generated/skill.js.map +0 -1
- package/dist/utils/config-manager.d.ts +0 -66
- package/dist/utils/config-manager.d.ts.map +0 -1
- package/dist/utils/config-manager.js +0 -193
- package/dist/utils/config-manager.js.map +0 -1
- package/dist/utils/errors.d.ts +0 -12
- package/dist/utils/errors.d.ts.map +0 -1
- package/dist/utils/errors.js +0 -27
- package/dist/utils/errors.js.map +0 -1
- package/dist/utils/version.d.ts +0 -5
- package/dist/utils/version.d.ts.map +0 -1
- package/dist/utils/version.js +0 -19
- package/dist/utils/version.js.map +0 -1
- package/eslint.config.js +0 -63
- package/src/commands/config.ts +0 -162
- package/src/commands/packages/pull.ts +0 -96
- package/src/commands/packages/run.test.ts +0 -261
- package/src/commands/packages/run.ts +0 -536
- package/src/commands/packages/search.ts +0 -83
- package/src/commands/packages/show.ts +0 -128
- package/src/commands/search.ts +0 -191
- package/src/commands/skills/index.ts +0 -7
- package/src/commands/skills/install.ts +0 -129
- package/src/commands/skills/list.ts +0 -116
- package/src/commands/skills/pack.test.ts +0 -260
- package/src/commands/skills/pack.ts +0 -145
- package/src/commands/skills/pull.ts +0 -88
- package/src/commands/skills/search.ts +0 -73
- package/src/commands/skills/show.ts +0 -72
- package/src/commands/skills/validate.test.ts +0 -466
- package/src/commands/skills/validate.ts +0 -227
- package/src/index.ts +0 -11
- package/src/lib/api/registry-client.ts +0 -223
- package/src/lib/api/schema.d.ts +0 -520
- package/src/lib/api/skills-client.ts +0 -148
- package/src/program.test.ts +0 -22
- package/src/program.ts +0 -226
- package/src/schemas/config.v1.schema.json +0 -37
- package/src/schemas/generated/api-responses.ts +0 -386
- package/src/schemas/generated/auth.ts +0 -21
- package/src/schemas/generated/index.ts +0 -5
- package/src/schemas/generated/package.ts +0 -29
- package/src/schemas/generated/skill.ts +0 -271
- package/src/utils/config-manager.test.ts +0 -330
- package/src/utils/config-manager.ts +0 -272
- package/src/utils/errors.test.ts +0 -25
- package/src/utils/errors.ts +0 -33
- package/src/utils/version.test.ts +0 -16
- package/src/utils/version.ts +0 -18
- package/test/integration/registry-client.test.ts +0 -180
- package/tsconfig.check.json +0 -9
- package/tsconfig.json +0 -25
- package/vitest.config.ts +0 -14
|
@@ -1,272 +0,0 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
|
|
2
|
-
import { homedir } from 'os';
|
|
3
|
-
import { join } from 'path';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Current config schema version
|
|
7
|
-
*/
|
|
8
|
-
export const CONFIG_VERSION = '1.0.0';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Per-package user configuration (stores user_config values)
|
|
12
|
-
*/
|
|
13
|
-
export interface PackageConfig {
|
|
14
|
-
[key: string]: string;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Configuration structure (v1.0.0)
|
|
19
|
-
*/
|
|
20
|
-
export interface MpakConfig {
|
|
21
|
-
version: string;
|
|
22
|
-
lastUpdated: string;
|
|
23
|
-
registryUrl?: string;
|
|
24
|
-
packages?: Record<string, PackageConfig>;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Error thrown when config file is corrupted or invalid
|
|
29
|
-
*/
|
|
30
|
-
export class ConfigCorruptedError extends Error {
|
|
31
|
-
constructor(
|
|
32
|
-
message: string,
|
|
33
|
-
public readonly configPath: string,
|
|
34
|
-
public readonly cause?: Error
|
|
35
|
-
) {
|
|
36
|
-
super(message);
|
|
37
|
-
this.name = 'ConfigCorruptedError';
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Validates that a parsed object conforms to the MpakConfig schema
|
|
43
|
-
*/
|
|
44
|
-
function validateConfig(data: unknown, configPath: string): MpakConfig {
|
|
45
|
-
if (typeof data !== 'object' || data === null) {
|
|
46
|
-
throw new ConfigCorruptedError(
|
|
47
|
-
'Config file must be a JSON object',
|
|
48
|
-
configPath
|
|
49
|
-
);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const obj = data as Record<string, unknown>;
|
|
53
|
-
|
|
54
|
-
// Required fields
|
|
55
|
-
if (typeof obj.version !== 'string') {
|
|
56
|
-
throw new ConfigCorruptedError(
|
|
57
|
-
'Config missing required field: version (string)',
|
|
58
|
-
configPath
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
if (typeof obj.lastUpdated !== 'string') {
|
|
63
|
-
throw new ConfigCorruptedError(
|
|
64
|
-
'Config missing required field: lastUpdated (string)',
|
|
65
|
-
configPath
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// Optional fields with type validation
|
|
70
|
-
if (obj.registryUrl !== undefined && typeof obj.registryUrl !== 'string') {
|
|
71
|
-
throw new ConfigCorruptedError(
|
|
72
|
-
'Config field registryUrl must be a string',
|
|
73
|
-
configPath
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
if (obj.packages !== undefined) {
|
|
78
|
-
if (typeof obj.packages !== 'object' || obj.packages === null) {
|
|
79
|
-
throw new ConfigCorruptedError(
|
|
80
|
-
'Config field packages must be an object',
|
|
81
|
-
configPath
|
|
82
|
-
);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Validate each package config
|
|
86
|
-
for (const [pkgName, pkgConfig] of Object.entries(
|
|
87
|
-
obj.packages as Record<string, unknown>
|
|
88
|
-
)) {
|
|
89
|
-
if (typeof pkgConfig !== 'object' || pkgConfig === null) {
|
|
90
|
-
throw new ConfigCorruptedError(
|
|
91
|
-
`Config packages.${pkgName} must be an object`,
|
|
92
|
-
configPath
|
|
93
|
-
);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
for (const [key, value] of Object.entries(
|
|
97
|
-
pkgConfig as Record<string, unknown>
|
|
98
|
-
)) {
|
|
99
|
-
if (typeof value !== 'string') {
|
|
100
|
-
throw new ConfigCorruptedError(
|
|
101
|
-
`Config packages.${pkgName}.${key} must be a string`,
|
|
102
|
-
configPath
|
|
103
|
-
);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Check for unknown fields (additionalProperties: false in schema)
|
|
110
|
-
const knownFields = new Set(['version', 'lastUpdated', 'registryUrl', 'packages']);
|
|
111
|
-
for (const key of Object.keys(obj)) {
|
|
112
|
-
if (!knownFields.has(key)) {
|
|
113
|
-
throw new ConfigCorruptedError(
|
|
114
|
-
`Config contains unknown field: ${key}`,
|
|
115
|
-
configPath
|
|
116
|
-
);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
return data as MpakConfig;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Configuration manager for CLI settings in ~/.mpak/config.json
|
|
125
|
-
*/
|
|
126
|
-
export class ConfigManager {
|
|
127
|
-
private configDir: string;
|
|
128
|
-
private configFile: string;
|
|
129
|
-
private config: MpakConfig | null = null;
|
|
130
|
-
|
|
131
|
-
constructor() {
|
|
132
|
-
this.configDir = join(homedir(), '.mpak');
|
|
133
|
-
this.configFile = join(this.configDir, 'config.json');
|
|
134
|
-
this.ensureConfigDir();
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
private ensureConfigDir(): void {
|
|
138
|
-
if (!existsSync(this.configDir)) {
|
|
139
|
-
mkdirSync(this.configDir, { recursive: true, mode: 0o700 });
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
loadConfig(): MpakConfig {
|
|
144
|
-
if (this.config) {
|
|
145
|
-
return this.config;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
if (!existsSync(this.configFile)) {
|
|
149
|
-
this.config = {
|
|
150
|
-
version: CONFIG_VERSION,
|
|
151
|
-
lastUpdated: new Date().toISOString(),
|
|
152
|
-
};
|
|
153
|
-
this.saveConfig();
|
|
154
|
-
return this.config;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
let configJson: string;
|
|
158
|
-
try {
|
|
159
|
-
configJson = readFileSync(this.configFile, 'utf8');
|
|
160
|
-
} catch (err) {
|
|
161
|
-
throw new ConfigCorruptedError(
|
|
162
|
-
`Failed to read config file: ${err instanceof Error ? err.message : String(err)}`,
|
|
163
|
-
this.configFile,
|
|
164
|
-
err instanceof Error ? err : undefined
|
|
165
|
-
);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
let parsed: unknown;
|
|
169
|
-
try {
|
|
170
|
-
parsed = JSON.parse(configJson);
|
|
171
|
-
} catch (err) {
|
|
172
|
-
throw new ConfigCorruptedError(
|
|
173
|
-
`Config file contains invalid JSON: ${err instanceof Error ? err.message : String(err)}`,
|
|
174
|
-
this.configFile,
|
|
175
|
-
err instanceof Error ? err : undefined
|
|
176
|
-
);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// Validate structure against schema
|
|
180
|
-
this.config = validateConfig(parsed, this.configFile);
|
|
181
|
-
return this.config;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
private saveConfig(): void {
|
|
185
|
-
if (!this.config) {
|
|
186
|
-
return;
|
|
187
|
-
}
|
|
188
|
-
this.config.lastUpdated = new Date().toISOString();
|
|
189
|
-
const configJson = JSON.stringify(this.config, null, 2);
|
|
190
|
-
writeFileSync(this.configFile, configJson, { mode: 0o600 });
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
setRegistryUrl(url: string): void {
|
|
194
|
-
const config = this.loadConfig();
|
|
195
|
-
config.registryUrl = url;
|
|
196
|
-
this.saveConfig();
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
getRegistryUrl(): string {
|
|
200
|
-
const config = this.loadConfig();
|
|
201
|
-
return config.registryUrl || process.env.MPAK_REGISTRY_URL || 'https://api.mpak.dev';
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
* Get all stored config values for a package
|
|
206
|
-
*/
|
|
207
|
-
getPackageConfig(packageName: string): PackageConfig | undefined {
|
|
208
|
-
const config = this.loadConfig();
|
|
209
|
-
return config.packages?.[packageName];
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
/**
|
|
213
|
-
* Get a specific config value for a package
|
|
214
|
-
*/
|
|
215
|
-
getPackageConfigValue(packageName: string, key: string): string | undefined {
|
|
216
|
-
const packageConfig = this.getPackageConfig(packageName);
|
|
217
|
-
return packageConfig?.[key];
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* Set a config value for a package
|
|
222
|
-
*/
|
|
223
|
-
setPackageConfigValue(packageName: string, key: string, value: string): void {
|
|
224
|
-
const config = this.loadConfig();
|
|
225
|
-
if (!config.packages) {
|
|
226
|
-
config.packages = {};
|
|
227
|
-
}
|
|
228
|
-
if (!config.packages[packageName]) {
|
|
229
|
-
config.packages[packageName] = {};
|
|
230
|
-
}
|
|
231
|
-
config.packages[packageName][key] = value;
|
|
232
|
-
this.saveConfig();
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* Clear all config values for a package
|
|
237
|
-
*/
|
|
238
|
-
clearPackageConfig(packageName: string): boolean {
|
|
239
|
-
const config = this.loadConfig();
|
|
240
|
-
if (config.packages?.[packageName]) {
|
|
241
|
-
delete config.packages[packageName];
|
|
242
|
-
this.saveConfig();
|
|
243
|
-
return true;
|
|
244
|
-
}
|
|
245
|
-
return false;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
/**
|
|
249
|
-
* Clear a specific config value for a package
|
|
250
|
-
*/
|
|
251
|
-
clearPackageConfigValue(packageName: string, key: string): boolean {
|
|
252
|
-
const config = this.loadConfig();
|
|
253
|
-
if (config.packages?.[packageName]?.[key] !== undefined) {
|
|
254
|
-
delete config.packages[packageName][key];
|
|
255
|
-
// Clean up empty package entries
|
|
256
|
-
if (Object.keys(config.packages[packageName]).length === 0) {
|
|
257
|
-
delete config.packages[packageName];
|
|
258
|
-
}
|
|
259
|
-
this.saveConfig();
|
|
260
|
-
return true;
|
|
261
|
-
}
|
|
262
|
-
return false;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
/**
|
|
266
|
-
* List all packages with stored config
|
|
267
|
-
*/
|
|
268
|
-
listPackagesWithConfig(): string[] {
|
|
269
|
-
const config = this.loadConfig();
|
|
270
|
-
return Object.keys(config.packages || {});
|
|
271
|
-
}
|
|
272
|
-
}
|
package/src/utils/errors.test.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { CLIError } from './errors.js';
|
|
3
|
-
|
|
4
|
-
describe('CLIError', () => {
|
|
5
|
-
it('should create error with message', () => {
|
|
6
|
-
const error = new CLIError('Test error');
|
|
7
|
-
expect(error.message).toBe('Test error');
|
|
8
|
-
expect(error.name).toBe('CLIError');
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
it('should have default exit code of 1', () => {
|
|
12
|
-
const error = new CLIError('Test error');
|
|
13
|
-
expect(error.exitCode).toBe(1);
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
it('should allow custom exit code', () => {
|
|
17
|
-
const error = new CLIError('Test error', 2);
|
|
18
|
-
expect(error.exitCode).toBe(2);
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
it('should be instance of Error', () => {
|
|
22
|
-
const error = new CLIError('Test error');
|
|
23
|
-
expect(error).toBeInstanceOf(Error);
|
|
24
|
-
});
|
|
25
|
-
});
|
package/src/utils/errors.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Custom error class for CLI errors
|
|
3
|
-
*/
|
|
4
|
-
export class CLIError extends Error {
|
|
5
|
-
public readonly exitCode: number;
|
|
6
|
-
|
|
7
|
-
constructor(
|
|
8
|
-
message: string,
|
|
9
|
-
exitCode: number = 1
|
|
10
|
-
) {
|
|
11
|
-
super(message);
|
|
12
|
-
this.name = 'CLIError';
|
|
13
|
-
this.exitCode = exitCode;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Handles errors gracefully and exits with appropriate code
|
|
19
|
-
*/
|
|
20
|
-
export function handleError(error: unknown): never {
|
|
21
|
-
if (error instanceof CLIError) {
|
|
22
|
-
console.error(`Error: ${error.message}`);
|
|
23
|
-
process.exit(error.exitCode);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
if (error instanceof Error) {
|
|
27
|
-
console.error(`Error: ${error.message}`);
|
|
28
|
-
process.exit(1);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
console.error('An unexpected error occurred');
|
|
32
|
-
process.exit(1);
|
|
33
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { getVersion } from './version.js';
|
|
3
|
-
|
|
4
|
-
describe('getVersion', () => {
|
|
5
|
-
it('should return a valid version string', () => {
|
|
6
|
-
const version = getVersion();
|
|
7
|
-
expect(version).toBeTruthy();
|
|
8
|
-
expect(typeof version).toBe('string');
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
it('should match semver format or be "unknown"', () => {
|
|
12
|
-
const version = getVersion();
|
|
13
|
-
const semverRegex = /^\d+\.\d+\.\d+/;
|
|
14
|
-
expect(version === 'unknown' || semverRegex.test(version)).toBe(true);
|
|
15
|
-
});
|
|
16
|
-
});
|
package/src/utils/version.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { readFileSync } from 'fs';
|
|
2
|
-
import { fileURLToPath } from 'url';
|
|
3
|
-
import { dirname, join } from 'path';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Gets the current version from package.json
|
|
7
|
-
*/
|
|
8
|
-
export function getVersion(): string {
|
|
9
|
-
try {
|
|
10
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
11
|
-
const __dirname = dirname(__filename);
|
|
12
|
-
const packageJsonPath = join(__dirname, '../../package.json');
|
|
13
|
-
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
14
|
-
return packageJson.version;
|
|
15
|
-
} catch (_error) {
|
|
16
|
-
return 'unknown';
|
|
17
|
-
}
|
|
18
|
-
}
|
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, afterAll } from 'vitest';
|
|
2
|
-
import { RegistryClient } from '../../src/lib/api/registry-client.js';
|
|
3
|
-
import * as fs from 'fs';
|
|
4
|
-
import * as path from 'path';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Integration tests for the mpak registry client
|
|
8
|
-
*
|
|
9
|
-
* These tests hit the live api.mpak.dev registry using the @nimblebraininc/echo
|
|
10
|
-
* bundle as a known fixture. They verify the full flow from search to download.
|
|
11
|
-
*
|
|
12
|
-
* Run with: npm run test:integration
|
|
13
|
-
*/
|
|
14
|
-
describe('RegistryClient Integration', () => {
|
|
15
|
-
const client = new RegistryClient();
|
|
16
|
-
const testBundle = '@nimblebraininc/echo';
|
|
17
|
-
const downloadedFiles: string[] = [];
|
|
18
|
-
|
|
19
|
-
afterAll(() => {
|
|
20
|
-
// Clean up any downloaded files
|
|
21
|
-
for (const file of downloadedFiles) {
|
|
22
|
-
if (fs.existsSync(file)) {
|
|
23
|
-
fs.unlinkSync(file);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
describe('searchBundles', () => {
|
|
29
|
-
it('should find echo bundle when searching for "echo"', async () => {
|
|
30
|
-
const result = await client.searchBundles('echo');
|
|
31
|
-
|
|
32
|
-
expect(result.bundles).toBeDefined();
|
|
33
|
-
expect(result.bundles.length).toBeGreaterThan(0);
|
|
34
|
-
|
|
35
|
-
const echoBundle = result.bundles.find(b => b.name === testBundle);
|
|
36
|
-
expect(echoBundle).toBeDefined();
|
|
37
|
-
expect(echoBundle?.description).toContain('Echo');
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it('should return empty results for nonsense query', async () => {
|
|
41
|
-
const result = await client.searchBundles('xyznonexistent12345');
|
|
42
|
-
|
|
43
|
-
expect(result.bundles).toBeDefined();
|
|
44
|
-
expect(result.bundles.length).toBe(0);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it('should respect limit parameter', async () => {
|
|
48
|
-
const result = await client.searchBundles('', { limit: 1 });
|
|
49
|
-
|
|
50
|
-
expect(result.bundles.length).toBeLessThanOrEqual(1);
|
|
51
|
-
});
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
describe('getBundle', () => {
|
|
55
|
-
it('should return bundle details for @nimblebraininc/echo', async () => {
|
|
56
|
-
const bundle = await client.getBundle(testBundle);
|
|
57
|
-
|
|
58
|
-
expect(bundle.name).toBe(testBundle);
|
|
59
|
-
expect(bundle.description).toBeDefined();
|
|
60
|
-
expect(bundle.server_type).toBe('python');
|
|
61
|
-
expect(bundle.author).toBeDefined();
|
|
62
|
-
expect(bundle.latest_version).toBeDefined();
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
it('should include provenance information', async () => {
|
|
66
|
-
const bundle = await client.getBundle(testBundle);
|
|
67
|
-
|
|
68
|
-
expect(bundle.provenance).toBeDefined();
|
|
69
|
-
expect(bundle.provenance?.provider).toBe('github_oidc');
|
|
70
|
-
expect(bundle.provenance?.repository).toContain('mcp-echo');
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
it('should throw error for non-existent bundle', async () => {
|
|
74
|
-
await expect(
|
|
75
|
-
client.getBundle('@nonexistent/bundle-xyz')
|
|
76
|
-
).rejects.toThrow('Bundle not found');
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it('should throw error for unscoped package name', async () => {
|
|
80
|
-
await expect(
|
|
81
|
-
client.getBundle('unscoped-name')
|
|
82
|
-
).rejects.toThrow('Package name must be scoped');
|
|
83
|
-
});
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
describe('getVersions', () => {
|
|
87
|
-
it('should return version list with platforms', async () => {
|
|
88
|
-
const result = await client.getVersions(testBundle);
|
|
89
|
-
|
|
90
|
-
expect(result.versions).toBeDefined();
|
|
91
|
-
expect(result.versions.length).toBeGreaterThan(0);
|
|
92
|
-
|
|
93
|
-
const latestVersion = result.versions[0];
|
|
94
|
-
expect(latestVersion.version).toBeDefined();
|
|
95
|
-
expect(latestVersion.platforms).toBeDefined();
|
|
96
|
-
expect(latestVersion.platforms.length).toBeGreaterThan(0);
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
it('should include linux platforms for echo bundle', async () => {
|
|
100
|
-
const result = await client.getVersions(testBundle);
|
|
101
|
-
|
|
102
|
-
const latestVersion = result.versions[0];
|
|
103
|
-
const platforms = latestVersion.platforms.map(p => `${p.os}-${p.arch}`);
|
|
104
|
-
|
|
105
|
-
expect(platforms).toContain('linux-x64');
|
|
106
|
-
expect(platforms).toContain('linux-arm64');
|
|
107
|
-
});
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
describe('getDownloadInfo', () => {
|
|
111
|
-
it('should return download URL for latest version', async () => {
|
|
112
|
-
const info = await client.getDownloadInfo(testBundle, undefined, {
|
|
113
|
-
os: 'linux',
|
|
114
|
-
arch: 'x64',
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
expect(info.url).toBeDefined();
|
|
118
|
-
expect(info.url).toMatch(/^https?:\/\//);
|
|
119
|
-
expect(info.bundle.version).toBeDefined();
|
|
120
|
-
expect(info.bundle.platform).toBeDefined();
|
|
121
|
-
expect(info.bundle.size).toBeGreaterThan(0);
|
|
122
|
-
expect(info.bundle.sha256).toBeDefined();
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
it('should return correct artifact for requested platform', async () => {
|
|
126
|
-
const info = await client.getDownloadInfo(testBundle, undefined, {
|
|
127
|
-
os: 'linux',
|
|
128
|
-
arch: 'arm64',
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
expect(info.bundle.platform.os).toBe('linux');
|
|
132
|
-
expect(info.bundle.platform.arch).toBe('arm64');
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
it('should return download info for specific version', async () => {
|
|
136
|
-
const versions = await client.getVersions(testBundle);
|
|
137
|
-
const specificVersion = versions.versions[0].version;
|
|
138
|
-
|
|
139
|
-
const info = await client.getDownloadInfo(testBundle, specificVersion, {
|
|
140
|
-
os: 'linux',
|
|
141
|
-
arch: 'x64',
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
expect(info.bundle.version).toBe(specificVersion);
|
|
145
|
-
});
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
describe('downloadBundle', () => {
|
|
149
|
-
it('should download bundle file successfully', async () => {
|
|
150
|
-
const info = await client.getDownloadInfo(testBundle, undefined, {
|
|
151
|
-
os: 'linux',
|
|
152
|
-
arch: 'x64',
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
const outputPath = path.join(
|
|
156
|
-
process.cwd(),
|
|
157
|
-
`test-download-${Date.now()}.mcpb`
|
|
158
|
-
);
|
|
159
|
-
downloadedFiles.push(outputPath);
|
|
160
|
-
|
|
161
|
-
await client.downloadBundle(info.url, outputPath);
|
|
162
|
-
|
|
163
|
-
expect(fs.existsSync(outputPath)).toBe(true);
|
|
164
|
-
|
|
165
|
-
const stats = fs.statSync(outputPath);
|
|
166
|
-
expect(stats.size).toBe(info.bundle.size);
|
|
167
|
-
}, 60000); // 60s timeout for download
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
describe('detectPlatform', () => {
|
|
171
|
-
it('should return valid platform object', () => {
|
|
172
|
-
const platform = RegistryClient.detectPlatform();
|
|
173
|
-
|
|
174
|
-
expect(platform.os).toBeDefined();
|
|
175
|
-
expect(platform.arch).toBeDefined();
|
|
176
|
-
expect(['darwin', 'linux', 'win32', 'any']).toContain(platform.os);
|
|
177
|
-
expect(['x64', 'arm64', 'any']).toContain(platform.arch);
|
|
178
|
-
});
|
|
179
|
-
});
|
|
180
|
-
});
|
package/tsconfig.check.json
DELETED
package/tsconfig.json
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2022",
|
|
4
|
-
"module": "ES2022",
|
|
5
|
-
"lib": ["ES2022"],
|
|
6
|
-
"moduleResolution": "bundler",
|
|
7
|
-
"resolveJsonModule": true,
|
|
8
|
-
"allowJs": true,
|
|
9
|
-
"outDir": "./dist",
|
|
10
|
-
"rootDir": "./src",
|
|
11
|
-
"strict": true,
|
|
12
|
-
"esModuleInterop": true,
|
|
13
|
-
"skipLibCheck": true,
|
|
14
|
-
"forceConsistentCasingInFileNames": true,
|
|
15
|
-
"declaration": true,
|
|
16
|
-
"declarationMap": true,
|
|
17
|
-
"sourceMap": true,
|
|
18
|
-
"noUnusedLocals": true,
|
|
19
|
-
"noUnusedParameters": true,
|
|
20
|
-
"noImplicitReturns": true,
|
|
21
|
-
"noFallthroughCasesInSwitch": true
|
|
22
|
-
},
|
|
23
|
-
"include": ["src/**/*"],
|
|
24
|
-
"exclude": ["node_modules", "dist", "**/*.test.ts"]
|
|
25
|
-
}
|
package/vitest.config.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from 'vitest/config';
|
|
2
|
-
|
|
3
|
-
export default defineConfig({
|
|
4
|
-
test: {
|
|
5
|
-
globals: true,
|
|
6
|
-
environment: 'node',
|
|
7
|
-
include: ['src/**/*.test.ts', 'test/**/*.test.ts'],
|
|
8
|
-
coverage: {
|
|
9
|
-
provider: 'v8',
|
|
10
|
-
reporter: ['text', 'json', 'html'],
|
|
11
|
-
exclude: ['dist', 'node_modules', '**/*.test.ts', '**/*.config.ts', 'test'],
|
|
12
|
-
},
|
|
13
|
-
},
|
|
14
|
-
});
|