create-arui-scripts-app 1.0.0 → 1.1.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/CHANGELOG.md +13 -0
- package/README.md +12 -3
- package/assets/.yarn/releases/yarn-4.9.1.cjs +0 -0
- package/build/build-context.js +5 -0
- package/build/build-file-map.js +8 -1
- package/build/create-program.js +5 -0
- package/build/defaults.d.ts +1 -0
- package/build/defaults.js +4 -2
- package/build/install-dependencies.d.ts +2 -0
- package/build/install-dependencies.js +18 -5
- package/build/questions.js +8 -0
- package/build/run.js +32 -0
- package/build/templates/app-component.template.js +10 -7
- package/build/templates/app-styles.template.js +6 -8
- package/build/templates/arui-scripts-config.template.js +2 -2
- package/build/templates/client-entry.template.js +2 -3
- package/build/templates/lint.template.d.ts +4 -0
- package/build/templates/lint.template.js +52 -0
- package/build/templates/misc.template.js +8 -2
- package/build/templates/package-json.template.js +18 -0
- package/build/templates/server-entry.template.js +13 -35
- package/build/templates/store.template.js +1 -1
- package/build/templates/tsconfig.template.js +11 -9
- package/build/types.d.ts +2 -0
- package/build/versions.d.ts +1 -1
- package/build/versions.js +1 -1
- package/package.json +55 -55
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# create-arui-scripts-app
|
|
2
|
+
|
|
3
|
+
## 1.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#566](https://github.com/core-ds/arui-scripts/pull/566) [`d5de571`](https://github.com/core-ds/arui-scripts/commit/d5de571bf16582ad78258d3b35acbc08d7da42a4) Thanks [@dmitrbrvsk](https://github.com/dmitrbrvsk)! - добавлена возможность подключать пакет arui-presets-lint (https://github.com/core-ds/arui-presets-lint/tree/master/packages/arui-presets-lint)
|
|
8
|
+
|
|
9
|
+
## 1.0.0
|
|
10
|
+
|
|
11
|
+
### Major Changes
|
|
12
|
+
|
|
13
|
+
- [#552](https://github.com/core-ds/arui-scripts/pull/552) [`3658e49`](https://github.com/core-ds/arui-scripts/commit/3658e49b0b752c592e738726aa8056569e28e19b) Thanks [@dmitrbrvsk](https://github.com/dmitrbrvsk)! - Добавлен пакет `create-arui-scripts-app` для генерации нового приложения через CLI. В `arui-scripts` CLI был переведен на commander.
|
package/README.md
CHANGED
|
@@ -35,7 +35,7 @@ npx create-arui-scripts-app my-app --yes
|
|
|
35
35
|
- `--css-modules` / `--no-css-modules` - CSS-модули
|
|
36
36
|
- `--client-port` / `--server-port` - порты клиента и сервера
|
|
37
37
|
- `--docker-registry` / `--presets` - docker registry и preset
|
|
38
|
-
- `--polyfills` / `--react-compiler` / `--install` - и соответствующие `--no-*`
|
|
38
|
+
- `--polyfills` / `--react-compiler` / `--lint` / `--install` - и соответствующие `--no-*`
|
|
39
39
|
|
|
40
40
|
## Что настраивает мастер
|
|
41
41
|
|
|
@@ -44,15 +44,24 @@ npx create-arui-scripts-app my-app --yes
|
|
|
44
44
|
- SSR-сервер на **Hapi** с рендерингом приложения (`renderToString`) и гидрацией на клиенте
|
|
45
45
|
- транспилятор (**swc** / babel / tsc) и тест-раннер (**Jest** / Vitest)
|
|
46
46
|
- CSS-модули, полифилы (`core-js`), `experimentalReactCompiler`, docker registry, preset
|
|
47
|
+
- опционально **arui-presets-lint** (eslint, prettier, stylelint, knip, secretlint, lefthook)
|
|
47
48
|
- опциональная установка зависимостей сразу после генерации
|
|
48
49
|
|
|
50
|
+
Пример с линтерами:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
npx create-arui-scripts-app my-app --yes --lint --install
|
|
54
|
+
```
|
|
55
|
+
|
|
49
56
|
## Результат
|
|
50
57
|
|
|
51
58
|
Генерируются `package.json`, `arui-scripts.config.ts`, `tsconfig.json`, клиентская точка входа,
|
|
52
59
|
пример компонента со стилями и тестом, `global-definitions.d.ts`, `.gitignore`, `README.md`,
|
|
53
60
|
`.yarnrc.yml` (с `nodeLinker: node-modules`),
|
|
54
|
-
а также в зависимости от ответов - серверная точка входа на Hapi, store на RTK,
|
|
55
|
-
`vitest.config.ts
|
|
61
|
+
а также в зависимости от ответов - серверная точка входа на Hapi, store на RTK, полифилы,
|
|
62
|
+
`vitest.config.ts` и конфиги `arui-presets-lint` (`eslint.config.mts`, `knip.ts`,
|
|
63
|
+
`.secretlintrc.json`, `lefthook.yml`).
|
|
56
64
|
|
|
57
65
|
Дальнейшая сборка и запуск через команды `arui-scripts` в созданном проекте.
|
|
58
66
|
См. [документацию arui-scripts](../arui-scripts/README.md).
|
|
67
|
+
При подключении lint: `yarn lint` / `yarn lint:fix`.
|
|
File without changes
|
package/build/build-context.js
CHANGED
|
@@ -23,6 +23,7 @@ const VERSIONS = {
|
|
|
23
23
|
tsJest: '^29.1.0',
|
|
24
24
|
typesJest: '^29.5.0',
|
|
25
25
|
vitest: '^4.1.5',
|
|
26
|
+
aruiPresetsLint: '^11.0.0',
|
|
26
27
|
};
|
|
27
28
|
function buildContext(answers, aruiScriptsVersion) {
|
|
28
29
|
const dependencies = {
|
|
@@ -63,6 +64,9 @@ function buildContext(answers, aruiScriptsVersion) {
|
|
|
63
64
|
else {
|
|
64
65
|
devDependencies.vitest = VERSIONS.vitest;
|
|
65
66
|
}
|
|
67
|
+
if (answers.useLint) {
|
|
68
|
+
devDependencies['arui-presets-lint'] = VERSIONS.aruiPresetsLint;
|
|
69
|
+
}
|
|
66
70
|
return {
|
|
67
71
|
name: answers.name,
|
|
68
72
|
useRtk: answers.useRtk,
|
|
@@ -76,6 +80,7 @@ function buildContext(answers, aruiScriptsVersion) {
|
|
|
76
80
|
presets: answers.presets.trim(),
|
|
77
81
|
polyfills: answers.polyfills,
|
|
78
82
|
reactCompiler: answers.reactCompiler,
|
|
83
|
+
useLint: answers.useLint,
|
|
79
84
|
aruiScriptsVersion,
|
|
80
85
|
dependencies,
|
|
81
86
|
devDependencies,
|
package/build/build-file-map.js
CHANGED
|
@@ -7,6 +7,7 @@ const app_styles_template_1 = require("./templates/app-styles.template");
|
|
|
7
7
|
const app_test_template_1 = require("./templates/app-test.template");
|
|
8
8
|
const arui_scripts_config_template_1 = require("./templates/arui-scripts-config.template");
|
|
9
9
|
const client_entry_template_1 = require("./templates/client-entry.template");
|
|
10
|
+
const lint_template_1 = require("./templates/lint.template");
|
|
10
11
|
const misc_template_1 = require("./templates/misc.template");
|
|
11
12
|
const package_json_template_1 = require("./templates/package-json.template");
|
|
12
13
|
const server_entry_template_1 = require("./templates/server-entry.template");
|
|
@@ -29,7 +30,7 @@ function buildFileMap(ctx) {
|
|
|
29
30
|
[`${client}/index.tsx`]: (0, client_entry_template_1.clientEntryTemplate)(ctx),
|
|
30
31
|
[`${client}/components/app.tsx`]: (0, app_component_template_1.appComponentTemplate)(ctx),
|
|
31
32
|
[`${client}/components/${(0, app_styles_template_1.appStylesFileName)(ctx)}`]: (0, app_styles_template_1.appStylesTemplate)(ctx),
|
|
32
|
-
[`${client}/components/__tests__/app.test.
|
|
33
|
+
[`${client}/components/__tests__/app.test.ts`]: (0, app_test_template_1.appTestTemplate)(ctx),
|
|
33
34
|
};
|
|
34
35
|
if (!ctx.clientOnly) {
|
|
35
36
|
files['src/server/index.tsx'] = (0, server_entry_template_1.serverEntryTemplate)(ctx);
|
|
@@ -45,5 +46,11 @@ function buildFileMap(ctx) {
|
|
|
45
46
|
files[`${client}/store/hooks.ts`] = (0, store_template_1.storeHooksTemplate)();
|
|
46
47
|
files[`${client}/store/counter-slice.ts`] = (0, store_template_1.counterSliceTemplate)();
|
|
47
48
|
}
|
|
49
|
+
if (ctx.useLint) {
|
|
50
|
+
files['eslint.config.mts'] = (0, lint_template_1.eslintConfigTemplate)();
|
|
51
|
+
files['knip.ts'] = (0, lint_template_1.knipConfigTemplate)();
|
|
52
|
+
files['.secretlintrc.json'] = (0, lint_template_1.secretlintConfigTemplate)();
|
|
53
|
+
files['lefthook.yml'] = (0, lint_template_1.lefthookConfigTemplate)();
|
|
54
|
+
}
|
|
48
55
|
return files;
|
|
49
56
|
}
|
package/build/create-program.js
CHANGED
|
@@ -41,6 +41,8 @@ function createProgram(onInit = defaultInitHandler) {
|
|
|
41
41
|
.option('--no-polyfills', 'Без полифилов')
|
|
42
42
|
.option('--react-compiler', 'Включить experimentalReactCompiler')
|
|
43
43
|
.option('--no-react-compiler', 'Выключить experimentalReactCompiler')
|
|
44
|
+
.option('--lint', 'Подключить arui-presets-lint')
|
|
45
|
+
.option('--no-lint', 'Без arui-presets-lint')
|
|
44
46
|
.option('--install', 'Установить зависимости после генерации')
|
|
45
47
|
.option('--no-install', 'Не устанавливать зависимости')
|
|
46
48
|
.showHelpAfterError('(используйте --help для справки)')
|
|
@@ -96,6 +98,9 @@ function mapOptsToFlags(opts) {
|
|
|
96
98
|
if (typeof opts.reactCompiler === 'boolean') {
|
|
97
99
|
flags.reactCompiler = opts.reactCompiler;
|
|
98
100
|
}
|
|
101
|
+
if (typeof opts.lint === 'boolean') {
|
|
102
|
+
flags.useLint = opts.lint;
|
|
103
|
+
}
|
|
99
104
|
if (typeof opts.install === 'boolean') {
|
|
100
105
|
flags.install = opts.install;
|
|
101
106
|
}
|
package/build/defaults.d.ts
CHANGED
package/build/defaults.js
CHANGED
|
@@ -17,6 +17,7 @@ function defaultAnswers(name) {
|
|
|
17
17
|
presets: '',
|
|
18
18
|
polyfills: false,
|
|
19
19
|
reactCompiler: false,
|
|
20
|
+
useLint: false,
|
|
20
21
|
install: false,
|
|
21
22
|
};
|
|
22
23
|
}
|
|
@@ -33,6 +34,7 @@ const ANSWER_FLAG_KEYS = [
|
|
|
33
34
|
'presets',
|
|
34
35
|
'polyfills',
|
|
35
36
|
'reactCompiler',
|
|
37
|
+
'useLint',
|
|
36
38
|
'install',
|
|
37
39
|
];
|
|
38
40
|
function hasAnswerFlags(flags) {
|
|
@@ -42,7 +44,7 @@ function hasAnswerFlags(flags) {
|
|
|
42
44
|
function answersFromFlags(defaultName, flags) {
|
|
43
45
|
var _a, _b;
|
|
44
46
|
const base = defaultAnswers(((_a = flags.name) === null || _a === void 0 ? void 0 : _a.trim()) || defaultName);
|
|
45
|
-
return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, base), (flags.useRtk === undefined ? {} : { useRtk: flags.useRtk })), (flags.clientOnly === undefined ? {} : { clientOnly: flags.clientOnly })), (flags.codeLoader === undefined ? {} : { codeLoader: flags.codeLoader })), (flags.testRunner === undefined ? {} : { testRunner: flags.testRunner })), (flags.cssModules === undefined ? {} : { cssModules: flags.cssModules })), (flags.clientServerPort === undefined
|
|
47
|
+
return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, base), (flags.useRtk === undefined ? {} : { useRtk: flags.useRtk })), (flags.clientOnly === undefined ? {} : { clientOnly: flags.clientOnly })), (flags.codeLoader === undefined ? {} : { codeLoader: flags.codeLoader })), (flags.testRunner === undefined ? {} : { testRunner: flags.testRunner })), (flags.cssModules === undefined ? {} : { cssModules: flags.cssModules })), (flags.clientServerPort === undefined
|
|
46
48
|
? {}
|
|
47
|
-
: { clientServerPort: flags.clientServerPort })), (flags.serverPort === undefined ? {} : { serverPort: flags.serverPort })), (flags.dockerRegistry === undefined ? {} : { dockerRegistry: flags.dockerRegistry })), (flags.presets === undefined ? {} : { presets: flags.presets })), (flags.polyfills === undefined ? {} : { polyfills: flags.polyfills })), (flags.reactCompiler === undefined ? {} : { reactCompiler: flags.reactCompiler })), (flags.install === undefined ? {} : { install: flags.install })), { name: (((_b = flags.name) === null || _b === void 0 ? void 0 : _b.trim()) || defaultName).trim() });
|
|
49
|
+
: { clientServerPort: flags.clientServerPort })), (flags.serverPort === undefined ? {} : { serverPort: flags.serverPort })), (flags.dockerRegistry === undefined ? {} : { dockerRegistry: flags.dockerRegistry })), (flags.presets === undefined ? {} : { presets: flags.presets })), (flags.polyfills === undefined ? {} : { polyfills: flags.polyfills })), (flags.reactCompiler === undefined ? {} : { reactCompiler: flags.reactCompiler })), (flags.useLint === undefined ? {} : { useLint: flags.useLint })), (flags.install === undefined ? {} : { install: flags.install })), { name: (((_b = flags.name) === null || _b === void 0 ? void 0 : _b.trim()) || defaultName).trim() });
|
|
48
50
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export type PackageManager = 'yarn' | 'npm';
|
|
2
2
|
export declare function detectPackageManager(): PackageManager;
|
|
3
3
|
export declare function installDependencies(targetDir: string, packageManager?: PackageManager): Promise<void>;
|
|
4
|
+
export declare function hasGitRepository(targetDir: string): boolean;
|
|
5
|
+
export declare function installLefthook(targetDir: string): Promise<void>;
|
|
@@ -5,17 +5,20 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.detectPackageManager = detectPackageManager;
|
|
7
7
|
exports.installDependencies = installDependencies;
|
|
8
|
+
exports.hasGitRepository = hasGitRepository;
|
|
9
|
+
exports.installLefthook = installLefthook;
|
|
8
10
|
const child_process_1 = require("child_process");
|
|
11
|
+
const fs_1 = __importDefault(require("fs"));
|
|
12
|
+
const path_1 = __importDefault(require("path"));
|
|
9
13
|
const shelljs_1 = __importDefault(require("shelljs"));
|
|
10
14
|
function detectPackageManager() {
|
|
11
15
|
return shelljs_1.default.which('yarn') ? 'yarn' : 'npm';
|
|
12
16
|
}
|
|
13
|
-
function
|
|
14
|
-
const args = packageManager === 'yarn' ? [] : ['install'];
|
|
17
|
+
function runCommand(command, args, cwd) {
|
|
15
18
|
return new Promise((resolve, reject) => {
|
|
16
19
|
var _a, _b;
|
|
17
|
-
const child = (0, child_process_1.spawn)(
|
|
18
|
-
cwd
|
|
20
|
+
const child = (0, child_process_1.spawn)(command, args, {
|
|
21
|
+
cwd,
|
|
19
22
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
20
23
|
// для windows
|
|
21
24
|
shell: process.platform === 'win32',
|
|
@@ -32,8 +35,18 @@ function installDependencies(targetDir, packageManager = detectPackageManager())
|
|
|
32
35
|
resolve();
|
|
33
36
|
}
|
|
34
37
|
else {
|
|
35
|
-
reject(new Error(`${
|
|
38
|
+
reject(new Error(`${command} ${args.join(' ')} завершился с кодом ${code}\n${output.trim()}`));
|
|
36
39
|
}
|
|
37
40
|
});
|
|
38
41
|
});
|
|
39
42
|
}
|
|
43
|
+
function installDependencies(targetDir, packageManager = detectPackageManager()) {
|
|
44
|
+
const args = packageManager === 'yarn' ? [] : ['install'];
|
|
45
|
+
return runCommand(packageManager, args, targetDir);
|
|
46
|
+
}
|
|
47
|
+
function hasGitRepository(targetDir) {
|
|
48
|
+
return fs_1.default.existsSync(path_1.default.join(targetDir, '.git'));
|
|
49
|
+
}
|
|
50
|
+
function installLefthook(targetDir) {
|
|
51
|
+
return runCommand('npx', ['--no-install', 'lefthook', 'install'], targetDir);
|
|
52
|
+
}
|
package/build/questions.js
CHANGED
|
@@ -114,6 +114,14 @@ function getQuestions(defaultName, prefill = {}) {
|
|
|
114
114
|
active: 'да',
|
|
115
115
|
inactive: 'нет',
|
|
116
116
|
},
|
|
117
|
+
{
|
|
118
|
+
type: unlessAnswered('useLint', 'toggle'),
|
|
119
|
+
name: 'useLint',
|
|
120
|
+
message: 'Подключить arui-presets-lint',
|
|
121
|
+
initial: false,
|
|
122
|
+
active: 'да',
|
|
123
|
+
inactive: 'нет',
|
|
124
|
+
},
|
|
117
125
|
{
|
|
118
126
|
type: unlessAnswered('install', 'toggle'),
|
|
119
127
|
name: 'install',
|
package/build/run.js
CHANGED
|
@@ -67,10 +67,32 @@ function runInit() {
|
|
|
67
67
|
spinner.fail(chalk_1.default.red('Не удалось установить зависимости'));
|
|
68
68
|
throw error;
|
|
69
69
|
}
|
|
70
|
+
if (initAnswers.useLint) {
|
|
71
|
+
yield tryInstallLefthook(targetDir);
|
|
72
|
+
}
|
|
70
73
|
}
|
|
71
74
|
printNextSteps(targetDir, baseCwd, initAnswers, packageManager);
|
|
72
75
|
});
|
|
73
76
|
}
|
|
77
|
+
function tryInstallLefthook(targetDir) {
|
|
78
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
79
|
+
if (!(0, install_dependencies_1.hasGitRepository)(targetDir)) {
|
|
80
|
+
console.log(` ${chalk_1.default.dim('lefthook: пропущено (нет .git). После git init выполните: npx --no-install lefthook install')}`);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const spinner = (0, ora_1.default)({ text: 'Устанавливаю git-хуки lefthook…', color: 'cyan' }).start();
|
|
84
|
+
try {
|
|
85
|
+
yield (0, install_dependencies_1.installLefthook)(targetDir);
|
|
86
|
+
spinner.succeed(chalk_1.default.green('Git-хуки lefthook установлены'));
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
spinner.fail(chalk_1.default.yellow('Не удалось установить lefthook'));
|
|
90
|
+
if (error instanceof Error && error.message) {
|
|
91
|
+
console.log(` ${chalk_1.default.dim(error.message)}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
}
|
|
74
96
|
function resolveAnswers(defaultName, flags) {
|
|
75
97
|
return __awaiter(this, void 0, void 0, function* () {
|
|
76
98
|
const base = (0, defaults_1.answersFromFlags)(defaultName, flags);
|
|
@@ -136,6 +158,9 @@ function mergePromptAnswers(base, answers) {
|
|
|
136
158
|
if (answers.reactCompiler !== undefined) {
|
|
137
159
|
merged.reactCompiler = Boolean(answers.reactCompiler);
|
|
138
160
|
}
|
|
161
|
+
if (answers.useLint !== undefined) {
|
|
162
|
+
merged.useLint = Boolean(answers.useLint);
|
|
163
|
+
}
|
|
139
164
|
if (answers.install !== undefined) {
|
|
140
165
|
merged.install = Boolean(answers.install);
|
|
141
166
|
}
|
|
@@ -153,6 +178,7 @@ function printSuccess(context, targetDir, fileCount) {
|
|
|
153
178
|
chalk_1.default.dim(context.clientOnly ? 'clientOnly' : 'SSR'),
|
|
154
179
|
chalk_1.default.dim(context.codeLoader),
|
|
155
180
|
chalk_1.default.dim(context.testRunner),
|
|
181
|
+
...(context.useLint ? [chalk_1.default.dim('lint')] : []),
|
|
156
182
|
].join(chalk_1.default.dim(' · '));
|
|
157
183
|
console.log();
|
|
158
184
|
console.log(` ${chalk_1.default.green('✔')} ${chalk_1.default.bold('Готово!')} ${chalk_1.default.dim(`проект «${context.name}» создан`)}`);
|
|
@@ -181,6 +207,12 @@ function printNextSteps(targetDir, baseCwd, answers, packageManager) {
|
|
|
181
207
|
if (!answers.install) {
|
|
182
208
|
steps.push(installCommand);
|
|
183
209
|
}
|
|
210
|
+
if (answers.useLint && (!answers.install || !(0, install_dependencies_1.hasGitRepository)(targetDir))) {
|
|
211
|
+
steps.push('npx --no-install lefthook install');
|
|
212
|
+
}
|
|
213
|
+
if (answers.useLint) {
|
|
214
|
+
steps.push(packageManager === 'yarn' ? 'yarn lint' : 'npm run lint');
|
|
215
|
+
}
|
|
184
216
|
steps.push(startCommand);
|
|
185
217
|
console.log();
|
|
186
218
|
console.log(` ${chalk_1.default.bold('Дальше')}`);
|
|
@@ -1,42 +1,44 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.appComponentTemplate = appComponentTemplate;
|
|
4
|
+
function tsString(value) {
|
|
5
|
+
return `'${value.replace(/\\/g, '\\\\').replace(/'/g, "\\'")}'`;
|
|
6
|
+
}
|
|
4
7
|
function appComponentTemplate(ctx) {
|
|
5
8
|
const styleImport = ctx.cssModules
|
|
6
9
|
? "import styles from './app.module.css';"
|
|
7
10
|
: "import './app.css';";
|
|
8
11
|
const rootClass = ctx.cssModules ? '{styles.root}' : "'app'";
|
|
9
12
|
const titleClass = ctx.cssModules ? '{styles.title}' : "'app__title'";
|
|
13
|
+
const appNameLiteral = tsString(ctx.name);
|
|
10
14
|
const coreImports = `import { Button } from '@alfalab/core-components/button';
|
|
11
15
|
import { Gap } from '@alfalab/core-components/gap';
|
|
12
16
|
import { Typography } from '@alfalab/core-components/typography';`;
|
|
13
17
|
const view = (count) => ` <div className=${rootClass}>
|
|
14
18
|
<Typography.Title view='medium' tag='h1' className=${titleClass}>
|
|
15
|
-
{
|
|
19
|
+
{appName}
|
|
16
20
|
</Typography.Title>
|
|
17
|
-
|
|
18
21
|
<Gap size={16} />
|
|
19
|
-
|
|
20
22
|
<Typography.Text view='primary-medium'>Счетчик: {${count}}</Typography.Text>
|
|
21
|
-
|
|
22
23
|
<Gap size={16} />`;
|
|
23
24
|
if (ctx.useRtk) {
|
|
24
25
|
return `import React from 'react';
|
|
25
26
|
|
|
26
27
|
${coreImports}
|
|
27
28
|
|
|
28
|
-
import { useAppDispatch, useAppSelector } from '../store/hooks';
|
|
29
29
|
import { decrement, increment } from '../store/counter-slice';
|
|
30
|
+
import { useAppDispatch, useAppSelector } from '../store/hooks';
|
|
30
31
|
|
|
31
32
|
${styleImport}
|
|
32
33
|
|
|
34
|
+
const appName = ${appNameLiteral};
|
|
35
|
+
|
|
33
36
|
export function App() {
|
|
34
37
|
const count = useAppSelector((state) => state.counter.value);
|
|
35
38
|
const dispatch = useAppDispatch();
|
|
36
39
|
|
|
37
40
|
return (
|
|
38
41
|
${view('count')}
|
|
39
|
-
|
|
40
42
|
<Button view='accent' size={48} onClick={() => dispatch(increment())}>
|
|
41
43
|
+1
|
|
42
44
|
</Button>{' '}
|
|
@@ -54,12 +56,13 @@ ${coreImports}
|
|
|
54
56
|
|
|
55
57
|
${styleImport}
|
|
56
58
|
|
|
59
|
+
const appName = ${appNameLiteral};
|
|
60
|
+
|
|
57
61
|
export function App() {
|
|
58
62
|
const [count, setCount] = useState(0);
|
|
59
63
|
|
|
60
64
|
return (
|
|
61
65
|
${view('count')}
|
|
62
|
-
|
|
63
66
|
<Button view='accent' size={48} onClick={() => setCount((prev) => prev + 1)}>
|
|
64
67
|
+1
|
|
65
68
|
</Button>{' '}
|
|
@@ -8,24 +8,22 @@ function appStylesFileName(ctx) {
|
|
|
8
8
|
function appStylesTemplate(ctx) {
|
|
9
9
|
if (ctx.cssModules) {
|
|
10
10
|
return `.root {
|
|
11
|
-
padding:
|
|
12
|
-
font-family: sans-serif;
|
|
11
|
+
padding: var(--gap-16);
|
|
13
12
|
}
|
|
14
13
|
|
|
15
14
|
.title {
|
|
16
|
-
margin: 0 0
|
|
17
|
-
|
|
15
|
+
margin: var(--gap-0) var(--gap-0) var(--gap-12);
|
|
16
|
+
@mixin headline_small;
|
|
18
17
|
}
|
|
19
18
|
`;
|
|
20
19
|
}
|
|
21
20
|
return `.app {
|
|
22
|
-
padding:
|
|
23
|
-
font-family: sans-serif;
|
|
21
|
+
padding: var(--gap-16);
|
|
24
22
|
}
|
|
25
23
|
|
|
26
24
|
.app__title {
|
|
27
|
-
margin: 0 0
|
|
28
|
-
|
|
25
|
+
margin: var(--gap-0) var(--gap-0) var(--gap-12);
|
|
26
|
+
@mixin headline_small;
|
|
29
27
|
}
|
|
30
28
|
`;
|
|
31
29
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.aruiScriptsConfigTemplate = aruiScriptsConfigTemplate;
|
|
4
|
-
// Безопасная вставка строки в конфиг
|
|
4
|
+
// Безопасная вставка строки в конфиг (одинарные кавычки как у prettier)
|
|
5
5
|
function tsString(value) {
|
|
6
|
-
return
|
|
6
|
+
return `'${value.replace(/\\/g, '\\\\').replace(/'/g, "\\'")}'`;
|
|
7
7
|
}
|
|
8
8
|
function aruiScriptsConfigTemplate(ctx) {
|
|
9
9
|
const lines = [];
|
|
@@ -3,10 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.clientEntryTemplate = clientEntryTemplate;
|
|
4
4
|
const HMR_BLOCK = `if (process.env.NODE_ENV !== 'production' && module.hot) {
|
|
5
5
|
module.hot.accept('./components/app', () => {
|
|
6
|
-
|
|
7
|
-
const NextApp = require('./components/app').App;
|
|
6
|
+
const mod = require('./components/app') as { App: typeof App };
|
|
8
7
|
|
|
9
|
-
render(
|
|
8
|
+
render(mod.App);
|
|
10
9
|
});
|
|
11
10
|
}
|
|
12
11
|
`;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.eslintConfigTemplate = eslintConfigTemplate;
|
|
4
|
+
exports.knipConfigTemplate = knipConfigTemplate;
|
|
5
|
+
exports.secretlintConfigTemplate = secretlintConfigTemplate;
|
|
6
|
+
exports.lefthookConfigTemplate = lefthookConfigTemplate;
|
|
7
|
+
function eslintConfigTemplate() {
|
|
8
|
+
return `import { defineConfig, eslintConfig, TYPESCRIPT_SCRIPTS_SCOPE } from 'arui-presets-lint/eslint';
|
|
9
|
+
|
|
10
|
+
export default defineConfig(eslintConfig, [
|
|
11
|
+
{
|
|
12
|
+
languageOptions: {
|
|
13
|
+
parserOptions: {
|
|
14
|
+
projectService: {
|
|
15
|
+
allowDefaultProject: [
|
|
16
|
+
'arui-scripts.config.ts',
|
|
17
|
+
'eslint.config.mts',
|
|
18
|
+
'knip.ts',
|
|
19
|
+
'vitest.config.ts',
|
|
20
|
+
],
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
files: [TYPESCRIPT_SCRIPTS_SCOPE],
|
|
25
|
+
},
|
|
26
|
+
]);
|
|
27
|
+
`;
|
|
28
|
+
}
|
|
29
|
+
function knipConfigTemplate() {
|
|
30
|
+
return `import baseConfig from 'arui-presets-lint/knip';
|
|
31
|
+
|
|
32
|
+
export default {
|
|
33
|
+
...baseConfig,
|
|
34
|
+
// ts-jest подключается через jest.preset arui-scripts, прямых импортов в коде нет
|
|
35
|
+
ignoreDependencies: [...baseConfig.ignoreDependencies, 'ts-jest'],
|
|
36
|
+
};
|
|
37
|
+
`;
|
|
38
|
+
}
|
|
39
|
+
function secretlintConfigTemplate() {
|
|
40
|
+
return `${JSON.stringify({
|
|
41
|
+
rules: [
|
|
42
|
+
{
|
|
43
|
+
id: '@secretlint/secretlint-rule-preset-recommend',
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
}, null, 4)}\n`;
|
|
47
|
+
}
|
|
48
|
+
function lefthookConfigTemplate() {
|
|
49
|
+
return `extends:
|
|
50
|
+
- ./node_modules/arui-presets-lint/lefthook/index.yml
|
|
51
|
+
`;
|
|
52
|
+
}
|
|
@@ -57,6 +57,13 @@ defaultSemverRangePrefix: ""
|
|
|
57
57
|
}
|
|
58
58
|
function readmeTemplate(ctx) {
|
|
59
59
|
const testCommand = ctx.testRunner === 'jest' ? 'arui-scripts test' : 'arui-scripts test:vitest';
|
|
60
|
+
const lintSection = ctx.useLint
|
|
61
|
+
? `
|
|
62
|
+
yarn lint - eslint, stylelint, prettier, knip, secretlint
|
|
63
|
+
yarn lint:fix - автофикс eslint/stylelint + format
|
|
64
|
+
yarn format - prettier
|
|
65
|
+
`
|
|
66
|
+
: '';
|
|
60
67
|
return `# ${ctx.name}
|
|
61
68
|
|
|
62
69
|
Проект создан с помощью arui-scripts.
|
|
@@ -65,8 +72,7 @@ function readmeTemplate(ctx) {
|
|
|
65
72
|
|
|
66
73
|
arui-scripts start - запуск dev-сервера
|
|
67
74
|
arui-scripts build - production-сборка
|
|
68
|
-
${testCommand}${' '.repeat(Math.max(1, 20 - testCommand.length))}- запуск
|
|
69
|
-
|
|
75
|
+
${testCommand}${' '.repeat(Math.max(1, 20 - testCommand.length))}- запуск тестов${lintSection}
|
|
70
76
|
## Установка
|
|
71
77
|
|
|
72
78
|
yarn install
|
|
@@ -18,6 +18,19 @@ function packageJsonTemplate(ctx) {
|
|
|
18
18
|
if (ctx.dockerRegistry) {
|
|
19
19
|
scripts['docker-build'] = 'arui-scripts docker-build';
|
|
20
20
|
}
|
|
21
|
+
if (ctx.useLint) {
|
|
22
|
+
scripts['lint:styles'] = 'arui-presets-lint styles --max-warnings=0';
|
|
23
|
+
scripts['lint:scripts'] = 'arui-presets-lint scripts --max-warnings=0';
|
|
24
|
+
scripts.format = 'arui-presets-lint format';
|
|
25
|
+
scripts['format:check'] = 'arui-presets-lint format:check';
|
|
26
|
+
scripts['lint:unused'] = 'arui-presets-lint knip';
|
|
27
|
+
scripts['lint:unused:fix'] = 'arui-presets-lint knip --fix';
|
|
28
|
+
scripts['lint:secrets'] = 'arui-presets-lint secretlint';
|
|
29
|
+
scripts.lint =
|
|
30
|
+
'yarn lint:styles && yarn lint:scripts && yarn format:check && yarn lint:unused && yarn lint:secrets';
|
|
31
|
+
scripts['lint:fix'] =
|
|
32
|
+
'yarn lint:styles --fix && yarn lint:scripts --fix && yarn format && yarn lint:secrets';
|
|
33
|
+
}
|
|
21
34
|
const pkg = {
|
|
22
35
|
name: ctx.name,
|
|
23
36
|
version: '0.1.0',
|
|
@@ -27,6 +40,11 @@ function packageJsonTemplate(ctx) {
|
|
|
27
40
|
node: '>=24.11.1',
|
|
28
41
|
},
|
|
29
42
|
};
|
|
43
|
+
if (ctx.useLint) {
|
|
44
|
+
pkg.prettier = 'arui-presets-lint/prettier';
|
|
45
|
+
pkg.stylelint = { extends: 'arui-presets-lint/stylelint' };
|
|
46
|
+
pkg.commitlint = { extends: './node_modules/arui-presets-lint/commitlint' };
|
|
47
|
+
}
|
|
30
48
|
if (ctx.testRunner === 'jest') {
|
|
31
49
|
pkg.jest = { preset: 'arui-scripts' };
|
|
32
50
|
}
|
|
@@ -6,38 +6,17 @@ function serverEntryTemplate(ctx) {
|
|
|
6
6
|
const storeImport = ctx.useRtk ? "\nimport { makeStore } from '../client/store';" : '';
|
|
7
7
|
const renderPageFn = ctx.useRtk
|
|
8
8
|
? `function renderPage(appHtml: string, assets: Assets, preloadedState: string): string {
|
|
9
|
-
const css = assets.css
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const js = assets.js.map((src) => '<script src="/' + src + '"></script>').join('');
|
|
13
|
-
const state = '<script>window.__PRELOADED_STATE__ = ' + preloadedState + ';</script>';
|
|
9
|
+
const css = assets.css.map((href) => \`<link rel="stylesheet" href="/\${href}" />\`).join('');
|
|
10
|
+
const js = assets.js.map((src) => \`<script src="/\${src}"></script>\`).join('');
|
|
11
|
+
const state = \`<script>window.__PRELOADED_STATE__ = \${preloadedState};</script>\`;
|
|
14
12
|
|
|
15
|
-
return
|
|
16
|
-
'<!DOCTYPE html><html lang="ru"><head><meta charset="utf-8" /><base href="/" />' +
|
|
17
|
-
css +
|
|
18
|
-
'</head><body><div id="react-app">' +
|
|
19
|
-
appHtml +
|
|
20
|
-
'</div>' +
|
|
21
|
-
state +
|
|
22
|
-
js +
|
|
23
|
-
'</body></html>'
|
|
24
|
-
);
|
|
13
|
+
return \`<!DOCTYPE html><html lang="ru"><head><meta charset="utf-8" /><base href="/" />\${css}</head><body><div id="react-app">\${appHtml}</div>\${state}\${js}</body></html>\`;
|
|
25
14
|
}`
|
|
26
15
|
: `function renderPage(appHtml: string, assets: Assets): string {
|
|
27
|
-
const css = assets.css
|
|
28
|
-
|
|
29
|
-
.join('');
|
|
30
|
-
const js = assets.js.map((src) => '<script src="/' + src + '"></script>').join('');
|
|
16
|
+
const css = assets.css.map((href) => \`<link rel="stylesheet" href="/\${href}" />\`).join('');
|
|
17
|
+
const js = assets.js.map((src) => \`<script src="/\${src}"></script>\`).join('');
|
|
31
18
|
|
|
32
|
-
return
|
|
33
|
-
'<!DOCTYPE html><html lang="ru"><head><meta charset="utf-8" /><base href="/" />' +
|
|
34
|
-
css +
|
|
35
|
-
'</head><body><div id="react-app">' +
|
|
36
|
-
appHtml +
|
|
37
|
-
'</div>' +
|
|
38
|
-
js +
|
|
39
|
-
'</body></html>'
|
|
40
|
-
);
|
|
19
|
+
return \`<!DOCTYPE html><html lang="ru"><head><meta charset="utf-8" /><base href="/" />\${css}</head><body><div id="react-app">\${appHtml}</div>\${js}</body></html>\`;
|
|
41
20
|
}`;
|
|
42
21
|
const handlerBody = ctx.useRtk
|
|
43
22
|
? ` const assets = await readAssetsManifest();
|
|
@@ -55,12 +34,11 @@ function serverEntryTemplate(ctx) {
|
|
|
55
34
|
const appHtml = renderToString(<App />);
|
|
56
35
|
|
|
57
36
|
return renderPage(appHtml, assets);`;
|
|
58
|
-
return `import
|
|
59
|
-
|
|
37
|
+
return `import React from 'react';
|
|
38
|
+
import { renderToString } from 'react-dom/server';${reduxImport}
|
|
60
39
|
import Hapi from '@hapi/hapi';
|
|
61
40
|
import Inert from '@hapi/inert';
|
|
62
|
-
import
|
|
63
|
-
import { renderToString } from 'react-dom/server';${reduxImport}
|
|
41
|
+
import path from 'node:path';
|
|
64
42
|
|
|
65
43
|
import { readAssetsManifest } from '@alfalab/scripts-server';
|
|
66
44
|
|
|
@@ -106,10 +84,10 @@ ${handlerBody}
|
|
|
106
84
|
});
|
|
107
85
|
|
|
108
86
|
await server.start();
|
|
109
|
-
// eslint-disable-next-line no-console
|
|
110
|
-
console.log(
|
|
87
|
+
// eslint-disable-next-line no-console -- стартовый лог dev-сервера
|
|
88
|
+
console.log(\`Server is listening on \${server.info.uri}\`);
|
|
111
89
|
}
|
|
112
90
|
|
|
113
|
-
start();
|
|
91
|
+
void start();
|
|
114
92
|
`;
|
|
115
93
|
}
|
|
@@ -2,13 +2,15 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.tsconfigTemplate = tsconfigTemplate;
|
|
4
4
|
function tsconfigTemplate(ctx) {
|
|
5
|
-
const types = ctx.testRunner === 'jest'
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
5
|
+
const types = ctx.testRunner === 'jest'
|
|
6
|
+
? '["jest", "node", "webpack-env"]'
|
|
7
|
+
: '["node", "webpack-env"]';
|
|
8
|
+
return `{
|
|
9
|
+
"extends": "arui-scripts/tsconfig.json",
|
|
10
|
+
"include": ["global-definitions.d.ts", "src/**/*.ts", "src/**/*.tsx"],
|
|
11
|
+
"compilerOptions": {
|
|
12
|
+
"types": ${types}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
`;
|
|
14
16
|
}
|
package/build/types.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export type InitAnswers = {
|
|
|
13
13
|
presets: string;
|
|
14
14
|
polyfills: boolean;
|
|
15
15
|
reactCompiler: boolean;
|
|
16
|
+
useLint: boolean;
|
|
16
17
|
install: boolean;
|
|
17
18
|
};
|
|
18
19
|
export type TemplateContext = {
|
|
@@ -28,6 +29,7 @@ export type TemplateContext = {
|
|
|
28
29
|
presets: string;
|
|
29
30
|
polyfills: boolean;
|
|
30
31
|
reactCompiler: boolean;
|
|
32
|
+
useLint: boolean;
|
|
31
33
|
aruiScriptsVersion: string;
|
|
32
34
|
dependencies: Record<string, string>;
|
|
33
35
|
devDependencies: Record<string, string>;
|
package/build/versions.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
/** Версия arui-scripts, которую scaffold кладёт в package.json нового проекта.
|
|
2
2
|
* Генерируется скриптом scripts/sync-arui-scripts-version.js при сборке.
|
|
3
3
|
*/
|
|
4
|
-
export declare const DEFAULT_ARUI_SCRIPTS_VERSION = "23.
|
|
4
|
+
export declare const DEFAULT_ARUI_SCRIPTS_VERSION = "23.3.1";
|
package/build/versions.js
CHANGED
|
@@ -4,4 +4,4 @@ exports.DEFAULT_ARUI_SCRIPTS_VERSION = void 0;
|
|
|
4
4
|
/** Версия arui-scripts, которую scaffold кладёт в package.json нового проекта.
|
|
5
5
|
* Генерируется скриптом scripts/sync-arui-scripts-version.js при сборке.
|
|
6
6
|
*/
|
|
7
|
-
exports.DEFAULT_ARUI_SCRIPTS_VERSION = '23.
|
|
7
|
+
exports.DEFAULT_ARUI_SCRIPTS_VERSION = '23.3.1';
|
package/package.json
CHANGED
|
@@ -1,56 +1,56 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
2
|
+
"name": "create-arui-scripts-app",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "CLI для генерации нового react приложения на arui-scripts",
|
|
5
|
+
"license": "MPL-2.0",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/core-ds/arui-scripts.git"
|
|
9
|
+
},
|
|
10
|
+
"bugs": {
|
|
11
|
+
"url": "https://github.com/core-ds/arui-scripts/issues"
|
|
12
|
+
},
|
|
13
|
+
"homepage": "https://github.com/core-ds/arui-scripts/tree/master/packages/create-arui-scripts-app#readme",
|
|
14
|
+
"bin": "./bin/create-arui-scripts-app.js",
|
|
15
|
+
"main": "./build/run.js",
|
|
16
|
+
"typings": "./build/run.d.ts",
|
|
17
|
+
"files": [
|
|
18
|
+
"assets",
|
|
19
|
+
"bin",
|
|
20
|
+
"build"
|
|
21
|
+
],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"sync:version": "node ./scripts/sync-arui-scripts-version.js",
|
|
24
|
+
"build": "yarn sync:version && tsc --project tsconfig.json",
|
|
25
|
+
"test": "jest",
|
|
26
|
+
"lint:scripts": "arui-presets-lint scripts",
|
|
27
|
+
"format": "arui-presets-lint format",
|
|
28
|
+
"format:check": "arui-presets-lint format:check",
|
|
29
|
+
"lint": "yarn lint:scripts && yarn format:check",
|
|
30
|
+
"lint:fix": "yarn lint:scripts --fix && yarn format",
|
|
31
|
+
"audit": "yarn npm audit --severity high --environment production"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"chalk": "^2.4.2",
|
|
35
|
+
"commander": "^12",
|
|
36
|
+
"fs-extra": "6.0.1",
|
|
37
|
+
"ora": "^5",
|
|
38
|
+
"prompts": "^2.4.2",
|
|
39
|
+
"shelljs": "0.8.5",
|
|
40
|
+
"validate-npm-package-name": "^5.0.1"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@types/fs-extra": "^9.0.13",
|
|
44
|
+
"@types/jest": "^29.5.14",
|
|
45
|
+
"@types/node": "^20.19.0",
|
|
46
|
+
"@types/prompts": "^2.4.9",
|
|
47
|
+
"@types/shelljs": "^0.8.12",
|
|
48
|
+
"@types/validate-npm-package-name": "^3.0.3",
|
|
49
|
+
"jest": "28.1.3",
|
|
50
|
+
"ts-jest": "28.0.8",
|
|
51
|
+
"typescript": "6.0.2"
|
|
52
|
+
},
|
|
53
|
+
"engines": {
|
|
54
|
+
"node": "^20.19.0 || >=22.12.0"
|
|
55
|
+
}
|
|
56
|
+
}
|