@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,261 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { homedir } from 'os';
3
- import { join } from 'path';
4
- import { parsePackageSpec, getCacheDir, resolveArgs, substituteUserConfig, substituteEnvVars, getLocalCacheDir, localBundleNeedsExtract } from './run.js';
5
-
6
- describe('parsePackageSpec', () => {
7
- describe('scoped packages', () => {
8
- it('parses @scope/name without version', () => {
9
- expect(parsePackageSpec('@scope/name')).toEqual({
10
- name: '@scope/name',
11
- });
12
- });
13
-
14
- it('parses @scope/name@1.0.0', () => {
15
- expect(parsePackageSpec('@scope/name@1.0.0')).toEqual({
16
- name: '@scope/name',
17
- version: '1.0.0',
18
- });
19
- });
20
-
21
- it('parses prerelease versions @scope/name@1.0.0-beta.1', () => {
22
- expect(parsePackageSpec('@scope/name@1.0.0-beta.1')).toEqual({
23
- name: '@scope/name',
24
- version: '1.0.0-beta.1',
25
- });
26
- });
27
-
28
- it('parses version with build metadata @scope/name@1.0.0+build.123', () => {
29
- expect(parsePackageSpec('@scope/name@1.0.0+build.123')).toEqual({
30
- name: '@scope/name',
31
- version: '1.0.0+build.123',
32
- });
33
- });
34
- });
35
-
36
- describe('edge cases', () => {
37
- it('handles package name with multiple slashes @org/sub/name', () => {
38
- // This is technically invalid per npm spec, but we should handle gracefully
39
- const result = parsePackageSpec('@org/sub/name');
40
- expect(result.name).toBe('@org/sub/name');
41
- });
42
-
43
- it('handles unscoped package name', () => {
44
- expect(parsePackageSpec('simple-name')).toEqual({
45
- name: 'simple-name',
46
- });
47
- });
48
-
49
- it('treats unscoped@version as invalid (mpak requires scoped packages)', () => {
50
- // mpak only supports scoped packages (@scope/name)
51
- // An unscoped name with @ is treated as the full name, not name@version
52
- expect(parsePackageSpec('unscoped@1.0.0')).toEqual({
53
- name: 'unscoped@1.0.0',
54
- });
55
- });
56
-
57
- it('handles empty string', () => {
58
- expect(parsePackageSpec('')).toEqual({ name: '' });
59
- });
60
-
61
- it('handles @ only', () => {
62
- expect(parsePackageSpec('@')).toEqual({ name: '@' });
63
- });
64
- });
65
- });
66
-
67
- describe('getCacheDir', () => {
68
- const expectedBase = join(homedir(), '.mpak', 'cache');
69
-
70
- it('converts @scope/name to scope-name', () => {
71
- expect(getCacheDir('@nimblebraininc/echo')).toBe(
72
- join(expectedBase, 'nimblebraininc-echo')
73
- );
74
- });
75
-
76
- it('handles simple scoped names', () => {
77
- expect(getCacheDir('@foo/bar')).toBe(join(expectedBase, 'foo-bar'));
78
- });
79
-
80
- it('handles unscoped names', () => {
81
- expect(getCacheDir('simple')).toBe(join(expectedBase, 'simple'));
82
- });
83
- });
84
-
85
- describe('resolveArgs', () => {
86
- const cacheDir = '/Users/test/.mpak/cache/scope-name';
87
-
88
- it('resolves ${__dirname} placeholder', () => {
89
- expect(resolveArgs(['${__dirname}/dist/index.js'], cacheDir)).toEqual([
90
- `${cacheDir}/dist/index.js`,
91
- ]);
92
- });
93
-
94
- it('resolves multiple ${__dirname} in single arg', () => {
95
- expect(
96
- resolveArgs(['--config=${__dirname}/config.json'], cacheDir)
97
- ).toEqual([`--config=${cacheDir}/config.json`]);
98
- });
99
-
100
- it('resolves ${__dirname} in multiple args', () => {
101
- expect(
102
- resolveArgs(
103
- ['${__dirname}/index.js', '--config', '${__dirname}/config.json'],
104
- cacheDir
105
- )
106
- ).toEqual([
107
- `${cacheDir}/index.js`,
108
- '--config',
109
- `${cacheDir}/config.json`,
110
- ]);
111
- });
112
-
113
- it('leaves args without placeholders unchanged', () => {
114
- expect(resolveArgs(['-m', 'mcp_echo.server'], cacheDir)).toEqual([
115
- '-m',
116
- 'mcp_echo.server',
117
- ]);
118
- });
119
-
120
- it('handles empty args array', () => {
121
- expect(resolveArgs([], cacheDir)).toEqual([]);
122
- });
123
-
124
- it('handles Windows-style paths in cacheDir', () => {
125
- const winPath = 'C:\\Users\\test\\.mpak\\cache\\scope-name';
126
- expect(resolveArgs(['${__dirname}\\dist\\index.js'], winPath)).toEqual([
127
- `${winPath}\\dist\\index.js`,
128
- ]);
129
- });
130
- });
131
-
132
- describe('substituteUserConfig', () => {
133
- it('substitutes single user_config variable', () => {
134
- expect(
135
- substituteUserConfig('${user_config.api_key}', { api_key: 'secret123' })
136
- ).toBe('secret123');
137
- });
138
-
139
- it('substitutes multiple user_config variables', () => {
140
- expect(
141
- substituteUserConfig('key=${user_config.key}&secret=${user_config.secret}', {
142
- key: 'mykey',
143
- secret: 'mysecret',
144
- })
145
- ).toBe('key=mykey&secret=mysecret');
146
- });
147
-
148
- it('leaves unmatched variables unchanged', () => {
149
- expect(
150
- substituteUserConfig('${user_config.missing}', { other: 'value' })
151
- ).toBe('${user_config.missing}');
152
- });
153
-
154
- it('handles mixed matched and unmatched variables', () => {
155
- expect(
156
- substituteUserConfig('${user_config.found}-${user_config.missing}', {
157
- found: 'yes',
158
- })
159
- ).toBe('yes-${user_config.missing}');
160
- });
161
-
162
- it('handles empty config values', () => {
163
- expect(
164
- substituteUserConfig('${user_config.empty}', { empty: '' })
165
- ).toBe('');
166
- });
167
-
168
- it('handles values with special characters', () => {
169
- expect(
170
- substituteUserConfig('${user_config.key}', { key: 'abc$def{ghi}' })
171
- ).toBe('abc$def{ghi}');
172
- });
173
-
174
- it('leaves non-user_config placeholders unchanged', () => {
175
- expect(
176
- substituteUserConfig('${__dirname}/path', { dirname: '/cache' })
177
- ).toBe('${__dirname}/path');
178
- });
179
- });
180
-
181
- describe('substituteEnvVars', () => {
182
- it('substitutes user_config in all env vars', () => {
183
- const env = {
184
- API_KEY: '${user_config.api_key}',
185
- DEBUG: 'true',
186
- TOKEN: '${user_config.token}',
187
- };
188
- const values = { api_key: 'key123', token: 'tok456' };
189
-
190
- expect(substituteEnvVars(env, values)).toEqual({
191
- API_KEY: 'key123',
192
- DEBUG: 'true',
193
- TOKEN: 'tok456',
194
- });
195
- });
196
-
197
- it('handles undefined env', () => {
198
- expect(substituteEnvVars(undefined, { key: 'value' })).toEqual({});
199
- });
200
-
201
- it('handles empty env', () => {
202
- expect(substituteEnvVars({}, { key: 'value' })).toEqual({});
203
- });
204
-
205
- it('preserves env vars without placeholders', () => {
206
- const env = { PATH: '/usr/bin', HOME: '/home/user' };
207
- expect(substituteEnvVars(env, {})).toEqual(env);
208
- });
209
-
210
- it('leaves unsubstituted placeholders as-is', () => {
211
- const env = {
212
- API_KEY: '${user_config.api_key}',
213
- DEBUG: 'true',
214
- };
215
- // api_key not provided, so placeholder remains
216
- // (process.env will override this at merge time)
217
- expect(substituteEnvVars(env, {})).toEqual({
218
- API_KEY: '${user_config.api_key}',
219
- DEBUG: 'true',
220
- });
221
- });
222
- });
223
-
224
- describe('getLocalCacheDir', () => {
225
- const expectedBase = join(homedir(), '.mpak', 'cache', '_local');
226
-
227
- it('returns consistent hash for same path', () => {
228
- const dir1 = getLocalCacheDir('/path/to/bundle.mcpb');
229
- const dir2 = getLocalCacheDir('/path/to/bundle.mcpb');
230
- expect(dir1).toBe(dir2);
231
- });
232
-
233
- it('returns different hash for different paths', () => {
234
- const dir1 = getLocalCacheDir('/path/to/bundle1.mcpb');
235
- const dir2 = getLocalCacheDir('/path/to/bundle2.mcpb');
236
- expect(dir1).not.toBe(dir2);
237
- });
238
-
239
- it('includes _local in path', () => {
240
- const dir = getLocalCacheDir('/path/to/bundle.mcpb');
241
- expect(dir).toContain('_local');
242
- expect(dir.startsWith(expectedBase)).toBe(true);
243
- });
244
-
245
- it('produces a 12-character hash suffix', () => {
246
- const dir = getLocalCacheDir('/path/to/bundle.mcpb');
247
- const hashPart = dir.split('/').pop();
248
- expect(hashPart).toHaveLength(12);
249
- });
250
- });
251
-
252
- describe('localBundleNeedsExtract', () => {
253
- it('returns true when cache directory does not exist', () => {
254
- expect(localBundleNeedsExtract('/any/path.mcpb', '/nonexistent/cache')).toBe(true);
255
- });
256
-
257
- it('returns true when meta file does not exist in cache dir', () => {
258
- // Using a directory that exists but has no .mpak-meta.json
259
- expect(localBundleNeedsExtract('/any/path.mcpb', '/tmp')).toBe(true);
260
- });
261
- });