skillstore 0.0.1 → 0.1.1

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 (55) hide show
  1. package/README.md +199 -0
  2. package/dist/cli/index.d.ts +3 -0
  3. package/dist/cli/index.d.ts.map +1 -0
  4. package/dist/cli/index.js +21 -0
  5. package/dist/cli/index.js.map +1 -0
  6. package/dist/commands/install.d.ts +35 -0
  7. package/dist/commands/install.d.ts.map +1 -0
  8. package/dist/commands/install.js +272 -0
  9. package/dist/commands/install.js.map +1 -0
  10. package/dist/commands/plugin/index.d.ts +3 -0
  11. package/dist/commands/plugin/index.d.ts.map +1 -0
  12. package/dist/commands/plugin/index.js +13 -0
  13. package/dist/commands/plugin/index.js.map +1 -0
  14. package/dist/commands/plugin/info.d.ts +9 -0
  15. package/dist/commands/plugin/info.d.ts.map +1 -0
  16. package/dist/commands/plugin/info.js +75 -0
  17. package/dist/commands/plugin/info.js.map +1 -0
  18. package/dist/commands/plugin/install.d.ts +29 -0
  19. package/dist/commands/plugin/install.d.ts.map +1 -0
  20. package/dist/commands/plugin/install.js +140 -0
  21. package/dist/commands/plugin/install.js.map +1 -0
  22. package/dist/commands/plugin/list.d.ts +22 -0
  23. package/dist/commands/plugin/list.d.ts.map +1 -0
  24. package/dist/commands/plugin/list.js +76 -0
  25. package/dist/commands/plugin/list.js.map +1 -0
  26. package/dist/index.d.ts +11 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +13 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/lib/plugin-api.d.ts +155 -0
  31. package/dist/lib/plugin-api.d.ts.map +1 -0
  32. package/dist/lib/plugin-api.js +173 -0
  33. package/dist/lib/plugin-api.js.map +1 -0
  34. package/dist/lib/plugin-config.d.ts +56 -0
  35. package/dist/lib/plugin-config.d.ts.map +1 -0
  36. package/dist/lib/plugin-config.js +64 -0
  37. package/dist/lib/plugin-config.js.map +1 -0
  38. package/dist/lib/plugin-download.d.ts +36 -0
  39. package/dist/lib/plugin-download.d.ts.map +1 -0
  40. package/dist/lib/plugin-download.js +134 -0
  41. package/dist/lib/plugin-download.js.map +1 -0
  42. package/dist/lib/plugin-logger.d.ts +79 -0
  43. package/dist/lib/plugin-logger.d.ts.map +1 -0
  44. package/dist/lib/plugin-logger.js +173 -0
  45. package/dist/lib/plugin-logger.js.map +1 -0
  46. package/dist/lib/plugin-verify.d.ts +35 -0
  47. package/dist/lib/plugin-verify.d.ts.map +1 -0
  48. package/dist/lib/plugin-verify.js +97 -0
  49. package/dist/lib/plugin-verify.js.map +1 -0
  50. package/dist/lib/skill-api.d.ts +33 -0
  51. package/dist/lib/skill-api.d.ts.map +1 -0
  52. package/dist/lib/skill-api.js +64 -0
  53. package/dist/lib/skill-api.js.map +1 -0
  54. package/package.json +56 -17
  55. package/src/index.js +0 -16
