create-lumen 1.2.0 → 2.0.0-alpha.1

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 (146) hide show
  1. package/README.md +71 -9
  2. package/bin/cli.js +18 -4
  3. package/package.json +15 -4
  4. package/schema/fixtures/index.js +62 -0
  5. package/schema/fixtures/v2/invalid/architecture-preset-type-mismatch.json +35 -0
  6. package/schema/fixtures/v2/invalid/harness-empty-commands.json +37 -0
  7. package/schema/fixtures/v2/invalid/harness-missing-command.json +41 -0
  8. package/schema/fixtures/v2/invalid/invalid-manifest-version.json +33 -0
  9. package/schema/fixtures/v2/invalid/invalid-validation-mode.json +34 -0
  10. package/schema/fixtures/v2/invalid/malformed-paths.json +33 -0
  11. package/schema/fixtures/v2/invalid/missing-required-fields.json +17 -0
  12. package/schema/fixtures/v2/invalid/next-type-based.json +33 -0
  13. package/schema/fixtures/v2/invalid/next-vite.json +33 -0
  14. package/schema/fixtures/v2/invalid/react-bundler.json +34 -0
  15. package/schema/fixtures/v2/invalid/react-hybrid.json +33 -0
  16. package/schema/fixtures/v2/invalid/react-variant-mismatch.json +33 -0
  17. package/schema/fixtures/v2/invalid/shadcn-without-tailwind.json +33 -0
  18. package/schema/fixtures/v2/invalid/v1-flat-config.json +11 -0
  19. package/schema/fixtures/v2/valid/full-kitchen-sink.json +35 -0
  20. package/schema/fixtures/v2/valid/harness-full.json +44 -0
  21. package/schema/fixtures/v2/valid/next-app-router-feature-based.json +35 -0
  22. package/schema/fixtures/v2/valid/next-app-router-hybrid.json +35 -0
  23. package/schema/fixtures/v2/valid/next-app-router-none.json +33 -0
  24. package/schema/fixtures/v2/valid/next-pages-router-feature-based.json +35 -0
  25. package/schema/fixtures/v2/valid/next-pages-router-hybrid.json +35 -0
  26. package/schema/fixtures/v2/valid/next-pages-router-none.json +33 -0
  27. package/schema/fixtures/v2/valid/react-vite-feature-based.json +33 -0
  28. package/schema/fixtures/v2/valid/react-vite-none.json +33 -0
  29. package/schema/fixtures/v2/valid/react-vite-type-based.json +33 -0
  30. package/schema/fixtures/v2/valid/validation-none.json +41 -0
  31. package/schema/fixtures/v2/valid/validation-relaxed.json +41 -0
  32. package/schema/lumen.config.v2.json +269 -0
  33. package/skills/create-lumen/SKILL.md +110 -0
  34. package/skills/create-lumen/references/manifest-v2.md +9 -0
  35. package/src/agent-context.js +114 -0
  36. package/src/cli-args.js +294 -0
  37. package/src/css.js +20 -9
  38. package/src/dependencies.js +12 -6
  39. package/src/engine/capabilities.js +218 -0
  40. package/src/engine/index.js +2 -0
  41. package/src/engine/providers/base-provider.js +219 -0
  42. package/src/injector.js +26 -13
  43. package/src/main.js +66 -10
  44. package/src/manifest/emit.js +166 -0
  45. package/src/manifest/index.js +11 -0
  46. package/src/manifest/paths.js +128 -0
  47. package/src/manifest/schema.js +270 -0
  48. package/src/prompts.js +26 -6
  49. package/templates/conditional/linting/eslint/next/eslint.config.mjs +16 -0
  50. package/templates/css/tailwind/postcss.config.mjs +5 -0
  51. /package/templates/architectures/{component-based → type-based}/main.jsx +0 -0
  52. /package/templates/architectures/{component-based → type-based}/main.tsx +0 -0
  53. /package/templates/architectures/{component-based → type-based}/src/App.jsx +0 -0
  54. /package/templates/architectures/{component-based → type-based}/src/App.tsx +0 -0
  55. /package/templates/architectures/{component-based → type-based}/src/components/common/Button.jsx +0 -0
  56. /package/templates/architectures/{component-based → type-based}/src/components/common/Button.tsx +0 -0
  57. /package/templates/architectures/{component-based → type-based}/src/components/common/index.js +0 -0
  58. /package/templates/architectures/{component-based → type-based}/src/components/common/index.ts +0 -0
  59. /package/templates/architectures/{component-based → type-based}/src/components/form/.gitkeep +0 -0
  60. /package/templates/architectures/{component-based → type-based}/src/config/.gitkeep +0 -0
  61. /package/templates/architectures/{component-based → type-based}/src/hooks/useApp.js +0 -0
  62. /package/templates/architectures/{component-based → type-based}/src/hooks/useApp.ts +0 -0
  63. /package/templates/architectures/{component-based → type-based}/src/hooks/useLocalStorage.jsx +0 -0
  64. /package/templates/architectures/{component-based → type-based}/src/hooks/useLocalStorage.ts +0 -0
  65. /package/templates/architectures/{component-based → type-based}/src/layouts/MainLayout.jsx +0 -0
  66. /package/templates/architectures/{component-based → type-based}/src/layouts/MainLayout.tsx +0 -0
  67. /package/templates/architectures/{component-based → type-based}/src/pages/Home/Home.jsx +0 -0
  68. /package/templates/architectures/{component-based → type-based}/src/pages/Home/Home.tsx +0 -0
  69. /package/templates/architectures/{component-based → type-based}/src/pages/Home/index.js +0 -0
  70. /package/templates/architectures/{component-based → type-based}/src/pages/Home/index.ts +0 -0
  71. /package/templates/architectures/{component-based → type-based}/src/providers/.gitkeep +0 -0
  72. /package/templates/architectures/{component-based → type-based}/src/providers/AppProvider.jsx +0 -0
  73. /package/templates/architectures/{component-based → type-based}/src/providers/AppProvider.tsx +0 -0
  74. /package/templates/architectures/{component-based → type-based}/src/providers/appcontext.js +0 -0
  75. /package/templates/architectures/{component-based → type-based}/src/providers/appcontext.ts +0 -0
  76. /package/templates/architectures/{component-based → type-based}/src/services/.gitkeep +0 -0
  77. /package/templates/architectures/{component-based → type-based}/src/store/.gitkeep +0 -0
  78. /package/templates/architectures/{component-based → type-based}/src/styles/.gitkeep +0 -0
  79. /package/templates/architectures/{component-based → type-based}/src/types/index.js +0 -0
  80. /package/templates/architectures/{component-based → type-based}/src/types/index.ts +0 -0
  81. /package/templates/architectures/{component-based → type-based}/src/utils/cn.jsx +0 -0
  82. /package/templates/architectures/{component-based → type-based}/src/utils/cn.ts +0 -0
  83. /package/templates/conditional/axios/{component-based → type-based}/src/config/axios.config.js +0 -0
  84. /package/templates/conditional/axios/{component-based → type-based}/src/config/axios.config.ts +0 -0
  85. /package/templates/conditional/axios/{component-based → type-based}/src/services/axios.client.js +0 -0
  86. /package/templates/conditional/axios/{component-based → type-based}/src/services/axios.client.ts +0 -0
  87. /package/templates/conditional/axios/{component-based → type-based}/src/services/user.service.js +0 -0
  88. /package/templates/conditional/axios/{component-based → type-based}/src/services/user.service.ts +0 -0
  89. /package/templates/conditional/fetch/{component-based → type-based}/src/config/api.config.js +0 -0
  90. /package/templates/conditional/fetch/{component-based → type-based}/src/config/api.config.ts +0 -0
  91. /package/templates/conditional/fetch/{component-based → type-based}/src/services/api.client.js +0 -0
  92. /package/templates/conditional/fetch/{component-based → type-based}/src/services/api.client.ts +0 -0
  93. /package/templates/conditional/fetch/{component-based → type-based}/src/services/user.service.js +0 -0
  94. /package/templates/conditional/fetch/{component-based → type-based}/src/services/user.service.ts +0 -0
  95. /package/templates/conditional/icons/huge/{component-based → type-based}/bootstrap/src/pages/Home/Home.jsx +0 -0
  96. /package/templates/conditional/icons/huge/{component-based → type-based}/bootstrap/src/pages/Home/Home.tsx +0 -0
  97. /package/templates/conditional/icons/huge/{component-based → type-based}/src/pages/Home/Home.jsx +0 -0
  98. /package/templates/conditional/icons/huge/{component-based → type-based}/src/pages/Home/Home.tsx +0 -0
  99. /package/templates/conditional/icons/huge/{component-based → type-based}/tailwind/src/pages/Home/Home.jsx +0 -0
  100. /package/templates/conditional/icons/huge/{component-based → type-based}/tailwind/src/pages/Home/Home.tsx +0 -0
  101. /package/templates/conditional/icons/lucide/{component-based → type-based}/bootstrap/src/pages/Home/Home.jsx +0 -0
  102. /package/templates/conditional/icons/lucide/{component-based → type-based}/bootstrap/src/pages/Home/Home.tsx +0 -0
  103. /package/templates/conditional/icons/lucide/{component-based → type-based}/src/pages/Home/Home.jsx +0 -0
  104. /package/templates/conditional/icons/lucide/{component-based → type-based}/src/pages/Home/Home.tsx +0 -0
  105. /package/templates/conditional/icons/lucide/{component-based → type-based}/tailwind/src/pages/Home/Home.jsx +0 -0
  106. /package/templates/conditional/icons/lucide/{component-based → type-based}/tailwind/src/pages/Home/Home.tsx +0 -0
  107. /package/templates/conditional/router/{component-based → type-based}/bootstrap/src/layouts/MainLayout.jsx +0 -0
  108. /package/templates/conditional/router/{component-based → type-based}/bootstrap/src/layouts/MainLayout.tsx +0 -0
  109. /package/templates/conditional/router/{component-based → type-based}/src/App.jsx +0 -0
  110. /package/templates/conditional/router/{component-based → type-based}/src/App.tsx +0 -0
  111. /package/templates/conditional/router/{component-based → type-based}/src/layouts/MainLayout.jsx +0 -0
  112. /package/templates/conditional/router/{component-based → type-based}/src/layouts/MainLayout.tsx +0 -0
  113. /package/templates/conditional/router/{component-based → type-based}/src/router/guards/AuthGuard.jsx +0 -0
  114. /package/templates/conditional/router/{component-based → type-based}/src/router/guards/AuthGuard.tsx +0 -0
  115. /package/templates/conditional/router/{component-based → type-based}/src/router/guards/GuestGuard.jsx +0 -0
  116. /package/templates/conditional/router/{component-based → type-based}/src/router/guards/GuestGuard.tsx +0 -0
  117. /package/templates/conditional/router/{component-based → type-based}/src/router/index.jsx +0 -0
  118. /package/templates/conditional/router/{component-based → type-based}/src/router/index.tsx +0 -0
  119. /package/templates/conditional/router/{component-based → type-based}/tailwind/src/layouts/MainLayout.jsx +0 -0
  120. /package/templates/conditional/router/{component-based → type-based}/tailwind/src/layouts/MainLayout.tsx +0 -0
  121. /package/templates/conditional/state/redux/{component-based → type-based}/src/pages/Home/counterSlice.jsx +0 -0
  122. /package/templates/conditional/state/redux/{component-based → type-based}/src/pages/Home/counterSlice.ts +0 -0
  123. /package/templates/conditional/state/redux/{component-based → type-based}/src/providers/StoreProvider.jsx +0 -0
  124. /package/templates/conditional/state/redux/{component-based → type-based}/src/providers/StoreProvider.tsx +0 -0
  125. /package/templates/conditional/state/redux/{component-based → type-based}/src/store/hooks.js +0 -0
  126. /package/templates/conditional/state/redux/{component-based → type-based}/src/store/hooks.ts +0 -0
  127. /package/templates/conditional/state/redux/{component-based → type-based}/src/store/index.js +0 -0
  128. /package/templates/conditional/state/redux/{component-based → type-based}/src/store/index.ts +0 -0
  129. /package/templates/conditional/state/zustand/{component-based → type-based}/src/store/useCounterStore.jsx +0 -0
  130. /package/templates/conditional/state/zustand/{component-based → type-based}/src/store/useCounterStore.ts +0 -0
  131. /package/templates/conditional/testing/jest/{component-based → type-based}/src/__tests__/App.test.jsx +0 -0
  132. /package/templates/conditional/testing/jest/{component-based → type-based}/src/__tests__/App.test.tsx +0 -0
  133. /package/templates/conditional/testing/vitest/{component-based → type-based}/src/__tests__/App.test.jsx +0 -0
  134. /package/templates/conditional/testing/vitest/{component-based → type-based}/src/__tests__/App.test.tsx +0 -0
  135. /package/templates/css/component-styles/bootstrap/{component-based → type-based}/src/components/common/Button.jsx +0 -0
  136. /package/templates/css/component-styles/bootstrap/{component-based → type-based}/src/components/common/Button.tsx +0 -0
  137. /package/templates/css/component-styles/bootstrap/{component-based → type-based}/src/layouts/MainLayout.jsx +0 -0
  138. /package/templates/css/component-styles/bootstrap/{component-based → type-based}/src/layouts/MainLayout.tsx +0 -0
  139. /package/templates/css/component-styles/bootstrap/{component-based → type-based}/src/pages/Home/Home.jsx +0 -0
  140. /package/templates/css/component-styles/bootstrap/{component-based → type-based}/src/pages/Home/Home.tsx +0 -0
  141. /package/templates/css/component-styles/tailwind/{component-based → type-based}/src/components/common/Button.jsx +0 -0
  142. /package/templates/css/component-styles/tailwind/{component-based → type-based}/src/components/common/Button.tsx +0 -0
  143. /package/templates/css/component-styles/tailwind/{component-based → type-based}/src/layouts/MainLayout.jsx +0 -0
  144. /package/templates/css/component-styles/tailwind/{component-based → type-based}/src/layouts/MainLayout.tsx +0 -0
  145. /package/templates/css/component-styles/tailwind/{component-based → type-based}/src/pages/Home/Home.jsx +0 -0
  146. /package/templates/css/component-styles/tailwind/{component-based → type-based}/src/pages/Home/Home.tsx +0 -0
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # create-lumen
2
2
 
