@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.
Files changed (151) hide show
  1. package/LICENSE +10 -198
  2. package/README.md +50 -383
  3. package/dist/index.d.ts +0 -2
  4. package/dist/index.js +2113 -4
  5. package/dist/index.js.map +1 -1
  6. package/package.json +32 -29
  7. package/.claude/settings.local.json +0 -19
  8. package/.env.example +0 -13
  9. package/.github/workflows/ci.yml +0 -27
  10. package/CLAUDE.md +0 -283
  11. package/dist/commands/config.d.ts +0 -31
  12. package/dist/commands/config.d.ts.map +0 -1
  13. package/dist/commands/config.js +0 -129
  14. package/dist/commands/config.js.map +0 -1
  15. package/dist/commands/packages/pull.d.ts +0 -11
  16. package/dist/commands/packages/pull.d.ts.map +0 -1
  17. package/dist/commands/packages/pull.js +0 -72
  18. package/dist/commands/packages/pull.js.map +0 -1
  19. package/dist/commands/packages/run.d.ts +0 -47
  20. package/dist/commands/packages/run.d.ts.map +0 -1
  21. package/dist/commands/packages/run.js +0 -419
  22. package/dist/commands/packages/run.js.map +0 -1
  23. package/dist/commands/packages/search.d.ts +0 -12
  24. package/dist/commands/packages/search.d.ts.map +0 -1
  25. package/dist/commands/packages/search.js +0 -63
  26. package/dist/commands/packages/search.js.map +0 -1
  27. package/dist/commands/packages/show.d.ts +0 -8
  28. package/dist/commands/packages/show.d.ts.map +0 -1
  29. package/dist/commands/packages/show.js +0 -109
  30. package/dist/commands/packages/show.js.map +0 -1
  31. package/dist/commands/search.d.ts +0 -12
  32. package/dist/commands/search.d.ts.map +0 -1
  33. package/dist/commands/search.js +0 -144
  34. package/dist/commands/search.js.map +0 -1
  35. package/dist/commands/skills/index.d.ts +0 -8
  36. package/dist/commands/skills/index.d.ts.map +0 -1
  37. package/dist/commands/skills/index.js +0 -8
  38. package/dist/commands/skills/index.js.map +0 -1
  39. package/dist/commands/skills/install.d.ts +0 -9
  40. package/dist/commands/skills/install.d.ts.map +0 -1
  41. package/dist/commands/skills/install.js +0 -110
  42. package/dist/commands/skills/install.js.map +0 -1
  43. package/dist/commands/skills/list.d.ts +0 -8
  44. package/dist/commands/skills/list.d.ts.map +0 -1
  45. package/dist/commands/skills/list.js +0 -89
  46. package/dist/commands/skills/list.js.map +0 -1
  47. package/dist/commands/skills/pack.d.ts +0 -22
  48. package/dist/commands/skills/pack.d.ts.map +0 -1
  49. package/dist/commands/skills/pack.js +0 -116
  50. package/dist/commands/skills/pack.js.map +0 -1
  51. package/dist/commands/skills/pull.d.ts +0 -9
  52. package/dist/commands/skills/pull.d.ts.map +0 -1
  53. package/dist/commands/skills/pull.js +0 -68
  54. package/dist/commands/skills/pull.js.map +0 -1
  55. package/dist/commands/skills/search.d.ts +0 -14
  56. package/dist/commands/skills/search.d.ts.map +0 -1
  57. package/dist/commands/skills/search.js +0 -53
  58. package/dist/commands/skills/search.js.map +0 -1
  59. package/dist/commands/skills/show.d.ts +0 -8
  60. package/dist/commands/skills/show.d.ts.map +0 -1
  61. package/dist/commands/skills/show.js +0 -64
  62. package/dist/commands/skills/show.js.map +0 -1
  63. package/dist/commands/skills/validate.d.ts +0 -25
  64. package/dist/commands/skills/validate.d.ts.map +0 -1
  65. package/dist/commands/skills/validate.js +0 -191
  66. package/dist/commands/skills/validate.js.map +0 -1
  67. package/dist/index.d.ts.map +0 -1
  68. package/dist/lib/api/registry-client.d.ts +0 -63
  69. package/dist/lib/api/registry-client.d.ts.map +0 -1
  70. package/dist/lib/api/registry-client.js +0 -167
  71. package/dist/lib/api/registry-client.js.map +0 -1
  72. package/dist/lib/api/skills-client.d.ts +0 -30
  73. package/dist/lib/api/skills-client.d.ts.map +0 -1
  74. package/dist/lib/api/skills-client.js +0 -110
  75. package/dist/lib/api/skills-client.js.map +0 -1
  76. package/dist/program.d.ts +0 -12
  77. package/dist/program.d.ts.map +0 -1
  78. package/dist/program.js +0 -186
  79. package/dist/program.js.map +0 -1
  80. package/dist/schemas/generated/api-responses.d.ts +0 -541
  81. package/dist/schemas/generated/api-responses.d.ts.map +0 -1
  82. package/dist/schemas/generated/api-responses.js +0 -313
  83. package/dist/schemas/generated/api-responses.js.map +0 -1
  84. package/dist/schemas/generated/auth.d.ts +0 -18
  85. package/dist/schemas/generated/auth.d.ts.map +0 -1
  86. package/dist/schemas/generated/auth.js +0 -18
  87. package/dist/schemas/generated/auth.js.map +0 -1
  88. package/dist/schemas/generated/index.d.ts +0 -5
  89. package/dist/schemas/generated/index.d.ts.map +0 -1
  90. package/dist/schemas/generated/index.js +0 -6
  91. package/dist/schemas/generated/index.js.map +0 -1
  92. package/dist/schemas/generated/package.d.ts +0 -43
  93. package/dist/schemas/generated/package.d.ts.map +0 -1
  94. package/dist/schemas/generated/package.js +0 -20
  95. package/dist/schemas/generated/package.js.map +0 -1
  96. package/dist/schemas/generated/skill.d.ts +0 -381
  97. package/dist/schemas/generated/skill.d.ts.map +0 -1
  98. package/dist/schemas/generated/skill.js +0 -216
  99. package/dist/schemas/generated/skill.js.map +0 -1
  100. package/dist/utils/config-manager.d.ts +0 -66
  101. package/dist/utils/config-manager.d.ts.map +0 -1
  102. package/dist/utils/config-manager.js +0 -193
  103. package/dist/utils/config-manager.js.map +0 -1
  104. package/dist/utils/errors.d.ts +0 -12
  105. package/dist/utils/errors.d.ts.map +0 -1
  106. package/dist/utils/errors.js +0 -27
  107. package/dist/utils/errors.js.map +0 -1
  108. package/dist/utils/version.d.ts +0 -5
  109. package/dist/utils/version.d.ts.map +0 -1
  110. package/dist/utils/version.js +0 -19
  111. package/dist/utils/version.js.map +0 -1
  112. package/eslint.config.js +0 -63
  113. package/src/commands/config.ts +0 -162
  114. package/src/commands/packages/pull.ts +0 -96
  115. package/src/commands/packages/run.test.ts +0 -261
  116. package/src/commands/packages/run.ts +0 -536
  117. package/src/commands/packages/search.ts +0 -83
  118. package/src/commands/packages/show.ts +0 -128
  119. package/src/commands/search.ts +0 -191
  120. package/src/commands/skills/index.ts +0 -7
  121. package/src/commands/skills/install.ts +0 -129
  122. package/src/commands/skills/list.ts +0 -116
  123. package/src/commands/skills/pack.test.ts +0 -260
  124. package/src/commands/skills/pack.ts +0 -145
  125. package/src/commands/skills/pull.ts +0 -88
  126. package/src/commands/skills/search.ts +0 -73
  127. package/src/commands/skills/show.ts +0 -72
  128. package/src/commands/skills/validate.test.ts +0 -466
  129. package/src/commands/skills/validate.ts +0 -227
  130. package/src/index.ts +0 -11
  131. package/src/lib/api/registry-client.ts +0 -223
  132. package/src/lib/api/schema.d.ts +0 -520
  133. package/src/lib/api/skills-client.ts +0 -148
  134. package/src/program.test.ts +0 -22
  135. package/src/program.ts +0 -226
  136. package/src/schemas/config.v1.schema.json +0 -37
  137. package/src/schemas/generated/api-responses.ts +0 -386
  138. package/src/schemas/generated/auth.ts +0 -21
  139. package/src/schemas/generated/index.ts +0 -5
  140. package/src/schemas/generated/package.ts +0 -29
  141. package/src/schemas/generated/skill.ts +0 -271
  142. package/src/utils/config-manager.test.ts +0 -330
  143. package/src/utils/config-manager.ts +0 -272
  144. package/src/utils/errors.test.ts +0 -25
  145. package/src/utils/errors.ts +0 -33
  146. package/src/utils/version.test.ts +0 -16
  147. package/src/utils/version.ts +0 -18
  148. package/test/integration/registry-client.test.ts +0 -180
  149. package/tsconfig.check.json +0 -9
  150. package/tsconfig.json +0 -25
  151. 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
- }
@@ -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
- });
@@ -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
- });
@@ -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
- });
@@ -1,9 +0,0 @@
1
- {
2
- "extends": "./tsconfig.json",
3
- "compilerOptions": {
4
- "rootDir": ".",
5
- "noEmit": true
6
- },
7
- "include": ["src/**/*", "test/**/*"],
8
- "exclude": ["node_modules", "dist"]
9
- }
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
- });