create-next-mui 0.1.3 → 0.1.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.
Files changed (113) hide show
  1. package/README.md +8 -0
  2. package/next-mui-features/react-query/js/.vscode/settings.json +7 -0
  3. package/next-mui-features/react-query/js/.vscode/typescript.code-snippets +10 -0
  4. package/next-mui-features/react-query/js/eslint.config.mjs +90 -0
  5. package/next-mui-features/react-query/js/jsconfig.json +11 -0
  6. package/next-mui-features/react-query/js/next.config.js +5 -0
  7. package/next-mui-features/react-query/js/package-lock.json +6779 -0
  8. package/next-mui-features/react-query/js/package.json +34 -0
  9. package/next-mui-features/react-query/js/public/mui.svg +11 -0
  10. package/next-mui-features/react-query/js/public/next.svg +23 -0
  11. package/next-mui-features/react-query/js/public/vercel.svg +1 -0
  12. package/next-mui-features/react-query/js/src/app/favicon.ico +0 -0
  13. package/next-mui-features/react-query/js/src/app/globals.css +28 -0
  14. package/next-mui-features/react-query/js/src/app/layout.jsx +40 -0
  15. package/next-mui-features/react-query/js/src/app/page.jsx +7 -0
  16. package/next-mui-features/react-query/js/src/app/profile/page.jsx +7 -0
  17. package/next-mui-features/react-query/js/src/config-global.js +6 -0
  18. package/next-mui-features/react-query/js/src/lib/router-link/index.js +5 -0
  19. package/next-mui-features/react-query/js/src/lib/tanstack-provider.jsx +29 -0
  20. package/next-mui-features/react-query/js/src/sections/home/profile-view.jsx +43 -0
  21. package/next-mui-features/react-query/js/src/sections/home/view.jsx +160 -0
  22. package/next-mui-features/react-query/js/src/theme/core/colors.json +46 -0
  23. package/next-mui-features/react-query/js/src/theme/core/components/button.js +31 -0
  24. package/next-mui-features/react-query/js/src/theme/core/components/card.js +13 -0
  25. package/next-mui-features/react-query/js/src/theme/core/components/index.js +9 -0
  26. package/next-mui-features/react-query/js/src/theme/core/palette.js +23 -0
  27. package/next-mui-features/react-query/js/src/theme/core/typography.js +51 -0
  28. package/next-mui-features/react-query/js/src/theme/create-theme.js +28 -0
  29. package/next-mui-features/react-query/js/src/theme/theme-provider.jsx +19 -0
  30. package/next-mui-features/react-query/manifest.json +18 -0
  31. package/next-mui-features/react-query/ts/.vscode/settings.json +7 -0
  32. package/next-mui-features/react-query/ts/.vscode/typescript.code-snippets +10 -0
  33. package/next-mui-features/react-query/ts/eslint.config.mjs +90 -0
  34. package/next-mui-features/react-query/ts/next.config.ts +7 -0
  35. package/next-mui-features/react-query/ts/package-lock.json +6779 -0
  36. package/next-mui-features/react-query/ts/package.json +34 -0
  37. package/next-mui-features/react-query/ts/public/mui.svg +11 -0
  38. package/next-mui-features/react-query/ts/public/next.svg +23 -0
  39. package/next-mui-features/react-query/ts/public/vercel.svg +1 -0
  40. package/next-mui-features/react-query/ts/src/app/favicon.ico +0 -0
  41. package/next-mui-features/react-query/ts/src/app/globals.css +28 -0
  42. package/next-mui-features/react-query/ts/src/app/layout.tsx +46 -0
  43. package/next-mui-features/react-query/ts/src/app/page.tsx +7 -0
  44. package/next-mui-features/react-query/ts/src/app/profile/page.tsx +7 -0
  45. package/next-mui-features/react-query/ts/src/config-global.ts +7 -0
  46. package/next-mui-features/react-query/ts/src/lib/router-link/index.ts +5 -0
  47. package/next-mui-features/react-query/ts/src/lib/tanstack-provider.tsx +29 -0
  48. package/next-mui-features/react-query/ts/src/sections/home/profile-view.tsx +43 -0
  49. package/next-mui-features/react-query/ts/src/sections/home/view.tsx +160 -0
  50. package/next-mui-features/react-query/ts/src/theme/core/colors.json +46 -0
  51. package/next-mui-features/react-query/ts/src/theme/core/components/button.ts +43 -0
  52. package/next-mui-features/react-query/ts/src/theme/core/components/card.ts +17 -0
  53. package/next-mui-features/react-query/ts/src/theme/core/components/index.ts +9 -0
  54. package/next-mui-features/react-query/ts/src/theme/core/palette.ts +34 -0
  55. package/next-mui-features/react-query/ts/src/theme/core/typography.ts +51 -0
  56. package/next-mui-features/react-query/ts/src/theme/create-theme.ts +28 -0
  57. package/next-mui-features/react-query/ts/src/theme/theme-provider.tsx +19 -0
  58. package/next-mui-features/react-query/ts/tsconfig.json +34 -0
  59. package/next-mui-features/zustand/js/.vscode/settings.json +7 -0
  60. package/next-mui-features/zustand/js/.vscode/typescript.code-snippets +10 -0
  61. package/next-mui-features/zustand/js/eslint.config.mjs +90 -0
  62. package/next-mui-features/zustand/js/jsconfig.json +11 -0
  63. package/next-mui-features/zustand/js/next.config.js +5 -0
  64. package/next-mui-features/zustand/js/package-lock.json +6753 -0
  65. package/next-mui-features/zustand/js/package.json +33 -0
  66. package/next-mui-features/zustand/js/public/mui.svg +11 -0
  67. package/next-mui-features/zustand/js/public/next.svg +23 -0
  68. package/next-mui-features/zustand/js/public/vercel.svg +1 -0
  69. package/next-mui-features/zustand/js/src/app/favicon.ico +0 -0
  70. package/next-mui-features/zustand/js/src/app/globals.css +28 -0
  71. package/next-mui-features/zustand/js/src/app/layout.jsx +36 -0
  72. package/next-mui-features/zustand/js/src/app/page.jsx +7 -0
  73. package/next-mui-features/zustand/js/src/config-global.js +6 -0
  74. package/next-mui-features/zustand/js/src/lib/router-link/index.js +5 -0
  75. package/next-mui-features/zustand/js/src/sections/home/view.jsx +218 -0
  76. package/next-mui-features/zustand/js/src/stores/counter-store.jsx +10 -0
  77. package/next-mui-features/zustand/js/src/theme/core/colors.json +46 -0
  78. package/next-mui-features/zustand/js/src/theme/core/components/button.js +31 -0
  79. package/next-mui-features/zustand/js/src/theme/core/components/card.js +13 -0
  80. package/next-mui-features/zustand/js/src/theme/core/components/index.js +9 -0
  81. package/next-mui-features/zustand/js/src/theme/core/palette.js +23 -0
  82. package/next-mui-features/zustand/js/src/theme/core/typography.js +51 -0
  83. package/next-mui-features/zustand/js/src/theme/create-theme.js +28 -0
  84. package/next-mui-features/zustand/js/src/theme/theme-provider.jsx +19 -0
  85. package/next-mui-features/zustand/manifest.json +12 -0
  86. package/next-mui-features/zustand/ts/.vscode/settings.json +7 -0
  87. package/next-mui-features/zustand/ts/.vscode/typescript.code-snippets +10 -0
  88. package/next-mui-features/zustand/ts/eslint.config.mjs +90 -0
  89. package/next-mui-features/zustand/ts/next.config.ts +7 -0
  90. package/next-mui-features/zustand/ts/package-lock.json +6753 -0
  91. package/next-mui-features/zustand/ts/package.json +33 -0
  92. package/next-mui-features/zustand/ts/public/mui.svg +11 -0
  93. package/next-mui-features/zustand/ts/public/next.svg +23 -0
  94. package/next-mui-features/zustand/ts/public/vercel.svg +1 -0
  95. package/next-mui-features/zustand/ts/src/app/favicon.ico +0 -0
  96. package/next-mui-features/zustand/ts/src/app/globals.css +28 -0
  97. package/next-mui-features/zustand/ts/src/app/layout.tsx +42 -0
  98. package/next-mui-features/zustand/ts/src/app/page.tsx +7 -0
  99. package/next-mui-features/zustand/ts/src/config-global.ts +7 -0
  100. package/next-mui-features/zustand/ts/src/lib/router-link/index.ts +5 -0
  101. package/next-mui-features/zustand/ts/src/sections/home/view.tsx +218 -0
  102. package/next-mui-features/zustand/ts/src/stores/counter-store.tsx +17 -0
  103. package/next-mui-features/zustand/ts/src/theme/core/colors.json +46 -0
  104. package/next-mui-features/zustand/ts/src/theme/core/components/button.ts +43 -0
  105. package/next-mui-features/zustand/ts/src/theme/core/components/card.ts +17 -0
  106. package/next-mui-features/zustand/ts/src/theme/core/components/index.ts +9 -0
  107. package/next-mui-features/zustand/ts/src/theme/core/palette.ts +34 -0
  108. package/next-mui-features/zustand/ts/src/theme/core/typography.ts +51 -0
  109. package/next-mui-features/zustand/ts/src/theme/create-theme.ts +28 -0
  110. package/next-mui-features/zustand/ts/src/theme/theme-provider.tsx +19 -0
  111. package/next-mui-features/zustand/ts/tsconfig.json +34 -0
  112. package/package.json +3 -2
  113. package/src/index.js +178 -61