3
- A scaffolder that generates production-ready React + Vite projects (feature-based or component-based).
3
+ A scaffolder that generates production-ready React + Vite projects (feature-based or type-based).
4
4
 
5
5
  Note: this repository is the CLI scaffolder itself, not a generated app. Generated projects live in the target folder you create.
6
6
 
@@ -14,15 +14,44 @@ cd my-app
14
14
  npm run dev
15
15
  ```
16
16
 
17
- Non-interactive Quick Setup (TypeScript + Tailwind + Feature-based + Router + ESLint + Prettier + Vitest), no prompts:
17
+ ### Non-interactive flags
18
+
19
+ Quick Setup (TypeScript + Tailwind + Feature-based + Router + ESLint + Prettier + Vitest), no prompts:
18
20
 
19
21
  ```bash
20
22
  npm create lumen my-app -- -y
21
23
  # or
22
24
  npm create lumen -- -y my-app
25
+ # or
26
+ npm create lumen my-app -- --yes
27
+ ```
28
+
29
+ Scaffold using a template preset (`react-ts`, `react-js`, `react-type-ts`, `react-type-js`):
30
+
31
+ ```bash
32
+ npm create lumen my-app -- --template react-ts
33
+ # or
34
+ npm create lumen my-app -- -t react-type-js
23
35
  ```
24
36
 
25
- The CLI ignores flag arguments when resolving the project name, so `-y` can appear before or after the app name without being mistaken for the folder name.
37
+ Drive scaffolding directly from a manifest file or inline JSON (manifest v2):
38
+
39
+ ```bash
40
+ # From file
41
+ npm create lumen my-app -- --manifest ./lumen.config.json
42
+
43
+ # From inline JSON
44
+ npm create lumen my-app -- -m '{"manifestVersion":2,"framework":{"name":"react","variant":"vite"},...}'
45
+ ```
46
+
47
+ The CLI parses options cleanly regardless of flag ordering, so flags can appear before or after the project name.
48
+
49
+ Display help and version:
50
+
51
+ ```bash
52
+ npm create lumen -- --help
53
+ npm create lumen -- --version
54
+ ```
26
55
 
27
56
  Run the scaffolder locally (development / testing the generator):
28
57
 
@@ -35,14 +64,16 @@ create-lumen my-app # after npm link
35
64
 
36
65
  ## Features
37
66
 
38
- - Architecture choice: feature-based or component-based
67
+ - Architecture choice: feature-based or type-based (with Next.js hybrid/none in v2)
39
68
  - TypeScript or JavaScript output
40
- - CSS frameworks: Tailwind, Bootstrap, or none
69
+ - CSS frameworks: Tailwind CSS v4 (CSS-first `@theme`, v3 dropped), Bootstrap 5.3+, or none
41
70
  - Optional state management: Zustand or Redux Toolkit
42
71
  - Optional router (React Router)
43
72
  - Optional testing: Vitest or Jest
44
- - Linting: ESLint (default) or Oxlint
73
+ - Linting: ESLint (default), Oxlint, or Biome
45
74
  - Code formatter: Prettier or Oxfmt (chosen after the linter; `eslint-config-prettier` is auto-wired for the ESLint + Prettier combo)
75
+ - Manifest v2: Emits a deterministic `lumen.config.json` (optional but recommended) validated against JSON Schema Draft 2020-12, including architecture validation modes and harness command configuration.
76
+ - Explicit path mapping: Target directories declared for `lumen-cli` code generation
46
77
  - Optional Axios setup and icon libraries
47
78
  - Auto `git init`, generated `README` (with a project description reflecting the chosen tooling) and `LICENSE`
48
79
  - `.env.example` scaffolded, and the generated `.gitignore` excludes env files (`.env`, `.env.*`) while keeping `.env.example`
@@ -123,7 +154,7 @@ src/
123
154
  └── utils
124
155
  ```
