@ccpluginizer/ccpluginizer 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/dist/index.js ADDED
@@ -0,0 +1,1925 @@
1
+ #!/usr/bin/env bun
2
+ // @bun
3
+ var __defProp = Object.defineProperty;
4
+ var __returnValue = (v) => v;
5
+ function __exportSetter(name, newValue) {
6
+ this[name] = __returnValue.bind(null, newValue);
7
+ }
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, {
11
+ get: all[name],
12
+ enumerable: true,
13
+ configurable: true,
14
+ set: __exportSetter.bind(all, name)
15
+ });
16
+ };
17
+ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
18
+
19
+ // ../../node_modules/.bun/@crustjs+core@0.0.16+7524df1edfed9f02/node_modules/@crustjs/core/dist/shared/chunk-vt64gs69.js
20
+ import { parseArgs as U } from "util";
21
+ function q(B) {
22
+ let J = {}, G = {};
23
+ if (!B)
24
+ return { options: J, aliasToName: G };
25
+ let z = new Map;
26
+ for (let j of Object.keys(B))
27
+ z.set(j, j);
28
+ for (let [j, H] of Object.entries(B)) {
29
+ if (j.startsWith("no-")) {
30
+ let L = j.slice(3);
31
+ throw new W("DEFINITION", `Flag "--${j}" must not use "no-" prefix; define "${L}" and negate with "--no-${L}"`);
32
+ }
33
+ let K = H.type === "boolean" ? "boolean" : "string", Q = { type: K };
34
+ if (H.multiple)
35
+ Q.multiple = true;
36
+ if (H.short) {
37
+ if (H.short.startsWith("no-"))
38
+ throw new W("DEFINITION", `Short alias "-${H.short}" on "--${j}" must not use "no-" prefix (reserved for negation)`);
39
+ let L = z.get(H.short);
40
+ if (L)
41
+ throw new W("DEFINITION", `Alias collision: "-${H.short}" is used by both "--${L}" and "--${j}"`);
42
+ z.set(H.short, j), G[H.short] = j, Q.short = H.short;
43
+ }
44
+ if (H.aliases)
45
+ for (let L of H.aliases) {
46
+ if (L.startsWith("no-"))
47
+ throw new W("DEFINITION", `Alias "--${L}" on "--${j}" must not use "no-" prefix (reserved for negation)`);
48
+ let X = z.get(L);
49
+ if (X)
50
+ throw new W("DEFINITION", `Alias collision: "${L.length === 1 ? "-" : "--"}${L}" is used by both "--${X}" and "--${j}"`);
51
+ z.set(L, j), G[L] = j;
52
+ let $ = { type: K };
53
+ if (H.multiple)
54
+ $.multiple = true;
55
+ J[L] = $;
56
+ }
57
+ J[j] = Q;
58
+ }
59
+ return { options: J, aliasToName: G };
60
+ }
61
+ function _(B, J, G) {
62
+ if (J === "number") {
63
+ let z = Number(B);
64
+ if (Number.isNaN(z))
65
+ throw new W("PARSE", `Expected number for ${G}, got "${B}"`);
66
+ return z;
67
+ }
68
+ if (J === "boolean")
69
+ return B === "true" || B === "1";
70
+ return B;
71
+ }
72
+ function I(B, J, G) {
73
+ let z = `--${B}`;
74
+ if (J.multiple && Array.isArray(G))
75
+ return J.type === "boolean" ? G.filter((j) => typeof j === "boolean") : G.map((j) => _(j, J.type, z));
76
+ if (J.type === "boolean") {
77
+ if (typeof G === "boolean")
78
+ return G;
79
+ throw new W("PARSE", `Expected boolean value for flag "${z}", got ${typeof G}`);
80
+ }
81
+ if (typeof G === "string")
82
+ return _(G, J.type, z);
83
+ if (G === true)
84
+ return J.default ?? undefined;
85
+ return G;
86
+ }
87
+ function M(B, J, G) {
88
+ let z = {};
89
+ for (let j in B) {
90
+ let H = J[j] ?? j;
91
+ if (!(H in G))
92
+ continue;
93
+ let K = B[j], Q = z[H];
94
+ if (Q !== undefined && Array.isArray(Q) && Array.isArray(K))
95
+ Q.push(...K);
96
+ else
97
+ z[H] = K;
98
+ }
99
+ return z;
100
+ }
101
+ function h(B, J, G) {
102
+ if (!B)
103
+ return {};
104
+ let z = M(J, G, B), j = {};
105
+ for (let [H, K] of Object.entries(B)) {
106
+ let Q = z[H];
107
+ if (Q !== undefined) {
108
+ j[H] = I(H, K, Q);
109
+ continue;
110
+ }
111
+ j[H] = K.default ?? undefined;
112
+ }
113
+ return j;
114
+ }
115
+ function O(B, J) {
116
+ if (!B)
117
+ return;
118
+ for (let [G, z] of Object.entries(B))
119
+ if (z.required === true && z.default === undefined) {
120
+ if (J[G] === undefined)
121
+ throw new W("VALIDATION", `Missing required flag "--${G}"`);
122
+ }
123
+ }
124
+ function P(B, J) {
125
+ if (!B)
126
+ return {};
127
+ let G = {}, z = 0;
128
+ for (let j of B) {
129
+ let { name: H } = j;
130
+ if (j.variadic) {
131
+ let K = J.slice(z);
132
+ G[H] = j.type === "string" ? K : K.map((Q) => _(Q, j.type, `<${H}>`)), z = J.length;
133
+ } else if (z < J.length)
134
+ G[H] = _(J[z], j.type, `<${H}>`), z++;
135
+ else
136
+ G[H] = j.default ?? undefined;
137
+ }
138
+ return G;
139
+ }
140
+ function S(B, J, G) {
141
+ if (!J)
142
+ return;
143
+ for (let z of B) {
144
+ if (z === "--")
145
+ return;
146
+ if (!z.startsWith("--no-"))
147
+ continue;
148
+ let j = z.indexOf("="), H = j === -1 ? z.slice(5) : z.slice(5, j);
149
+ if (!H)
150
+ continue;
151
+ let K = G[H];
152
+ if (!K)
153
+ continue;
154
+ if (K === H)
155
+ continue;
156
+ if (J[K]?.type !== "boolean")
157
+ continue;
158
+ throw new W("PARSE", `Cannot negate alias "--no-${H}"; use "--no-${K}" instead`);
159
+ }
160
+ }
161
+ function b(B, J) {
162
+ let { args: G, effectiveFlags: z } = B, { options: j, aliasToName: H } = q(z);
163
+ S(J, z, H);
164
+ let K;
165
+ try {
166
+ K = U({ args: J, options: j, strict: true, allowPositionals: true, allowNegative: true, tokens: true });
167
+ } catch (Y) {
168
+ if (Y instanceof Error) {
169
+ let Z = Y.message.match(/Unknown option '(.+?)'/);
170
+ if (Z)
171
+ throw new W("PARSE", `Unknown flag "${Z[1]}"`).withCause(Y);
172
+ }
173
+ throw new W("PARSE", "Failed to parse command arguments").withCause(Y);
174
+ }
175
+ let Q = [], L = [];
176
+ if (K.tokens) {
177
+ let Y = false;
178
+ for (let Z of K.tokens) {
179
+ if (Z.kind === "option-terminator") {
180
+ Y = true;
181
+ continue;
182
+ }
183
+ if (Z.kind === "positional")
184
+ (Y ? Q : L).push(Z.value ?? "");
185
+ }
186
+ } else
187
+ L.push(...K.positionals);
188
+ let X = h(z, K.values, H);
189
+ return { args: P(G, L), flags: X, rawArgs: Q };
190
+ }
191
+ function E(B, J) {
192
+ let { args: G, effectiveFlags: z } = B, j = J.args, H = J.flags;
193
+ if (G)
194
+ for (let K of G) {
195
+ let { name: Q } = K, L = `argument "<${Q}>"`, X = j[Q];
196
+ if (K.required === true && K.default === undefined) {
197
+ if (K.variadic) {
198
+ if (!Array.isArray(X) || X.length === 0)
199
+ throw new W("VALIDATION", `Missing required ${L}`);
200
+ } else if (X === undefined)
201
+ throw new W("VALIDATION", `Missing required ${L}`);
202
+ }
203
+ }
204
+ O(z, H);
205
+ }
206
+ var W;
207
+ var init_chunk_vt64gs69 = __esm(() => {
208
+ W = class W extends Error {
209
+ code;
210
+ details;
211
+ cause;
212
+ constructor(B, J, ...G) {
213
+ super(J);
214
+ this.name = "CrustError", this.code = B, this.details = G[0];
215
+ }
216
+ is(B) {
217
+ return this.code === B;
218
+ }
219
+ withCause(B) {
220
+ return this.cause = B, this;
221
+ }
222
+ };
223
+ });
224
+
225
+ // ../../node_modules/.bun/@crustjs+core@0.0.16+7524df1edfed9f02/node_modules/@crustjs/core/dist/shared/chunk-5apf3vnv.js
226
+ var exports_chunk_5apf3vnv = {};
227
+ __export(exports_chunk_5apf3vnv, {
228
+ validateCommandTree: () => _2
229
+ });
230
+ function M2(B) {
231
+ switch (B.type) {
232
+ case "number":
233
+ return "1";
234
+ case "boolean":
235
+ return "true";
236
+ default:
237
+ return "sample";
238
+ }
239
+ }
240
+ function X(B) {
241
+ let z = [], K = B.effectiveFlags;
242
+ for (let [j, G] of Object.entries(K)) {
243
+ if (G.required !== true || G.default !== undefined)
244
+ continue;
245
+ if (z.push(`--${j}`), G.type !== "boolean")
246
+ z.push(M2(G));
247
+ }
248
+ let J = B.args;
249
+ if (J)
250
+ for (let j of J) {
251
+ if (j.required !== true || j.default !== undefined)
252
+ continue;
253
+ z.push(M2(j));
254
+ }
255
+ return z;
256
+ }
257
+ function _2(B) {
258
+ let z = [{ command: B, path: [B.meta.name] }], K = new Set;
259
+ while (z.length > 0) {
260
+ let J = z.pop();
261
+ if (!J)
262
+ break;
263
+ let { command: j, path: G } = J;
264
+ if (K.has(j))
265
+ continue;
266
+ K.add(j);
267
+ try {
268
+ let H = b(j, X(j));
269
+ E(j, H);
270
+ } catch (H) {
271
+ let L = H instanceof Error ? H.message : "Unknown validation error";
272
+ throw new W("DEFINITION", `Command "${G.join(" ")}" failed runtime validation: ${L}`).withCause(H);
273
+ }
274
+ for (let [H, L] of Object.entries(j.subCommands))
275
+ z.push({ command: L, path: [...G, H] });
276
+ }
277
+ }
278
+ var init_chunk_5apf3vnv = __esm(() => {
279
+ init_chunk_vt64gs69();
280
+ });
281
+
282
+ // ../../node_modules/.bun/@crustjs+core@0.0.16+7524df1edfed9f02/node_modules/@crustjs/core/dist/index.js
283
+ init_chunk_vt64gs69();
284
+ function T(j) {
285
+ return { meta: { name: j }, localFlags: {}, effectiveFlags: {}, args: undefined, subCommands: {}, plugins: [], preRun: undefined, run: undefined, postRun: undefined };
286
+ }
287
+ function z(j, q2) {
288
+ let J = {};
289
+ for (let [Q, $] of Object.entries(j))
290
+ if ($.inherit === true)
291
+ J[Q] = $;
292
+ for (let [Q, $] of Object.entries(q2))
293
+ J[Q] = $;
294
+ return J;
295
+ }
296
+ function D(j, q2) {
297
+ let J = [j.meta.name], Q = j, $ = q2;
298
+ while ($.length > 0) {
299
+ let K = Q.subCommands;
300
+ if (!K || Object.keys(K).length === 0)
301
+ break;
302
+ let Z = $[0];
303
+ if (!Z || Z.startsWith("-"))
304
+ break;
305
+ if (Z in K && K[Z]) {
306
+ Q = K[Z], J.push(Z), $ = $.slice(1);
307
+ continue;
308
+ }
309
+ if (Q.run)
310
+ break;
311
+ let H = Object.keys(K);
312
+ throw new W("COMMAND_NOT_FOUND", `Unknown command "${Z}".`, { input: Z, available: H, commandPath: [...J], parentCommand: Q });
313
+ }
314
+ return { command: Q, argv: $, commandPath: J };
315
+ }
316
+ function N(j) {
317
+ for (let [q2, J] of Object.entries(j)) {
318
+ if (q2.startsWith("no-")) {
319
+ let Q = q2.slice(3);
320
+ throw new W("DEFINITION", `Flag "--${q2}" must not use "no-" prefix; define "${Q}" and negate with "--no-${Q}"`);
321
+ }
322
+ if (J.short?.startsWith("no-"))
323
+ throw new W("DEFINITION", `Short alias "-${J.short}" on "--${q2}" must not use "no-" prefix (reserved for negation)`);
324
+ if (J.aliases) {
325
+ for (let Q of J.aliases)
326
+ if (Q.startsWith("no-"))
327
+ throw new W("DEFINITION", `Alias "--${Q}" on "--${q2}" must not use "no-" prefix (reserved for negation)`);
328
+ }
329
+ }
330
+ }
331
+ var w = "CRUST_INTERNAL_VALIDATE_ONLY";
332
+ var P2 = 130;
333
+ var v = "__CRUST_VALIDATE_RESULT__";
334
+ function x() {
335
+ let j = new Map;
336
+ return { get(q2) {
337
+ return j.get(q2);
338
+ }, has(q2) {
339
+ return j.has(q2);
340
+ }, set(q2, J) {
341
+ j.set(q2, J);
342
+ }, delete(q2) {
343
+ return j.delete(q2);
344
+ } };
345
+ }
346
+ function B(j) {
347
+ if (!(j instanceof Error))
348
+ return false;
349
+ return j.name === "CancelledError";
350
+ }
351
+ function b2(j, q2) {
352
+ j.effectiveFlags = z(q2, j.localFlags);
353
+ for (let J of Object.values(j.subCommands))
354
+ b2(J, j.effectiveFlags);
355
+ }
356
+ function y(j) {
357
+ return { addFlag(q2, J, Q) {
358
+ if (J in q2.effectiveFlags)
359
+ j?.push(`Plugin flag "--${J}" on "${q2.meta.name}" overrides existing flag`);
360
+ q2.effectiveFlags[J] = Q;
361
+ }, addSubCommand(q2, J, Q) {
362
+ if (!J.trim())
363
+ throw new W("DEFINITION", "addSubCommand: name must be a non-empty string");
364
+ if (q2.subCommands[J]) {
365
+ j?.push(`Plugin subcommand "${J}" on "${q2.meta.name}" skipped (already exists)`);
366
+ return;
367
+ }
368
+ b2(Q, q2.effectiveFlags), q2.subCommands[J] = Q;
369
+ } };
370
+ }
371
+ async function A2(j, q2, J) {
372
+ for (let Q of j) {
373
+ if (!Q.setup)
374
+ continue;
375
+ await Q.setup(q2, J);
376
+ }
377
+ }
378
+ async function F(j, q2, J) {
379
+ let Q = j.map((Z) => Z.middleware).filter((Z) => Boolean(Z)), $ = -1, K = async (Z) => {
380
+ if (Z <= $)
381
+ throw new W("DEFINITION", "Plugin middleware called next() multiple times");
382
+ if ($ = Z, Z === Q.length) {
383
+ await J();
384
+ return;
385
+ }
386
+ let H = Q[Z];
387
+ if (!H)
388
+ throw new W("DEFINITION", "Plugin middleware stack is invalid");
389
+ await H(q2, () => K(Z + 1));
390
+ };
391
+ await K(0);
392
+ }
393
+ function I2(j) {
394
+ let q2 = [...j.plugins];
395
+ for (let J of Object.values(j.subCommands))
396
+ q2.push(...I2(J));
397
+ return q2;
398
+ }
399
+ function k(j) {
400
+ let q2 = {};
401
+ for (let [J, Q] of Object.entries(j))
402
+ q2[J] = { ...Q, aliases: Q.aliases ? [...Q.aliases] : undefined };
403
+ return q2;
404
+ }
405
+ function h2(j) {
406
+ let q2 = {};
407
+ for (let [J, Q] of Object.entries(j.subCommands))
408
+ q2[J] = h2(Q);
409
+ return { meta: { ...j.meta }, localFlags: k(j.localFlags), effectiveFlags: k(j.effectiveFlags), args: j.args ? j.args.map((J) => ({ ...J })) : undefined, subCommands: q2, plugins: [...j.plugins], preRun: j.preRun, run: j.run, postRun: j.postRun };
410
+ }
411
+ function _3(j) {
412
+ if (Object.freeze(j), Object.freeze(j.localFlags), Object.freeze(j.effectiveFlags), Object.freeze(j.meta), Object.freeze(j.plugins), j.args)
413
+ Object.freeze(j.args);
414
+ for (let q2 of Object.values(j.subCommands))
415
+ _3(q2);
416
+ Object.freeze(j.subCommands);
417
+ }
418
+
419
+ class R {
420
+ _node;
421
+ _inheritedFlags;
422
+ constructor(j) {
423
+ if (!j.trim())
424
+ throw new W("DEFINITION", "meta.name must be a non-empty string");
425
+ this._node = T(j), this._inheritedFlags = {};
426
+ }
427
+ static _createChild(j, q2) {
428
+ let J = new R(j);
429
+ return J._inheritedFlags = q2, J;
430
+ }
431
+ _clone(j) {
432
+ let q2 = Object.create(Object.getPrototypeOf(this)), J = { ...this._node, localFlags: { ...this._node.localFlags }, effectiveFlags: { ...this._node.effectiveFlags }, subCommands: { ...this._node.subCommands }, plugins: [...this._node.plugins], meta: { ...this._node.meta }, args: this._node.args ? [...this._node.args] : undefined, ...j };
433
+ return q2._node = J, q2._inheritedFlags = this._inheritedFlags, q2;
434
+ }
435
+ meta(j) {
436
+ return this._clone({ meta: { ...this._node.meta, ...j } });
437
+ }
438
+ flags(j) {
439
+ N(j);
440
+ let q2 = {};
441
+ for (let [J, Q] of Object.entries(j))
442
+ q2[J] = { ...Q };
443
+ return this._clone({ localFlags: q2, effectiveFlags: z(this._inheritedFlags, q2) });
444
+ }
445
+ args(j) {
446
+ let q2 = j.map((J) => ({ ...J }));
447
+ return this._clone({ args: q2 });
448
+ }
449
+ run(j) {
450
+ return this._clone({ run: j });
451
+ }
452
+ preRun(j) {
453
+ return this._clone({ preRun: j });
454
+ }
455
+ postRun(j) {
456
+ return this._clone({ postRun: j });
457
+ }
458
+ use(j) {
459
+ return this._clone({ plugins: [...this._node.plugins, j] });
460
+ }
461
+ sub(j) {
462
+ if (!j.trim())
463
+ throw new W("DEFINITION", "Subcommand name must be a non-empty string");
464
+ let q2 = z(this._inheritedFlags, this._node.localFlags);
465
+ return R._createChild(j, q2);
466
+ }
467
+ command(j, q2) {
468
+ if (typeof j === "string") {
469
+ let K = j;
470
+ if (!q2)
471
+ throw new W("DEFINITION", "command(name, cb) requires a callback");
472
+ if (!K.trim())
473
+ throw new W("DEFINITION", "Subcommand name must be a non-empty string");
474
+ if (this._node.subCommands[K])
475
+ throw new W("DEFINITION", `Subcommand "${K}" is already registered`);
476
+ let Z = z(this._inheritedFlags, this._node.localFlags), H = R._createChild(K, Z), X2 = q2(H), W2 = { ...X2._node, effectiveFlags: z(X2._inheritedFlags, X2._node.localFlags) };
477
+ return this._clone({ subCommands: { ...this._node.subCommands, [K]: W2 } });
478
+ }
479
+ let J = j, Q = J._node.meta.name;
480
+ if (!Q.trim())
481
+ throw new W("DEFINITION", "Subcommand name must be a non-empty string");
482
+ if (this._node.subCommands[Q])
483
+ throw new W("DEFINITION", `Subcommand "${Q}" is already registered`);
484
+ let $ = { ...J._node, effectiveFlags: z(J._inheritedFlags, J._node.localFlags) };
485
+ return this._clone({ subCommands: { ...this._node.subCommands, [Q]: $ } });
486
+ }
487
+ async prepareCommandTree(j) {
488
+ let q2 = j?.argv ?? [], J = h2(this._node), Q = I2(J), $ = [], K = x(), Z = { argv: [...q2], rootCommand: J, state: K }, H = y($);
489
+ try {
490
+ await A2(Q, Z, H);
491
+ } catch (W2) {
492
+ if (B(W2))
493
+ throw W2;
494
+ if (W2 instanceof W)
495
+ throw W2;
496
+ if (W2 instanceof Error)
497
+ throw W2;
498
+ throw new W("DEFINITION", String(W2));
499
+ }
500
+ _3(J);
501
+ let { validateCommandTree: X2 } = await Promise.resolve().then(() => (init_chunk_5apf3vnv(), exports_chunk_5apf3vnv));
502
+ return X2(J), { root: J, warnings: $ };
503
+ }
504
+ async execute(j) {
505
+ let q2 = j?.argv ?? process.argv.slice(2), J = this._node, Q = I2(J), $ = [], K = x(), Z = { argv: [...q2], rootCommand: J, state: K }, H = y($);
506
+ try {
507
+ await A2(Q, Z, H);
508
+ } catch (W2) {
509
+ if (B(W2)) {
510
+ process.exitCode = P2;
511
+ return;
512
+ }
513
+ if (W2 instanceof W) {
514
+ console.error(`Error: ${W2.message}`), process.exitCode = 1;
515
+ return;
516
+ }
517
+ let U2 = W2 instanceof Error ? W2.message : String(W2);
518
+ console.error(`Error: ${U2}`), process.exitCode = 1;
519
+ return;
520
+ }
521
+ if (_3(J), process.env[w] === "1") {
522
+ let W2 = (async () => {
523
+ try {
524
+ let { validateCommandTree: U2 } = await Promise.resolve().then(() => (init_chunk_5apf3vnv(), exports_chunk_5apf3vnv));
525
+ U2(J);
526
+ for (let Y of $)
527
+ console.warn(`Warning: ${Y}`);
528
+ return { ok: true };
529
+ } catch (U2) {
530
+ let Y = U2 instanceof Error ? U2.message : String(U2);
531
+ return console.error(Y), process.exitCode = 1, { ok: false, error: U2 };
532
+ }
533
+ })();
534
+ return globalThis[v] = W2, await W2, process.exit(process.exitCode ?? 0);
535
+ }
536
+ for (let W2 of $)
537
+ console.warn(`Warning: ${W2}`);
538
+ let X2 = { argv: [...q2], rootCommand: J, state: K, route: null, input: null };
539
+ try {
540
+ let W2, U2;
541
+ try {
542
+ let Y = D(J, [...q2]);
543
+ X2.route = Y, W2 = Y.command, U2 = b(W2, Y.argv), X2.input = U2;
544
+ } catch (Y) {
545
+ await F(Q, X2, async () => {
546
+ throw Y;
547
+ });
548
+ return;
549
+ }
550
+ await F(Q, X2, async () => {
551
+ if (E(W2, U2), !W2.run)
552
+ return;
553
+ let Y = { args: U2.args, flags: U2.flags, rawArgs: U2.rawArgs, command: W2 }, V;
554
+ try {
555
+ if (W2.preRun)
556
+ await W2.preRun(Y);
557
+ await W2.run(Y);
558
+ } catch (M3) {
559
+ V = M3;
560
+ }
561
+ if (W2.postRun)
562
+ try {
563
+ await W2.postRun(Y);
564
+ } catch (M3) {
565
+ if (!V)
566
+ V = M3;
567
+ else
568
+ console.error(`Error in postRun: ${M3 instanceof Error ? M3.message : String(M3)}`);
569
+ }
570
+ if (V)
571
+ throw V;
572
+ });
573
+ } catch (W2) {
574
+ if (B(W2)) {
575
+ process.exitCode = P2;
576
+ return;
577
+ }
578
+ if (W2 instanceof W) {
579
+ console.error(`Error: ${W2.message}`), process.exitCode = 1;
580
+ return;
581
+ }
582
+ if (W2 instanceof Error) {
583
+ let U2 = new W("EXECUTION", W2.message).withCause(W2);
584
+ console.error(`Error: ${U2.message}`), process.exitCode = 1;
585
+ return;
586
+ }
587
+ console.error(`Error: ${String(W2)}`), process.exitCode = 1;
588
+ }
589
+ }
590
+ }
591
+
592
+ // src/commands/scan.ts
593
+ import { writeFileSync } from "fs";
594
+
595
+ // src/sources/github.ts
596
+ import { mkdtempSync } from "fs";
597
+ import { tmpdir } from "os";
598
+ import { join } from "path";
599
+
600
+ // src/errors.ts
601
+ class CcpluginizerError extends Error {
602
+ name = "CcpluginizerError";
603
+ }
604
+
605
+ class AlreadyMarketplaceError extends CcpluginizerError {
606
+ repoPath;
607
+ name = "AlreadyMarketplaceError";
608
+ constructor(repoPath) {
609
+ super("This repo is already a marketplace; install via `/plugin marketplace add <repo>` directly. ccpluginizer is for non-plugin repos only.");
610
+ this.repoPath = repoPath;
611
+ }
612
+ }
613
+
614
+ class MarkerFileError extends CcpluginizerError {
615
+ issues;
616
+ name = "MarkerFileError";
617
+ constructor(message, issues) {
618
+ super(message);
619
+ this.issues = issues;
620
+ }
621
+ }
622
+
623
+ class PathNormalizationError extends CcpluginizerError {
624
+ invalidPath;
625
+ name = "PathNormalizationError";
626
+ constructor(invalidPath, reason) {
627
+ super(`Path "${invalidPath}" is invalid: ${reason}`);
628
+ this.invalidPath = invalidPath;
629
+ }
630
+ }
631
+
632
+ class SourceCloneError extends CcpluginizerError {
633
+ source;
634
+ name = "SourceCloneError";
635
+ constructor(source, cause) {
636
+ super(`Failed to fetch source "${source}": ${cause}`);
637
+ this.source = source;
638
+ }
639
+ }
640
+
641
+ // src/sources/github.ts
642
+ async function resolveGithub(repo) {
643
+ const dest = mkdtempSync(join(tmpdir(), `ccp-${repo.replace("/", "-")}-`));
644
+ const url = `https://github.com/${repo}.git`;
645
+ const proc = Bun.spawn(["git", "clone", "--depth=1", url, dest], {
646
+ stdout: "pipe",
647
+ stderr: "pipe"
648
+ });
649
+ const exitCode = await proc.exited;
650
+ if (exitCode !== 0) {
651
+ const stderr = await new Response(proc.stderr).text();
652
+ throw new SourceCloneError(repo, stderr);
653
+ }
654
+ return dest;
655
+ }
656
+
657
+ // src/sources/index.ts
658
+ function parseSourceInput(input) {
659
+ const trimmed = input.trim();
660
+ if (trimmed.startsWith("/") || trimmed.startsWith("./") || trimmed.startsWith("../")) {
661
+ return { kind: "local", path: trimmed };
662
+ }
663
+ const httpsMatch = /^https:\/\/github\.com\/([^/]+\/[^/]+?)(?:\.git)?\/?$/.exec(trimmed);
664
+ if (httpsMatch?.[1] !== undefined) {
665
+ return { kind: "github", repo: httpsMatch[1] };
666
+ }
667
+ const sshMatch = /^git@github\.com:([^/]+\/[^/]+?)(?:\.git)?$/.exec(trimmed);
668
+ if (sshMatch?.[1] !== undefined) {
669
+ return { kind: "github", repo: sshMatch[1] };
670
+ }
671
+ if (/^[\w.-]+\/[\w.-]+$/.test(trimmed)) {
672
+ return { kind: "github", repo: trimmed };
673
+ }
674
+ throw new Error(`Cannot parse source input: ${trimmed}`);
675
+ }
676
+ function inferSourceRepo(input) {
677
+ const parsed = parseSourceInput(input);
678
+ if (parsed.kind === "github") {
679
+ return parsed.repo;
680
+ }
681
+ const basename = parsed.path.split("/").filter(Boolean).pop() ?? "unknown";
682
+ return `local/${basename}`;
683
+ }
684
+ async function resolveSource(input) {
685
+ const parsed = parseSourceInput(input);
686
+ if (parsed.kind === "local") {
687
+ return parsed.path;
688
+ }
689
+ return resolveGithub(parsed.repo);
690
+ }
691
+
692
+ // src/detector/marketplaceGuard.ts
693
+ import { existsSync } from "fs";
694
+ import { join as join2 } from "path";
695
+ function checkMarketplaceGuard(repoRoot) {
696
+ const marketplaceFile = join2(repoRoot, ".claude-plugin", "marketplace.json");
697
+ if (existsSync(marketplaceFile)) {
698
+ throw new AlreadyMarketplaceError(repoRoot);
699
+ }
700
+ }
701
+
702
+ // src/detector/markerFile.ts
703
+ import { existsSync as existsSync2, readFileSync } from "fs";
704
+ import { join as join3 } from "path";
705
+
706
+ // ../../node_modules/.bun/valibot@1.3.1+7524df1edfed9f02/node_modules/valibot/dist/index.mjs
707
+ var store$4;
708
+ function getGlobalConfig(config$1) {
709
+ return {
710
+ lang: config$1?.lang ?? store$4?.lang,
711
+ message: config$1?.message,
712
+ abortEarly: config$1?.abortEarly ?? store$4?.abortEarly,
713
+ abortPipeEarly: config$1?.abortPipeEarly ?? store$4?.abortPipeEarly
714
+ };
715
+ }
716
+ var store$3;
717
+ function getGlobalMessage(lang) {
718
+ return store$3?.get(lang);
719
+ }
720
+ var store$2;
721
+ function getSchemaMessage(lang) {
722
+ return store$2?.get(lang);
723
+ }
724
+ var store$1;
725
+ function getSpecificMessage(reference, lang) {
726
+ return store$1?.get(reference)?.get(lang);
727
+ }
728
+ function _stringify(input) {
729
+ const type = typeof input;
730
+ if (type === "string")
731
+ return `"${input}"`;
732
+ if (type === "number" || type === "bigint" || type === "boolean")
733
+ return `${input}`;
734
+ if (type === "object" || type === "function")
735
+ return (input && Object.getPrototypeOf(input)?.constructor?.name) ?? "null";
736
+ return type;
737
+ }
738
+ function _addIssue(context, label, dataset, config$1, other) {
739
+ const input = other && "input" in other ? other.input : dataset.value;
740
+ const expected = other?.expected ?? context.expects ?? null;
741
+ const received = other?.received ?? /* @__PURE__ */ _stringify(input);
742
+ const issue = {
743
+ kind: context.kind,
744
+ type: context.type,
745
+ input,
746
+ expected,
747
+ received,
748
+ message: `Invalid ${label}: ${expected ? `Expected ${expected} but r` : "R"}eceived ${received}`,
749
+ requirement: context.requirement,
750
+ path: other?.path,
751
+ issues: other?.issues,
752
+ lang: config$1.lang,
753
+ abortEarly: config$1.abortEarly,
754
+ abortPipeEarly: config$1.abortPipeEarly
755
+ };
756
+ const isSchema = context.kind === "schema";
757
+ const message$1 = other?.message ?? context.message ?? /* @__PURE__ */ getSpecificMessage(context.reference, issue.lang) ?? (isSchema ? /* @__PURE__ */ getSchemaMessage(issue.lang) : null) ?? config$1.message ?? /* @__PURE__ */ getGlobalMessage(issue.lang);
758
+ if (message$1 !== undefined)
759
+ issue.message = typeof message$1 === "function" ? message$1(issue) : message$1;
760
+ if (isSchema)
761
+ dataset.typed = false;
762
+ if (dataset.issues)
763
+ dataset.issues.push(issue);
764
+ else
765
+ dataset.issues = [issue];
766
+ }
767
+ function _getStandardProps(context) {
768
+ return {
769
+ version: 1,
770
+ vendor: "valibot",
771
+ validate(value$1) {
772
+ return context["~run"]({ value: value$1 }, /* @__PURE__ */ getGlobalConfig());
773
+ }
774
+ };
775
+ }
776
+ function _isValidObjectKey(object$1, key) {
777
+ return Object.hasOwn(object$1, key) && key !== "__proto__" && key !== "prototype" && key !== "constructor";
778
+ }
779
+ function _joinExpects(values$1, separator) {
780
+ const list = [...new Set(values$1)];
781
+ if (list.length > 1)
782
+ return `(${list.join(` ${separator} `)})`;
783
+ return list[0] ?? "never";
784
+ }
785
+ function regex(requirement, message$1) {
786
+ return {
787
+ kind: "validation",
788
+ type: "regex",
789
+ reference: regex,
790
+ async: false,
791
+ expects: `${requirement}`,
792
+ requirement,
793
+ message: message$1,
794
+ "~run"(dataset, config$1) {
795
+ if (dataset.typed && !this.requirement.test(dataset.value))
796
+ _addIssue(this, "format", dataset, config$1);
797
+ return dataset;
798
+ }
799
+ };
800
+ }
801
+ function startsWith(requirement, message$1) {
802
+ return {
803
+ kind: "validation",
804
+ type: "starts_with",
805
+ reference: startsWith,
806
+ async: false,
807
+ expects: `"${requirement}"`,
808
+ requirement,
809
+ message: message$1,
810
+ "~run"(dataset, config$1) {
811
+ if (dataset.typed && !dataset.value.startsWith(this.requirement))
812
+ _addIssue(this, "start", dataset, config$1, { received: `"${dataset.value.slice(0, this.requirement.length)}"` });
813
+ return dataset;
814
+ }
815
+ };
816
+ }
817
+ var _LruCache = class {
818
+ constructor(config$1) {
819
+ this.refCount = 0;
820
+ this.maxSize = config$1?.maxSize ?? 1000;
821
+ this.maxAge = config$1?.maxAge ?? Infinity;
822
+ this.hasMaxAge = isFinite(this.maxAge);
823
+ }
824
+ #stringify(input) {
825
+ const type = typeof input;
826
+ if (type === "string")
827
+ return `"${input}"`;
828
+ if (type === "number" || type === "boolean")
829
+ return `${input}`;
830
+ if (type === "bigint")
831
+ return `${input}n`;
832
+ if (type === "object" || type === "function") {
833
+ if (input) {
834
+ this.refIds ??= /* @__PURE__ */ new WeakMap;
835
+ let id = this.refIds.get(input);
836
+ if (!id) {
837
+ id = ++this.refCount;
838
+ this.refIds.set(input, id);
839
+ }
840
+ return `#${id}`;
841
+ }
842
+ return "null";
843
+ }
844
+ return type;
845
+ }
846
+ key(input, config$1 = {}) {
847
+ return `${this.#stringify(input)}|${this.#stringify(config$1.lang)}|${this.#stringify(config$1.message)}|${this.#stringify(config$1.abortEarly)}|${this.#stringify(config$1.abortPipeEarly)}`;
848
+ }
849
+ get(key) {
850
+ if (!this.store)
851
+ return;
852
+ const entry = this.store.get(key);
853
+ if (!entry)
854
+ return;
855
+ if (this.hasMaxAge && Date.now() - entry[1] > this.maxAge) {
856
+ this.store.delete(key);
857
+ return;
858
+ }
859
+ this.store.delete(key);
860
+ this.store.set(key, entry);
861
+ return entry[0];
862
+ }
863
+ set(key, value$1) {
864
+ this.store ??= /* @__PURE__ */ new Map;
865
+ this.store.delete(key);
866
+ const timestamp = this.hasMaxAge ? Date.now() : 0;
867
+ this.store.set(key, [value$1, timestamp]);
868
+ if (this.store.size > this.maxSize)
869
+ this.store.delete(this.store.keys().next().value);
870
+ }
871
+ clear() {
872
+ this.store?.clear();
873
+ }
874
+ };
875
+ function getFallback(schema, dataset, config$1) {
876
+ return typeof schema.fallback === "function" ? schema.fallback(dataset, config$1) : schema.fallback;
877
+ }
878
+ function getDefault(schema, dataset, config$1) {
879
+ return typeof schema.default === "function" ? schema.default(dataset, config$1) : schema.default;
880
+ }
881
+ function array(item, message$1) {
882
+ return {
883
+ kind: "schema",
884
+ type: "array",
885
+ reference: array,
886
+ expects: "Array",
887
+ async: false,
888
+ item,
889
+ message: message$1,
890
+ get "~standard"() {
891
+ return /* @__PURE__ */ _getStandardProps(this);
892
+ },
893
+ "~run"(dataset, config$1) {
894
+ const input = dataset.value;
895
+ if (Array.isArray(input)) {
896
+ dataset.typed = true;
897
+ dataset.value = [];
898
+ for (let key = 0;key < input.length; key++) {
899
+ const value$1 = input[key];
900
+ const itemDataset = this.item["~run"]({ value: value$1 }, config$1);
901
+ if (itemDataset.issues) {
902
+ const pathItem = {
903
+ type: "array",
904
+ origin: "value",
905
+ input,
906
+ key,
907
+ value: value$1
908
+ };
909
+ for (const issue of itemDataset.issues) {
910
+ if (issue.path)
911
+ issue.path.unshift(pathItem);
912
+ else
913
+ issue.path = [pathItem];
914
+ dataset.issues?.push(issue);
915
+ }
916
+ if (!dataset.issues)
917
+ dataset.issues = itemDataset.issues;
918
+ if (config$1.abortEarly) {
919
+ dataset.typed = false;
920
+ break;
921
+ }
922
+ }
923
+ if (!itemDataset.typed)
924
+ dataset.typed = false;
925
+ dataset.value.push(itemDataset.value);
926
+ }
927
+ } else
928
+ _addIssue(this, "type", dataset, config$1);
929
+ return dataset;
930
+ }
931
+ };
932
+ }
933
+ function boolean(message$1) {
934
+ return {
935
+ kind: "schema",
936
+ type: "boolean",
937
+ reference: boolean,
938
+ expects: "boolean",
939
+ async: false,
940
+ message: message$1,
941
+ get "~standard"() {
942
+ return /* @__PURE__ */ _getStandardProps(this);
943
+ },
944
+ "~run"(dataset, config$1) {
945
+ if (typeof dataset.value === "boolean")
946
+ dataset.typed = true;
947
+ else
948
+ _addIssue(this, "type", dataset, config$1);
949
+ return dataset;
950
+ }
951
+ };
952
+ }
953
+ function literal(literal_, message$1) {
954
+ return {
955
+ kind: "schema",
956
+ type: "literal",
957
+ reference: literal,
958
+ expects: /* @__PURE__ */ _stringify(literal_),
959
+ async: false,
960
+ literal: literal_,
961
+ message: message$1,
962
+ get "~standard"() {
963
+ return /* @__PURE__ */ _getStandardProps(this);
964
+ },
965
+ "~run"(dataset, config$1) {
966
+ if (dataset.value === this.literal)
967
+ dataset.typed = true;
968
+ else
969
+ _addIssue(this, "type", dataset, config$1);
970
+ return dataset;
971
+ }
972
+ };
973
+ }
974
+ function number(message$1) {
975
+ return {
976
+ kind: "schema",
977
+ type: "number",
978
+ reference: number,
979
+ expects: "number",
980
+ async: false,
981
+ message: message$1,
982
+ get "~standard"() {
983
+ return /* @__PURE__ */ _getStandardProps(this);
984
+ },
985
+ "~run"(dataset, config$1) {
986
+ if (typeof dataset.value === "number" && !isNaN(dataset.value))
987
+ dataset.typed = true;
988
+ else
989
+ _addIssue(this, "type", dataset, config$1);
990
+ return dataset;
991
+ }
992
+ };
993
+ }
994
+ function object(entries$1, message$1) {
995
+ return {
996
+ kind: "schema",
997
+ type: "object",
998
+ reference: object,
999
+ expects: "Object",
1000
+ async: false,
1001
+ entries: entries$1,
1002
+ message: message$1,
1003
+ get "~standard"() {
1004
+ return /* @__PURE__ */ _getStandardProps(this);
1005
+ },
1006
+ "~run"(dataset, config$1) {
1007
+ const input = dataset.value;
1008
+ if (input && typeof input === "object") {
1009
+ dataset.typed = true;
1010
+ dataset.value = {};
1011
+ for (const key in this.entries) {
1012
+ const valueSchema = this.entries[key];
1013
+ if (key in input || (valueSchema.type === "exact_optional" || valueSchema.type === "optional" || valueSchema.type === "nullish") && valueSchema.default !== undefined) {
1014
+ const value$1 = key in input ? input[key] : /* @__PURE__ */ getDefault(valueSchema);
1015
+ const valueDataset = valueSchema["~run"]({ value: value$1 }, config$1);
1016
+ if (valueDataset.issues) {
1017
+ const pathItem = {
1018
+ type: "object",
1019
+ origin: "value",
1020
+ input,
1021
+ key,
1022
+ value: value$1
1023
+ };
1024
+ for (const issue of valueDataset.issues) {
1025
+ if (issue.path)
1026
+ issue.path.unshift(pathItem);
1027
+ else
1028
+ issue.path = [pathItem];
1029
+ dataset.issues?.push(issue);
1030
+ }
1031
+ if (!dataset.issues)
1032
+ dataset.issues = valueDataset.issues;
1033
+ if (config$1.abortEarly) {
1034
+ dataset.typed = false;
1035
+ break;
1036
+ }
1037
+ }
1038
+ if (!valueDataset.typed)
1039
+ dataset.typed = false;
1040
+ dataset.value[key] = valueDataset.value;
1041
+ } else if (valueSchema.fallback !== undefined)
1042
+ dataset.value[key] = /* @__PURE__ */ getFallback(valueSchema);
1043
+ else if (valueSchema.type !== "exact_optional" && valueSchema.type !== "optional" && valueSchema.type !== "nullish") {
1044
+ _addIssue(this, "key", dataset, config$1, {
1045
+ input: undefined,
1046
+ expected: `"${key}"`,
1047
+ path: [{
1048
+ type: "object",
1049
+ origin: "key",
1050
+ input,
1051
+ key,
1052
+ value: input[key]
1053
+ }]
1054
+ });
1055
+ if (config$1.abortEarly)
1056
+ break;
1057
+ }
1058
+ }
1059
+ } else
1060
+ _addIssue(this, "type", dataset, config$1);
1061
+ return dataset;
1062
+ }
1063
+ };
1064
+ }
1065
+ function optional(wrapped, default_) {
1066
+ return {
1067
+ kind: "schema",
1068
+ type: "optional",
1069
+ reference: optional,
1070
+ expects: `(${wrapped.expects} | undefined)`,
1071
+ async: false,
1072
+ wrapped,
1073
+ default: default_,
1074
+ get "~standard"() {
1075
+ return /* @__PURE__ */ _getStandardProps(this);
1076
+ },
1077
+ "~run"(dataset, config$1) {
1078
+ if (dataset.value === undefined) {
1079
+ if (this.default !== undefined)
1080
+ dataset.value = /* @__PURE__ */ getDefault(this, dataset, config$1);
1081
+ if (dataset.value === undefined) {
1082
+ dataset.typed = true;
1083
+ return dataset;
1084
+ }
1085
+ }
1086
+ return this.wrapped["~run"](dataset, config$1);
1087
+ }
1088
+ };
1089
+ }
1090
+ function record(key, value$1, message$1) {
1091
+ return {
1092
+ kind: "schema",
1093
+ type: "record",
1094
+ reference: record,
1095
+ expects: "Object",
1096
+ async: false,
1097
+ key,
1098
+ value: value$1,
1099
+ message: message$1,
1100
+ get "~standard"() {
1101
+ return /* @__PURE__ */ _getStandardProps(this);
1102
+ },
1103
+ "~run"(dataset, config$1) {
1104
+ const input = dataset.value;
1105
+ if (input && typeof input === "object") {
1106
+ dataset.typed = true;
1107
+ dataset.value = {};
1108
+ for (const entryKey in input)
1109
+ if (/* @__PURE__ */ _isValidObjectKey(input, entryKey)) {
1110
+ const entryValue = input[entryKey];
1111
+ const keyDataset = this.key["~run"]({ value: entryKey }, config$1);
1112
+ if (keyDataset.issues) {
1113
+ const pathItem = {
1114
+ type: "object",
1115
+ origin: "key",
1116
+ input,
1117
+ key: entryKey,
1118
+ value: entryValue
1119
+ };
1120
+ for (const issue of keyDataset.issues) {
1121
+ issue.path = [pathItem];
1122
+ dataset.issues?.push(issue);
1123
+ }
1124
+ if (!dataset.issues)
1125
+ dataset.issues = keyDataset.issues;
1126
+ if (config$1.abortEarly) {
1127
+ dataset.typed = false;
1128
+ break;
1129
+ }
1130
+ }
1131
+ const valueDataset = this.value["~run"]({ value: entryValue }, config$1);
1132
+ if (valueDataset.issues) {
1133
+ const pathItem = {
1134
+ type: "object",
1135
+ origin: "value",
1136
+ input,
1137
+ key: entryKey,
1138
+ value: entryValue
1139
+ };
1140
+ for (const issue of valueDataset.issues) {
1141
+ if (issue.path)
1142
+ issue.path.unshift(pathItem);
1143
+ else
1144
+ issue.path = [pathItem];
1145
+ dataset.issues?.push(issue);
1146
+ }
1147
+ if (!dataset.issues)
1148
+ dataset.issues = valueDataset.issues;
1149
+ if (config$1.abortEarly) {
1150
+ dataset.typed = false;
1151
+ break;
1152
+ }
1153
+ }
1154
+ if (!keyDataset.typed || !valueDataset.typed)
1155
+ dataset.typed = false;
1156
+ if (keyDataset.typed)
1157
+ dataset.value[keyDataset.value] = valueDataset.value;
1158
+ }
1159
+ } else
1160
+ _addIssue(this, "type", dataset, config$1);
1161
+ return dataset;
1162
+ }
1163
+ };
1164
+ }
1165
+ function strictObject(entries$1, message$1) {
1166
+ return {
1167
+ kind: "schema",
1168
+ type: "strict_object",
1169
+ reference: strictObject,
1170
+ expects: "Object",
1171
+ async: false,
1172
+ entries: entries$1,
1173
+ message: message$1,
1174
+ get "~standard"() {
1175
+ return /* @__PURE__ */ _getStandardProps(this);
1176
+ },
1177
+ "~run"(dataset, config$1) {
1178
+ const input = dataset.value;
1179
+ if (input && typeof input === "object") {
1180
+ dataset.typed = true;
1181
+ dataset.value = {};
1182
+ for (const key in this.entries) {
1183
+ const valueSchema = this.entries[key];
1184
+ if (key in input || (valueSchema.type === "exact_optional" || valueSchema.type === "optional" || valueSchema.type === "nullish") && valueSchema.default !== undefined) {
1185
+ const value$1 = key in input ? input[key] : /* @__PURE__ */ getDefault(valueSchema);
1186
+ const valueDataset = valueSchema["~run"]({ value: value$1 }, config$1);
1187
+ if (valueDataset.issues) {
1188
+ const pathItem = {
1189
+ type: "object",
1190
+ origin: "value",
1191
+ input,
1192
+ key,
1193
+ value: value$1
1194
+ };
1195
+ for (const issue of valueDataset.issues) {
1196
+ if (issue.path)
1197
+ issue.path.unshift(pathItem);
1198
+ else
1199
+ issue.path = [pathItem];
1200
+ dataset.issues?.push(issue);
1201
+ }
1202
+ if (!dataset.issues)
1203
+ dataset.issues = valueDataset.issues;
1204
+ if (config$1.abortEarly) {
1205
+ dataset.typed = false;
1206
+ break;
1207
+ }
1208
+ }
1209
+ if (!valueDataset.typed)
1210
+ dataset.typed = false;
1211
+ dataset.value[key] = valueDataset.value;
1212
+ } else if (valueSchema.fallback !== undefined)
1213
+ dataset.value[key] = /* @__PURE__ */ getFallback(valueSchema);
1214
+ else if (valueSchema.type !== "exact_optional" && valueSchema.type !== "optional" && valueSchema.type !== "nullish") {
1215
+ _addIssue(this, "key", dataset, config$1, {
1216
+ input: undefined,
1217
+ expected: `"${key}"`,
1218
+ path: [{
1219
+ type: "object",
1220
+ origin: "key",
1221
+ input,
1222
+ key,
1223
+ value: input[key]
1224
+ }]
1225
+ });
1226
+ if (config$1.abortEarly)
1227
+ break;
1228
+ }
1229
+ }
1230
+ if (!dataset.issues || !config$1.abortEarly) {
1231
+ for (const key in input)
1232
+ if (!(key in this.entries)) {
1233
+ _addIssue(this, "key", dataset, config$1, {
1234
+ input: key,
1235
+ expected: "never",
1236
+ path: [{
1237
+ type: "object",
1238
+ origin: "key",
1239
+ input,
1240
+ key,
1241
+ value: input[key]
1242
+ }]
1243
+ });
1244
+ break;
1245
+ }
1246
+ }
1247
+ } else
1248
+ _addIssue(this, "type", dataset, config$1);
1249
+ return dataset;
1250
+ }
1251
+ };
1252
+ }
1253
+ function string(message$1) {
1254
+ return {
1255
+ kind: "schema",
1256
+ type: "string",
1257
+ reference: string,
1258
+ expects: "string",
1259
+ async: false,
1260
+ message: message$1,
1261
+ get "~standard"() {
1262
+ return /* @__PURE__ */ _getStandardProps(this);
1263
+ },
1264
+ "~run"(dataset, config$1) {
1265
+ if (typeof dataset.value === "string")
1266
+ dataset.typed = true;
1267
+ else
1268
+ _addIssue(this, "type", dataset, config$1);
1269
+ return dataset;
1270
+ }
1271
+ };
1272
+ }
1273
+ function _subIssues(datasets) {
1274
+ let issues;
1275
+ if (datasets)
1276
+ for (const dataset of datasets)
1277
+ if (issues)
1278
+ issues.push(...dataset.issues);
1279
+ else
1280
+ issues = dataset.issues;
1281
+ return issues;
1282
+ }
1283
+ function union(options, message$1) {
1284
+ return {
1285
+ kind: "schema",
1286
+ type: "union",
1287
+ reference: union,
1288
+ expects: /* @__PURE__ */ _joinExpects(options.map((option) => option.expects), "|"),
1289
+ async: false,
1290
+ options,
1291
+ message: message$1,
1292
+ get "~standard"() {
1293
+ return /* @__PURE__ */ _getStandardProps(this);
1294
+ },
1295
+ "~run"(dataset, config$1) {
1296
+ let validDataset;
1297
+ let typedDatasets;
1298
+ let untypedDatasets;
1299
+ for (const schema of this.options) {
1300
+ const optionDataset = schema["~run"]({ value: dataset.value }, config$1);
1301
+ if (optionDataset.typed)
1302
+ if (optionDataset.issues)
1303
+ if (typedDatasets)
1304
+ typedDatasets.push(optionDataset);
1305
+ else
1306
+ typedDatasets = [optionDataset];
1307
+ else {
1308
+ validDataset = optionDataset;
1309
+ break;
1310
+ }
1311
+ else if (untypedDatasets)
1312
+ untypedDatasets.push(optionDataset);
1313
+ else
1314
+ untypedDatasets = [optionDataset];
1315
+ }
1316
+ if (validDataset)
1317
+ return validDataset;
1318
+ if (typedDatasets) {
1319
+ if (typedDatasets.length === 1)
1320
+ return typedDatasets[0];
1321
+ _addIssue(this, "type", dataset, config$1, { issues: /* @__PURE__ */ _subIssues(typedDatasets) });
1322
+ dataset.typed = true;
1323
+ } else if (untypedDatasets?.length === 1)
1324
+ return untypedDatasets[0];
1325
+ else
1326
+ _addIssue(this, "type", dataset, config$1, { issues: /* @__PURE__ */ _subIssues(untypedDatasets) });
1327
+ return dataset;
1328
+ }
1329
+ };
1330
+ }
1331
+ function unknown() {
1332
+ return {
1333
+ kind: "schema",
1334
+ type: "unknown",
1335
+ reference: unknown,
1336
+ expects: "unknown",
1337
+ async: false,
1338
+ get "~standard"() {
1339
+ return /* @__PURE__ */ _getStandardProps(this);
1340
+ },
1341
+ "~run"(dataset) {
1342
+ dataset.typed = true;
1343
+ return dataset;
1344
+ }
1345
+ };
1346
+ }
1347
+ function pipe(...pipe$1) {
1348
+ return {
1349
+ ...pipe$1[0],
1350
+ pipe: pipe$1,
1351
+ get "~standard"() {
1352
+ return /* @__PURE__ */ _getStandardProps(this);
1353
+ },
1354
+ "~run"(dataset, config$1) {
1355
+ for (const item of pipe$1)
1356
+ if (item.kind !== "metadata") {
1357
+ if (dataset.issues && (item.kind === "schema" || item.kind === "transformation")) {
1358
+ dataset.typed = false;
1359
+ break;
1360
+ }
1361
+ if (!dataset.issues || !config$1.abortEarly && !config$1.abortPipeEarly)
1362
+ dataset = item["~run"](dataset, config$1);
1363
+ }
1364
+ return dataset;
1365
+ }
1366
+ };
1367
+ }
1368
+ function safeParse(schema, input, config$1) {
1369
+ const dataset = schema["~run"]({ value: input }, /* @__PURE__ */ getGlobalConfig(config$1));
1370
+ return {
1371
+ typed: dataset.typed,
1372
+ success: !dataset.issues,
1373
+ output: dataset.value,
1374
+ issues: dataset.issues
1375
+ };
1376
+ }
1377
+
1378
+ // src/schemas/markerFile.ts
1379
+ var MarkerFileSchema = strictObject({
1380
+ name: pipe(string(), regex(/^[a-z0-9][a-z0-9-]*$/)),
1381
+ description: optional(string()),
1382
+ skills: optional(array(pipe(string(), startsWith("./")))),
1383
+ agents: optional(array(pipe(string(), startsWith("./")))),
1384
+ commands: optional(array(pipe(string(), startsWith("./")))),
1385
+ hooks: optional(string()),
1386
+ mcpServers: optional(string()),
1387
+ outputStyles: optional(array(pipe(string(), startsWith("./")))),
1388
+ themes: optional(array(pipe(string(), startsWith("./")))),
1389
+ monitors: optional(string()),
1390
+ license: optional(string()),
1391
+ homepage: optional(string()),
1392
+ repository: optional(string())
1393
+ });
1394
+
1395
+ // src/detector/markerFile.ts
1396
+ function detectMarkerFile(repoRoot) {
1397
+ const markerPath = join3(repoRoot, ".ccpluginizer.json");
1398
+ if (!existsSync2(markerPath)) {
1399
+ return null;
1400
+ }
1401
+ const raw = readFileSync(markerPath, "utf8");
1402
+ let parsed;
1403
+ try {
1404
+ parsed = JSON.parse(raw);
1405
+ } catch (e) {
1406
+ throw new MarkerFileError(`Invalid JSON in ${markerPath}: ${e instanceof Error ? e.message : String(e)}`, []);
1407
+ }
1408
+ const result = safeParse(MarkerFileSchema, parsed);
1409
+ if (!result.success) {
1410
+ throw new MarkerFileError(`Marker file at ${markerPath} failed validation`, result.issues);
1411
+ }
1412
+ return result.output;
1413
+ }
1414
+
1415
+ // src/detector/conventions.ts
1416
+ import { existsSync as existsSync3, readdirSync, statSync } from "fs";
1417
+ import { join as join4 } from "path";
1418
+ var FOLDER_KINDS = [
1419
+ { folder: "skills", kind: "skills" },
1420
+ { folder: "agents", kind: "agents" },
1421
+ { folder: "commands", kind: "commands" },
1422
+ { folder: "output-styles", kind: "outputStyles" },
1423
+ { folder: "themes", kind: "themes" }
1424
+ ];
1425
+ var FILE_KINDS = [
1426
+ { file: "hooks/hooks.json", kind: "hooks" },
1427
+ { file: ".mcp.json", kind: "mcpServers" },
1428
+ { file: "monitors/monitors.json", kind: "monitors" }
1429
+ ];
1430
+ function detectConventions(repoRoot) {
1431
+ const rootFindings = scanRoot(repoRoot, "");
1432
+ const dotfilesFindings = scanRoot(repoRoot, ".claude");
1433
+ return mergeByKind([...rootFindings, ...dotfilesFindings]);
1434
+ }
1435
+ function scanRoot(repoRoot, prefix) {
1436
+ const findings = [];
1437
+ const baseDir = prefix === "" ? repoRoot : join4(repoRoot, prefix);
1438
+ const pathPrefix = prefix === "" ? "./" : `./${prefix}/`;
1439
+ for (const { folder, kind } of FOLDER_KINDS) {
1440
+ const folderPath = join4(baseDir, folder);
1441
+ if (existsSync3(folderPath) && statSync(folderPath).isDirectory()) {
1442
+ const hasContents = readdirSync(folderPath).length > 0;
1443
+ findings.push({
1444
+ kind,
1445
+ paths: [`${pathPrefix}${folder}/`],
1446
+ confidence: hasContents ? "high" : "medium",
1447
+ source: "convention"
1448
+ });
1449
+ }
1450
+ }
1451
+ for (const { file, kind } of FILE_KINDS) {
1452
+ if (existsSync3(join4(baseDir, file))) {
1453
+ findings.push({
1454
+ kind,
1455
+ paths: [`${pathPrefix}${file}`],
1456
+ confidence: "high",
1457
+ source: "convention"
1458
+ });
1459
+ }
1460
+ }
1461
+ return findings;
1462
+ }
1463
+ function mergeByKind(findings) {
1464
+ const byKind = new Map;
1465
+ for (const finding of findings) {
1466
+ const existing = byKind.get(finding.kind);
1467
+ if (existing === undefined) {
1468
+ byKind.set(finding.kind, finding);
1469
+ } else {
1470
+ const mergedPaths = [...new Set([...existing.paths, ...finding.paths])];
1471
+ const mergedConfidence = existing.confidence === "high" || finding.confidence === "high" ? "high" : existing.confidence === "medium" || finding.confidence === "medium" ? "medium" : "low";
1472
+ byKind.set(finding.kind, {
1473
+ kind: finding.kind,
1474
+ paths: mergedPaths,
1475
+ confidence: mergedConfidence,
1476
+ source: existing.source
1477
+ });
1478
+ }
1479
+ }
1480
+ return Array.from(byKind.values());
1481
+ }
1482
+
1483
+ // src/detector/nonStandardManifest.ts
1484
+ import { existsSync as existsSync4, readFileSync as readFileSync2, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
1485
+ import { join as join5 } from "path";
1486
+
1487
+ // src/schemas/nonStandardManifest.ts
1488
+ var NonStandardManifestSchema = object({
1489
+ name: optional(string()),
1490
+ description: optional(string()),
1491
+ version: optional(string()),
1492
+ author: optional(union([string(), object({ name: string() })])),
1493
+ homepage: optional(string()),
1494
+ repository: optional(string()),
1495
+ license: optional(string()),
1496
+ skills: optional(array(string())),
1497
+ agents: optional(array(string())),
1498
+ commands: optional(array(string())),
1499
+ hooks: optional(string()),
1500
+ mcpServers: optional(string())
1501
+ });
1502
+
1503
+ // src/detector/nonStandardManifest.ts
1504
+ function detectNonStandardManifest(repoRoot) {
1505
+ const dir = join5(repoRoot, ".claude-plugin");
1506
+ if (!existsSync4(dir) || !statSync2(dir).isDirectory()) {
1507
+ return null;
1508
+ }
1509
+ for (const entry of readdirSync2(dir)) {
1510
+ if (entry === "plugin.json" || entry === "marketplace.json") {
1511
+ continue;
1512
+ }
1513
+ if (!entry.endsWith(".json")) {
1514
+ continue;
1515
+ }
1516
+ const filePath = join5(dir, entry);
1517
+ let parsed;
1518
+ try {
1519
+ parsed = JSON.parse(readFileSync2(filePath, "utf8"));
1520
+ } catch {
1521
+ continue;
1522
+ }
1523
+ const result = safeParse(NonStandardManifestSchema, parsed);
1524
+ if (!result.success) {
1525
+ continue;
1526
+ }
1527
+ const m = result.output;
1528
+ const hasComponent = m.skills !== undefined || m.agents !== undefined || m.commands !== undefined || m.hooks !== undefined || m.mcpServers !== undefined;
1529
+ if (!hasComponent) {
1530
+ continue;
1531
+ }
1532
+ return { filename: entry, manifest: m };
1533
+ }
1534
+ return null;
1535
+ }
1536
+
1537
+ // src/detector/contentSniff.ts
1538
+ import { readdirSync as readdirSync3, readFileSync as readFileSync3, statSync as statSync3 } from "fs";
1539
+ import { join as join6, dirname, relative } from "path";
1540
+
1541
+ // src/schemas/frontmatter.ts
1542
+ var SkillFrontmatterSchema = object({
1543
+ name: optional(string()),
1544
+ description: string(),
1545
+ "disable-model-invocation": optional(boolean())
1546
+ });
1547
+ var AgentFrontmatterSchema = object({
1548
+ name: string(),
1549
+ description: string(),
1550
+ model: optional(string()),
1551
+ effort: optional(string()),
1552
+ maxTurns: optional(number()),
1553
+ tools: optional(array(string())),
1554
+ disallowedTools: optional(union([string(), array(string())]))
1555
+ });
1556
+
1557
+ // src/detector/contentSniff.ts
1558
+ function detectContentSniff(repoRoot) {
1559
+ const skillDirs = new Set;
1560
+ const agentFiles = new Set;
1561
+ walk(repoRoot, repoRoot, (filePath) => {
1562
+ if (filePath.endsWith("SKILL.md")) {
1563
+ const fm = parseFrontmatter(filePath);
1564
+ if (fm !== null && safeParse(SkillFrontmatterSchema, fm).success) {
1565
+ const dir = dirname(filePath);
1566
+ skillDirs.add(dir);
1567
+ }
1568
+ return;
1569
+ }
1570
+ if (filePath.endsWith(".md")) {
1571
+ const fm = parseFrontmatter(filePath);
1572
+ if (fm !== null && safeParse(AgentFrontmatterSchema, fm).success) {
1573
+ agentFiles.add(filePath);
1574
+ }
1575
+ }
1576
+ });
1577
+ const findings = [];
1578
+ if (skillDirs.size > 0) {
1579
+ findings.push({
1580
+ kind: "skills",
1581
+ paths: Array.from(skillDirs).map((dir) => `./${relative(repoRoot, dir)}/`),
1582
+ confidence: "medium",
1583
+ source: "sniff"
1584
+ });
1585
+ }
1586
+ if (agentFiles.size > 0) {
1587
+ findings.push({
1588
+ kind: "agents",
1589
+ paths: Array.from(agentFiles).map((file) => `./${relative(repoRoot, file)}`),
1590
+ confidence: "medium",
1591
+ source: "sniff"
1592
+ });
1593
+ }
1594
+ return findings;
1595
+ }
1596
+ function walk(repoRoot, dir, visit) {
1597
+ for (const entry of readdirSync3(dir)) {
1598
+ if (entry === "node_modules" || entry === ".git") {
1599
+ continue;
1600
+ }
1601
+ const fullPath = join6(dir, entry);
1602
+ const s = statSync3(fullPath);
1603
+ if (s.isDirectory()) {
1604
+ walk(repoRoot, fullPath, visit);
1605
+ } else if (s.isFile()) {
1606
+ visit(fullPath);
1607
+ }
1608
+ }
1609
+ }
1610
+ function parseFrontmatter(filePath) {
1611
+ const content = readFileSync3(filePath, "utf8");
1612
+ const match = /^---\n([\s\S]*?)\n---/.exec(content);
1613
+ if (match === null) {
1614
+ return null;
1615
+ }
1616
+ const yamlBody = match[1];
1617
+ if (yamlBody === undefined) {
1618
+ return null;
1619
+ }
1620
+ return parseYamlBlock(yamlBody);
1621
+ }
1622
+ function parseYamlBlock(body) {
1623
+ const out = {};
1624
+ for (const line of body.split(`
1625
+ `)) {
1626
+ const trimmed = line.trim();
1627
+ if (trimmed === "" || trimmed.startsWith("#")) {
1628
+ continue;
1629
+ }
1630
+ const colonIdx = trimmed.indexOf(":");
1631
+ if (colonIdx === -1) {
1632
+ continue;
1633
+ }
1634
+ const key = trimmed.slice(0, colonIdx).trim();
1635
+ const rawValue = trimmed.slice(colonIdx + 1).trim();
1636
+ out[key] = coerceYamlValue(rawValue);
1637
+ }
1638
+ return out;
1639
+ }
1640
+ function coerceYamlValue(raw) {
1641
+ if (raw === "true")
1642
+ return true;
1643
+ if (raw === "false")
1644
+ return false;
1645
+ if (raw === "null" || raw === "~")
1646
+ return null;
1647
+ if (/^-?\d+$/.test(raw))
1648
+ return Number(raw);
1649
+ if (raw.startsWith('"') && raw.endsWith('"'))
1650
+ return raw.slice(1, -1);
1651
+ if (raw.startsWith("'") && raw.endsWith("'"))
1652
+ return raw.slice(1, -1);
1653
+ return raw;
1654
+ }
1655
+
1656
+ // src/detector/normalize.ts
1657
+ import { existsSync as existsSync5 } from "fs";
1658
+ import { join as join7 } from "path";
1659
+ function normalizePath(input) {
1660
+ if (input.split("/").includes("..")) {
1661
+ throw new PathNormalizationError(input, "path traversal (..) not allowed");
1662
+ }
1663
+ if (input.startsWith("/") || input.startsWith("~")) {
1664
+ throw new PathNormalizationError(input, "absolute paths not allowed");
1665
+ }
1666
+ if (/^[A-Za-z]:[/\\]/.test(input)) {
1667
+ throw new PathNormalizationError(input, "windows-style absolute paths not allowed");
1668
+ }
1669
+ if (input.startsWith("./")) {
1670
+ return input;
1671
+ }
1672
+ return `./${input}`;
1673
+ }
1674
+ function normalizePathsAgainstRepo(repoRoot, paths) {
1675
+ const kept = [];
1676
+ const dropped = [];
1677
+ for (const raw of paths) {
1678
+ const normalized = normalizePath(raw);
1679
+ const fullPath = join7(repoRoot, normalized);
1680
+ if (existsSync5(fullPath)) {
1681
+ kept.push(normalized);
1682
+ } else {
1683
+ dropped.push(normalized);
1684
+ }
1685
+ }
1686
+ return { kept, dropped };
1687
+ }
1688
+
1689
+ // src/detector/synthesize.ts
1690
+ function synthesizeEntry(input) {
1691
+ checkMarketplaceGuard(input.repoRoot);
1692
+ const marker = detectMarkerFile(input.repoRoot);
1693
+ if (marker !== null) {
1694
+ return buildEntryFromMarker(marker, input.sourceRepo, input.repoRoot);
1695
+ }
1696
+ const conventionFindings = detectConventions(input.repoRoot);
1697
+ const manifestResult = detectNonStandardManifest(input.repoRoot);
1698
+ const sniffFindings = detectContentSniff(input.repoRoot);
1699
+ const findings = [...conventionFindings];
1700
+ const manifestKindsWithFindings = new Set;
1701
+ if (manifestResult !== null) {
1702
+ addManifestFindings(findings, manifestResult.manifest, manifestKindsWithFindings);
1703
+ }
1704
+ let mergedFindings = findings.filter((f) => {
1705
+ if (f.source === "convention" && manifestKindsWithFindings.has(f.kind)) {
1706
+ return false;
1707
+ }
1708
+ return true;
1709
+ });
1710
+ for (const sniffF of sniffFindings) {
1711
+ if (!hasKind(mergedFindings, sniffF.kind)) {
1712
+ mergedFindings = [...mergedFindings, sniffF];
1713
+ }
1714
+ }
1715
+ const entry = buildEntryFromFindings(mergedFindings, input.repoRoot, input.sourceRepo);
1716
+ if (manifestResult !== null) {
1717
+ return mergeManifestMetadata(entry, manifestResult.manifest);
1718
+ }
1719
+ return entry;
1720
+ }
1721
+ function addManifestFindings(findings, manifest, manifestKindsWithFindings) {
1722
+ const kinds = [
1723
+ { key: "skills", kind: "skills" },
1724
+ { key: "agents", kind: "agents" },
1725
+ { key: "commands", kind: "commands" }
1726
+ ];
1727
+ for (const { key, kind } of kinds) {
1728
+ const value = manifest[key];
1729
+ if (Array.isArray(value)) {
1730
+ findings.push({
1731
+ kind,
1732
+ paths: value,
1733
+ confidence: "high",
1734
+ source: "manifest"
1735
+ });
1736
+ manifestKindsWithFindings.add(kind);
1737
+ }
1738
+ }
1739
+ }
1740
+ function mergeManifestMetadata(entry, manifest) {
1741
+ return {
1742
+ ...entry,
1743
+ ...manifest.description !== undefined ? { description: manifest.description } : {},
1744
+ ...manifest.homepage !== undefined ? { homepage: manifest.homepage } : {},
1745
+ ...manifest.repository !== undefined ? { repository: manifest.repository } : {},
1746
+ ...manifest.license !== undefined ? { license: manifest.license } : {},
1747
+ ...manifest.author !== undefined ? { author: manifest.author } : {}
1748
+ };
1749
+ }
1750
+ function buildEntryFromMarker(marker, sourceRepo, repoRoot) {
1751
+ const normalizeIfPresent = (paths) => {
1752
+ if (paths === undefined) {
1753
+ return;
1754
+ }
1755
+ const { kept } = normalizePathsAgainstRepo(repoRoot, paths);
1756
+ return kept.length > 0 ? [...kept] : undefined;
1757
+ };
1758
+ const skills = normalizeIfPresent(marker.skills);
1759
+ const agents = normalizeIfPresent(marker.agents);
1760
+ const commands = normalizeIfPresent(marker.commands);
1761
+ const outputStyles = normalizeIfPresent(marker.outputStyles);
1762
+ const themes = normalizeIfPresent(marker.themes);
1763
+ return {
1764
+ name: marker.name,
1765
+ source: makeGithubSource(sourceRepo),
1766
+ strict: false,
1767
+ ...marker.description !== undefined ? { description: marker.description } : {},
1768
+ ...marker.license !== undefined ? { license: marker.license } : {},
1769
+ ...marker.homepage !== undefined ? { homepage: marker.homepage } : {},
1770
+ ...marker.repository !== undefined ? { repository: marker.repository } : {},
1771
+ ...skills !== undefined ? { skills } : {},
1772
+ ...agents !== undefined ? { agents } : {},
1773
+ ...commands !== undefined ? { commands } : {},
1774
+ ...marker.hooks !== undefined ? { hooks: marker.hooks } : {},
1775
+ ...marker.mcpServers !== undefined ? { mcpServers: marker.mcpServers } : {},
1776
+ ...outputStyles !== undefined ? { outputStyles } : {},
1777
+ ...themes !== undefined ? { themes } : {},
1778
+ ...marker.monitors !== undefined ? { monitors: marker.monitors } : {}
1779
+ };
1780
+ }
1781
+ function buildEntryFromFindings(findings, repoRoot, sourceRepo) {
1782
+ const byKind = groupByKind(findings);
1783
+ const componentEntries = {};
1784
+ for (const [kind, kindFindings] of byKind) {
1785
+ const allPaths = kindFindings.flatMap((f) => f.paths);
1786
+ const { kept } = normalizePathsAgainstRepo(repoRoot, allPaths);
1787
+ if (kept.length > 0) {
1788
+ componentEntries[kind] = kept;
1789
+ }
1790
+ }
1791
+ return {
1792
+ name: defaultEntryName(sourceRepo),
1793
+ source: makeGithubSource(sourceRepo),
1794
+ strict: false,
1795
+ ...componentEntries
1796
+ };
1797
+ }
1798
+ function hasKind(findings, kind) {
1799
+ for (const f of findings) {
1800
+ if (f.kind === kind) {
1801
+ return true;
1802
+ }
1803
+ }
1804
+ return false;
1805
+ }
1806
+ function groupByKind(findings) {
1807
+ const map = new Map;
1808
+ for (const f of findings) {
1809
+ const list = map.get(f.kind) ?? [];
1810
+ list.push(f);
1811
+ map.set(f.kind, list);
1812
+ }
1813
+ return map;
1814
+ }
1815
+ function makeGithubSource(repo) {
1816
+ return { source: "github", repo };
1817
+ }
1818
+ function defaultEntryName(sourceRepo) {
1819
+ return sourceRepo.replace("/", "-").toLowerCase();
1820
+ }
1821
+
1822
+ // src/commands/scan.ts
1823
+ var scanCommand = new R("scan").meta({ description: "Scan a non-plugin repo and emit a marketplace entry" }).args([{ name: "repo", type: "string", required: true, description: "owner/repo, URL, or local path" }]).flags({
1824
+ output: { type: "string", short: "o", description: "Write entry JSON to file" }
1825
+ }).run(async ({ args, flags }) => {
1826
+ const repoPath = await resolveSource(args.repo);
1827
+ const sourceRepo = inferSourceRepo(args.repo);
1828
+ const entry = synthesizeEntry({ repoRoot: repoPath, sourceRepo });
1829
+ const json = JSON.stringify(entry, null, 2);
1830
+ if (flags.output !== undefined) {
1831
+ writeFileSync(flags.output, json + `
1832
+ `, "utf8");
1833
+ } else {
1834
+ console.log(json);
1835
+ }
1836
+ });
1837
+
1838
+ // src/commands/validate.ts
1839
+ import { readFileSync as readFileSync4 } from "fs";
1840
+
1841
+ // src/schemas/marketplaceEntry.ts
1842
+ var PathString = pipe(string(), startsWith("./"));
1843
+ var GithubSourceSchema = strictObject({
1844
+ source: literal("github"),
1845
+ repo: pipe(string(), regex(/^[\w.-]+\/[\w.-]+$/)),
1846
+ ref: optional(string()),
1847
+ sha: optional(string())
1848
+ });
1849
+ var UrlSourceSchema = strictObject({
1850
+ source: literal("url"),
1851
+ url: string(),
1852
+ ref: optional(string()),
1853
+ sha: optional(string())
1854
+ });
1855
+ var GitSubdirSourceSchema = strictObject({
1856
+ source: literal("git-subdir"),
1857
+ url: string(),
1858
+ path: string(),
1859
+ ref: optional(string()),
1860
+ sha: optional(string())
1861
+ });
1862
+ var SourceSchema = union([GithubSourceSchema, UrlSourceSchema, GitSubdirSourceSchema]);
1863
+ var MarketplaceEntrySchema = object({
1864
+ name: pipe(string(), regex(/^[a-z0-9][a-z0-9-]*$/)),
1865
+ source: SourceSchema,
1866
+ strict: optional(boolean()),
1867
+ description: optional(string()),
1868
+ version: optional(string()),
1869
+ author: optional(union([string(), object({ name: string() })])),
1870
+ homepage: optional(string()),
1871
+ repository: optional(string()),
1872
+ license: optional(string()),
1873
+ keywords: optional(array(string())),
1874
+ skills: optional(array(PathString)),
1875
+ agents: optional(array(PathString)),
1876
+ commands: optional(array(PathString)),
1877
+ hooks: optional(union([PathString, record(string(), unknown())])),
1878
+ mcpServers: optional(union([PathString, record(string(), unknown())])),
1879
+ outputStyles: optional(array(PathString)),
1880
+ themes: optional(array(PathString)),
1881
+ monitors: optional(PathString)
1882
+ });
1883
+
1884
+ // src/commands/validate.ts
1885
+ var validateCommand = new R("validate").meta({ description: "Validate a marketplace entry JSON file against the schema" }).args([{ name: "entryFile", type: "string", required: true, description: "Path to entry JSON file" }]).run(({ args }) => {
1886
+ const raw = readFileSync4(args.entryFile, "utf8");
1887
+ const parsed = JSON.parse(raw);
1888
+ const result = safeParse(MarketplaceEntrySchema, parsed);
1889
+ if (!result.success) {
1890
+ console.error("Validation failed:");
1891
+ for (const issue of result.issues) {
1892
+ console.error(JSON.stringify(issue));
1893
+ }
1894
+ process.exit(1);
1895
+ }
1896
+ console.log("OK");
1897
+ });
1898
+
1899
+ // src/commands/submit.ts
1900
+ import { writeFileSync as writeFileSync2, mkdtempSync as mkdtempSync2 } from "fs";
1901
+ import { tmpdir as tmpdir2 } from "os";
1902
+ import { join as join8 } from "path";
1903
+ var submitCommand = new R("submit").meta({ description: "Generate an entry and open a PR against ccpluginizer/marketplace" }).args([{ name: "repo", type: "string", required: true, description: "owner/repo to pluginize" }]).flags({
1904
+ dryRun: { type: "boolean", short: "n", description: "Print the PR plan without opening it" }
1905
+ }).run(async ({ args, flags }) => {
1906
+ const repoPath = await resolveSource(args.repo);
1907
+ const sourceRepo = inferSourceRepo(args.repo);
1908
+ const entry = synthesizeEntry({ repoRoot: repoPath, sourceRepo });
1909
+ const tmpFile = join8(mkdtempSync2(join8(tmpdir2(), "ccp-submit-")), `${entry.name}.json`);
1910
+ writeFileSync2(tmpFile, JSON.stringify(entry, null, 2) + `
1911
+ `, "utf8");
1912
+ if (flags.dryRun === true) {
1913
+ console.log(`Would submit:
1914
+ entry: ${tmpFile}
1915
+ to: ccpluginizer/marketplace`);
1916
+ console.log(JSON.stringify(entry, null, 2));
1917
+ return;
1918
+ }
1919
+ console.log(`Generated entry at ${tmpFile}`);
1920
+ console.log("Run with --dryRun to preview, or follow the manual PR workflow in CONTRIBUTING.md.");
1921
+ });
1922
+
1923
+ // src/index.ts
1924
+ var app = new R("ccpluginizer").meta({ description: "Pluginize non-plugin Claude Code repos" }).command(scanCommand).command(validateCommand).command(submitCommand);
1925
+ await app.execute();