create-alistt69-kit 0.3.4 → 0.3.6

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 (63) hide show
  1. package/LICENSE +20 -20
  2. package/README.md +189 -189
  3. package/bin/index.js +24 -24
  4. package/package.json +44 -44
  5. package/src/core/apply-features.js +14 -14
  6. package/src/core/collect-project-info.js +170 -170
  7. package/src/core/copy-base-template.js +11 -11
  8. package/src/core/create-project.js +99 -99
  9. package/src/core/install-dependencies.js +27 -27
  10. package/src/core/parse-cli-args.js +122 -122
  11. package/src/core/prepare-target-directory.js +69 -69
  12. package/src/core/render-project-readme.js +278 -278
  13. package/src/core/replace-tokens.js +45 -45
  14. package/src/core/restore-special-files.js +18 -18
  15. package/src/features/agents-md/files/AGENTS.md +36 -36
  16. package/src/features/agents-md/index.js +13 -13
  17. package/src/features/autoprefixer/files/postcss.config.cjs +4 -4
  18. package/src/features/autoprefixer/index.js +31 -31
  19. package/src/features/define-feature.js +32 -32
  20. package/src/features/eslint/files/eslint.config.mjs +135 -135
  21. package/src/features/eslint/index.js +43 -43
  22. package/src/features/index.js +28 -28
  23. package/src/features/prerender/files/prerender.routes.mjs +5 -5
  24. package/src/features/prerender/files/scripts/prerender.mjs +114 -114
  25. package/src/features/prerender/index.js +40 -40
  26. package/src/features/react-router/files/scripts/generate/page.mjs +366 -366
  27. package/src/features/react-router/files/src/app/App.tsx +18 -18
  28. package/src/features/react-router/files/src/app/providers/error-boundary/lib/provider/index.tsx +44 -44
  29. package/src/features/react-router/files/src/app/providers/error-boundary/ui/error-screen/index.tsx +151 -151
  30. package/src/features/react-router/files/src/app/providers/index.ts +17 -17
  31. package/src/features/react-router/files/src/app/providers/router/lib/provider/index.tsx +21 -21
  32. package/src/features/react-router/files/src/app/providers/router/model/router/index.tsx +24 -24
  33. package/src/features/react-router/files/src/app/providers/router/types/index.ts +10 -10
  34. package/src/features/react-router/files/src/app/providers/router/ui/app/index.tsx +36 -36
  35. package/src/features/react-router/files/src/index.tsx +23 -23
  36. package/src/features/react-router/files/src/pages/error/index.ts +1 -1
  37. package/src/features/react-router/files/src/pages/error/lazy.ts +3 -3
  38. package/src/features/react-router/files/src/pages/error/page.tsx +7 -7
  39. package/src/features/react-router/files/src/pages/main/index.ts +1 -1
  40. package/src/features/react-router/files/src/pages/main/lazy.ts +3 -3
  41. package/src/features/react-router/files/src/pages/main/page.tsx +7 -7
  42. package/src/features/react-router/index.js +36 -36
  43. package/src/features/stylelint/files/stylelint.config.mjs +13 -13
  44. package/src/features/stylelint/index.js +37 -37
  45. package/src/templates/base/.editorconfig +11 -11
  46. package/src/templates/base/README.md +2 -2
  47. package/src/templates/base/babel.config.json +12 -12
  48. package/src/templates/base/gitignore +27 -27
  49. package/src/templates/base/package.json +48 -48
  50. package/src/templates/base/public/index.html +12 -12
  51. package/src/templates/base/src/app/App.tsx +12 -12
  52. package/src/templates/base/src/app/providers/error-boundary/lib/provider/index.tsx +44 -44
  53. package/src/templates/base/src/app/providers/error-boundary/ui/error-screen/index.tsx +150 -150
  54. package/src/templates/base/src/app/providers/index.ts +5 -5
  55. package/src/templates/base/src/index.tsx +19 -19
  56. package/src/templates/base/src/styles/index.scss +13 -13
  57. package/src/templates/base/src/styles/normalize.scss +36 -36
  58. package/src/templates/base/src/widgets/created-by/index.tsx +1 -1
  59. package/src/templates/base/tsconfig.json +25 -25
  60. package/src/utils/agents-md.js +52 -52
  61. package/src/utils/console-format.js +11 -11
  62. package/src/utils/package-json.js +96 -96
  63. package/src/utils/package-manager.js +22 -22
