create-alistt69-kit 0.1.9 → 0.1.12

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 (45) hide show
  1. package/LICENSE +20 -20
  2. package/README.md +123 -122
  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 -194
  7. package/src/core/copy-base-template.js +11 -11
  8. package/src/core/create-project.js +99 -98
  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 +188 -75
  13. package/src/core/replace-tokens.js +45 -45
  14. package/src/core/restore-special-files.js +18 -18
  15. package/src/features/autoprefixer/files/postcss.config.cjs +4 -4
  16. package/src/features/autoprefixer/index.js +19 -23
  17. package/src/features/define-feature.js +33 -0
  18. package/src/features/eslint/files/eslint.config.mjs +133 -133
  19. package/src/features/eslint/index.js +30 -35
  20. package/src/features/index.js +25 -15
  21. package/src/features/react-router/files/src/app/App.tsx +20 -20
  22. package/src/features/react-router/files/src/app/layouts/app/index.tsx +36 -36
  23. package/src/features/react-router/files/src/app/providers/router/config/router.tsx +13 -13
  24. package/src/features/react-router/files/src/pages/error/index.ts +1 -1
  25. package/src/features/react-router/files/src/pages/error/lazy.ts +3 -3
  26. package/src/features/react-router/files/src/pages/error/page.tsx +7 -7
  27. package/src/features/react-router/files/src/pages/main/index.ts +1 -1
  28. package/src/features/react-router/files/src/pages/main/lazy.ts +3 -3
  29. package/src/features/react-router/files/src/pages/main/page.tsx +7 -7
  30. package/src/features/react-router/index.js +19 -23
  31. package/src/features/stylelint/files/stylelint.config.mjs +13 -13
  32. package/src/features/stylelint/index.js +24 -29
  33. package/src/templates/base/.editorconfig +11 -11
  34. package/src/templates/base/README.md +2 -2
  35. package/src/templates/base/babel.config.json +12 -12
  36. package/src/templates/base/gitignore +27 -27
  37. package/src/templates/base/package.json +48 -48
  38. package/src/templates/base/public/index.html +12 -12
  39. package/src/templates/base/src/app/App.tsx +17 -17
  40. package/src/templates/base/src/index.tsx +16 -16
  41. package/src/templates/base/src/styles/index.scss +13 -13
  42. package/src/templates/base/tsconfig.json +25 -25
  43. package/src/utils/console-format.js +11 -11
  44. package/src/utils/package-json.js +96 -72
  45. package/src/utils/package-manager.js +22 -22