@@ -0,0 +1,173 @@
1
+ import consola from 'consola';
2
+ /**
3
+ * Plugin CLI Logger
4
+ *
5
+ * Provides styled logging and progress indicators for plugin operations.
6
+ */
7
+ /** Color codes for different log types */
8
+ const colors = {
9
+ info: '\x1b[36m', // Cyan
10
+ success: '\x1b[32m', // Green
11
+ warn: '\x1b[33m', // Yellow
12
+ error: '\x1b[31m', // Red
13
+ dim: '\x1b[90m', // Gray
14
+ reset: '\x1b[0m',
15
+ bold: '\x1b[1m',
16
+ };
17
+ class PluginLogger {
18
+ progressState = null;
19
+ spinnerInterval = null;
20
+ spinnerFrames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
21
+ spinnerIndex = 0;
22
+ /**
23
+ * Log info message
24
+ */
25
+ info(message) {
26
+ consola.info(message);
27
+ }
28
+ /**
29
+ * Log success message
30
+ */
31
+ success(message) {
32
+ consola.success(message);
33
+ }
34
+ /**
35
+ * Log warning message
36
+ */
37
+ warn(message) {
38
+ consola.warn(message);
39
+ }
40
+ /**
41
+ * Log error message
42
+ */
43
+ error(message, err) {
44
+ consola.error(message);
45
+ if (err && process.env.DEBUG) {
46
+ consola.error(err);
47
+ }
48
+ }
49
+ /**
50
+ * Log debug message (only in DEBUG mode)
51
+ */
52
+ debug(message) {
53
+ if (process.env.DEBUG) {
54
+ consola.debug(message);
55
+ }
56
+ }
57
+ /**
58
+ * Start a spinner with message
59
+ */
60
+ startSpinner(message) {
61
+ this.stopSpinner();
62
+ this.spinnerIndex = 0;
63
+ const spin = () => {
64
+ const frame = this.spinnerFrames[this.spinnerIndex];
65
+ process.stdout.write(`\r${colors.info}${frame}${colors.reset} ${message}`);
66
+ this.spinnerIndex = (this.spinnerIndex + 1) % this.spinnerFrames.length;
67
+ };
68
+ spin();
69
+ this.spinnerInterval = setInterval(spin, 80);
70
+ }
71
+ /**
72
+ * Stop the spinner
73
+ */
74
+ stopSpinner() {
75
+ if (this.spinnerInterval) {
76
+ clearInterval(this.spinnerInterval);
77
+ this.spinnerInterval = null;
78
+ process.stdout.write('\r\x1b[K'); // Clear line
79
+ }
80
+ }
81
+ /**
82
+ * Complete spinner with success
83
+ */
84
+ spinnerSuccess(message) {
85
+ this.stopSpinner();
86
+ console.log(`${colors.success}✓${colors.reset} ${message}`);
87
+ }
88
+ /**
89
+ * Complete spinner with error
90
+ */
91
+ spinnerError(message) {
92
+ this.stopSpinner();
93
+ console.log(`${colors.error}✗${colors.reset} ${message}`);
94
+ }
95
+ /**
96
+ * Start progress tracking
97
+ */
98
+ startProgress(total, label) {
99
+ this.progressState = { current: 0, total, label };
100
+ this.renderProgress();
101
+ }
102
+ /**
103
+ * Update progress
104
+ */
105
+ updateProgress(current) {
106
+ if (this.progressState) {
107
+ this.progressState.current = current;
108
+ this.renderProgress();
109
+ }
110
+ }
111
+ /**
112
+ * Increment progress by 1
113
+ */
114
+ incrementProgress() {
115
+ if (this.progressState) {
116
+ this.progressState.current++;
117
+ this.renderProgress();
118
+ }
119
+ }
120
+ /**
121
+ * Complete progress
122
+ */
123
+ completeProgress() {
124
+ if (this.progressState) {
125
+ process.stdout.write('\r\x1b[K'); // Clear line
126
+ const { total, label } = this.progressState;
127
+ console.log(`${colors.success}✓${colors.reset} ${label} (${total}/${total})`);
128
+ this.progressState = null;
129
+ }
130
+ }
131
+ /**
132
+ * Render progress bar
133
+ */
134
+ renderProgress() {
135
+ if (!this.progressState)
136
+ return;
137
+ const { current, total, label } = this.progressState;
138
+ const percent = Math.round((current / total) * 100);
139
+ const barWidth = 20;
140
+ const filled = Math.round((current / total) * barWidth);
141
+ const empty = barWidth - filled;
142
+ const bar = `${'█'.repeat(filled)}${'░'.repeat(empty)}`;
143
+ process.stdout.write(`\r${colors.info}↓${colors.reset} ${label} ${colors.dim}[${bar}]${colors.reset} ${current}/${total} (${percent}%)`);
144
+ }
145
+ /**
146
+ * Print a box with content
147
+ */
148
+ box(title, content) {
149
+ const width = Math.max(title.length, ...content.map((c) => c.length)) + 4;
150
+ const border = '─'.repeat(width);
151
+ console.log(`${colors.dim}┌${border}┐${colors.reset}`);
152
+ console.log(`${colors.dim}│${colors.reset} ${colors.bold}${title.padEnd(width - 2)}${colors.reset} ${colors.dim}│${colors.reset}`);
153
+ console.log(`${colors.dim}├${border}┤${colors.reset}`);
154
+ for (const line of content) {
155
+ console.log(`${colors.dim}│${colors.reset} ${line.padEnd(width - 2)} ${colors.dim}│${colors.reset}`);
156
+ }
157
+ console.log(`${colors.dim}└${border}┘${colors.reset}`);
158
+ }
159
+ /**
160
+ * Print skill installation summary
161
+ */
162
+ skillSummary(slug, status) {
163
+ const icons = {
164
+ installed: `${colors.success}✓${colors.reset}`,
165
+ skipped: `${colors.warn}○${colors.reset}`,
166
+ failed: `${colors.error}✗${colors.reset}`,
167
+ };
168
+ console.log(` ${icons[status]} ${slug}`);
169
+ }
170
+ }
171
+ /** Singleton logger instance */
172
+ export const logger = new PluginLogger();
173
+ //# sourceMappingURL=plugin-logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-logger.js","sourceRoot":"","sources":["../../src/lib/plugin-logger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import type { PluginManifest } from './plugin-api.js';
2
+ /**
3
+ * Plugin Manifest Verification
4
+ *
5
+ * Verifies HMAC-SHA256 signatures on plugin manifests to ensure integrity.
6
+ */
7
+ /** Verification result */
8
+ export interface VerifyResult {
9
+ valid: boolean;
10
+ error?: string;
11
+ }
12
+ /**
13
+ * Get the signing key for manifest verification
14
+ * Uses built-in key by default, can be overridden via environment variable
15
+ */
16
+ export declare function getVerificationKey(): string;
17
+ /**
18
+ * Verify manifest signature using HMAC-SHA256
19
+ *
20
+ * The signature is computed over the manifest JSON without the signature field.
21
+ */
22
+ export declare function verifyManifestSignature(manifest: PluginManifest, key: string): VerifyResult;
23
+ /**
24
+ * Verify skill content hash
25
+ *
26
+ * Ensures downloaded skill content matches the hash in the manifest.
27
+ */
28
+ export declare function verifyContentHash(content: string, expectedHash: string): boolean;
29
+ /**
30
+ * Verify entire manifest (signature + metadata)
31
+ */
32
+ export declare function verifyManifest(manifest: PluginManifest, options?: {
33
+ skipSignature?: boolean;
34
+ }): Promise<VerifyResult>;
35
+ //# sourceMappingURL=plugin-verify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-verify.d.ts","sourceRoot":"","sources":["../../src/lib/plugin-verify.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtD;;;;GAIG;AAEH,0BAA0B;AAC1B,MAAM,WAAW,YAAY;IAC5B,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAQD;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACtC,QAAQ,EAAE,cAAc,EACxB,GAAG,EAAE,MAAM,GACT,YAAY,CA6Bd;AAgBD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAMhF;AAED;;GAEG;AACH,wBAAsB,cAAc,CACnC,QAAQ,EAAE,cAAc,EACxB,OAAO,GAAE;IAAE,aAAa,CAAC,EAAE,OAAO,CAAA;CAAO,GACvC,OAAO,CAAC,YAAY,CAAC,CA+BvB"}
@@ -0,0 +1,97 @@
1
+ import { createHmac, createHash, timingSafeEqual as cryptoTimingSafeEqual } from 'node:crypto';
2
+ /**
3
+ * Built-in verification key for skillstore.io manifests
4
+ * This key is used to verify HMAC-SHA256 signatures on plugin manifests
5
+ */
6
+ const DEFAULT_VERIFICATION_KEY = '3d2b8f367783854cbdb6f81c9a39d586201c8d898ec8737bfa464162a9177943';
7
+ /**
8
+ * Get the signing key for manifest verification
9
+ * Uses built-in key by default, can be overridden via environment variable
10
+ */
11
+ export function getVerificationKey() {
12
+ return process.env.SKILLSTORE_VERIFY_KEY || DEFAULT_VERIFICATION_KEY;
13
+ }
14
+ /**
15
+ * Verify manifest signature using HMAC-SHA256
16
+ *
17
+ * The signature is computed over the manifest JSON without the signature field.
18
+ */
19
+ export function verifyManifestSignature(manifest, key) {
20
+ try {
21
+ // Extract signature and create unsigned manifest
22
+ const { signature, ...unsignedManifest } = manifest;
23
+ if (!signature) {
24
+ return { valid: false, error: 'Manifest has no signature' };
25
+ }
26
+ // Compute expected signature (matching server-side implementation)
27
+ const dataToSign = JSON.stringify(unsignedManifest, null, 0);
28
+ const expectedSignature = createHmac('sha256', key)
29
+ .update(dataToSign)
30
+ .digest('hex');
31
+ // Constant-time comparison to prevent timing attacks
32
+ const valid = timingSafeEqual(signature, expectedSignature);
33
+ if (!valid) {
34
+ return { valid: false, error: 'Signature verification failed' };
35
+ }
36
+ return { valid: true };
37
+ }
38
+ catch (err) {
39
+ return {
40
+ valid: false,
41
+ error: `Verification error: ${err instanceof Error ? err.message : 'Unknown error'}`,
42
+ };
43
+ }
44
+ }
45
+ /**
46
+ * Constant-time string comparison to prevent timing attacks
47
+ */
48
+ function timingSafeEqual(a, b) {
49
+ if (a.length !== b.length) {
50
+ return false;
51
+ }
52
+ const bufA = Buffer.from(a, 'utf8');
53
+ const bufB = Buffer.from(b, 'utf8');
54
+ return cryptoTimingSafeEqual(bufA, bufB);
55
+ }
56
+ /**
57
+ * Verify skill content hash
58
+ *
59
+ * Ensures downloaded skill content matches the hash in the manifest.
60
+ */
61
+ export function verifyContentHash(content, expectedHash) {
62
+ const actualHash = createHash('sha256').update(content).digest('hex');
63
+ // Content hash might be truncated, compare common length
64
+ const compareLength = Math.min(actualHash.length, expectedHash.length);
65
+ return actualHash.substring(0, compareLength) === expectedHash.substring(0, compareLength);
66
+ }
67
+ /**
68
+ * Verify entire manifest (signature + metadata)
69
+ */
70
+ export async function verifyManifest(manifest, options = {}) {
71
+ // Validate manifest structure
72
+ if (!manifest.version || manifest.version !== '1.0') {
73
+ return { valid: false, error: 'Unsupported manifest version' };
74
+ }
75
+ if (!manifest.plugin?.slug) {
76
+ return { valid: false, error: 'Missing plugin slug in manifest' };
77
+ }
78
+ if (!Array.isArray(manifest.skills) || manifest.skills.length === 0) {
79
+ return { valid: false, error: 'Manifest contains no skills' };
80
+ }
81
+ // Validate skill entries
82
+ for (const skill of manifest.skills) {
83
+ if (!skill.slug || !skill.downloadUrl) {
84
+ return { valid: false, error: `Invalid skill entry: ${skill.slug || 'unknown'}` };
85
+ }
86
+ }
87
+ // Verify signature unless skipped
88
+ if (!options.skipSignature) {
89
+ const key = getVerificationKey();
90
+ const signatureResult = verifyManifestSignature(manifest, key);
91
+ if (!signatureResult.valid) {
92
+ return signatureResult;
93
+ }
94
+ }
95
+ return { valid: true };
96
+ }
97
+ //# sourceMappingURL=plugin-verify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-verify.js","sourceRoot":"","sources":["../../src/lib/plugin-verify.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import type { PluginConfig } from './plugin-config.js';
2
+ /**
3
+ * Skill API Client
4
+ *
5
+ * Handles HTTP requests for single skill operations.
6
+ */
7
+ /** Skill info response */
8
+ export interface SkillInfo {
9
+ slug: string;
10
+ name: string;
11
+ description: string | null;
12
+ category: string | null;
13
+ version: string | null;
14
+ author: string | null;
15
+ riskLevel: string | null;
16
+ qualityScore: number | null;
17
+ pluginPath: string | null;
18
+ }
19
+ /** API Error */
20
+ export declare class SkillApiError extends Error {
21
+ statusCode: number;
22
+ code?: string | undefined;
23
+ constructor(message: string, statusCode: number, code?: string | undefined);
24
+ }
25
+ /**
26
+ * Fetch skill info/details
27
+ */
28
+ export declare function fetchSkillInfo(config: PluginConfig, skillSlug: string): Promise<SkillInfo>;
29
+ /**
30
+ * Download skill as ZIP
31
+ */
32
+ export declare function downloadSkillZip(config: PluginConfig, skillSlug: string): Promise<ArrayBuffer>;
33
+ //# sourceMappingURL=skill-api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-api.d.ts","sourceRoot":"","sources":["../../src/lib/skill-api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD;;;;GAIG;AAEH,0BAA0B;AAC1B,MAAM,WAAW,SAAS;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,gBAAgB;AAChB,qBAAa,aAAc,SAAQ,KAAK;IAG/B,UAAU,EAAE,MAAM;IAClB,IAAI,CAAC,EAAE,MAAM;gBAFpB,OAAO,EAAE,MAAM,EACR,UAAU,EAAE,MAAM,EAClB,IAAI,CAAC,EAAE,MAAM,YAAA;CAKrB;AAgBD;;GAEG;AACH,wBAAsB,cAAc,CACnC,MAAM,EAAE,YAAY,EACpB,SAAS,EAAE,MAAM,GACf,OAAO,CAAC,SAAS,CAAC,CA6BpB;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACrC,MAAM,EAAE,YAAY,EACpB,SAAS,EAAE,MAAM,GACf,OAAO,CAAC,WAAW,CAAC,CAgBtB"}
@@ -0,0 +1,64 @@
1
+ /** API Error */
2
+ export class SkillApiError extends Error {
3
+ statusCode;
4
+ code;
5
+ constructor(message, statusCode, code) {
6
+ super(message);
7
+ this.statusCode = statusCode;
8
+ this.code = code;
9
+ this.name = 'SkillApiError';
10
+ }
11
+ }
12
+ /**
13
+ * Get the API endpoint for skill info
14
+ */
15
+ function getSkillInfoUrl(config, skillSlug) {
16
+ return `${config.apiBaseUrl}/skills/${skillSlug}`;
17
+ }
18
+ /**
19
+ * Get the download URL for a skill
20
+ */
21
+ function getSkillDownloadUrl(config, skillSlug) {
22
+ return `${config.apiBaseUrl}/skills/${skillSlug}/download`;
23
+ }
24
+ /**
25
+ * Fetch skill info/details
26
+ */
27
+ export async function fetchSkillInfo(config, skillSlug) {
28
+ const url = getSkillInfoUrl(config, skillSlug);
29
+ const response = await fetch(url, {
30
+ method: 'GET',
31
+ headers: {
32
+ Accept: 'application/json',
33
+ },
34
+ signal: AbortSignal.timeout(config.timeout),
35
+ });
36
+ if (!response.ok) {
37
+ const errorText = await response.text().catch(() => 'Unknown error');
38
+ let errorData = {};
39
+ try {
40
+ errorData = JSON.parse(errorText);
41
+ }
42
+ catch {
43
+ // Not JSON
44
+ }
45
+ throw new SkillApiError(errorData.error || `Failed to fetch skill info: ${response.statusText}`, response.status, errorData.code);
46
+ }
47
+ const result = (await response.json());
48
+ return result.data;
49
+ }
50
+ /**
51
+ * Download skill as ZIP
52
+ */
53
+ export async function downloadSkillZip(config, skillSlug) {
54
+ const url = getSkillDownloadUrl(config, skillSlug);
55
+ const response = await fetch(url, {
56
+ method: 'GET',
57
+ signal: AbortSignal.timeout(config.timeout * 2), // Longer timeout for download
58
+ });
59
+ if (!response.ok) {
60
+ throw new SkillApiError(`Failed to download skill: ${response.statusText}`, response.status);
61
+ }
62
+ return await response.arrayBuffer();
63
+ }
64
+ //# sourceMappingURL=skill-api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-api.js","sourceRoot":"","sources":["../../src/lib/skill-api.ts"],"names":[],"mappings":"AAqBA,gBAAgB;AAChB,MAAM,OAAO,aAAc,SAAQ,KAAK;IAG/B;IACA;IAHR,YACC,OAAe,EACR,UAAkB,EAClB,IAAa;QAEpB,KAAK,CAAC,OAAO,CAAC,CAAC;QAHR,eAAU,GAAV,UAAU,CAAQ;QAClB,SAAI,GAAJ,IAAI,CAAS;QAGpB,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC7B,CAAC;CACD;AAED;;GAEG;AACH,SAAS,eAAe,CAAC,MAAoB,EAAE,SAAiB;IAC/D,OAAO,GAAG,MAAM,CAAC,UAAU,WAAW,SAAS,EAAE,CAAC;AACnD,CAAC;AAED;;GAEG;AACH,SAAS,mBAAmB,CAAC,MAAoB,EAAE,SAAiB;IACnE,OAAO,GAAG,MAAM,CAAC,UAAU,WAAW,SAAS,WAAW,CAAC;AAC5D,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CACnC,MAAoB,EACpB,SAAiB;IAEjB,MAAM,GAAG,GAAG,eAAe,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAE/C,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QACjC,MAAM,EAAE,KAAK;QACb,OAAO,EAAE;YACR,MAAM,EAAE,kBAAkB;SAC1B;QACD,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC;KAC3C,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QAClB,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,eAAe,CAAC,CAAC;QACrE,IAAI,SAAS,GAAsC,EAAE,CAAC;QACtD,IAAI,CAAC;YACJ,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACnC,CAAC;QAAC,MAAM,CAAC;YACR,WAAW;QACZ,CAAC;QAED,MAAM,IAAI,aAAa,CACtB,SAAS,CAAC,KAAK,IAAI,+BAA+B,QAAQ,CAAC,UAAU,EAAE,EACvE,QAAQ,CAAC,MAAM,EACf,SAAS,CAAC,IAAI,CACd,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAwB,CAAC;IAC9D,OAAO,MAAM,CAAC,IAAI,CAAC;AACpB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACrC,MAAoB,EACpB,SAAiB;IAEjB,MAAM,GAAG,GAAG,mBAAmB,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAEnD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QACjC,MAAM,EAAE,KAAK;QACb,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,GAAG,CAAC,CAAC,EAAE,8BAA8B;KAC/E,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QAClB,MAAM,IAAI,aAAa,CACtB,6BAA6B,QAAQ,CAAC,UAAU,EAAE,EAClD,QAAQ,CAAC,MAAM,CACf,CAAC;IACH,CAAC;IAED,OAAO,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAC;AACrC,CAAC"}
package/package.json CHANGED
@@ -1,19 +1,58 @@
1
1
  {
2
- "name": "skillstore",
3
- "version": "0.0.1",
4
- "description": "AI Skillstore SDK",
5
- "main": "src/index.js",
6
- "type": "module",
7
- "scripts": {
8
- "start": "node src/index.js",
9
- "test": "echo \"Error: no test specified\" && exit 1"
10
- },
11
- "keywords": [
12
- "skillstore",
13
- "ai",
14
- "skills",
15
- "claude"
16
- ],
17
- "author": "",
18
- "license": "MIT"
2
+ "name": "skillstore",
3
+ "version": "0.1.1",
4
+ "description": "Skillstore CLI - AI Skills marketplace for Claude Code",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "bin": {
9
+ "skillstore": "dist/cli/index.js"
10
+ },
11
+ "exports": {
12
+ ".": {
13
+ "import": "./dist/index.js",
14
+ "types": "./dist/index.d.ts"
15
+ },
16
+ "./plugin": {
17
+ "import": "./dist/lib/plugin-api.js",
18
+ "types": "./dist/lib/plugin-api.d.ts"
19
+ }
20
+ },
21
+ "files": [
22
+ "dist"
23
+ ],
24
+ "scripts": {
25
+ "build": "tsc",
26
+ "dev": "tsc --watch",
27
+ "check": "tsc --noEmit",
28
+ "test": "vitest run",
29
+ "test:watch": "vitest",
30
+ "test:coverage": "vitest run --coverage",
31
+ "prepublishOnly": "npm run build"
32
+ },
33
+ "keywords": [
34
+ "skillstore",
35
+ "ai",
36
+ "skills",
37
+ "claude",
38
+ "claude-code",
39
+ "codex",
40
+ "cli"
41
+ ],
42
+ "author": "",
43
+ "license": "MIT",
44
+ "dependencies": {
45
+ "citty": "^0.1.6",
46
+ "consola": "^3.2.3",
47
+ "fflate": "^0.8.2"
48
+ },
49
+ "devDependencies": {
50
+ "@types/node": "^22.10.5",
51
+ "@vitest/coverage-v8": "^3.0.0",
52
+ "typescript": "^5.7.3",
53
+ "vitest": "^3.0.0"
54
+ },
55
+ "engines": {
56
+ "node": ">=18.0.0"
57
+ }
19
58
  }
package/src/index.js DELETED
@@ -1,16 +0,0 @@
1
- /**
2
- * Skillstore SDK
3
- * AI Skills marketplace for Claude Code
4
- */
5
-
6
- export function hello() {
7
- return 'Hello, World!';
8
- }
9
-
10
- export function greet(name) {
11
- return `Hello, ${name}!`;
12
- }
13
-
14
- if (import.meta.url === `file://${process.argv[1]}`) {
15
- console.log(hello());
16
- }