@@ -1,29 +1,29 @@
1
- import { agentsMdFeature } from './agents-md/index.js';
2
- import { autoprefixerFeature } from './autoprefixer/index.js';
3
- import { eslintFeature } from './eslint/index.js';
4
- import { prerenderFeature } from './prerender/index.js';
5
- import { reactRouterFeature } from './react-router/index.js';
6
- import { stylelintFeature } from './stylelint/index.js';
7
-
8
- export const features = [
9
- agentsMdFeature,
10
- autoprefixerFeature,
11
- eslintFeature,
12
- prerenderFeature,
13
- reactRouterFeature,
14
- stylelintFeature,
15
- ];
16
-
17
- export const featuresById = new Map(
18
- features.map((feature) => [feature.id, feature]),
19
- );
20
-
21
- export const featurePromptOptions = features.map((feature) => ({
22
- value: feature.id,
23
- label: feature.title,
24
- hint: feature.hint,
25
- }));
26
-
27
- export const defaultFeatureIds = features.map((feature) => feature.id);
28
-
1
+ import { agentsMdFeature } from './agents-md/index.js';
2
+ import { autoprefixerFeature } from './autoprefixer/index.js';
3
+ import { eslintFeature } from './eslint/index.js';
4
+ import { prerenderFeature } from './prerender/index.js';
5
+ import { reactRouterFeature } from './react-router/index.js';
6
+ import { stylelintFeature } from './stylelint/index.js';
7
+
8
+ export const features = [
9
+ agentsMdFeature,
10
+ autoprefixerFeature,
11
+ eslintFeature,
12
+ prerenderFeature,
13
+ reactRouterFeature,
14
+ stylelintFeature,
15
+ ];
16
+
17
+ export const featuresById = new Map(
18
+ features.map((feature) => [feature.id, feature]),
19
+ );
20
+
21
+ export const featurePromptOptions = features.map((feature) => ({
22
+ value: feature.id,
23
+ label: feature.title,
24
+ hint: feature.hint,
25
+ }));
26
+
27
+ export const defaultFeatureIds = features.map((feature) => feature.id);
28
+
29
29
  export const availableFeatureIdSet = new Set(defaultFeatureIds);
