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 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.9";
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
- const vars = { name: projectName };
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.replace(
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-jant",
3
- "version": "0.2.5",
3
+ "version": "0.3.11",
4
4
  "description": "Create a new Jant project",
5
5
  "type": "module",
6
6
  "bin": {
@@ -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');
@@ -193,7 +193,7 @@ export default defineConfig({
193
193
 
194
194
  resolve: {
195
195
  alias: {
196
- // @monorepo-only-start
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
- // @monorepo-only-end
209
+ // @create-jant: @remove-end
210
210
  },
211
211
  },
212
212
  });