create-jant 0.2.5 → 0.3.11
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 +111 -27
- package/package.json +1 -1
- package/template/scripts/seed-demo.sql +6 -6
- package/template/vite.config.ts +2 -2
package/dist/index.js
CHANGED
|
@@ -2,13 +2,14 @@
|
|
|
2
2
|
import { program } from "commander";
|
|
3
3
|
import * as p from "@clack/prompts";
|
|
4
4
|
import chalk from "chalk";
|
|
5
|
+
import { execSync } from "child_process";
|
|
5
6
|
import crypto from "crypto";
|
|
6
7
|
import fs from "fs-extra";
|
|
7
8
|
import path from "path";
|
|
8
9
|
import { fileURLToPath } from "url";
|
|
9
10
|
var __filename = fileURLToPath(import.meta.url);
|
|
10
11
|
var __dirname = path.dirname(__filename);
|
|
11
|
-
var CORE_VERSION = "0.3.
|
|
12
|
+
var CORE_VERSION = "0.3.11";
|
|
12
13
|
var TEMPLATE_DIR = fs.existsSync(path.resolve(__dirname, "../template")) ? path.resolve(__dirname, "../template") : path.resolve(__dirname, "../../../templates/jant-site");
|
|
13
14
|
function isValidProjectName(name) {
|
|
14
15
|
return /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/.test(name);
|
|
@@ -19,8 +20,57 @@ function toValidProjectName(name) {
|
|
|
19
20
|
function generateAuthSecret() {
|
|
20
21
|
return crypto.randomBytes(32).toString("base64");
|
|
21
22
|
}
|
|
23
|
+
function detectPackageManager() {
|
|
24
|
+
const userAgent = process.env.npm_config_user_agent;
|
|
25
|
+
if (userAgent) {
|
|
26
|
+
const name = userAgent.split("/")[0];
|
|
27
|
+
if (name === "pnpm" || name === "yarn" || name === "npm") {
|
|
28
|
+
return name;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
for (const pm of ["pnpm", "yarn", "npm"]) {
|
|
32
|
+
try {
|
|
33
|
+
execSync(`${pm} --version`, { stdio: "ignore" });
|
|
34
|
+
return pm;
|
|
35
|
+
} catch {
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return "npm";
|
|
39
|
+
}
|
|
40
|
+
function formatRunCmd(pm, script) {
|
|
41
|
+
return pm === "npm" ? `npm run ${script}` : `${pm} ${script}`;
|
|
42
|
+
}
|
|
43
|
+
function runCommand(cmd, cwd) {
|
|
44
|
+
try {
|
|
45
|
+
execSync(cmd, { stdio: "ignore", cwd });
|
|
46
|
+
return true;
|
|
47
|
+
} catch {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function processMarkers(content, vars) {
|
|
52
|
+
content = content.replace(
|
|
53
|
+
/\s*(?:\/\/|#)\s*@create-jant:\s*@remove-start[\s\S]*?(?:\/\/|#)\s*@create-jant:\s*@remove-end\n?/g,
|
|
54
|
+
""
|
|
55
|
+
);
|
|
56
|
+
content = content.replace(
|
|
57
|
+
/^.*(?:\/\/|#)\s*@create-jant:\s*@remove\s*\n?/gm,
|
|
58
|
+
""
|
|
59
|
+
);
|
|
60
|
+
content = content.replace(
|
|
61
|
+
/^(.+=\s*)"[^"]*"\s*(?:\/\/|#)\s*@create-jant:\s*"([^"]*)"/gm,
|
|
62
|
+
(_, prefix, template) => {
|
|
63
|
+
const value = template.replace(
|
|
64
|
+
/\$\{(\w+)\}/g,
|
|
65
|
+
(__, key) => vars[key] ?? ""
|
|
66
|
+
);
|
|
67
|
+
return `${prefix}"${value}"`;
|
|
68
|
+
}
|
|
69
|
+
);
|
|
70
|
+
return content;
|
|
71
|
+
}
|
|
22
72
|
async function copyTemplate(config) {
|
|
23
|
-
const { projectName, targetDir } = config;
|
|
73
|
+
const { projectName, targetDir, packageManager } = config;
|
|
24
74
|
await fs.copy(TEMPLATE_DIR, targetDir, {
|
|
25
75
|
filter: (src) => {
|
|
26
76
|
const basename = path.basename(src);
|
|
@@ -30,6 +80,10 @@ async function copyTemplate(config) {
|
|
|
30
80
|
if (basename === ".swc") return false;
|
|
31
81
|
if (basename === ".dev.vars") return false;
|
|
32
82
|
if (basename === "pnpm-lock.yaml") return false;
|
|
83
|
+
if (basename === "yarn.lock") return false;
|
|
84
|
+
if (basename === "package-lock.json") return false;
|
|
85
|
+
if (basename === "bun.lockb") return false;
|
|
86
|
+
if (basename === "pnpm-workspace.yaml") return false;
|
|
33
87
|
if (basename === "dist") return false;
|
|
34
88
|
if (basename === "wrangler.demo.toml") return false;
|
|
35
89
|
if (basename === "reset-demo.sql") return false;
|
|
@@ -61,23 +115,25 @@ async function copyTemplate(config) {
|
|
|
61
115
|
if (pkg.dependencies?.["@jant/core"] === "workspace:*") {
|
|
62
116
|
pkg.dependencies["@jant/core"] = `^${CORE_VERSION}`;
|
|
63
117
|
}
|
|
118
|
+
if (packageManager !== "pnpm") {
|
|
119
|
+
delete pkg.packageManager;
|
|
120
|
+
if (pkg.scripts) {
|
|
121
|
+
for (const [key, value] of Object.entries(pkg.scripts)) {
|
|
122
|
+
if (typeof value === "string") {
|
|
123
|
+
pkg.scripts[key] = value.replace(
|
|
124
|
+
/pnpm (\S+)/g,
|
|
125
|
+
(_, script) => formatRunCmd(packageManager, script)
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
64
131
|
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
|
65
132
|
}
|
|
66
133
|
const wranglerPath = path.join(targetDir, "wrangler.toml");
|
|
67
134
|
if (await fs.pathExists(wranglerPath)) {
|
|
68
135
|
let content = await fs.readFile(wranglerPath, "utf-8");
|
|
69
|
-
|
|
70
|
-
content = content.replace(
|
|
71
|
-
/^(.+=\s*)"[^"]*"\s*#\s*@create-jant:\s*"([^"]*)"/gm,
|
|
72
|
-
(_, prefix, template) => {
|
|
73
|
-
const value = template.replace(
|
|
74
|
-
/\$\{(\w+)\}/g,
|
|
75
|
-
(__, key) => vars[key] ?? ""
|
|
76
|
-
);
|
|
77
|
-
return `${prefix}"${value}"`;
|
|
78
|
-
}
|
|
79
|
-
);
|
|
80
|
-
content = content.replace(/^.*#\s*@create-jant:\s*@remove\s*\n?/gm, "");
|
|
136
|
+
content = processMarkers(content, { name: projectName });
|
|
81
137
|
await fs.writeFile(wranglerPath, content, "utf-8");
|
|
82
138
|
}
|
|
83
139
|
const authSecret = generateAuthSecret();
|
|
@@ -113,21 +169,20 @@ S3_SECRET_ACCESS_KEY=
|
|
|
113
169
|
const viteConfigPath = path.join(targetDir, "vite.config.ts");
|
|
114
170
|
if (await fs.pathExists(viteConfigPath)) {
|
|
115
171
|
let content = await fs.readFile(viteConfigPath, "utf-8");
|
|
116
|
-
content = content
|
|
117
|
-
/\s*\/\/ @monorepo-only-start[\s\S]*?\/\/ @monorepo-only-end\n?/g,
|
|
118
|
-
""
|
|
119
|
-
);
|
|
120
|
-
content = content.replace(
|
|
121
|
-
/@jant\/core\/src\/([^"']+)\.ts/g,
|
|
122
|
-
"@jant/core/dist/$1.js"
|
|
123
|
-
);
|
|
172
|
+
content = processMarkers(content, {});
|
|
124
173
|
await fs.writeFile(viteConfigPath, content, "utf-8");
|
|
125
174
|
}
|
|
175
|
+
if (packageManager === "pnpm") {
|
|
176
|
+
const wsSource = path.join(TEMPLATE_DIR, "pnpm-workspace.yaml");
|
|
177
|
+
if (await fs.pathExists(wsSource)) {
|
|
178
|
+
await fs.copy(wsSource, path.join(targetDir, "pnpm-workspace.yaml"));
|
|
179
|
+
}
|
|
180
|
+
}
|
|
126
181
|
}
|
|
127
182
|
async function main() {
|
|
128
183
|
console.log();
|
|
129
184
|
p.intro(chalk.bgCyan.black(" create-jant "));
|
|
130
|
-
program.name("create-jant").description("Create a new Jant project").argument("[project-name]", "Name of the project").option("-y, --yes", "Skip prompts and use defaults").option("--s3", "Use S3-compatible storage instead of Cloudflare R2").parse();
|
|
185
|
+
program.name("create-jant").description("Create a new Jant project").argument("[project-name]", "Name of the project").option("-y, --yes", "Skip prompts and use defaults").option("--s3", "Use S3-compatible storage instead of Cloudflare R2").option("--no-install", "Skip dependency installation").option("--no-git", "Skip git initialization").parse();
|
|
131
186
|
const args = program.args;
|
|
132
187
|
const opts = program.opts();
|
|
133
188
|
let projectName;
|
|
@@ -183,9 +238,13 @@ async function main() {
|
|
|
183
238
|
await fs.emptyDir(targetDir);
|
|
184
239
|
}
|
|
185
240
|
}
|
|
241
|
+
const packageManager = detectPackageManager();
|
|
186
242
|
const config = {
|
|
187
243
|
projectName,
|
|
188
244
|
targetDir,
|
|
245
|
+
packageManager,
|
|
246
|
+
install: opts.install,
|
|
247
|
+
git: opts.git,
|
|
189
248
|
s3: opts.s3
|
|
190
249
|
};
|
|
191
250
|
const spinner2 = p.spinner();
|
|
@@ -198,11 +257,36 @@ async function main() {
|
|
|
198
257
|
p.log.error(error instanceof Error ? error.message : String(error));
|
|
199
258
|
process.exit(1);
|
|
200
259
|
}
|
|
260
|
+
let installOk = false;
|
|
261
|
+
if (config.install) {
|
|
262
|
+
spinner2.start("Installing dependencies...");
|
|
263
|
+
installOk = runCommand(`${packageManager} install`, targetDir);
|
|
264
|
+
if (installOk) {
|
|
265
|
+
spinner2.stop("Dependencies installed.");
|
|
266
|
+
} else {
|
|
267
|
+
spinner2.stop(
|
|
268
|
+
chalk.yellow(
|
|
269
|
+
`Failed to install dependencies. Run ${chalk.bold(`${packageManager} install`)} manually.`
|
|
270
|
+
)
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
if (config.git) {
|
|
275
|
+
spinner2.start("Initializing git repository...");
|
|
276
|
+
const gitOk = runCommand("git init", targetDir) && runCommand("git add -A", targetDir) && runCommand('git commit -m "Initial commit"', targetDir);
|
|
277
|
+
if (gitOk) {
|
|
278
|
+
spinner2.stop("Git repository initialized.");
|
|
279
|
+
} else {
|
|
280
|
+
spinner2.stop("Skipped git initialization.");
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
const steps = [`cd ${projectName}`];
|
|
284
|
+
if (!config.install || !installOk) {
|
|
285
|
+
steps.push(`${packageManager} install`);
|
|
286
|
+
}
|
|
287
|
+
steps.push(formatRunCmd(packageManager, "dev"));
|
|
201
288
|
console.log();
|
|
202
|
-
p.note(
|
|
203
|
-
[`cd ${projectName}`, "pnpm install", "pnpm dev"].join("\n"),
|
|
204
|
-
"Next steps"
|
|
205
|
-
);
|
|
289
|
+
p.note(steps.join("\n"), "Next steps");
|
|
206
290
|
p.outro(chalk.green("Happy coding!"));
|
|
207
291
|
}
|
|
208
292
|
main().catch((error) => {
|
package/package.json
CHANGED
|
@@ -187,9 +187,9 @@ INSERT INTO post_collections VALUES(1,1,1770689095);
|
|
|
187
187
|
INSERT INTO post_collections VALUES(6,2,1770758568);
|
|
188
188
|
|
|
189
189
|
-- media
|
|
190
|
-
INSERT INTO media VALUES('019c496c-46bd-7954-bd6a-77b1b8f1d451',NULL,'019c496c-46bd-7954-bd6a-77b1b8f1d451.webp','tegan-conway-KaFfNTw8OYQ-unsplash.webp','image/webp',715364,'media/2026/02/019c496c-46bd-7954-bd6a-77b1b8f1d451.webp',NULL,NULL,NULL,1770758358,0,NULL);
|
|
191
|
-
INSERT INTO media VALUES('019c496c-5e44-70d2-ac8a-c0c0bdaab65c',6,'019c496c-5e44-70d2-ac8a-c0c0bdaab65c.webp','land-o-lakes-inc-9w6Qb-dqBwE-unsplash.webp','image/webp',306042,'media/2026/02/019c496c-5e44-70d2-ac8a-c0c0bdaab65c.webp',NULL,NULL,NULL,1770758364,3,NULL);
|
|
192
|
-
INSERT INTO media VALUES('019c496d-5011-7981-89a0-b4373a695d78',6,'019c496d-5011-7981-89a0-b4373a695d78.webp','land-o-lakes-inc-k71TQkbVIgI-unsplash.webp','image/webp',597680,'media/2026/02/019c496d-5011-7981-89a0-b4373a695d78.webp',NULL,NULL,NULL,1770758426,2,NULL);
|
|
193
|
-
INSERT INTO media VALUES('019c496d-630c-70b4-9004-51a194746566',6,'019c496d-630c-70b4-9004-51a194746566.webp','thingsneverchange-CgHNmQ0c2w4-unsplash.webp','image/webp',358320,'media/2026/02/019c496d-630c-70b4-9004-51a194746566.webp',NULL,NULL,NULL,1770758431,1,NULL);
|
|
194
|
-
INSERT INTO media VALUES('019c496d-720f-70d2-98b8-3779457de73c',6,'019c496d-720f-70d2-98b8-3779457de73c.webp','willian-justen-de-vasconcellos-7jg7Y_Mlf2Q-unsplash.webp','image/webp',478956,'media/2026/02/019c496d-720f-70d2-98b8-3779457de73c.webp',NULL,NULL,NULL,1770758435,0,NULL);
|
|
195
|
-
INSERT INTO media VALUES('019c496e-6904-7f61-b14f-080035ffe23f',5,'019c496e-6904-7f61-b14f-080035ffe23f.webp','richard-stachmann-Es--yoQocSM-unsplash.webp','image/webp',381534,'media/2026/02/019c496e-6904-7f61-b14f-080035ffe23f.webp',NULL,NULL,NULL,1770758498,0,NULL);
|
|
190
|
+
INSERT INTO media VALUES('019c496c-46bd-7954-bd6a-77b1b8f1d451',NULL,'019c496c-46bd-7954-bd6a-77b1b8f1d451.webp','tegan-conway-KaFfNTw8OYQ-unsplash.webp','image/webp',715364,'media/2026/02/019c496c-46bd-7954-bd6a-77b1b8f1d451.webp',NULL,NULL,NULL,1770758358,0,NULL,'r2');
|
|
191
|
+
INSERT INTO media VALUES('019c496c-5e44-70d2-ac8a-c0c0bdaab65c',6,'019c496c-5e44-70d2-ac8a-c0c0bdaab65c.webp','land-o-lakes-inc-9w6Qb-dqBwE-unsplash.webp','image/webp',306042,'media/2026/02/019c496c-5e44-70d2-ac8a-c0c0bdaab65c.webp',NULL,NULL,NULL,1770758364,3,NULL,'r2');
|
|
192
|
+
INSERT INTO media VALUES('019c496d-5011-7981-89a0-b4373a695d78',6,'019c496d-5011-7981-89a0-b4373a695d78.webp','land-o-lakes-inc-k71TQkbVIgI-unsplash.webp','image/webp',597680,'media/2026/02/019c496d-5011-7981-89a0-b4373a695d78.webp',NULL,NULL,NULL,1770758426,2,NULL,'r2');
|
|
193
|
+
INSERT INTO media VALUES('019c496d-630c-70b4-9004-51a194746566',6,'019c496d-630c-70b4-9004-51a194746566.webp','thingsneverchange-CgHNmQ0c2w4-unsplash.webp','image/webp',358320,'media/2026/02/019c496d-630c-70b4-9004-51a194746566.webp',NULL,NULL,NULL,1770758431,1,NULL,'r2');
|
|
194
|
+
INSERT INTO media VALUES('019c496d-720f-70d2-98b8-3779457de73c',6,'019c496d-720f-70d2-98b8-3779457de73c.webp','willian-justen-de-vasconcellos-7jg7Y_Mlf2Q-unsplash.webp','image/webp',478956,'media/2026/02/019c496d-720f-70d2-98b8-3779457de73c.webp',NULL,NULL,NULL,1770758435,0,NULL,'r2');
|
|
195
|
+
INSERT INTO media VALUES('019c496e-6904-7f61-b14f-080035ffe23f',5,'019c496e-6904-7f61-b14f-080035ffe23f.webp','richard-stachmann-Es--yoQocSM-unsplash.webp','image/webp',381534,'media/2026/02/019c496e-6904-7f61-b14f-080035ffe23f.webp',NULL,NULL,NULL,1770758498,0,NULL,'r2');
|
package/template/vite.config.ts
CHANGED
|
@@ -193,7 +193,7 @@ export default defineConfig({
|
|
|
193
193
|
|
|
194
194
|
resolve: {
|
|
195
195
|
alias: {
|
|
196
|
-
// @
|
|
196
|
+
// @create-jant: @remove-start
|
|
197
197
|
// Monorepo development aliases
|
|
198
198
|
// - @lingui/react/macro: Prevents Vite dependency scan error. Source code imports
|
|
199
199
|
// from @lingui/react/macro (for SWC plugin), but we use Hono JSX. SWC rewrites
|
|
@@ -206,7 +206,7 @@ export default defineConfig({
|
|
|
206
206
|
"../../packages/core/src/i18n/index.ts",
|
|
207
207
|
),
|
|
208
208
|
"@jant/core": resolve(__dirname, "../../packages/core/src"),
|
|
209
|
-
// @
|
|
209
|
+
// @create-jant: @remove-end
|
|
210
210
|
},
|
|
211
211
|
},
|
|
212
212
|
});
|