@@ -1,6 +1,6 @@
1
- export default async function getPrerenderRoutes() {
2
- return [
3
- '/',
4
- // @prerender-routes
5
- ];
1
+ export default async function getPrerenderRoutes() {
2
+ return [
3
+ '/',
4
+ // @prerender-routes
5
+ ];
6
6
  }
@@ -1,115 +1,115 @@
1
- import http from 'node:http';
2
- import fs from 'node:fs/promises';
3
- import path from 'node:path';
4
- import { fileURLToPath } from 'node:url';
5
-
6
- import handler from 'serve-handler';
7
- import puppeteer from 'puppeteer';
8
-
9
- import getPrerenderRoutes from '../prerender.routes.mjs';
10
-
11
- const __filename = fileURLToPath(import.meta.url);
12
- const __dirname = path.dirname(__filename);
13
- const projectRoot = path.resolve(__dirname, '..');
14
- const buildDir = path.join(projectRoot, 'build');
15
-
16
- const routesRaw = await getPrerenderRoutes();
17
- const routes = normalizeRoutes(routesRaw);
18
-
19
- if (routes.length === 0) {
20
- throw new Error('No prerender routes provided in prerender.routes.mjs');
21
- }
22
-
23
- const rewrites = routes.map((route) => ({
24
- source: route,
25
- destination: '/index.html',
26
- }));
27
-
28
- const server = http.createServer((request, response) => (
29
- handler(request, response, {
30
- public: buildDir,
31
- rewrites,
32
- })
33
- ));
34
-
35
- await new Promise((resolvePromise) => {
36
- server.listen(0, '127.0.0.1', resolvePromise);
37
- });
38
-
39
- const address = server.address();
40
-
41
- if (!address || typeof address === 'string') {
42
- throw new Error('Failed to start local prerender server');
43
- }
44
-
45
- const baseUrl = `http://127.0.0.1:${address.port}`;
46
- const browser = await puppeteer.launch({
47
- headless: true,
48
- args: [
49
- '--no-sandbox',
50
- '--disable-setuid-sandbox',
51
- '--disable-dev-shm-usage',
52
- ],
53
- });
54
-
55
- try {
56
- for (const route of routes) {
57
- const page = await browser.newPage();
58
-
59
- await page.goto(`${baseUrl}${route}`, {
60
- waitUntil: 'domcontentloaded',
61
- });
62
-
63
- await page.waitForSelector('#root', { timeout: 15000 });
64
-
65
- await page.waitForNetworkIdle({
66
- idleTime: 500,
67
- timeout: 15000,
68
- }).catch(() => {});
69
-
70
- await page.waitForFunction(
71
- () => globalThis.window?.__PRERENDER_READY__ !== false,
72
- { timeout: 3000 },
73
- ).catch(() => {});
74
-
75
- const html = `<!DOCTYPE html>\n${await page.content()}`;
76
- const targetFilePath = getTargetHtmlPath(buildDir, route);
77
-
78
- await fs.mkdir(path.dirname(targetFilePath), { recursive: true });
79
- await fs.writeFile(targetFilePath, html, 'utf8');
80
-
81
- await page.close();
82
-
83
- console.log(`✔ prerendered ${route} -> ${path.relative(projectRoot, targetFilePath)}`);
84
- }
85
- } finally {
86
- await browser.close();
87
- server.close();
88
- }
89
-
90
- function normalizeRoutes(routes) {
91
- if (!Array.isArray(routes)) {
92
- throw new TypeError('prerender.routes.mjs must return an array of routes');
93
- }
94
-
95
- return [...new Set(
96
- routes
97
- .map((route) => String(route).trim())
98
- .filter(Boolean)
99
- .map((route) => {
100
- if (route === '/') {
101
- return '/';
102
- }
103
-
104
- return `/${route.replace(/^\/+|\/+$/g, '')}`;
105
- }),
106
- )];
107
- }
108
-
109
- function getTargetHtmlPath(outputDir, route) {
110
- if (route === '/') {
111
- return path.join(outputDir, 'index.html');
112
- }
113
-
114
- return path.join(outputDir, route.slice(1), 'index.html');
1
+ import http from 'node:http';
2
+ import fs from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+
6
+ import handler from 'serve-handler';
7
+ import puppeteer from 'puppeteer';
8
+
9
+ import getPrerenderRoutes from '../prerender.routes.mjs';
10
+
11
+ const __filename = fileURLToPath(import.meta.url);
12
+ const __dirname = path.dirname(__filename);
13
+ const projectRoot = path.resolve(__dirname, '..');
14
+ const buildDir = path.join(projectRoot, 'build');
15
+
16
+ const routesRaw = await getPrerenderRoutes();
17
+ const routes = normalizeRoutes(routesRaw);
18
+
19
+ if (routes.length === 0) {
20
+ throw new Error('No prerender routes provided in prerender.routes.mjs');
21
+ }
22
+
23
+ const rewrites = routes.map((route) => ({
24
+ source: route,
25
+ destination: '/index.html',
26
+ }));
27
+
28
+ const server = http.createServer((request, response) => (
29
+ handler(request, response, {
30
+ public: buildDir,
31
+ rewrites,
32
+ })
33
+ ));
34
+
35
+ await new Promise((resolvePromise) => {
36
+ server.listen(0, '127.0.0.1', resolvePromise);
37
+ });
38
+
39
+ const address = server.address();
40
+
41
+ if (!address || typeof address === 'string') {
42
+ throw new Error('Failed to start local prerender server');
43
+ }
44
+
45
+ const baseUrl = `http://127.0.0.1:${address.port}`;
46
+ const browser = await puppeteer.launch({
47
+ headless: true,
48
+ args: [
49
+ '--no-sandbox',
50
+ '--disable-setuid-sandbox',
51
+ '--disable-dev-shm-usage',
52
+ ],
53
+ });
54
+
55
+ try {
56
+ for (const route of routes) {
57
+ const page = await browser.newPage();
58
+
59
+ await page.goto(`${baseUrl}${route}`, {
60
+ waitUntil: 'domcontentloaded',
61
+ });
62
+
63
+ await page.waitForSelector('#root', { timeout: 15000 });
64
+
65
+ await page.waitForNetworkIdle({
66
+ idleTime: 500,
67
+ timeout: 15000,
68
+ }).catch(() => {});
69
+
70
+ await page.waitForFunction(
71
+ () => globalThis.window?.__PRERENDER_READY__ !== false,
72
+ { timeout: 3000 },
73
+ ).catch(() => {});
74
+
75
+ const html = `<!DOCTYPE html>\n${await page.content()}`;
76
+ const targetFilePath = getTargetHtmlPath(buildDir, route);
77
+
78
+ await fs.mkdir(path.dirname(targetFilePath), { recursive: true });
79
+ await fs.writeFile(targetFilePath, html, 'utf8');
80
+
81
+ await page.close();
82
+
83
+ console.log(`✔ prerendered ${route} -> ${path.relative(projectRoot, targetFilePath)}`);
84
+ }
85
+ } finally {
86
+ await browser.close();
87
+ server.close();
88
+ }
89
+
90
+ function normalizeRoutes(routes) {
91
+ if (!Array.isArray(routes)) {
92
+ throw new TypeError('prerender.routes.mjs must return an array of routes');
93
+ }
94
+
95
+ return [...new Set(
96
+ routes
97
+ .map((route) => String(route).trim())
98
+ .filter(Boolean)
99
+ .map((route) => {
100
+ if (route === '/') {
101
+ return '/';
102
+ }
103
+
104
+ return `/${route.replace(/^\/+|\/+$/g, '')}`;
105
+ }),
106
+ )];
107
+ }
108
+
109
+ function getTargetHtmlPath(outputDir, route) {
110
+ if (route === '/') {
111
+ return path.join(outputDir, 'index.html');
112
+ }
113
+
114
+ return path.join(outputDir, route.slice(1), 'index.html');
115
115
  }
@@ -1,41 +1,41 @@
1
- import { dirname, resolve } from 'node:path';
2
- import { fileURLToPath } from 'node:url';
3
-
4
- import { defineFeature } from '../define-feature.js';
5
- import { appendAgentsSection } from '../../utils/agents-md.js';
6
-
7
- const currentFilePath = fileURLToPath(import.meta.url);
8
- const currentDirPath = dirname(currentFilePath);
9
-
10
- export const prerenderFeature = defineFeature({
11
- id: 'prerender',
12
- title: 'Prerender',
13
- hint: 'Static HTML prerender via Puppeteer after webpack build',
14
- packageJson: {
15
- devDependencies: {
16
- puppeteer: '^24.19.0',
17
- 'serve-handler': '^6.1.6',
18
- },
19
- scripts: {
20
- build: 'npm run build:assets && npm run prerender',
21
- 'build:assets': 'webpack --env mode=production',
22
- 'build:prod': 'npm run build',
23
- prerender: 'node ./scripts/prerender.mjs',
24
- },
25
- },
26
- copyFiles: resolve(currentDirPath, 'files'),
27
- async apply({ projectPath }) {
28
- await appendAgentsSection(
29
- projectPath,
30
- 'prerender',
31
- `
32
- ## Prerender
33
-
34
- - Production build runs in two steps: \`npm run build:assets\` then \`npm run prerender\`.
35
- - Prerender route manifest lives in \`prerender.routes.mjs\`.
36
- - Prerender script lives in \`scripts/prerender.mjs\`.
37
- - When adding static routes, keep \`prerender.routes.mjs\` updated.
38
- `,
39
- );
40
- },
1
+ import { dirname, resolve } from 'node:path';
2
+ import { fileURLToPath } from 'node:url';
3
+
4
+ import { defineFeature } from '../define-feature.js';
5
+ import { appendAgentsSection } from '../../utils/agents-md.js';
6
+
7
+ const currentFilePath = fileURLToPath(import.meta.url);
8
+ const currentDirPath = dirname(currentFilePath);
9
+
10
+ export const prerenderFeature = defineFeature({
11
+ id: 'prerender',
12
+ title: 'Prerender',
13
+ hint: 'Static HTML prerender via Puppeteer after webpack build',
14
+ packageJson: {
15
+ devDependencies: {
16
+ puppeteer: '^24.19.0',
17
+ 'serve-handler': '^6.1.6',
18
+ },
19
+ scripts: {
20
+ build: 'npm run build:assets && npm run prerender',
21
+ 'build:assets': 'webpack --env mode=production',
22
+ 'build:prod': 'npm run build',
23
+ prerender: 'node ./scripts/prerender.mjs',
24
+ },
25
+ },
26
+ copyFiles: resolve(currentDirPath, 'files'),
27
+ async apply({ projectPath }) {
28
+ await appendAgentsSection(
29
+ projectPath,
30
+ 'prerender',
31
+ `
32
+ ## Prerender
33
+
34
+ - Production build runs in two steps: \`npm run build:assets\` then \`npm run prerender\`.
35
+ - Prerender route manifest lives in \`prerender.routes.mjs\`.
36
+ - Prerender script lives in \`scripts/prerender.mjs\`.
37
+ - When adding static routes, keep \`prerender.routes.mjs\` updated.
38
+ `,
39
+ );
40
+ },
41
41
  });