bejamas 0.0.0-canary.02ea75e
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/README.md +43 -0
- package/dist/generate-mdx-CR4bXlml.js +664 -0
- package/dist/generate-mdx-CR4bXlml.js.map +1 -0
- package/dist/get-config-CJUwQ2Xb.js +217 -0
- package/dist/get-config-CJUwQ2Xb.js.map +1 -0
- package/dist/index.js +716 -0
- package/dist/index.js.map +1 -0
- package/package.json +56 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,716 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { BASE_COLORS, getConfig, getProjectInfo, highlighter, logger, spinner } from "./get-config-CJUwQ2Xb.js";
|
|
3
|
+
import { Command } from "commander";
|
|
4
|
+
import { createRequire } from "module";
|
|
5
|
+
import path from "path";
|
|
6
|
+
import fsExtra from "fs-extra";
|
|
7
|
+
import os from "os";
|
|
8
|
+
import dotenv from "dotenv";
|
|
9
|
+
import { detect } from "@antfu/ni";
|
|
10
|
+
import { z } from "zod";
|
|
11
|
+
import { execa } from "execa";
|
|
12
|
+
import prompts from "prompts";
|
|
13
|
+
import fg from "fast-glob";
|
|
14
|
+
import path$1, { dirname as dirname$1, isAbsolute, relative as relative$1, resolve } from "node:path";
|
|
15
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
16
|
+
import { fileURLToPath } from "node:url";
|
|
17
|
+
import fs from "node:fs/promises";
|
|
18
|
+
|
|
19
|
+
//#region src/utils/errors.ts
|
|
20
|
+
const MISSING_DIR_OR_EMPTY_PROJECT = "1";
|
|
21
|
+
|
|
22
|
+
//#endregion
|
|
23
|
+
//#region src/preflights/preflight-init.ts
|
|
24
|
+
async function preFlightInit(options) {
|
|
25
|
+
const errors = {};
|
|
26
|
+
if (!fsExtra.existsSync(options.cwd) || !fsExtra.existsSync(path.resolve(options.cwd, "package.json"))) {
|
|
27
|
+
errors[MISSING_DIR_OR_EMPTY_PROJECT] = true;
|
|
28
|
+
return {
|
|
29
|
+
errors,
|
|
30
|
+
projectInfo: null
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
errors,
|
|
35
|
+
projectInfo: null
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
//#endregion
|
|
40
|
+
//#region src/registry/context.ts
|
|
41
|
+
let context = { headers: {} };
|
|
42
|
+
function clearRegistryContext() {
|
|
43
|
+
context.headers = {};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
//#endregion
|
|
47
|
+
//#region src/utils/get-package-manager.ts
|
|
48
|
+
async function getPackageManager(targetDir, { withFallback } = { withFallback: false }) {
|
|
49
|
+
const packageManager = await detect({
|
|
50
|
+
programmatic: true,
|
|
51
|
+
cwd: targetDir
|
|
52
|
+
});
|
|
53
|
+
if (packageManager === "yarn@berry") return "yarn";
|
|
54
|
+
if (packageManager === "pnpm@6") return "pnpm";
|
|
55
|
+
if (packageManager === "bun") return "bun";
|
|
56
|
+
if (packageManager === "deno") return "deno";
|
|
57
|
+
if (!withFallback) return packageManager ?? "npm";
|
|
58
|
+
const userAgent = process.env.npm_config_user_agent || "";
|
|
59
|
+
if (userAgent.startsWith("yarn")) return "yarn";
|
|
60
|
+
if (userAgent.startsWith("pnpm")) return "pnpm";
|
|
61
|
+
if (userAgent.startsWith("bun")) return "bun";
|
|
62
|
+
return "npm";
|
|
63
|
+
}
|
|
64
|
+
async function getPackageRunner(cwd) {
|
|
65
|
+
const packageManager = await getPackageManager(cwd);
|
|
66
|
+
if (packageManager === "pnpm") return "pnpm dlx";
|
|
67
|
+
if (packageManager === "bun") return "bunx";
|
|
68
|
+
return "npx";
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
//#endregion
|
|
72
|
+
//#region src/registry/errors.ts
|
|
73
|
+
const RegistryErrorCode = {
|
|
74
|
+
NETWORK_ERROR: "NETWORK_ERROR",
|
|
75
|
+
NOT_FOUND: "NOT_FOUND",
|
|
76
|
+
UNAUTHORIZED: "UNAUTHORIZED",
|
|
77
|
+
FORBIDDEN: "FORBIDDEN",
|
|
78
|
+
FETCH_ERROR: "FETCH_ERROR",
|
|
79
|
+
NOT_CONFIGURED: "NOT_CONFIGURED",
|
|
80
|
+
INVALID_CONFIG: "INVALID_CONFIG",
|
|
81
|
+
MISSING_ENV_VARS: "MISSING_ENV_VARS",
|
|
82
|
+
LOCAL_FILE_ERROR: "LOCAL_FILE_ERROR",
|
|
83
|
+
PARSE_ERROR: "PARSE_ERROR",
|
|
84
|
+
VALIDATION_ERROR: "VALIDATION_ERROR",
|
|
85
|
+
UNKNOWN_ERROR: "UNKNOWN_ERROR"
|
|
86
|
+
};
|
|
87
|
+
var RegistryError = class extends Error {
|
|
88
|
+
constructor(message, options = {}) {
|
|
89
|
+
super(message);
|
|
90
|
+
this.name = "RegistryError";
|
|
91
|
+
this.code = options.code || RegistryErrorCode.UNKNOWN_ERROR;
|
|
92
|
+
this.statusCode = options.statusCode;
|
|
93
|
+
this.cause = options.cause;
|
|
94
|
+
this.context = options.context;
|
|
95
|
+
this.suggestion = options.suggestion;
|
|
96
|
+
this.timestamp = /* @__PURE__ */ new Date();
|
|
97
|
+
if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor);
|
|
98
|
+
}
|
|
99
|
+
toJSON() {
|
|
100
|
+
return {
|
|
101
|
+
name: this.name,
|
|
102
|
+
message: this.message,
|
|
103
|
+
code: this.code,
|
|
104
|
+
statusCode: this.statusCode,
|
|
105
|
+
context: this.context,
|
|
106
|
+
suggestion: this.suggestion,
|
|
107
|
+
timestamp: this.timestamp,
|
|
108
|
+
stack: this.stack
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
//#endregion
|
|
114
|
+
//#region src/utils/handle-error.ts
|
|
115
|
+
function handleError(error) {
|
|
116
|
+
logger.break();
|
|
117
|
+
logger.error(`Something went wrong. Please check the error below for more details.`);
|
|
118
|
+
logger.error(`If the problem persists, please open an issue on GitHub: https://github.com/bejamas/ui/issues`);
|
|
119
|
+
logger.error("");
|
|
120
|
+
if (typeof error === "string") {
|
|
121
|
+
logger.error(error);
|
|
122
|
+
logger.break();
|
|
123
|
+
process.exit(1);
|
|
124
|
+
}
|
|
125
|
+
if (error instanceof RegistryError) {
|
|
126
|
+
if (error.message) {
|
|
127
|
+
logger.error(error.cause ? "Error:" : "Message:");
|
|
128
|
+
logger.error(error.message);
|
|
129
|
+
}
|
|
130
|
+
if (error.cause) {
|
|
131
|
+
logger.error("\nMessage:");
|
|
132
|
+
logger.error(error.cause);
|
|
133
|
+
}
|
|
134
|
+
if (error.suggestion) {
|
|
135
|
+
logger.error("\nSuggestion:");
|
|
136
|
+
logger.error(error.suggestion);
|
|
137
|
+
}
|
|
138
|
+
logger.break();
|
|
139
|
+
process.exit(1);
|
|
140
|
+
}
|
|
141
|
+
if (error instanceof z.ZodError) {
|
|
142
|
+
logger.error("Validation failed:");
|
|
143
|
+
for (const [key, value] of Object.entries(error.flatten().fieldErrors)) logger.error(`- ${highlighter.info(key)}: ${value}`);
|
|
144
|
+
logger.break();
|
|
145
|
+
process.exit(1);
|
|
146
|
+
}
|
|
147
|
+
if (error instanceof Error) {
|
|
148
|
+
logger.error(error.message);
|
|
149
|
+
logger.break();
|
|
150
|
+
process.exit(1);
|
|
151
|
+
}
|
|
152
|
+
logger.break();
|
|
153
|
+
process.exit(1);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
//#endregion
|
|
157
|
+
//#region src/utils/create-project.ts
|
|
158
|
+
const TEMPLATES = {
|
|
159
|
+
astro: "astro",
|
|
160
|
+
"astro-monorepo": "astro-monorepo",
|
|
161
|
+
"astro-with-component-docs-monorepo": "astro-with-component-docs-monorepo"
|
|
162
|
+
};
|
|
163
|
+
const MONOREPO_TEMPLATE_URL = "https://codeload.github.com/bejamas/ui/tar.gz/main";
|
|
164
|
+
async function createProject(options) {
|
|
165
|
+
options = {
|
|
166
|
+
srcDir: false,
|
|
167
|
+
...options
|
|
168
|
+
};
|
|
169
|
+
let template = options.template && TEMPLATES[options.template] ? options.template : "astro";
|
|
170
|
+
let projectName = "my-app";
|
|
171
|
+
const isRemoteComponent = options.components?.length === 1 && !!options.components[0].match(/\/chat\/b\//);
|
|
172
|
+
if (!options.force) {
|
|
173
|
+
const { type, name } = await prompts([{
|
|
174
|
+
type: options.template || isRemoteComponent ? null : "select",
|
|
175
|
+
name: "type",
|
|
176
|
+
message: `The path ${highlighter.info(options.cwd)} does not contain a package.json file.\n Would you like to start a new project?`,
|
|
177
|
+
choices: [
|
|
178
|
+
{
|
|
179
|
+
title: "Astro",
|
|
180
|
+
value: "astro"
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
title: "Astro (Monorepo)",
|
|
184
|
+
value: "astro-monorepo"
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
title: "Astro with Component Docs (Monorepo)",
|
|
188
|
+
value: "astro-with-component-docs-monorepo"
|
|
189
|
+
}
|
|
190
|
+
],
|
|
191
|
+
initial: 0
|
|
192
|
+
}, {
|
|
193
|
+
type: "text",
|
|
194
|
+
name: "name",
|
|
195
|
+
message: "What is your project named?",
|
|
196
|
+
initial: (_prev, values) => {
|
|
197
|
+
return (options.template && TEMPLATES[options.template] && options.template || values.type || template)?.endsWith("monorepo") ? "my-monorepo" : "my-app";
|
|
198
|
+
},
|
|
199
|
+
format: (value) => value.trim(),
|
|
200
|
+
validate: (value) => value.length > 128 ? `Name should be less than 128 characters.` : true
|
|
201
|
+
}]);
|
|
202
|
+
template = type ?? template;
|
|
203
|
+
projectName = name;
|
|
204
|
+
}
|
|
205
|
+
const packageManager = await getPackageManager(options.cwd, { withFallback: true });
|
|
206
|
+
const projectPath = `${options.cwd}/${projectName}`;
|
|
207
|
+
try {
|
|
208
|
+
await fsExtra.access(options.cwd, fsExtra.constants.W_OK);
|
|
209
|
+
} catch (error) {
|
|
210
|
+
logger.break();
|
|
211
|
+
logger.error(`The path ${highlighter.info(options.cwd)} is not writable.`);
|
|
212
|
+
logger.error(`It is likely you do not have write permissions for this folder or the path ${highlighter.info(options.cwd)} does not exist.`);
|
|
213
|
+
logger.break();
|
|
214
|
+
process.exit(1);
|
|
215
|
+
}
|
|
216
|
+
if (fsExtra.existsSync(path.resolve(options.cwd, projectName, "package.json"))) {
|
|
217
|
+
logger.break();
|
|
218
|
+
logger.error(`A project with the name ${highlighter.info(projectName)} already exists.`);
|
|
219
|
+
logger.error(`Please choose a different name and try again.`);
|
|
220
|
+
logger.break();
|
|
221
|
+
process.exit(1);
|
|
222
|
+
}
|
|
223
|
+
await createProjectFromTemplate(projectPath, {
|
|
224
|
+
templateKey: template,
|
|
225
|
+
packageManager,
|
|
226
|
+
cwd: options.cwd
|
|
227
|
+
});
|
|
228
|
+
return {
|
|
229
|
+
projectPath,
|
|
230
|
+
projectName,
|
|
231
|
+
template
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
async function createProjectFromTemplate(projectPath, options) {
|
|
235
|
+
const createSpinner = spinner(`Creating a new project from template. This may take a few minutes.`).start();
|
|
236
|
+
const TEMPLATE_TAR_SUBPATH = {
|
|
237
|
+
astro: "ui-main/templates/astro",
|
|
238
|
+
"astro-monorepo": "ui-main/templates/monorepo-astro",
|
|
239
|
+
"astro-with-component-docs-monorepo": "ui-main/templates/monorepo-astro-with-docs"
|
|
240
|
+
};
|
|
241
|
+
try {
|
|
242
|
+
dotenv.config({ quiet: true });
|
|
243
|
+
const templatePath = path.join(os.tmpdir(), `bejamas-template-${Date.now()}`);
|
|
244
|
+
await fsExtra.ensureDir(templatePath);
|
|
245
|
+
const authToken = process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
|
|
246
|
+
const usedAuth = Boolean(authToken);
|
|
247
|
+
const headers = { "User-Agent": "bejamas-cli" };
|
|
248
|
+
if (authToken) headers["Authorization"] = `Bearer ${authToken}`;
|
|
249
|
+
const response = await fetch(MONOREPO_TEMPLATE_URL, { headers });
|
|
250
|
+
if (!response.ok) {
|
|
251
|
+
if (response.status === 401 || response.status === 403 || !usedAuth && response.status === 404) throw new Error("Unauthorized to access private template. Set GITHUB_TOKEN or GH_TOKEN (in .env or env) with repo access and try again.");
|
|
252
|
+
if (response.status === 404) throw new Error("Failed to download template: not found.");
|
|
253
|
+
throw new Error(`Failed to download template: ${response.status} ${response.statusText}`);
|
|
254
|
+
}
|
|
255
|
+
const tarPath = path.resolve(templatePath, "template.tar.gz");
|
|
256
|
+
await fsExtra.writeFile(tarPath, Buffer.from(await response.arrayBuffer()));
|
|
257
|
+
const tarSubpath = TEMPLATE_TAR_SUBPATH[options.templateKey];
|
|
258
|
+
const leafName = tarSubpath.split("/").pop();
|
|
259
|
+
await execa("tar", [
|
|
260
|
+
"-xzf",
|
|
261
|
+
tarPath,
|
|
262
|
+
"-C",
|
|
263
|
+
templatePath,
|
|
264
|
+
"--strip-components=2",
|
|
265
|
+
tarSubpath
|
|
266
|
+
]);
|
|
267
|
+
const extractedPath = path.resolve(templatePath, leafName);
|
|
268
|
+
await fsExtra.move(extractedPath, projectPath);
|
|
269
|
+
await fsExtra.remove(templatePath);
|
|
270
|
+
await execa(options.packageManager, ["install"], { cwd: projectPath });
|
|
271
|
+
try {
|
|
272
|
+
const { stdout } = await execa("git", ["rev-parse", "--is-inside-work-tree"], { cwd: projectPath });
|
|
273
|
+
if (!(stdout.trim() === "true")) {
|
|
274
|
+
await execa("git", ["init"], { cwd: projectPath });
|
|
275
|
+
await execa("git", ["add", "-A"], { cwd: projectPath });
|
|
276
|
+
await execa("git", [
|
|
277
|
+
"commit",
|
|
278
|
+
"-m",
|
|
279
|
+
"Initial commit"
|
|
280
|
+
], { cwd: projectPath });
|
|
281
|
+
}
|
|
282
|
+
} catch (_) {}
|
|
283
|
+
createSpinner?.succeed("Creating a new project from template.");
|
|
284
|
+
} catch (error) {
|
|
285
|
+
createSpinner?.fail("Something went wrong creating a new project from template.");
|
|
286
|
+
handleError(error);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
//#endregion
|
|
291
|
+
//#region src/commands/init.ts
|
|
292
|
+
const DEFAULT_REGISTRY_URL$1 = "https://ui.bejamas.com/r";
|
|
293
|
+
const initOptionsSchema = z.object({
|
|
294
|
+
cwd: z.string(),
|
|
295
|
+
components: z.array(z.string()).optional(),
|
|
296
|
+
yes: z.boolean(),
|
|
297
|
+
defaults: z.boolean(),
|
|
298
|
+
force: z.boolean(),
|
|
299
|
+
silent: z.boolean(),
|
|
300
|
+
isNewProject: z.boolean(),
|
|
301
|
+
srcDir: z.boolean().optional(),
|
|
302
|
+
cssVariables: z.boolean(),
|
|
303
|
+
template: z.string().optional().refine((val) => {
|
|
304
|
+
if (val) return TEMPLATES[val];
|
|
305
|
+
return true;
|
|
306
|
+
}, { message: "Invalid template. Please use 'next' or 'next-monorepo'." }),
|
|
307
|
+
baseColor: z.string().optional().refine((val) => {
|
|
308
|
+
if (val) return BASE_COLORS.find((color) => color.name === val);
|
|
309
|
+
return true;
|
|
310
|
+
}, { message: `Invalid base color. Please use '${BASE_COLORS.map((color) => color.name).join("', '")}'` }),
|
|
311
|
+
baseStyle: z.boolean()
|
|
312
|
+
});
|
|
313
|
+
const init = new Command().name("init").description("initialize your project and install dependencies").argument("[components...]", "names, url or local path to component").option("-t, --template <template>", "the template to use. (next, next-monorepo)").option("-b, --base-color <base-color>", "the base color to use. (neutral, gray, zinc, stone, slate)", void 0).option("-y, --yes", "skip confirmation prompt.", true).option("-d, --defaults,", "use default configuration.", false).option("-f, --force", "force overwrite of existing configuration.", false).option("-c, --cwd <cwd>", "the working directory. defaults to the current directory.", process.cwd()).option("-s, --silent", "mute output.", false).option("--src-dir", "use the src directory when creating a new project.", false).option("--no-src-dir", "do not use the src directory when creating a new project.").option("--css-variables", "use css variables for theming.", true).option("--no-css-variables", "do not use css variables for theming.").option("--no-base-style", "do not install the base shadcn style.").action(async (_components, opts) => {
|
|
314
|
+
try {
|
|
315
|
+
await runInit(opts);
|
|
316
|
+
} catch (error) {
|
|
317
|
+
logger.break();
|
|
318
|
+
handleError(error);
|
|
319
|
+
} finally {
|
|
320
|
+
clearRegistryContext();
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
async function runInit(options) {
|
|
324
|
+
let newProjectTemplate;
|
|
325
|
+
if (!options.skipPreflight) {
|
|
326
|
+
const preflight = await preFlightInit(options);
|
|
327
|
+
if (preflight.errors[MISSING_DIR_OR_EMPTY_PROJECT]) {
|
|
328
|
+
const { projectPath, template } = await createProject(options);
|
|
329
|
+
if (!projectPath) process.exit(1);
|
|
330
|
+
options.cwd = projectPath;
|
|
331
|
+
options.isNewProject = true;
|
|
332
|
+
newProjectTemplate = template;
|
|
333
|
+
}
|
|
334
|
+
preflight.projectInfo;
|
|
335
|
+
} else await getProjectInfo(options.cwd);
|
|
336
|
+
if (newProjectTemplate) {
|
|
337
|
+
options.cwd = path.resolve(options.cwd, {
|
|
338
|
+
"astro-monorepo": "apps/web",
|
|
339
|
+
"astro-with-component-docs-monorepo": "apps/web",
|
|
340
|
+
astro: ""
|
|
341
|
+
}[newProjectTemplate]);
|
|
342
|
+
logger.log(`${highlighter.success("Success!")} Project initialization completed.\nYou may now add components.`);
|
|
343
|
+
return await getConfig(options.cwd);
|
|
344
|
+
}
|
|
345
|
+
const shadcnBin = process.platform === "win32" ? "shadcn.cmd" : "shadcn";
|
|
346
|
+
const localShadcnPath = path.resolve(options.cwd, "node_modules", ".bin", shadcnBin);
|
|
347
|
+
try {
|
|
348
|
+
const env = {
|
|
349
|
+
...process.env,
|
|
350
|
+
REGISTRY_URL: process.env.REGISTRY_URL || DEFAULT_REGISTRY_URL$1
|
|
351
|
+
};
|
|
352
|
+
if (await fsExtra.pathExists(localShadcnPath)) await execa(localShadcnPath, [
|
|
353
|
+
"init",
|
|
354
|
+
"--base-color",
|
|
355
|
+
"neutral"
|
|
356
|
+
], {
|
|
357
|
+
stdio: "inherit",
|
|
358
|
+
cwd: options.cwd,
|
|
359
|
+
env
|
|
360
|
+
});
|
|
361
|
+
else await execa("npx", [
|
|
362
|
+
"-y",
|
|
363
|
+
"shadcn@latest",
|
|
364
|
+
"init",
|
|
365
|
+
"--base-color",
|
|
366
|
+
"neutral"
|
|
367
|
+
], {
|
|
368
|
+
stdio: "inherit",
|
|
369
|
+
cwd: options.cwd,
|
|
370
|
+
env
|
|
371
|
+
});
|
|
372
|
+
} catch (err) {
|
|
373
|
+
process.exit(1);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
//#endregion
|
|
378
|
+
//#region src/commands/docs.ts
|
|
379
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
380
|
+
dirname$1(__filename);
|
|
381
|
+
function readTsConfig(projectRoot) {
|
|
382
|
+
try {
|
|
383
|
+
const tsconfigPath = resolve(projectRoot, "tsconfig.json");
|
|
384
|
+
if (!existsSync(tsconfigPath)) return null;
|
|
385
|
+
const raw = readFileSync(tsconfigPath, "utf-8");
|
|
386
|
+
return JSON.parse(raw);
|
|
387
|
+
} catch {
|
|
388
|
+
return null;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
function resolveAliasPathUsingTsConfig(inputPath, projectRoot) {
|
|
392
|
+
const cfg = readTsConfig(projectRoot);
|
|
393
|
+
if (!cfg || !cfg.compilerOptions) return null;
|
|
394
|
+
const baseUrl = cfg.compilerOptions.baseUrl || ".";
|
|
395
|
+
const paths = cfg.compilerOptions.paths || {};
|
|
396
|
+
for (const [key, values] of Object.entries(paths)) {
|
|
397
|
+
const pattern = key.replace(/\*/g, "(.*)");
|
|
398
|
+
const re = /* @__PURE__ */ new RegExp(`^${pattern}$`);
|
|
399
|
+
const match = inputPath.match(re);
|
|
400
|
+
if (!match) continue;
|
|
401
|
+
const wildcard = match[1] || "";
|
|
402
|
+
const first = Array.isArray(values) ? values[0] : values;
|
|
403
|
+
if (!first) continue;
|
|
404
|
+
const target = String(first).replace(/\*/g, wildcard);
|
|
405
|
+
return resolve(projectRoot, baseUrl, target);
|
|
406
|
+
}
|
|
407
|
+
return null;
|
|
408
|
+
}
|
|
409
|
+
async function generateDocs({ cwd, outDir, verbose }) {
|
|
410
|
+
const DEBUG = process.env.BEJAMAS_DEBUG === "1" || process.env.BEJAMAS_DEBUG === "true" || verbose;
|
|
411
|
+
try {
|
|
412
|
+
const shellCwd = process.cwd();
|
|
413
|
+
let projectRoot = shellCwd;
|
|
414
|
+
let probe = shellCwd;
|
|
415
|
+
for (let i = 0; i < 6 && probe; i += 1) {
|
|
416
|
+
const candidate = resolve(probe, "components.json");
|
|
417
|
+
if (existsSync(candidate)) {
|
|
418
|
+
projectRoot = probe;
|
|
419
|
+
try {
|
|
420
|
+
const raw = readFileSync(candidate, "utf-8");
|
|
421
|
+
const config = JSON.parse(raw);
|
|
422
|
+
if (!cwd && !process.env.BEJAMAS_UI_ROOT && config?.aliases?.ui) {
|
|
423
|
+
const mapped = String(config.aliases.ui);
|
|
424
|
+
let uiAbs = null;
|
|
425
|
+
if (mapped.startsWith("./") || mapped.startsWith("../") || isAbsolute(mapped)) uiAbs = resolve(projectRoot, mapped);
|
|
426
|
+
else uiAbs = resolveAliasPathUsingTsConfig(mapped, projectRoot);
|
|
427
|
+
if (!uiAbs && mapped.startsWith("@/")) uiAbs = resolve(projectRoot, "src", mapped.slice(2));
|
|
428
|
+
if (uiAbs) process.env.BEJAMAS_UI_ROOT = uiAbs;
|
|
429
|
+
}
|
|
430
|
+
if (!cwd && !process.env.BEJAMAS_UI_ROOT && config?.tailwind?.css) {
|
|
431
|
+
const cssRaw = String(config.tailwind.css);
|
|
432
|
+
let cssAbs = null;
|
|
433
|
+
if (cssRaw.startsWith("./") || cssRaw.startsWith("../") || isAbsolute(cssRaw)) cssAbs = resolve(projectRoot, cssRaw);
|
|
434
|
+
else cssAbs = resolveAliasPathUsingTsConfig(cssRaw, projectRoot);
|
|
435
|
+
if (!cssAbs && cssRaw.startsWith("@/")) cssAbs = resolve(projectRoot, "src", cssRaw.slice(2));
|
|
436
|
+
if (cssAbs) {
|
|
437
|
+
const uiRootFromCss = resolve(cssAbs, "..", "..", "..");
|
|
438
|
+
process.env.BEJAMAS_UI_ROOT = uiRootFromCss;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
if (!outDir && config?.aliases?.docs) {
|
|
442
|
+
const mapped = String(config.aliases.docs);
|
|
443
|
+
let outResolved = null;
|
|
444
|
+
if (mapped.startsWith("./") || mapped.startsWith("../") || isAbsolute(mapped)) outResolved = mapped;
|
|
445
|
+
else {
|
|
446
|
+
const abs = resolveAliasPathUsingTsConfig(mapped, projectRoot);
|
|
447
|
+
if (abs) outResolved = relative$1(projectRoot, abs);
|
|
448
|
+
}
|
|
449
|
+
if (!outResolved && mapped.startsWith("@/")) outResolved = mapped.replace(/^@\//, "src/");
|
|
450
|
+
const finalOut = outResolved ?? mapped;
|
|
451
|
+
if (finalOut && !process.env.BEJAMAS_DOCS_OUT_DIR) {
|
|
452
|
+
process.env.BEJAMAS_DOCS_OUT_DIR = finalOut;
|
|
453
|
+
process.env.BEJAMAS_DOCS_CWD = projectRoot;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
} catch {}
|
|
457
|
+
break;
|
|
458
|
+
}
|
|
459
|
+
const parent = resolve(probe, "..");
|
|
460
|
+
probe = parent === probe ? null : parent;
|
|
461
|
+
}
|
|
462
|
+
if (!process.env.BEJAMAS_DOCS_CWD) process.env.BEJAMAS_DOCS_CWD = shellCwd;
|
|
463
|
+
if (!process.env.BEJAMAS_UI_ROOT) {
|
|
464
|
+
const defaultGuess = (() => {
|
|
465
|
+
let current = shellCwd;
|
|
466
|
+
for (let i = 0; i < 6; i += 1) {
|
|
467
|
+
const cand = resolve(current, "packages/ui/package.json");
|
|
468
|
+
if (existsSync(cand)) {
|
|
469
|
+
const abs = resolve(current, "packages/ui");
|
|
470
|
+
return relative$1(shellCwd, abs) || abs;
|
|
471
|
+
}
|
|
472
|
+
const parent = resolve(current, "..");
|
|
473
|
+
if (parent === current) break;
|
|
474
|
+
current = parent;
|
|
475
|
+
}
|
|
476
|
+
const nm = resolve(shellCwd, "node_modules/@bejamas/ui/package.json");
|
|
477
|
+
if (existsSync(nm)) {
|
|
478
|
+
const abs = resolve(shellCwd, "node_modules/@bejamas/ui");
|
|
479
|
+
return relative$1(shellCwd, abs) || abs;
|
|
480
|
+
}
|
|
481
|
+
return "packages/ui";
|
|
482
|
+
})();
|
|
483
|
+
const { uiRoot } = await prompts({
|
|
484
|
+
type: "text",
|
|
485
|
+
name: "uiRoot",
|
|
486
|
+
message: "Path to @bejamas/ui package root:",
|
|
487
|
+
initial: defaultGuess,
|
|
488
|
+
validate: (val) => {
|
|
489
|
+
const p = resolve(shellCwd, val);
|
|
490
|
+
return existsSync(resolve(p, "package.json")) ? true : `No package.json found in ${p}`;
|
|
491
|
+
}
|
|
492
|
+
});
|
|
493
|
+
if (!uiRoot) {
|
|
494
|
+
logger.error("@bejamas/ui root is required to generate docs.");
|
|
495
|
+
process.exit(1);
|
|
496
|
+
}
|
|
497
|
+
process.env.BEJAMAS_UI_ROOT = resolve(shellCwd, uiRoot);
|
|
498
|
+
}
|
|
499
|
+
if (cwd && cwd.length) process.env.BEJAMAS_UI_ROOT = resolve(cwd);
|
|
500
|
+
if (outDir && outDir.length) process.env.BEJAMAS_DOCS_OUT_DIR = outDir;
|
|
501
|
+
if (!process.env.BEJAMAS_DOCS_OUT_DIR) {
|
|
502
|
+
const { out } = await prompts({
|
|
503
|
+
type: "text",
|
|
504
|
+
name: "out",
|
|
505
|
+
message: "Where should we output docs (relative to project root)?",
|
|
506
|
+
initial: "src/content/docs/components"
|
|
507
|
+
});
|
|
508
|
+
if (!out) {
|
|
509
|
+
logger.error("An output directory is required to generate docs.");
|
|
510
|
+
process.exit(1);
|
|
511
|
+
}
|
|
512
|
+
process.env.BEJAMAS_DOCS_OUT_DIR = out;
|
|
513
|
+
process.env.BEJAMAS_DOCS_CWD = process.env.BEJAMAS_DOCS_CWD || shellCwd;
|
|
514
|
+
}
|
|
515
|
+
process.env.BEJAMAS_SKIP_AUTO_RUN = "1";
|
|
516
|
+
logger.info(`Generating docs...`);
|
|
517
|
+
if (DEBUG) {
|
|
518
|
+
logger.info(`Generator entry: @/src/docs/generate-mdx/index`);
|
|
519
|
+
if (process.env.BEJAMAS_UI_ROOT) logger.info(`UI root: ${process.env.BEJAMAS_UI_ROOT}`);
|
|
520
|
+
if (process.env.BEJAMAS_DOCS_CWD) logger.info(`Docs CWD: ${process.env.BEJAMAS_DOCS_CWD}`);
|
|
521
|
+
if (process.env.BEJAMAS_DOCS_OUT_DIR) logger.info(`Docs out: ${process.env.BEJAMAS_DOCS_OUT_DIR}`);
|
|
522
|
+
}
|
|
523
|
+
const mod = await import("./generate-mdx-CR4bXlml.js");
|
|
524
|
+
if (typeof mod.runDocsGenerator === "function") await mod.runDocsGenerator();
|
|
525
|
+
else throw new Error("Failed to load docs generator. Export 'runDocsGenerator' not found.");
|
|
526
|
+
} catch (err) {
|
|
527
|
+
logger.error(err?.message || String(err));
|
|
528
|
+
process.exit(1);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
const docs = new Command().name("docs:build").alias("docs").description("generate docs from @bejamas/ui components").option("-c, --cwd <cwd>", "path to UI working directory").option("-o, --out <outDir>", "output directory for generated MDX files").action(async (opts) => {
|
|
532
|
+
await generateDocs({
|
|
533
|
+
cwd: opts.cwd,
|
|
534
|
+
outDir: opts.out,
|
|
535
|
+
verbose: Boolean(opts.verbose)
|
|
536
|
+
});
|
|
537
|
+
});
|
|
538
|
+
|
|
539
|
+
//#endregion
|
|
540
|
+
//#region src/utils/astro-imports.ts
|
|
541
|
+
function updateImportAliases(moduleSpecifier, config, isRemote = false) {
|
|
542
|
+
if (!moduleSpecifier.startsWith("@/") && !isRemote) return moduleSpecifier;
|
|
543
|
+
let specifier = moduleSpecifier;
|
|
544
|
+
if (isRemote && specifier.startsWith("@/")) specifier = specifier.replace(/^@\//, "@/registry/new-york/");
|
|
545
|
+
if (!specifier.startsWith("@/registry/")) {
|
|
546
|
+
const alias = config.aliases.components.split("/")[0];
|
|
547
|
+
return specifier.replace(/^@\//, `${alias}/`);
|
|
548
|
+
}
|
|
549
|
+
if (specifier.match(/^@\/registry\/(.+)\/ui/)) return specifier.replace(/^@\/registry\/(.+)\/ui/, config.aliases.ui ?? `${config.aliases.components}/ui`);
|
|
550
|
+
if (config.aliases.components && specifier.match(/^@\/registry\/(.+)\/components/)) return specifier.replace(/^@\/registry\/(.+)\/components/, config.aliases.components);
|
|
551
|
+
if (config.aliases.lib && specifier.match(/^@\/registry\/(.+)\/lib/)) return specifier.replace(/^@\/registry\/(.+)\/lib/, config.aliases.lib);
|
|
552
|
+
if (config.aliases.hooks && specifier.match(/^@\/registry\/(.+)\/hooks/)) return specifier.replace(/^@\/registry\/(.+)\/hooks/, config.aliases.hooks);
|
|
553
|
+
return specifier.replace(/^@\/registry\/[^/]+/, config.aliases.components);
|
|
554
|
+
}
|
|
555
|
+
function rewriteAstroImports(content, config) {
|
|
556
|
+
let updated = content;
|
|
557
|
+
const utilsAlias = config.aliases?.utils;
|
|
558
|
+
const utilsImport = `${typeof utilsAlias === "string" && utilsAlias.includes("/") ? utilsAlias.split("/")[0] : "@"}/lib/utils`;
|
|
559
|
+
updated = updated.replace(/import\s+([\s\S]*?)\s+from\s+["']([^"']+)["']/g, (full, importsPart, specifier) => {
|
|
560
|
+
const next = updateImportAliases(specifier, config, false);
|
|
561
|
+
let finalSpec = next;
|
|
562
|
+
if (typeof importsPart === "string" && importsPart.split(/[{},\s]/).some((part) => part === "cn") && config.aliases.utils && (next === utilsImport || next === "@/lib/utils")) finalSpec = utilsImport === next ? next.replace(utilsImport, config.aliases.utils) : config.aliases.utils;
|
|
563
|
+
if (finalSpec === specifier) return full;
|
|
564
|
+
return full.replace(specifier, finalSpec);
|
|
565
|
+
});
|
|
566
|
+
updated = updated.replace(/import\s+["']([^"']+)["']/g, (full, specifier) => {
|
|
567
|
+
const next = updateImportAliases(specifier, config, false);
|
|
568
|
+
if (next === specifier) return full;
|
|
569
|
+
return full.replace(specifier, next);
|
|
570
|
+
});
|
|
571
|
+
return updated;
|
|
572
|
+
}
|
|
573
|
+
async function fixAstroImports(cwd, isVerbose) {
|
|
574
|
+
const config = await getConfig(cwd);
|
|
575
|
+
if (!config) return;
|
|
576
|
+
const searchRoots = new Set([config.resolvedPaths.components, config.resolvedPaths.ui]);
|
|
577
|
+
for (const root of Array.from(searchRoots)) {
|
|
578
|
+
if (!root) continue;
|
|
579
|
+
const astroFiles = await fg("**/*.astro", {
|
|
580
|
+
cwd: root,
|
|
581
|
+
absolute: true,
|
|
582
|
+
dot: false
|
|
583
|
+
});
|
|
584
|
+
for (const filePath of astroFiles) {
|
|
585
|
+
const original = await fs.readFile(filePath, "utf8");
|
|
586
|
+
const rewritten = rewriteAstroImports(original, config);
|
|
587
|
+
if (rewritten === original) continue;
|
|
588
|
+
await fs.writeFile(filePath, rewritten, "utf8");
|
|
589
|
+
if (isVerbose) logger.info(`[bejamas-ui] fixed imports in ${path$1.relative(cwd, filePath)}`);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
//#endregion
|
|
595
|
+
//#region src/commands/add.ts
|
|
596
|
+
const DEFAULT_REGISTRY_URL = "https://ui.bejamas.com/r";
|
|
597
|
+
function extractOptionsForShadcn(rawArgv, cmd) {
|
|
598
|
+
if (typeof cmd.getOptionValueSource === "function") {
|
|
599
|
+
const opts = cmd.optsWithGlobals();
|
|
600
|
+
const forwarded$1 = [];
|
|
601
|
+
const getSource = (key) => cmd.getOptionValueSource(key);
|
|
602
|
+
const addBoolean = (key, flag, negateFlag) => {
|
|
603
|
+
if (getSource(key) !== "cli") return;
|
|
604
|
+
const value = opts[key];
|
|
605
|
+
if (typeof value !== "boolean") return;
|
|
606
|
+
if (value) forwarded$1.push(flag);
|
|
607
|
+
else if (negateFlag) forwarded$1.push(negateFlag);
|
|
608
|
+
};
|
|
609
|
+
const addString = (key, flag) => {
|
|
610
|
+
if (getSource(key) !== "cli") return;
|
|
611
|
+
const value = opts[key];
|
|
612
|
+
if (typeof value === "string") forwarded$1.push(flag, value);
|
|
613
|
+
};
|
|
614
|
+
addBoolean("yes", "--yes");
|
|
615
|
+
addBoolean("overwrite", "--overwrite");
|
|
616
|
+
addString("cwd", "--cwd");
|
|
617
|
+
addBoolean("all", "--all");
|
|
618
|
+
addString("path", "--path");
|
|
619
|
+
addBoolean("silent", "--silent");
|
|
620
|
+
addBoolean("srcDir", "--src-dir", "--no-src-dir");
|
|
621
|
+
const addIndex$1 = rawArgv.findIndex((arg) => arg === "add");
|
|
622
|
+
if (addIndex$1 !== -1) {
|
|
623
|
+
const rest$1 = rawArgv.slice(addIndex$1 + 1);
|
|
624
|
+
const doubleDashIndex = rest$1.indexOf("--");
|
|
625
|
+
if (doubleDashIndex !== -1) forwarded$1.push(...rest$1.slice(doubleDashIndex));
|
|
626
|
+
}
|
|
627
|
+
return forwarded$1;
|
|
628
|
+
}
|
|
629
|
+
const addIndex = rawArgv.findIndex((arg) => arg === "add");
|
|
630
|
+
if (addIndex === -1) return [];
|
|
631
|
+
const rest = rawArgv.slice(addIndex + 1);
|
|
632
|
+
const forwarded = [];
|
|
633
|
+
const optionsWithValues = new Set([
|
|
634
|
+
"-c",
|
|
635
|
+
"--cwd",
|
|
636
|
+
"-p",
|
|
637
|
+
"--path"
|
|
638
|
+
]);
|
|
639
|
+
const filteredFlags = new Set(["-v", "--verbose"]);
|
|
640
|
+
for (let i = 0; i < rest.length; i += 1) {
|
|
641
|
+
const token = rest[i];
|
|
642
|
+
if (token === "--") {
|
|
643
|
+
forwarded.push("--", ...rest.slice(i + 1));
|
|
644
|
+
break;
|
|
645
|
+
}
|
|
646
|
+
if (!token.startsWith("-")) continue;
|
|
647
|
+
if (filteredFlags.has(token)) continue;
|
|
648
|
+
forwarded.push(token);
|
|
649
|
+
if (token.includes("=")) continue;
|
|
650
|
+
if (optionsWithValues.has(token)) {
|
|
651
|
+
const next = rest[i + 1];
|
|
652
|
+
if (next) {
|
|
653
|
+
forwarded.push(next);
|
|
654
|
+
i += 1;
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
return forwarded;
|
|
659
|
+
}
|
|
660
|
+
async function addComponents(packages, forwardedOptions, isVerbose) {
|
|
661
|
+
const runner = await getPackageRunner(process.cwd());
|
|
662
|
+
const env = {
|
|
663
|
+
...process.env,
|
|
664
|
+
REGISTRY_URL: process.env.REGISTRY_URL || DEFAULT_REGISTRY_URL
|
|
665
|
+
};
|
|
666
|
+
const baseArgs = [
|
|
667
|
+
"shadcn@latest",
|
|
668
|
+
"add",
|
|
669
|
+
...packages,
|
|
670
|
+
...forwardedOptions
|
|
671
|
+
];
|
|
672
|
+
let cmd = "npx";
|
|
673
|
+
let args = ["-y", ...baseArgs];
|
|
674
|
+
if (runner === "bunx") {
|
|
675
|
+
cmd = "bunx";
|
|
676
|
+
args = baseArgs;
|
|
677
|
+
} else if (runner === "pnpm dlx") {
|
|
678
|
+
cmd = "pnpm";
|
|
679
|
+
args = ["dlx", ...baseArgs];
|
|
680
|
+
} else if (runner === "npx") {
|
|
681
|
+
cmd = "npx";
|
|
682
|
+
args = ["-y", ...baseArgs];
|
|
683
|
+
}
|
|
684
|
+
if (isVerbose) logger.info(`[bejamas-ui] ${cmd} ${args.join(" ")}`);
|
|
685
|
+
try {
|
|
686
|
+
await execa(cmd, args, {
|
|
687
|
+
stdio: "inherit",
|
|
688
|
+
env
|
|
689
|
+
});
|
|
690
|
+
} catch (err) {
|
|
691
|
+
process.exit(1);
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
const add = new Command().name("add").description("Add components via shadcn@latest using registry URLs").argument("[components...]", "Component package names to add").option("-y, --yes", "skip confirmation prompt.", false).option("-o, --overwrite", "overwrite existing files.", false).option("-c, --cwd <cwd>", "the working directory. defaults to the current directory.", process.cwd()).option("-a, --all", "add all available components", false).option("-p, --path <path>", "the path to add the component to.").option("-s, --silent", "mute output.", false).option("--src-dir", "use the src directory when creating a new project.", false).option("--no-src-dir", "do not use the src directory when creating a new project.").action(async function action(packages, _opts, cmd) {
|
|
695
|
+
const root = cmd?.parent;
|
|
696
|
+
const verbose = Boolean(root?.opts?.().verbose);
|
|
697
|
+
const rawArgv = process.argv.slice(2);
|
|
698
|
+
const forwardedOptions = extractOptionsForShadcn(rawArgv, cmd);
|
|
699
|
+
const cwd = (typeof cmd.optsWithGlobals === "function" ? cmd.optsWithGlobals() : cmd.opts?.() ?? {}).cwd || process.cwd();
|
|
700
|
+
await addComponents(packages || [], forwardedOptions, verbose);
|
|
701
|
+
await fixAstroImports(cwd, verbose);
|
|
702
|
+
});
|
|
703
|
+
|
|
704
|
+
//#endregion
|
|
705
|
+
//#region src/index.ts
|
|
706
|
+
const pkg = createRequire(import.meta.url)("../package.json");
|
|
707
|
+
const program = new Command().name("bejamas").description("bejamas/ui cli").configureHelp({ helpWidth: Math.min(100, process.stdout.columns || 100) }).version(pkg.version, "-v, --version", "output the version number");
|
|
708
|
+
program.addCommand(init);
|
|
709
|
+
program.addCommand(add);
|
|
710
|
+
program.addCommand(docs);
|
|
711
|
+
program.parse(process.argv);
|
|
712
|
+
var src_default = program;
|
|
713
|
+
|
|
714
|
+
//#endregion
|
|
715
|
+
export { src_default as default };
|
|
716
|
+
//# sourceMappingURL=index.js.map
|