125
156
 
126
- Component-based (example):
157
+ Type-based (example):
127
158
 
128
159
  ```
129
160
  src/
@@ -152,9 +183,40 @@ src/
152
183
  └── utils
153
184
  ```
154
185
 
155
- ## Roadmap
186
+ ## Manifest v2 & Ecosystem Architecture
187
+
188
+ `create-lumen` is part of the Lumen ecosystem alongside **`lumen-cli`**:
189
+
190
+ - **`create-lumen` (this repo):** The bootstrap scaffolder that initializes project repositories and writes an explicit, strictly validated `lumen.config.json` manifest (`manifestVersion: 2`) into the project root. The manifest is **optional but highly recommended** for full editor integration and agent interoperability. If omitted, `lumen-cli` will attempt to infer a basic configuration, but advanced features (like configurable harness and architecture validation) require the manifest.
191
+ - **`lumen-cli`:** The companion developer CLI that reads `lumen.config.json` to generate components, features, hooks, services, and run diagnostics (harness and doctor) at the paths declared in `manifest.paths`. It also provides commands to inspect and update the manifest.
192
+
193
+ ### Manifest v2 Schema (v2.0.0-alpha.1+)
194
+
195
+ The manifest now includes:
196
+ - **`architecture.preset`**: The base architecture (`feature-based`, `type-based`, `hybrid`, `none`).
197
+ - **`architecture.validation`**: Validation mode for `lumen doctor` (`strict`, `relaxed`, `none`).
198
+ - **`harness.commands`**: An array of commands to run with `lumen harness` (e.g., lint, format, types, test, build), each with a name, shell command, required flag, and description.
199
+
200
+ ### Ecosystem Documentation & Contracts
201
+
202
+ - **[Manifest v2 Overview](./docs/manifest-v2.md):** Specification of the nested schema, validation behavior, and the new harness and architecture validation fields.
203
+ - **[Shared Contract: `create-lumen` ↔ `lumen-cli`](./docs/contracts/manifest-v2-contract.md):** The agreed contract for path mapping, barrel conventions, version negotiation, and the harness/configuration interface.
204
+ - **[v1 to v2 Migration Guide](./docs/migration/v1-to-v2.md):** Complete guide for migrating generated projects and legacy flat configs to v2.
205
+
206
+ ### Agent Interoperability
207
+
208
+ Lumen is designed for both people and agents. When `agentDocs: true` is set in the manifest (or via the `--agent-docs` flag), `create-lumen` generates a `.lumen/` directory in the project root containing:
209
+ - `project.json`: The resolved manifest.
210
+ - `architecture.json`: The effective architecture preset and validation mode.
211
+ - `conventions.md`: A markdown file documenting project-specific conventions (e.g., component naming, file organization).
212
+ These files enable agents to understand the project without parsing the source code.
213
+
214
+ ## Roadmap & Planning
156
215
 
