create-m5kdev 0.7.0 → 0.8.2
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/src/constants.d.mts +7 -0
- package/dist/src/constants.mjs +10 -0
- package/dist/src/constants.mjs.map +1 -0
- package/dist/src/create.d.mts +12 -0
- package/dist/src/create.mjs +33 -0
- package/dist/src/create.mjs.map +1 -0
- package/dist/src/fs.d.mts +10 -0
- package/dist/src/fs.mjs +50 -0
- package/dist/src/fs.mjs.map +1 -0
- package/dist/src/index.d.mts +1 -0
- package/dist/src/index.mjs +12 -0
- package/dist/src/index.mjs.map +1 -0
- package/dist/src/paths.d.mts +5 -0
- package/dist/src/paths.mjs +13 -0
- package/dist/src/paths.mjs.map +1 -0
- package/dist/src/prompts.d.mts +7 -0
- package/dist/src/prompts.mjs +45 -0
- package/dist/src/prompts.mjs.map +1 -0
- package/dist/src/runCli.d.mts +12 -0
- package/dist/src/runCli.mjs +101 -0
- package/dist/src/runCli.mjs.map +1 -0
- package/dist/src/strings.d.mts +11 -0
- package/dist/src/strings.mjs +34 -0
- package/dist/src/strings.mjs.map +1 -0
- package/dist/src/types.d.mts +22 -0
- package/package.json +3 -2
- package/dist/__tests__/create.smoke.test.js +0 -91
- package/dist/__tests__/create.test.js +0 -102
- package/dist/__tests__/runCli.test.js +0 -44
- package/dist/__tests__/strings.test.js +0 -24
- package/dist/constants.js +0 -9
- package/dist/create.js +0 -54
- package/dist/fs.js +0 -119
- package/dist/index.js +0 -9
- package/dist/paths.js +0 -14
- package/dist/prompts.js +0 -98
- package/dist/runCli.js +0 -119
- package/dist/src/__tests__/create.smoke.test.js +0 -56
- package/dist/src/__tests__/create.test.d.ts +0 -1
- package/dist/src/__tests__/create.test.js +0 -55
- package/dist/src/__tests__/runCli.test.d.ts +0 -1
- package/dist/src/__tests__/runCli.test.js +0 -44
- package/dist/src/__tests__/strings.test.d.ts +0 -1
- package/dist/src/__tests__/strings.test.js +0 -24
- package/dist/src/constants.d.ts +0 -3
- package/dist/src/constants.js +0 -9
- package/dist/src/create.d.ts +0 -7
- package/dist/src/create.js +0 -36
- package/dist/src/fs.d.ts +0 -5
- package/dist/src/fs.js +0 -60
- package/dist/src/index.d.ts +0 -2
- package/dist/src/index.js +0 -9
- package/dist/src/paths.d.ts +0 -1
- package/dist/src/paths.js +0 -14
- package/dist/src/prompts.d.ts +0 -2
- package/dist/src/prompts.js +0 -55
- package/dist/src/runCli.d.ts +0 -9
- package/dist/src/runCli.js +0 -107
- package/dist/src/strings.d.ts +0 -6
- package/dist/src/strings.js +0 -47
- package/dist/src/types.d.ts +0 -18
- package/dist/src/types.js +0 -2
- package/dist/strings.js +0 -47
- package/dist/tsconfig.tsbuildinfo +0 -1
- package/dist/types.js +0 -2
- /package/dist/src/{__tests__/create.smoke.test.d.ts → types.mjs} +0 -0
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const tslib_1 = require("tslib");
|
|
4
|
-
const promises_1 = tslib_1.__importDefault(require("node:fs/promises"));
|
|
5
|
-
const node_os_1 = tslib_1.__importDefault(require("node:os"));
|
|
6
|
-
const node_path_1 = tslib_1.__importDefault(require("node:path"));
|
|
7
|
-
const create_1 = require("../create");
|
|
8
|
-
describe("scaffoldProject", () => {
|
|
9
|
-
let tempRoot = "";
|
|
10
|
-
let initialCwd = "";
|
|
11
|
-
beforeEach(async () => {
|
|
12
|
-
initialCwd = process.cwd();
|
|
13
|
-
tempRoot = await promises_1.default.mkdtemp(node_path_1.default.join(node_os_1.default.tmpdir(), "m5kdev-cli-"));
|
|
14
|
-
process.chdir(tempRoot);
|
|
15
|
-
});
|
|
16
|
-
afterEach(async () => {
|
|
17
|
-
process.chdir(initialCwd);
|
|
18
|
-
await promises_1.default.rm(tempRoot, { recursive: true, force: true });
|
|
19
|
-
});
|
|
20
|
-
it("creates the minimal starter and replaces placeholders", async () => {
|
|
21
|
-
const result = await (0, create_1.scaffoldProject)({
|
|
22
|
-
targetDirectory: "editorial-desk",
|
|
23
|
-
appName: "Editorial Desk",
|
|
24
|
-
appDescription: "A clean newsroom starter.",
|
|
25
|
-
yes: true,
|
|
26
|
-
force: false,
|
|
27
|
-
skipInstall: true,
|
|
28
|
-
skipGit: true,
|
|
29
|
-
});
|
|
30
|
-
await expect(promises_1.default.stat(node_path_1.default.join(result.targetDirectory, "AGENTS.md"))).resolves.toBeTruthy();
|
|
31
|
-
await expect(promises_1.default.stat(node_path_1.default.join(result.targetDirectory, "apps/server/src/modules/posts/posts.service.ts"))).resolves.toBeTruthy();
|
|
32
|
-
await expect(promises_1.default.stat(node_path_1.default.join(result.targetDirectory, "apps/webapp/src/modules/posts/PostsRoute.tsx"))).resolves.toBeTruthy();
|
|
33
|
-
const rootPackage = await promises_1.default.readFile(node_path_1.default.join(result.targetDirectory, "package.json"), "utf8");
|
|
34
|
-
const rootAgents = await promises_1.default.readFile(node_path_1.default.join(result.targetDirectory, "AGENTS.md"), "utf8");
|
|
35
|
-
const sharedEnv = await promises_1.default.readFile(node_path_1.default.join(result.targetDirectory, "apps/shared/.env"), "utf8");
|
|
36
|
-
expect(rootPackage).toContain("\"name\": \"editorial-desk\"");
|
|
37
|
-
expect(rootAgents).toContain("Editorial Desk");
|
|
38
|
-
expect(rootAgents).toContain("A clean newsroom starter.");
|
|
39
|
-
expect(sharedEnv).toContain("VITE_APP_NAME=Editorial Desk");
|
|
40
|
-
expect(sharedEnv).not.toContain("{{APP_NAME}}");
|
|
41
|
-
});
|
|
42
|
-
it("refuses to overwrite a non-empty directory without force", async () => {
|
|
43
|
-
await promises_1.default.mkdir(node_path_1.default.join(tempRoot, "occupied"), { recursive: true });
|
|
44
|
-
await promises_1.default.writeFile(node_path_1.default.join(tempRoot, "occupied", "README.md"), "taken", "utf8");
|
|
45
|
-
await expect((0, create_1.scaffoldProject)({
|
|
46
|
-
targetDirectory: "occupied",
|
|
47
|
-
appName: "Occupied",
|
|
48
|
-
appDescription: "Collision test",
|
|
49
|
-
yes: true,
|
|
50
|
-
force: false,
|
|
51
|
-
skipInstall: true,
|
|
52
|
-
skipGit: true,
|
|
53
|
-
})).rejects.toThrow("Target directory is not empty");
|
|
54
|
-
});
|
|
55
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const runCli_1 = require("../runCli");
|
|
4
|
-
describe("parseCli", () => {
|
|
5
|
-
it("parses the explicit create command", () => {
|
|
6
|
-
expect((0, runCli_1.parseCli)(["create", "blog-app", "--name", "Blog App"])).toEqual({
|
|
7
|
-
command: "create",
|
|
8
|
-
directory: "blog-app",
|
|
9
|
-
help: false,
|
|
10
|
-
options: {
|
|
11
|
-
name: "Blog App",
|
|
12
|
-
},
|
|
13
|
-
});
|
|
14
|
-
});
|
|
15
|
-
it("treats a bare directory as the create command", () => {
|
|
16
|
-
expect((0, runCli_1.parseCli)(["blog-app", "--description", "Starter app"])).toEqual({
|
|
17
|
-
command: "create",
|
|
18
|
-
directory: "blog-app",
|
|
19
|
-
help: false,
|
|
20
|
-
options: {
|
|
21
|
-
description: "Starter app",
|
|
22
|
-
},
|
|
23
|
-
});
|
|
24
|
-
});
|
|
25
|
-
it("treats flag-only input as the create command", () => {
|
|
26
|
-
expect((0, runCli_1.parseCli)(["--name", "Blog App", "--yes"])).toEqual({
|
|
27
|
-
command: "create",
|
|
28
|
-
directory: undefined,
|
|
29
|
-
help: false,
|
|
30
|
-
options: {
|
|
31
|
-
name: "Blog App",
|
|
32
|
-
yes: true,
|
|
33
|
-
},
|
|
34
|
-
});
|
|
35
|
-
});
|
|
36
|
-
it("recognizes help in create mode", () => {
|
|
37
|
-
expect((0, runCli_1.parseCli)(["create", "--help"])).toEqual({
|
|
38
|
-
command: "create",
|
|
39
|
-
directory: undefined,
|
|
40
|
-
help: true,
|
|
41
|
-
options: {},
|
|
42
|
-
});
|
|
43
|
-
});
|
|
44
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const strings_1 = require("../strings");
|
|
4
|
-
describe("string helpers", () => {
|
|
5
|
-
it("slugifies app names into kebab-case", () => {
|
|
6
|
-
expect((0, strings_1.slugifyAppName)(" Editorial Desk ")).toBe("editorial-desk");
|
|
7
|
-
expect((0, strings_1.slugifyAppName)("M5 / Blog --- Starter")).toBe("m5-blog-starter");
|
|
8
|
-
});
|
|
9
|
-
it("derives a scoped package name", () => {
|
|
10
|
-
expect((0, strings_1.derivePackageScope)("editorial-desk")).toBe("@editorial-desk");
|
|
11
|
-
});
|
|
12
|
-
it("renders template placeholders", () => {
|
|
13
|
-
expect((0, strings_1.renderTemplate)("Hello {{APP_NAME}} from {{PACKAGE_SCOPE}}", {
|
|
14
|
-
appName: "Editorial Desk",
|
|
15
|
-
appDescription: "A test app",
|
|
16
|
-
appSlug: "editorial-desk",
|
|
17
|
-
packageScope: "@editorial-desk",
|
|
18
|
-
betterAuthSecret: "secret",
|
|
19
|
-
})).toBe("Hello Editorial Desk from @editorial-desk");
|
|
20
|
-
});
|
|
21
|
-
it("creates non-empty auth secrets", () => {
|
|
22
|
-
expect((0, strings_1.createBetterAuthSecret)()).toHaveLength(32);
|
|
23
|
-
});
|
|
24
|
-
});
|
package/dist/src/constants.d.ts
DELETED
package/dist/src/constants.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DEFAULT_APP_NAME = exports.TEMPLATE_NAME = void 0;
|
|
4
|
-
exports.getDefaultDescription = getDefaultDescription;
|
|
5
|
-
exports.TEMPLATE_NAME = "minimal-app";
|
|
6
|
-
exports.DEFAULT_APP_NAME = "M5 Starter";
|
|
7
|
-
function getDefaultDescription(appName) {
|
|
8
|
-
return `${appName} is a blog publishing platform scaffolded with the m5kdev stack.`;
|
|
9
|
-
}
|
package/dist/src/create.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { CreateCommandOptions, TemplateContext } from "./types";
|
|
2
|
-
export interface ScaffoldResult {
|
|
3
|
-
context: TemplateContext;
|
|
4
|
-
targetDirectory: string;
|
|
5
|
-
templateName: string;
|
|
6
|
-
}
|
|
7
|
-
export declare function scaffoldProject(initialOptions: CreateCommandOptions): Promise<ScaffoldResult>;
|
package/dist/src/create.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.scaffoldProject = scaffoldProject;
|
|
4
|
-
const tslib_1 = require("tslib");
|
|
5
|
-
const node_path_1 = tslib_1.__importDefault(require("node:path"));
|
|
6
|
-
const constants_1 = require("./constants");
|
|
7
|
-
const fs_1 = require("./fs");
|
|
8
|
-
const paths_1 = require("./paths");
|
|
9
|
-
const prompts_1 = require("./prompts");
|
|
10
|
-
const strings_1 = require("./strings");
|
|
11
|
-
async function scaffoldProject(initialOptions) {
|
|
12
|
-
const options = await (0, prompts_1.resolveCreateCommandOptions)(initialOptions);
|
|
13
|
-
const appSlug = (0, strings_1.slugifyAppName)(options.appName);
|
|
14
|
-
const targetDirectory = node_path_1.default.resolve(process.cwd(), options.targetDirectory);
|
|
15
|
-
const templateDirectory = (0, paths_1.getTemplateRoot)();
|
|
16
|
-
const context = {
|
|
17
|
-
appName: options.appName,
|
|
18
|
-
appDescription: options.appDescription,
|
|
19
|
-
appSlug,
|
|
20
|
-
packageScope: (0, strings_1.derivePackageScope)(appSlug),
|
|
21
|
-
betterAuthSecret: (0, strings_1.createBetterAuthSecret)(),
|
|
22
|
-
};
|
|
23
|
-
await (0, fs_1.ensureDirectoryState)(targetDirectory, options.force);
|
|
24
|
-
await (0, fs_1.copyTemplateDirectory)(templateDirectory, targetDirectory, context);
|
|
25
|
-
if (!options.skipGit) {
|
|
26
|
-
await (0, fs_1.runGitInit)(targetDirectory);
|
|
27
|
-
}
|
|
28
|
-
if (!options.skipInstall) {
|
|
29
|
-
await (0, fs_1.runInstall)(targetDirectory);
|
|
30
|
-
}
|
|
31
|
-
return {
|
|
32
|
-
context,
|
|
33
|
-
targetDirectory,
|
|
34
|
-
templateName: constants_1.TEMPLATE_NAME,
|
|
35
|
-
};
|
|
36
|
-
}
|
package/dist/src/fs.d.ts
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import type { TemplateContext } from "./types";
|
|
2
|
-
export declare function ensureDirectoryState(targetDirectory: string, force: boolean): Promise<void>;
|
|
3
|
-
export declare function copyTemplateDirectory(templateDirectory: string, targetDirectory: string, context: TemplateContext): Promise<void>;
|
|
4
|
-
export declare function runInstall(targetDirectory: string): Promise<void>;
|
|
5
|
-
export declare function runGitInit(targetDirectory: string): Promise<void>;
|
package/dist/src/fs.js
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ensureDirectoryState = ensureDirectoryState;
|
|
4
|
-
exports.copyTemplateDirectory = copyTemplateDirectory;
|
|
5
|
-
exports.runInstall = runInstall;
|
|
6
|
-
exports.runGitInit = runGitInit;
|
|
7
|
-
const tslib_1 = require("tslib");
|
|
8
|
-
const node_child_process_1 = require("node:child_process");
|
|
9
|
-
const promises_1 = tslib_1.__importDefault(require("node:fs/promises"));
|
|
10
|
-
const node_path_1 = tslib_1.__importDefault(require("node:path"));
|
|
11
|
-
const node_util_1 = require("node:util");
|
|
12
|
-
const strings_1 = require("./strings");
|
|
13
|
-
const execFileAsync = (0, node_util_1.promisify)(node_child_process_1.execFile);
|
|
14
|
-
const TEMPLATE_LINE_ENDING = "\r\n";
|
|
15
|
-
async function ensureDirectoryState(targetDirectory, force) {
|
|
16
|
-
const stat = await promises_1.default.stat(targetDirectory).catch(() => null);
|
|
17
|
-
if (!stat) {
|
|
18
|
-
await promises_1.default.mkdir(targetDirectory, { recursive: true });
|
|
19
|
-
return;
|
|
20
|
-
}
|
|
21
|
-
if (!stat.isDirectory()) {
|
|
22
|
-
throw new Error(`Target path is not a directory: ${targetDirectory}`);
|
|
23
|
-
}
|
|
24
|
-
const entries = await promises_1.default.readdir(targetDirectory);
|
|
25
|
-
if (entries.length > 0 && !force) {
|
|
26
|
-
throw new Error(`Target directory is not empty: ${targetDirectory}. Re-run with --force to overwrite.`);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
async function copyTemplateDirectory(templateDirectory, targetDirectory, context) {
|
|
30
|
-
const entries = await promises_1.default.readdir(templateDirectory, { withFileTypes: true });
|
|
31
|
-
for (const entry of entries) {
|
|
32
|
-
const sourcePath = node_path_1.default.join(templateDirectory, entry.name);
|
|
33
|
-
const targetName = entry.name.endsWith(".tpl") ? entry.name.slice(0, -4) : entry.name;
|
|
34
|
-
const targetPath = node_path_1.default.join(targetDirectory, targetName);
|
|
35
|
-
if (entry.isDirectory()) {
|
|
36
|
-
await promises_1.default.mkdir(targetPath, { recursive: true });
|
|
37
|
-
await copyTemplateDirectory(sourcePath, targetPath, context);
|
|
38
|
-
continue;
|
|
39
|
-
}
|
|
40
|
-
if (!entry.isFile()) {
|
|
41
|
-
continue;
|
|
42
|
-
}
|
|
43
|
-
const content = await promises_1.default.readFile(sourcePath, "utf8");
|
|
44
|
-
const rendered = (0, strings_1.renderTemplate)(content, context).replace(/\r?\n/g, TEMPLATE_LINE_ENDING);
|
|
45
|
-
await promises_1.default.mkdir(node_path_1.default.dirname(targetPath), { recursive: true });
|
|
46
|
-
await promises_1.default.writeFile(targetPath, rendered, "utf8");
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
async function runInstall(targetDirectory) {
|
|
50
|
-
await execFileAsync("pnpm", ["install"], {
|
|
51
|
-
cwd: targetDirectory,
|
|
52
|
-
env: process.env,
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
async function runGitInit(targetDirectory) {
|
|
56
|
-
await execFileAsync("git", ["init"], {
|
|
57
|
-
cwd: targetDirectory,
|
|
58
|
-
env: process.env,
|
|
59
|
-
});
|
|
60
|
-
}
|
package/dist/src/index.d.ts
DELETED
package/dist/src/index.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
"use strict";
|
|
3
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
const runCli_1 = require("./runCli");
|
|
5
|
-
(0, runCli_1.runCli)(process.argv.slice(2)).catch((error) => {
|
|
6
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
7
|
-
console.error(message);
|
|
8
|
-
process.exitCode = 1;
|
|
9
|
-
});
|
package/dist/src/paths.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function getTemplateRoot(): string;
|
package/dist/src/paths.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getTemplateRoot = getTemplateRoot;
|
|
4
|
-
const tslib_1 = require("tslib");
|
|
5
|
-
const node_fs_1 = tslib_1.__importDefault(require("node:fs"));
|
|
6
|
-
const node_path_1 = tslib_1.__importDefault(require("node:path"));
|
|
7
|
-
const constants_1 = require("./constants");
|
|
8
|
-
function getTemplateRoot() {
|
|
9
|
-
const sourcePath = node_path_1.default.resolve(__dirname, "../templates", constants_1.TEMPLATE_NAME);
|
|
10
|
-
if (node_fs_1.default.existsSync(sourcePath)) {
|
|
11
|
-
return sourcePath;
|
|
12
|
-
}
|
|
13
|
-
return node_path_1.default.resolve(__dirname, "../../templates", constants_1.TEMPLATE_NAME);
|
|
14
|
-
}
|
package/dist/src/prompts.d.ts
DELETED
package/dist/src/prompts.js
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.resolveCreateCommandOptions = resolveCreateCommandOptions;
|
|
4
|
-
const tslib_1 = require("tslib");
|
|
5
|
-
const promises_1 = tslib_1.__importDefault(require("node:readline/promises"));
|
|
6
|
-
const node_process_1 = require("node:process");
|
|
7
|
-
const constants_1 = require("./constants");
|
|
8
|
-
const strings_1 = require("./strings");
|
|
9
|
-
function requireInteractive(yes) {
|
|
10
|
-
if (!yes && !process.stdin.isTTY) {
|
|
11
|
-
throw new Error("Missing required values in a non-interactive shell. Pass --yes or provide flags.");
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
async function promptValue(question, fallback) {
|
|
15
|
-
const rl = promises_1.default.createInterface({ input: node_process_1.stdin, output: node_process_1.stdout });
|
|
16
|
-
try {
|
|
17
|
-
const suffix = fallback ? ` (${fallback})` : "";
|
|
18
|
-
const response = await rl.question(`${question}${suffix}: `);
|
|
19
|
-
return response.trim() || fallback || "";
|
|
20
|
-
}
|
|
21
|
-
finally {
|
|
22
|
-
rl.close();
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
async function resolveCreateCommandOptions(options) {
|
|
26
|
-
const resolved = { ...options };
|
|
27
|
-
if (!resolved.appName) {
|
|
28
|
-
requireInteractive(resolved.yes);
|
|
29
|
-
resolved.appName = resolved.yes
|
|
30
|
-
? resolved.targetDirectory
|
|
31
|
-
? (0, strings_1.toDisplayName)(pathBaseName(resolved.targetDirectory))
|
|
32
|
-
: constants_1.DEFAULT_APP_NAME
|
|
33
|
-
: await promptValue("App name", resolved.targetDirectory ? pathBaseName(resolved.targetDirectory) : constants_1.DEFAULT_APP_NAME);
|
|
34
|
-
}
|
|
35
|
-
resolved.appName = (0, strings_1.toDisplayName)(resolved.appName);
|
|
36
|
-
if (!resolved.targetDirectory) {
|
|
37
|
-
requireInteractive(resolved.yes);
|
|
38
|
-
resolved.targetDirectory = resolved.yes
|
|
39
|
-
? (0, strings_1.slugifyAppName)(resolved.appName)
|
|
40
|
-
: await promptValue("Target directory", (0, strings_1.slugifyAppName)(resolved.appName));
|
|
41
|
-
}
|
|
42
|
-
if (!resolved.appDescription) {
|
|
43
|
-
requireInteractive(resolved.yes);
|
|
44
|
-
const fallback = (0, constants_1.getDefaultDescription)(resolved.appName);
|
|
45
|
-
resolved.appDescription = resolved.yes
|
|
46
|
-
? fallback
|
|
47
|
-
: await promptValue("App description", fallback);
|
|
48
|
-
}
|
|
49
|
-
return resolved;
|
|
50
|
-
}
|
|
51
|
-
function pathBaseName(value) {
|
|
52
|
-
const normalized = value.replace(/[\\/]+$/g, "");
|
|
53
|
-
const segments = normalized.split(/[\\/]/).filter(Boolean);
|
|
54
|
-
return segments.at(-1) || constants_1.DEFAULT_APP_NAME;
|
|
55
|
-
}
|
package/dist/src/runCli.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
interface ParsedCli {
|
|
2
|
-
command?: string;
|
|
3
|
-
directory?: string;
|
|
4
|
-
help?: boolean;
|
|
5
|
-
options: Record<string, string | boolean>;
|
|
6
|
-
}
|
|
7
|
-
export declare function runCli(argv: readonly string[]): Promise<void>;
|
|
8
|
-
export declare function parseCli(argv: readonly string[]): ParsedCli;
|
|
9
|
-
export {};
|
package/dist/src/runCli.js
DELETED
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.runCli = runCli;
|
|
4
|
-
exports.parseCli = parseCli;
|
|
5
|
-
const create_1 = require("./create");
|
|
6
|
-
async function runCli(argv) {
|
|
7
|
-
const parsed = parseCli(argv);
|
|
8
|
-
if (!parsed.command ||
|
|
9
|
-
parsed.help ||
|
|
10
|
-
parsed.command === "--help" ||
|
|
11
|
-
parsed.command === "-h" ||
|
|
12
|
-
parsed.command === "help") {
|
|
13
|
-
printHelp();
|
|
14
|
-
return;
|
|
15
|
-
}
|
|
16
|
-
if (parsed.command !== "create") {
|
|
17
|
-
throw new Error(`Unknown command: ${parsed.command}`);
|
|
18
|
-
}
|
|
19
|
-
const options = toCreateCommandOptions(parsed);
|
|
20
|
-
const result = await (0, create_1.scaffoldProject)(options);
|
|
21
|
-
console.log("");
|
|
22
|
-
console.log(`Scaffolded ${result.context.appName} in ${result.targetDirectory}`);
|
|
23
|
-
console.log("");
|
|
24
|
-
console.log("Next steps:");
|
|
25
|
-
console.log(` cd ${result.targetDirectory}`);
|
|
26
|
-
if (options.skipInstall) {
|
|
27
|
-
console.log(" pnpm install");
|
|
28
|
-
}
|
|
29
|
-
console.log(" pnpm --filter ./apps/server sync");
|
|
30
|
-
console.log(" pnpm dev");
|
|
31
|
-
}
|
|
32
|
-
function parseCli(argv) {
|
|
33
|
-
const normalizedArgv = normalizeCliArgv(argv);
|
|
34
|
-
const [command, ...rest] = normalizedArgv;
|
|
35
|
-
const options = {};
|
|
36
|
-
let directory;
|
|
37
|
-
let help = false;
|
|
38
|
-
for (let index = 0; index < rest.length; index += 1) {
|
|
39
|
-
const token = rest[index];
|
|
40
|
-
if (token === "--help" || token === "-h") {
|
|
41
|
-
help = true;
|
|
42
|
-
continue;
|
|
43
|
-
}
|
|
44
|
-
if (!token.startsWith("--")) {
|
|
45
|
-
directory ??= token;
|
|
46
|
-
continue;
|
|
47
|
-
}
|
|
48
|
-
const [rawKey, inlineValue] = token.slice(2).split("=", 2);
|
|
49
|
-
if (isBooleanFlag(rawKey)) {
|
|
50
|
-
options[rawKey] = true;
|
|
51
|
-
continue;
|
|
52
|
-
}
|
|
53
|
-
const nextValue = inlineValue ?? rest[index + 1];
|
|
54
|
-
if (!nextValue || nextValue.startsWith("--")) {
|
|
55
|
-
throw new Error(`Missing value for --${rawKey}`);
|
|
56
|
-
}
|
|
57
|
-
options[rawKey] = nextValue;
|
|
58
|
-
if (inlineValue === undefined) {
|
|
59
|
-
index += 1;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
return { command, directory, help, options };
|
|
63
|
-
}
|
|
64
|
-
function normalizeCliArgv(argv) {
|
|
65
|
-
const [firstToken] = argv;
|
|
66
|
-
if (!firstToken || firstToken === "create" || firstToken === "--help" || firstToken === "-h") {
|
|
67
|
-
return argv;
|
|
68
|
-
}
|
|
69
|
-
if (firstToken === "help") {
|
|
70
|
-
return ["--help"];
|
|
71
|
-
}
|
|
72
|
-
return ["create", ...argv];
|
|
73
|
-
}
|
|
74
|
-
function isBooleanFlag(value) {
|
|
75
|
-
return ["yes", "force", "skip-install", "skip-git"].includes(value);
|
|
76
|
-
}
|
|
77
|
-
function toCreateCommandOptions(parsed) {
|
|
78
|
-
return {
|
|
79
|
-
targetDirectory: parsed.directory,
|
|
80
|
-
appName: getStringOption(parsed.options, "name"),
|
|
81
|
-
appDescription: getStringOption(parsed.options, "description"),
|
|
82
|
-
yes: Boolean(parsed.options.yes),
|
|
83
|
-
force: Boolean(parsed.options.force),
|
|
84
|
-
skipInstall: Boolean(parsed.options["skip-install"]),
|
|
85
|
-
skipGit: Boolean(parsed.options["skip-git"]),
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
function getStringOption(options, key) {
|
|
89
|
-
const value = options[key];
|
|
90
|
-
return typeof value === "string" ? value : undefined;
|
|
91
|
-
}
|
|
92
|
-
function printHelp() {
|
|
93
|
-
console.log("m5kdev");
|
|
94
|
-
console.log("");
|
|
95
|
-
console.log("Usage:");
|
|
96
|
-
console.log(" pnpm create m5kdev [directory] [options]");
|
|
97
|
-
console.log(" m5kdev [directory] [options]");
|
|
98
|
-
console.log(" m5kdev create [directory] [options]");
|
|
99
|
-
console.log("");
|
|
100
|
-
console.log("Options:");
|
|
101
|
-
console.log(" --name <value> Set the app name");
|
|
102
|
-
console.log(" --description <value> Set the app description");
|
|
103
|
-
console.log(" --yes Accept defaults for missing prompts");
|
|
104
|
-
console.log(" --force Allow writing into a non-empty directory");
|
|
105
|
-
console.log(" --skip-install Skip pnpm install");
|
|
106
|
-
console.log(" --skip-git Skip git init");
|
|
107
|
-
}
|
package/dist/src/strings.d.ts
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import type { TemplateContext } from "./types";
|
|
2
|
-
export declare function slugifyAppName(value: string): string;
|
|
3
|
-
export declare function derivePackageScope(appSlug: string): string;
|
|
4
|
-
export declare function toDisplayName(value: string): string;
|
|
5
|
-
export declare function createBetterAuthSecret(): string;
|
|
6
|
-
export declare function renderTemplate(content: string, context: TemplateContext): string;
|
package/dist/src/strings.js
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.slugifyAppName = slugifyAppName;
|
|
4
|
-
exports.derivePackageScope = derivePackageScope;
|
|
5
|
-
exports.toDisplayName = toDisplayName;
|
|
6
|
-
exports.createBetterAuthSecret = createBetterAuthSecret;
|
|
7
|
-
exports.renderTemplate = renderTemplate;
|
|
8
|
-
const node_crypto_1 = require("node:crypto");
|
|
9
|
-
function slugifyAppName(value) {
|
|
10
|
-
const slug = value
|
|
11
|
-
.trim()
|
|
12
|
-
.toLowerCase()
|
|
13
|
-
.replace(/[^a-z0-9]+/g, "-")
|
|
14
|
-
.replace(/^-+/g, "")
|
|
15
|
-
.replace(/-+$/g, "")
|
|
16
|
-
.replace(/-{2,}/g, "-");
|
|
17
|
-
if (!slug) {
|
|
18
|
-
throw new Error("Unable to derive an app slug from the provided name.");
|
|
19
|
-
}
|
|
20
|
-
return slug;
|
|
21
|
-
}
|
|
22
|
-
function derivePackageScope(appSlug) {
|
|
23
|
-
return `@${appSlug}`;
|
|
24
|
-
}
|
|
25
|
-
function toDisplayName(value) {
|
|
26
|
-
const normalized = value.trim();
|
|
27
|
-
if (!normalized) {
|
|
28
|
-
throw new Error("App name cannot be empty.");
|
|
29
|
-
}
|
|
30
|
-
return normalized;
|
|
31
|
-
}
|
|
32
|
-
function createBetterAuthSecret() {
|
|
33
|
-
return (0, node_crypto_1.randomBytes)(24).toString("base64url");
|
|
34
|
-
}
|
|
35
|
-
function renderTemplate(content, context) {
|
|
36
|
-
const replacements = {
|
|
37
|
-
APP_NAME: context.appName,
|
|
38
|
-
APP_DESCRIPTION: context.appDescription,
|
|
39
|
-
APP_SLUG: context.appSlug,
|
|
40
|
-
PACKAGE_SCOPE: context.packageScope,
|
|
41
|
-
BETTER_AUTH_SECRET: context.betterAuthSecret,
|
|
42
|
-
};
|
|
43
|
-
return content.replace(/\{\{([A-Z_]+)\}\}/g, (match, token) => {
|
|
44
|
-
const replacement = replacements[token];
|
|
45
|
-
return replacement ?? match;
|
|
46
|
-
});
|
|
47
|
-
}
|
package/dist/src/types.d.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
export interface PromptValues {
|
|
2
|
-
targetDirectory?: string;
|
|
3
|
-
appName?: string;
|
|
4
|
-
appDescription?: string;
|
|
5
|
-
}
|
|
6
|
-
export interface CreateCommandOptions extends PromptValues {
|
|
7
|
-
yes: boolean;
|
|
8
|
-
force: boolean;
|
|
9
|
-
skipInstall: boolean;
|
|
10
|
-
skipGit: boolean;
|
|
11
|
-
}
|
|
12
|
-
export interface TemplateContext {
|
|
13
|
-
appName: string;
|
|
14
|
-
appDescription: string;
|
|
15
|
-
appSlug: string;
|
|
16
|
-
packageScope: string;
|
|
17
|
-
betterAuthSecret: string;
|
|
18
|
-
}
|
package/dist/src/types.js
DELETED
package/dist/strings.js
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.slugifyAppName = slugifyAppName;
|
|
4
|
-
exports.derivePackageScope = derivePackageScope;
|
|
5
|
-
exports.toDisplayName = toDisplayName;
|
|
6
|
-
exports.createBetterAuthSecret = createBetterAuthSecret;
|
|
7
|
-
exports.renderTemplate = renderTemplate;
|
|
8
|
-
var node_crypto_1 = require("node:crypto");
|
|
9
|
-
function slugifyAppName(value) {
|
|
10
|
-
var slug = value
|
|
11
|
-
.trim()
|
|
12
|
-
.toLowerCase()
|
|
13
|
-
.replace(/[^a-z0-9]+/g, "-")
|
|
14
|
-
.replace(/^-+/g, "")
|
|
15
|
-
.replace(/-+$/g, "")
|
|
16
|
-
.replace(/-{2,}/g, "-");
|
|
17
|
-
if (!slug) {
|
|
18
|
-
throw new Error("Unable to derive an app slug from the provided name.");
|
|
19
|
-
}
|
|
20
|
-
return slug;
|
|
21
|
-
}
|
|
22
|
-
function derivePackageScope(appSlug) {
|
|
23
|
-
return "@".concat(appSlug);
|
|
24
|
-
}
|
|
25
|
-
function toDisplayName(value) {
|
|
26
|
-
var normalized = value.trim();
|
|
27
|
-
if (!normalized) {
|
|
28
|
-
throw new Error("App name cannot be empty.");
|
|
29
|
-
}
|
|
30
|
-
return normalized;
|
|
31
|
-
}
|
|
32
|
-
function createBetterAuthSecret() {
|
|
33
|
-
return (0, node_crypto_1.randomBytes)(24).toString("base64url");
|
|
34
|
-
}
|
|
35
|
-
function renderTemplate(content, context) {
|
|
36
|
-
var replacements = {
|
|
37
|
-
APP_NAME: context.appName,
|
|
38
|
-
APP_DESCRIPTION: context.appDescription,
|
|
39
|
-
APP_SLUG: context.appSlug,
|
|
40
|
-
PACKAGE_SCOPE: context.packageScope,
|
|
41
|
-
BETTER_AUTH_SECRET: context.betterAuthSecret,
|
|
42
|
-
};
|
|
43
|
-
return content.replace(/\{\{([A-Z_]+)\}\}/g, function (match, token) {
|
|
44
|
-
var replacement = replacements[token];
|
|
45
|
-
return replacement !== null && replacement !== void 0 ? replacement : match;
|
|
46
|
-
});
|
|
47
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"root":["../src/constants.ts","../src/create.ts","../src/fs.ts","../src/index.ts","../src/paths.ts","../src/prompts.ts","../src/runcli.ts","../src/strings.ts","../src/types.ts","../src/__tests__/create.smoke.test.ts","../src/__tests__/create.test.ts","../src/__tests__/runcli.test.ts","../src/__tests__/strings.test.ts"],"version":"5.9.2"}
|
package/dist/types.js
DELETED
|
File without changes
|