create-lumen 2.0.0-beta.3 → 2.0.0-beta.5
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/package.json +1 -1
- package/src/cleanup.js +4 -1
- package/src/cli-args.js +10 -0
- package/src/css.js +15 -4
- package/src/dependencies.js +7 -0
- package/src/engine/composition.js +4 -0
- package/src/main.js +3 -1
- package/src/prompts.js +4 -0
- package/src/utils/dev-server.js +37 -10
- package/templates/conditional/state/redux/feature-based/src/app/providers/StoreProvider.jsx +2 -0
- package/templates/conditional/state/redux/feature-based/src/app/providers/StoreProvider.tsx +2 -0
- package/templates/conditional/state/redux/type-based/src/providers/StoreProvider.jsx +2 -0
- package/templates/conditional/state/redux/type-based/src/providers/StoreProvider.tsx +2 -0
- /package/templates/conditional/state/zustand/feature-based/src/{stores → shared/stores}/useCounterStore.jsx +0 -0
- /package/templates/conditional/state/zustand/feature-based/src/{stores → shared/stores}/useCounterStore.ts +0 -0
package/package.json
CHANGED
package/src/cleanup.js
CHANGED
|
@@ -21,6 +21,7 @@ export async function cleanupBoilerplate(projectPath, responses = {}) {
|
|
|
21
21
|
await deleteIfExists(`${projectPath}/src/App.tsx`);
|
|
22
22
|
await deleteIfExists(`${projectPath}/src/App.jsx`);
|
|
23
23
|
await deleteIfExists(`${projectPath}/src/App.css`);
|
|
24
|
+
await deleteIfExists(`${projectPath}/src/shared/styles`);
|
|
24
25
|
|
|
25
26
|
const isPagesRouter =
|
|
26
27
|
responses?.framework?.variant === "pages-router" ||
|
|
@@ -34,7 +35,9 @@ export async function cleanupBoilerplate(projectPath, responses = {}) {
|
|
|
34
35
|
await deleteIfExists(`${projectPath}/src/app/App.jsx`);
|
|
35
36
|
await deleteIfExists(`${projectPath}/src/app/hooks`);
|
|
36
37
|
await deleteIfExists(`${projectPath}/src/app/contexts`);
|
|
37
|
-
|
|
38
|
+
if (responses?.stateManagement !== "redux") {
|
|
39
|
+
await deleteIfExists(`${projectPath}/src/app/providers`);
|
|
40
|
+
}
|
|
38
41
|
}
|
|
39
42
|
}
|
|
40
43
|
}
|
package/src/cli-args.js
CHANGED
|
@@ -299,6 +299,9 @@ export function parseCliArgs(argv = process.argv.slice(2)) {
|
|
|
299
299
|
styling: { type: "string" },
|
|
300
300
|
"css-framework": { type: "string" },
|
|
301
301
|
cssFramework: { type: "string" },
|
|
302
|
+
state: { type: "string", short: "s" },
|
|
303
|
+
"state-management": { type: "string" },
|
|
304
|
+
stateManagement: { type: "string" },
|
|
302
305
|
ui: { type: "string", short: "u" },
|
|
303
306
|
uiKit: { type: "string" },
|
|
304
307
|
"ui-kit": { type: "string" },
|
|
@@ -348,6 +351,11 @@ export function parseCliArgs(argv = process.argv.slice(2)) {
|
|
|
348
351
|
values.cssFramework ||
|
|
349
352
|
null;
|
|
350
353
|
const uiKit = values.ui || values.uiKit || values["ui-kit"] || null;
|
|
354
|
+
let stateManagement = values.state || values["state-management"] || values.stateManagement || null;
|
|
355
|
+
if (stateManagement) {
|
|
356
|
+
stateManagement = stateManagement.trim().toLowerCase();
|
|
357
|
+
if (stateManagement === "rtk" || stateManagement === "reduxtoolkit") stateManagement = "redux";
|
|
358
|
+
}
|
|
351
359
|
const testing = values.testing ? values.testing.trim().toLowerCase() : null;
|
|
352
360
|
const linter = values.linter ? values.linter.trim().toLowerCase() : null;
|
|
353
361
|
const formatter = values.formatter ? values.formatter.trim().toLowerCase() : null;
|
|
@@ -361,6 +369,7 @@ export function parseCliArgs(argv = process.argv.slice(2)) {
|
|
|
361
369
|
arch,
|
|
362
370
|
language,
|
|
363
371
|
cssFramework,
|
|
372
|
+
stateManagement,
|
|
364
373
|
uiKit,
|
|
365
374
|
bundler,
|
|
366
375
|
adapter,
|
|
@@ -487,6 +496,7 @@ ${chalk.bold("OPTIONS")}
|
|
|
487
496
|
${chalk.yellow("-a, --arch")} <name> Architecture preset (feature-based, type-based, none)
|
|
488
497
|
${chalk.yellow("-l, --language")} <lang> Language (ts, js)
|
|
489
498
|
${chalk.yellow("-c, --css")} <framework> Styling engine (tailwind, none)
|
|
499
|
+
${chalk.yellow("-s, --state")} <lib> State management (zustand, redux, none)
|
|
490
500
|
${chalk.yellow("-m, --manifest")} <path> Drive scaffolding from a lumen.config.json or inline JSON
|
|
491
501
|
${chalk.yellow("-t, --template")} <name> Scaffold using a preset (${Object.keys(PRESETS).join(", ")})
|
|
492
502
|
${chalk.yellow("-f, --framework")} <name> Target framework (react, next, react:vite, next:app-router, etc.)
|
package/src/css.js
CHANGED
|
@@ -24,15 +24,26 @@ export async function setupCssFramework({
|
|
|
24
24
|
// framework is "none"); type-based imports ./styles/globals.css (or
|
|
25
25
|
// main.css). The chosen framework's styles land in the file the architecture
|
|
26
26
|
// actually imports.
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
let stylesDir;
|
|
28
|
+
if (fw.name === "next") {
|
|
29
|
+
stylesDir =
|
|
30
|
+
fw.variant === "pages-router"
|
|
31
|
+
? path.join(projectPath, "src", "styles")
|
|
32
|
+
: path.join(projectPath, "src", "app");
|
|
33
|
+
} else {
|
|
34
|
+
stylesDir =
|
|
35
|
+
architecture === "feature-based"
|
|
36
|
+
? path.join(projectPath, "src", "shared", "styles")
|
|
37
|
+
: path.join(projectPath, "src", "styles");
|
|
38
|
+
}
|
|
31
39
|
|
|
32
40
|
// Vanilla CSS gets a stylesheet named main.css; tailwind keeps
|
|
33
41
|
// globals.css (its idiomatic name — it injects framework directives).
|
|
34
42
|
const mainFileName = cssFramework === "none" ? "main.css" : "globals.css";
|
|
35
43
|
|
|
44
|
+
// Ensure the styles dir exists
|
|
45
|
+
await fsp.mkdir(stylesDir, { recursive: true });
|
|
46
|
+
|
|
36
47
|
async function writeCss(content, fileName) {
|
|
37
48
|
await fsp.writeFile(path.join(stylesDir, fileName), content, "utf8");
|
|
38
49
|
}
|
package/src/dependencies.js
CHANGED
|
@@ -34,6 +34,13 @@ export async function installAllDeps(responses, pkg, cwd) {
|
|
|
34
34
|
for (const batch of devDepBatches) {
|
|
35
35
|
await installDeps(pkg, true, batch, cwd);
|
|
36
36
|
}
|
|
37
|
+
|
|
38
|
+
if (responses.database === "prisma") {
|
|
39
|
+
try {
|
|
40
|
+
const runner = pkg === "npm" ? "npx" : pkg;
|
|
41
|
+
await execa(runner, ["prisma", "generate"], { cwd, stdio: "pipe" });
|
|
42
|
+
} catch {}
|
|
43
|
+
}
|
|
37
44
|
}
|
|
38
45
|
|
|
39
46
|
// Pure dependency computation — the package list for a given matrix cell,
|
|
@@ -384,6 +384,7 @@ export function resolveFragments(responses = {}, templatesDir) {
|
|
|
384
384
|
"db:push": "prisma db push",
|
|
385
385
|
"db:seed": "prisma db seed",
|
|
386
386
|
"db:studio": "prisma studio",
|
|
387
|
+
postinstall: "prisma generate",
|
|
387
388
|
},
|
|
388
389
|
action: async ({ projectPath, templatesDir: tDir }) => {
|
|
389
390
|
const prismaTplDir = path.join(tDir, "conditional", "database", "prisma");
|
|
@@ -753,6 +754,9 @@ export function resolveFragments(responses = {}, templatesDir) {
|
|
|
753
754
|
try {
|
|
754
755
|
await fsp.rm(path.join(projectPath, "src", "app", "page.tsx"), { force: true });
|
|
755
756
|
} catch {}
|
|
757
|
+
try {
|
|
758
|
+
await fsp.rm(path.join(projectPath, "src", "app", "page.module.css"), { force: true });
|
|
759
|
+
} catch {}
|
|
756
760
|
// Adjust existing test file if it imported @/app/page before route groups was applied
|
|
757
761
|
for (const testExt of ["tsx", "jsx", "ts", "js"]) {
|
|
758
762
|
const testPath = path.join(projectPath, "src", "__tests__", `page.test.${testExt}`);
|
package/src/main.js
CHANGED
|
@@ -54,6 +54,7 @@ export async function main(options = {}) {
|
|
|
54
54
|
arch: archArg,
|
|
55
55
|
language: languageArg,
|
|
56
56
|
cssFramework: cssArg,
|
|
57
|
+
stateManagement: stateArg,
|
|
57
58
|
uiKit: uiKitArg,
|
|
58
59
|
database: databaseArg,
|
|
59
60
|
databaseProvider: dbProviderArg,
|
|
@@ -118,6 +119,7 @@ export async function main(options = {}) {
|
|
|
118
119
|
// Overlay explicit CLI flags if provided
|
|
119
120
|
if (languageArg) responses.language = languageArg;
|
|
120
121
|
if (cssArg) responses.cssFramework = cssArg;
|
|
122
|
+
if (stateArg) responses.stateManagement = stateArg;
|
|
121
123
|
if (uiKitArg) responses.uiKit = uiKitArg;
|
|
122
124
|
if (linterArg) responses.linter = linterArg;
|
|
123
125
|
if (formatterArg) responses.formatter = formatterArg;
|
|
@@ -362,5 +364,5 @@ export async function main(options = {}) {
|
|
|
362
364
|
);
|
|
363
365
|
|
|
364
366
|
// 14. Offer dev server
|
|
365
|
-
await handleDevServer(pkg,
|
|
367
|
+
await handleDevServer(pkg, projectPath, { isNonInteractive, projectName });
|
|
366
368
|
}
|
package/src/prompts.js
CHANGED
|
@@ -548,6 +548,10 @@ export async function getUserInputs(
|
|
|
548
548
|
{
|
|
549
549
|
id: "stateManagement",
|
|
550
550
|
message: "Which state management library do you want to use?",
|
|
551
|
+
skip: (ans) => ans.architecture === "none",
|
|
552
|
+
onSkip: (ans) => {
|
|
553
|
+
ans.stateManagement = "none";
|
|
554
|
+
},
|
|
551
555
|
getOptions: () => [
|
|
552
556
|
{ label: "None", value: "none" },
|
|
553
557
|
{ label: "Redux Toolkit", value: "redux" },
|
package/src/utils/dev-server.js
CHANGED
|
@@ -1,14 +1,30 @@
|
|
|
1
1
|
import { isCancel, select } from "@clack/prompts";
|
|
2
2
|
import chalk from "chalk";
|
|
3
3
|
import { execa } from "execa";
|
|
4
|
+
import path from "path";
|
|
4
5
|
|
|
5
|
-
export async function handleDevServer(
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
export async function handleDevServer(
|
|
7
|
+
pkg,
|
|
8
|
+
projectPathOrName,
|
|
9
|
+
{
|
|
10
|
+
isNonInteractive = false,
|
|
11
|
+
projectName = null,
|
|
12
|
+
selectFn = select,
|
|
13
|
+
execaFn = execa,
|
|
14
|
+
isTTY = process.stdin.isTTY,
|
|
15
|
+
} = {}
|
|
16
|
+
) {
|
|
17
|
+
const targetDir = path.isAbsolute(projectPathOrName)
|
|
18
|
+
? projectPathOrName
|
|
19
|
+
: path.resolve(process.cwd(), projectPathOrName);
|
|
20
|
+
const displayName = projectName || path.basename(projectPathOrName);
|
|
21
|
+
|
|
22
|
+
if (isNonInteractive || process.env.CI || !isTTY) {
|
|
23
|
+
printNextSteps(displayName, pkg);
|
|
8
24
|
return;
|
|
9
25
|
}
|
|
10
26
|
|
|
11
|
-
const startDev = await
|
|
27
|
+
const startDev = await selectFn({
|
|
12
28
|
message: "Start the development server?",
|
|
13
29
|
options: [
|
|
14
30
|
{ label: "Yes", value: true },
|
|
@@ -18,22 +34,33 @@ export async function handleDevServer(pkg, projectName, { isNonInteractive = fal
|
|
|
18
34
|
});
|
|
19
35
|
|
|
20
36
|
if (isCancel(startDev)) {
|
|
21
|
-
printNextSteps(
|
|
37
|
+
printNextSteps(displayName, pkg);
|
|
22
38
|
return;
|
|
23
39
|
}
|
|
24
40
|
|
|
25
41
|
if (startDev) {
|
|
26
42
|
console.log(chalk.green("\nStarting dev server...\n"));
|
|
27
|
-
|
|
43
|
+
try {
|
|
44
|
+
await execaFn(pkg, ["run", "dev"], { cwd: targetDir, stdio: "inherit" });
|
|
45
|
+
} catch (err) {
|
|
46
|
+
if (
|
|
47
|
+
err?.signal === "SIGINT" ||
|
|
48
|
+
err?.signal === "SIGTERM" ||
|
|
49
|
+
err?.exitCode === 130
|
|
50
|
+
) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
throw err;
|
|
54
|
+
}
|
|
28
55
|
} else {
|
|
29
|
-
printNextSteps(
|
|
56
|
+
printNextSteps(displayName, pkg);
|
|
30
57
|
}
|
|
31
58
|
}
|
|
32
59
|
|
|
33
|
-
function printNextSteps(
|
|
60
|
+
function printNextSteps(displayName, pkg) {
|
|
34
61
|
console.log(chalk.bold("\nNext steps:"));
|
|
35
|
-
if (
|
|
36
|
-
console.log(chalk.gray(` cd ${
|
|
62
|
+
if (displayName !== "." && displayName !== "") {
|
|
63
|
+
console.log(chalk.gray(` cd ${displayName}`));
|
|
37
64
|
}
|
|
38
65
|
console.log(chalk.gray(` ${pkg} run dev\n`));
|
|
39
66
|
}
|
|
File without changes
|
|
File without changes
|