157
- Released versions live in [`docs/CHANGELOG.md`](./docs/CHANGELOG.md); planned work is tracked in [`docs/ROADMAP.md`](./docs/ROADMAP.md).
216
+ - **Changelog:** Notable changes are documented in [`docs/CHANGELOG.md`](./docs/CHANGELOG.md) (Keep a Changelog format).
217
+ - **Roadmap:** Milestones (M1 through M5) are tracked in [`docs/ROADMAP.md`](./docs/ROADMAP.md).
218
+ - **Visual Plan:** Dependency graphs and parallel wave execution plans live in [`docs/PLAN.md`](./docs/PLAN.md).
219
+ - **Branching Workflow:** Guide for branch conventions and PR checklist in [`docs/BRANCHING.md`](./docs/BRANCHING.md).
158
220
 
159
221
  ## Requirements
160
222
 
package/bin/cli.js CHANGED
@@ -3,14 +3,23 @@
3
3
  import { readFile } from "node:fs/promises";
4
4
  import chalk from "chalk";
5
5
  import "../register.js";
6
+ import { parseCliArgs, printHelp } from "../src/cli-args.js";
6
7
 
7
8
  const { version } = JSON.parse(
8
9
  await readFile(new URL("../package.json", import.meta.url), "utf8")
9
10
  );
