create-lumen 1.2.0 → 2.0.0-alpha.0
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/README.md +56 -9
- package/bin/cli.js +18 -4
- package/package.json +14 -4
- package/schema/fixtures/index.js +62 -0
- package/schema/fixtures/v2/invalid/invalid-manifest-version.json +33 -0
- package/schema/fixtures/v2/invalid/malformed-paths.json +33 -0
- package/schema/fixtures/v2/invalid/missing-required-fields.json +17 -0
- package/schema/fixtures/v2/invalid/next-type-based.json +33 -0
- package/schema/fixtures/v2/invalid/next-vite.json +33 -0
- package/schema/fixtures/v2/invalid/react-bundler.json +34 -0
- package/schema/fixtures/v2/invalid/react-hybrid.json +33 -0
- package/schema/fixtures/v2/invalid/react-variant-mismatch.json +33 -0
- package/schema/fixtures/v2/invalid/shadcn-without-tailwind.json +33 -0
- package/schema/fixtures/v2/invalid/v1-flat-config.json +11 -0
- package/schema/fixtures/v2/valid/full-kitchen-sink.json +35 -0
- package/schema/fixtures/v2/valid/next-app-router-feature-based.json +35 -0
- package/schema/fixtures/v2/valid/next-app-router-hybrid.json +35 -0
- package/schema/fixtures/v2/valid/next-app-router-none.json +33 -0
- package/schema/fixtures/v2/valid/next-pages-router-feature-based.json +35 -0
- package/schema/fixtures/v2/valid/next-pages-router-hybrid.json +35 -0
- package/schema/fixtures/v2/valid/next-pages-router-none.json +33 -0
- package/schema/fixtures/v2/valid/react-vite-feature-based.json +33 -0
- package/schema/fixtures/v2/valid/react-vite-none.json +33 -0
- package/schema/fixtures/v2/valid/react-vite-type-based.json +33 -0
- package/schema/lumen.config.v2.json +216 -0
- package/src/cli-args.js +294 -0
- package/src/css.js +20 -9
- package/src/dependencies.js +12 -6
- package/src/engine/capabilities.js +218 -0
- package/src/engine/index.js +2 -0
- package/src/engine/providers/base-provider.js +219 -0
- package/src/injector.js +26 -13
- package/src/main.js +52 -10
- package/src/manifest/emit.js +120 -0
- package/src/manifest/index.js +11 -0
- package/src/manifest/paths.js +128 -0
- package/src/manifest/schema.js +212 -0
- package/src/prompts.js +26 -6
- package/templates/conditional/linting/eslint/next/eslint.config.mjs +16 -0
- package/templates/css/tailwind/postcss.config.mjs +5 -0
- /package/templates/architectures/{component-based → type-based}/main.jsx +0 -0
- /package/templates/architectures/{component-based → type-based}/main.tsx +0 -0
- /package/templates/architectures/{component-based → type-based}/src/App.jsx +0 -0
- /package/templates/architectures/{component-based → type-based}/src/App.tsx +0 -0
- /package/templates/architectures/{component-based → type-based}/src/components/common/Button.jsx +0 -0
- /package/templates/architectures/{component-based → type-based}/src/components/common/Button.tsx +0 -0
- /package/templates/architectures/{component-based → type-based}/src/components/common/index.js +0 -0
- /package/templates/architectures/{component-based → type-based}/src/components/common/index.ts +0 -0
- /package/templates/architectures/{component-based → type-based}/src/components/form/.gitkeep +0 -0
- /package/templates/architectures/{component-based → type-based}/src/config/.gitkeep +0 -0
- /package/templates/architectures/{component-based → type-based}/src/hooks/useApp.js +0 -0
- /package/templates/architectures/{component-based → type-based}/src/hooks/useApp.ts +0 -0
- /package/templates/architectures/{component-based → type-based}/src/hooks/useLocalStorage.jsx +0 -0
- /package/templates/architectures/{component-based → type-based}/src/hooks/useLocalStorage.ts +0 -0
- /package/templates/architectures/{component-based → type-based}/src/layouts/MainLayout.jsx +0 -0
- /package/templates/architectures/{component-based → type-based}/src/layouts/MainLayout.tsx +0 -0
- /package/templates/architectures/{component-based → type-based}/src/pages/Home/Home.jsx +0 -0
- /package/templates/architectures/{component-based → type-based}/src/pages/Home/Home.tsx +0 -0
- /package/templates/architectures/{component-based → type-based}/src/pages/Home/index.js +0 -0
- /package/templates/architectures/{component-based → type-based}/src/pages/Home/index.ts +0 -0
- /package/templates/architectures/{component-based → type-based}/src/providers/.gitkeep +0 -0
- /package/templates/architectures/{component-based → type-based}/src/providers/AppProvider.jsx +0 -0
- /package/templates/architectures/{component-based → type-based}/src/providers/AppProvider.tsx +0 -0
- /package/templates/architectures/{component-based → type-based}/src/providers/appcontext.js +0 -0
- /package/templates/architectures/{component-based → type-based}/src/providers/appcontext.ts +0 -0
- /package/templates/architectures/{component-based → type-based}/src/services/.gitkeep +0 -0
- /package/templates/architectures/{component-based → type-based}/src/store/.gitkeep +0 -0
- /package/templates/architectures/{component-based → type-based}/src/styles/.gitkeep +0 -0
- /package/templates/architectures/{component-based → type-based}/src/types/index.js +0 -0
- /package/templates/architectures/{component-based → type-based}/src/types/index.ts +0 -0
- /package/templates/architectures/{component-based → type-based}/src/utils/cn.jsx +0 -0
- /package/templates/architectures/{component-based → type-based}/src/utils/cn.ts +0 -0
- /package/templates/conditional/axios/{component-based → type-based}/src/config/axios.config.js +0 -0
- /package/templates/conditional/axios/{component-based → type-based}/src/config/axios.config.ts +0 -0
- /package/templates/conditional/axios/{component-based → type-based}/src/services/axios.client.js +0 -0
- /package/templates/conditional/axios/{component-based → type-based}/src/services/axios.client.ts +0 -0
- /package/templates/conditional/axios/{component-based → type-based}/src/services/user.service.js +0 -0
- /package/templates/conditional/axios/{component-based → type-based}/src/services/user.service.ts +0 -0
- /package/templates/conditional/fetch/{component-based → type-based}/src/config/api.config.js +0 -0
- /package/templates/conditional/fetch/{component-based → type-based}/src/config/api.config.ts +0 -0
- /package/templates/conditional/fetch/{component-based → type-based}/src/services/api.client.js +0 -0
- /package/templates/conditional/fetch/{component-based → type-based}/src/services/api.client.ts +0 -0
- /package/templates/conditional/fetch/{component-based → type-based}/src/services/user.service.js +0 -0
- /package/templates/conditional/fetch/{component-based → type-based}/src/services/user.service.ts +0 -0
- /package/templates/conditional/icons/huge/{component-based → type-based}/bootstrap/src/pages/Home/Home.jsx +0 -0
- /package/templates/conditional/icons/huge/{component-based → type-based}/bootstrap/src/pages/Home/Home.tsx +0 -0
- /package/templates/conditional/icons/huge/{component-based → type-based}/src/pages/Home/Home.jsx +0 -0
- /package/templates/conditional/icons/huge/{component-based → type-based}/src/pages/Home/Home.tsx +0 -0
- /package/templates/conditional/icons/huge/{component-based → type-based}/tailwind/src/pages/Home/Home.jsx +0 -0
- /package/templates/conditional/icons/huge/{component-based → type-based}/tailwind/src/pages/Home/Home.tsx +0 -0
- /package/templates/conditional/icons/lucide/{component-based → type-based}/bootstrap/src/pages/Home/Home.jsx +0 -0
- /package/templates/conditional/icons/lucide/{component-based → type-based}/bootstrap/src/pages/Home/Home.tsx +0 -0
- /package/templates/conditional/icons/lucide/{component-based → type-based}/src/pages/Home/Home.jsx +0 -0
- /package/templates/conditional/icons/lucide/{component-based → type-based}/src/pages/Home/Home.tsx +0 -0
- /package/templates/conditional/icons/lucide/{component-based → type-based}/tailwind/src/pages/Home/Home.jsx +0 -0
- /package/templates/conditional/icons/lucide/{component-based → type-based}/tailwind/src/pages/Home/Home.tsx +0 -0
- /package/templates/conditional/router/{component-based → type-based}/bootstrap/src/layouts/MainLayout.jsx +0 -0
- /package/templates/conditional/router/{component-based → type-based}/bootstrap/src/layouts/MainLayout.tsx +0 -0
- /package/templates/conditional/router/{component-based → type-based}/src/App.jsx +0 -0
- /package/templates/conditional/router/{component-based → type-based}/src/App.tsx +0 -0
- /package/templates/conditional/router/{component-based → type-based}/src/layouts/MainLayout.jsx +0 -0
- /package/templates/conditional/router/{component-based → type-based}/src/layouts/MainLayout.tsx +0 -0
- /package/templates/conditional/router/{component-based → type-based}/src/router/guards/AuthGuard.jsx +0 -0
- /package/templates/conditional/router/{component-based → type-based}/src/router/guards/AuthGuard.tsx +0 -0
- /package/templates/conditional/router/{component-based → type-based}/src/router/guards/GuestGuard.jsx +0 -0
- /package/templates/conditional/router/{component-based → type-based}/src/router/guards/GuestGuard.tsx +0 -0
- /package/templates/conditional/router/{component-based → type-based}/src/router/index.jsx +0 -0
- /package/templates/conditional/router/{component-based → type-based}/src/router/index.tsx +0 -0
- /package/templates/conditional/router/{component-based → type-based}/tailwind/src/layouts/MainLayout.jsx +0 -0
- /package/templates/conditional/router/{component-based → type-based}/tailwind/src/layouts/MainLayout.tsx +0 -0
- /package/templates/conditional/state/redux/{component-based → type-based}/src/pages/Home/counterSlice.jsx +0 -0
- /package/templates/conditional/state/redux/{component-based → type-based}/src/pages/Home/counterSlice.ts +0 -0
- /package/templates/conditional/state/redux/{component-based → type-based}/src/providers/StoreProvider.jsx +0 -0
- /package/templates/conditional/state/redux/{component-based → type-based}/src/providers/StoreProvider.tsx +0 -0
- /package/templates/conditional/state/redux/{component-based → type-based}/src/store/hooks.js +0 -0
- /package/templates/conditional/state/redux/{component-based → type-based}/src/store/hooks.ts +0 -0
- /package/templates/conditional/state/redux/{component-based → type-based}/src/store/index.js +0 -0
- /package/templates/conditional/state/redux/{component-based → type-based}/src/store/index.ts +0 -0
- /package/templates/conditional/state/zustand/{component-based → type-based}/src/store/useCounterStore.jsx +0 -0
- /package/templates/conditional/state/zustand/{component-based → type-based}/src/store/useCounterStore.ts +0 -0
- /package/templates/conditional/testing/jest/{component-based → type-based}/src/__tests__/App.test.jsx +0 -0
- /package/templates/conditional/testing/jest/{component-based → type-based}/src/__tests__/App.test.tsx +0 -0
- /package/templates/conditional/testing/vitest/{component-based → type-based}/src/__tests__/App.test.jsx +0 -0
- /package/templates/conditional/testing/vitest/{component-based → type-based}/src/__tests__/App.test.tsx +0 -0
- /package/templates/css/component-styles/bootstrap/{component-based → type-based}/src/components/common/Button.jsx +0 -0
- /package/templates/css/component-styles/bootstrap/{component-based → type-based}/src/components/common/Button.tsx +0 -0
- /package/templates/css/component-styles/bootstrap/{component-based → type-based}/src/layouts/MainLayout.jsx +0 -0
- /package/templates/css/component-styles/bootstrap/{component-based → type-based}/src/layouts/MainLayout.tsx +0 -0
- /package/templates/css/component-styles/bootstrap/{component-based → type-based}/src/pages/Home/Home.jsx +0 -0
- /package/templates/css/component-styles/bootstrap/{component-based → type-based}/src/pages/Home/Home.tsx +0 -0
- /package/templates/css/component-styles/tailwind/{component-based → type-based}/src/components/common/Button.jsx +0 -0
- /package/templates/css/component-styles/tailwind/{component-based → type-based}/src/components/common/Button.tsx +0 -0
- /package/templates/css/component-styles/tailwind/{component-based → type-based}/src/layouts/MainLayout.jsx +0 -0
- /package/templates/css/component-styles/tailwind/{component-based → type-based}/src/layouts/MainLayout.tsx +0 -0
- /package/templates/css/component-styles/tailwind/{component-based → type-based}/src/pages/Home/Home.jsx +0 -0
- /package/templates/css/component-styles/tailwind/{component-based → type-based}/src/pages/Home/Home.tsx +0 -0
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { fromZodError } from "zod-validation-error";
|
|
3
|
+
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// Constants - keep in sync with docs/manifest-v2.md and ROADMAP
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
export const MANIFEST_VERSION = 2;
|
|
8
|
+
export const SCHEMA_URL = "https://lumen-sh.github.io/create-lumen/schema/lumen.config.v2.json";
|
|
9
|
+
|
|
10
|
+
export const FRAMEWORK_NAMES = ["react", "next"];
|
|
11
|
+
export const FRAMEWORK_VARIANTS = ["vite", "app-router", "pages-router"];
|
|
12
|
+
export const FRAMEWORK_BUNDLERS = ["turbopack", "webpack"];
|
|
13
|
+
export const FRAMEWORK_ADAPTERS = ["node", "vercel", "cloudflare", "static"];
|
|
14
|
+
|
|
15
|
+
export const STYLING_ENGINES = ["tailwind", "bootstrap", "none"];
|
|
16
|
+
export const ARCHITECTURE_TYPES = ["feature-based", "type-based", "hybrid", "none"];
|
|
17
|
+
export const UI_KITS = ["shadcn", "none"];
|
|
18
|
+
export const DOCS_LANGUAGES = ["en", "es"];
|
|
19
|
+
export const TOOLING_LANGUAGES = ["ts", "js"];
|
|
20
|
+
export const TOOLING_LINTERS = ["eslint", "oxlint", "biome", "none"];
|
|
21
|
+
export const TOOLING_FORMATTERS = ["prettier", "oxfmt", "none"];
|
|
22
|
+
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// Sub-schemas
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
const frameworkSchema = z
|
|
27
|
+
.object({
|
|
28
|
+
name: z.enum(FRAMEWORK_NAMES),
|
|
29
|
+
variant: z.enum(FRAMEWORK_VARIANTS),
|
|
30
|
+
bundler: z.enum(FRAMEWORK_BUNDLERS).optional(),
|
|
31
|
+
adapter: z.enum(FRAMEWORK_ADAPTERS).optional(),
|
|
32
|
+
})
|
|
33
|
+
.strict();
|
|
34
|
+
|
|
35
|
+
const stylingSchema = z
|
|
36
|
+
.object({
|
|
37
|
+
engine: z.enum(STYLING_ENGINES),
|
|
38
|
+
})
|
|
39
|
+
.strict();
|
|
40
|
+
|
|
41
|
+
const architectureSchema = z
|
|
42
|
+
.object({
|
|
43
|
+
type: z.enum(ARCHITECTURE_TYPES),
|
|
44
|
+
})
|
|
45
|
+
.strict();
|
|
46
|
+
|
|
47
|
+
const uiSchema = z
|
|
48
|
+
.object({
|
|
49
|
+
kit: z.enum(UI_KITS),
|
|
50
|
+
})
|
|
51
|
+
.strict();
|
|
52
|
+
|
|
53
|
+
const docsSchema = z
|
|
54
|
+
.object({
|
|
55
|
+
language: z.enum(DOCS_LANGUAGES),
|
|
56
|
+
})
|
|
57
|
+
.strict();
|
|
58
|
+
|
|
59
|
+
const pathsSchema = z
|
|
60
|
+
.object({
|
|
61
|
+
features: z.string().min(1),
|
|
62
|
+
components: z.string().min(1),
|
|
63
|
+
services: z.string().min(1),
|
|
64
|
+
hooks: z.string().min(1),
|
|
65
|
+
pages: z.string().min(1),
|
|
66
|
+
ui: z.string().min(1),
|
|
67
|
+
})
|
|
68
|
+
.strict();
|
|
69
|
+
|
|
70
|
+
const toolingSchema = z
|
|
71
|
+
.object({
|
|
72
|
+
language: z.enum(TOOLING_LANGUAGES),
|
|
73
|
+
linter: z.enum(TOOLING_LINTERS),
|
|
74
|
+
formatter: z.enum(TOOLING_FORMATTERS),
|
|
75
|
+
})
|
|
76
|
+
.strict();
|
|
77
|
+
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
// Top-level manifest v2 - strict, no extra keys except $schema
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
export const manifestSchemaV2 = z
|
|
82
|
+
.object({
|
|
83
|
+
$schema: z.string().url().optional().default(SCHEMA_URL),
|
|
84
|
+
manifestVersion: z.literal(MANIFEST_VERSION),
|
|
85
|
+
framework: frameworkSchema,
|
|
86
|
+
styling: stylingSchema,
|
|
87
|
+
architecture: architectureSchema,
|
|
88
|
+
ui: uiSchema,
|
|
89
|
+
docs: docsSchema,
|
|
90
|
+
paths: pathsSchema,
|
|
91
|
+
tooling: toolingSchema,
|
|
92
|
+
reactCompiler: z.boolean().optional(),
|
|
93
|
+
agentDocs: z.boolean().optional(),
|
|
94
|
+
})
|
|
95
|
+
.strict()
|
|
96
|
+
.superRefine((val, ctx) => {
|
|
97
|
+
const { framework, architecture, styling, ui } = val;
|
|
98
|
+
|
|
99
|
+
// framework.variant must match framework.name
|
|
100
|
+
if (framework.name === "react" && framework.variant !== "vite") {
|
|
101
|
+
ctx.addIssue({
|
|
102
|
+
code: "custom",
|
|
103
|
+
path: ["framework", "variant"],
|
|
104
|
+
message: `framework.variant must be "vite" when framework.name is "react" (got "${framework.variant}")`,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
if (framework.name === "next" && framework.variant === "vite") {
|
|
108
|
+
ctx.addIssue({
|
|
109
|
+
code: "custom",
|
|
110
|
+
path: ["framework", "variant"],
|
|
111
|
+
message: `framework.variant must be "app-router" or "pages-router" when framework.name is "next" (got "vite")`,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// bundler only for Next.js
|
|
116
|
+
if (framework.bundler !== undefined && framework.name !== "next") {
|
|
117
|
+
ctx.addIssue({
|
|
118
|
+
code: "custom",
|
|
119
|
+
path: ["framework", "bundler"],
|
|
120
|
+
message: `framework.bundler is only valid when framework.name is "next"`,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// adapter only for Next.js (behavior in #22)
|
|
125
|
+
if (framework.adapter !== undefined && framework.name !== "next") {
|
|
126
|
+
ctx.addIssue({
|
|
127
|
+
code: "custom",
|
|
128
|
+
path: ["framework", "adapter"],
|
|
129
|
+
message: `framework.adapter is only valid when framework.name is "next"`,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// architecture scoping per framework (#34)
|
|
134
|
+
const allowedByFramework =
|
|
135
|
+
framework.name === "react"
|
|
136
|
+
? ["feature-based", "type-based", "none"]
|
|
137
|
+
: ["feature-based", "hybrid", "none"];
|
|
138
|
+
if (!allowedByFramework.includes(architecture.type)) {
|
|
139
|
+
ctx.addIssue({
|
|
140
|
+
code: "custom",
|
|
141
|
+
path: ["architecture", "type"],
|
|
142
|
+
message: `architecture.type "${architecture.type}" is not valid for framework "${framework.name}" (allowed: ${allowedByFramework.join(", ")})`,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// shadcn requires tailwind (#33)
|
|
147
|
+
if (ui.kit === "shadcn" && styling.engine !== "tailwind") {
|
|
148
|
+
ctx.addIssue({
|
|
149
|
+
code: "custom",
|
|
150
|
+
path: ["ui", "kit"],
|
|
151
|
+
message: `ui.kit "shadcn" requires styling.engine "tailwind" (got "${styling.engine}")`,
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
// ---------------------------------------------------------------------------
|
|
157
|
+
// v1 detection - flat shape from create-lumen 1.x
|
|
158
|
+
// ---------------------------------------------------------------------------
|
|
159
|
+
const V1_FLAT_KEYS = ["css", "cssFramework", "architecture", "language", "router", "stateManagement", "iconLibrary", "apiClient", "testing"];
|
|
160
|
+
|
|
161
|
+
export function isV1Manifest(raw) {
|
|
162
|
+
if (!raw || typeof raw !== "object") return false;
|
|
163
|
+
// v1 had framework as string or missing manifestVersion
|
|
164
|
+
if (raw.manifestVersion === 1) return true;
|
|
165
|
+
if (typeof raw.framework === "string") return true;
|
|
166
|
+
if (raw.framework === undefined && V1_FLAT_KEYS.some((k) => k in raw)) return true;
|
|
167
|
+
// flat config without nested framework object but with css/architecture as string
|
|
168
|
+
if (typeof raw.architecture === "string" && typeof raw.framework !== "object") return true;
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export function formatZodError(error) {
|
|
173
|
+
try {
|
|
174
|
+
const ve = fromZodError(error, {
|
|
175
|
+
prefix: "Manifest validation failed",
|
|
176
|
+
prefixSeparator: ": ",
|
|
177
|
+
issueSeparator: "; ",
|
|
178
|
+
});
|
|
179
|
+
return ve.message;
|
|
180
|
+
} catch {
|
|
181
|
+
return error.message;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Parse and validate a manifest v2 object.
|
|
187
|
+
* - Throws with migration-oriented message for v1 manifests (#14 AC)
|
|
188
|
+
* - Throws with user-friendly field path + expected shape for malformed v2
|
|
189
|
+
* @param {unknown} raw
|
|
190
|
+
* @returns {import("zod").infer<typeof manifestSchemaV2>}
|
|
191
|
+
*/
|
|
192
|
+
export function parseManifest(raw) {
|
|
193
|
+
if (isV1Manifest(raw)) {
|
|
194
|
+
throw new Error(
|
|
195
|
+
`Manifest v1 detected (flat config). create-lumen v2 uses a nested manifest (manifestVersion: 2).\n` +
|
|
196
|
+
`Please migrate: delete the old config and re-run create-lumen, or see the migration guide (docs/migration/v1-to-v2.md).\n` +
|
|
197
|
+
`Raw keys: ${Object.keys(raw || {}).join(", ")}`
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const result = manifestSchemaV2.safeParse(raw);
|
|
202
|
+
if (!result.success) {
|
|
203
|
+
const msg = formatZodError(result.error);
|
|
204
|
+
const err = new Error(msg);
|
|
205
|
+
err.cause = result.error;
|
|
206
|
+
throw err;
|
|
207
|
+
}
|
|
208
|
+
return result.data;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Re-export type helper for JSDoc (z.infer)
|
|
212
|
+
// /** @typedef {z.infer<typeof manifestSchemaV2>} ManifestV2 */
|
package/src/prompts.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { confirm, isCancel, note, select } from "@clack/prompts";
|
|
2
2
|
import chalk from "chalk";
|
|
3
3
|
import { configExists, loadConfig, saveConfig } from "@/config-cache.js";
|
|
4
4
|
|
|
@@ -12,7 +12,9 @@ function formatConfig(responses) {
|
|
|
12
12
|
const arch =
|
|
13
13
|
responses.architecture === "feature-based"
|
|
14
14
|
? "Feature-based"
|
|
15
|
-
: "
|
|
15
|
+
: responses.architecture === "type-based" || responses.architecture === "component-based"
|
|
16
|
+
? "Type-based"
|
|
17
|
+
: responses.architecture;
|
|
16
18
|
const css =
|
|
17
19
|
responses.cssFramework === "none"
|
|
18
20
|
? "None"
|
|
@@ -32,6 +34,7 @@ function formatConfig(responses) {
|
|
|
32
34
|
? "Redux Toolkit"
|
|
33
35
|
: "Zustand";
|
|
34
36
|
|
|
37
|
+
const docsLang = responses.docsLanguage === "es" ? "ES" : responses.docsLanguage === "en" ? "EN" : "—";
|
|
35
38
|
return [
|
|
36
39
|
`• ${chalk.bold("Architecture:")} ${chalk.green(arch)}`,
|
|
37
40
|
`• ${chalk.bold("Language:")} ${chalk.green(lang)}`,
|
|
@@ -43,14 +46,15 @@ function formatConfig(responses) {
|
|
|
43
46
|
`• ${chalk.bold("API Client:")} ${responses.apiClient === "axios" ? chalk.green("Axios") : responses.apiClient === "fetch" ? chalk.yellow("Fetch") : chalk.red("None")}`,
|
|
44
47
|
`• ${chalk.bold("Linter:")} ${responses.linter === "oxlint" ? chalk.green("Oxlint") : responses.linter === "eslint" ? chalk.yellow("ESLint") : chalk.red("None")}`,
|
|
45
48
|
`• ${chalk.bold("Formatter:")} ${responses.formatter === "oxfmt" ? chalk.green("Oxfmt") : responses.formatter === "prettier" ? chalk.yellow("Prettier") : chalk.red("None")}`,
|
|
49
|
+
`• ${chalk.bold("Docs:")} ${chalk.cyan(docsLang)}`,
|
|
46
50
|
`• ${chalk.bold("Git:")} ${responses.gitInit ? chalk.green("Yes") : chalk.red("No")}`,
|
|
47
51
|
`• ${chalk.bold("README:")} ${responses.readme ? chalk.green("Yes") : chalk.red("No")}`,
|
|
48
52
|
].join("\n");
|
|
49
53
|
}
|
|
50
54
|
|
|
51
55
|
export async function getUserInputs(projectName, { quickSetup = false } = {}) {
|
|
52
|
-
let oldConfig
|
|
53
|
-
let useOldConfig
|
|
56
|
+
let oldConfig;
|
|
57
|
+
let useOldConfig;
|
|
54
58
|
|
|
55
59
|
// Non-interactive quick setup: apply defaults without prompting.
|
|
56
60
|
if (quickSetup) {
|
|
@@ -66,6 +70,7 @@ export async function getUserInputs(projectName, { quickSetup = false } = {}) {
|
|
|
66
70
|
apiClient: "none",
|
|
67
71
|
linter: "eslint",
|
|
68
72
|
formatter: "prettier",
|
|
73
|
+
docsLanguage: "en",
|
|
69
74
|
gitInit: true,
|
|
70
75
|
readme: true,
|
|
71
76
|
};
|
|
@@ -101,6 +106,9 @@ export async function getUserInputs(projectName, { quickSetup = false } = {}) {
|
|
|
101
106
|
if (oldConfig.formatter === undefined) {
|
|
102
107
|
oldConfig.formatter = "none";
|
|
103
108
|
}
|
|
109
|
+
if (oldConfig.docsLanguage === undefined) {
|
|
110
|
+
oldConfig.docsLanguage = "en";
|
|
111
|
+
}
|
|
104
112
|
return { ...oldConfig, projectName };
|
|
105
113
|
}
|
|
106
114
|
}
|
|
@@ -126,6 +134,7 @@ export async function getUserInputs(projectName, { quickSetup = false } = {}) {
|
|
|
126
134
|
apiClient: "none",
|
|
127
135
|
linter: "eslint",
|
|
128
136
|
formatter: "prettier",
|
|
137
|
+
docsLanguage: "en",
|
|
129
138
|
gitInit: true,
|
|
130
139
|
readme: true,
|
|
131
140
|
};
|
|
@@ -143,8 +152,8 @@ export async function getUserInputs(projectName, { quickSetup = false } = {}) {
|
|
|
143
152
|
hint: "Scales to large apps — code grouped by business domain",
|
|
144
153
|
},
|
|
145
154
|
{
|
|
146
|
-
label: "
|
|
147
|
-
value: "
|
|
155
|
+
label: "Type-based",
|
|
156
|
+
value: "type-based",
|
|
148
157
|
hint: "Small apps / component libraries — code grouped by UI type",
|
|
149
158
|
},
|
|
150
159
|
],
|
|
@@ -261,6 +270,16 @@ export async function getUserInputs(projectName, { quickSetup = false } = {}) {
|
|
|
261
270
|
if (isCancel(formatter)) onCancel();
|
|
262
271
|
}
|
|
263
272
|
|
|
273
|
+
const docsLanguage = await select({
|
|
274
|
+
message: "Which docs language do you want?",
|
|
275
|
+
options: [
|
|
276
|
+
{ label: "English", value: "en" },
|
|
277
|
+
{ label: "Español", value: "es" },
|
|
278
|
+
],
|
|
279
|
+
initialValue: "en",
|
|
280
|
+
});
|
|
281
|
+
if (isCancel(docsLanguage)) onCancel();
|
|
282
|
+
|
|
264
283
|
const readme = await confirm({
|
|
265
284
|
message: "Would you like to generate a README.md and LICENSE?",
|
|
266
285
|
initialValue: true,
|
|
@@ -279,6 +298,7 @@ export async function getUserInputs(projectName, { quickSetup = false } = {}) {
|
|
|
279
298
|
apiClient,
|
|
280
299
|
linter,
|
|
281
300
|
formatter,
|
|
301
|
+
docsLanguage,
|
|
282
302
|
gitInit,
|
|
283
303
|
readme,
|
|
284
304
|
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { dirname } from "path";
|
|
2
|
+
import { fileURLToPath } from "url";
|
|
3
|
+
import { FlatCompat } from "@eslint/eslintrc";
|
|
4
|
+
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = dirname(__filename);
|
|
7
|
+
|
|
8
|
+
const compat = new FlatCompat({
|
|
9
|
+
baseDirectory: __dirname,
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
const eslintConfig = [
|
|
13
|
+
...compat.extends("next/core-web-vitals"),
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
export default eslintConfig;
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/templates/architectures/{component-based → type-based}/src/components/common/Button.jsx
RENAMED
|
File without changes
|
/package/templates/architectures/{component-based → type-based}/src/components/common/Button.tsx
RENAMED
|
File without changes
|
/package/templates/architectures/{component-based → type-based}/src/components/common/index.js
RENAMED
|
File without changes
|
/package/templates/architectures/{component-based → type-based}/src/components/common/index.ts
RENAMED
|
File without changes
|
/package/templates/architectures/{component-based → type-based}/src/components/form/.gitkeep
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/templates/architectures/{component-based → type-based}/src/hooks/useLocalStorage.jsx
RENAMED
|
File without changes
|
/package/templates/architectures/{component-based → type-based}/src/hooks/useLocalStorage.ts
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/templates/architectures/{component-based → type-based}/src/providers/AppProvider.jsx
RENAMED
|
File without changes
|
/package/templates/architectures/{component-based → type-based}/src/providers/AppProvider.tsx
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/templates/conditional/axios/{component-based → type-based}/src/config/axios.config.js
RENAMED
|
File without changes
|
/package/templates/conditional/axios/{component-based → type-based}/src/config/axios.config.ts
RENAMED
|
File without changes
|
/package/templates/conditional/axios/{component-based → type-based}/src/services/axios.client.js
RENAMED
|
File without changes
|
/package/templates/conditional/axios/{component-based → type-based}/src/services/axios.client.ts
RENAMED
|
File without changes
|
/package/templates/conditional/axios/{component-based → type-based}/src/services/user.service.js
RENAMED
|
File without changes
|
/package/templates/conditional/axios/{component-based → type-based}/src/services/user.service.ts
RENAMED
|
File without changes
|
/package/templates/conditional/fetch/{component-based → type-based}/src/config/api.config.js
RENAMED
|
File without changes
|
/package/templates/conditional/fetch/{component-based → type-based}/src/config/api.config.ts
RENAMED
|
File without changes
|
/package/templates/conditional/fetch/{component-based → type-based}/src/services/api.client.js
RENAMED
|
File without changes
|
/package/templates/conditional/fetch/{component-based → type-based}/src/services/api.client.ts
RENAMED
|
File without changes
|
/package/templates/conditional/fetch/{component-based → type-based}/src/services/user.service.js
RENAMED
|
File without changes
|
/package/templates/conditional/fetch/{component-based → type-based}/src/services/user.service.ts
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/templates/conditional/icons/huge/{component-based → type-based}/src/pages/Home/Home.jsx
RENAMED
|
File without changes
|
/package/templates/conditional/icons/huge/{component-based → type-based}/src/pages/Home/Home.tsx
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/templates/conditional/icons/lucide/{component-based → type-based}/src/pages/Home/Home.jsx
RENAMED
|
File without changes
|
/package/templates/conditional/icons/lucide/{component-based → type-based}/src/pages/Home/Home.tsx
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/templates/conditional/router/{component-based → type-based}/src/layouts/MainLayout.jsx
RENAMED
|
File without changes
|
/package/templates/conditional/router/{component-based → type-based}/src/layouts/MainLayout.tsx
RENAMED
|
File without changes
|
/package/templates/conditional/router/{component-based → type-based}/src/router/guards/AuthGuard.jsx
RENAMED
|
File without changes
|
/package/templates/conditional/router/{component-based → type-based}/src/router/guards/AuthGuard.tsx
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/templates/conditional/state/redux/{component-based → type-based}/src/store/hooks.js
RENAMED
|
File without changes
|
/package/templates/conditional/state/redux/{component-based → type-based}/src/store/hooks.ts
RENAMED
|
File without changes
|
/package/templates/conditional/state/redux/{component-based → type-based}/src/store/index.js
RENAMED
|
File without changes
|
/package/templates/conditional/state/redux/{component-based → type-based}/src/store/index.ts
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|