@@ -1,46 +1,46 @@
1
- import { readFile, readdir, stat, writeFile } from 'node:fs/promises';
2
- import { resolve } from 'node:path';
3
-
4
- const replaceTokensInFile = async (filePath, tokens) => {
5
- const fileContent = await readFile(filePath, 'utf8');
6
-
7
- let updatedContent = fileContent;
8
-
9
- for (const [token, value] of Object.entries(tokens)) {
10
- updatedContent = updatedContent.replaceAll(token, value);
11
- }
12
-
13
- await writeFile(filePath, updatedContent, 'utf8');
14
- };
15
-
16
- const replaceTokensRecursively = async (targetPath, tokens) => {
17
- const targetStat = await stat(targetPath);
18
-
19
- if (targetStat.isFile()) {
20
- await replaceTokensInFile(targetPath, tokens);
21
- return;
22
- }
23
-
24
- if (!targetStat.isDirectory()) {
25
- return;
26
- }
27
-
28
- const entries = await readdir(targetPath, { withFileTypes: true });
29
-
30
- for (const entry of entries) {
31
- const entryPath = resolve(targetPath, entry.name);
32
-
33
- if (entry.isDirectory()) {
34
- await replaceTokensRecursively(entryPath, tokens);
35
- continue;
36
- }
37
-
38
- if (entry.isFile()) {
39
- await replaceTokensInFile(entryPath, tokens);
40
- }
41
- }
42
- };
43
-
44
- export async function replaceTokens(targetDirPath, tokens) {
45
- await replaceTokensRecursively(targetDirPath, tokens);
1
+ import { readFile, readdir, stat, writeFile } from 'node:fs/promises';
2
+ import { resolve } from 'node:path';
3
+
4
+ const replaceTokensInFile = async (filePath, tokens) => {
5
+ const fileContent = await readFile(filePath, 'utf8');
6
+
7
+ let updatedContent = fileContent;
8
+
9
+ for (const [token, value] of Object.entries(tokens)) {
10
+ updatedContent = updatedContent.replaceAll(token, value);
11
+ }
12
+
13
+ await writeFile(filePath, updatedContent, 'utf8');
14
+ };
15
+
16
+ const replaceTokensRecursively = async (targetPath, tokens) => {
17
+ const targetStat = await stat(targetPath);
18
+
19
+ if (targetStat.isFile()) {
20
+ await replaceTokensInFile(targetPath, tokens);
21
+ return;
22
+ }
23
+
24
+ if (!targetStat.isDirectory()) {
25
+ return;
26
+ }
27
+
28
+ const entries = await readdir(targetPath, { withFileTypes: true });
29
+
30
+ for (const entry of entries) {
31
+ const entryPath = resolve(targetPath, entry.name);
32
+
33
+ if (entry.isDirectory()) {
34
+ await replaceTokensRecursively(entryPath, tokens);
35
+ continue;
36
+ }
37
+
38
+ if (entry.isFile()) {
39
+ await replaceTokensInFile(entryPath, tokens);
40
+ }
41
+ }
42
+ };
43
+
44
+ export async function replaceTokens(targetDirPath, tokens) {
45
+ await replaceTokensRecursively(targetDirPath, tokens);
46
46
  }
@@ -1,19 +1,19 @@
1
- import { access, rename } from 'node:fs/promises';
2
- import { resolve } from 'node:path';
3
-
4
- async function renameIfExists(fromPath, toPath) {
5
- try {
6
- await access(fromPath);
7
- } catch {
8
- return;
9
- }
10
-
11
- await rename(fromPath, toPath);
12
- }
13
-
14
- export async function restoreSpecialFiles(projectPath) {
15
- await renameIfExists(
16
- resolve(projectPath, 'gitignore'),
17
- resolve(projectPath, '.gitignore'),
18
- );
1
+ import { access, rename } from 'node:fs/promises';
2
+ import { resolve } from 'node:path';
3
+
4
+ async function renameIfExists(fromPath, toPath) {
5
+ try {
6
+ await access(fromPath);
7
+ } catch {
8
+ return;
9
+ }
10
+
11
+ await rename(fromPath, toPath);
12
+ }
13
+
14
+ export async function restoreSpecialFiles(projectPath) {
15
+ await renameIfExists(
16
+ resolve(projectPath, 'gitignore'),
17
+ resolve(projectPath, '.gitignore'),
18
+ );
19
19
  }
@@ -1,5 +1,5 @@
1
- module.exports = {
2
- plugins: [
3
- require('autoprefixer'),
4
- ],
1
+ module.exports = {
2
+ plugins: [
3
+ require('autoprefixer'),
4
+ ],
5
5
  };
@@ -1,23 +1,19 @@
1
- import { cp } from 'node:fs/promises';
2
- import { dirname, resolve } from 'node:path';
3
- import { fileURLToPath } from 'node:url';
4
- import { addDevDependencies } from '../../utils/package-json.js';
5
-
6
- const currentFilePath = fileURLToPath(import.meta.url);
7
- const currentDirPath = dirname(currentFilePath);
8
-
9
- export const autoprefixerFeature = {
10
- id: 'autoprefixer',
11
- title: 'Autoprefixer',
12
- apply: async ({ projectPath }) => {
13
- await addDevDependencies(projectPath, {
14
- autoprefixer: '^10.4.21',
15
- });
16
-
17
- const filesDirPath = resolve(currentDirPath, 'files');
18
-
19
- await cp(filesDirPath, projectPath, {
20
- recursive: true,
21
- });
22
- },
23
- };
1
+ import { dirname, resolve } from 'node:path';
2
+ import { fileURLToPath } from 'node:url';
3
+
4
+ import { defineFeature } from '../define-feature.js';
5
+
6
+ const currentFilePath = fileURLToPath(import.meta.url);
7
+ const currentDirPath = dirname(currentFilePath);
8
+
9
+ export const autoprefixerFeature = defineFeature({
10
+ id: 'autoprefixer',
11
+ title: 'Autoprefixer',
12
+ hint: 'PostCSS vendor prefixes',
13
+ packageJson: {
14
+ devDependencies: {
15
+ autoprefixer: '^10.4.21',
16
+ },
17
+ },
18
+ copyFiles: resolve(currentDirPath, 'files'),
19
+ });
@@ -0,0 +1,33 @@
1
+ import { cp } from 'node:fs/promises';
2
+
3
+ import { patchPackageJson } from '../utils/package-json.js';
4
+
5
+ export function defineFeature({
6
+ id,
7
+ title,
8
+ hint,
9
+ packageJson,
10
+ apply,
11
+ copyFiles,
12
+ }) {
13
+ return {
14
+ id,
15
+ title,
16
+ hint,
17
+ async applyFeature(context) {
18
+ if (packageJson) {
19
+ await patchPackageJson(context.projectPath, packageJson);
20
+ }
21
+
22
+ if (copyFiles) {
23
+ await cp(copyFiles, context.projectPath, {
24
+ recursive: true,
25
+ });
26
+ }
27
+
28
+ if (apply) {
29
+ await apply(context);
30
+ }
31
+ },
32
+ };
33
+ }
@@ -1,134 +1,134 @@
1
- import js from '@eslint/js';
2
- import stylistic from '@stylistic/eslint-plugin';
3
- import importPlugin from 'eslint-plugin-import';
4
- import react from 'eslint-plugin-react';
5
- import reactHooks from 'eslint-plugin-react-hooks';
6
- import unused from 'eslint-plugin-unused-imports';
7
- import tseslint from 'typescript-eslint';
8
-
9
- export default [
10
- // ESLint recommended rules
11
- js.configs.recommended,
12
-
13
- // Paths to ignore
14
- {
15
- ignores: ['**/dist', '**/node_modules', '**/build', 'webpack.config.ts', 'postcss.config.cjs'],
16
- },
17
-
18
- // TypeScript rules
19
- ...tseslint.configs.recommended,
20
- ...tseslint.configs.stylistic,
21
-
22
- // TypeScript parser configuration
23
- {
24
- files: ['**/*.ts', '**/*.tsx'],
25
- languageOptions: {
26
- parser: tseslint.parser,
27
- parserOptions: { sourceType: 'module' },
28
- },
29
- },
30
-
31
- // Stylistic rules (Prettier alternative)
32
- stylistic.configs.recommended,
33
-
34
- // Main rule configuration
35
- {
36
- plugins: {
37
- react,
38
- 'react-hooks': reactHooks,
39
- '@stylistic': stylistic,
40
- import: importPlugin,
41
- 'unused-imports': unused,
42
- },
43
- settings: { react: { version: 'detect' } },
44
- rules: {
45
- // === Formatting ===
46
- '@stylistic/indent': ['error', 4, { SwitchCase: 1 }],
47
- '@stylistic/semi': ['error', 'always'],
48
- '@stylistic/quotes': ['error', 'single', { avoidEscape: true }],
49
- '@stylistic/comma-dangle': ['error', 'always-multiline'],
50
- '@stylistic/object-curly-spacing': ['error', 'always'],
51
- '@stylistic/array-bracket-spacing': ['error', 'never'],
52
- '@stylistic/eol-last': ['error', 'always'],
53
- '@stylistic/arrow-parens': ['error', 'always'],
54
- '@stylistic/quote-props': ['error', 'as-needed', { keywords: false }],
55
- '@stylistic/member-delimiter-style': ['error', {
56
- multiline: { delimiter: 'semi', requireLast: true },
57
- singleline: { delimiter: 'semi', requireLast: false },
58
- }],
59
- '@stylistic/no-extra-parens': 'off',
60
- '@stylistic/jsx-indent-props': 'off',
61
- '@stylistic/multiline-ternary': 'off',
62
-
63
- // === Whitespace ===
64
- 'no-trailing-spaces': ['warn', { skipBlankLines: false }],
65
- 'no-multiple-empty-lines': ['error', { max: 1, maxBOF: 0, maxEOF: 1 }],
66
- 'comma-style': ['error', 'last'],
67
-
68
- // === Line length ===
69
- 'max-len': ['error', {
70
- code: 120,
71
- tabWidth: 4,
72
- ignoreUrls: true,
73
- ignoreStrings: true,
74
- ignoreComments: false,
75
- ignoreTemplateLiterals: true,
76
- }],
77
-
78
- // === Imports ===
79
- 'unused-imports/no-unused-imports': 'warn',
80
- 'unused-imports/no-unused-vars': ['warn', {
81
- args: 'after-used',
82
- argsIgnorePattern: '^_',
83
- varsIgnorePattern: '^_',
84
- caughtErrorsIgnorePattern: '^_',
85
- }],
86
- 'import/order': ['error', {
87
- groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'object', 'type'],
88
- pathGroups: [
89
- { pattern: '@/**', group: 'internal', position: 'after' },
90
- { pattern: '@app/**', group: 'internal', position: 'after' },
91
- { pattern: '@pages/**', group: 'internal', position: 'after' },
92
- { pattern: '@widgets/**', group: 'internal', position: 'after' },
93
- { pattern: '@features/**', group: 'internal', position: 'after' },
94
- { pattern: '@entities/**', group: 'internal', position: 'after' },
95
- { pattern: '@shared/**', group: 'internal', position: 'after' },
96
- ],
97
- pathGroupsExcludedImportTypes: ['builtin', 'external'],
98
- 'newlines-between': 'never',
99
- alphabetize: { order: 'asc', caseInsensitive: true },
100
- }],
101
-
102
- // === React ===
103
- ...react.configs.recommended.rules,
104
- ...reactHooks.configs.recommended.rules,
105
- 'react/react-in-jsx-scope': 'off', // Not needed in React 17+
106
- 'react/jsx-uses-react': 'off', // Not needed in React 17+
107
- 'react/prop-types': 'off', // TypeScript handles this
108
-
109
- // === JSX formatting ===
110
- 'react/jsx-indent': ['error', 4],
111
- 'react/jsx-indent-props': ['error', 4],
112
- 'react/jsx-curly-spacing': ['error', { when: 'never', children: true }],
113
- 'react/jsx-equals-spacing': ['error', 'never'],
114
- 'react/jsx-tag-spacing': ['error', {
115
- closingSlash: 'never',
116
- beforeSelfClosing: 'always',
117
- afterOpening: 'never',
118
- beforeClosing: 'never',
119
- }],
120
- 'react/jsx-first-prop-new-line': ['error', 'multiline-multiprop'],
121
- 'react/jsx-max-props-per-line': ['error', { maximum: 1, when: 'multiline' }],
122
- 'react/jsx-closing-bracket-location': ['error', 'line-aligned'],
123
-
124
- // === General ===
125
- '@typescript-eslint/no-unused-vars': 'off', // Handled by unused-imports
126
- 'no-console': ['warn', { allow: ['error'] }],
127
- 'no-restricted-imports': ['error', {
128
- name: 'react',
129
- importNames: ['default'],
130
- message: 'React import is not needed in React 17+. Remove import React from "react".',
131
- }],
132
- },
133
- },
1
+ import js from '@eslint/js';
2
+ import stylistic from '@stylistic/eslint-plugin';
3
+ import importPlugin from 'eslint-plugin-import';
4
+ import react from 'eslint-plugin-react';
5
+ import reactHooks from 'eslint-plugin-react-hooks';
6
+ import unused from 'eslint-plugin-unused-imports';
7
+ import tseslint from 'typescript-eslint';
8
+
9
+ export default [
10
+ // ESLint recommended rules
11
+ js.configs.recommended,
12
+
13
+ // Paths to ignore
14
+ {
15
+ ignores: ['**/dist', '**/node_modules', '**/build', 'webpack.config.ts', 'postcss.config.cjs'],
16
+ },
17
+
18
+ // TypeScript rules
19
+ ...tseslint.configs.recommended,
20
+ ...tseslint.configs.stylistic,
21
+
22
+ // TypeScript parser configuration
23
+ {
24
+ files: ['**/*.ts', '**/*.tsx'],
25
+ languageOptions: {
26
+ parser: tseslint.parser,
27
+ parserOptions: { sourceType: 'module' },
28
+ },
29
+ },
30
+
31
+ // Stylistic rules (Prettier alternative)
32
+ stylistic.configs.recommended,
33
+
34
+ // Main rule configuration
35
+ {
36
+ plugins: {
37
+ react,
38
+ 'react-hooks': reactHooks,
39
+ '@stylistic': stylistic,
40
+ import: importPlugin,
41
+ 'unused-imports': unused,
42
+ },
43
+ settings: { react: { version: 'detect' } },
44
+ rules: {
45
+ // === Formatting ===
46
+ '@stylistic/indent': ['error', 4, { SwitchCase: 1 }],
47
+ '@stylistic/semi': ['error', 'always'],
48
+ '@stylistic/quotes': ['error', 'single', { avoidEscape: true }],
49
+ '@stylistic/comma-dangle': ['error', 'always-multiline'],
50
+ '@stylistic/object-curly-spacing': ['error', 'always'],
51
+ '@stylistic/array-bracket-spacing': ['error', 'never'],
52
+ '@stylistic/eol-last': ['error', 'always'],
53
+ '@stylistic/arrow-parens': ['error', 'always'],
54
+ '@stylistic/quote-props': ['error', 'as-needed', { keywords: false }],
55
+ '@stylistic/member-delimiter-style': ['error', {
56
+ multiline: { delimiter: 'semi', requireLast: true },
57
+ singleline: { delimiter: 'semi', requireLast: false },
58
+ }],
59
+ '@stylistic/no-extra-parens': 'off',
60
+ '@stylistic/jsx-indent-props': 'off',
61
+ '@stylistic/multiline-ternary': 'off',
62
+
63
+ // === Whitespace ===
64
+ 'no-trailing-spaces': ['warn', { skipBlankLines: false }],
65
+ 'no-multiple-empty-lines': ['error', { max: 1, maxBOF: 0, maxEOF: 1 }],
66
+ 'comma-style': ['error', 'last'],
67
+
68
+ // === Line length ===
69
+ 'max-len': ['error', {
70
+ code: 120,
71
+ tabWidth: 4,
72
+ ignoreUrls: true,
73
+ ignoreStrings: true,
74
+ ignoreComments: false,
75
+ ignoreTemplateLiterals: true,
76
+ }],
77
+
78
+ // === Imports ===
79
+ 'unused-imports/no-unused-imports': 'warn',
80
+ 'unused-imports/no-unused-vars': ['warn', {
81
+ args: 'after-used',
82
+ argsIgnorePattern: '^_',
83
+ varsIgnorePattern: '^_',
84
+ caughtErrorsIgnorePattern: '^_',
85
+ }],
86
+ 'import/order': ['error', {
87
+ groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'object', 'type'],
88
+ pathGroups: [
89
+ { pattern: '@/**', group: 'internal', position: 'after' },
90
+ { pattern: '@app/**', group: 'internal', position: 'after' },
91
+ { pattern: '@pages/**', group: 'internal', position: 'after' },
92
+ { pattern: '@widgets/**', group: 'internal', position: 'after' },
93
+ { pattern: '@features/**', group: 'internal', position: 'after' },
94
+ { pattern: '@entities/**', group: 'internal', position: 'after' },
95
+ { pattern: '@shared/**', group: 'internal', position: 'after' },
96
+ ],
97
+ pathGroupsExcludedImportTypes: ['builtin', 'external'],
98
+ 'newlines-between': 'never',
99
+ alphabetize: { order: 'asc', caseInsensitive: true },
100
+ }],
101
+
102
+ // === React ===
103
+ ...react.configs.recommended.rules,
104
+ ...reactHooks.configs.recommended.rules,
105
+ 'react/react-in-jsx-scope': 'off', // Not needed in React 17+
106
+ 'react/jsx-uses-react': 'off', // Not needed in React 17+
107
+ 'react/prop-types': 'off', // TypeScript handles this
108
+
109
+ // === JSX formatting ===
110
+ 'react/jsx-indent': ['error', 4],
111
+ 'react/jsx-indent-props': ['error', 4],
112
+ 'react/jsx-curly-spacing': ['error', { when: 'never', children: true }],
113
+ 'react/jsx-equals-spacing': ['error', 'never'],
114
+ 'react/jsx-tag-spacing': ['error', {
115
+ closingSlash: 'never',
116
+ beforeSelfClosing: 'always',
117
+ afterOpening: 'never',
118
+ beforeClosing: 'never',
119
+ }],
120
+ 'react/jsx-first-prop-new-line': ['error', 'multiline-multiprop'],
121
+ 'react/jsx-max-props-per-line': ['error', { maximum: 1, when: 'multiline' }],
122
+ 'react/jsx-closing-bracket-location': ['error', 'line-aligned'],
123
+
124
+ // === General ===
125
+ '@typescript-eslint/no-unused-vars': 'off', // Handled by unused-imports
126
+ 'no-console': ['warn', { allow: ['error'] }],
127
+ 'no-restricted-imports': ['error', {
128
+ name: 'react',
129
+ importNames: ['default'],
130
+ message: 'React import is not needed in React 17+. Remove import React from "react".',
131
+ }],
132
+ },
133
+ },
134
134
  ];
@@ -1,35 +1,30 @@
1
- import { cp } from 'node:fs/promises';
2
- import { dirname, resolve } from 'node:path';
3
- import { fileURLToPath } from 'node:url';
4
- import { addDevDependencies, addScripts } from '../../utils/package-json.js';
5
-
6
- const currentFilePath = fileURLToPath(import.meta.url);
7
- const currentDirPath = dirname(currentFilePath);
8
-
9
- export const eslintFeature = {
10
- id: 'eslint',
11
- title: 'ESLint + Stylistic',
12
- apply: async ({ projectPath }) => {
13
- await addDevDependencies(projectPath, {
14
- "eslint": "^9.0.0",
15
- "@eslint/js": "^9.0.0",
16
- "@stylistic/eslint-plugin": "^5.0.0",
17
- "typescript-eslint": "^8.0.0",
18
- "eslint-plugin-import": "^2.0.0",
19
- "eslint-plugin-react": "^7.0.0",
20
- "eslint-plugin-react-hooks": "^7.0.0",
21
- "eslint-plugin-unused-imports": "^4.0.0"
22
- });
23
-
24
- await addScripts(projectPath, {
25
- lint: 'eslint . --ext .js,.jsx,.ts,.tsx',
26
- 'lint:fix': 'eslint . --ext .js,.jsx,.ts,.tsx --fix',
27
- });
28
-
29
- const filesDirPath = resolve(currentDirPath, 'files');
30
-
31
- await cp(filesDirPath, projectPath, {
32
- recursive: true,
33
- });
34
- },
35
- };
1
+ import { dirname, resolve } from 'node:path';
2
+ import { fileURLToPath } from 'node:url';
3
+
4
+ import { defineFeature } from '../define-feature.js';
5
+
6
+ const currentFilePath = fileURLToPath(import.meta.url);
7
+ const currentDirPath = dirname(currentFilePath);
8
+
9
+ export const eslintFeature = defineFeature({
10
+ id: 'eslint',
11
+ title: 'ESLint + Stylistic',
12
+ hint: 'JS/TS/React linting',
13
+ packageJson: {
14
+ devDependencies: {
15
+ eslint: '^9.0.0',
16
+ '@eslint/js': '^9.0.0',
17
+ '@stylistic/eslint-plugin': '^5.0.0',
18
+ 'typescript-eslint': '^8.0.0',
19
+ 'eslint-plugin-import': '^2.0.0',
20
+ 'eslint-plugin-react': '^7.0.0',
21
+ 'eslint-plugin-react-hooks': '^7.0.0',
22
+ 'eslint-plugin-unused-imports': '^4.0.0',
23
+ },
24
+ scripts: {
25
+ lint: 'eslint . --ext .js,.jsx,.ts,.tsx',
26
+ 'lint:fix': 'eslint . --ext .js,.jsx,.ts,.tsx --fix',
27
+ },
28
+ },
29
+ copyFiles: resolve(currentDirPath, 'files'),
30
+ });
@@ -1,15 +1,25 @@
1
- import { autoprefixerFeature } from './autoprefixer/index.js';
2
- import { eslintFeature } from './eslint/index.js';
3
- import { reactRouterFeature } from './react-router/index.js';
4
- import { stylelintFeature } from './stylelint/index.js';
5
-
6
- export const features = [
7
- autoprefixerFeature,
8
- eslintFeature,
9
- reactRouterFeature,
10
- stylelintFeature,
11
- ];
12
-
13
- export const featuresById = new Map(
14
- features.map((feature) => [feature.id, feature]),
15
- );
1
+ import { autoprefixerFeature } from './autoprefixer/index.js';
2
+ import { eslintFeature } from './eslint/index.js';
3
+ import { reactRouterFeature } from './react-router/index.js';
4
+ import { stylelintFeature } from './stylelint/index.js';
5
+
6
+ export const features = [
7
+ autoprefixerFeature,
8
+ eslintFeature,
9
+ reactRouterFeature,
10
+ stylelintFeature,
11
+ ];
12
+
13
+ export const featuresById = new Map(
14
+ features.map((feature) => [feature.id, feature]),
15
+ );
16
+
17
+ export const featurePromptOptions = features.map((feature) => ({
18
+ value: feature.id,
19
+ label: feature.title,
20
+ hint: feature.hint,
21
+ }));
22
+
23
+ export const defaultFeatureIds = features.map((feature) => feature.id);
24
+
25
+ export const availableFeatureIdSet = new Set(defaultFeatureIds);
@@ -1,20 +1,20 @@
1
- import { RouterProvider } from 'react-router-dom';
2
- import Logo from '../../public/create-alistt69-kit-logo.svg';
3
- import { appRouter } from './providers/router/config/router';
4
- import styles from './styles.module.scss';
5
-
6
- function App() {
7
- return (
8
- <div className={styles.app_wrapper}>
9
- <div className={styles.created_by_section}>
10
- <Logo className={styles.logo} />
11
- <p className={styles.promo}>
12
- created by create-alistt69-kit
13
- </p>
14
- </div>
15
- <RouterProvider router={appRouter} />
16
- </div>
17
- );
18
- }
19
-
20
- export default App;
1
+ import { RouterProvider } from 'react-router-dom';
2
+ import Logo from '../../public/create-alistt69-kit-logo.svg';
3
+ import { appRouter } from './providers/router/config/router';
4
+ import styles from './styles.module.scss';
5
+
6
+ function App() {
7
+ return (
8
+ <div className={styles.app_wrapper}>
9
+ <div className={styles.created_by_section}>
10
+ <Logo className={styles.logo} />
11
+ <p className={styles.promo}>
12
+ created by create-alistt69-kit
13
+ </p>
14
+ </div>
15
+ <RouterProvider router={appRouter} />
16
+ </div>
17
+ );
18
+ }
19
+
20
+ export default App;