@voltenworks/shipui 0.1.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 (48) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +125 -0
  3. package/dist/commands/add.d.ts +2 -0
  4. package/dist/commands/add.js +153 -0
  5. package/dist/commands/add.js.map +1 -0
  6. package/dist/commands/info.d.ts +2 -0
  7. package/dist/commands/info.js +44 -0
  8. package/dist/commands/info.js.map +1 -0
  9. package/dist/commands/init.d.ts +2 -0
  10. package/dist/commands/init.js +70 -0
  11. package/dist/commands/init.js.map +1 -0
  12. package/dist/commands/list.d.ts +2 -0
  13. package/dist/commands/list.js +54 -0
  14. package/dist/commands/list.js.map +1 -0
  15. package/dist/commands/login.d.ts +2 -0
  16. package/dist/commands/login.js +40 -0
  17. package/dist/commands/login.js.map +1 -0
  18. package/dist/index.d.ts +2 -0
  19. package/dist/index.js +19 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/lib/api.d.ts +52 -0
  22. package/dist/lib/api.js +32 -0
  23. package/dist/lib/api.js.map +1 -0
  24. package/dist/lib/auth.d.ts +5 -0
  25. package/dist/lib/auth.js +24 -0
  26. package/dist/lib/auth.js.map +1 -0
  27. package/dist/lib/config.d.ts +16 -0
  28. package/dist/lib/config.js +56 -0
  29. package/dist/lib/config.js.map +1 -0
  30. package/dist/lib/css-merger.d.ts +12 -0
  31. package/dist/lib/css-merger.js +59 -0
  32. package/dist/lib/css-merger.js.map +1 -0
  33. package/dist/lib/deps.d.ts +5 -0
  34. package/dist/lib/deps.js +38 -0
  35. package/dist/lib/deps.js.map +1 -0
  36. package/dist/lib/parse.d.ts +9 -0
  37. package/dist/lib/parse.js +29 -0
  38. package/dist/lib/parse.js.map +1 -0
  39. package/dist/lib/paths.d.ts +1 -0
  40. package/dist/lib/paths.js +13 -0
  41. package/dist/lib/paths.js.map +1 -0
  42. package/dist/lib/prompts.d.ts +3 -0
  43. package/dist/lib/prompts.js +28 -0
  44. package/dist/lib/prompts.js.map +1 -0
  45. package/dist/lib/writer.d.ts +21 -0
  46. package/dist/lib/writer.js +63 -0
  47. package/dist/lib/writer.js.map +1 -0
  48. package/package.json +32 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Voltenworks
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,125 @@
1
+ # shipui
2
+
3
+ Install [ShipUI](https://voltenworks.com/shipui) components into your project. Base components are free. Premium theme styling requires a theme purchase.
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ npx shipui add button
9
+ ```
10
+
11
+ ## Commands
12
+
13
+ ### `npx shipui add <name>`
14
+
15
+ Install a base component (free, no auth required).
16
+
17
+ ```bash
18
+ npx shipui add button
19
+ npx shipui add badge
20
+ npx shipui add card
21
+ ```
22
+
23
+ ### `npx shipui add <name> --theme <slug>`
24
+
25
+ Install a component with premium theme styling.
26
+
27
+ ```bash
28
+ npx shipui add button --theme aloha
29
+ npx shipui add card --theme retro
30
+ ```
31
+
32
+ Free themes (like Candy) don't require auth. Paid themes require a purchase token via `shipui login`.
33
+
34
+ ### `npx shipui list`
35
+
36
+ List available components and themes.
37
+
38
+ ```bash
39
+ npx shipui list
40
+ npx shipui list --theme aloha
41
+ npx shipui list --category ui
42
+ npx shipui list --free
43
+ ```
44
+
45
+ ### `npx shipui login`
46
+
47
+ Authenticate with your purchase token (from your purchase confirmation email).
48
+
49
+ ```bash
50
+ npx shipui login
51
+ ```
52
+
53
+ Tokens are stored in `~/.config/shipui/config.json` and persist across all projects.
54
+
55
+ ### `npx shipui init`
56
+
57
+ Create a `shipui.json` config file for your project. Optional, sensible defaults are used without it.
58
+
59
+ ```bash
60
+ npx shipui init
61
+ ```
62
+
63
+ ### `npx shipui info <name>`
64
+
65
+ Show component details, available themes, and install commands.
66
+
67
+ ```bash
68
+ npx shipui info button
69
+ ```
70
+
71
+ ## Configuration
72
+
73
+ ### `shipui.json` (optional)
74
+
75
+ ```json
76
+ {
77
+ "$schemaVersion": 1,
78
+ "registry": "https://voltenworks.com/api/registry",
79
+ "paths": {
80
+ "components": "src/components",
81
+ "lib": "src/lib",
82
+ "css": "src/app/globals.css"
83
+ },
84
+ "importAlias": "@/"
85
+ }
86
+ ```
87
+
88
+ Without a config file, the CLI auto-detects paths from your project structure.
89
+
90
+ ## Flags
91
+
92
+ | Flag | Description |
93
+ |------|-------------|
94
+ | `--theme <slug>` | Apply theme styling |
95
+ | `--yes` | Skip all confirmation prompts |
96
+ | `--overwrite` | Overwrite existing files |
97
+ | `--dry-run` | Preview changes without writing |
98
+ | `--force` | Override theme conflict guard |
99
+ | `--token <token>` | Auth token (alternative to `shipui login`) |
100
+
101
+ ## CSS Merging
102
+
103
+ When installing with a theme, the CLI appends theme tokens and component CSS to your `globals.css` using markers:
104
+
105
+ ```css
106
+ /* shipui:theme:aloha:start */
107
+ @theme { ... }
108
+ /* shipui:theme:aloha:end */
109
+
110
+ /* shipui:component:aloha-button:start */
111
+ .btn-base { ... }
112
+ /* shipui:component:aloha-button:end */
113
+ ```
114
+
115
+ One theme per project by default. Use `--force` to mix themes.
116
+
117
+ ## Environment Variables
118
+
119
+ | Variable | Description |
120
+ |----------|-------------|
121
+ | `SHIPUI_TOKEN` | Auth token (overrides stored config) |
122
+
123
+ ## License
124
+
125
+ MIT
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare const addCommand: Command;
@@ -0,0 +1,153 @@
1
+ import { Command } from 'commander';
2
+ import chalk from 'chalk';
3
+ import path from 'path';
4
+ import { parseInput } from '../lib/parse.js';
5
+ import { getProjectConfig } from '../lib/config.js';
6
+ import { resolveToken } from '../lib/auth.js';
7
+ import { fetchComponent, fetchRegistryIndex } from '../lib/api.js';
8
+ import { writeComponentFiles, writeUtility } from '../lib/writer.js';
9
+ import { mergeCss } from '../lib/css-merger.js';
10
+ import { detectPackageManager, getMissingDeps, installDeps } from '../lib/deps.js';
11
+ import { confirmOverwrite, confirmInstallDeps } from '../lib/prompts.js';
12
+ export const addCommand = new Command('add')
13
+ .description('Add a ShipUI component to your project')
14
+ .argument('<name>', 'Component name (e.g., button, badge, card)')
15
+ .option('--theme <slug>', 'Apply theme styling (e.g., aloha, retro)')
16
+ .option('--yes', 'Skip all confirmation prompts')
17
+ .option('--overwrite', 'Overwrite existing files')
18
+ .option('--dry-run', 'Preview changes without writing files')
19
+ .option('--force', 'Override theme conflict guard')
20
+ .option('--token <token>', 'Authentication token')
21
+ .action(async (name, options) => {
22
+ try {
23
+ const config = getProjectConfig();
24
+ // Get known themes for dash-syntax parsing
25
+ let knownThemes;
26
+ try {
27
+ const index = await fetchRegistryIndex(config.registry);
28
+ const themeSlugs = new Set();
29
+ for (const c of index.components) {
30
+ for (const t of c.themes) {
31
+ themeSlugs.add(t.themeSlug);
32
+ }
33
+ }
34
+ knownThemes = [...themeSlugs];
35
+ }
36
+ catch {
37
+ // Proceed without known themes, dash syntax won't work
38
+ }
39
+ const parsed = parseInput(name, options.theme, knownThemes);
40
+ console.log();
41
+ if (options.dryRun) {
42
+ console.log(chalk.yellow('DRY RUN, no files will be written\n'));
43
+ }
44
+ // Resolve token if theme is specified
45
+ const token = parsed.themeSlug ? resolveToken(parsed.themeSlug, options.token) : null;
46
+ // Fetch component
47
+ console.log(`Fetching ${parsed.componentName}${parsed.themeSlug ? ` with ${parsed.themeSlug} theme` : ''}...`);
48
+ const manifest = await fetchComponent(config.registry, parsed.componentName, parsed.themeSlug, token);
49
+ // Handle registry dependencies (e.g., utils)
50
+ if (manifest.registryDependencies.includes('utils')) {
51
+ const utilPath = await writeUtility(config, {
52
+ overwrite: options.overwrite ?? false,
53
+ dryRun: options.dryRun ?? false,
54
+ });
55
+ if (utilPath) {
56
+ console.log(` ${chalk.green('+')} ${path.relative(process.cwd(), utilPath)}`);
57
+ }
58
+ }
59
+ // Check for existing files
60
+ if (!options.overwrite && !options.yes) {
61
+ for (const file of manifest.files) {
62
+ let targetPath;
63
+ if (file.path.startsWith('components/')) {
64
+ targetPath = path.join(process.cwd(), config.paths.components, file.path.slice('components/'.length));
65
+ }
66
+ else {
67
+ targetPath = path.join(process.cwd(), config.paths.components, file.path);
68
+ }
69
+ const fsExtra = await import('fs-extra');
70
+ if (fsExtra.default.existsSync(targetPath)) {
71
+ const confirmed = await confirmOverwrite(path.relative(process.cwd(), targetPath));
72
+ if (!confirmed) {
73
+ console.log(chalk.yellow(`Skipped ${manifest.displayName}.`));
74
+ return;
75
+ }
76
+ options.overwrite = true;
77
+ }
78
+ }
79
+ }
80
+ // Write component files
81
+ const writeResult = await writeComponentFiles(manifest.files, config, {
82
+ overwrite: options.overwrite ?? false,
83
+ dryRun: options.dryRun ?? false,
84
+ });
85
+ for (const f of writeResult.written) {
86
+ console.log(` ${chalk.green('+')} ${path.relative(process.cwd(), f)}`);
87
+ }
88
+ for (const f of writeResult.skipped) {
89
+ console.log(` ${chalk.yellow('~')} ${path.relative(process.cwd(), f)} (exists, skipped)`);
90
+ }
91
+ // Merge CSS if theme is included
92
+ if (manifest.theme) {
93
+ const cssPath = path.join(process.cwd(), config.paths.css);
94
+ const cssResults = await mergeCss(cssPath, parsed.componentName, manifest.theme, {
95
+ overwrite: options.overwrite ?? false,
96
+ force: options.force ?? false,
97
+ });
98
+ for (const r of cssResults) {
99
+ if (r.action === 'appended') {
100
+ console.log(` ${chalk.green('+')} ${r.message}`);
101
+ }
102
+ else if (r.action === 'skipped') {
103
+ console.log(` ${chalk.yellow('~')} ${r.message}`);
104
+ }
105
+ else if (r.action === 'conflict') {
106
+ console.log(` ${chalk.red('!')} ${r.message}`);
107
+ return;
108
+ }
109
+ }
110
+ }
111
+ // Auto-install npm deps
112
+ if (manifest.npmDependencies.length > 0 && !options.dryRun) {
113
+ const missing = getMissingDeps(manifest.npmDependencies);
114
+ if (missing.length > 0) {
115
+ const pm = detectPackageManager();
116
+ const shouldInstall = options.yes || await confirmInstallDeps(missing, pm);
117
+ if (shouldInstall) {
118
+ console.log(`\nInstalling dependencies with ${pm}...`);
119
+ installDeps(missing, pm);
120
+ }
121
+ else {
122
+ console.log(chalk.yellow(`\nSkipped installing: ${missing.join(', ')}`));
123
+ }
124
+ }
125
+ }
126
+ // Summary
127
+ console.log();
128
+ if (manifest.theme) {
129
+ console.log(chalk.green(`Installed ${manifest.displayName} with ${manifest.theme.themeName} styling.`));
130
+ }
131
+ else if (manifest.themeAccess === 'unauthorized') {
132
+ console.log(chalk.green(`Installed ${manifest.displayName} (base).`));
133
+ console.log(chalk.yellow(`Premium ${manifest.themeSlug?.toUpperCase()} styling requires a purchase:`));
134
+ console.log(chalk.cyan(manifest.purchaseUrl ?? ''));
135
+ console.log(`\nOr run: ${chalk.bold('npx shipui login')} after purchasing.`);
136
+ }
137
+ else {
138
+ console.log(chalk.green(`Installed ${manifest.displayName} (base).`));
139
+ console.log(`Add theme styling: ${chalk.bold(`npx shipui add ${parsed.componentName} --theme <slug>`)}`);
140
+ }
141
+ // Usage example
142
+ if (manifest.usage) {
143
+ console.log(`\nUsage:`);
144
+ console.log(chalk.dim(manifest.usage));
145
+ }
146
+ console.log();
147
+ }
148
+ catch (error) {
149
+ console.error(chalk.red(error.message));
150
+ process.exit(1);
151
+ }
152
+ });
153
+ //# sourceMappingURL=add.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add.js","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare const infoCommand: Command;
@@ -0,0 +1,44 @@
1
+ import { Command } from 'commander';
2
+ import chalk from 'chalk';
3
+ import { getProjectConfig } from '../lib/config.js';
4
+ import { fetchRegistryIndex } from '../lib/api.js';
5
+ export const infoCommand = new Command('info')
6
+ .description('Show details about a component')
7
+ .argument('<name>', 'Component name (e.g., button, badge, card)')
8
+ .action(async (name) => {
9
+ try {
10
+ const config = getProjectConfig();
11
+ const index = await fetchRegistryIndex(config.registry);
12
+ const component = index.components.find((c) => c.name === name.toLowerCase());
13
+ if (!component) {
14
+ console.log(chalk.red(`Component "${name}" not found.`));
15
+ console.log(`Run ${chalk.bold('npx shipui list')} to see available components.`);
16
+ process.exit(1);
17
+ }
18
+ console.log();
19
+ console.log(chalk.bold(component.displayName));
20
+ console.log(chalk.dim(component.category));
21
+ console.log();
22
+ console.log(component.description);
23
+ console.log();
24
+ console.log(chalk.bold('Available themes:'));
25
+ for (const theme of component.themes) {
26
+ const price = theme.free
27
+ ? chalk.green('free')
28
+ : chalk.dim(`$${theme.themePrice}`);
29
+ console.log(` ${theme.themeSlug.padEnd(14)} ${theme.themeName.padEnd(20)} ${price}`);
30
+ }
31
+ console.log();
32
+ console.log(chalk.bold('Install:'));
33
+ console.log(` ${chalk.cyan(`npx shipui add ${name}`)}`);
34
+ if (component.themes.length > 0) {
35
+ console.log(` ${chalk.cyan(`npx shipui add ${name} --theme ${component.themes[0].themeSlug}`)}`);
36
+ }
37
+ console.log();
38
+ }
39
+ catch (error) {
40
+ console.error(chalk.red(error.message));
41
+ process.exit(1);
42
+ }
43
+ });
44
+ //# sourceMappingURL=info.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"info.js","sourceRoot":"","sources":["../../src/commands/info.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare const initCommand: Command;
@@ -0,0 +1,70 @@
1
+ import { Command } from 'commander';
2
+ import chalk from 'chalk';
3
+ import fs from 'fs-extra';
4
+ import path from 'path';
5
+ import promptsLib from 'prompts';
6
+ export const initCommand = new Command('init')
7
+ .description('Initialize ShipUI configuration for your project')
8
+ .option('--yes', 'Use defaults without prompting')
9
+ .action(async (options) => {
10
+ try {
11
+ const configPath = path.join(process.cwd(), 'shipui.json');
12
+ if (fs.existsSync(configPath)) {
13
+ console.log(chalk.yellow('shipui.json already exists.'));
14
+ return;
15
+ }
16
+ const config = {
17
+ $schemaVersion: 1,
18
+ registry: 'https://voltenworks.com/api/registry',
19
+ paths: {
20
+ components: 'src/components',
21
+ lib: 'src/lib',
22
+ css: 'src/app/globals.css',
23
+ },
24
+ importAlias: '@/',
25
+ };
26
+ if (!options.yes) {
27
+ const responses = await promptsLib([
28
+ {
29
+ type: 'text',
30
+ name: 'components',
31
+ message: 'Components path:',
32
+ initial: fs.existsSync(path.join(process.cwd(), 'components')) ? 'components' : 'src/components',
33
+ },
34
+ {
35
+ type: 'text',
36
+ name: 'lib',
37
+ message: 'Lib path:',
38
+ initial: fs.existsSync(path.join(process.cwd(), 'lib')) ? 'lib' : 'src/lib',
39
+ },
40
+ {
41
+ type: 'text',
42
+ name: 'css',
43
+ message: 'CSS path:',
44
+ initial: fs.existsSync(path.join(process.cwd(), 'app/globals.css')) ? 'app/globals.css' : 'src/app/globals.css',
45
+ },
46
+ {
47
+ type: 'text',
48
+ name: 'importAlias',
49
+ message: 'Import alias:',
50
+ initial: '@/',
51
+ },
52
+ ]);
53
+ config.paths = {
54
+ components: responses.components ?? config.paths.components,
55
+ lib: responses.lib ?? config.paths.lib,
56
+ css: responses.css ?? config.paths.css,
57
+ };
58
+ config.importAlias = responses.importAlias ?? config.importAlias;
59
+ }
60
+ await fs.writeJson(configPath, config, { spaces: 2 });
61
+ console.log(chalk.green('Created shipui.json'));
62
+ console.log(`\nRun ${chalk.bold('npx shipui add button')} to install your first component.`);
63
+ console.log();
64
+ }
65
+ catch (error) {
66
+ console.error(chalk.red(error.message));
67
+ process.exit(1);
68
+ }
69
+ });
70
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare const listCommand: Command;
@@ -0,0 +1,54 @@
1
+ import { Command } from 'commander';
2
+ import chalk from 'chalk';
3
+ import { getProjectConfig } from '../lib/config.js';
4
+ import { fetchRegistryIndex } from '../lib/api.js';
5
+ export const listCommand = new Command('list')
6
+ .description('List available ShipUI components')
7
+ .option('--theme <slug>', 'Filter by theme')
8
+ .option('--category <category>', 'Filter by category (ui, section)')
9
+ .option('--free', 'Show only free theme components')
10
+ .action(async (options) => {
11
+ try {
12
+ const config = getProjectConfig();
13
+ const index = await fetchRegistryIndex(config.registry);
14
+ let components = index.components;
15
+ if (options.category) {
16
+ components = components.filter((c) => c.category === options.category);
17
+ }
18
+ if (options.theme) {
19
+ components = components.filter((c) => c.themes.some((t) => t.themeSlug === options.theme));
20
+ }
21
+ if (options.free) {
22
+ components = components.filter((c) => c.themes.some((t) => t.free));
23
+ }
24
+ if (components.length === 0) {
25
+ console.log(chalk.yellow('No components found matching your filters.'));
26
+ return;
27
+ }
28
+ console.log();
29
+ console.log(chalk.bold('Available Components'));
30
+ console.log();
31
+ // Table header
32
+ const nameWidth = 20;
33
+ const catWidth = 10;
34
+ console.log(chalk.dim('Name'.padEnd(nameWidth) + 'Type'.padEnd(catWidth) + 'Themes'));
35
+ console.log(chalk.dim('-'.repeat(70)));
36
+ for (const comp of components) {
37
+ const themes = comp.themes
38
+ .map((t) => t.free ? chalk.green(t.themeSlug) : t.themeSlug)
39
+ .join(', ');
40
+ console.log(chalk.white(comp.displayName.padEnd(nameWidth)) +
41
+ chalk.dim(comp.category.padEnd(catWidth)) +
42
+ themes);
43
+ }
44
+ console.log();
45
+ console.log(`Install: ${chalk.bold('npx shipui add <name>')}`);
46
+ console.log(`With theme: ${chalk.bold('npx shipui add <name> --theme <slug>')}`);
47
+ console.log();
48
+ }
49
+ catch (error) {
50
+ console.error(chalk.red(error.message));
51
+ process.exit(1);
52
+ }
53
+ });
54
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare const loginCommand: Command;
@@ -0,0 +1,40 @@
1
+ import { Command } from 'commander';
2
+ import chalk from 'chalk';
3
+ import { getProjectConfig, getGlobalConfig, saveGlobalConfig } from '../lib/config.js';
4
+ import { validateToken } from '../lib/api.js';
5
+ import { promptToken } from '../lib/prompts.js';
6
+ export const loginCommand = new Command('login')
7
+ .description('Authenticate with your ShipUI download token')
8
+ .option('--token <token>', 'Token to save (skips prompt)')
9
+ .action(async (options) => {
10
+ try {
11
+ const token = options.token ?? await promptToken();
12
+ if (!token) {
13
+ console.log(chalk.yellow('No token provided.'));
14
+ return;
15
+ }
16
+ const config = getProjectConfig();
17
+ console.log('Validating token...');
18
+ const result = await validateToken(config.registry, token);
19
+ if (!result.valid || !result.product) {
20
+ console.log(chalk.red('Invalid token. Please check your purchase email for the correct token.'));
21
+ process.exit(1);
22
+ }
23
+ // Save to global config
24
+ const globalConfig = getGlobalConfig();
25
+ globalConfig.tokens[result.product] = token;
26
+ saveGlobalConfig(globalConfig);
27
+ console.log();
28
+ console.log(chalk.green(`Authenticated for ${result.product.replace(/_/g, ' ').toUpperCase()}.`));
29
+ if (result.email) {
30
+ console.log(chalk.dim(`Account: ${result.email}`));
31
+ }
32
+ console.log(`\nYou can now install themed components with: ${chalk.bold('npx shipui add <name> --theme <slug>')}`);
33
+ console.log();
34
+ }
35
+ catch (error) {
36
+ console.error(chalk.red(error.message));
37
+ process.exit(1);
38
+ }
39
+ });
40
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AACtF,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAE/C,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC;KAC7C,WAAW,CAAC,8CAA8C,CAAC;KAC3D,MAAM,CAAC,iBAAiB,EAAE,8BAA8B,CAAC;KACzD,MAAM,CAAC,KAAK,EAAE,OAA2B,EAAE,EAAE;IAC5C,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,MAAM,WAAW,EAAE,CAAA;QAElD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,CAAA;YAC/C,OAAM;QACR,CAAC;QAED,MAAM,MAAM,GAAG,gBAAgB,EAAE,CAAA;QACjC,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAA;QAElC,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAA;QAE1D,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACrC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,wEAAwE,CAAC,CAAC,CAAA;YAChG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC;QAED,wBAAwB;QACxB,MAAM,YAAY,GAAG,eAAe,EAAE,CAAA;QACtC,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,KAAK,CAAA;QAC3C,gBAAgB,CAAC,YAAY,CAAC,CAAA;QAE9B,OAAO,CAAC,GAAG,EAAE,CAAA;QACb,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,qBAAqB,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,CAAA;QACjG,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;QACpD,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,iDAAiD,KAAK,CAAC,IAAI,CAAC,sCAAsC,CAAC,EAAE,CAAC,CAAA;QAClH,OAAO,CAAC,GAAG,EAAE,CAAA;IAEf,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAE,KAAe,CAAC,OAAO,CAAC,CAAC,CAAA;QAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;AACH,CAAC,CAAC,CAAA"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { addCommand } from './commands/add.js';
4
+ import { listCommand } from './commands/list.js';
5
+ import { loginCommand } from './commands/login.js';
6
+ import { initCommand } from './commands/init.js';
7
+ import { infoCommand } from './commands/info.js';
8
+ const program = new Command();
9
+ program
10
+ .name('shipui')
11
+ .description('Install ShipUI components into your project')
12
+ .version('0.1.0');
13
+ program.addCommand(addCommand);
14
+ program.addCommand(listCommand);
15
+ program.addCommand(loginCommand);
16
+ program.addCommand(initCommand);
17
+ program.addCommand(infoCommand);
18
+ program.parse();
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAEhD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAA;AAE7B,OAAO;KACJ,IAAI,CAAC,QAAQ,CAAC;KACd,WAAW,CAAC,6CAA6C,CAAC;KAC1D,OAAO,CAAC,OAAO,CAAC,CAAA;AAEnB,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,CAAA;AAC9B,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAA;AAC/B,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAA;AAChC,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAA;AAC/B,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAA;AAE/B,OAAO,CAAC,KAAK,EAAE,CAAA"}
@@ -0,0 +1,52 @@
1
+ export interface RegistryFile {
2
+ path: string;
3
+ content: string;
4
+ hash: string;
5
+ }
6
+ export interface ThemeOverlay {
7
+ themeSlug: string;
8
+ themeName: string;
9
+ themeTokens: string;
10
+ componentCss: string;
11
+ mode: 'light' | 'dark';
12
+ }
13
+ export interface ComponentManifest {
14
+ version: number;
15
+ kind: 'component';
16
+ name: string;
17
+ displayName: string;
18
+ files: RegistryFile[];
19
+ registryDependencies: string[];
20
+ npmDependencies: string[];
21
+ theme: ThemeOverlay | null;
22
+ themeAccess?: 'unauthorized';
23
+ themeSlug?: string;
24
+ purchaseUrl?: string;
25
+ usage: string;
26
+ variantSnippets: string[];
27
+ updatedAt: string;
28
+ }
29
+ export interface RegistryIndex {
30
+ version: number;
31
+ components: {
32
+ name: string;
33
+ displayName: string;
34
+ category: string;
35
+ description: string;
36
+ tags: string[];
37
+ themes: {
38
+ themeSlug: string;
39
+ themeName: string;
40
+ free: boolean;
41
+ themePrice: number;
42
+ }[];
43
+ }[];
44
+ }
45
+ export interface ValidateResponse {
46
+ valid: boolean;
47
+ product?: string;
48
+ email?: string;
49
+ }
50
+ export declare function fetchRegistryIndex(registryUrl: string): Promise<RegistryIndex>;
51
+ export declare function fetchComponent(registryUrl: string, name: string, themeSlug?: string, token?: string | null): Promise<ComponentManifest>;
52
+ export declare function validateToken(registryUrl: string, token: string): Promise<ValidateResponse>;
@@ -0,0 +1,32 @@
1
+ export async function fetchRegistryIndex(registryUrl) {
2
+ const response = await fetch(registryUrl);
3
+ if (!response.ok) {
4
+ throw new Error(`Failed to fetch registry index: ${response.status}`);
5
+ }
6
+ return response.json();
7
+ }
8
+ export async function fetchComponent(registryUrl, name, themeSlug, token) {
9
+ const url = new URL(`${registryUrl}/components/${name}`);
10
+ if (themeSlug)
11
+ url.searchParams.set('theme', themeSlug);
12
+ const headers = {};
13
+ if (token)
14
+ headers['Authorization'] = `Bearer ${token}`;
15
+ const response = await fetch(url.toString(), { headers });
16
+ if (response.status === 404) {
17
+ throw new Error(`Component "${name}" not found. Run \`npx shipui list\` to see available components.`);
18
+ }
19
+ if (!response.ok) {
20
+ throw new Error(`Registry error: ${response.status}`);
21
+ }
22
+ return response.json();
23
+ }
24
+ export async function validateToken(registryUrl, token) {
25
+ const url = `${registryUrl}/validate?token=${encodeURIComponent(token)}`;
26
+ const response = await fetch(url);
27
+ if (!response.ok) {
28
+ throw new Error(`Validation failed: ${response.status}`);
29
+ }
30
+ return response.json();
31
+ }
32
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"AAsDA,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,WAAmB;IAC1D,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,WAAW,CAAC,CAAA;IACzC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,mCAAmC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAA;IACvE,CAAC;IACD,OAAO,QAAQ,CAAC,IAAI,EAA4B,CAAA;AAClD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,WAAmB,EACnB,IAAY,EACZ,SAAkB,EAClB,KAAqB;IAErB,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,WAAW,eAAe,IAAI,EAAE,CAAC,CAAA;IACxD,IAAI,SAAS;QAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,SAAS,CAAC,CAAA;IAEvD,MAAM,OAAO,GAA2B,EAAE,CAAA;IAC1C,IAAI,KAAK;QAAE,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,KAAK,EAAE,CAAA;IAEvD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,CAAA;IACzD,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,cAAc,IAAI,mEAAmE,CAAC,CAAA;IACxG,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,mBAAmB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAA;IACvD,CAAC;IACD,OAAO,QAAQ,CAAC,IAAI,EAAgC,CAAA;AACtD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,WAAmB,EAAE,KAAa;IACpE,MAAM,GAAG,GAAG,GAAG,WAAW,mBAAmB,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAA;IACxE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAA;IACjC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,sBAAsB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAA;IAC1D,CAAC;IACD,OAAO,QAAQ,CAAC,IAAI,EAA+B,CAAA;AACrD,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Find the best token for a given theme slug.
3
+ * Priority: env var > Pro > bundle > theme-specific.
4
+ */
5
+ export declare function resolveToken(themeSlug: string, explicitToken?: string): string | null;
@@ -0,0 +1,24 @@
1
+ import { getGlobalConfig } from './config.js';
2
+ /**
3
+ * Find the best token for a given theme slug.
4
+ * Priority: env var > Pro > bundle > theme-specific.
5
+ */
6
+ export function resolveToken(themeSlug, explicitToken) {
7
+ // Explicit token from --token flag
8
+ if (explicitToken)
9
+ return explicitToken;
10
+ // Env var override
11
+ if (process.env.SHIPUI_TOKEN)
12
+ return process.env.SHIPUI_TOKEN;
13
+ const config = getGlobalConfig();
14
+ const { tokens } = config;
15
+ // Priority: Pro > bundle > theme-specific
16
+ if (tokens.theme_pro)
17
+ return tokens.theme_pro;
18
+ if (tokens[`theme_${themeSlug}_bundle`])
19
+ return tokens[`theme_${themeSlug}_bundle`];
20
+ if (tokens[`theme_${themeSlug}`])
21
+ return tokens[`theme_${themeSlug}`];
22
+ return null;
23
+ }
24
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAE7C;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,SAAiB,EAAE,aAAsB;IACpE,mCAAmC;IACnC,IAAI,aAAa;QAAE,OAAO,aAAa,CAAA;IAEvC,mBAAmB;IACnB,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,YAAY,CAAA;IAE7D,MAAM,MAAM,GAAG,eAAe,EAAE,CAAA;IAChC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAAA;IAEzB,0CAA0C;IAC1C,IAAI,MAAM,CAAC,SAAS;QAAE,OAAO,MAAM,CAAC,SAAS,CAAA;IAC7C,IAAI,MAAM,CAAC,SAAS,SAAS,SAAS,CAAC;QAAE,OAAO,MAAM,CAAC,SAAS,SAAS,SAAS,CAAC,CAAA;IACnF,IAAI,MAAM,CAAC,SAAS,SAAS,EAAE,CAAC;QAAE,OAAO,MAAM,CAAC,SAAS,SAAS,EAAE,CAAC,CAAA;IAErE,OAAO,IAAI,CAAA;AACb,CAAC"}
@@ -0,0 +1,16 @@
1
+ export interface ProjectConfig {
2
+ $schemaVersion: number;
3
+ registry: string;
4
+ paths: {
5
+ components: string;
6
+ lib: string;
7
+ css: string;
8
+ };
9
+ importAlias: string;
10
+ }
11
+ export interface GlobalConfig {
12
+ tokens: Record<string, string>;
13
+ }
14
+ export declare function getProjectConfig(): ProjectConfig;
15
+ export declare function getGlobalConfig(): GlobalConfig;
16
+ export declare function saveGlobalConfig(config: GlobalConfig): void;
@@ -0,0 +1,56 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'path';
3
+ import { getGlobalConfigPath } from './paths.js';
4
+ const DEFAULT_REGISTRY = 'https://voltenworks.com/api/registry';
5
+ const DEFAULT_PATHS = {
6
+ components: 'src/components',
7
+ lib: 'src/lib',
8
+ css: 'src/app/globals.css',
9
+ };
10
+ const DEFAULT_IMPORT_ALIAS = '@/';
11
+ export function getProjectConfig() {
12
+ const configPath = path.join(process.cwd(), 'shipui.json');
13
+ if (fs.existsSync(configPath)) {
14
+ const raw = fs.readJsonSync(configPath);
15
+ return {
16
+ $schemaVersion: raw.$schemaVersion ?? 1,
17
+ registry: raw.registry ?? DEFAULT_REGISTRY,
18
+ paths: {
19
+ components: raw.paths?.components ?? DEFAULT_PATHS.components,
20
+ lib: raw.paths?.lib ?? DEFAULT_PATHS.lib,
21
+ css: raw.paths?.css ?? DEFAULT_PATHS.css,
22
+ },
23
+ importAlias: raw.importAlias ?? DEFAULT_IMPORT_ALIAS,
24
+ };
25
+ }
26
+ // Auto-detect paths
27
+ const paths = { ...DEFAULT_PATHS };
28
+ if (fs.existsSync(path.join(process.cwd(), 'components'))) {
29
+ paths.components = 'components';
30
+ }
31
+ if (fs.existsSync(path.join(process.cwd(), 'lib'))) {
32
+ paths.lib = 'lib';
33
+ }
34
+ if (fs.existsSync(path.join(process.cwd(), 'app/globals.css'))) {
35
+ paths.css = 'app/globals.css';
36
+ }
37
+ return {
38
+ $schemaVersion: 1,
39
+ registry: DEFAULT_REGISTRY,
40
+ paths,
41
+ importAlias: DEFAULT_IMPORT_ALIAS,
42
+ };
43
+ }
44
+ export function getGlobalConfig() {
45
+ const configPath = getGlobalConfigPath();
46
+ if (fs.existsSync(configPath)) {
47
+ return fs.readJsonSync(configPath);
48
+ }
49
+ return { tokens: {} };
50
+ }
51
+ export function saveGlobalConfig(config) {
52
+ const configPath = getGlobalConfigPath();
53
+ fs.ensureDirSync(path.dirname(configPath));
54
+ fs.writeJsonSync(configPath, config, { spaces: 2 });
55
+ }
56
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,UAAU,CAAA;AACzB,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAiBhD,MAAM,gBAAgB,GAAG,sCAAsC,CAAA;AAE/D,MAAM,aAAa,GAAG;IACpB,UAAU,EAAE,gBAAgB;IAC5B,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,qBAAqB;CAC3B,CAAA;AAED,MAAM,oBAAoB,GAAG,IAAI,CAAA;AAEjC,MAAM,UAAU,gBAAgB;IAC9B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,CAAC,CAAA;IAE1D,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9B,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,CAA2B,CAAA;QACjE,OAAO;YACL,cAAc,EAAE,GAAG,CAAC,cAAc,IAAI,CAAC;YACvC,QAAQ,EAAE,GAAG,CAAC,QAAQ,IAAI,gBAAgB;YAC1C,KAAK,EAAE;gBACL,UAAU,EAAE,GAAG,CAAC,KAAK,EAAE,UAAU,IAAI,aAAa,CAAC,UAAU;gBAC7D,GAAG,EAAE,GAAG,CAAC,KAAK,EAAE,GAAG,IAAI,aAAa,CAAC,GAAG;gBACxC,GAAG,EAAE,GAAG,CAAC,KAAK,EAAE,GAAG,IAAI,aAAa,CAAC,GAAG;aACzC;YACD,WAAW,EAAE,GAAG,CAAC,WAAW,IAAI,oBAAoB;SACrD,CAAA;IACH,CAAC;IAED,oBAAoB;IACpB,MAAM,KAAK,GAAG,EAAE,GAAG,aAAa,EAAE,CAAA;IAClC,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC;QAC1D,KAAK,CAAC,UAAU,GAAG,YAAY,CAAA;IACjC,CAAC;IACD,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC;QACnD,KAAK,CAAC,GAAG,GAAG,KAAK,CAAA;IACnB,CAAC;IACD,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,iBAAiB,CAAC,CAAC,EAAE,CAAC;QAC/D,KAAK,CAAC,GAAG,GAAG,iBAAiB,CAAA;IAC/B,CAAC;IAED,OAAO;QACL,cAAc,EAAE,CAAC;QACjB,QAAQ,EAAE,gBAAgB;QAC1B,KAAK;QACL,WAAW,EAAE,oBAAoB;KAClC,CAAA;AACH,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,MAAM,UAAU,GAAG,mBAAmB,EAAE,CAAA;IAExC,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9B,OAAO,EAAE,CAAC,YAAY,CAAC,UAAU,CAAiB,CAAA;IACpD,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,CAAA;AACvB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAoB;IACnD,MAAM,UAAU,GAAG,mBAAmB,EAAE,CAAA;IACxC,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAA;IAC1C,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAA;AACrD,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { ThemeOverlay } from './api.js';
2
+ export interface MergeResult {
3
+ action: 'appended' | 'skipped' | 'conflict';
4
+ message: string;
5
+ }
6
+ /**
7
+ * Merge theme tokens and component CSS into globals.css using markers.
8
+ */
9
+ export declare function mergeCss(cssPath: string, componentName: string, theme: ThemeOverlay, options: {
10
+ overwrite: boolean;
11
+ force: boolean;
12
+ }): Promise<MergeResult[]>;
@@ -0,0 +1,59 @@
1
+ import fs from 'fs-extra';
2
+ const THEME_START = (slug) => `/* shipui:theme:${slug}:start */`;
3
+ const THEME_END = (slug) => `/* shipui:theme:${slug}:end */`;
4
+ const COMPONENT_START = (id) => `/* shipui:component:${id}:start */`;
5
+ const COMPONENT_END = (id) => `/* shipui:component:${id}:end */`;
6
+ /**
7
+ * Merge theme tokens and component CSS into globals.css using markers.
8
+ */
9
+ export async function mergeCss(cssPath, componentName, theme, options) {
10
+ const results = [];
11
+ let css = '';
12
+ if (await fs.pathExists(cssPath)) {
13
+ css = await fs.readFile(cssPath, 'utf-8');
14
+ }
15
+ const componentId = `${theme.themeSlug}-${componentName}`;
16
+ // Check for theme block
17
+ const themeStart = THEME_START(theme.themeSlug);
18
+ const hasThemeBlock = css.includes(themeStart);
19
+ // Check for a DIFFERENT theme block (conflict)
20
+ const otherThemeMatch = css.match(/\/\* shipui:theme:(\w+):start \*\//);
21
+ if (otherThemeMatch && otherThemeMatch[1] !== theme.themeSlug && !options.force) {
22
+ results.push({
23
+ action: 'conflict',
24
+ message: `Theme "${otherThemeMatch[1]}" is already installed. Use --force to override with "${theme.themeSlug}" theme tokens.`,
25
+ });
26
+ return results;
27
+ }
28
+ // Add theme tokens
29
+ if (!hasThemeBlock && theme.themeTokens) {
30
+ const themeBlock = `\n${themeStart}\n${theme.themeTokens}\n${THEME_END(theme.themeSlug)}\n`;
31
+ css += themeBlock;
32
+ results.push({ action: 'appended', message: `Added ${theme.themeName} theme tokens` });
33
+ }
34
+ else if (hasThemeBlock) {
35
+ results.push({ action: 'skipped', message: `${theme.themeName} theme tokens already installed` });
36
+ }
37
+ // Add component CSS
38
+ const componentStart = COMPONENT_START(componentId);
39
+ const hasComponentBlock = css.includes(componentStart);
40
+ if (!hasComponentBlock && theme.componentCss) {
41
+ const componentBlock = `\n${componentStart}\n${theme.componentCss}\n${COMPONENT_END(componentId)}\n`;
42
+ css += componentBlock;
43
+ results.push({ action: 'appended', message: `Added ${componentName} CSS rules` });
44
+ }
45
+ else if (hasComponentBlock && !options.overwrite) {
46
+ results.push({ action: 'skipped', message: `${componentName} CSS already installed` });
47
+ }
48
+ else if (hasComponentBlock && options.overwrite) {
49
+ // Replace existing block
50
+ const startIdx = css.indexOf(componentStart);
51
+ const endMarker = COMPONENT_END(componentId);
52
+ const endIdx = css.indexOf(endMarker) + endMarker.length;
53
+ css = css.slice(0, startIdx) + `${componentStart}\n${theme.componentCss}\n${endMarker}` + css.slice(endIdx);
54
+ results.push({ action: 'appended', message: `Replaced ${componentName} CSS rules` });
55
+ }
56
+ await fs.writeFile(cssPath, css, 'utf-8');
57
+ return results;
58
+ }
59
+ //# sourceMappingURL=css-merger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"css-merger.js","sourceRoot":"","sources":["../../src/lib/css-merger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ type PackageManager = 'npm' | 'yarn' | 'pnpm' | 'bun';
2
+ export declare function detectPackageManager(): PackageManager;
3
+ export declare function getMissingDeps(deps: string[]): string[];
4
+ export declare function installDeps(deps: string[], pm: PackageManager): void;
5
+ export {};
@@ -0,0 +1,38 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { execSync } from 'child_process';
4
+ export function detectPackageManager() {
5
+ const cwd = process.cwd();
6
+ if (fs.existsSync(path.join(cwd, 'bun.lockb')) || fs.existsSync(path.join(cwd, 'bun.lock')))
7
+ return 'bun';
8
+ if (fs.existsSync(path.join(cwd, 'pnpm-lock.yaml')))
9
+ return 'pnpm';
10
+ if (fs.existsSync(path.join(cwd, 'yarn.lock')))
11
+ return 'yarn';
12
+ return 'npm';
13
+ }
14
+ export function getMissingDeps(deps) {
15
+ const missing = [];
16
+ for (const dep of deps) {
17
+ try {
18
+ const pkgPath = path.join(process.cwd(), 'node_modules', dep, 'package.json');
19
+ if (!fs.existsSync(pkgPath)) {
20
+ missing.push(dep);
21
+ }
22
+ }
23
+ catch {
24
+ missing.push(dep);
25
+ }
26
+ }
27
+ return missing;
28
+ }
29
+ export function installDeps(deps, pm) {
30
+ const installCmd = {
31
+ npm: `npm install ${deps.join(' ')}`,
32
+ yarn: `yarn add ${deps.join(' ')}`,
33
+ pnpm: `pnpm add ${deps.join(' ')}`,
34
+ bun: `bun add ${deps.join(' ')}`,
35
+ };
36
+ execSync(installCmd[pm], { stdio: 'inherit', cwd: process.cwd() });
37
+ }
38
+ //# sourceMappingURL=deps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deps.js","sourceRoot":"","sources":["../../src/lib/deps.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAA;AACnB,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAIxC,MAAM,UAAU,oBAAoB;IAClC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAA;IAEzB,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;QAAE,OAAO,KAAK,CAAA;IACzG,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC;QAAE,OAAO,MAAM,CAAA;IAClE,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;QAAE,OAAO,MAAM,CAAA;IAC7D,OAAO,KAAK,CAAA;AACd,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAc;IAC3C,MAAM,OAAO,GAAa,EAAE,CAAA;IAC5B,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,GAAG,EAAE,cAAc,CAAC,CAAA;YAC7E,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC5B,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YACnB,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QACnB,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAA;AAChB,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAc,EAAE,EAAkB;IAC5D,MAAM,UAAU,GAAG;QACjB,GAAG,EAAE,eAAe,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;QACpC,IAAI,EAAE,YAAY,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;QAClC,IAAI,EAAE,YAAY,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;QAClC,GAAG,EAAE,WAAW,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;KACjC,CAAA;IAED,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;AACpE,CAAC"}
@@ -0,0 +1,9 @@
1
+ export interface ParsedInput {
2
+ componentName: string;
3
+ themeSlug?: string;
4
+ }
5
+ /**
6
+ * Parse input into { componentName, themeSlug? }.
7
+ * Supports: "button", "aloha/button", "aloha-button" (with known theme list)
8
+ */
9
+ export declare function parseInput(input: string, themeFlag?: string, knownThemes?: string[]): ParsedInput;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Parse input into { componentName, themeSlug? }.
3
+ * Supports: "button", "aloha/button", "aloha-button" (with known theme list)
4
+ */
5
+ export function parseInput(input, themeFlag, knownThemes) {
6
+ // --theme flag takes priority
7
+ if (themeFlag) {
8
+ return { componentName: input.toLowerCase(), themeSlug: themeFlag.toLowerCase() };
9
+ }
10
+ // Check for slash syntax: "aloha/button"
11
+ if (input.includes('/')) {
12
+ const [theme, ...rest] = input.split('/');
13
+ return { componentName: rest.join('/').toLowerCase(), themeSlug: theme.toLowerCase() };
14
+ }
15
+ // Check for dash syntax: "aloha-button" (only if we know the theme list)
16
+ if (knownThemes) {
17
+ for (const theme of knownThemes) {
18
+ if (input.toLowerCase().startsWith(`${theme}-`)) {
19
+ const componentName = input.slice(theme.length + 1).toLowerCase();
20
+ if (componentName) {
21
+ return { componentName, themeSlug: theme };
22
+ }
23
+ }
24
+ }
25
+ }
26
+ // Plain component name
27
+ return { componentName: input.toLowerCase() };
28
+ }
29
+ //# sourceMappingURL=parse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.js","sourceRoot":"","sources":["../../src/lib/parse.ts"],"names":[],"mappings":"AAKA;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,KAAa,EAAE,SAAkB,EAAE,WAAsB;IAClF,8BAA8B;IAC9B,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,EAAE,aAAa,EAAE,KAAK,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,SAAS,CAAC,WAAW,EAAE,EAAE,CAAA;IACnF,CAAC;IAED,yCAAyC;IACzC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QACzC,OAAO,EAAE,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,KAAK,CAAC,WAAW,EAAE,EAAE,CAAA;IACxF,CAAC;IAED,yEAAyE;IACzE,IAAI,WAAW,EAAE,CAAC;QAChB,KAAK,MAAM,KAAK,IAAI,WAAW,EAAE,CAAC;YAChC,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,GAAG,KAAK,GAAG,CAAC,EAAE,CAAC;gBAChD,MAAM,aAAa,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,CAAA;gBACjE,IAAI,aAAa,EAAE,CAAC;oBAClB,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,KAAK,EAAE,CAAA;gBAC5C,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,uBAAuB;IACvB,OAAO,EAAE,aAAa,EAAE,KAAK,CAAC,WAAW,EAAE,EAAE,CAAA;AAC/C,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function getGlobalConfigPath(): string;
@@ -0,0 +1,13 @@
1
+ import path from 'path';
2
+ import os from 'os';
3
+ export function getGlobalConfigPath() {
4
+ const platform = os.platform();
5
+ if (platform === 'win32') {
6
+ const appData = process.env.APPDATA ?? path.join(os.homedir(), 'AppData', 'Roaming');
7
+ return path.join(appData, 'shipui', 'config.json');
8
+ }
9
+ // macOS and Linux
10
+ const configHome = process.env.XDG_CONFIG_HOME ?? path.join(os.homedir(), '.config');
11
+ return path.join(configHome, 'shipui', 'config.json');
12
+ }
13
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/lib/paths.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,EAAE,MAAM,IAAI,CAAA;AAEnB,MAAM,UAAU,mBAAmB;IACjC,MAAM,QAAQ,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAA;IAE9B,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,SAAS,CAAC,CAAA;QACpF,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAA;IACpD,CAAC;IAED,kBAAkB;IAClB,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAA;IACpF,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAA;AACvD,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function confirmOverwrite(filePath: string): Promise<boolean>;
2
+ export declare function confirmInstallDeps(deps: string[], pm: string): Promise<boolean>;
3
+ export declare function promptToken(): Promise<string>;
@@ -0,0 +1,28 @@
1
+ import promptsLib from 'prompts';
2
+ export async function confirmOverwrite(filePath) {
3
+ const response = await promptsLib({
4
+ type: 'confirm',
5
+ name: 'overwrite',
6
+ message: `${filePath} already exists. Overwrite?`,
7
+ initial: false,
8
+ });
9
+ return response.overwrite === true;
10
+ }
11
+ export async function confirmInstallDeps(deps, pm) {
12
+ const response = await promptsLib({
13
+ type: 'confirm',
14
+ name: 'install',
15
+ message: `Missing dependencies: ${deps.join(', ')}. Install with ${pm}?`,
16
+ initial: true,
17
+ });
18
+ return response.install === true;
19
+ }
20
+ export async function promptToken() {
21
+ const response = await promptsLib({
22
+ type: 'text',
23
+ name: 'token',
24
+ message: 'Paste your ShipUI download token (from purchase email):',
25
+ });
26
+ return response.token ?? '';
27
+ }
28
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../src/lib/prompts.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,SAAS,CAAA;AAEhC,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,QAAgB;IACrD,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC;QAChC,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,GAAG,QAAQ,6BAA6B;QACjD,OAAO,EAAE,KAAK;KACf,CAAC,CAAA;IACF,OAAO,QAAQ,CAAC,SAAS,KAAK,IAAI,CAAA;AACpC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,IAAc,EAAE,EAAU;IACjE,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC;QAChC,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,yBAAyB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,GAAG;QACxE,OAAO,EAAE,IAAI;KACd,CAAC,CAAA;IACF,OAAO,QAAQ,CAAC,OAAO,KAAK,IAAI,CAAA;AAClC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC;QAChC,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,yDAAyD;KACnE,CAAC,CAAA;IACF,OAAO,QAAQ,CAAC,KAAK,IAAI,EAAE,CAAA;AAC7B,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { RegistryFile } from './api.js';
2
+ import type { ProjectConfig } from './config.js';
3
+ export interface WriteResult {
4
+ written: string[];
5
+ skipped: string[];
6
+ }
7
+ /**
8
+ * Write component files to the user's project.
9
+ * Rewrites import aliases from @/ to the project's configured alias.
10
+ */
11
+ export declare function writeComponentFiles(files: RegistryFile[], config: ProjectConfig, options: {
12
+ overwrite: boolean;
13
+ dryRun: boolean;
14
+ }): Promise<WriteResult>;
15
+ /**
16
+ * Write the cn() utility to the project's lib directory.
17
+ */
18
+ export declare function writeUtility(config: ProjectConfig, options: {
19
+ overwrite: boolean;
20
+ dryRun: boolean;
21
+ }): Promise<string | null>;
@@ -0,0 +1,63 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'path';
3
+ /**
4
+ * Write component files to the user's project.
5
+ * Rewrites import aliases from @/ to the project's configured alias.
6
+ */
7
+ export async function writeComponentFiles(files, config, options) {
8
+ const result = { written: [], skipped: [] };
9
+ for (const file of files) {
10
+ // Map file path: "components/ui/Button.tsx" -> "<config.paths.components>/ui/Button.tsx"
11
+ let targetPath;
12
+ if (file.path.startsWith('components/')) {
13
+ targetPath = path.join(process.cwd(), config.paths.components, file.path.slice('components/'.length));
14
+ }
15
+ else if (file.path.startsWith('lib/')) {
16
+ targetPath = path.join(process.cwd(), config.paths.lib, file.path.slice('lib/'.length));
17
+ }
18
+ else {
19
+ targetPath = path.join(process.cwd(), config.paths.components, file.path);
20
+ }
21
+ // Check if file exists
22
+ if (fs.existsSync(targetPath) && !options.overwrite) {
23
+ result.skipped.push(targetPath);
24
+ continue;
25
+ }
26
+ if (options.dryRun) {
27
+ result.written.push(targetPath);
28
+ continue;
29
+ }
30
+ // Rewrite import aliases
31
+ let content = file.content;
32
+ if (config.importAlias !== '@/') {
33
+ content = content.replace(/@\//g, config.importAlias);
34
+ }
35
+ // Ensure directory exists and write
36
+ await fs.ensureDir(path.dirname(targetPath));
37
+ await fs.writeFile(targetPath, content, 'utf-8');
38
+ result.written.push(targetPath);
39
+ }
40
+ return result;
41
+ }
42
+ /**
43
+ * Write the cn() utility to the project's lib directory.
44
+ */
45
+ export async function writeUtility(config, options) {
46
+ const utilPath = path.join(process.cwd(), config.paths.lib, 'utils.ts');
47
+ if (fs.existsSync(utilPath) && !options.overwrite) {
48
+ return null;
49
+ }
50
+ const utilContent = `import { type ClassValue, clsx } from 'clsx'
51
+ import { twMerge } from 'tailwind-merge'
52
+
53
+ export function cn(...inputs: ClassValue[]): string {
54
+ return twMerge(clsx(inputs))
55
+ }
56
+ `;
57
+ if (options.dryRun)
58
+ return utilPath;
59
+ await fs.ensureDir(path.dirname(utilPath));
60
+ await fs.writeFile(utilPath, utilContent, 'utf-8');
61
+ return utilPath;
62
+ }
63
+ //# sourceMappingURL=writer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"writer.js","sourceRoot":"","sources":["../../src/lib/writer.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "@voltenworks/shipui",
3
+ "version": "0.1.0",
4
+ "description": "Install ShipUI components into your project",
5
+ "bin": {
6
+ "shipui": "./dist/index.js"
7
+ },
8
+ "type": "module",
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "dev": "tsc --watch",
12
+ "prepublishOnly": "tsc"
13
+ },
14
+ "files": ["dist"],
15
+ "dependencies": {
16
+ "commander": "^12.0.0",
17
+ "prompts": "^2.4.2",
18
+ "chalk": "^5.3.0",
19
+ "fs-extra": "^11.2.0"
20
+ },
21
+ "devDependencies": {
22
+ "@types/prompts": "^2.4.9",
23
+ "@types/fs-extra": "^11.0.4",
24
+ "typescript": "^5.4.0"
25
+ },
26
+ "keywords": ["shipui", "components", "nextjs", "tailwind", "cli"],
27
+ "license": "MIT",
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "https://github.com/voltenworks/shipui-cli"
31
+ }
32
+ }