@@ -0,0 +1,34 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2017",
4
+ "lib": ["dom", "dom.iterable", "esnext"],
5
+ "allowJs": true,
6
+ "skipLibCheck": true,
7
+ "strict": true,
8
+ "noEmit": true,
9
+ "esModuleInterop": true,
10
+ "module": "esnext",
11
+ "moduleResolution": "bundler",
12
+ "resolveJsonModule": true,
13
+ "isolatedModules": true,
14
+ "jsx": "react-jsx",
15
+ "incremental": true,
16
+ "plugins": [
17
+ {
18
+ "name": "next"
19
+ }
20
+ ],
21
+ "paths": {
22
+ "@/*": ["./src/*"]
23
+ }
24
+ },
25
+ "include": [
26
+ "next-env.d.ts",
27
+ "**/*.ts",
28
+ "**/*.tsx",
29
+ ".next/types/**/*.ts",
30
+ ".next/dev/types/**/*.ts",
31
+ "**/*.mts"
32
+ ],
33
+ "exclude": ["node_modules"]
34
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-next-mui",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "spin up your nextjs project with mui setup",
5
5
  "keywords": [
6
6
  "nextjs",
@@ -23,7 +23,8 @@
23
23
  },
24
24
  "files": [
25
25
  "src",
26
- "next-mui-templates"
26
+ "next-mui-templates",
27
+ "next-mui-features"
27
28
  ],
