create-bodhi-js 0.6.0 → 0.7.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 +69 -15
- package/package.json +5 -2
package/dist/index.js
CHANGED
|
@@ -26,7 +26,9 @@ var TEMPLATE_FILES = [
|
|
|
26
26
|
"CONTRIBUTING.md",
|
|
27
27
|
"src/App.tsx",
|
|
28
28
|
".github/SECURITY.md",
|
|
29
|
-
".github/ISSUE_TEMPLATE/config.yml"
|
|
29
|
+
".github/ISSUE_TEMPLATE/config.yml",
|
|
30
|
+
".github/workflows/ci.yml",
|
|
31
|
+
".github/workflows/deploy-pages.yml"
|
|
30
32
|
];
|
|
31
33
|
async function processTemplates(targetDir, vars) {
|
|
32
34
|
for (const file of TEMPLATE_FILES) {
|
|
@@ -36,7 +38,11 @@ async function processTemplates(targetDir, vars) {
|
|
|
36
38
|
const template = Handlebars.compile(content);
|
|
37
39
|
const rendered = template(vars);
|
|
38
40
|
await fs.writeFile(filePath, rendered, "utf-8");
|
|
39
|
-
} catch {
|
|
41
|
+
} catch (error) {
|
|
42
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
throw new Error(`Failed to process template ${file}: ${error}`);
|
|
40
46
|
}
|
|
41
47
|
}
|
|
42
48
|
}
|
|
@@ -45,6 +51,9 @@ async function processTemplates(targetDir, vars) {
|
|
|
45
51
|
import { exec } from "child_process";
|
|
46
52
|
import { promisify } from "util";
|
|
47
53
|
var execAsync = promisify(exec);
|
|
54
|
+
function isLocalPath(templateUrl) {
|
|
55
|
+
return templateUrl.startsWith("/") || templateUrl.startsWith("./") || templateUrl.startsWith("../");
|
|
56
|
+
}
|
|
48
57
|
async function scaffold(options) {
|
|
49
58
|
const {
|
|
50
59
|
projectName,
|
|
@@ -54,7 +63,9 @@ async function scaffold(options) {
|
|
|
54
63
|
basePath,
|
|
55
64
|
pathSegmentsToKeep,
|
|
56
65
|
install,
|
|
57
|
-
git
|
|
66
|
+
git,
|
|
67
|
+
devClientId,
|
|
68
|
+
prodClientId
|
|
58
69
|
} = options;
|
|
59
70
|
const targetDir = path2.resolve(process.cwd(), projectName);
|
|
60
71
|
try {
|
|
@@ -65,10 +76,15 @@ async function scaffold(options) {
|
|
|
65
76
|
throw err;
|
|
66
77
|
}
|
|
67
78
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
79
|
+
if (isLocalPath(templateUrl)) {
|
|
80
|
+
await fs2.cp(templateUrl, targetDir, { recursive: true });
|
|
81
|
+
} else {
|
|
82
|
+
await downloadTemplate(templateUrl, {
|
|
83
|
+
dir: targetDir,
|
|
84
|
+
offline: false,
|
|
85
|
+
force: true
|
|
86
|
+
});
|
|
87
|
+
}
|
|
72
88
|
const templateSubdir = path2.join(targetDir, "template");
|
|
73
89
|
try {
|
|
74
90
|
await fs2.access(templateSubdir);
|
|
@@ -93,7 +109,9 @@ async function scaffold(options) {
|
|
|
93
109
|
githubOrg,
|
|
94
110
|
githubPages,
|
|
95
111
|
basePath,
|
|
96
|
-
pathSegmentsToKeep
|
|
112
|
+
pathSegmentsToKeep,
|
|
113
|
+
devClientId,
|
|
114
|
+
prodClientId
|
|
97
115
|
});
|
|
98
116
|
if (!githubPages) {
|
|
99
117
|
const filesToDelete = [
|
|
@@ -107,16 +125,23 @@ async function scaffold(options) {
|
|
|
107
125
|
}
|
|
108
126
|
}
|
|
109
127
|
}
|
|
110
|
-
const metaFiles = ["template.json", "test-template.sh", "TECH.md"];
|
|
128
|
+
const metaFiles = ["template.json", "test-template.sh", "TECH.md", ".env.local"];
|
|
111
129
|
for (const file of metaFiles) {
|
|
112
130
|
try {
|
|
113
131
|
await fs2.unlink(path2.join(targetDir, file));
|
|
114
132
|
} catch {
|
|
115
133
|
}
|
|
116
134
|
}
|
|
135
|
+
try {
|
|
136
|
+
await fs2.rm(path2.join(targetDir, "template"), { recursive: true, force: true });
|
|
137
|
+
} catch {
|
|
138
|
+
}
|
|
117
139
|
if (git) {
|
|
118
140
|
try {
|
|
119
141
|
await execAsync("git init", { cwd: targetDir });
|
|
142
|
+
if (install) {
|
|
143
|
+
await execAsync("npm install", { cwd: targetDir });
|
|
144
|
+
}
|
|
120
145
|
await execAsync("git add .", { cwd: targetDir });
|
|
121
146
|
await execAsync('git commit -m "chore: initial commit from create-bodhi-js"', {
|
|
122
147
|
cwd: targetDir
|
|
@@ -124,19 +149,29 @@ async function scaffold(options) {
|
|
|
124
149
|
} catch {
|
|
125
150
|
console.warn("Warning: Git initialization failed");
|
|
126
151
|
}
|
|
127
|
-
}
|
|
128
|
-
if (install) {
|
|
152
|
+
} else if (install) {
|
|
129
153
|
await execAsync("npm install", { cwd: targetDir });
|
|
130
154
|
}
|
|
155
|
+
if (devClientId) {
|
|
156
|
+
const envContent = `VITE_BODHI_APP_CLIENT_ID=${devClientId}
|
|
157
|
+
VITE_BODHI_AUTH_SERVER_URL=https://main-id.getbodhi.app/realms/bodhi
|
|
158
|
+
`;
|
|
159
|
+
await fs2.writeFile(path2.join(targetDir, ".env.local"), envContent, "utf-8");
|
|
160
|
+
}
|
|
131
161
|
}
|
|
132
162
|
|
|
133
163
|
// src/templates.ts
|
|
164
|
+
import { existsSync } from "fs";
|
|
165
|
+
import { resolve } from "path";
|
|
134
166
|
var TEMPLATES = {
|
|
135
167
|
react: "gh:BodhiSearch/template-bodhi-react-vite"
|
|
136
168
|
// Future templates
|
|
137
169
|
// svelte: 'gh:BodhiSearch/template-bodhi-svelte-vite',
|
|
138
170
|
// vue: 'gh:BodhiSearch/template-bodhi-vue-vite',
|
|
139
171
|
};
|
|
172
|
+
function isLocalPath2(name) {
|
|
173
|
+
return name.startsWith("/") || name.startsWith("./") || name.startsWith("../");
|
|
174
|
+
}
|
|
140
175
|
function resolveTemplate(name) {
|
|
141
176
|
if (TEMPLATES[name]) {
|
|
142
177
|
return TEMPLATES[name];
|
|
@@ -144,18 +179,33 @@ function resolveTemplate(name) {
|
|
|
144
179
|
if (name.includes(":")) {
|
|
145
180
|
return name;
|
|
146
181
|
}
|
|
182
|
+
if (isLocalPath2(name)) {
|
|
183
|
+
const absolutePath = name.startsWith("/") ? name : resolve(process.cwd(), name);
|
|
184
|
+
if (!existsSync(absolutePath)) {
|
|
185
|
+
throw new Error(`Template path does not exist: ${absolutePath}`);
|
|
186
|
+
}
|
|
187
|
+
return absolutePath;
|
|
188
|
+
}
|
|
147
189
|
throw new Error(
|
|
148
190
|
`Unknown template: ${name}
|
|
149
191
|
|
|
150
192
|
Available templates:
|
|
151
|
-
${Object.keys(TEMPLATES).map((t) => ` - ${t}`).join(
|
|
193
|
+
${Object.keys(TEMPLATES).map((t) => ` - ${t}`).join(
|
|
194
|
+
"\n"
|
|
195
|
+
)}
|
|
152
196
|
|
|
153
|
-
Or use a custom template: gh:user/repo
|
|
197
|
+
Or use a custom template: gh:user/repo
|
|
198
|
+
Or use a local path: /path/to/template`
|
|
154
199
|
);
|
|
155
200
|
}
|
|
156
201
|
|
|
157
202
|
// src/cli.ts
|
|
158
203
|
async function create(projectName, options) {
|
|
204
|
+
if (options.ci) {
|
|
205
|
+
process.env.CI = "true";
|
|
206
|
+
process.env.NO_COLOR = "1";
|
|
207
|
+
delete process.env.FORCE_COLOR;
|
|
208
|
+
}
|
|
159
209
|
console.log();
|
|
160
210
|
p.intro(pc.bgCyan(pc.black(" create-bodhi-js ")));
|
|
161
211
|
let targetDir = projectName;
|
|
@@ -222,6 +272,8 @@ async function create(projectName, options) {
|
|
|
222
272
|
}
|
|
223
273
|
basePath = `/${targetDir}/`;
|
|
224
274
|
pathSegmentsToKeep = 1;
|
|
275
|
+
} else {
|
|
276
|
+
githubOrg = "YOUR_ORG";
|
|
225
277
|
}
|
|
226
278
|
const spinner2 = p.spinner();
|
|
227
279
|
spinner2.start("Scaffolding project...");
|
|
@@ -234,7 +286,9 @@ async function create(projectName, options) {
|
|
|
234
286
|
basePath,
|
|
235
287
|
pathSegmentsToKeep,
|
|
236
288
|
install: options.install,
|
|
237
|
-
git: options.git
|
|
289
|
+
git: options.git,
|
|
290
|
+
devClientId: options.devClientId,
|
|
291
|
+
prodClientId: options.prodClientId
|
|
238
292
|
});
|
|
239
293
|
spinner2.stop("Project scaffolded successfully!");
|
|
240
294
|
p.note(
|
|
@@ -251,7 +305,7 @@ async function create(projectName, options) {
|
|
|
251
305
|
|
|
252
306
|
// src/index.ts
|
|
253
307
|
var program = new Command();
|
|
254
|
-
program.name("create-bodhi-js").description("Scaffold Bodhi-powered applications").version("0.1.0").argument("[project-name]", "Name of the project").option("-t, --template <name>", "Template
|
|
308
|
+
program.name("create-bodhi-js").description("Scaffold Bodhi-powered applications").version("0.1.0").argument("[project-name]", "Name of the project").option("-t, --template <name>", "Template name or local path", "react").option("--no-install", "Skip dependency installation").option("--no-git", "Skip git initialization").option("--github-pages", "Enable GitHub Pages deployment setup").option("--no-github-pages", "Disable GitHub Pages deployment setup").option("--github-org <org>", "GitHub repository owner (user/org)").option("--dev-client-id <id>", "Development client ID (for .env.local and CI)").option("--prod-client-id <id>", "Production client ID (for GitHub Pages deploy)").option("--ci", "Run in CI mode (disable animations)").action(async (projectName, options) => {
|
|
255
309
|
await create(projectName, options);
|
|
256
310
|
});
|
|
257
311
|
program.parse();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-bodhi-js",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Scaffold Bodhi-powered applications with React, TypeScript, Vite, and more",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
"lint:fix": "eslint . --fix",
|
|
21
21
|
"check": "npm run lint && npm run typecheck",
|
|
22
22
|
"check:fix": "npm run lint:fix && npm run typecheck",
|
|
23
|
-
"test": "
|
|
23
|
+
"test": "playwright test",
|
|
24
|
+
"test:headed": "playwright test --headed",
|
|
24
25
|
"prepublishOnly": "npm run build"
|
|
25
26
|
},
|
|
26
27
|
"keywords": [
|
|
@@ -53,7 +54,9 @@
|
|
|
53
54
|
},
|
|
54
55
|
"devDependencies": {
|
|
55
56
|
"@eslint/js": "^9.39.1",
|
|
57
|
+
"@playwright/test": "^1.57.0",
|
|
56
58
|
"@types/node": "^25.0.3",
|
|
59
|
+
"dotenv": "^17.2.3",
|
|
57
60
|
"eslint": "^9.39.1",
|
|
58
61
|
"eslint-config-prettier": "^10.1.8",
|
|
59
62
|
"eslint-plugin-prettier": "^5.5.4",
|