bunkit-cli 1.0.1 → 1.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.
- package/dist/index.js +697 -449
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -11215,7 +11215,7 @@ function normalizeString(path, allowAboveRoot) {
|
|
|
11215
11215
|
}
|
|
11216
11216
|
return res;
|
|
11217
11217
|
}
|
|
11218
|
-
var _DRIVE_LETTER_START_RE, _UNC_REGEX, _IS_ABSOLUTE_RE, _DRIVE_LETTER_RE, normalize = function(path) {
|
|
11218
|
+
var _DRIVE_LETTER_START_RE, _UNC_REGEX, _IS_ABSOLUTE_RE, _DRIVE_LETTER_RE, _ROOT_FOLDER_RE, sep = "/", delimiter = ":", normalize = function(path) {
|
|
11219
11219
|
if (path.length === 0) {
|
|
11220
11220
|
return ".";
|
|
11221
11221
|
}
|
|
@@ -11280,24 +11280,95 @@ var _DRIVE_LETTER_START_RE, _UNC_REGEX, _IS_ABSOLUTE_RE, _DRIVE_LETTER_RE, norma
|
|
|
11280
11280
|
return resolvedPath.length > 0 ? resolvedPath : ".";
|
|
11281
11281
|
}, isAbsolute = function(p2) {
|
|
11282
11282
|
return _IS_ABSOLUTE_RE.test(p2);
|
|
11283
|
+
}, toNamespacedPath = function(p2) {
|
|
11284
|
+
return normalizeWindowsPath(p2);
|
|
11285
|
+
}, _EXTNAME_RE, extname = function(p2) {
|
|
11286
|
+
const match = _EXTNAME_RE.exec(normalizeWindowsPath(p2));
|
|
11287
|
+
return match && match[1] || "";
|
|
11288
|
+
}, relative = function(from, to) {
|
|
11289
|
+
const _from = resolve(from).replace(_ROOT_FOLDER_RE, "$1").split("/");
|
|
11290
|
+
const _to = resolve(to).replace(_ROOT_FOLDER_RE, "$1").split("/");
|
|
11291
|
+
if (_to[0][1] === ":" && _from[0][1] === ":" && _from[0] !== _to[0]) {
|
|
11292
|
+
return _to.join("/");
|
|
11293
|
+
}
|
|
11294
|
+
const _fromCopy = [..._from];
|
|
11295
|
+
for (const segment of _fromCopy) {
|
|
11296
|
+
if (_to[0] !== segment) {
|
|
11297
|
+
break;
|
|
11298
|
+
}
|
|
11299
|
+
_from.shift();
|
|
11300
|
+
_to.shift();
|
|
11301
|
+
}
|
|
11302
|
+
return [..._from.map(() => ".."), ..._to].join("/");
|
|
11283
11303
|
}, dirname = function(p2) {
|
|
11284
11304
|
const segments = normalizeWindowsPath(p2).replace(/\/$/, "").split("/").slice(0, -1);
|
|
11285
11305
|
if (segments.length === 1 && _DRIVE_LETTER_RE.test(segments[0])) {
|
|
11286
11306
|
segments[0] += "/";
|
|
11287
11307
|
}
|
|
11288
11308
|
return segments.join("/") || (isAbsolute(p2) ? "/" : ".");
|
|
11309
|
+
}, format = function(p2) {
|
|
11310
|
+
const segments = [p2.root, p2.dir, p2.base ?? p2.name + p2.ext].filter(Boolean);
|
|
11311
|
+
return normalizeWindowsPath(p2.root ? resolve(...segments) : segments.join("/"));
|
|
11289
11312
|
}, basename = function(p2, extension) {
|
|
11290
11313
|
const lastSegment = normalizeWindowsPath(p2).split("/").pop();
|
|
11291
11314
|
return extension && lastSegment.endsWith(extension) ? lastSegment.slice(0, -extension.length) : lastSegment;
|
|
11292
|
-
}
|
|
11315
|
+
}, parse = function(p2) {
|
|
11316
|
+
const root = normalizeWindowsPath(p2).split("/").shift() || "/";
|
|
11317
|
+
const base = basename(p2);
|
|
11318
|
+
const extension = extname(base);
|
|
11319
|
+
return {
|
|
11320
|
+
root,
|
|
11321
|
+
dir: dirname(p2),
|
|
11322
|
+
base,
|
|
11323
|
+
ext: extension,
|
|
11324
|
+
name: base.slice(0, base.length - extension.length)
|
|
11325
|
+
};
|
|
11326
|
+
}, path;
|
|
11293
11327
|
var init_pathe_ff20891b = __esm(() => {
|
|
11294
11328
|
_DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
|
|
11295
11329
|
_UNC_REGEX = /^[/\\]{2}/;
|
|
11296
11330
|
_IS_ABSOLUTE_RE = /^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Za-z]:[/\\]/;
|
|
11297
11331
|
_DRIVE_LETTER_RE = /^[A-Za-z]:$/;
|
|
11332
|
+
_ROOT_FOLDER_RE = /^\/([A-Za-z]:)?$/;
|
|
11333
|
+
_EXTNAME_RE = /.(\.[^./]+)$/;
|
|
11334
|
+
path = {
|
|
11335
|
+
__proto__: null,
|
|
11336
|
+
basename,
|
|
11337
|
+
delimiter,
|
|
11338
|
+
dirname,
|
|
11339
|
+
extname,
|
|
11340
|
+
format,
|
|
11341
|
+
isAbsolute,
|
|
11342
|
+
join,
|
|
11343
|
+
normalize,
|
|
11344
|
+
normalizeString,
|
|
11345
|
+
parse,
|
|
11346
|
+
relative,
|
|
11347
|
+
resolve,
|
|
11348
|
+
sep,
|
|
11349
|
+
toNamespacedPath
|
|
11350
|
+
};
|
|
11298
11351
|
});
|
|
11299
11352
|
|
|
11300
11353
|
// ../../node_modules/pathe/dist/index.mjs
|
|
11354
|
+
var exports_dist = {};
|
|
11355
|
+
__export(exports_dist, {
|
|
11356
|
+
toNamespacedPath: () => toNamespacedPath,
|
|
11357
|
+
sep: () => sep,
|
|
11358
|
+
resolve: () => resolve,
|
|
11359
|
+
relative: () => relative,
|
|
11360
|
+
parse: () => parse,
|
|
11361
|
+
normalizeString: () => normalizeString,
|
|
11362
|
+
normalize: () => normalize,
|
|
11363
|
+
join: () => join,
|
|
11364
|
+
isAbsolute: () => isAbsolute,
|
|
11365
|
+
format: () => format,
|
|
11366
|
+
extname: () => extname,
|
|
11367
|
+
dirname: () => dirname,
|
|
11368
|
+
delimiter: () => delimiter,
|
|
11369
|
+
default: () => path,
|
|
11370
|
+
basename: () => basename
|
|
11371
|
+
});
|
|
11301
11372
|
var init_dist = __esm(() => {
|
|
11302
11373
|
init_pathe_ff20891b();
|
|
11303
11374
|
});
|
|
@@ -18563,9 +18634,11 @@ async function isGitAvailable() {
|
|
|
18563
18634
|
}
|
|
18564
18635
|
}
|
|
18565
18636
|
async function initGit(cwd2) {
|
|
18566
|
-
await execa("git", ["init"], { cwd: cwd2 });
|
|
18637
|
+
await execa("git", ["init", "--initial-branch=main"], { cwd: cwd2 });
|
|
18567
18638
|
await execa("git", ["add", "-A"], { cwd: cwd2 });
|
|
18568
|
-
|
|
18639
|
+
try {
|
|
18640
|
+
await execa("git", ["commit", "-m", "Initial commit from bunkit", "--no-verify"], { cwd: cwd2 });
|
|
18641
|
+
} catch {}
|
|
18569
18642
|
}
|
|
18570
18643
|
async function isGitRepository(cwd2) {
|
|
18571
18644
|
try {
|
|
@@ -23042,17 +23115,24 @@ var init_monorepo = __esm(() => {
|
|
|
23042
23115
|
});
|
|
23043
23116
|
|
|
23044
23117
|
// ../core/src/presets.ts
|
|
23118
|
+
function getPresetsDir() {
|
|
23119
|
+
return join(process.env.HOME || process.env.USERPROFILE || ".", ".bunkit");
|
|
23120
|
+
}
|
|
23121
|
+
function getPresetsFile() {
|
|
23122
|
+
return join(getPresetsDir(), "presets.json");
|
|
23123
|
+
}
|
|
23045
23124
|
async function loadCustomPresets() {
|
|
23046
23125
|
try {
|
|
23047
|
-
|
|
23048
|
-
|
|
23126
|
+
const presetsDir = getPresetsDir();
|
|
23127
|
+
await ensureDirectory(presetsDir);
|
|
23128
|
+
const content = await readFile(getPresetsFile());
|
|
23049
23129
|
return JSON.parse(content);
|
|
23050
23130
|
} catch (error) {
|
|
23051
23131
|
return {};
|
|
23052
23132
|
}
|
|
23053
23133
|
}
|
|
23054
23134
|
async function saveCustomPreset(preset) {
|
|
23055
|
-
await ensureDirectory(
|
|
23135
|
+
await ensureDirectory(getPresetsDir());
|
|
23056
23136
|
const presets = await loadCustomPresets();
|
|
23057
23137
|
const existing = presets[preset.name];
|
|
23058
23138
|
presets[preset.name] = {
|
|
@@ -23060,7 +23140,7 @@ async function saveCustomPreset(preset) {
|
|
|
23060
23140
|
createdAt: existing?.createdAt || new Date().toISOString(),
|
|
23061
23141
|
updatedAt: new Date().toISOString()
|
|
23062
23142
|
};
|
|
23063
|
-
await writeFile(
|
|
23143
|
+
await writeFile(getPresetsFile(), JSON.stringify(presets, null, 2));
|
|
23064
23144
|
}
|
|
23065
23145
|
async function deleteCustomPreset(name) {
|
|
23066
23146
|
const presets = await loadCustomPresets();
|
|
@@ -23068,7 +23148,7 @@ async function deleteCustomPreset(name) {
|
|
|
23068
23148
|
return false;
|
|
23069
23149
|
}
|
|
23070
23150
|
delete presets[name];
|
|
23071
|
-
await writeFile(
|
|
23151
|
+
await writeFile(getPresetsFile(), JSON.stringify(presets, null, 2));
|
|
23072
23152
|
return true;
|
|
23073
23153
|
}
|
|
23074
23154
|
async function getCustomPreset(name) {
|
|
@@ -23079,12 +23159,9 @@ async function listCustomPresets() {
|
|
|
23079
23159
|
const presets = await loadCustomPresets();
|
|
23080
23160
|
return Object.values(presets);
|
|
23081
23161
|
}
|
|
23082
|
-
var PRESETS_DIR, PRESETS_FILE;
|
|
23083
23162
|
var init_presets = __esm(() => {
|
|
23084
23163
|
init_dist();
|
|
23085
23164
|
init_fs();
|
|
23086
|
-
PRESETS_DIR = join(process.env.HOME || process.env.USERPROFILE || ".", ".bunkit");
|
|
23087
|
-
PRESETS_FILE = join(PRESETS_DIR, "presets.json");
|
|
23088
23165
|
});
|
|
23089
23166
|
|
|
23090
23167
|
// ../core/src/index.ts
|
|
@@ -26245,77 +26322,116 @@ var themes = {
|
|
|
26245
26322
|
};
|
|
26246
26323
|
function generateThemeCSS(theme, customRadius) {
|
|
26247
26324
|
const radius = customRadius || theme.light.radius;
|
|
26248
|
-
return `@
|
|
26249
|
-
|
|
26250
|
-
|
|
26251
|
-
|
|
26252
|
-
|
|
26253
|
-
|
|
26254
|
-
|
|
26255
|
-
|
|
26256
|
-
|
|
26257
|
-
|
|
26258
|
-
|
|
26259
|
-
|
|
26260
|
-
|
|
26261
|
-
|
|
26262
|
-
|
|
26263
|
-
|
|
26264
|
-
|
|
26265
|
-
|
|
26266
|
-
|
|
26267
|
-
|
|
26268
|
-
|
|
26269
|
-
|
|
26270
|
-
|
|
26271
|
-
|
|
26272
|
-
|
|
26273
|
-
|
|
26274
|
-
|
|
26275
|
-
|
|
26276
|
-
|
|
26277
|
-
|
|
26278
|
-
|
|
26279
|
-
|
|
26280
|
-
|
|
26281
|
-
|
|
26282
|
-
|
|
26283
|
-
}
|
|
26284
|
-
|
|
26285
|
-
|
|
26286
|
-
|
|
26287
|
-
|
|
26288
|
-
|
|
26289
|
-
|
|
26290
|
-
|
|
26291
|
-
|
|
26292
|
-
|
|
26293
|
-
|
|
26294
|
-
|
|
26295
|
-
|
|
26296
|
-
|
|
26297
|
-
|
|
26298
|
-
|
|
26299
|
-
|
|
26300
|
-
|
|
26301
|
-
|
|
26302
|
-
|
|
26303
|
-
|
|
26304
|
-
|
|
26305
|
-
|
|
26306
|
-
|
|
26307
|
-
|
|
26308
|
-
|
|
26309
|
-
|
|
26310
|
-
|
|
26311
|
-
|
|
26312
|
-
|
|
26313
|
-
|
|
26314
|
-
|
|
26315
|
-
|
|
26316
|
-
|
|
26317
|
-
|
|
26318
|
-
}
|
|
26325
|
+
return `@import "tailwindcss";
|
|
26326
|
+
@import "tw-animate-css";
|
|
26327
|
+
|
|
26328
|
+
:root {
|
|
26329
|
+
--radius: ${radius};
|
|
26330
|
+
--background: ${theme.light.background};
|
|
26331
|
+
--foreground: ${theme.light.foreground};
|
|
26332
|
+
--card: ${theme.light.card};
|
|
26333
|
+
--card-foreground: ${theme.light.cardForeground};
|
|
26334
|
+
--popover: ${theme.light.popover};
|
|
26335
|
+
--popover-foreground: ${theme.light.popoverForeground};
|
|
26336
|
+
--primary: ${theme.light.primary};
|
|
26337
|
+
--primary-foreground: ${theme.light.primaryForeground};
|
|
26338
|
+
--secondary: ${theme.light.secondary};
|
|
26339
|
+
--secondary-foreground: ${theme.light.secondaryForeground};
|
|
26340
|
+
--muted: ${theme.light.muted};
|
|
26341
|
+
--muted-foreground: ${theme.light.mutedForeground};
|
|
26342
|
+
--accent: ${theme.light.accent};
|
|
26343
|
+
--accent-foreground: ${theme.light.accentForeground};
|
|
26344
|
+
--destructive: ${theme.light.destructive};
|
|
26345
|
+
--destructive-foreground: ${theme.light.destructiveForeground};
|
|
26346
|
+
--border: ${theme.light.border};
|
|
26347
|
+
--input: ${theme.light.input};
|
|
26348
|
+
--ring: ${theme.light.ring};
|
|
26349
|
+
--chart-1: ${theme.light.chart1};
|
|
26350
|
+
--chart-2: ${theme.light.chart2};
|
|
26351
|
+
--chart-3: ${theme.light.chart3};
|
|
26352
|
+
--chart-4: ${theme.light.chart4};
|
|
26353
|
+
--chart-5: ${theme.light.chart5};
|
|
26354
|
+
--sidebar: ${theme.light.sidebar};
|
|
26355
|
+
--sidebar-foreground: ${theme.light.sidebarForeground};
|
|
26356
|
+
--sidebar-primary: ${theme.light.sidebarPrimary};
|
|
26357
|
+
--sidebar-primary-foreground: ${theme.light.sidebarPrimaryForeground};
|
|
26358
|
+
--sidebar-accent: ${theme.light.sidebarAccent};
|
|
26359
|
+
--sidebar-accent-foreground: ${theme.light.sidebarAccentForeground};
|
|
26360
|
+
--sidebar-border: ${theme.light.sidebarBorder};
|
|
26361
|
+
--sidebar-ring: ${theme.light.sidebarRing};
|
|
26362
|
+
}
|
|
26363
|
+
|
|
26364
|
+
.dark {
|
|
26365
|
+
--background: ${theme.dark.background};
|
|
26366
|
+
--foreground: ${theme.dark.foreground};
|
|
26367
|
+
--card: ${theme.dark.card};
|
|
26368
|
+
--card-foreground: ${theme.dark.cardForeground};
|
|
26369
|
+
--popover: ${theme.dark.popover};
|
|
26370
|
+
--popover-foreground: ${theme.dark.popoverForeground};
|
|
26371
|
+
--primary: ${theme.dark.primary};
|
|
26372
|
+
--primary-foreground: ${theme.dark.primaryForeground};
|
|
26373
|
+
--secondary: ${theme.dark.secondary};
|
|
26374
|
+
--secondary-foreground: ${theme.dark.secondaryForeground};
|
|
26375
|
+
--muted: ${theme.dark.muted};
|
|
26376
|
+
--muted-foreground: ${theme.dark.mutedForeground};
|
|
26377
|
+
--accent: ${theme.dark.accent};
|
|
26378
|
+
--accent-foreground: ${theme.dark.accentForeground};
|
|
26379
|
+
--destructive: ${theme.dark.destructive};
|
|
26380
|
+
--destructive-foreground: ${theme.dark.destructiveForeground};
|
|
26381
|
+
--border: ${theme.dark.border};
|
|
26382
|
+
--input: ${theme.dark.input};
|
|
26383
|
+
--ring: ${theme.dark.ring};
|
|
26384
|
+
--chart-1: ${theme.dark.chart1};
|
|
26385
|
+
--chart-2: ${theme.dark.chart2};
|
|
26386
|
+
--chart-3: ${theme.dark.chart3};
|
|
26387
|
+
--chart-4: ${theme.dark.chart4};
|
|
26388
|
+
--chart-5: ${theme.dark.chart5};
|
|
26389
|
+
--sidebar: ${theme.dark.sidebar};
|
|
26390
|
+
--sidebar-foreground: ${theme.dark.sidebarForeground};
|
|
26391
|
+
--sidebar-primary: ${theme.dark.sidebarPrimary};
|
|
26392
|
+
--sidebar-primary-foreground: ${theme.dark.sidebarPrimaryForeground};
|
|
26393
|
+
--sidebar-accent: ${theme.dark.sidebarAccent};
|
|
26394
|
+
--sidebar-accent-foreground: ${theme.dark.sidebarAccentForeground};
|
|
26395
|
+
--sidebar-border: ${theme.dark.sidebarBorder};
|
|
26396
|
+
--sidebar-ring: ${theme.dark.sidebarRing};
|
|
26397
|
+
}
|
|
26398
|
+
|
|
26399
|
+
@theme inline {
|
|
26400
|
+
--color-background: var(--background);
|
|
26401
|
+
--color-foreground: var(--foreground);
|
|
26402
|
+
--color-card: var(--card);
|
|
26403
|
+
--color-card-foreground: var(--card-foreground);
|
|
26404
|
+
--color-popover: var(--popover);
|
|
26405
|
+
--color-popover-foreground: var(--popover-foreground);
|
|
26406
|
+
--color-primary: var(--primary);
|
|
26407
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
26408
|
+
--color-secondary: var(--secondary);
|
|
26409
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
|
26410
|
+
--color-muted: var(--muted);
|
|
26411
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
26412
|
+
--color-accent: var(--accent);
|
|
26413
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
26414
|
+
--color-destructive: var(--destructive);
|
|
26415
|
+
--color-destructive-foreground: var(--destructive-foreground);
|
|
26416
|
+
--color-border: var(--border);
|
|
26417
|
+
--color-input: var(--input);
|
|
26418
|
+
--color-ring: var(--ring);
|
|
26419
|
+
--color-chart-1: var(--chart-1);
|
|
26420
|
+
--color-chart-2: var(--chart-2);
|
|
26421
|
+
--color-chart-3: var(--chart-3);
|
|
26422
|
+
--color-chart-4: var(--chart-4);
|
|
26423
|
+
--color-chart-5: var(--chart-5);
|
|
26424
|
+
--color-sidebar: var(--sidebar);
|
|
26425
|
+
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
26426
|
+
--color-sidebar-primary: var(--sidebar-primary);
|
|
26427
|
+
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
26428
|
+
--color-sidebar-accent: var(--sidebar-accent);
|
|
26429
|
+
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
26430
|
+
--color-sidebar-border: var(--sidebar-border);
|
|
26431
|
+
--color-sidebar-ring: var(--sidebar-ring);
|
|
26432
|
+
--radius-lg: var(--radius);
|
|
26433
|
+
--radius-md: calc(var(--radius) - 2px);
|
|
26434
|
+
--radius-sm: calc(var(--radius) - 4px);
|
|
26319
26435
|
}
|
|
26320
26436
|
|
|
26321
26437
|
@layer base {
|
|
@@ -26333,7 +26449,6 @@ function generateThemeCSS(theme, customRadius) {
|
|
|
26333
26449
|
init_execa();
|
|
26334
26450
|
init_dist();
|
|
26335
26451
|
init_src();
|
|
26336
|
-
init_src();
|
|
26337
26452
|
var DEFAULT_SHADCN_COMPONENTS = [
|
|
26338
26453
|
"button",
|
|
26339
26454
|
"card"
|
|
@@ -26341,50 +26456,107 @@ var DEFAULT_SHADCN_COMPONENTS = [
|
|
|
26341
26456
|
async function installShadcnComponents(projectPath, components, options = {}) {
|
|
26342
26457
|
const cwd2 = options.cwd || projectPath;
|
|
26343
26458
|
const stdio = options.silent ? "pipe" : "inherit";
|
|
26459
|
+
const targetCwd = options.isMonorepo ? join(projectPath, "packages/ui") : cwd2;
|
|
26344
26460
|
try {
|
|
26345
26461
|
await execa("bunx", ["shadcn@latest", "add", ...components], {
|
|
26346
|
-
cwd:
|
|
26347
|
-
stdio
|
|
26462
|
+
cwd: targetCwd,
|
|
26463
|
+
stdio,
|
|
26464
|
+
env: {
|
|
26465
|
+
...process.env,
|
|
26466
|
+
BUN_INSTALL_LINKER: "isolated"
|
|
26467
|
+
}
|
|
26348
26468
|
});
|
|
26469
|
+
if (options.isMonorepo) {
|
|
26470
|
+
await updateComponentsIndex(join(targetCwd, "src/components"));
|
|
26471
|
+
}
|
|
26349
26472
|
} catch (error) {
|
|
26350
26473
|
try {
|
|
26351
26474
|
await execa("npx", ["shadcn@latest", "add", ...components], {
|
|
26352
|
-
cwd:
|
|
26475
|
+
cwd: targetCwd,
|
|
26353
26476
|
stdio
|
|
26354
26477
|
});
|
|
26478
|
+
if (options.isMonorepo) {
|
|
26479
|
+
await updateComponentsIndex(join(targetCwd, "src/components"));
|
|
26480
|
+
}
|
|
26355
26481
|
} catch (fallbackError) {
|
|
26356
|
-
logger.warn(`Could not install shadcn components automatically. You can install them manually with: bunx shadcn@latest add ${components.join(" ")}`);
|
|
26482
|
+
logger.warn(`Could not install shadcn components automatically. You can install them manually with: cd ${targetCwd} && bunx shadcn@latest add ${components.join(" ")}`);
|
|
26483
|
+
throw fallbackError;
|
|
26484
|
+
}
|
|
26485
|
+
}
|
|
26486
|
+
}
|
|
26487
|
+
async function updateComponentsIndex(componentsDir) {
|
|
26488
|
+
const indexPath = join(componentsDir, "index.ts");
|
|
26489
|
+
const uiDir = join(componentsDir, "ui");
|
|
26490
|
+
try {
|
|
26491
|
+
const { existsSync } = await import("fs");
|
|
26492
|
+
if (!existsSync(uiDir)) {
|
|
26493
|
+
logger.debug(`UI directory does not exist: ${uiDir}`);
|
|
26494
|
+
return;
|
|
26495
|
+
}
|
|
26496
|
+
const { readdir } = await import("fs/promises");
|
|
26497
|
+
const entries = await readdir(uiDir, { withFileTypes: true });
|
|
26498
|
+
const componentFiles = entries.filter((entry) => entry.isFile() && entry.name.endsWith(".tsx")).map((entry) => entry.name.replace(".tsx", "")).sort();
|
|
26499
|
+
if (componentFiles.length === 0) {
|
|
26500
|
+
logger.debug(`No component files found in ${uiDir}`);
|
|
26501
|
+
return;
|
|
26357
26502
|
}
|
|
26503
|
+
const exports = componentFiles.map((comp) => `export * from './ui/${comp}';`).join(`
|
|
26504
|
+
`);
|
|
26505
|
+
const newContent = `// Auto-generated exports for shadcn/ui components
|
|
26506
|
+
// Components are installed via: bunkit add component --components [name]
|
|
26507
|
+
// Or: bunx shadcn@latest add [name] (from packages/ui directory)
|
|
26508
|
+
|
|
26509
|
+
${exports}
|
|
26510
|
+
`;
|
|
26511
|
+
await writeFile(indexPath, newContent);
|
|
26512
|
+
logger.debug(`Updated components index with ${componentFiles.length} components`);
|
|
26513
|
+
} catch (error) {
|
|
26514
|
+
logger.warn(`Could not update components index file: ${error.message}`);
|
|
26358
26515
|
}
|
|
26359
26516
|
}
|
|
26360
26517
|
async function installDefaultShadcnComponents(projectPath, options = {}) {
|
|
26361
26518
|
if (options.skipDefaults) {
|
|
26362
26519
|
return;
|
|
26363
26520
|
}
|
|
26521
|
+
const isMonorepo = options.isMonorepo ?? (await import("fs")).existsSync((await Promise.resolve().then(() => (init_dist(), exports_dist))).join(projectPath, "packages/ui/components.json"));
|
|
26364
26522
|
logger.step("Installing default shadcn/ui components...");
|
|
26365
26523
|
try {
|
|
26366
26524
|
await installShadcnComponents(projectPath, [...DEFAULT_SHADCN_COMPONENTS], {
|
|
26367
26525
|
silent: options.silent,
|
|
26368
|
-
cwd: projectPath
|
|
26526
|
+
cwd: projectPath,
|
|
26527
|
+
isMonorepo
|
|
26369
26528
|
});
|
|
26370
26529
|
logger.success("Default components installed");
|
|
26371
26530
|
} catch (error) {
|
|
26372
|
-
|
|
26531
|
+
const manualCommand = isMonorepo ? "cd packages/ui && bunx shadcn@latest add button card" : "bunx shadcn@latest add button card";
|
|
26532
|
+
logger.warn(`Could not install default components automatically. Install them manually with: ${manualCommand}`);
|
|
26373
26533
|
}
|
|
26374
26534
|
}
|
|
26375
|
-
async function createShadcnExample(projectPath, isMonorepo = false) {
|
|
26535
|
+
async function createShadcnExample(projectPath, isMonorepo = false, packageName) {
|
|
26376
26536
|
const examplePath = isMonorepo ? join(projectPath, "apps/web/src/components/example.tsx") : join(projectPath, "src/components/example.tsx");
|
|
26377
|
-
const
|
|
26378
|
-
|
|
26379
|
-
import { Button } from "@/components/ui/button"
|
|
26380
|
-
import {
|
|
26537
|
+
const buttonImport = isMonorepo ? `import { Button } from "@workspace/ui/components/ui/button"` : `import { Button } from "@/components/ui/button"`;
|
|
26538
|
+
const cardImport = isMonorepo ? `import {
|
|
26381
26539
|
Card,
|
|
26382
26540
|
CardContent,
|
|
26383
26541
|
CardDescription,
|
|
26384
26542
|
CardFooter,
|
|
26385
26543
|
CardHeader,
|
|
26386
26544
|
CardTitle,
|
|
26387
|
-
} from "
|
|
26545
|
+
} from "@workspace/ui/components/ui/card"` : `import {
|
|
26546
|
+
Card,
|
|
26547
|
+
CardContent,
|
|
26548
|
+
CardDescription,
|
|
26549
|
+
CardFooter,
|
|
26550
|
+
CardHeader,
|
|
26551
|
+
CardTitle,
|
|
26552
|
+
} from "@/components/ui/card"`;
|
|
26553
|
+
const importHint = isMonorepo ? `// In monorepo, components are imported from @workspace/ui package
|
|
26554
|
+
// This ensures all apps share the same UI components and Tailwind CSS v4 config` : `// Components are imported using the @ alias configured in tsconfig.json`;
|
|
26555
|
+
const exampleContent = `"use client"
|
|
26556
|
+
|
|
26557
|
+
${importHint}
|
|
26558
|
+
${buttonImport}
|
|
26559
|
+
${cardImport}
|
|
26388
26560
|
|
|
26389
26561
|
/**
|
|
26390
26562
|
* Example component showcasing shadcn/ui components
|
|
@@ -26404,7 +26576,7 @@ export function ExampleComponent() {
|
|
|
26404
26576
|
</CardHeader>
|
|
26405
26577
|
<CardContent>
|
|
26406
26578
|
<p className="text-sm text-muted-foreground">
|
|
26407
|
-
You can start building your UI by importing components from @/components/ui
|
|
26579
|
+
${isMonorepo ? "Components are shared via @workspace/ui package. Add more components with: bunkit add component --components [name]" : "You can start building your UI by importing components from @/components/ui"}
|
|
26408
26580
|
</p>
|
|
26409
26581
|
</CardContent>
|
|
26410
26582
|
<CardFooter className="flex gap-2">
|
|
@@ -26427,9 +26599,77 @@ init_dist();
|
|
|
26427
26599
|
init_src();
|
|
26428
26600
|
async function createShadcnDocs(projectPath, isMonorepo = false, context) {
|
|
26429
26601
|
const docsPath = isMonorepo ? join(projectPath, "packages/ui/SHADCN.md") : join(projectPath, "SHADCN.md");
|
|
26602
|
+
const monorepoSection = isMonorepo ? `
|
|
26603
|
+
## \uD83C\uDFD7\uFE0F Bun Monorepo Setup
|
|
26604
|
+
|
|
26605
|
+
This is a **Bun monorepo** with shared UI components in \`packages/ui\`. All shadcn/ui components are installed here and shared across all apps in the monorepo.
|
|
26606
|
+
|
|
26607
|
+
### Monorepo Structure
|
|
26608
|
+
|
|
26609
|
+
\`\`\`
|
|
26610
|
+
packages/
|
|
26611
|
+
ui/ # Shared UI package
|
|
26612
|
+
src/
|
|
26613
|
+
components/ui/ # shadcn/ui components
|
|
26614
|
+
styles/ # Tailwind CSS v4 configuration
|
|
26615
|
+
lib/utils.ts # Utility functions (cn helper)
|
|
26616
|
+
components.json # shadcn/ui configuration
|
|
26617
|
+
\`\`\`
|
|
26618
|
+
|
|
26619
|
+
### Adding Components (Monorepo)
|
|
26620
|
+
|
|
26621
|
+
Components are installed in \`packages/ui\` and automatically shared:
|
|
26622
|
+
|
|
26623
|
+
\`\`\`bash
|
|
26624
|
+
# From project root - bunkit handles monorepo detection
|
|
26625
|
+
bunkit add component --components button
|
|
26626
|
+
|
|
26627
|
+
# Or directly in packages/ui directory
|
|
26628
|
+
cd packages/ui
|
|
26629
|
+
bunx shadcn@latest add button
|
|
26630
|
+
\`\`\`
|
|
26631
|
+
|
|
26632
|
+
### Using Components (Monorepo)
|
|
26633
|
+
|
|
26634
|
+
Import components using Bun workspace aliases:
|
|
26635
|
+
|
|
26636
|
+
\`\`\`tsx
|
|
26637
|
+
// Recommended: Use @workspace/ui alias (Bun workspace resolution)
|
|
26638
|
+
import { Button } from "@workspace/ui/components/ui/button"
|
|
26639
|
+
import { Card, CardContent, CardHeader, CardTitle } from "@workspace/ui/components/ui/card"
|
|
26640
|
+
|
|
26641
|
+
// Or use the package name directly
|
|
26642
|
+
import { Button } from "@${context?.packageName || "workspace"}/ui/components/ui/button"
|
|
26643
|
+
\`\`\`
|
|
26644
|
+
|
|
26645
|
+
### Tailwind CSS v4 Configuration
|
|
26646
|
+
|
|
26647
|
+
Tailwind CSS v4 is configured in \`packages/ui/src/styles/globals.css\` using CSS-first configuration:
|
|
26648
|
+
- \u2705 No \`tailwind.config.ts\` needed (Tailwind v4 feature)
|
|
26649
|
+
- \u2705 Uses \`@theme inline\` directive for design tokens
|
|
26650
|
+
- \u2705 OKLCH color space (modern color format)
|
|
26651
|
+
- \u2705 Shared across all apps via workspace imports
|
|
26652
|
+
|
|
26653
|
+
All apps import the CSS from the UI package:
|
|
26654
|
+
\`\`\`css
|
|
26655
|
+
/* In apps/web/src/app/globals.css */
|
|
26656
|
+
@import "../../../packages/ui/src/styles/globals.css";
|
|
26657
|
+
\`\`\`
|
|
26658
|
+
|
|
26659
|
+
### Bun Workspace Features
|
|
26660
|
+
|
|
26661
|
+
This setup leverages Bun 1.3 workspace features:
|
|
26662
|
+
- **Catalogs**: Dependency versions managed in root \`package.json\` catalog
|
|
26663
|
+
- **Isolated Installs**: Each package only sees its declared dependencies
|
|
26664
|
+
- **Workspace Aliases**: Use \`@workspace/ui\` for internal imports
|
|
26665
|
+
- **Fast Resolution**: Bun's native workspace resolution
|
|
26666
|
+
|
|
26667
|
+
` : "";
|
|
26430
26668
|
const docsContent = `# shadcn/ui Guide
|
|
26431
26669
|
|
|
26432
|
-
This project uses [shadcn/ui](https://ui.shadcn.com) - a collection of re-usable components built with Radix UI and Tailwind CSS.
|
|
26670
|
+
This project uses [shadcn/ui](https://ui.shadcn.com) - a collection of re-usable components built with Radix UI and Tailwind CSS v4.
|
|
26671
|
+
|
|
26672
|
+
${monorepoSection}
|
|
26433
26673
|
|
|
26434
26674
|
## \uD83D\uDE80 Quick Start
|
|
26435
26675
|
|
|
@@ -26451,14 +26691,40 @@ bunkit add component --all
|
|
|
26451
26691
|
Or use the official shadcn CLI directly:
|
|
26452
26692
|
|
|
26453
26693
|
\`\`\`bash
|
|
26454
|
-
bunx shadcn@latest add button
|
|
26455
|
-
bunx shadcn@latest add card
|
|
26456
|
-
bunx shadcn@latest add input
|
|
26694
|
+
${isMonorepo ? "cd packages/ui && " : ""}bunx shadcn@latest add button
|
|
26695
|
+
${isMonorepo ? "cd packages/ui && " : ""}bunx shadcn@latest add card
|
|
26696
|
+
${isMonorepo ? "cd packages/ui && " : ""}bunx shadcn@latest add input
|
|
26457
26697
|
\`\`\`
|
|
26458
26698
|
|
|
26459
26699
|
### Using Components
|
|
26460
26700
|
|
|
26461
|
-
Import components from the
|
|
26701
|
+
${isMonorepo ? `Import components from the \`@workspace/ui\` package:
|
|
26702
|
+
|
|
26703
|
+
\`\`\`tsx
|
|
26704
|
+
import { Button } from "@workspace/ui/components/ui/button"
|
|
26705
|
+
import {
|
|
26706
|
+
Card,
|
|
26707
|
+
CardContent,
|
|
26708
|
+
CardDescription,
|
|
26709
|
+
CardFooter,
|
|
26710
|
+
CardHeader,
|
|
26711
|
+
CardTitle,
|
|
26712
|
+
} from "@workspace/ui/components/ui/card"
|
|
26713
|
+
|
|
26714
|
+
export function MyComponent() {
|
|
26715
|
+
return (
|
|
26716
|
+
<Card>
|
|
26717
|
+
<CardHeader>
|
|
26718
|
+
<CardTitle>Hello</CardTitle>
|
|
26719
|
+
<CardDescription>World</CardDescription>
|
|
26720
|
+
</CardHeader>
|
|
26721
|
+
<CardContent>
|
|
26722
|
+
<Button>Click me</Button>
|
|
26723
|
+
</CardContent>
|
|
26724
|
+
</Card>
|
|
26725
|
+
)
|
|
26726
|
+
}
|
|
26727
|
+
\`\`\`` : `Import components from the \`@/components/ui\` path:
|
|
26462
26728
|
|
|
26463
26729
|
\`\`\`tsx
|
|
26464
26730
|
import { Button } from "@/components/ui/button"
|
|
@@ -26484,7 +26750,7 @@ export function MyComponent() {
|
|
|
26484
26750
|
</Card>
|
|
26485
26751
|
)
|
|
26486
26752
|
}
|
|
26487
|
-
|
|
26753
|
+
\`\`\``}
|
|
26488
26754
|
|
|
26489
26755
|
## \uD83D\uDCDA Available Components
|
|
26490
26756
|
|
|
@@ -26515,20 +26781,34 @@ Your project is configured with:
|
|
|
26515
26781
|
Edit the CSS variables in \`${isMonorepo ? "packages/ui/src/styles/globals.css" : "src/app/globals.css"}\`:
|
|
26516
26782
|
|
|
26517
26783
|
\`\`\`css
|
|
26518
|
-
|
|
26519
|
-
|
|
26520
|
-
|
|
26521
|
-
|
|
26522
|
-
|
|
26523
|
-
|
|
26524
|
-
|
|
26784
|
+
/* Tailwind CSS v4 uses CSS-first configuration */
|
|
26785
|
+
@import "tailwindcss";
|
|
26786
|
+
@import "tw-animate-css";
|
|
26787
|
+
|
|
26788
|
+
:root {
|
|
26789
|
+
--radius: 0.625rem;
|
|
26790
|
+
--background: oklch(...);
|
|
26791
|
+
--foreground: oklch(...);
|
|
26792
|
+
/* ... */
|
|
26793
|
+
}
|
|
26794
|
+
|
|
26795
|
+
@theme inline {
|
|
26796
|
+
--color-background: var(--background);
|
|
26797
|
+
--color-foreground: var(--foreground);
|
|
26798
|
+
/* ... */
|
|
26525
26799
|
}
|
|
26526
26800
|
\`\`\`
|
|
26527
26801
|
|
|
26802
|
+
**Note**: Tailwind CSS v4 uses CSS-first configuration. No \`tailwind.config.ts\` is needed - all configuration is done via CSS using the \`@theme inline\` directive.
|
|
26803
|
+
|
|
26528
26804
|
### Component Customization
|
|
26529
26805
|
|
|
26530
26806
|
Components are copied directly into your project at \`${isMonorepo ? "packages/ui/src/components/ui" : "src/components/ui"}\`. You can modify them directly - they're YOUR code!
|
|
26531
26807
|
|
|
26808
|
+
${isMonorepo ? `
|
|
26809
|
+
**Monorepo Tip**: Since components are in \`packages/ui\`, changes automatically propagate to all apps that import them. This ensures consistent UI across your entire monorepo.
|
|
26810
|
+
` : ""}
|
|
26811
|
+
|
|
26532
26812
|
## \uD83D\uDCD6 Documentation
|
|
26533
26813
|
|
|
26534
26814
|
- [Official shadcn/ui Docs](https://ui.shadcn.com)
|
|
@@ -26638,119 +26918,6 @@ ${shadcnCss}`;
|
|
|
26638
26918
|
}
|
|
26639
26919
|
await writeFile(globalsCssPath, globalsCss);
|
|
26640
26920
|
}
|
|
26641
|
-
const tailwindConfigPath = join(projectPath, "tailwind.config.ts");
|
|
26642
|
-
let tailwindConfig = "";
|
|
26643
|
-
try {
|
|
26644
|
-
tailwindConfig = await Bun.file(tailwindConfigPath).text();
|
|
26645
|
-
} catch {}
|
|
26646
|
-
if (tailwindConfig && !tailwindConfig.includes("hsl(var(--background))")) {
|
|
26647
|
-
const shadcnTheme = ` theme: {
|
|
26648
|
-
extend: {
|
|
26649
|
-
colors: {
|
|
26650
|
-
border: "hsl(var(--border))",
|
|
26651
|
-
input: "hsl(var(--input))",
|
|
26652
|
-
ring: "hsl(var(--ring))",
|
|
26653
|
-
background: "hsl(var(--background))",
|
|
26654
|
-
foreground: "hsl(var(--foreground))",
|
|
26655
|
-
primary: {
|
|
26656
|
-
DEFAULT: "hsl(var(--primary))",
|
|
26657
|
-
foreground: "hsl(var(--primary-foreground))",
|
|
26658
|
-
},
|
|
26659
|
-
secondary: {
|
|
26660
|
-
DEFAULT: "hsl(var(--secondary))",
|
|
26661
|
-
foreground: "hsl(var(--secondary-foreground))",
|
|
26662
|
-
},
|
|
26663
|
-
destructive: {
|
|
26664
|
-
DEFAULT: "hsl(var(--destructive))",
|
|
26665
|
-
foreground: "hsl(var(--destructive-foreground))",
|
|
26666
|
-
},
|
|
26667
|
-
muted: {
|
|
26668
|
-
DEFAULT: "hsl(var(--muted))",
|
|
26669
|
-
foreground: "hsl(var(--muted-foreground))",
|
|
26670
|
-
},
|
|
26671
|
-
accent: {
|
|
26672
|
-
DEFAULT: "hsl(var(--accent))",
|
|
26673
|
-
foreground: "hsl(var(--accent-foreground))",
|
|
26674
|
-
},
|
|
26675
|
-
popover: {
|
|
26676
|
-
DEFAULT: "hsl(var(--popover))",
|
|
26677
|
-
foreground: "hsl(var(--popover-foreground))",
|
|
26678
|
-
},
|
|
26679
|
-
card: {
|
|
26680
|
-
DEFAULT: "hsl(var(--card))",
|
|
26681
|
-
foreground: "hsl(var(--card-foreground))",
|
|
26682
|
-
},
|
|
26683
|
-
},
|
|
26684
|
-
borderRadius: {
|
|
26685
|
-
lg: "var(--radius)",
|
|
26686
|
-
md: "calc(var(--radius) - 2px)",
|
|
26687
|
-
sm: "calc(var(--radius) - 4px)",
|
|
26688
|
-
},
|
|
26689
|
-
},
|
|
26690
|
-
},`;
|
|
26691
|
-
if (tailwindConfig.includes("theme:")) {
|
|
26692
|
-
const updatedConfig = tailwindConfig.replace(/theme:\s*\{[^}]*\}/s, shadcnTheme.trim());
|
|
26693
|
-
await writeFile(tailwindConfigPath, updatedConfig);
|
|
26694
|
-
} else {
|
|
26695
|
-
const updatedConfig = tailwindConfig.replace(/(\s*)(plugins:.*?)(\n\s*\};)/s, `$1$2$1${shadcnTheme}$3`);
|
|
26696
|
-
await writeFile(tailwindConfigPath, updatedConfig);
|
|
26697
|
-
}
|
|
26698
|
-
} else if (!tailwindConfig) {
|
|
26699
|
-
const newTailwindConfig = `import type { Config } from 'tailwindcss';
|
|
26700
|
-
|
|
26701
|
-
const config: Config = {
|
|
26702
|
-
content: ['./src/**/*.{js,ts,jsx,tsx,mdx}'],
|
|
26703
|
-
theme: {
|
|
26704
|
-
extend: {
|
|
26705
|
-
colors: {
|
|
26706
|
-
border: "hsl(var(--border))",
|
|
26707
|
-
input: "hsl(var(--input))",
|
|
26708
|
-
ring: "hsl(var(--ring))",
|
|
26709
|
-
background: "hsl(var(--background))",
|
|
26710
|
-
foreground: "hsl(var(--foreground))",
|
|
26711
|
-
primary: {
|
|
26712
|
-
DEFAULT: "hsl(var(--primary))",
|
|
26713
|
-
foreground: "hsl(var(--primary-foreground))",
|
|
26714
|
-
},
|
|
26715
|
-
secondary: {
|
|
26716
|
-
DEFAULT: "hsl(var(--secondary))",
|
|
26717
|
-
foreground: "hsl(var(--secondary-foreground))",
|
|
26718
|
-
},
|
|
26719
|
-
destructive: {
|
|
26720
|
-
DEFAULT: "hsl(var(--destructive))",
|
|
26721
|
-
foreground: "hsl(var(--destructive-foreground))",
|
|
26722
|
-
},
|
|
26723
|
-
muted: {
|
|
26724
|
-
DEFAULT: "hsl(var(--muted))",
|
|
26725
|
-
foreground: "hsl(var(--muted-foreground))",
|
|
26726
|
-
},
|
|
26727
|
-
accent: {
|
|
26728
|
-
DEFAULT: "hsl(var(--accent))",
|
|
26729
|
-
foreground: "hsl(var(--accent-foreground))",
|
|
26730
|
-
},
|
|
26731
|
-
popover: {
|
|
26732
|
-
DEFAULT: "hsl(var(--popover))",
|
|
26733
|
-
foreground: "hsl(var(--popover-foreground))",
|
|
26734
|
-
},
|
|
26735
|
-
card: {
|
|
26736
|
-
DEFAULT: "hsl(var(--card))",
|
|
26737
|
-
foreground: "hsl(var(--card-foreground))",
|
|
26738
|
-
},
|
|
26739
|
-
},
|
|
26740
|
-
borderRadius: {
|
|
26741
|
-
lg: "var(--radius)",
|
|
26742
|
-
md: "calc(var(--radius) - 2px)",
|
|
26743
|
-
sm: "calc(var(--radius) - 4px)",
|
|
26744
|
-
},
|
|
26745
|
-
},
|
|
26746
|
-
},
|
|
26747
|
-
plugins: [],
|
|
26748
|
-
};
|
|
26749
|
-
|
|
26750
|
-
export default config;
|
|
26751
|
-
`;
|
|
26752
|
-
await writeFile(tailwindConfigPath, newTailwindConfig);
|
|
26753
|
-
}
|
|
26754
26921
|
if (context.install !== false) {}
|
|
26755
26922
|
await createShadcnExample(projectPath, false);
|
|
26756
26923
|
await createShadcnDocs(projectPath, false, context);
|
|
@@ -26772,10 +26939,13 @@ async function setupShadcnMonorepo(projectPath, context) {
|
|
|
26772
26939
|
main: "./src/index.ts",
|
|
26773
26940
|
types: "./src/index.ts",
|
|
26774
26941
|
exports: {
|
|
26942
|
+
".": "./src/index.ts",
|
|
26775
26943
|
"./components": "./src/components/index.ts",
|
|
26944
|
+
"./components/*": "./src/components/ui/*/index.ts",
|
|
26776
26945
|
"./lib/utils": "./src/lib/utils.ts",
|
|
26777
26946
|
"./hooks": "./src/hooks/index.ts",
|
|
26778
|
-
"./styles": "./src/styles/globals.css"
|
|
26947
|
+
"./styles": "./src/styles/globals.css",
|
|
26948
|
+
"./components/ui/*": "./src/components/ui/*/index.ts"
|
|
26779
26949
|
},
|
|
26780
26950
|
dependencies: {
|
|
26781
26951
|
"@radix-ui/react-slot": "catalog:",
|
|
@@ -26804,11 +26974,11 @@ async function setupShadcnMonorepo(projectPath, context) {
|
|
|
26804
26974
|
},
|
|
26805
26975
|
iconLibrary: "lucide",
|
|
26806
26976
|
aliases: {
|
|
26807
|
-
components: "
|
|
26808
|
-
utils: "
|
|
26809
|
-
hooks: "
|
|
26810
|
-
lib: "
|
|
26811
|
-
ui: "
|
|
26977
|
+
components: "@/components",
|
|
26978
|
+
utils: "@/lib/utils",
|
|
26979
|
+
hooks: "@/hooks",
|
|
26980
|
+
lib: "@/lib",
|
|
26981
|
+
ui: "@/components/ui"
|
|
26812
26982
|
}
|
|
26813
26983
|
};
|
|
26814
26984
|
await writeFile(join(projectPath, "packages/ui/components.json"), JSON.stringify(uiComponentsJson, null, 2));
|
|
@@ -26821,9 +26991,27 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
26821
26991
|
`;
|
|
26822
26992
|
await writeFile(join(projectPath, "packages/ui/src/lib/utils.ts"), uiUtilsContent);
|
|
26823
26993
|
const uiComponentsIndex = `// Export shadcn/ui components here
|
|
26824
|
-
// Components
|
|
26994
|
+
// Components are installed in src/components/ui/ and exported here
|
|
26995
|
+
// Add components using: bunkit add component --components button,card,input
|
|
26996
|
+
// Or directly: bunx shadcn@latest add [component] (from packages/ui directory)
|
|
26997
|
+
|
|
26998
|
+
// Components will be automatically exported here when added
|
|
26825
26999
|
`;
|
|
26826
27000
|
await writeFile(join(projectPath, "packages/ui/src/components/index.ts"), uiComponentsIndex);
|
|
27001
|
+
const uiIndexContent = `// Main entry point for @${packageName}/ui package
|
|
27002
|
+
// This package provides shared shadcn/ui components and Tailwind CSS v4 configuration
|
|
27003
|
+
|
|
27004
|
+
// Export utilities
|
|
27005
|
+
export * from './lib/utils';
|
|
27006
|
+
|
|
27007
|
+
// Export hooks (if any)
|
|
27008
|
+
export * from './hooks';
|
|
27009
|
+
|
|
27010
|
+
// Components are exported from individual files
|
|
27011
|
+
// Import like: import { Button } from '@${packageName}/ui/components/ui/button'
|
|
27012
|
+
// Or use the re-export: import { Button } from '@workspace/ui/components/ui/button'
|
|
27013
|
+
`;
|
|
27014
|
+
await writeFile(join(projectPath, "packages/ui/src/index.ts"), uiIndexContent);
|
|
26827
27015
|
const uiHooksIndex = `// Export custom hooks here
|
|
26828
27016
|
`;
|
|
26829
27017
|
await writeFile(join(projectPath, "packages/ui/src/hooks/index.ts"), uiHooksIndex);
|
|
@@ -26844,212 +27032,81 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
26844
27032
|
resolveJsonModule: true,
|
|
26845
27033
|
isolatedModules: true,
|
|
26846
27034
|
jsx: "react-jsx",
|
|
26847
|
-
types: ["react", "react-dom"]
|
|
27035
|
+
types: ["react", "react-dom"],
|
|
27036
|
+
paths: {
|
|
27037
|
+
"@/*": ["./src/*"]
|
|
27038
|
+
}
|
|
26848
27039
|
},
|
|
26849
27040
|
include: ["src/**/*"],
|
|
26850
27041
|
exclude: ["node_modules"]
|
|
26851
27042
|
};
|
|
26852
27043
|
await writeFile(join(projectPath, "packages/ui/tsconfig.json"), JSON.stringify(uiTsconfig, null, 2));
|
|
26853
|
-
|
|
26854
|
-
|
|
26855
|
-
|
|
26856
|
-
|
|
26857
|
-
style,
|
|
26858
|
-
rsc: true,
|
|
26859
|
-
tsx: true,
|
|
26860
|
-
tailwind: {
|
|
26861
|
-
config: "",
|
|
26862
|
-
css: "../../packages/ui/src/styles/globals.css",
|
|
26863
|
-
baseColor,
|
|
26864
|
-
cssVariables: true
|
|
26865
|
-
},
|
|
26866
|
-
iconLibrary: "lucide",
|
|
26867
|
-
aliases: {
|
|
26868
|
-
components: "@/components",
|
|
26869
|
-
hooks: "@/hooks",
|
|
26870
|
-
lib: "@/lib",
|
|
26871
|
-
utils: "@workspace/ui/lib/utils",
|
|
26872
|
-
ui: "@workspace/ui/components"
|
|
26873
|
-
}
|
|
26874
|
-
};
|
|
26875
|
-
await writeFile(join(projectPath, "apps/web/components.json"), JSON.stringify(webComponentsJson, null, 2));
|
|
26876
|
-
const webGlobalsCssPath = join(projectPath, "apps/web/src/app/globals.css");
|
|
26877
|
-
const webGlobalsCss = `@import "../../../packages/ui/src/styles/globals.css";
|
|
26878
|
-
`;
|
|
26879
|
-
await writeFile(webGlobalsCssPath, webGlobalsCss);
|
|
26880
|
-
const webPackageJsonPath = join(projectPath, "apps/web/package.json");
|
|
26881
|
-
let webPackageJson = {};
|
|
26882
|
-
try {
|
|
26883
|
-
webPackageJson = JSON.parse(await Bun.file(webPackageJsonPath).text());
|
|
26884
|
-
} catch {}
|
|
26885
|
-
if (webPackageJson.dependencies) {
|
|
26886
|
-
webPackageJson.dependencies[uiPackageName] = "workspace:*";
|
|
26887
|
-
await writeFile(webPackageJsonPath, JSON.stringify(webPackageJson, null, 2));
|
|
26888
|
-
}
|
|
26889
|
-
await ensureDirectory(join(projectPath, "apps/platform/src/components"));
|
|
26890
|
-
await ensureDirectory(join(projectPath, "apps/platform/src/lib"));
|
|
26891
|
-
const platformComponentsJson = {
|
|
26892
|
-
$schema: "https://ui.shadcn.com/schema.json",
|
|
26893
|
-
style,
|
|
26894
|
-
rsc: true,
|
|
26895
|
-
tsx: true,
|
|
26896
|
-
tailwind: {
|
|
26897
|
-
config: "",
|
|
26898
|
-
css: "../../packages/ui/src/styles/globals.css",
|
|
26899
|
-
baseColor,
|
|
26900
|
-
cssVariables: true
|
|
26901
|
-
},
|
|
26902
|
-
iconLibrary: "lucide",
|
|
26903
|
-
aliases: {
|
|
26904
|
-
components: "@/components",
|
|
26905
|
-
hooks: "@/hooks",
|
|
26906
|
-
lib: "@/lib",
|
|
26907
|
-
utils: "@workspace/ui/lib/utils",
|
|
26908
|
-
ui: "@workspace/ui/components"
|
|
27044
|
+
const configureNextJsApp = async (appName) => {
|
|
27045
|
+
const appPath = join(projectPath, `apps/${appName}`);
|
|
27046
|
+
if (!await directoryExists(appPath)) {
|
|
27047
|
+
return;
|
|
26909
27048
|
}
|
|
26910
|
-
|
|
26911
|
-
|
|
26912
|
-
|
|
26913
|
-
|
|
26914
|
-
|
|
26915
|
-
|
|
26916
|
-
|
|
26917
|
-
|
|
26918
|
-
|
|
26919
|
-
|
|
26920
|
-
|
|
26921
|
-
|
|
26922
|
-
platformPackageJson.dependencies[uiPackageName] = "workspace:*";
|
|
26923
|
-
await writeFile(platformPackageJsonPath, JSON.stringify(platformPackageJson, null, 2));
|
|
26924
|
-
}
|
|
26925
|
-
const updateAppTailwindConfig = async (appPath) => {
|
|
26926
|
-
const tailwindConfigPath = join(projectPath, appPath, "tailwind.config.ts");
|
|
26927
|
-
let tailwindConfig = "";
|
|
26928
|
-
try {
|
|
26929
|
-
tailwindConfig = await Bun.file(tailwindConfigPath).text();
|
|
26930
|
-
} catch {}
|
|
26931
|
-
const shadcnTheme = ` theme: {
|
|
26932
|
-
extend: {
|
|
26933
|
-
colors: {
|
|
26934
|
-
border: "hsl(var(--border))",
|
|
26935
|
-
input: "hsl(var(--input))",
|
|
26936
|
-
ring: "hsl(var(--ring))",
|
|
26937
|
-
background: "hsl(var(--background))",
|
|
26938
|
-
foreground: "hsl(var(--foreground))",
|
|
26939
|
-
primary: {
|
|
26940
|
-
DEFAULT: "hsl(var(--primary))",
|
|
26941
|
-
foreground: "hsl(var(--primary-foreground))",
|
|
26942
|
-
},
|
|
26943
|
-
secondary: {
|
|
26944
|
-
DEFAULT: "hsl(var(--secondary))",
|
|
26945
|
-
foreground: "hsl(var(--secondary-foreground))",
|
|
26946
|
-
},
|
|
26947
|
-
destructive: {
|
|
26948
|
-
DEFAULT: "hsl(var(--destructive))",
|
|
26949
|
-
foreground: "hsl(var(--destructive-foreground))",
|
|
26950
|
-
},
|
|
26951
|
-
muted: {
|
|
26952
|
-
DEFAULT: "hsl(var(--muted))",
|
|
26953
|
-
foreground: "hsl(var(--muted-foreground))",
|
|
26954
|
-
},
|
|
26955
|
-
accent: {
|
|
26956
|
-
DEFAULT: "hsl(var(--accent))",
|
|
26957
|
-
foreground: "hsl(var(--accent-foreground))",
|
|
26958
|
-
},
|
|
26959
|
-
popover: {
|
|
26960
|
-
DEFAULT: "hsl(var(--popover))",
|
|
26961
|
-
foreground: "hsl(var(--popover-foreground))",
|
|
26962
|
-
},
|
|
26963
|
-
card: {
|
|
26964
|
-
DEFAULT: "hsl(var(--card))",
|
|
26965
|
-
foreground: "hsl(var(--card-foreground))",
|
|
26966
|
-
},
|
|
27049
|
+
await ensureDirectory(join(appPath, "src/components"));
|
|
27050
|
+
await ensureDirectory(join(appPath, "src/lib"));
|
|
27051
|
+
const appComponentsJson = {
|
|
27052
|
+
$schema: "https://ui.shadcn.com/schema.json",
|
|
27053
|
+
style,
|
|
27054
|
+
rsc: true,
|
|
27055
|
+
tsx: true,
|
|
27056
|
+
tailwind: {
|
|
27057
|
+
config: "",
|
|
27058
|
+
css: "../../packages/ui/src/styles/globals.css",
|
|
27059
|
+
baseColor,
|
|
27060
|
+
cssVariables: true
|
|
26967
27061
|
},
|
|
26968
|
-
|
|
26969
|
-
|
|
26970
|
-
|
|
26971
|
-
|
|
26972
|
-
|
|
26973
|
-
|
|
26974
|
-
|
|
26975
|
-
if (tailwindConfig && !tailwindConfig.includes("hsl(var(--background))")) {
|
|
26976
|
-
if (tailwindConfig.includes("theme:")) {
|
|
26977
|
-
const updatedConfig = tailwindConfig.replace(/theme:\s*\{[^}]*\}/s, shadcnTheme.trim());
|
|
26978
|
-
await writeFile(tailwindConfigPath, updatedConfig);
|
|
26979
|
-
} else {
|
|
26980
|
-
const updatedConfig = tailwindConfig.replace(/(\s*)(plugins:.*?)(\n\s*\};)/s, `$1$2$1${shadcnTheme}$3`);
|
|
26981
|
-
await writeFile(tailwindConfigPath, updatedConfig);
|
|
27062
|
+
iconLibrary: "lucide",
|
|
27063
|
+
aliases: {
|
|
27064
|
+
components: "@/components",
|
|
27065
|
+
hooks: "@/hooks",
|
|
27066
|
+
lib: "@/lib",
|
|
27067
|
+
utils: "@workspace/ui/lib/utils",
|
|
27068
|
+
ui: "@workspace/ui/components/ui"
|
|
26982
27069
|
}
|
|
26983
|
-
}
|
|
26984
|
-
|
|
26985
|
-
|
|
26986
|
-
const
|
|
26987
|
-
content: ['./src/**/*.{js,ts,jsx,tsx,mdx}'],
|
|
26988
|
-
theme: {
|
|
26989
|
-
extend: {
|
|
26990
|
-
colors: {
|
|
26991
|
-
border: "hsl(var(--border))",
|
|
26992
|
-
input: "hsl(var(--input))",
|
|
26993
|
-
ring: "hsl(var(--ring))",
|
|
26994
|
-
background: "hsl(var(--background))",
|
|
26995
|
-
foreground: "hsl(var(--foreground))",
|
|
26996
|
-
primary: {
|
|
26997
|
-
DEFAULT: "hsl(var(--primary))",
|
|
26998
|
-
foreground: "hsl(var(--primary-foreground))",
|
|
26999
|
-
},
|
|
27000
|
-
secondary: {
|
|
27001
|
-
DEFAULT: "hsl(var(--secondary))",
|
|
27002
|
-
foreground: "hsl(var(--secondary-foreground))",
|
|
27003
|
-
},
|
|
27004
|
-
destructive: {
|
|
27005
|
-
DEFAULT: "hsl(var(--destructive))",
|
|
27006
|
-
foreground: "hsl(var(--destructive-foreground))",
|
|
27007
|
-
},
|
|
27008
|
-
muted: {
|
|
27009
|
-
DEFAULT: "hsl(var(--muted))",
|
|
27010
|
-
foreground: "hsl(var(--muted-foreground))",
|
|
27011
|
-
},
|
|
27012
|
-
accent: {
|
|
27013
|
-
DEFAULT: "hsl(var(--accent))",
|
|
27014
|
-
foreground: "hsl(var(--accent-foreground))",
|
|
27015
|
-
},
|
|
27016
|
-
popover: {
|
|
27017
|
-
DEFAULT: "hsl(var(--popover))",
|
|
27018
|
-
foreground: "hsl(var(--popover-foreground))",
|
|
27019
|
-
},
|
|
27020
|
-
card: {
|
|
27021
|
-
DEFAULT: "hsl(var(--card))",
|
|
27022
|
-
foreground: "hsl(var(--card-foreground))",
|
|
27023
|
-
},
|
|
27024
|
-
},
|
|
27025
|
-
borderRadius: {
|
|
27026
|
-
lg: "var(--radius)",
|
|
27027
|
-
md: "calc(var(--radius) - 2px)",
|
|
27028
|
-
sm: "calc(var(--radius) - 4px)",
|
|
27029
|
-
},
|
|
27030
|
-
},
|
|
27031
|
-
},
|
|
27032
|
-
plugins: [],
|
|
27033
|
-
};
|
|
27034
|
-
|
|
27035
|
-
export default config;
|
|
27070
|
+
};
|
|
27071
|
+
await writeFile(join(appPath, "components.json"), JSON.stringify(appComponentsJson, null, 2));
|
|
27072
|
+
const globalsCssPath = join(appPath, "src/app/globals.css");
|
|
27073
|
+
const globalsCss = `@import "../../../packages/ui/src/styles/globals.css";
|
|
27036
27074
|
`;
|
|
27037
|
-
|
|
27075
|
+
await writeFile(globalsCssPath, globalsCss);
|
|
27076
|
+
const packageJsonPath = join(appPath, "package.json");
|
|
27077
|
+
let packageJson = {};
|
|
27078
|
+
try {
|
|
27079
|
+
packageJson = JSON.parse(await Bun.file(packageJsonPath).text());
|
|
27080
|
+
} catch {}
|
|
27081
|
+
if (packageJson.dependencies) {
|
|
27082
|
+
packageJson.dependencies[uiPackageName] = "workspace:*";
|
|
27083
|
+
await writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
27038
27084
|
}
|
|
27085
|
+
await createShadcnExample(appPath, true, packageName);
|
|
27039
27086
|
};
|
|
27040
|
-
await
|
|
27041
|
-
await
|
|
27087
|
+
await configureNextJsApp("web");
|
|
27088
|
+
await configureNextJsApp("platform");
|
|
27089
|
+
await configureNextJsApp("app");
|
|
27042
27090
|
const rootPackageJsonPath = join(projectPath, "package.json");
|
|
27043
27091
|
let rootPackageJson = {};
|
|
27044
27092
|
try {
|
|
27045
27093
|
rootPackageJson = JSON.parse(await Bun.file(rootPackageJsonPath).text());
|
|
27046
27094
|
} catch {}
|
|
27047
|
-
if (rootPackageJson.catalog) {
|
|
27048
|
-
rootPackageJson.catalog
|
|
27049
|
-
|
|
27050
|
-
|
|
27051
|
-
|
|
27052
|
-
|
|
27095
|
+
if (!rootPackageJson.catalog) {
|
|
27096
|
+
rootPackageJson.catalog = {};
|
|
27097
|
+
}
|
|
27098
|
+
const shadcnDependencies = {
|
|
27099
|
+
"@radix-ui/react-slot": "^1.1.0",
|
|
27100
|
+
"class-variance-authority": "^0.7.1",
|
|
27101
|
+
clsx: "^2.1.1",
|
|
27102
|
+
"tailwind-merge": "^2.5.5",
|
|
27103
|
+
"lucide-react": "^0.468.0",
|
|
27104
|
+
"@types/react": "^18.3.18",
|
|
27105
|
+
"@types/react-dom": "^18.3.5",
|
|
27106
|
+
typescript: "^5.7.2"
|
|
27107
|
+
};
|
|
27108
|
+
Object.assign(rootPackageJson.catalog, shadcnDependencies);
|
|
27109
|
+
await writeFile(rootPackageJsonPath, JSON.stringify(rootPackageJson, null, 2));
|
|
27053
27110
|
await createShadcnDocs(join(projectPath, "packages/ui"), true, context);
|
|
27054
27111
|
}
|
|
27055
27112
|
|
|
@@ -29920,6 +29977,7 @@ async function buildFullPreset(projectPath, context) {
|
|
|
29920
29977
|
await ensureDirectory(join(projectPath, "apps/api"));
|
|
29921
29978
|
await ensureDirectory(join(projectPath, "packages/types"));
|
|
29922
29979
|
await ensureDirectory(join(projectPath, "packages/utils"));
|
|
29980
|
+
await ensureDirectory(join(projectPath, "packages/ui"));
|
|
29923
29981
|
if (context.database && context.database !== "none") {
|
|
29924
29982
|
await ensureDirectory(join(projectPath, "packages/db"));
|
|
29925
29983
|
}
|
|
@@ -29994,7 +30052,8 @@ async function buildFullPreset(projectPath, context) {
|
|
|
29994
30052
|
react: "catalog:",
|
|
29995
30053
|
"react-dom": "catalog:",
|
|
29996
30054
|
next: "catalog:",
|
|
29997
|
-
[`@${context.packageName}/types`]: "workspace:*"
|
|
30055
|
+
[`@${context.packageName}/types`]: "workspace:*",
|
|
30056
|
+
[`@${context.packageName}/ui`]: "workspace:*"
|
|
29998
30057
|
},
|
|
29999
30058
|
devDependencies: {
|
|
30000
30059
|
"@types/react": "catalog:",
|
|
@@ -30021,7 +30080,8 @@ async function buildFullPreset(projectPath, context) {
|
|
|
30021
30080
|
react: "catalog:",
|
|
30022
30081
|
"react-dom": "catalog:",
|
|
30023
30082
|
next: "catalog:",
|
|
30024
|
-
[`@${context.packageName}/types`]: "workspace:*"
|
|
30083
|
+
[`@${context.packageName}/types`]: "workspace:*",
|
|
30084
|
+
[`@${context.packageName}/ui`]: "workspace:*"
|
|
30025
30085
|
},
|
|
30026
30086
|
devDependencies: {
|
|
30027
30087
|
"@types/react": "catalog:",
|
|
@@ -30819,8 +30879,15 @@ networks:
|
|
|
30819
30879
|
if (context.cicd) {
|
|
30820
30880
|
await setupGitHubActions(projectPath, context);
|
|
30821
30881
|
}
|
|
30822
|
-
if (context.
|
|
30823
|
-
|
|
30882
|
+
if (context.cssFramework === "tailwind" && (context.uiLibrary === "shadcn" || context.uiLibrary === undefined)) {
|
|
30883
|
+
const fullContext = {
|
|
30884
|
+
...context,
|
|
30885
|
+
uiLibrary: "shadcn",
|
|
30886
|
+
shadcnStyle: context.shadcnStyle || "new-york",
|
|
30887
|
+
shadcnBaseColor: context.shadcnBaseColor || "zinc",
|
|
30888
|
+
shadcnRadius: context.shadcnRadius || "0.625rem"
|
|
30889
|
+
};
|
|
30890
|
+
await setupShadcnMonorepo(projectPath, fullContext);
|
|
30824
30891
|
}
|
|
30825
30892
|
await setupTooling(projectPath, context);
|
|
30826
30893
|
await setupVSCodeDebug(projectPath, context, "full");
|
|
@@ -31416,14 +31483,14 @@ async function buildEnterprisePreset(projectPath, context) {
|
|
|
31416
31483
|
version: "0.0.0",
|
|
31417
31484
|
private: true,
|
|
31418
31485
|
scripts: {
|
|
31419
|
-
dev: "next dev -p 3000",
|
|
31486
|
+
dev: "next dev -p ${PORT:-3000}",
|
|
31420
31487
|
build: "next build",
|
|
31421
|
-
start: "next start -p 3000",
|
|
31488
|
+
start: "next start -p ${PORT:-3000}",
|
|
31422
31489
|
lint: "biome check .",
|
|
31423
31490
|
format: "biome check --write .",
|
|
31424
|
-
debug: "bun --inspect node_modules/.bin/next dev -p 3000",
|
|
31425
|
-
"debug:brk": "bun --inspect-brk node_modules/.bin/next dev -p 3000",
|
|
31426
|
-
"debug:wait": "bun --inspect-wait node_modules/.bin/next dev -p 3000"
|
|
31491
|
+
debug: "bun --inspect node_modules/.bin/next dev -p ${PORT:-3000}",
|
|
31492
|
+
"debug:brk": "bun --inspect-brk node_modules/.bin/next dev -p ${PORT:-3000}",
|
|
31493
|
+
"debug:wait": "bun --inspect-wait node_modules/.bin/next dev -p ${PORT:-3000}"
|
|
31427
31494
|
},
|
|
31428
31495
|
dependencies: {
|
|
31429
31496
|
react: "catalog:",
|
|
@@ -31447,14 +31514,14 @@ async function buildEnterprisePreset(projectPath, context) {
|
|
|
31447
31514
|
version: "0.0.0",
|
|
31448
31515
|
private: true,
|
|
31449
31516
|
scripts: {
|
|
31450
|
-
dev: "next dev -p 3001",
|
|
31517
|
+
dev: "next dev -p ${PORT:-3001}",
|
|
31451
31518
|
build: "next build",
|
|
31452
|
-
start: "next start -p 3001",
|
|
31519
|
+
start: "next start -p ${PORT:-3001}",
|
|
31453
31520
|
lint: "biome check .",
|
|
31454
31521
|
format: "biome check --write .",
|
|
31455
|
-
debug: "bun --inspect node_modules/.bin/next dev -p 3001",
|
|
31456
|
-
"debug:brk": "bun --inspect-brk node_modules/.bin/next dev -p 3001",
|
|
31457
|
-
"debug:wait": "bun --inspect-wait node_modules/.bin/next dev -p 3001"
|
|
31522
|
+
debug: "bun --inspect node_modules/.bin/next dev -p ${PORT:-3001}",
|
|
31523
|
+
"debug:brk": "bun --inspect-brk node_modules/.bin/next dev -p ${PORT:-3001}",
|
|
31524
|
+
"debug:wait": "bun --inspect-wait node_modules/.bin/next dev -p ${PORT:-3001}"
|
|
31458
31525
|
},
|
|
31459
31526
|
dependencies: {
|
|
31460
31527
|
react: "catalog:",
|
|
@@ -31479,14 +31546,14 @@ async function buildEnterprisePreset(projectPath, context) {
|
|
|
31479
31546
|
version: "0.0.0",
|
|
31480
31547
|
private: true,
|
|
31481
31548
|
scripts: {
|
|
31482
|
-
dev: "next dev -p 3002",
|
|
31549
|
+
dev: "next dev -p ${PORT:-3002}",
|
|
31483
31550
|
build: "next build",
|
|
31484
|
-
start: "next start -p 3002",
|
|
31551
|
+
start: "next start -p ${PORT:-3002}",
|
|
31485
31552
|
lint: "biome check .",
|
|
31486
31553
|
format: "biome check --write .",
|
|
31487
|
-
debug: "bun --inspect node_modules/.bin/next dev -p 3002",
|
|
31488
|
-
"debug:brk": "bun --inspect-brk node_modules/.bin/next dev -p 3002",
|
|
31489
|
-
"debug:wait": "bun --inspect-wait node_modules/.bin/next dev -p 3002"
|
|
31554
|
+
debug: "bun --inspect node_modules/.bin/next dev -p ${PORT:-3002}",
|
|
31555
|
+
"debug:brk": "bun --inspect-brk node_modules/.bin/next dev -p ${PORT:-3002}",
|
|
31556
|
+
"debug:wait": "bun --inspect-wait node_modules/.bin/next dev -p ${PORT:-3002}"
|
|
31490
31557
|
},
|
|
31491
31558
|
dependencies: {
|
|
31492
31559
|
react: "catalog:",
|
|
@@ -31560,11 +31627,63 @@ async function buildEnterprisePreset(projectPath, context) {
|
|
|
31560
31627
|
if (context.cicd) {
|
|
31561
31628
|
await setupGitHubActions(projectPath, context);
|
|
31562
31629
|
}
|
|
31563
|
-
if (context.uiLibrary === "shadcn") {
|
|
31564
|
-
|
|
31630
|
+
if (context.cssFramework === "tailwind" && (context.uiLibrary === "shadcn" || context.uiLibrary === undefined)) {
|
|
31631
|
+
const enterpriseContext = {
|
|
31632
|
+
...context,
|
|
31633
|
+
uiLibrary: "shadcn",
|
|
31634
|
+
shadcnStyle: context.shadcnStyle || "new-york",
|
|
31635
|
+
shadcnBaseColor: context.shadcnBaseColor || "zinc",
|
|
31636
|
+
shadcnRadius: context.shadcnRadius || "0.625rem"
|
|
31637
|
+
};
|
|
31638
|
+
await setupShadcnMonorepo(projectPath, enterpriseContext);
|
|
31565
31639
|
}
|
|
31566
31640
|
await setupTooling(projectPath, context);
|
|
31567
31641
|
await setupVSCodeDebug(projectPath, context);
|
|
31642
|
+
const typesPackageJson = {
|
|
31643
|
+
name: `@${context.packageName}/types`,
|
|
31644
|
+
version: "0.0.0",
|
|
31645
|
+
private: true,
|
|
31646
|
+
main: "./src/index.ts",
|
|
31647
|
+
types: "./src/index.ts"
|
|
31648
|
+
};
|
|
31649
|
+
await writeFile(join(projectPath, "packages/types/package.json"), JSON.stringify(typesPackageJson, null, 2));
|
|
31650
|
+
const typesContent = `// Shared types for ${context.projectName}
|
|
31651
|
+
|
|
31652
|
+
export interface User {
|
|
31653
|
+
id: string;
|
|
31654
|
+
email: string;
|
|
31655
|
+
name?: string;
|
|
31656
|
+
createdAt: Date;
|
|
31657
|
+
}
|
|
31658
|
+
|
|
31659
|
+
export interface ApiResponse<T = unknown> {
|
|
31660
|
+
data?: T;
|
|
31661
|
+
error?: string;
|
|
31662
|
+
message?: string;
|
|
31663
|
+
}
|
|
31664
|
+
`;
|
|
31665
|
+
await ensureDirectory(join(projectPath, "packages/types/src"));
|
|
31666
|
+
await writeFile(join(projectPath, "packages/types/src/index.ts"), typesContent);
|
|
31667
|
+
const utilsPackageJson = {
|
|
31668
|
+
name: `@${context.packageName}/utils`,
|
|
31669
|
+
version: "0.0.0",
|
|
31670
|
+
private: true,
|
|
31671
|
+
main: "./src/index.ts",
|
|
31672
|
+
types: "./src/index.ts"
|
|
31673
|
+
};
|
|
31674
|
+
await writeFile(join(projectPath, "packages/utils/package.json"), JSON.stringify(utilsPackageJson, null, 2));
|
|
31675
|
+
const utilsContent = `// Shared utilities for ${context.projectName}
|
|
31676
|
+
|
|
31677
|
+
export function formatDate(date: Date): string {
|
|
31678
|
+
return date.toISOString();
|
|
31679
|
+
}
|
|
31680
|
+
|
|
31681
|
+
export function capitalize(str: string): string {
|
|
31682
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
31683
|
+
}
|
|
31684
|
+
`;
|
|
31685
|
+
await ensureDirectory(join(projectPath, "packages/utils/src"));
|
|
31686
|
+
await writeFile(join(projectPath, "packages/utils/src/index.ts"), utilsContent);
|
|
31568
31687
|
await ensureDirectory(join(projectPath, "apps/service-identity/src/routes"));
|
|
31569
31688
|
await ensureDirectory(join(projectPath, "apps/service-identity/src/middleware"));
|
|
31570
31689
|
const serviceIdentityIndex = `import { Hono } from 'hono';
|
|
@@ -31695,10 +31814,14 @@ bun install
|
|
|
31695
31814
|
bun dev
|
|
31696
31815
|
|
|
31697
31816
|
# Start individual apps
|
|
31698
|
-
bun run dev:web # Start marketing site
|
|
31699
|
-
bun run dev:app # Start main product app
|
|
31700
|
-
bun run dev:platform # Start admin dashboard
|
|
31701
|
-
bun run dev:identity # Start identity service
|
|
31817
|
+
bun run dev:web # Start marketing site (port 3000)
|
|
31818
|
+
bun run dev:app # Start main product app (port 3002)
|
|
31819
|
+
bun run dev:platform # Start admin dashboard (port 3001)
|
|
31820
|
+
bun run dev:identity # Start identity service (port 3003)
|
|
31821
|
+
|
|
31822
|
+
# Use custom ports if defaults are in use
|
|
31823
|
+
PORT=3004 bun run dev:app # Run app on port 3004
|
|
31824
|
+
PORT=3005 bun run dev:web # Run web on port 3005
|
|
31702
31825
|
|
|
31703
31826
|
# Build all apps
|
|
31704
31827
|
bun build
|
|
@@ -31708,6 +31831,26 @@ bun lint
|
|
|
31708
31831
|
bun format
|
|
31709
31832
|
\`\`\`
|
|
31710
31833
|
|
|
31834
|
+
### Port Configuration
|
|
31835
|
+
|
|
31836
|
+
All apps support the \`PORT\` environment variable to override the default port:
|
|
31837
|
+
|
|
31838
|
+
- **apps/web**: Default port 3000
|
|
31839
|
+
- **apps/platform**: Default port 3001
|
|
31840
|
+
- **apps/app**: Default port 3002
|
|
31841
|
+
- **apps/service-identity**: Default port 3003
|
|
31842
|
+
|
|
31843
|
+
If a port is already in use, you can easily change it:
|
|
31844
|
+
|
|
31845
|
+
\`\`\`bash
|
|
31846
|
+
# Example: Run app on a different port
|
|
31847
|
+
PORT=4000 cd apps/app && bun dev
|
|
31848
|
+
|
|
31849
|
+
# Or set it globally for the session
|
|
31850
|
+
export PORT=4000
|
|
31851
|
+
cd apps/app && bun dev
|
|
31852
|
+
\`\`\`
|
|
31853
|
+
|
|
31711
31854
|
## Adding More Services
|
|
31712
31855
|
|
|
31713
31856
|
You can easily add more services using bunkit:
|
|
@@ -32714,6 +32857,69 @@ async function createCommand2(preset, name, options) {
|
|
|
32714
32857
|
}
|
|
32715
32858
|
console.log("");
|
|
32716
32859
|
const s = Y2();
|
|
32860
|
+
const isEnterprise = normalizedPreset === "enterprise-monorepo";
|
|
32861
|
+
let shadcnStyle = "new-york";
|
|
32862
|
+
let shadcnBaseColor = "zinc";
|
|
32863
|
+
let shadcnRadius = "0.625rem";
|
|
32864
|
+
if (isEnterprise) {
|
|
32865
|
+
Me(`Default theme: ${source_default.cyan("New York")} style, ${source_default.cyan("Zinc")} color, ${source_default.cyan("0.625rem")} radius`, "shadcn/ui defaults");
|
|
32866
|
+
const customize = await ye({
|
|
32867
|
+
message: `\uD83C\uDFA8 Customize shadcn/ui theme?`,
|
|
32868
|
+
initialValue: false
|
|
32869
|
+
});
|
|
32870
|
+
if (pD(customize)) {
|
|
32871
|
+
xe("Operation cancelled.");
|
|
32872
|
+
process.exit(0);
|
|
32873
|
+
}
|
|
32874
|
+
if (customize) {
|
|
32875
|
+
const styleChoice = await ve({
|
|
32876
|
+
message: "\uD83C\uDFA8 Component style",
|
|
32877
|
+
options: [
|
|
32878
|
+
{ value: "new-york", label: "New York (Recommended)", hint: "Modern, rounded, subtle shadows" },
|
|
32879
|
+
{ value: "default", label: "Default", hint: "Classic, sharper edges, higher contrast" }
|
|
32880
|
+
],
|
|
32881
|
+
initialValue: "new-york"
|
|
32882
|
+
});
|
|
32883
|
+
if (pD(styleChoice)) {
|
|
32884
|
+
xe("Operation cancelled.");
|
|
32885
|
+
process.exit(0);
|
|
32886
|
+
}
|
|
32887
|
+
shadcnStyle = styleChoice;
|
|
32888
|
+
const colorChoice = await ve({
|
|
32889
|
+
message: "\uD83C\uDFA8 Base color theme",
|
|
32890
|
+
options: [
|
|
32891
|
+
{ value: "zinc", label: "Zinc (Recommended)", hint: "Neutral gray - versatile, modern" },
|
|
32892
|
+
{ value: "neutral", label: "Neutral", hint: "Pure neutral - no color cast" },
|
|
32893
|
+
{ value: "gray", label: "Gray", hint: "Warm gray palette" },
|
|
32894
|
+
{ value: "slate", label: "Slate", hint: "Cool gray - bluer tone" },
|
|
32895
|
+
{ value: "stone", label: "Stone", hint: "Warm beige-gray - earthy feel" }
|
|
32896
|
+
],
|
|
32897
|
+
initialValue: "zinc"
|
|
32898
|
+
});
|
|
32899
|
+
if (pD(colorChoice)) {
|
|
32900
|
+
xe("Operation cancelled.");
|
|
32901
|
+
process.exit(0);
|
|
32902
|
+
}
|
|
32903
|
+
shadcnBaseColor = colorChoice;
|
|
32904
|
+
const radiusInput = await he({
|
|
32905
|
+
message: "\uD83D\uDCD0 Border radius",
|
|
32906
|
+
placeholder: "0.625rem",
|
|
32907
|
+
initialValue: "0.625rem",
|
|
32908
|
+
validate: (value) => {
|
|
32909
|
+
if (!value.trim())
|
|
32910
|
+
return "Radius cannot be empty";
|
|
32911
|
+
if (!/^\d+(\.\d+)?(rem|px|em|%)$/.test(value.trim())) {
|
|
32912
|
+
return "Please enter a valid CSS value (e.g., 0.5rem, 8px)";
|
|
32913
|
+
}
|
|
32914
|
+
}
|
|
32915
|
+
});
|
|
32916
|
+
if (pD(radiusInput)) {
|
|
32917
|
+
xe("Operation cancelled.");
|
|
32918
|
+
process.exit(0);
|
|
32919
|
+
}
|
|
32920
|
+
shadcnRadius = radiusInput;
|
|
32921
|
+
}
|
|
32922
|
+
}
|
|
32717
32923
|
s.start(`${source_default.cyan("\uD83D\uDD28")} Creating ${preset} project: ${source_default.bold(name)}`);
|
|
32718
32924
|
try {
|
|
32719
32925
|
const config = {
|
|
@@ -32725,13 +32931,18 @@ async function createCommand2(preset, name, options) {
|
|
|
32725
32931
|
database: "none",
|
|
32726
32932
|
redis: false,
|
|
32727
32933
|
useBunSecrets: false,
|
|
32728
|
-
codeQuality: "ultracite",
|
|
32934
|
+
codeQuality: isEnterprise ? "biome" : "ultracite",
|
|
32729
32935
|
tsStrictness: "strict",
|
|
32730
32936
|
testing: "bun-test",
|
|
32731
32937
|
docker: false,
|
|
32732
32938
|
cicd: false,
|
|
32733
32939
|
envExample: true,
|
|
32734
|
-
pathAliases: true
|
|
32940
|
+
pathAliases: true,
|
|
32941
|
+
cssFramework: isEnterprise ? "tailwind" : undefined,
|
|
32942
|
+
uiLibrary: isEnterprise ? "shadcn" : undefined,
|
|
32943
|
+
shadcnStyle: isEnterprise ? shadcnStyle : undefined,
|
|
32944
|
+
shadcnBaseColor: isEnterprise ? shadcnBaseColor : undefined,
|
|
32945
|
+
shadcnRadius: isEnterprise ? shadcnRadius : undefined
|
|
32735
32946
|
};
|
|
32736
32947
|
s.message(`${source_default.cyan("\uD83D\uDCC1")} Creating project structure...`);
|
|
32737
32948
|
await createProject(config);
|
|
@@ -32765,6 +32976,19 @@ async function createCommand2(preset, name, options) {
|
|
|
32765
32976
|
break;
|
|
32766
32977
|
}
|
|
32767
32978
|
s.message(`${source_default.cyan("\u2728")} Finalizing setup...`);
|
|
32979
|
+
if (isEnterprise && config.uiLibrary === "shadcn" && config.install !== false) {
|
|
32980
|
+
await new Promise((resolve2) => setTimeout(resolve2, 1000));
|
|
32981
|
+
s.message(`${source_default.cyan("\uD83E\uDDE9")} Installing default shadcn/ui components...`);
|
|
32982
|
+
try {
|
|
32983
|
+
await installDefaultShadcnComponents(projectPath, {
|
|
32984
|
+
silent: false,
|
|
32985
|
+
skipDefaults: false
|
|
32986
|
+
});
|
|
32987
|
+
} catch (error) {
|
|
32988
|
+
s.message(`${source_default.yellow("\u26A0\uFE0F")} Could not install default components automatically`);
|
|
32989
|
+
s.message(`${source_default.dim(" You can install them manually:")} ${source_default.cyan("cd packages/ui && bunx shadcn@latest add button card")}`);
|
|
32990
|
+
}
|
|
32991
|
+
}
|
|
32768
32992
|
s.stop(`${source_default.green("\u2705")} Project ${source_default.bold(name)} created successfully!`);
|
|
32769
32993
|
const getPresetEmoji = () => {
|
|
32770
32994
|
switch (normalizedPreset) {
|
|
@@ -33262,6 +33486,20 @@ ${import_picocolors5.default.bold("Package info:")}
|
|
|
33262
33486
|
// src/commands/add/component.ts
|
|
33263
33487
|
init_dist();
|
|
33264
33488
|
import { existsSync } from "fs";
|
|
33489
|
+
async function getPackageName(cwd2) {
|
|
33490
|
+
try {
|
|
33491
|
+
const packageJsonPath = join(cwd2, "package.json");
|
|
33492
|
+
if (existsSync(packageJsonPath)) {
|
|
33493
|
+
const packageJson = JSON.parse(await Bun.file(packageJsonPath).text());
|
|
33494
|
+
const name = packageJson.name;
|
|
33495
|
+
if (name && name.endsWith("-monorepo")) {
|
|
33496
|
+
return name.replace("-monorepo", "");
|
|
33497
|
+
}
|
|
33498
|
+
return name || null;
|
|
33499
|
+
}
|
|
33500
|
+
} catch {}
|
|
33501
|
+
return null;
|
|
33502
|
+
}
|
|
33265
33503
|
async function addComponentCommand(options = {}) {
|
|
33266
33504
|
const cwd2 = options.cwd || process.cwd();
|
|
33267
33505
|
const spinner = Y2();
|
|
@@ -33273,6 +33511,12 @@ async function addComponentCommand(options = {}) {
|
|
|
33273
33511
|
process.exit(1);
|
|
33274
33512
|
}
|
|
33275
33513
|
const targetPath = isMonorepo ? join(cwd2, "packages/ui") : cwd2;
|
|
33514
|
+
const targetComponentsJson = join(targetPath, "components.json");
|
|
33515
|
+
if (!existsSync(targetComponentsJson)) {
|
|
33516
|
+
M2.error(`shadcn/ui is not configured in ${isMonorepo ? "packages/ui" : "this project"}.`);
|
|
33517
|
+
M2.info("Run `bunkit init` with --ui-library shadcn to set up shadcn/ui first.");
|
|
33518
|
+
process.exit(1);
|
|
33519
|
+
}
|
|
33276
33520
|
let components = [];
|
|
33277
33521
|
if (options.all) {
|
|
33278
33522
|
const popularComponents = [
|
|
@@ -33358,12 +33602,16 @@ async function addComponentCommand(options = {}) {
|
|
|
33358
33602
|
try {
|
|
33359
33603
|
await installShadcnComponents(targetPath, components, {
|
|
33360
33604
|
silent: false,
|
|
33361
|
-
cwd:
|
|
33605
|
+
cwd: cwd2,
|
|
33606
|
+
isMonorepo
|
|
33362
33607
|
});
|
|
33363
33608
|
spinner.stop(`\u2705 Installed: ${components.join(", ")}`);
|
|
33364
33609
|
if (isMonorepo) {
|
|
33610
|
+
const packageName = await getPackageName(cwd2);
|
|
33365
33611
|
Me(`Components installed in packages/ui. Import them using:
|
|
33366
|
-
import { Button } from "@workspace/ui/components/ui/button"
|
|
33612
|
+
` + `import { Button } from "@workspace/ui/components/ui/button"
|
|
33613
|
+
` + `// Or using workspace alias:
|
|
33614
|
+
` + `import { Button } from "${packageName ? `@${packageName}/ui` : "@workspace/ui"}/components/ui/button"`, "Usage");
|
|
33367
33615
|
} else {
|
|
33368
33616
|
Me(`Import components using:
|
|
33369
33617
|
import { Button } from "@/components/ui/button"`, "Usage");
|