create-m5kdev 0.21.4 → 0.21.6

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.
Files changed (40) hide show
  1. package/dist/_virtual/_rolldown/runtime.cjs +23 -0
  2. package/dist/src/constants.cjs +13 -0
  3. package/dist/src/{constants.mjs.map → constants.cjs.map} +1 -1
  4. package/dist/src/{constants.d.mts → constants.d.cts} +1 -1
  5. package/dist/src/create.cjs +36 -0
  6. package/dist/src/create.cjs.map +1 -0
  7. package/dist/src/{create.d.mts → create.d.cts} +2 -2
  8. package/dist/src/fs.cjs +56 -0
  9. package/dist/src/fs.cjs.map +1 -0
  10. package/dist/src/{fs.d.mts → fs.d.cts} +2 -2
  11. package/dist/src/{index.mjs → index.cjs} +2 -4
  12. package/dist/src/index.cjs.map +1 -0
  13. package/dist/src/paths.cjs +17 -0
  14. package/dist/src/paths.cjs.map +1 -0
  15. package/dist/src/{paths.d.mts → paths.d.cts} +1 -1
  16. package/dist/src/prompts.cjs +48 -0
  17. package/dist/src/prompts.cjs.map +1 -0
  18. package/dist/src/{prompts.d.mts → prompts.d.cts} +2 -2
  19. package/dist/src/{runCli.mjs → runCli.cjs} +6 -4
  20. package/dist/src/runCli.cjs.map +1 -0
  21. package/dist/src/{runCli.d.mts → runCli.d.cts} +1 -1
  22. package/dist/src/{strings.mjs → strings.cjs} +10 -4
  23. package/dist/src/{strings.mjs.map → strings.cjs.map} +1 -1
  24. package/dist/src/{strings.d.mts → strings.d.cts} +2 -2
  25. package/dist/src/types.cjs +0 -0
  26. package/dist/src/{types.d.mts → types.d.cts} +1 -1
  27. package/package.json +1 -1
  28. package/dist/src/constants.mjs +0 -10
  29. package/dist/src/create.mjs +0 -33
  30. package/dist/src/create.mjs.map +0 -1
  31. package/dist/src/fs.mjs +0 -50
  32. package/dist/src/fs.mjs.map +0 -1
  33. package/dist/src/index.mjs.map +0 -1
  34. package/dist/src/paths.mjs +0 -13
  35. package/dist/src/paths.mjs.map +0 -1
  36. package/dist/src/prompts.mjs +0 -45
  37. package/dist/src/prompts.mjs.map +0 -1
  38. package/dist/src/runCli.mjs.map +0 -1
  39. package/dist/src/types.mjs +0 -1
  40. /package/dist/src/{index.d.mts → index.d.cts} +0 -0
@@ -0,0 +1,23 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
10
+ key = keys[i];
11
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
12
+ get: ((k) => from[k]).bind(null, key),
13
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
14
+ });
15
+ }
16
+ return to;
17
+ };
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
19
+ value: mod,
20
+ enumerable: true
21
+ }) : target, mod));
22
+ //#endregion
23
+ exports.__toESM = __toESM;
@@ -0,0 +1,13 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region src/constants.ts
3
+ const TEMPLATE_NAME = "minimal-app";
4
+ const DEFAULT_APP_NAME = "M5 Starter";
5
+ function getDefaultDescription(appName) {
6
+ return `${appName} is a blog publishing platform scaffolded with the m5kdev stack.`;
7
+ }
8
+ //#endregion
9
+ exports.DEFAULT_APP_NAME = DEFAULT_APP_NAME;
10
+ exports.TEMPLATE_NAME = TEMPLATE_NAME;
11
+ exports.getDefaultDescription = getDefaultDescription;
12
+
13
+ //# sourceMappingURL=constants.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.mjs","names":[],"sources":["../../src/constants.ts"],"sourcesContent":["export const TEMPLATE_NAME = \"minimal-app\";\r\n\r\nexport const DEFAULT_APP_NAME = \"M5 Starter\";\r\n\r\nexport function getDefaultDescription(appName: string): string {\r\n return `${appName} is a blog publishing platform scaffolded with the m5kdev stack.`;\r\n}\r\n"],"mappings":";AAAA,MAAa,gBAAgB;AAE7B,MAAa,mBAAmB;AAEhC,SAAgB,sBAAsB,SAAyB;AAC7D,QAAO,GAAG,QAAQ"}
1
+ {"version":3,"file":"constants.cjs","names":[],"sources":["../../src/constants.ts"],"sourcesContent":["export const TEMPLATE_NAME = \"minimal-app\";\r\n\r\nexport const DEFAULT_APP_NAME = \"M5 Starter\";\r\n\r\nexport function getDefaultDescription(appName: string): string {\r\n return `${appName} is a blog publishing platform scaffolded with the m5kdev stack.`;\r\n}\r\n"],"mappings":";;AAAA,MAAa,gBAAgB;AAE7B,MAAa,mBAAmB;AAEhC,SAAgB,sBAAsB,SAAyB;AAC7D,QAAO,GAAG,QAAQ"}
@@ -4,4 +4,4 @@ declare const DEFAULT_APP_NAME = "M5 Starter";
4
4
  declare function getDefaultDescription(appName: string): string;
5
5
  //#endregion
6
6
  export { DEFAULT_APP_NAME, TEMPLATE_NAME, getDefaultDescription };
7
- //# sourceMappingURL=constants.d.mts.map
7
+ //# sourceMappingURL=constants.d.cts.map
@@ -0,0 +1,36 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
3
+ const require_src_constants = require("./constants.cjs");
4
+ const require_src_strings = require("./strings.cjs");
5
+ const require_src_fs = require("./fs.cjs");
6
+ const require_src_paths = require("./paths.cjs");
7
+ const require_src_prompts = require("./prompts.cjs");
8
+ let node_path = require("node:path");
9
+ node_path = require_runtime.__toESM(node_path);
10
+ //#region src/create.ts
11
+ async function scaffoldProject(initialOptions) {
12
+ const options = await require_src_prompts.resolveCreateCommandOptions(initialOptions);
13
+ const appSlug = require_src_strings.slugifyAppName(options.appName);
14
+ const targetDirectory = node_path.default.resolve(process.cwd(), options.targetDirectory);
15
+ const templateDirectory = require_src_paths.getTemplateRoot();
16
+ const context = {
17
+ appName: options.appName,
18
+ appDescription: options.appDescription,
19
+ appSlug,
20
+ packageScope: require_src_strings.derivePackageScope(appSlug),
21
+ betterAuthSecret: require_src_strings.createBetterAuthSecret()
22
+ };
23
+ await require_src_fs.ensureDirectoryState(targetDirectory, options.force);
24
+ await require_src_fs.copyTemplateDirectory(templateDirectory, targetDirectory, context);
25
+ if (!options.skipGit) await require_src_fs.runGitInit(targetDirectory);
26
+ if (!options.skipInstall) await require_src_fs.runInstall(targetDirectory);
27
+ return {
28
+ context,
29
+ targetDirectory,
30
+ templateName: require_src_constants.TEMPLATE_NAME
31
+ };
32
+ }
33
+ //#endregion
34
+ exports.scaffoldProject = scaffoldProject;
35
+
36
+ //# sourceMappingURL=create.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create.cjs","names":["resolveCreateCommandOptions","slugifyAppName","path","getTemplateRoot","derivePackageScope","createBetterAuthSecret","ensureDirectoryState","copyTemplateDirectory","runGitInit","runInstall","TEMPLATE_NAME"],"sources":["../../src/create.ts"],"sourcesContent":["import path from \"node:path\";\r\nimport { TEMPLATE_NAME } from \"./constants\";\r\nimport { copyTemplateDirectory, ensureDirectoryState, runGitInit, runInstall } from \"./fs\";\r\nimport { getTemplateRoot } from \"./paths\";\r\nimport { resolveCreateCommandOptions } from \"./prompts\";\r\nimport { createBetterAuthSecret, derivePackageScope, slugifyAppName } from \"./strings\";\r\nimport type { CreateCommandOptions, TemplateContext } from \"./types\";\r\n\r\nexport interface ScaffoldResult {\r\n context: TemplateContext;\r\n targetDirectory: string;\r\n templateName: string;\r\n}\r\n\r\nexport async function scaffoldProject(initialOptions: CreateCommandOptions): Promise<ScaffoldResult> {\r\n const options = await resolveCreateCommandOptions(initialOptions);\r\n const appSlug = slugifyAppName(options.appName!);\r\n const targetDirectory = path.resolve(process.cwd(), options.targetDirectory!);\r\n const templateDirectory = getTemplateRoot();\r\n\r\n const context: TemplateContext = {\r\n appName: options.appName!,\r\n appDescription: options.appDescription!,\r\n appSlug,\r\n packageScope: derivePackageScope(appSlug),\r\n betterAuthSecret: createBetterAuthSecret(),\r\n };\r\n\r\n await ensureDirectoryState(targetDirectory, options.force);\r\n await copyTemplateDirectory(templateDirectory, targetDirectory, context);\r\n\r\n if (!options.skipGit) {\r\n await runGitInit(targetDirectory);\r\n }\r\n\r\n if (!options.skipInstall) {\r\n await runInstall(targetDirectory);\r\n }\r\n\r\n return {\r\n context,\r\n targetDirectory,\r\n templateName: TEMPLATE_NAME,\r\n };\r\n}\r\n"],"mappings":";;;;;;;;;;AAcA,eAAsB,gBAAgB,gBAA+D;CACnG,MAAM,UAAU,MAAMA,oBAAAA,4BAA4B,eAAe;CACjE,MAAM,UAAUC,oBAAAA,eAAe,QAAQ,QAAS;CAChD,MAAM,kBAAkBC,UAAAA,QAAK,QAAQ,QAAQ,KAAK,EAAE,QAAQ,gBAAiB;CAC7E,MAAM,oBAAoBC,kBAAAA,iBAAiB;CAE3C,MAAM,UAA2B;EAC/B,SAAS,QAAQ;EACjB,gBAAgB,QAAQ;EACxB;EACA,cAAcC,oBAAAA,mBAAmB,QAAQ;EACzC,kBAAkBC,oBAAAA,wBAAwB;EAC3C;AAED,OAAMC,eAAAA,qBAAqB,iBAAiB,QAAQ,MAAM;AAC1D,OAAMC,eAAAA,sBAAsB,mBAAmB,iBAAiB,QAAQ;AAExE,KAAI,CAAC,QAAQ,QACX,OAAMC,eAAAA,WAAW,gBAAgB;AAGnC,KAAI,CAAC,QAAQ,YACX,OAAMC,eAAAA,WAAW,gBAAgB;AAGnC,QAAO;EACL;EACA;EACA,cAAcC,sBAAAA;EACf"}
@@ -1,4 +1,4 @@
1
- import { CreateCommandOptions, TemplateContext } from "./types.mjs";
1
+ import { CreateCommandOptions, TemplateContext } from "./types.cjs";
2
2
 