28
29
  "main": "index.js",
29
30
  "scripts": {
package/src/index.js CHANGED
@@ -12,6 +12,8 @@ const __filename = fileURLToPath(import.meta.url);
12
12
  const __dirname = path.dirname(__filename);
13
13
 
14
14
  const args = process.argv.slice(2);
15
+ const command = args[0];
16
+ const featureName = args[1];
15
17
 
16
18
  const positionalArgs = args.filter(
17
19
  (arg) => !["--yes", "-y", "--js"].includes(arg),
@@ -53,6 +55,8 @@ const FEATURES = [
53
55
  },
54
56
  ];
55
57
 
58
+ // ----------------------------------------------------------------------
59
+ // Helper Functions
56
60
  // ----------------------------------------------------------------------
57
61
 
58
62
  function validateProjectName(value) {
@@ -71,31 +75,126 @@ function getPackageName(projectName, targetProjectDir) {
71
75
  }
72
76
 
73
77
  async function updateProjectName(targetProjectDir, packageName) {
74
- const files = ["package.json", "package-lock.json"];
78
+ const filePath = path.join(targetProjectDir, "package.json");
79
+ try {
80
+ const content = await fs.readFile(filePath, "utf8");
81
+ const json = JSON.parse(content);
82
+ json.name = packageName;
75
83
 
76
- await Promise.all(
77
- files.map(async (file) => {
78
- const filePath = path.join(targetProjectDir, file);
84
+ if (json.packages?.[""]?.name) {
85
+ json.packages[""].name = packageName;
86
+ }
87
+ await fs.writeFile(filePath, `${JSON.stringify(json, null, 2)}\n`);
88
+ } catch (error) {
89
+ if (error.code === "ENOENT") return;
90
+ throw error;
91
+ }
92
+ }
79
93
 
80
- try {
81
- const content = await fs.readFile(filePath, "utf8");
82
- const json = JSON.parse(content);
94
+ async function mergePackageJson(targetProjectDir, manifest) {
95
+ const filePath = path.join(targetProjectDir, "package.json");
96
+ try {
97
+ const content = await fs.readFile(filePath, "utf8");
98
+ const json = JSON.parse(content);
99
+
100
+ json.dependencies = {
101
+ ...json.dependencies,
102
+ ...(manifest.dependencies || {}),
103
+ };
83
104
 
84
- json.name = packageName;
105
+ json.devDependencies = {
106
+ ...json.devDependencies,
107
+ ...(manifest.devDependencies || {}),
108
+ };
85
109
 
86
- if (json.packages?.[""]?.name) {
87
- json.packages[""].name = packageName;
88
- }
110
+ await fs.writeFile(filePath, `${JSON.stringify(json, null, 2)}\n`);
111
+ } catch (error) {
112
+ if (error.code === "ENOENT") return;
113
+ throw error;
114
+ }
115
+ }
89
116
 
90
- await fs.writeFile(filePath, `${JSON.stringify(json, null, 2)}\n`);
91
- } catch (error) {
92
- if (error.code === "ENOENT") return;
93
- throw error;
117
+ async function injectProviderToLayout(targetProjectDir, manifest, language) {
118
+ const ext = language === "ts" ? "tsx" : "jsx";
119
+ const layoutPath = path.join(targetProjectDir, "src", "app", `layout.${ext}`);
120
+
121
+ try {
122
+ let content = await fs.readFile(layoutPath, "utf8");
123
+
124
+ // 1. Inject the Import Line safely below the last import
125
+ if (manifest.importLine && !content.includes(manifest.importLine)) {
126
+ const lines = content.split("\n");
127
+ const lastImportIndex = lines.findLastIndex((line) =>
128
+ line.trim().startsWith("import"),
129
+ );
130
+
131
+ if (lastImportIndex !== -1) {
132
+ lines.splice(lastImportIndex + 1, 0, manifest.importLine);
133
+ content = lines.join("\n");
134
+ } else {
135
+ content = `${manifest.importLine}\n${content}`;
136
+ }
137
+ }
138
+
139
+ // 2. Wrap {children} dynamically
140
+ if (manifest.expression) {
141
+ const openTag = manifest.expression.open;
142
+ const closeTag = manifest.expression.close;
143
+
144
+ if (!content.includes(openTag)) {
145
+ content = content.replace(
146
+ /(\>\s*)\{\s*children\s*\}(\s*\<)/,
147
+ `$1${openTag} {children} ${closeTag}$2`,
148
+ );
94
149
  }
95
- }),
150
+ }
151
+
152
+ await fs.writeFile(layoutPath, content, "utf8");
153
+ } catch (error) {
154
+ if (error.code === "ENOENT") return;
155
+ throw error;
156
+ }
157
+ }
158
+
159
+ async function applyFeature(feature, targetProjectDir, language) {
160
+ const featureDir = path.resolve(
161
+ __dirname,
162
+ "..",
163
+ "next-mui-features",
164
+ feature,
96
165
  );
166
+ const manifestPath = path.join(featureDir, "manifest.json");
167
+ const ext = language == "ts" ? "tsx" : "jsx";
168
+
169
+ let manifest = {};
170
+ try {
171
+ const manifestContent = await fs.readFile(manifestPath, "utf8");
172
+ manifest = JSON.parse(manifestContent);
173
+ } catch {
174
+ // Fail-safe if manifest is missing or malformed
175
+ return;
176
+ }
177
+
178
+ // 1. Copy feature-specific files from the language subdirectory
179
+ if (manifest.files) {
180
+ for (const file of manifest.files) {
181
+ const srcPath = path.resolve(featureDir, language, `${file.src}.${ext}`);
182
+ const destPath = path.resolve(targetProjectDir, `${file.dest}.${ext}`);
183
+
184
+ await fs.mkdir(path.dirname(destPath), { recursive: true });
185
+ await fs.copyFile(srcPath, destPath);
186
+ }
187
+ }
188
+
189
+ // 2. Merge dependencies into package.json
190
+ await mergePackageJson(targetProjectDir, manifest);
191
+
192
+ // 3. Perform dynamic layout file nesting
193
+ await injectProviderToLayout(targetProjectDir, manifest, language);
97
194
  }
98
195
 
196
+ // ----------------------------------------------------------------------
197
+ // Main Execution Control Loop
99
198
  // ----------------------------------------------------------------------
100
199
 
101
200
  async function main() {
@@ -103,6 +202,65 @@ async function main() {
103
202
 
104
203
  p.intro(color.bgBlue(color.white(" create-next-mui ")));
105
204
 
205
+ // ----------------------------------------------------------------------
206
+ // Add Feature Command Pipeline
207
+ // ----------------------------------------------------------------------
208
+
209
+ if (command === "add") {
210
+ if (!featureName) {
211
+ p.cancel(
212
+ "Please specify a feature.\n\nExample:\ncreate-next-mui add react-query",
213
+ );
214
+ process.exit(1);
215
+ }
216
+
217
+ if (!FEATURES.some((f) => f.value === featureName)) {
218
+ p.cancel(`Unknown feature "${featureName}".`);
219
+ process.exit(1);
220
+ }
221
+
222
+ const projectRoot = process.cwd();
223
+
224
+ // Verify package.json exists in target execution environment
225
+ try {
226
+ await fs.access(path.join(projectRoot, "package.json"));
227
+ } catch {
228
+ p.cancel(
229
+ "No package.json found.\nRun this command inside a Next.js project.",
230
+ );
231
+ process.exit(1);
232
+ }
233
+
234
+ // Auto-detect layout flavor via tsconfig existence
235
+ let language = "js";
236
+ try {
237
+ await fs.access(path.join(projectRoot, "tsconfig.json"));
238
+ language = "ts";
239
+ } catch {
240
+ // Keep fallback as js configuration
241
+ }
242
+
243
+ const spinner = p.spinner();
244
+ spinner.start(`Installing ${featureName}...`);
245
+
246
+ try {
247
+ await applyFeature(featureName, projectRoot, language);
248
+
249
+ spinner.stop(color.green(`${featureName} installed successfully.`));
250
+ p.note(`${color.cyan("npm install")}`, "Next Step");
251
+ p.outro(`✨ ${featureName} added successfully!`);
252
+ return;
253
+ } catch (error) {
254
+ spinner.stop(color.red("Failed to install feature."));
255
+ p.note(error.message, "Error");
256
+ process.exit(1);
257
+ }
258
+ }
259
+
260
+ // ----------------------------------------------------------------------
261
+ // Interactive Fresh Workspace Scaffolding Pipeline
262
+ // ----------------------------------------------------------------------
263
+
106
264
  const projectNameError = hasInitialProjectName
107
265
  ? validateProjectName(PROJECT_NAME)
108
266
  : undefined;
@@ -148,10 +306,6 @@ async function main() {
148
306
  },
149
307
  );
150
308
 
151
- // --------------------------------------------------------------------
152
- // Paths
153
- // --------------------------------------------------------------------
154
-
155
309
  const baseTemplateDir = path.resolve(
156
310
  __dirname,
157
311
  "..",
@@ -160,24 +314,17 @@ async function main() {
160
314
  );
161
315
 
162
316
  const targetProjectDir = path.resolve(process.cwd(), project.name);
163
-
164
317
  const packageName = getPackageName(project.name, targetProjectDir);
165
318
 
166
- // --------------------------------------------------------------------
167
- // Current directory validation
168
- // --------------------------------------------------------------------
169
-
170
319
  if (project.name === ".") {
171
320
  try {
172
321
  const files = await fs.readdir(targetProjectDir);
173
-
174
322
  if (files.length > 0) {
175
323
  p.log.error(
176
324
  color.red(
177
325
  "The current directory is not empty! Please clear it or specify another project name.",
178
326
  ),
179
327
  );
180
-
181
328
  process.exit(1);
182
329
  }
183
330
  } catch {
@@ -185,64 +332,34 @@ async function main() {
185
332
  }
186
333
  }
187
334
 
188
- // --------------------------------------------------------------------
189
-
190
335
  const s = p.spinner();
191
-
192
336
  s.start("Scaffolding your Next.js + MUI workspace...");
193
337
 
194
338
  try {
195
- // ------------------------------------------------------------------
196
- // Copy base template
197
- // ------------------------------------------------------------------
198
-
339
+ // 1. Unpack base layout system
199
340
  await fs.cp(baseTemplateDir, targetProjectDir, {
200
341
  recursive: true,
201
342
  filter: (src) => {
202
343
  const name = path.basename(src);
203
-
204
344
  return !["node_modules", ".next", "out", "build"].includes(name);
205
345
  },
206
346
  });
207
347
 
208
- // ------------------------------------------------------------------
209
- // Apply selected features
210
- // ------------------------------------------------------------------
211
-
348
+ // 2. Map and loop over chosen features sequentially
212
349
  for (const feature of project.features) {
213
- const featureDir = path.resolve(
214
- __dirname,
215
- "..",
216
- "next-mui-features",
217
- feature,
218
- project.language,
219
- );
220
-
221
- await fs.cp(featureDir, targetProjectDir, {
222
- recursive: true,
223
- filter: (src) => {
224
- const name = path.basename(src);
225
-
226
- return !["node_modules", ".next", "out", "build"].includes(name);
227
- },
228
- });
350
+ await applyFeature(feature, targetProjectDir, project.language);
229
351
  }
230
352
 
231
- // ------------------------------------------------------------------
232
-
353
+ // 3. Finalize package.json configuration naming
233
354
  await updateProjectName(targetProjectDir, packageName);
234
355
 
235
356
  s.stop(color.green("Workspace scaffolded successfully!"));
236
357
  } catch (error) {
237
358
  s.stop(color.red("Failed to scaffold workspace."));
238
-
239
359
  p.note(color.yellow(error.message), "Troubleshooting");
240
-
241
360
  process.exit(1);
242
361
  }
243
362
 
244
- // --------------------------------------------------------------------
245
-
246
363
  const cd =
247
364
  project.name === "." ? "" : `${color.cyan(`cd ${project.name}`)}\n`;
248
365