10
11
 
11
- const args = process.argv.slice(2);
12
- const quickSetup = args.includes("-y");
13
- const projectName = args.find((a) => !a.startsWith("-"));
12
+ const cliArgs = parseCliArgs(process.argv.slice(2));
13
+
14
+ if (cliArgs.help) {
15
+ printHelp();
16
+ process.exit(0);
17
+ }
18
+
19
+ if (cliArgs.version) {
20
+ console.log(version);
21
+ process.exit(0);
22
+ }
14
23
 
15
24
  console.log(
16
25
  chalk.bold.cyan("\n ✦ LUMEN") +
@@ -22,7 +31,12 @@ console.log(
22
31
 
23
32
  const { main } = await import("@/main.js");
24
33
 
25
- main({ quickSetup, projectName }).catch((e) => {
34
+ main({
35
+ quickSetup: cliArgs.quickSetup,
36
+ projectName: cliArgs.projectName,
37
+ manifest: cliArgs.manifest,
38
+ template: cliArgs.template,
39
+ }).catch((e) => {
26
40
  console.error(chalk.red("\nError:"), e.message || e);
27
41
  process.exit(1);
28
42
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "create-lumen",
3
- "version": "1.2.0",
4
- "description": "Scaffold a React + Vite project with architecture choice: feature-based or component-based.",
3
+ "version": "2.0.0-alpha.1",
4
+ "description": "Scaffold a React + Vite project with architecture choice: feature-based or type-based.",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "create-lumen": "bin/cli.js"
@@ -15,10 +15,13 @@
15
15
  "register.js",
16
16
  "src/",
17
17
  "templates/",
18
+ "skills/",
19
+ "schema/",
18
20
  "README.md",
19
21
  "LICENSE"
20
22
  ],
21
23
  "scripts": {
24
+ "gen:schema": "node scripts/generate-schema.mjs",
22
25
  "test": "node --import ./register.js --test \"tests/unit/*.test.mjs\" \"tests/smoke/*.test.mjs\"",
23
26
  "verify:vendor": "node --import ./register.js tests/verify/install-vendor.mjs",
24
27
  "verify:offline": "node --import ./register.js tests/verify/verify-offline.mjs",
@@ -35,7 +38,7 @@
35
38
  "react",
36
39
  "typescript",
37
40
  "feature-based",
38
- "component-based",
41
+ "type-based",
39
42
  "architecture",
40
43
  "starter",
41
44
  "boilerplate"
@@ -45,9 +48,17 @@
45
48
  "dependencies": {
46
49
  "@clack/prompts": "^0.11.0",
47
50
  "chalk": "^5.6.2",
48
- "execa": "^9.6.0"
51
+ "execa": "^9.6.0",
52
+ "zod": "4.6.5",
53
+ "zod-validation-error": "4.0.0"
49
54
  },
50
55
  "engines": {
51
56
  "node": ">=18"
57
+ },
58
+ "devDependencies": {
59
+ "@eslint/js": "^10.0.1",
60
+ "@microsoft/eslint-formatter-sarif": "^3.1.0",
61
+ "eslint": "^10.10.0",
62
+ "globals": "^17.12.0"
52
63
  }
53
64
  }
@@ -0,0 +1,62 @@
1
+ import { readdir, readFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+
5
+ const __filename = fileURLToPath(import.meta.url);
6
+ const __dirname = path.dirname(__filename);
7
+
8
+ export const FIXTURES_DIR = __dirname;
9
+ export const VALID_FIXTURES_DIR = path.join(__dirname, "v2", "valid");
10
+ export const INVALID_FIXTURES_DIR = path.join(__dirname, "v2", "invalid");
11
+
12
+ /**
13
+ * Loads all valid manifest fixtures as an array of { name, filename, manifest }.
14
+ * @returns {Promise<Array<{ name: string, filename: string, manifest: object }>>}
15
+ */
16
+ export async function loadValidFixtures() {
17
+ const files = (await readdir(VALID_FIXTURES_DIR)).filter((f) => f.endsWith(".json"));
18
+ const fixtures = [];
19
+ for (const filename of files) {
20
+ const filePath = path.join(VALID_FIXTURES_DIR, filename);
21
+ const content = await readFile(filePath, "utf8");
22
+ fixtures.push({
23
+ name: path.basename(filename, ".json"),
24
+ filename,
25
+ manifest: JSON.parse(content),
26
+ });
27
+ }
28
+ return fixtures;
29
+ }
30
+
31
+ /**
32
+ * Loads all invalid manifest fixtures as an array of { name, filename, manifest }.
33
+ * @returns {Promise<Array<{ name: string, filename: string, manifest: object }>>}
34
+ */
35
+ export async function loadInvalidFixtures() {
36
+ const files = (await readdir(INVALID_FIXTURES_DIR)).filter((f) => f.endsWith(".json"));
37
+ const fixtures = [];
38
+ for (const filename of files) {
39
+ const filePath = path.join(INVALID_FIXTURES_DIR, filename);
40
+ const content = await readFile(filePath, "utf8");
41
+ fixtures.push({
42
+ name: path.basename(filename, ".json"),
43
+ filename,
44
+ manifest: JSON.parse(content),
45
+ });
46
+ }
47
+ return fixtures;
48
+ }
49
+
50
+ /**
51
+ * Loads a single fixture by category ('valid' | 'invalid') and fixture name.
52
+ * @param {'valid' | 'invalid'} category
53
+ * @param {string} name
54
+ * @returns {Promise<object>}
55
+ */
56
+ export async function getFixture(category, name) {
57
+ const dir = category === "valid" ? VALID_FIXTURES_DIR : INVALID_FIXTURES_DIR;
58
+ const filename = name.endsWith(".json") ? name : `${name}.json`;
59
+ const filePath = path.join(dir, filename);
60
+ const content = await readFile(filePath, "utf8");
61
+ return JSON.parse(content);
62
+ }
@@ -0,0 +1,35 @@
1
+ {
2
+ "$schema": "https://lumen-sh.github.io/create-lumen/schema/lumen.config.v2.json",
3
+ "manifestVersion": 2,
4
+ "framework": {
5
+ "name": "react",
6
+ "variant": "vite"
7
+ },
8
+ "styling": {
9
+ "engine": "tailwind"
10
+ },
11
+ "architecture": {
12
+ "preset": "feature-based",
13
+ "type": "type-based",
14
+ "validation": "strict"
15
+ },
16
+ "ui": {
17
+ "kit": "none"
18
+ },
19
+ "docs": {
20
+ "language": "en"
21
+ },
22
+ "paths": {
23
+ "features": "src/features",
24
+ "components": "src/shared/components",
25
+ "services": "src/shared/services",
26
+ "hooks": "src/shared/hooks",
27
+ "pages": "src/app/router",
28
+ "ui": "src/shared/components/ui"
29
+ },
30
+ "tooling": {
31
+ "language": "ts",
32
+ "linter": "eslint",
33
+ "formatter": "prettier"
34
+ }
35
+ }
@@ -0,0 +1,37 @@
1
+ {
2
+ "$schema": "https://lumen-sh.github.io/create-lumen/schema/lumen.config.v2.json",
3
+ "manifestVersion": 2,
4
+ "framework": {
5
+ "name": "react",
6
+ "variant": "vite"
7
+ },
8
+ "styling": {
9
+ "engine": "tailwind"
10
+ },
11
+ "architecture": {
12
+ "preset": "feature-based",
13
+ "validation": "strict"
14
+ },
15
+ "harness": {
16
+ "commands": []
17
+ },
18
+ "ui": {
19
+ "kit": "none"
20
+ },
21
+ "docs": {
22
+ "language": "en"
23
+ },
24
+ "paths": {
25
+ "features": "src/features",
26
+ "components": "src/shared/components",
27
+ "services": "src/shared/services",
28
+ "hooks": "src/shared/hooks",
29
+ "pages": "src/app/router",
30
+ "ui": "src/shared/components/ui"
31
+ },
32
+ "tooling": {
33
+ "language": "ts",
34
+ "linter": "eslint",
35
+ "formatter": "prettier"
36
+ }
37
+ }
@@ -0,0 +1,41 @@
1
+ {
2
+ "$schema": "https://lumen-sh.github.io/create-lumen/schema/lumen.config.v2.json",
3
+ "manifestVersion": 2,
4
+ "framework": {
5
+ "name": "react",
6
+ "variant": "vite"
7
+ },
8
+ "styling": {
9
+ "engine": "tailwind"
10
+ },
11
+ "architecture": {
12
+ "preset": "feature-based",
13
+ "validation": "strict"
14
+ },
15
+ "harness": {
16
+ "commands": [
17
+ { "name": "lint", "required": true },
18
+ { "name": "test", "command": "vitest run", "required": true },
19
+ { "name": "build", "command": "npm run build", "required": true }
20
+ ]
21
+ },
22
+ "ui": {
23
+ "kit": "none"
24
+ },
25
+ "docs": {
26
+ "language": "en"
27
+ },
28
+ "paths": {
29
+ "features": "src/features",
30
+ "components": "src/shared/components",
31
+ "services": "src/shared/services",
32
+ "hooks": "src/shared/hooks",
33
+ "pages": "src/app/router",
34
+ "ui": "src/shared/components/ui"
35
+ },
36
+ "tooling": {
37
+ "language": "ts",
38
+ "linter": "eslint",
39
+ "formatter": "prettier"
40
+ }
41
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "$schema": "https://lumen-sh.github.io/create-lumen/schema/lumen.config.v2.json",
3
+ "manifestVersion": 3,
4
+ "framework": {
5
+ "name": "react",
6
+ "variant": "vite"
7
+ },
8
+ "styling": {
9
+ "engine": "tailwind"
10
+ },
11
+ "architecture": {
12
+ "type": "feature-based"
13
+ },
14
+ "ui": {
15
+ "kit": "none"
16
+ },
17
+ "docs": {
18
+ "language": "en"
19
+ },
20
+ "paths": {
21
+ "features": "src/features",
22
+ "components": "src/shared/components",
23
+ "services": "src/shared/services",
24
+ "hooks": "src/shared/hooks",
25
+ "pages": "src/app/router",
26
+ "ui": "src/shared/components/ui"
27
+ },
28
+ "tooling": {
29
+ "language": "ts",
30
+ "linter": "eslint",
31
+ "formatter": "prettier"
32
+ }
33
+ }
@@ -0,0 +1,34 @@
1
+ {
2
+ "$schema": "https://lumen-sh.github.io/create-lumen/schema/lumen.config.v2.json",
3
+ "manifestVersion": 2,
4
+ "framework": {
5
+ "name": "react",
6
+ "variant": "vite"
7
+ },
8
+ "styling": {
9
+ "engine": "tailwind"
10
+ },
11
+ "architecture": {
12
+ "preset": "feature-based",
13
+ "validation": "super-strict"
14
+ },
15
+ "ui": {
16
+ "kit": "none"
17
+ },
18
+ "docs": {
19
+ "language": "en"
20
+ },
21
+ "paths": {
22
+ "features": "src/features",
23
+ "components": "src/shared/components",
24
+ "services": "src/shared/services",
25
+ "hooks": "src/shared/hooks",
26
+ "pages": "src/app/router",
27
+ "ui": "src/shared/components/ui"
28
+ },
29
+ "tooling": {
30
+ "language": "ts",
31
+ "linter": "eslint",
32
+ "formatter": "prettier"
33
+ }
34
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "$schema": "https://lumen-sh.github.io/create-lumen/schema/lumen.config.v2.json",
3
+ "manifestVersion": 2,
4
+ "framework": {
5
+ "name": "react",
6
+ "variant": "vite"
7
+ },
8
+ "styling": {
9
+ "engine": "tailwind"
10
+ },
11
+ "architecture": {
12
+ "type": "feature-based"
13
+ },
14
+ "ui": {
15
+ "kit": "none"
16
+ },
17
+ "docs": {
18
+ "language": "en"
19
+ },
20
+ "paths": {
21
+ "features": "",
22
+ "components": "src/shared/components",
23
+ "services": "src/shared/services",
24
+ "hooks": "src/shared/hooks",
25
+ "pages": "src/app/router",
26
+ "ui": "src/shared/components/ui"
27
+ },
28
+ "tooling": {
29
+ "language": "ts",
30
+ "linter": "eslint",
31
+ "formatter": "prettier"
32
+ }
33
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "$schema": "https://lumen-sh.github.io/create-lumen/schema/lumen.config.v2.json",
3
+ "manifestVersion": 2,
4
+ "framework": {
5
+ "name": "react",
6
+ "variant": "vite"
7
+ },
8
+ "styling": {
9
+ "engine": "tailwind"
10
+ },
11
+ "architecture": {
12
+ "type": "feature-based"
13
+ },
14
+ "ui": {
15
+ "kit": "none"
16
+ }
17
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "$schema": "https://lumen-sh.github.io/create-lumen/schema/lumen.config.v2.json",
3
+ "manifestVersion": 2,
4
+ "framework": {
5
+ "name": "next",
6
+ "variant": "app-router"
7
+ },
8
+ "styling": {
9
+ "engine": "tailwind"
10
+ },
11
+ "architecture": {
12
+ "type": "type-based"
13
+ },
14
+ "ui": {
15
+ "kit": "none"
16
+ },
17
+ "docs": {
18
+ "language": "en"
19
+ },
20
+ "paths": {
21
+ "features": "src/components",
22
+ "components": "src/components",
23
+ "services": "src/services",
24
+ "hooks": "src/hooks",
25
+ "pages": "app",
26
+ "ui": "src/components/ui"
27
+ },
28
+ "tooling": {
29
+ "language": "ts",
30
+ "linter": "eslint",
31
+ "formatter": "prettier"
32
+ }
33
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "$schema": "https://lumen-sh.github.io/create-lumen/schema/lumen.config.v2.json",
3
+ "manifestVersion": 2,
4
+ "framework": {
5
+ "name": "next",
6
+ "variant": "vite"
7
+ },
8
+ "styling": {
9
+ "engine": "tailwind"
10
+ },
11
+ "architecture": {
12
+ "type": "feature-based"
13
+ },
14
+ "ui": {
15
+ "kit": "none"
16
+ },
17
+ "docs": {
18
+ "language": "en"
19
+ },
20
+ "paths": {
21
+ "features": "src/features",
22
+ "components": "src/shared/components",
23
+ "services": "src/shared/services",
24
+ "hooks": "src/shared/hooks",
25
+ "pages": "app",
26
+ "ui": "src/shared/components/ui"
27
+ },
28
+ "tooling": {
29
+ "language": "ts",
30
+ "linter": "eslint",
31
+ "formatter": "prettier"
32
+ }
33
+ }
@@ -0,0 +1,34 @@
1
+ {
2
+ "$schema": "https://lumen-sh.github.io/create-lumen/schema/lumen.config.v2.json",
3
+ "manifestVersion": 2,
4
+ "framework": {
5
+ "name": "react",
6
+ "variant": "vite",
7
+ "bundler": "turbopack"
8
+ },
9
+ "styling": {
10
+ "engine": "tailwind"
11
+ },
12
+ "architecture": {
13
+ "type": "feature-based"
14
+ },
15
+ "ui": {
16
+ "kit": "none"
17
+ },
18
+ "docs": {
19
+ "language": "en"
20
+ },
21
+ "paths": {
22
+ "features": "src/features",
23
+ "components": "src/shared/components",
24
+ "services": "src/shared/services",
25
+ "hooks": "src/shared/hooks",
26
+ "pages": "src/app/router",
27
+ "ui": "src/shared/components/ui"
28
+ },
29
+ "tooling": {
30
+ "language": "ts",
31
+ "linter": "eslint",
32
+ "formatter": "prettier"
33
+ }
34
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "$schema": "https://lumen-sh.github.io/create-lumen/schema/lumen.config.v2.json",
3
+ "manifestVersion": 2,
4
+ "framework": {
5
+ "name": "react",
6
+ "variant": "vite"
7
+ },
8
+ "styling": {
9
+ "engine": "tailwind"
10
+ },
11
+ "architecture": {
12
+ "type": "hybrid"
13
+ },
14
+ "ui": {
15
+ "kit": "none"
16
+ },
17
+ "docs": {
18
+ "language": "en"
19
+ },
20
+ "paths": {
21
+ "features": "src/features",
22
+ "components": "src/shared/components",
23
+ "services": "src/shared/services",
24
+ "hooks": "src/shared/hooks",
25
+ "pages": "src/app/router",
26
+ "ui": "src/shared/components/ui"
27
+ },
28
+ "tooling": {
29
+ "language": "ts",
30
+ "linter": "eslint",
31
+ "formatter": "prettier"
32
+ }
33
+ }