3
3
  //#region src/create.d.ts
4
4
  interface ScaffoldResult {
@@ -9,4 +9,4 @@ interface ScaffoldResult {
9
9
  declare function scaffoldProject(initialOptions: CreateCommandOptions): Promise<ScaffoldResult>;
10
10
  //#endregion
11
11
  export { ScaffoldResult, scaffoldProject };
12
- //# sourceMappingURL=create.d.mts.map
12
+ //# sourceMappingURL=create.d.cts.map
@@ -0,0 +1,56 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
3
+ const require_src_strings = require("./strings.cjs");
4
+ let node_path = require("node:path");
5
+ node_path = require_runtime.__toESM(node_path);
6
+ let node_child_process = require("node:child_process");
7
+ let node_fs_promises = require("node:fs/promises");
8
+ node_fs_promises = require_runtime.__toESM(node_fs_promises);
9
+ //#region src/fs.ts
10
+ const execFileAsync = (0, require("node:util").promisify)(node_child_process.execFile);
11
+ const TEMPLATE_LINE_ENDING = "\r\n";
12
+ async function ensureDirectoryState(targetDirectory, force) {
13
+ const stat = await node_fs_promises.default.stat(targetDirectory).catch(() => null);
14
+ if (!stat) {
15
+ await node_fs_promises.default.mkdir(targetDirectory, { recursive: true });
16
+ return;
17
+ }
18
+ if (!stat.isDirectory()) throw new Error(`Target path is not a directory: ${targetDirectory}`);
19
+ if ((await node_fs_promises.default.readdir(targetDirectory)).length > 0 && !force) throw new Error(`Target directory is not empty: ${targetDirectory}. Re-run with --force to overwrite.`);
20
+ }
21
+ async function copyTemplateDirectory(templateDirectory, targetDirectory, context) {
22
+ const entries = await node_fs_promises.default.readdir(templateDirectory, { withFileTypes: true });
23
+ for (const entry of entries) {
24
+ const sourcePath = node_path.default.join(templateDirectory, entry.name);
25
+ const targetName = entry.name.endsWith(".tpl") ? entry.name.slice(0, -4) : entry.name;
26
+ const targetPath = node_path.default.join(targetDirectory, targetName);
27
+ if (entry.isDirectory()) {
28
+ await node_fs_promises.default.mkdir(targetPath, { recursive: true });
29
+ await copyTemplateDirectory(sourcePath, targetPath, context);
30
+ continue;
31
+ }
32
+ if (!entry.isFile()) continue;
33
+ const rendered = require_src_strings.renderTemplate(await node_fs_promises.default.readFile(sourcePath, "utf8"), context).replace(/\r?\n/g, TEMPLATE_LINE_ENDING);
34
+ await node_fs_promises.default.mkdir(node_path.default.dirname(targetPath), { recursive: true });
35
+ await node_fs_promises.default.writeFile(targetPath, rendered, "utf8");
36
+ }
37
+ }
38
+ async function runInstall(targetDirectory) {
39
+ await execFileAsync("pnpm", ["install"], {
40
+ cwd: targetDirectory,
41
+ env: process.env
42
+ });
43
+ }
44
+ async function runGitInit(targetDirectory) {
45
+ await execFileAsync("git", ["init"], {
46
+ cwd: targetDirectory,
47
+ env: process.env
48
+ });
49
+ }
50
+ //#endregion
51
+ exports.copyTemplateDirectory = copyTemplateDirectory;
52
+ exports.ensureDirectoryState = ensureDirectoryState;
53
+ exports.runGitInit = runGitInit;
54
+ exports.runInstall = runInstall;
55
+
56
+ //# sourceMappingURL=fs.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs.cjs","names":["execFile","fs","path","renderTemplate"],"sources":["../../src/fs.ts"],"sourcesContent":["import { execFile } from \"node:child_process\";\r\nimport fs from \"node:fs/promises\";\r\nimport path from \"node:path\";\r\nimport { promisify } from \"node:util\";\r\nimport type { TemplateContext } from \"./types\";\r\nimport { renderTemplate } from \"./strings\";\r\n\r\nconst execFileAsync = promisify(execFile);\r\nconst TEMPLATE_LINE_ENDING = \"\\r\\n\";\r\n\r\nexport async function ensureDirectoryState(\r\n targetDirectory: string,\r\n force: boolean\r\n): Promise<void> {\r\n const stat = await fs.stat(targetDirectory).catch(() => null);\r\n\r\n if (!stat) {\r\n await fs.mkdir(targetDirectory, { recursive: true });\r\n return;\r\n }\r\n\r\n if (!stat.isDirectory()) {\r\n throw new Error(`Target path is not a directory: ${targetDirectory}`);\r\n }\r\n\r\n const entries = await fs.readdir(targetDirectory);\r\n if (entries.length > 0 && !force) {\r\n throw new Error(\r\n `Target directory is not empty: ${targetDirectory}. Re-run with --force to overwrite.`\r\n );\r\n }\r\n}\r\n\r\nexport async function copyTemplateDirectory(\r\n templateDirectory: string,\r\n targetDirectory: string,\r\n context: TemplateContext\r\n): Promise<void> {\r\n const entries = await fs.readdir(templateDirectory, { withFileTypes: true });\r\n\r\n for (const entry of entries) {\r\n const sourcePath = path.join(templateDirectory, entry.name);\r\n const targetName = entry.name.endsWith(\".tpl\") ? entry.name.slice(0, -4) : entry.name;\r\n const targetPath = path.join(targetDirectory, targetName);\r\n\r\n if (entry.isDirectory()) {\r\n await fs.mkdir(targetPath, { recursive: true });\r\n await copyTemplateDirectory(sourcePath, targetPath, context);\r\n continue;\r\n }\r\n\r\n if (!entry.isFile()) {\r\n continue;\r\n }\r\n\r\n const content = await fs.readFile(sourcePath, \"utf8\");\r\n const rendered = renderTemplate(content, context).replace(/\\r?\\n/g, TEMPLATE_LINE_ENDING);\r\n await fs.mkdir(path.dirname(targetPath), { recursive: true });\r\n await fs.writeFile(targetPath, rendered, \"utf8\");\r\n }\r\n}\r\n\r\nexport async function runInstall(targetDirectory: string): Promise<void> {\r\n await execFileAsync(\"pnpm\", [\"install\"], {\r\n cwd: targetDirectory,\r\n env: process.env,\r\n });\r\n}\r\n\r\nexport async function runGitInit(targetDirectory: string): Promise<void> {\r\n await execFileAsync(\"git\", [\"init\"], {\r\n cwd: targetDirectory,\r\n env: process.env,\r\n });\r\n}\r\n"],"mappings":";;;;;;;;;AAOA,MAAM,iBAAA,wBAAA,WAA0BA,mBAAAA,SAAS;AACzC,MAAM,uBAAuB;AAE7B,eAAsB,qBACpB,iBACA,OACe;CACf,MAAM,OAAO,MAAMC,iBAAAA,QAAG,KAAK,gBAAgB,CAAC,YAAY,KAAK;AAE7D,KAAI,CAAC,MAAM;AACT,QAAMA,iBAAAA,QAAG,MAAM,iBAAiB,EAAE,WAAW,MAAM,CAAC;AACpD;;AAGF,KAAI,CAAC,KAAK,aAAa,CACrB,OAAM,IAAI,MAAM,mCAAmC,kBAAkB;AAIvE,MADgB,MAAMA,iBAAAA,QAAG,QAAQ,gBAAgB,EACrC,SAAS,KAAK,CAAC,MACzB,OAAM,IAAI,MACR,kCAAkC,gBAAgB,qCACnD;;AAIL,eAAsB,sBACpB,mBACA,iBACA,SACe;CACf,MAAM,UAAU,MAAMA,iBAAAA,QAAG,QAAQ,mBAAmB,EAAE,eAAe,MAAM,CAAC;AAE5E,MAAK,MAAM,SAAS,SAAS;EAC3B,MAAM,aAAaC,UAAAA,QAAK,KAAK,mBAAmB,MAAM,KAAK;EAC3D,MAAM,aAAa,MAAM,KAAK,SAAS,OAAO,GAAG,MAAM,KAAK,MAAM,GAAG,GAAG,GAAG,MAAM;EACjF,MAAM,aAAaA,UAAAA,QAAK,KAAK,iBAAiB,WAAW;AAEzD,MAAI,MAAM,aAAa,EAAE;AACvB,SAAMD,iBAAAA,QAAG,MAAM,YAAY,EAAE,WAAW,MAAM,CAAC;AAC/C,SAAM,sBAAsB,YAAY,YAAY,QAAQ;AAC5D;;AAGF,MAAI,CAAC,MAAM,QAAQ,CACjB;EAIF,MAAM,WAAWE,oBAAAA,eADD,MAAMF,iBAAAA,QAAG,SAAS,YAAY,OAAO,EACZ,QAAQ,CAAC,QAAQ,UAAU,qBAAqB;AACzF,QAAMA,iBAAAA,QAAG,MAAMC,UAAAA,QAAK,QAAQ,WAAW,EAAE,EAAE,WAAW,MAAM,CAAC;AAC7D,QAAMD,iBAAAA,QAAG,UAAU,YAAY,UAAU,OAAO;;;AAIpD,eAAsB,WAAW,iBAAwC;AACvE,OAAM,cAAc,QAAQ,CAAC,UAAU,EAAE;EACvC,KAAK;EACL,KAAK,QAAQ;EACd,CAAC;;AAGJ,eAAsB,WAAW,iBAAwC;AACvE,OAAM,cAAc,OAAO,CAAC,OAAO,EAAE;EACnC,KAAK;EACL,KAAK,QAAQ;EACd,CAAC"}
@@ -1,4 +1,4 @@
1
- import { TemplateContext } from "./types.mjs";
1
+ import { TemplateContext } from "./types.cjs";
2
2
 
3
3
  //#region src/fs.d.ts
4
4
  declare function ensureDirectoryState(targetDirectory: string, force: boolean): Promise<void>;
@@ -7,4 +7,4 @@ declare function runInstall(targetDirectory: string): Promise<void>;
7
7
  declare function runGitInit(targetDirectory: string): Promise<void>;
8
8
  //#endregion
9
9
  export { copyTemplateDirectory, ensureDirectoryState, runGitInit, runInstall };
10
- //# sourceMappingURL=fs.d.mts.map
10
+ //# sourceMappingURL=fs.d.cts.map
@@ -1,12 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import { runCli } from "./runCli.mjs";
3
2
  //#region src/index.ts
4
- runCli(process.argv.slice(2)).catch((error) => {
3
+ require("./runCli.cjs").runCli(process.argv.slice(2)).catch((error) => {
5
4
  const message = error instanceof Error ? error.message : String(error);
6
5
  console.error(message);
7
6
  process.exitCode = 1;
8
7
  });
9
8
  //#endregion
10
- export {};
11
9
 
12
- //# sourceMappingURL=index.mjs.map
10
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":["runCli"],"sources":["../../src/index.ts"],"sourcesContent":["#!/usr/bin/env node\r\n\r\nimport { runCli } from \"./runCli\";\r\n\r\nrunCli(process.argv.slice(2)).catch((error: unknown) => {\r\n const message = error instanceof Error ? error.message : String(error);\r\n console.error(message);\r\n process.exitCode = 1;\r\n});\r\n"],"mappings":";;wBAIAA,OAAO,QAAQ,KAAK,MAAM,EAAE,CAAC,CAAC,OAAO,UAAmB;CACtD,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AACtE,SAAQ,MAAM,QAAQ;AACtB,SAAQ,WAAW;EACnB"}
@@ -0,0 +1,17 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
3
+ const require_src_constants = require("./constants.cjs");
4
+ let node_path = require("node:path");
5
+ node_path = require_runtime.__toESM(node_path);
6
+ let node_fs = require("node:fs");
7
+ node_fs = require_runtime.__toESM(node_fs);
8
+ //#region src/paths.ts
9
+ function getTemplateRoot() {
10
+ const sourcePath = node_path.default.resolve(__dirname, "../templates", require_src_constants.TEMPLATE_NAME);
11
+ if (node_fs.default.existsSync(sourcePath)) return sourcePath;
12
+ return node_path.default.resolve(__dirname, "../../templates", require_src_constants.TEMPLATE_NAME);
13
+ }
14
+ //#endregion
15
+ exports.getTemplateRoot = getTemplateRoot;
16
+
17
+ //# sourceMappingURL=paths.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.cjs","names":["path","TEMPLATE_NAME","fs"],"sources":["../../src/paths.ts"],"sourcesContent":["import fs from \"node:fs\";\r\nimport path from \"node:path\";\r\nimport { TEMPLATE_NAME } from \"./constants\";\r\n\r\nexport function getTemplateRoot(): string {\r\n const sourcePath = path.resolve(__dirname, \"../templates\", TEMPLATE_NAME);\r\n if (fs.existsSync(sourcePath)) {\r\n return sourcePath;\r\n }\r\n\r\n return path.resolve(__dirname, \"../../templates\", TEMPLATE_NAME);\r\n}\r\n"],"mappings":";;;;;;;;AAIA,SAAgB,kBAA0B;CACxC,MAAM,aAAaA,UAAAA,QAAK,QAAQ,WAAW,gBAAgBC,sBAAAA,cAAc;AACzE,KAAIC,QAAAA,QAAG,WAAW,WAAW,CAC3B,QAAO;AAGT,QAAOF,UAAAA,QAAK,QAAQ,WAAW,mBAAmBC,sBAAAA,cAAc"}
@@ -2,4 +2,4 @@
2
2
  declare function getTemplateRoot(): string;
3
3
  //#endregion
4
4
  export { getTemplateRoot };
5
- //# sourceMappingURL=paths.d.mts.map
5
+ //# sourceMappingURL=paths.d.cts.map
@@ -0,0 +1,48 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
3
+ const require_src_constants = require("./constants.cjs");
4
+ const require_src_strings = require("./strings.cjs");
5
+ let node_readline_promises = require("node:readline/promises");
6
+ node_readline_promises = require_runtime.__toESM(node_readline_promises);
7
+ let node_process = require("node:process");
8
+ //#region src/prompts.ts
9
+ function requireInteractive(yes) {
10
+ if (!yes && !process.stdin.isTTY) throw new Error("Missing required values in a non-interactive shell. Pass --yes or provide flags.");
11
+ }
12
+ async function promptValue(question, fallback) {
13
+ const rl = node_readline_promises.default.createInterface({
14
+ input: node_process.stdin,
15
+ output: node_process.stdout
16
+ });
17
+ try {
18
+ const suffix = fallback ? ` (${fallback})` : "";
19
+ return (await rl.question(`${question}${suffix}: `)).trim() || fallback || "";
20
+ } finally {
21
+ rl.close();
22
+ }
23
+ }
24
+ async function resolveCreateCommandOptions(options) {
25
+ const resolved = { ...options };
26
+ if (!resolved.appName) {
27
+ requireInteractive(resolved.yes);
28
+ resolved.appName = resolved.yes ? resolved.targetDirectory ? require_src_strings.toDisplayName(pathBaseName(resolved.targetDirectory)) : require_src_constants.DEFAULT_APP_NAME : await promptValue("App name", resolved.targetDirectory ? pathBaseName(resolved.targetDirectory) : require_src_constants.DEFAULT_APP_NAME);
29
+ }
30
+ resolved.appName = require_src_strings.toDisplayName(resolved.appName);
31
+ if (!resolved.targetDirectory) {
32
+ requireInteractive(resolved.yes);
33
+ resolved.targetDirectory = resolved.yes ? require_src_strings.slugifyAppName(resolved.appName) : await promptValue("Target directory", require_src_strings.slugifyAppName(resolved.appName));
34
+ }
35
+ if (!resolved.appDescription) {
36
+ requireInteractive(resolved.yes);
37
+ const fallback = require_src_constants.getDefaultDescription(resolved.appName);
38
+ resolved.appDescription = resolved.yes ? fallback : await promptValue("App description", fallback);
39
+ }
40
+ return resolved;
41
+ }
42
+ function pathBaseName(value) {
43
+ return value.replace(/[\\/]+$/g, "").split(/[\\/]/).filter(Boolean).at(-1) || "M5 Starter";
44
+ }
45
+ //#endregion
46
+ exports.resolveCreateCommandOptions = resolveCreateCommandOptions;
47
+
48
+ //# sourceMappingURL=prompts.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.cjs","names":["readline","toDisplayName","DEFAULT_APP_NAME","slugifyAppName","getDefaultDescription"],"sources":["../../src/prompts.ts"],"sourcesContent":["import readline from \"node:readline/promises\";\r\nimport { stdin as input, stdout as output } from \"node:process\";\r\nimport { DEFAULT_APP_NAME, getDefaultDescription } from \"./constants\";\r\nimport { slugifyAppName, toDisplayName } from \"./strings\";\r\nimport type { CreateCommandOptions } from \"./types\";\r\n\r\nfunction requireInteractive(yes: boolean): void {\r\n if (!yes && !process.stdin.isTTY) {\r\n throw new Error(\"Missing required values in a non-interactive shell. Pass --yes or provide flags.\");\r\n }\r\n}\r\n\r\nasync function promptValue(question: string, fallback?: string): Promise<string> {\r\n const rl = readline.createInterface({ input, output });\r\n\r\n try {\r\n const suffix = fallback ? ` (${fallback})` : \"\";\r\n const response = await rl.question(`${question}${suffix}: `);\r\n return response.trim() || fallback || \"\";\r\n } finally {\r\n rl.close();\r\n }\r\n}\r\n\r\nexport async function resolveCreateCommandOptions(\r\n options: CreateCommandOptions\r\n): Promise<CreateCommandOptions> {\r\n const resolved = { ...options };\r\n\r\n if (!resolved.appName) {\r\n requireInteractive(resolved.yes);\r\n resolved.appName = resolved.yes\r\n ? resolved.targetDirectory\r\n ? toDisplayName(pathBaseName(resolved.targetDirectory))\r\n : DEFAULT_APP_NAME\r\n : await promptValue(\"App name\", resolved.targetDirectory ? pathBaseName(resolved.targetDirectory) : DEFAULT_APP_NAME);\r\n }\r\n\r\n resolved.appName = toDisplayName(resolved.appName);\r\n\r\n if (!resolved.targetDirectory) {\r\n requireInteractive(resolved.yes);\r\n resolved.targetDirectory = resolved.yes\r\n ? slugifyAppName(resolved.appName)\r\n : await promptValue(\"Target directory\", slugifyAppName(resolved.appName));\r\n }\r\n\r\n if (!resolved.appDescription) {\r\n requireInteractive(resolved.yes);\r\n const fallback = getDefaultDescription(resolved.appName);\r\n resolved.appDescription = resolved.yes\r\n ? fallback\r\n : await promptValue(\"App description\", fallback);\r\n }\r\n\r\n return resolved;\r\n}\r\n\r\nfunction pathBaseName(value: string): string {\r\n const normalized = value.replace(/[\\\\/]+$/g, \"\");\r\n const segments = normalized.split(/[\\\\/]/).filter(Boolean);\r\n return segments.at(-1) || DEFAULT_APP_NAME;\r\n}\r\n"],"mappings":";;;;;;;;AAMA,SAAS,mBAAmB,KAAoB;AAC9C,KAAI,CAAC,OAAO,CAAC,QAAQ,MAAM,MACzB,OAAM,IAAI,MAAM,mFAAmF;;AAIvG,eAAe,YAAY,UAAkB,UAAoC;CAC/E,MAAM,KAAKA,uBAAAA,QAAS,gBAAgB;EAAE,OAAA,aAAA;EAAO,QAAA,aAAA;EAAQ,CAAC;AAEtD,KAAI;EACF,MAAM,SAAS,WAAW,KAAK,SAAS,KAAK;AAE7C,UADiB,MAAM,GAAG,SAAS,GAAG,WAAW,OAAO,IAAI,EAC5C,MAAM,IAAI,YAAY;WAC9B;AACR,KAAG,OAAO;;;AAId,eAAsB,4BACpB,SAC+B;CAC/B,MAAM,WAAW,EAAE,GAAG,SAAS;AAE/B,KAAI,CAAC,SAAS,SAAS;AACrB,qBAAmB,SAAS,IAAI;AAChC,WAAS,UAAU,SAAS,MACxB,SAAS,kBACPC,oBAAAA,cAAc,aAAa,SAAS,gBAAgB,CAAC,GACrDC,sBAAAA,mBACF,MAAM,YAAY,YAAY,SAAS,kBAAkB,aAAa,SAAS,gBAAgB,GAAGA,sBAAAA,iBAAiB;;AAGzH,UAAS,UAAUD,oBAAAA,cAAc,SAAS,QAAQ;AAElD,KAAI,CAAC,SAAS,iBAAiB;AAC7B,qBAAmB,SAAS,IAAI;AAChC,WAAS,kBAAkB,SAAS,MAChCE,oBAAAA,eAAe,SAAS,QAAQ,GAChC,MAAM,YAAY,oBAAoBA,oBAAAA,eAAe,SAAS,QAAQ,CAAC;;AAG7E,KAAI,CAAC,SAAS,gBAAgB;AAC5B,qBAAmB,SAAS,IAAI;EAChC,MAAM,WAAWC,sBAAAA,sBAAsB,SAAS,QAAQ;AACxD,WAAS,iBAAiB,SAAS,MAC/B,WACA,MAAM,YAAY,mBAAmB,SAAS;;AAGpD,QAAO;;AAGT,SAAS,aAAa,OAAuB;AAG3C,QAFmB,MAAM,QAAQ,YAAY,GAAG,CACpB,MAAM,QAAQ,CAAC,OAAO,QAAQ,CAC1C,GAAG,GAAG,IAAA"}
@@ -1,7 +1,7 @@
1
- import { CreateCommandOptions } from "./types.mjs";
1
+ import { CreateCommandOptions } from "./types.cjs";
2
2
 
3
3
  //#region src/prompts.d.ts
4
4
  declare function resolveCreateCommandOptions(options: CreateCommandOptions): Promise<CreateCommandOptions>;
5
5
  //#endregion
6
6
  export { resolveCreateCommandOptions };
7
- //# sourceMappingURL=prompts.d.mts.map
7
+ //# sourceMappingURL=prompts.d.cts.map
@@ -1,4 +1,5 @@
1
- import { scaffoldProject } from "./create.mjs";
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_src_create = require("./create.cjs");
2
3
  //#region src/runCli.ts
3
4
  async function runCli(argv) {
4
5
  const parsed = parseCli(argv);
@@ -8,7 +9,7 @@ async function runCli(argv) {
8
9
  }
9
10
  if (parsed.command !== "create") throw new Error(`Unknown command: ${parsed.command}`);
10
11
  const options = toCreateCommandOptions(parsed);
11
- const result = await scaffoldProject(options);
12
+ const result = await require_src_create.scaffoldProject(options);
12
13
  console.log("");
13
14
  console.log(`Scaffolded ${result.context.appName} in ${result.targetDirectory}`);
14
15
  console.log("");
@@ -96,6 +97,7 @@ function printHelp() {
96
97
  console.log(" --skip-git Skip git init");
97
98
  }
98
99
  //#endregion
99
- export { parseCli, runCli };
100
+ exports.parseCli = parseCli;
101
+ exports.runCli = runCli;
100
102
 
101
- //# sourceMappingURL=runCli.mjs.map
103
+ //# sourceMappingURL=runCli.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runCli.cjs","names":["scaffoldProject"],"sources":["../../src/runCli.ts"],"sourcesContent":["import { scaffoldProject } from \"./create\";\r\nimport type { CreateCommandOptions } from \"./types\";\r\n\r\ninterface ParsedCli {\r\n command?: string;\r\n directory?: string;\r\n help?: boolean;\r\n options: Record<string, string | boolean>;\r\n}\r\n\r\nexport async function runCli(argv: readonly string[]): Promise<void> {\r\n const parsed = parseCli(argv);\r\n\r\n if (\r\n !parsed.command ||\r\n parsed.help ||\r\n parsed.command === \"--help\" ||\r\n parsed.command === \"-h\" ||\r\n parsed.command === \"help\"\r\n ) {\r\n printHelp();\r\n return;\r\n }\r\n\r\n if (parsed.command !== \"create\") {\r\n throw new Error(`Unknown command: ${parsed.command}`);\r\n }\r\n\r\n const options = toCreateCommandOptions(parsed);\r\n const result = await scaffoldProject(options);\r\n\r\n console.log(\"\");\r\n console.log(`Scaffolded ${result.context.appName} in ${result.targetDirectory}`);\r\n console.log(\"\");\r\n console.log(\"Next steps:\");\r\n console.log(` cd ${result.targetDirectory}`);\r\n if (options.skipInstall) {\r\n console.log(\" pnpm install\");\r\n }\r\n console.log(\" pnpm --filter ./apps/server sync\");\r\n console.log(\" pnpm dev\");\r\n}\r\n\r\nexport function parseCli(argv: readonly string[]): ParsedCli {\r\n const normalizedArgv = normalizeCliArgv(argv);\r\n const [command, ...rest] = normalizedArgv;\r\n const options: Record<string, string | boolean> = {};\r\n let directory: string | undefined;\r\n let help = false;\r\n\r\n for (let index = 0; index < rest.length; index += 1) {\r\n const token = rest[index];\r\n\r\n if (token === \"--help\" || token === \"-h\") {\r\n help = true;\r\n continue;\r\n }\r\n\r\n if (!token.startsWith(\"--\")) {\r\n directory ??= token;\r\n continue;\r\n }\r\n\r\n const [rawKey, inlineValue] = token.slice(2).split(\"=\", 2);\r\n\r\n if (isBooleanFlag(rawKey)) {\r\n options[rawKey] = true;\r\n continue;\r\n }\r\n\r\n const nextValue = inlineValue ?? rest[index + 1];\r\n if (!nextValue || nextValue.startsWith(\"--\")) {\r\n throw new Error(`Missing value for --${rawKey}`);\r\n }\r\n\r\n options[rawKey] = nextValue;\r\n if (inlineValue === undefined) {\r\n index += 1;\r\n }\r\n }\r\n\r\n return { command, directory, help, options };\r\n}\r\n\r\nfunction normalizeCliArgv(argv: readonly string[]): readonly string[] {\r\n const [firstToken] = argv;\r\n\r\n if (!firstToken || firstToken === \"create\" || firstToken === \"--help\" || firstToken === \"-h\") {\r\n return argv;\r\n }\r\n\r\n if (firstToken === \"help\") {\r\n return [\"--help\"];\r\n }\r\n\r\n return [\"create\", ...argv];\r\n}\r\n\r\nfunction isBooleanFlag(value: string): boolean {\r\n return [\"yes\", \"force\", \"skip-install\", \"skip-git\"].includes(value);\r\n}\r\n\r\nfunction toCreateCommandOptions(parsed: ParsedCli): CreateCommandOptions {\r\n return {\r\n targetDirectory: parsed.directory,\r\n appName: getStringOption(parsed.options, \"name\"),\r\n appDescription: getStringOption(parsed.options, \"description\"),\r\n yes: Boolean(parsed.options.yes),\r\n force: Boolean(parsed.options.force),\r\n skipInstall: Boolean(parsed.options[\"skip-install\"]),\r\n skipGit: Boolean(parsed.options[\"skip-git\"]),\r\n };\r\n}\r\n\r\nfunction getStringOption(\r\n options: Record<string, string | boolean>,\r\n key: string\r\n): string | undefined {\r\n const value = options[key];\r\n return typeof value === \"string\" ? value : undefined;\r\n}\r\n\r\nfunction printHelp(): void {\r\n console.log(\"m5kdev\");\r\n console.log(\"\");\r\n console.log(\"Usage:\");\r\n console.log(\" pnpm create m5kdev [directory] [options]\");\r\n console.log(\" m5kdev [directory] [options]\");\r\n console.log(\" m5kdev create [directory] [options]\");\r\n console.log(\"\");\r\n console.log(\"Options:\");\r\n console.log(\" --name <value> Set the app name\");\r\n console.log(\" --description <value> Set the app description\");\r\n console.log(\" --yes Accept defaults for missing prompts\");\r\n console.log(\" --force Allow writing into a non-empty directory\");\r\n console.log(\" --skip-install Skip pnpm install\");\r\n console.log(\" --skip-git Skip git init\");\r\n}\r\n"],"mappings":";;;AAUA,eAAsB,OAAO,MAAwC;CACnE,MAAM,SAAS,SAAS,KAAK;AAE7B,KACE,CAAC,OAAO,WACR,OAAO,QACP,OAAO,YAAY,YACnB,OAAO,YAAY,QACnB,OAAO,YAAY,QACnB;AACA,aAAW;AACX;;AAGF,KAAI,OAAO,YAAY,SACrB,OAAM,IAAI,MAAM,oBAAoB,OAAO,UAAU;CAGvD,MAAM,UAAU,uBAAuB,OAAO;CAC9C,MAAM,SAAS,MAAMA,mBAAAA,gBAAgB,QAAQ;AAE7C,SAAQ,IAAI,GAAG;AACf,SAAQ,IAAI,cAAc,OAAO,QAAQ,QAAQ,MAAM,OAAO,kBAAkB;AAChF,SAAQ,IAAI,GAAG;AACf,SAAQ,IAAI,cAAc;AAC1B,SAAQ,IAAI,QAAQ,OAAO,kBAAkB;AAC7C,KAAI,QAAQ,YACV,SAAQ,IAAI,iBAAiB;AAE/B,SAAQ,IAAI,qCAAqC;AACjD,SAAQ,IAAI,aAAa;;AAG3B,SAAgB,SAAS,MAAoC;CAE3D,MAAM,CAAC,SAAS,GAAG,QADI,iBAAiB,KAAK;CAE7C,MAAM,UAA4C,EAAE;CACpD,IAAI;CACJ,IAAI,OAAO;AAEX,MAAK,IAAI,QAAQ,GAAG,QAAQ,KAAK,QAAQ,SAAS,GAAG;EACnD,MAAM,QAAQ,KAAK;AAEnB,MAAI,UAAU,YAAY,UAAU,MAAM;AACxC,UAAO;AACP;;AAGF,MAAI,CAAC,MAAM,WAAW,KAAK,EAAE;AAC3B,iBAAc;AACd;;EAGF,MAAM,CAAC,QAAQ,eAAe,MAAM,MAAM,EAAE,CAAC,MAAM,KAAK,EAAE;AAE1D,MAAI,cAAc,OAAO,EAAE;AACzB,WAAQ,UAAU;AAClB;;EAGF,MAAM,YAAY,eAAe,KAAK,QAAQ;AAC9C,MAAI,CAAC,aAAa,UAAU,WAAW,KAAK,CAC1C,OAAM,IAAI,MAAM,uBAAuB,SAAS;AAGlD,UAAQ,UAAU;AAClB,MAAI,gBAAgB,KAAA,EAClB,UAAS;;AAIb,QAAO;EAAE;EAAS;EAAW;EAAM;EAAS;;AAG9C,SAAS,iBAAiB,MAA4C;CACpE,MAAM,CAAC,cAAc;AAErB,KAAI,CAAC,cAAc,eAAe,YAAY,eAAe,YAAY,eAAe,KACtF,QAAO;AAGT,KAAI,eAAe,OACjB,QAAO,CAAC,SAAS;AAGnB,QAAO,CAAC,UAAU,GAAG,KAAK;;AAG5B,SAAS,cAAc,OAAwB;AAC7C,QAAO;EAAC;EAAO;EAAS;EAAgB;EAAW,CAAC,SAAS,MAAM;;AAGrE,SAAS,uBAAuB,QAAyC;AACvE,QAAO;EACL,iBAAiB,OAAO;EACxB,SAAS,gBAAgB,OAAO,SAAS,OAAO;EAChD,gBAAgB,gBAAgB,OAAO,SAAS,cAAc;EAC9D,KAAK,QAAQ,OAAO,QAAQ,IAAI;EAChC,OAAO,QAAQ,OAAO,QAAQ,MAAM;EACpC,aAAa,QAAQ,OAAO,QAAQ,gBAAgB;EACpD,SAAS,QAAQ,OAAO,QAAQ,YAAY;EAC7C;;AAGH,SAAS,gBACP,SACA,KACoB;CACpB,MAAM,QAAQ,QAAQ;AACtB,QAAO,OAAO,UAAU,WAAW,QAAQ,KAAA;;AAG7C,SAAS,YAAkB;AACzB,SAAQ,IAAI,SAAS;AACrB,SAAQ,IAAI,GAAG;AACf,SAAQ,IAAI,SAAS;AACrB,SAAQ,IAAI,6CAA6C;AACzD,SAAQ,IAAI,iCAAiC;AAC7C,SAAQ,IAAI,wCAAwC;AACpD,SAAQ,IAAI,GAAG;AACf,SAAQ,IAAI,WAAW;AACvB,SAAQ,IAAI,8CAA8C;AAC1D,SAAQ,IAAI,qDAAqD;AACjE,SAAQ,IAAI,iEAAiE;AAC7E,SAAQ,IAAI,sEAAsE;AAClF,SAAQ,IAAI,+CAA+C;AAC3D,SAAQ,IAAI,2CAA2C"}
@@ -9,4 +9,4 @@ declare function runCli(argv: readonly string[]): Promise<void>;
9
9
  declare function parseCli(argv: readonly string[]): ParsedCli;
10
10
  //#endregion
11
11
  export { parseCli, runCli };
12
- //# sourceMappingURL=runCli.d.mts.map
12
+ //# sourceMappingURL=runCli.d.cts.map
@@ -1,4 +1,6 @@
1
- import { randomBytes } from "node:crypto";
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ require("../_virtual/_rolldown/runtime.cjs");
3
+ let node_crypto = require("node:crypto");
2
4
  //#region src/strings.ts
3
5
  function slugifyAppName(value) {
4
6
  const slug = value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+/g, "").replace(/-+$/g, "").replace(/-{2,}/g, "-");
@@ -14,7 +16,7 @@ function toDisplayName(value) {
14
16
  return normalized;
15
17
  }
16
18
  function createBetterAuthSecret() {
17
- return randomBytes(24).toString("base64url");
19
+ return (0, node_crypto.randomBytes)(24).toString("base64url");
18
20
  }
19
21
  function renderTemplate(content, context) {
20
22
  const replacements = {
@@ -29,6 +31,10 @@ function renderTemplate(content, context) {
29
31
  });
30
32
  }
31
33
  //#endregion
32
- export { createBetterAuthSecret, derivePackageScope, renderTemplate, slugifyAppName, toDisplayName };
34
+ exports.createBetterAuthSecret = createBetterAuthSecret;
35
+ exports.derivePackageScope = derivePackageScope;
36
+ exports.renderTemplate = renderTemplate;
37
+ exports.slugifyAppName = slugifyAppName;
38
+ exports.toDisplayName = toDisplayName;
33
39
 
34
- //# sourceMappingURL=strings.mjs.map
40
+ //# sourceMappingURL=strings.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"strings.mjs","names":[],"sources":["../../src/strings.ts"],"sourcesContent":["import { randomBytes } from \"node:crypto\";\r\nimport type { TemplateContext } from \"./types\";\r\n\r\nexport function slugifyAppName(value: string): string {\r\n const slug = value\r\n .trim()\r\n .toLowerCase()\r\n .replace(/[^a-z0-9]+/g, \"-\")\r\n .replace(/^-+/g, \"\")\r\n .replace(/-+$/g, \"\")\r\n .replace(/-{2,}/g, \"-\");\r\n\r\n if (!slug) {\r\n throw new Error(\"Unable to derive an app slug from the provided name.\");\r\n }\r\n\r\n return slug;\r\n}\r\n\r\nexport function derivePackageScope(appSlug: string): string {\r\n return `@${appSlug}`;\r\n}\r\n\r\nexport function toDisplayName(value: string): string {\r\n const normalized = value.trim();\r\n if (!normalized) {\r\n throw new Error(\"App name cannot be empty.\");\r\n }\r\n\r\n return normalized;\r\n}\r\n\r\nexport function createBetterAuthSecret(): string {\r\n return randomBytes(24).toString(\"base64url\");\r\n}\r\n\r\nexport function renderTemplate(content: string, context: TemplateContext): string {\r\n const replacements: Record<string, string> = {\r\n APP_NAME: context.appName,\r\n APP_DESCRIPTION: context.appDescription,\r\n APP_SLUG: context.appSlug,\r\n PACKAGE_SCOPE: context.packageScope,\r\n BETTER_AUTH_SECRET: context.betterAuthSecret,\r\n };\r\n\r\n return content.replace(/\\{\\{([A-Z_]+)\\}\\}/g, (match, token: string) => {\r\n const replacement = replacements[token];\r\n return replacement ?? match;\r\n });\r\n}\r\n"],"mappings":";;AAGA,SAAgB,eAAe,OAAuB;CACpD,MAAM,OAAO,MACV,MAAM,CACN,aAAa,CACb,QAAQ,eAAe,IAAI,CAC3B,QAAQ,QAAQ,GAAG,CACnB,QAAQ,QAAQ,GAAG,CACnB,QAAQ,UAAU,IAAI;AAEzB,KAAI,CAAC,KACH,OAAM,IAAI,MAAM,uDAAuD;AAGzE,QAAO;;AAGT,SAAgB,mBAAmB,SAAyB;AAC1D,QAAO,IAAI;;AAGb,SAAgB,cAAc,OAAuB;CACnD,MAAM,aAAa,MAAM,MAAM;AAC/B,KAAI,CAAC,WACH,OAAM,IAAI,MAAM,4BAA4B;AAG9C,QAAO;;AAGT,SAAgB,yBAAiC;AAC/C,QAAO,YAAY,GAAG,CAAC,SAAS,YAAY;;AAG9C,SAAgB,eAAe,SAAiB,SAAkC;CAChF,MAAM,eAAuC;EAC3C,UAAU,QAAQ;EAClB,iBAAiB,QAAQ;EACzB,UAAU,QAAQ;EAClB,eAAe,QAAQ;EACvB,oBAAoB,QAAQ;EAC7B;AAED,QAAO,QAAQ,QAAQ,uBAAuB,OAAO,UAAkB;AAErE,SADoB,aAAa,UACX;GACtB"}
1
+ {"version":3,"file":"strings.cjs","names":[],"sources":["../../src/strings.ts"],"sourcesContent":["import { randomBytes } from \"node:crypto\";\r\nimport type { TemplateContext } from \"./types\";\r\n\r\nexport function slugifyAppName(value: string): string {\r\n const slug = value\r\n .trim()\r\n .toLowerCase()\r\n .replace(/[^a-z0-9]+/g, \"-\")\r\n .replace(/^-+/g, \"\")\r\n .replace(/-+$/g, \"\")\r\n .replace(/-{2,}/g, \"-\");\r\n\r\n if (!slug) {\r\n throw new Error(\"Unable to derive an app slug from the provided name.\");\r\n }\r\n\r\n return slug;\r\n}\r\n\r\nexport function derivePackageScope(appSlug: string): string {\r\n return `@${appSlug}`;\r\n}\r\n\r\nexport function toDisplayName(value: string): string {\r\n const normalized = value.trim();\r\n if (!normalized) {\r\n throw new Error(\"App name cannot be empty.\");\r\n }\r\n\r\n return normalized;\r\n}\r\n\r\nexport function createBetterAuthSecret(): string {\r\n return randomBytes(24).toString(\"base64url\");\r\n}\r\n\r\nexport function renderTemplate(content: string, context: TemplateContext): string {\r\n const replacements: Record<string, string> = {\r\n APP_NAME: context.appName,\r\n APP_DESCRIPTION: context.appDescription,\r\n APP_SLUG: context.appSlug,\r\n PACKAGE_SCOPE: context.packageScope,\r\n BETTER_AUTH_SECRET: context.betterAuthSecret,\r\n };\r\n\r\n return content.replace(/\\{\\{([A-Z_]+)\\}\\}/g, (match, token: string) => {\r\n const replacement = replacements[token];\r\n return replacement ?? match;\r\n });\r\n}\r\n"],"mappings":";;;;AAGA,SAAgB,eAAe,OAAuB;CACpD,MAAM,OAAO,MACV,MAAM,CACN,aAAa,CACb,QAAQ,eAAe,IAAI,CAC3B,QAAQ,QAAQ,GAAG,CACnB,QAAQ,QAAQ,GAAG,CACnB,QAAQ,UAAU,IAAI;AAEzB,KAAI,CAAC,KACH,OAAM,IAAI,MAAM,uDAAuD;AAGzE,QAAO;;AAGT,SAAgB,mBAAmB,SAAyB;AAC1D,QAAO,IAAI;;AAGb,SAAgB,cAAc,OAAuB;CACnD,MAAM,aAAa,MAAM,MAAM;AAC/B,KAAI,CAAC,WACH,OAAM,IAAI,MAAM,4BAA4B;AAG9C,QAAO;;AAGT,SAAgB,yBAAiC;AAC/C,SAAA,GAAA,YAAA,aAAmB,GAAG,CAAC,SAAS,YAAY;;AAG9C,SAAgB,eAAe,SAAiB,SAAkC;CAChF,MAAM,eAAuC;EAC3C,UAAU,QAAQ;EAClB,iBAAiB,QAAQ;EACzB,UAAU,QAAQ;EAClB,eAAe,QAAQ;EACvB,oBAAoB,QAAQ;EAC7B;AAED,QAAO,QAAQ,QAAQ,uBAAuB,OAAO,UAAkB;AAErE,SADoB,aAAa,UACX;GACtB"}
@@ -1,4 +1,4 @@
1
- import { TemplateContext } from "./types.mjs";
1
+ import { TemplateContext } from "./types.cjs";
2
2
 
3
3
  //#region src/strings.d.ts
4
4
  declare function slugifyAppName(value: string): string;
@@ -8,4 +8,4 @@ declare function createBetterAuthSecret(): string;
8
8
  declare function renderTemplate(content: string, context: TemplateContext): string;
9
9
  //#endregion
10
10
  export { createBetterAuthSecret, derivePackageScope, renderTemplate, slugifyAppName, toDisplayName };
11
- //# sourceMappingURL=strings.d.mts.map
11
+ //# sourceMappingURL=strings.d.cts.map
File without changes
@@ -19,4 +19,4 @@ interface TemplateContext {
19
19
  }
20
20
  //#endregion
21
21
  export { CreateCommandOptions, PromptValues, TemplateContext };
22
- //# sourceMappingURL=types.d.mts.map
22
+ //# sourceMappingURL=types.d.cts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-m5kdev",
3
- "version": "0.21.4",
3
+ "version": "0.21.6",
4
4
  "license": "GPL-3.0-only",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1,10 +0,0 @@
1
- //#region src/constants.ts
2
- const TEMPLATE_NAME = "minimal-app";
3
- const DEFAULT_APP_NAME = "M5 Starter";
4
- function getDefaultDescription(appName) {
5
- return `${appName} is a blog publishing platform scaffolded with the m5kdev stack.`;
6
- }
7
- //#endregion
8
- export { DEFAULT_APP_NAME, TEMPLATE_NAME, getDefaultDescription };
9
-
10
- //# sourceMappingURL=constants.mjs.map
@@ -1,33 +0,0 @@
1
- import { TEMPLATE_NAME } from "./constants.mjs";
2
- import { createBetterAuthSecret, derivePackageScope, slugifyAppName } from "./strings.mjs";
3
- import { copyTemplateDirectory, ensureDirectoryState, runGitInit, runInstall } from "./fs.mjs";
4
- import { getTemplateRoot } from "./paths.mjs";
5
- import { resolveCreateCommandOptions } from "./prompts.mjs";
6
- import path from "node:path";
7
- //#region src/create.ts
8
- async function scaffoldProject(initialOptions) {
9
- const options = await resolveCreateCommandOptions(initialOptions);
10
- const appSlug = slugifyAppName(options.appName);
11
- const targetDirectory = path.resolve(process.cwd(), options.targetDirectory);
12
- const templateDirectory = getTemplateRoot();
13
- const context = {
14
- appName: options.appName,
15
- appDescription: options.appDescription,
16
- appSlug,
17
- packageScope: derivePackageScope(appSlug),
18
- betterAuthSecret: createBetterAuthSecret()
19
- };
20
- await ensureDirectoryState(targetDirectory, options.force);
21
- await copyTemplateDirectory(templateDirectory, targetDirectory, context);
22
- if (!options.skipGit) await runGitInit(targetDirectory);
23
- if (!options.skipInstall) await runInstall(targetDirectory);
24
- return {
25
- context,
26
- targetDirectory,
27
- templateName: TEMPLATE_NAME
28
- };
29
- }
30
- //#endregion
31
- export { scaffoldProject };
32
-
33
- //# sourceMappingURL=create.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"create.mjs","names":[],"sources":["../../src/create.ts"],"sourcesContent":["import path from \"node:path\";\r\nimport { TEMPLATE_NAME } from \"./constants\";\r\nimport { copyTemplateDirectory, ensureDirectoryState, runGitInit, runInstall } from \"./fs\";\r\nimport { getTemplateRoot } from \"./paths\";\r\nimport { resolveCreateCommandOptions } from \"./prompts\";\r\nimport { createBetterAuthSecret, derivePackageScope, slugifyAppName } from \"./strings\";\r\nimport type { CreateCommandOptions, TemplateContext } from \"./types\";\r\n\r\nexport interface ScaffoldResult {\r\n context: TemplateContext;\r\n targetDirectory: string;\r\n templateName: string;\r\n}\r\n\r\nexport async function scaffoldProject(initialOptions: CreateCommandOptions): Promise<ScaffoldResult> {\r\n const options = await resolveCreateCommandOptions(initialOptions);\r\n const appSlug = slugifyAppName(options.appName!);\r\n const targetDirectory = path.resolve(process.cwd(), options.targetDirectory!);\r\n const templateDirectory = getTemplateRoot();\r\n\r\n const context: TemplateContext = {\r\n appName: options.appName!,\r\n appDescription: options.appDescription!,\r\n appSlug,\r\n packageScope: derivePackageScope(appSlug),\r\n betterAuthSecret: createBetterAuthSecret(),\r\n };\r\n\r\n await ensureDirectoryState(targetDirectory, options.force);\r\n await copyTemplateDirectory(templateDirectory, targetDirectory, context);\r\n\r\n if (!options.skipGit) {\r\n await runGitInit(targetDirectory);\r\n }\r\n\r\n if (!options.skipInstall) {\r\n await runInstall(targetDirectory);\r\n }\r\n\r\n return {\r\n context,\r\n targetDirectory,\r\n templateName: TEMPLATE_NAME,\r\n };\r\n}\r\n"],"mappings":";;;;;;;AAcA,eAAsB,gBAAgB,gBAA+D;CACnG,MAAM,UAAU,MAAM,4BAA4B,eAAe;CACjE,MAAM,UAAU,eAAe,QAAQ,QAAS;CAChD,MAAM,kBAAkB,KAAK,QAAQ,QAAQ,KAAK,EAAE,QAAQ,gBAAiB;CAC7E,MAAM,oBAAoB,iBAAiB;CAE3C,MAAM,UAA2B;EAC/B,SAAS,QAAQ;EACjB,gBAAgB,QAAQ;EACxB;EACA,cAAc,mBAAmB,QAAQ;EACzC,kBAAkB,wBAAwB;EAC3C;AAED,OAAM,qBAAqB,iBAAiB,QAAQ,MAAM;AAC1D,OAAM,sBAAsB,mBAAmB,iBAAiB,QAAQ;AAExE,KAAI,CAAC,QAAQ,QACX,OAAM,WAAW,gBAAgB;AAGnC,KAAI,CAAC,QAAQ,YACX,OAAM,WAAW,gBAAgB;AAGnC,QAAO;EACL;EACA;EACA,cAAc;EACf"}
package/dist/src/fs.mjs DELETED
@@ -1,50 +0,0 @@
1
- import { renderTemplate } from "./strings.mjs";
2
- import path from "node:path";
3
- import { execFile } from "node:child_process";
4
- import fs from "node:fs/promises";
5
- import { promisify } from "node:util";
6
- //#region src/fs.ts
7
- const execFileAsync = promisify(execFile);
8
- const TEMPLATE_LINE_ENDING = "\r\n";
9
- async function ensureDirectoryState(targetDirectory, force) {
10
- const stat = await fs.stat(targetDirectory).catch(() => null);
11
- if (!stat) {
12
- await fs.mkdir(targetDirectory, { recursive: true });
13
- return;
14
- }
15
- if (!stat.isDirectory()) throw new Error(`Target path is not a directory: ${targetDirectory}`);
16
- if ((await fs.readdir(targetDirectory)).length > 0 && !force) throw new Error(`Target directory is not empty: ${targetDirectory}. Re-run with --force to overwrite.`);
17
- }
18
- async function copyTemplateDirectory(templateDirectory, targetDirectory, context) {
19
- const entries = await fs.readdir(templateDirectory, { withFileTypes: true });
20
- for (const entry of entries) {
21
- const sourcePath = path.join(templateDirectory, entry.name);
22
- const targetName = entry.name.endsWith(".tpl") ? entry.name.slice(0, -4) : entry.name;
23
- const targetPath = path.join(targetDirectory, targetName);
24
- if (entry.isDirectory()) {
25
- await fs.mkdir(targetPath, { recursive: true });
26
- await copyTemplateDirectory(sourcePath, targetPath, context);
27
- continue;
28
- }
29
- if (!entry.isFile()) continue;
30
- const rendered = renderTemplate(await fs.readFile(sourcePath, "utf8"), context).replace(/\r?\n/g, TEMPLATE_LINE_ENDING);
31
- await fs.mkdir(path.dirname(targetPath), { recursive: true });
32
- await fs.writeFile(targetPath, rendered, "utf8");
33
- }
34
- }
35
- async function runInstall(targetDirectory) {
36
- await execFileAsync("pnpm", ["install"], {
37
- cwd: targetDirectory,
38
- env: process.env
39
- });
40
- }
41
- async function runGitInit(targetDirectory) {
42
- await execFileAsync("git", ["init"], {
43
- cwd: targetDirectory,
44
- env: process.env
45
- });
46
- }
47
- //#endregion
48
- export { copyTemplateDirectory, ensureDirectoryState, runGitInit, runInstall };
49
-
50
- //# sourceMappingURL=fs.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"fs.mjs","names":[],"sources":["../../src/fs.ts"],"sourcesContent":["import { execFile } from \"node:child_process\";\r\nimport fs from \"node:fs/promises\";\r\nimport path from \"node:path\";\r\nimport { promisify } from \"node:util\";\r\nimport type { TemplateContext } from \"./types\";\r\nimport { renderTemplate } from \"./strings\";\r\n\r\nconst execFileAsync = promisify(execFile);\r\nconst TEMPLATE_LINE_ENDING = \"\\r\\n\";\r\n\r\nexport async function ensureDirectoryState(\r\n targetDirectory: string,\r\n force: boolean\r\n): Promise<void> {\r\n const stat = await fs.stat(targetDirectory).catch(() => null);\r\n\r\n if (!stat) {\r\n await fs.mkdir(targetDirectory, { recursive: true });\r\n return;\r\n }\r\n\r\n if (!stat.isDirectory()) {\r\n throw new Error(`Target path is not a directory: ${targetDirectory}`);\r\n }\r\n\r\n const entries = await fs.readdir(targetDirectory);\r\n if (entries.length > 0 && !force) {\r\n throw new Error(\r\n `Target directory is not empty: ${targetDirectory}. Re-run with --force to overwrite.`\r\n );\r\n }\r\n}\r\n\r\nexport async function copyTemplateDirectory(\r\n templateDirectory: string,\r\n targetDirectory: string,\r\n context: TemplateContext\r\n): Promise<void> {\r\n const entries = await fs.readdir(templateDirectory, { withFileTypes: true });\r\n\r\n for (const entry of entries) {\r\n const sourcePath = path.join(templateDirectory, entry.name);\r\n const targetName = entry.name.endsWith(\".tpl\") ? entry.name.slice(0, -4) : entry.name;\r\n const targetPath = path.join(targetDirectory, targetName);\r\n\r\n if (entry.isDirectory()) {\r\n await fs.mkdir(targetPath, { recursive: true });\r\n await copyTemplateDirectory(sourcePath, targetPath, context);\r\n continue;\r\n }\r\n\r\n if (!entry.isFile()) {\r\n continue;\r\n }\r\n\r\n const content = await fs.readFile(sourcePath, \"utf8\");\r\n const rendered = renderTemplate(content, context).replace(/\\r?\\n/g, TEMPLATE_LINE_ENDING);\r\n await fs.mkdir(path.dirname(targetPath), { recursive: true });\r\n await fs.writeFile(targetPath, rendered, \"utf8\");\r\n }\r\n}\r\n\r\nexport async function runInstall(targetDirectory: string): Promise<void> {\r\n await execFileAsync(\"pnpm\", [\"install\"], {\r\n cwd: targetDirectory,\r\n env: process.env,\r\n });\r\n}\r\n\r\nexport async function runGitInit(targetDirectory: string): Promise<void> {\r\n await execFileAsync(\"git\", [\"init\"], {\r\n cwd: targetDirectory,\r\n env: process.env,\r\n });\r\n}\r\n"],"mappings":";;;;;;AAOA,MAAM,gBAAgB,UAAU,SAAS;AACzC,MAAM,uBAAuB;AAE7B,eAAsB,qBACpB,iBACA,OACe;CACf,MAAM,OAAO,MAAM,GAAG,KAAK,gBAAgB,CAAC,YAAY,KAAK;AAE7D,KAAI,CAAC,MAAM;AACT,QAAM,GAAG,MAAM,iBAAiB,EAAE,WAAW,MAAM,CAAC;AACpD;;AAGF,KAAI,CAAC,KAAK,aAAa,CACrB,OAAM,IAAI,MAAM,mCAAmC,kBAAkB;AAIvE,MADgB,MAAM,GAAG,QAAQ,gBAAgB,EACrC,SAAS,KAAK,CAAC,MACzB,OAAM,IAAI,MACR,kCAAkC,gBAAgB,qCACnD;;AAIL,eAAsB,sBACpB,mBACA,iBACA,SACe;CACf,MAAM,UAAU,MAAM,GAAG,QAAQ,mBAAmB,EAAE,eAAe,MAAM,CAAC;AAE5E,MAAK,MAAM,SAAS,SAAS;EAC3B,MAAM,aAAa,KAAK,KAAK,mBAAmB,MAAM,KAAK;EAC3D,MAAM,aAAa,MAAM,KAAK,SAAS,OAAO,GAAG,MAAM,KAAK,MAAM,GAAG,GAAG,GAAG,MAAM;EACjF,MAAM,aAAa,KAAK,KAAK,iBAAiB,WAAW;AAEzD,MAAI,MAAM,aAAa,EAAE;AACvB,SAAM,GAAG,MAAM,YAAY,EAAE,WAAW,MAAM,CAAC;AAC/C,SAAM,sBAAsB,YAAY,YAAY,QAAQ;AAC5D;;AAGF,MAAI,CAAC,MAAM,QAAQ,CACjB;EAIF,MAAM,WAAW,eADD,MAAM,GAAG,SAAS,YAAY,OAAO,EACZ,QAAQ,CAAC,QAAQ,UAAU,qBAAqB;AACzF,QAAM,GAAG,MAAM,KAAK,QAAQ,WAAW,EAAE,EAAE,WAAW,MAAM,CAAC;AAC7D,QAAM,GAAG,UAAU,YAAY,UAAU,OAAO;;;AAIpD,eAAsB,WAAW,iBAAwC;AACvE,OAAM,cAAc,QAAQ,CAAC,UAAU,EAAE;EACvC,KAAK;EACL,KAAK,QAAQ;EACd,CAAC;;AAGJ,eAAsB,WAAW,iBAAwC;AACvE,OAAM,cAAc,OAAO,CAAC,OAAO,EAAE;EACnC,KAAK;EACL,KAAK,QAAQ;EACd,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../src/index.ts"],"sourcesContent":["#!/usr/bin/env node\r\n\r\nimport { runCli } from \"./runCli\";\r\n\r\nrunCli(process.argv.slice(2)).catch((error: unknown) => {\r\n const message = error instanceof Error ? error.message : String(error);\r\n console.error(message);\r\n process.exitCode = 1;\r\n});\r\n"],"mappings":";;;AAIA,OAAO,QAAQ,KAAK,MAAM,EAAE,CAAC,CAAC,OAAO,UAAmB;CACtD,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AACtE,SAAQ,MAAM,QAAQ;AACtB,SAAQ,WAAW;EACnB"}
@@ -1,13 +0,0 @@
1
- import { TEMPLATE_NAME } from "./constants.mjs";
2
- import path from "node:path";
3
- import fs from "node:fs";
4
- //#region src/paths.ts
5
- function getTemplateRoot() {
6
- const sourcePath = path.resolve(__dirname, "../templates", TEMPLATE_NAME);
7
- if (fs.existsSync(sourcePath)) return sourcePath;
8
- return path.resolve(__dirname, "../../templates", TEMPLATE_NAME);
9
- }
10
- //#endregion
11
- export { getTemplateRoot };
12
-
13
- //# sourceMappingURL=paths.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"paths.mjs","names":[],"sources":["../../src/paths.ts"],"sourcesContent":["import fs from \"node:fs\";\r\nimport path from \"node:path\";\r\nimport { TEMPLATE_NAME } from \"./constants\";\r\n\r\nexport function getTemplateRoot(): string {\r\n const sourcePath = path.resolve(__dirname, \"../templates\", TEMPLATE_NAME);\r\n if (fs.existsSync(sourcePath)) {\r\n return sourcePath;\r\n }\r\n\r\n return path.resolve(__dirname, \"../../templates\", TEMPLATE_NAME);\r\n}\r\n"],"mappings":";;;;AAIA,SAAgB,kBAA0B;CACxC,MAAM,aAAa,KAAK,QAAQ,WAAW,gBAAgB,cAAc;AACzE,KAAI,GAAG,WAAW,WAAW,CAC3B,QAAO;AAGT,QAAO,KAAK,QAAQ,WAAW,mBAAmB,cAAc"}
@@ -1,45 +0,0 @@
1
- import { DEFAULT_APP_NAME, getDefaultDescription } from "./constants.mjs";
2
- import { slugifyAppName, toDisplayName } from "./strings.mjs";
3
- import readline from "node:readline/promises";
4
- import { stdin, stdout } from "node:process";
5
- //#region src/prompts.ts
6
- function requireInteractive(yes) {
7
- if (!yes && !process.stdin.isTTY) throw new Error("Missing required values in a non-interactive shell. Pass --yes or provide flags.");
8
- }
9
- async function promptValue(question, fallback) {
10
- const rl = readline.createInterface({
11
- input: stdin,
12
- output: stdout
13
- });
14
- try {
15
- const suffix = fallback ? ` (${fallback})` : "";
16
- return (await rl.question(`${question}${suffix}: `)).trim() || fallback || "";
17
- } finally {
18
- rl.close();
19
- }
20
- }
21
- async function resolveCreateCommandOptions(options) {
22
- const resolved = { ...options };
23
- if (!resolved.appName) {
24
- requireInteractive(resolved.yes);
25
- resolved.appName = resolved.yes ? resolved.targetDirectory ? toDisplayName(pathBaseName(resolved.targetDirectory)) : DEFAULT_APP_NAME : await promptValue("App name", resolved.targetDirectory ? pathBaseName(resolved.targetDirectory) : DEFAULT_APP_NAME);
26
- }
27
- resolved.appName = toDisplayName(resolved.appName);
28
- if (!resolved.targetDirectory) {
29
- requireInteractive(resolved.yes);
30
- resolved.targetDirectory = resolved.yes ? slugifyAppName(resolved.appName) : await promptValue("Target directory", slugifyAppName(resolved.appName));
31
- }
32
- if (!resolved.appDescription) {
33
- requireInteractive(resolved.yes);
34
- const fallback = getDefaultDescription(resolved.appName);
35
- resolved.appDescription = resolved.yes ? fallback : await promptValue("App description", fallback);
36
- }
37
- return resolved;
38
- }
39
- function pathBaseName(value) {
40
- return value.replace(/[\\/]+$/g, "").split(/[\\/]/).filter(Boolean).at(-1) || "M5 Starter";
41
- }
42
- //#endregion
43
- export { resolveCreateCommandOptions };
44
-
45
- //# sourceMappingURL=prompts.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"prompts.mjs","names":[],"sources":["../../src/prompts.ts"],"sourcesContent":["import readline from \"node:readline/promises\";\r\nimport { stdin as input, stdout as output } from \"node:process\";\r\nimport { DEFAULT_APP_NAME, getDefaultDescription } from \"./constants\";\r\nimport { slugifyAppName, toDisplayName } from \"./strings\";\r\nimport type { CreateCommandOptions } from \"./types\";\r\n\r\nfunction requireInteractive(yes: boolean): void {\r\n if (!yes && !process.stdin.isTTY) {\r\n throw new Error(\"Missing required values in a non-interactive shell. Pass --yes or provide flags.\");\r\n }\r\n}\r\n\r\nasync function promptValue(question: string, fallback?: string): Promise<string> {\r\n const rl = readline.createInterface({ input, output });\r\n\r\n try {\r\n const suffix = fallback ? ` (${fallback})` : \"\";\r\n const response = await rl.question(`${question}${suffix}: `);\r\n return response.trim() || fallback || \"\";\r\n } finally {\r\n rl.close();\r\n }\r\n}\r\n\r\nexport async function resolveCreateCommandOptions(\r\n options: CreateCommandOptions\r\n): Promise<CreateCommandOptions> {\r\n const resolved = { ...options };\r\n\r\n if (!resolved.appName) {\r\n requireInteractive(resolved.yes);\r\n resolved.appName = resolved.yes\r\n ? resolved.targetDirectory\r\n ? toDisplayName(pathBaseName(resolved.targetDirectory))\r\n : DEFAULT_APP_NAME\r\n : await promptValue(\"App name\", resolved.targetDirectory ? pathBaseName(resolved.targetDirectory) : DEFAULT_APP_NAME);\r\n }\r\n\r\n resolved.appName = toDisplayName(resolved.appName);\r\n\r\n if (!resolved.targetDirectory) {\r\n requireInteractive(resolved.yes);\r\n resolved.targetDirectory = resolved.yes\r\n ? slugifyAppName(resolved.appName)\r\n : await promptValue(\"Target directory\", slugifyAppName(resolved.appName));\r\n }\r\n\r\n if (!resolved.appDescription) {\r\n requireInteractive(resolved.yes);\r\n const fallback = getDefaultDescription(resolved.appName);\r\n resolved.appDescription = resolved.yes\r\n ? fallback\r\n : await promptValue(\"App description\", fallback);\r\n }\r\n\r\n return resolved;\r\n}\r\n\r\nfunction pathBaseName(value: string): string {\r\n const normalized = value.replace(/[\\\\/]+$/g, \"\");\r\n const segments = normalized.split(/[\\\\/]/).filter(Boolean);\r\n return segments.at(-1) || DEFAULT_APP_NAME;\r\n}\r\n"],"mappings":";;;;;AAMA,SAAS,mBAAmB,KAAoB;AAC9C,KAAI,CAAC,OAAO,CAAC,QAAQ,MAAM,MACzB,OAAM,IAAI,MAAM,mFAAmF;;AAIvG,eAAe,YAAY,UAAkB,UAAoC;CAC/E,MAAM,KAAK,SAAS,gBAAgB;EAAE,OAAA;EAAO,QAAA;EAAQ,CAAC;AAEtD,KAAI;EACF,MAAM,SAAS,WAAW,KAAK,SAAS,KAAK;AAE7C,UADiB,MAAM,GAAG,SAAS,GAAG,WAAW,OAAO,IAAI,EAC5C,MAAM,IAAI,YAAY;WAC9B;AACR,KAAG,OAAO;;;AAId,eAAsB,4BACpB,SAC+B;CAC/B,MAAM,WAAW,EAAE,GAAG,SAAS;AAE/B,KAAI,CAAC,SAAS,SAAS;AACrB,qBAAmB,SAAS,IAAI;AAChC,WAAS,UAAU,SAAS,MACxB,SAAS,kBACP,cAAc,aAAa,SAAS,gBAAgB,CAAC,GACrD,mBACF,MAAM,YAAY,YAAY,SAAS,kBAAkB,aAAa,SAAS,gBAAgB,GAAG,iBAAiB;;AAGzH,UAAS,UAAU,cAAc,SAAS,QAAQ;AAElD,KAAI,CAAC,SAAS,iBAAiB;AAC7B,qBAAmB,SAAS,IAAI;AAChC,WAAS,kBAAkB,SAAS,MAChC,eAAe,SAAS,QAAQ,GAChC,MAAM,YAAY,oBAAoB,eAAe,SAAS,QAAQ,CAAC;;AAG7E,KAAI,CAAC,SAAS,gBAAgB;AAC5B,qBAAmB,SAAS,IAAI;EAChC,MAAM,WAAW,sBAAsB,SAAS,QAAQ;AACxD,WAAS,iBAAiB,SAAS,MAC/B,WACA,MAAM,YAAY,mBAAmB,SAAS;;AAGpD,QAAO;;AAGT,SAAS,aAAa,OAAuB;AAG3C,QAFmB,MAAM,QAAQ,YAAY,GAAG,CACpB,MAAM,QAAQ,CAAC,OAAO,QAAQ,CAC1C,GAAG,GAAG,IAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"runCli.mjs","names":[],"sources":["../../src/runCli.ts"],"sourcesContent":["import { scaffoldProject } from \"./create\";\r\nimport type { CreateCommandOptions } from \"./types\";\r\n\r\ninterface ParsedCli {\r\n command?: string;\r\n directory?: string;\r\n help?: boolean;\r\n options: Record<string, string | boolean>;\r\n}\r\n\r\nexport async function runCli(argv: readonly string[]): Promise<void> {\r\n const parsed = parseCli(argv);\r\n\r\n if (\r\n !parsed.command ||\r\n parsed.help ||\r\n parsed.command === \"--help\" ||\r\n parsed.command === \"-h\" ||\r\n parsed.command === \"help\"\r\n ) {\r\n printHelp();\r\n return;\r\n }\r\n\r\n if (parsed.command !== \"create\") {\r\n throw new Error(`Unknown command: ${parsed.command}`);\r\n }\r\n\r\n const options = toCreateCommandOptions(parsed);\r\n const result = await scaffoldProject(options);\r\n\r\n console.log(\"\");\r\n console.log(`Scaffolded ${result.context.appName} in ${result.targetDirectory}`);\r\n console.log(\"\");\r\n console.log(\"Next steps:\");\r\n console.log(` cd ${result.targetDirectory}`);\r\n if (options.skipInstall) {\r\n console.log(\" pnpm install\");\r\n }\r\n console.log(\" pnpm --filter ./apps/server sync\");\r\n console.log(\" pnpm dev\");\r\n}\r\n\r\nexport function parseCli(argv: readonly string[]): ParsedCli {\r\n const normalizedArgv = normalizeCliArgv(argv);\r\n const [command, ...rest] = normalizedArgv;\r\n const options: Record<string, string | boolean> = {};\r\n let directory: string | undefined;\r\n let help = false;\r\n\r\n for (let index = 0; index < rest.length; index += 1) {\r\n const token = rest[index];\r\n\r\n if (token === \"--help\" || token === \"-h\") {\r\n help = true;\r\n continue;\r\n }\r\n\r\n if (!token.startsWith(\"--\")) {\r\n directory ??= token;\r\n continue;\r\n }\r\n\r\n const [rawKey, inlineValue] = token.slice(2).split(\"=\", 2);\r\n\r\n if (isBooleanFlag(rawKey)) {\r\n options[rawKey] = true;\r\n continue;\r\n }\r\n\r\n const nextValue = inlineValue ?? rest[index + 1];\r\n if (!nextValue || nextValue.startsWith(\"--\")) {\r\n throw new Error(`Missing value for --${rawKey}`);\r\n }\r\n\r\n options[rawKey] = nextValue;\r\n if (inlineValue === undefined) {\r\n index += 1;\r\n }\r\n }\r\n\r\n return { command, directory, help, options };\r\n}\r\n\r\nfunction normalizeCliArgv(argv: readonly string[]): readonly string[] {\r\n const [firstToken] = argv;\r\n\r\n if (!firstToken || firstToken === \"create\" || firstToken === \"--help\" || firstToken === \"-h\") {\r\n return argv;\r\n }\r\n\r\n if (firstToken === \"help\") {\r\n return [\"--help\"];\r\n }\r\n\r\n return [\"create\", ...argv];\r\n}\r\n\r\nfunction isBooleanFlag(value: string): boolean {\r\n return [\"yes\", \"force\", \"skip-install\", \"skip-git\"].includes(value);\r\n}\r\n\r\nfunction toCreateCommandOptions(parsed: ParsedCli): CreateCommandOptions {\r\n return {\r\n targetDirectory: parsed.directory,\r\n appName: getStringOption(parsed.options, \"name\"),\r\n appDescription: getStringOption(parsed.options, \"description\"),\r\n yes: Boolean(parsed.options.yes),\r\n force: Boolean(parsed.options.force),\r\n skipInstall: Boolean(parsed.options[\"skip-install\"]),\r\n skipGit: Boolean(parsed.options[\"skip-git\"]),\r\n };\r\n}\r\n\r\nfunction getStringOption(\r\n options: Record<string, string | boolean>,\r\n key: string\r\n): string | undefined {\r\n const value = options[key];\r\n return typeof value === \"string\" ? value : undefined;\r\n}\r\n\r\nfunction printHelp(): void {\r\n console.log(\"m5kdev\");\r\n console.log(\"\");\r\n console.log(\"Usage:\");\r\n console.log(\" pnpm create m5kdev [directory] [options]\");\r\n console.log(\" m5kdev [directory] [options]\");\r\n console.log(\" m5kdev create [directory] [options]\");\r\n console.log(\"\");\r\n console.log(\"Options:\");\r\n console.log(\" --name <value> Set the app name\");\r\n console.log(\" --description <value> Set the app description\");\r\n console.log(\" --yes Accept defaults for missing prompts\");\r\n console.log(\" --force Allow writing into a non-empty directory\");\r\n console.log(\" --skip-install Skip pnpm install\");\r\n console.log(\" --skip-git Skip git init\");\r\n}\r\n"],"mappings":";;AAUA,eAAsB,OAAO,MAAwC;CACnE,MAAM,SAAS,SAAS,KAAK;AAE7B,KACE,CAAC,OAAO,WACR,OAAO,QACP,OAAO,YAAY,YACnB,OAAO,YAAY,QACnB,OAAO,YAAY,QACnB;AACA,aAAW;AACX;;AAGF,KAAI,OAAO,YAAY,SACrB,OAAM,IAAI,MAAM,oBAAoB,OAAO,UAAU;CAGvD,MAAM,UAAU,uBAAuB,OAAO;CAC9C,MAAM,SAAS,MAAM,gBAAgB,QAAQ;AAE7C,SAAQ,IAAI,GAAG;AACf,SAAQ,IAAI,cAAc,OAAO,QAAQ,QAAQ,MAAM,OAAO,kBAAkB;AAChF,SAAQ,IAAI,GAAG;AACf,SAAQ,IAAI,cAAc;AAC1B,SAAQ,IAAI,QAAQ,OAAO,kBAAkB;AAC7C,KAAI,QAAQ,YACV,SAAQ,IAAI,iBAAiB;AAE/B,SAAQ,IAAI,qCAAqC;AACjD,SAAQ,IAAI,aAAa;;AAG3B,SAAgB,SAAS,MAAoC;CAE3D,MAAM,CAAC,SAAS,GAAG,QADI,iBAAiB,KAAK;CAE7C,MAAM,UAA4C,EAAE;CACpD,IAAI;CACJ,IAAI,OAAO;AAEX,MAAK,IAAI,QAAQ,GAAG,QAAQ,KAAK,QAAQ,SAAS,GAAG;EACnD,MAAM,QAAQ,KAAK;AAEnB,MAAI,UAAU,YAAY,UAAU,MAAM;AACxC,UAAO;AACP;;AAGF,MAAI,CAAC,MAAM,WAAW,KAAK,EAAE;AAC3B,iBAAc;AACd;;EAGF,MAAM,CAAC,QAAQ,eAAe,MAAM,MAAM,EAAE,CAAC,MAAM,KAAK,EAAE;AAE1D,MAAI,cAAc,OAAO,EAAE;AACzB,WAAQ,UAAU;AAClB;;EAGF,MAAM,YAAY,eAAe,KAAK,QAAQ;AAC9C,MAAI,CAAC,aAAa,UAAU,WAAW,KAAK,CAC1C,OAAM,IAAI,MAAM,uBAAuB,SAAS;AAGlD,UAAQ,UAAU;AAClB,MAAI,gBAAgB,KAAA,EAClB,UAAS;;AAIb,QAAO;EAAE;EAAS;EAAW;EAAM;EAAS;;AAG9C,SAAS,iBAAiB,MAA4C;CACpE,MAAM,CAAC,cAAc;AAErB,KAAI,CAAC,cAAc,eAAe,YAAY,eAAe,YAAY,eAAe,KACtF,QAAO;AAGT,KAAI,eAAe,OACjB,QAAO,CAAC,SAAS;AAGnB,QAAO,CAAC,UAAU,GAAG,KAAK;;AAG5B,SAAS,cAAc,OAAwB;AAC7C,QAAO;EAAC;EAAO;EAAS;EAAgB;EAAW,CAAC,SAAS,MAAM;;AAGrE,SAAS,uBAAuB,QAAyC;AACvE,QAAO;EACL,iBAAiB,OAAO;EACxB,SAAS,gBAAgB,OAAO,SAAS,OAAO;EAChD,gBAAgB,gBAAgB,OAAO,SAAS,cAAc;EAC9D,KAAK,QAAQ,OAAO,QAAQ,IAAI;EAChC,OAAO,QAAQ,OAAO,QAAQ,MAAM;EACpC,aAAa,QAAQ,OAAO,QAAQ,gBAAgB;EACpD,SAAS,QAAQ,OAAO,QAAQ,YAAY;EAC7C;;AAGH,SAAS,gBACP,SACA,KACoB;CACpB,MAAM,QAAQ,QAAQ;AACtB,QAAO,OAAO,UAAU,WAAW,QAAQ,KAAA;;AAG7C,SAAS,YAAkB;AACzB,SAAQ,IAAI,SAAS;AACrB,SAAQ,IAAI,GAAG;AACf,SAAQ,IAAI,SAAS;AACrB,SAAQ,IAAI,6CAA6C;AACzD,SAAQ,IAAI,iCAAiC;AAC7C,SAAQ,IAAI,wCAAwC;AACpD,SAAQ,IAAI,GAAG;AACf,SAAQ,IAAI,WAAW;AACvB,SAAQ,IAAI,8CAA8C;AAC1D,SAAQ,IAAI,qDAAqD;AACjE,SAAQ,IAAI,iEAAiE;AAC7E,SAAQ,IAAI,sEAAsE;AAClF,SAAQ,IAAI,+CAA+C;AAC3D,SAAQ,IAAI,2CAA2C"}
@@ -1 +0,0 @@
1
- export {};
File without changes