create-arui-scripts-app 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +58 -0
- package/assets/.yarn/releases/yarn-4.9.1.cjs +948 -0
- package/bin/create-arui-scripts-app.js +3 -0
- package/build/build-context.d.ts +2 -0
- package/build/build-context.js +83 -0
- package/build/build-file-map.d.ts +3 -0
- package/build/build-file-map.js +49 -0
- package/build/cli.d.ts +1 -0
- package/build/cli.js +15 -0
- package/build/create-program.d.ts +5 -0
- package/build/create-program.js +103 -0
- package/build/defaults.d.ts +21 -0
- package/build/defaults.js +48 -0
- package/build/install-dependencies.d.ts +3 -0
- package/build/install-dependencies.js +39 -0
- package/build/questions.d.ts +3 -0
- package/build/questions.js +126 -0
- package/build/run.d.ts +9 -0
- package/build/run.js +191 -0
- package/build/templates/app-component.template.d.ts +2 -0
- package/build/templates/app-component.template.js +73 -0
- package/build/templates/app-styles.template.d.ts +3 -0
- package/build/templates/app-styles.template.js +31 -0
- package/build/templates/app-test.template.d.ts +2 -0
- package/build/templates/app-test.template.js +14 -0
- package/build/templates/arui-scripts-config.template.d.ts +2 -0
- package/build/templates/arui-scripts-config.template.js +46 -0
- package/build/templates/client-entry.template.d.ts +2 -0
- package/build/templates/client-entry.template.js +105 -0
- package/build/templates/misc.template.d.ts +6 -0
- package/build/templates/misc.template.js +74 -0
- package/build/templates/package-json.template.d.ts +2 -0
- package/build/templates/package-json.template.js +36 -0
- package/build/templates/server-entry.template.d.ts +2 -0
- package/build/templates/server-entry.template.js +115 -0
- package/build/templates/store.template.d.ts +3 -0
- package/build/templates/store.template.js +63 -0
- package/build/templates/tsconfig.template.d.ts +2 -0
- package/build/templates/tsconfig.template.js +14 -0
- package/build/templates/vitest-config.template.d.ts +1 -0
- package/build/templates/vitest-config.template.js +18 -0
- package/build/types.d.ts +34 -0
- package/build/types.js +2 -0
- package/build/validate-project-name.d.ts +1 -0
- package/build/validate-project-name.js +20 -0
- package/build/versions.d.ts +4 -0
- package/build/versions.js +7 -0
- package/build/write-files.d.ts +4 -0
- package/build/write-files.js +59 -0
- package/package.json +56 -0
package/build/run.js
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.runInit = runInit;
|
|
16
|
+
exports.resolveCdPath = resolveCdPath;
|
|
17
|
+
/* eslint-disable no-console */
|
|
18
|
+
const path_1 = __importDefault(require("path"));
|
|
19
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
20
|
+
const ora_1 = __importDefault(require("ora"));
|
|
21
|
+
const prompts_1 = __importDefault(require("prompts"));
|
|
22
|
+
const build_context_1 = require("./build-context");
|
|
23
|
+
const build_file_map_1 = require("./build-file-map");
|
|
24
|
+
const defaults_1 = require("./defaults");
|
|
25
|
+
const install_dependencies_1 = require("./install-dependencies");
|
|
26
|
+
const questions_1 = require("./questions");
|
|
27
|
+
const validate_project_name_1 = require("./validate-project-name");
|
|
28
|
+
const versions_1 = require("./versions");
|
|
29
|
+
const write_files_1 = require("./write-files");
|
|
30
|
+
// eslint-disable-next-line global-require, @typescript-eslint/no-var-requires
|
|
31
|
+
const { version: cliVersion } = require('../package.json');
|
|
32
|
+
function runInit() {
|
|
33
|
+
return __awaiter(this, arguments, void 0, function* (options = {}) {
|
|
34
|
+
var _a, _b, _c;
|
|
35
|
+
const baseCwd = (_a = options.cwd) !== null && _a !== void 0 ? _a : process.cwd();
|
|
36
|
+
const targetDir = options.targetDirArg ? path_1.default.resolve(baseCwd, options.targetDirArg) : baseCwd;
|
|
37
|
+
const defaultName = path_1.default.basename(targetDir);
|
|
38
|
+
const aruiScriptsVersion = (_b = options.aruiScriptsVersion) !== null && _b !== void 0 ? _b : versions_1.DEFAULT_ARUI_SCRIPTS_VERSION;
|
|
39
|
+
const flags = (_c = options.flags) !== null && _c !== void 0 ? _c : {};
|
|
40
|
+
printBanner();
|
|
41
|
+
const initAnswers = yield resolveAnswers(defaultName, flags);
|
|
42
|
+
const nameError = (0, validate_project_name_1.validateProjectName)(initAnswers.name);
|
|
43
|
+
if (nameError !== true) {
|
|
44
|
+
throw new Error(nameError);
|
|
45
|
+
}
|
|
46
|
+
const context = (0, build_context_1.buildContext)(initAnswers, aruiScriptsVersion);
|
|
47
|
+
const files = (0, build_file_map_1.buildFileMap)(context);
|
|
48
|
+
const conflicts = yield (0, write_files_1.findConflictingFiles)(targetDir, files, write_files_1.STATIC_ASSET_PATHS);
|
|
49
|
+
if (conflicts.length > 0 && !flags.force) {
|
|
50
|
+
throw new Error([
|
|
51
|
+
`В ${targetDir} уже есть файлы, которые мастер хочет создать:`,
|
|
52
|
+
...conflicts.map((file) => ` - ${file}`),
|
|
53
|
+
'Передайте --force, чтобы перезаписать, или выберите пустую папку.',
|
|
54
|
+
].join('\n'));
|
|
55
|
+
}
|
|
56
|
+
yield (0, write_files_1.writeFiles)(targetDir, files);
|
|
57
|
+
const assetsCount = yield (0, write_files_1.copyStaticAssets)(targetDir);
|
|
58
|
+
printSuccess(context, targetDir, Object.keys(files).length + assetsCount);
|
|
59
|
+
const packageManager = (0, install_dependencies_1.detectPackageManager)();
|
|
60
|
+
if (initAnswers.install) {
|
|
61
|
+
const spinner = (0, ora_1.default)({ text: 'Устанавливаю зависимости…', color: 'cyan' }).start();
|
|
62
|
+
try {
|
|
63
|
+
yield (0, install_dependencies_1.installDependencies)(targetDir, packageManager);
|
|
64
|
+
spinner.succeed(chalk_1.default.green('Зависимости установлены'));
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
spinner.fail(chalk_1.default.red('Не удалось установить зависимости'));
|
|
68
|
+
throw error;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
printNextSteps(targetDir, baseCwd, initAnswers, packageManager);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
function resolveAnswers(defaultName, flags) {
|
|
75
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
76
|
+
const base = (0, defaults_1.answersFromFlags)(defaultName, flags);
|
|
77
|
+
if (flags.yes) {
|
|
78
|
+
return base;
|
|
79
|
+
}
|
|
80
|
+
if (!process.stdin.isTTY) {
|
|
81
|
+
if ((0, defaults_1.hasAnswerFlags)(flags)) {
|
|
82
|
+
return base;
|
|
83
|
+
}
|
|
84
|
+
throw new Error('Интерактивный режим недоступен. Передайте --yes или явные флаги настроек.');
|
|
85
|
+
}
|
|
86
|
+
let cancelled = false;
|
|
87
|
+
// Вопросы, отвеченные флагами, пропускаются — мастер задаст только остальные.
|
|
88
|
+
const answers = yield (0, prompts_1.default)((0, questions_1.getQuestions)(defaultName, flags), {
|
|
89
|
+
onCancel: () => {
|
|
90
|
+
cancelled = true;
|
|
91
|
+
return false;
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
if (cancelled) {
|
|
95
|
+
throw new Error('Отменено.');
|
|
96
|
+
}
|
|
97
|
+
return mergePromptAnswers(base, answers);
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
// Накладывает ответы мастера поверх базовых значений (флаги + дефолты)
|
|
101
|
+
function mergePromptAnswers(base, answers) {
|
|
102
|
+
const merged = Object.assign({}, base);
|
|
103
|
+
if (answers.name !== undefined) {
|
|
104
|
+
merged.name = String(answers.name).trim();
|
|
105
|
+
}
|
|
106
|
+
if (answers.useRtk !== undefined) {
|
|
107
|
+
merged.useRtk = Boolean(answers.useRtk);
|
|
108
|
+
}
|
|
109
|
+
if (answers.clientOnly !== undefined) {
|
|
110
|
+
merged.clientOnly = Boolean(answers.clientOnly);
|
|
111
|
+
}
|
|
112
|
+
if (answers.codeLoader !== undefined) {
|
|
113
|
+
merged.codeLoader = answers.codeLoader;
|
|
114
|
+
}
|
|
115
|
+
if (answers.testRunner !== undefined) {
|
|
116
|
+
merged.testRunner = answers.testRunner;
|
|
117
|
+
}
|
|
118
|
+
if (answers.cssModules !== undefined) {
|
|
119
|
+
merged.cssModules = Boolean(answers.cssModules);
|
|
120
|
+
}
|
|
121
|
+
if (answers.clientServerPort !== undefined) {
|
|
122
|
+
merged.clientServerPort = Number(answers.clientServerPort) || 8080;
|
|
123
|
+
}
|
|
124
|
+
if (answers.serverPort !== undefined) {
|
|
125
|
+
merged.serverPort = Number(answers.serverPort) || 3000;
|
|
126
|
+
}
|
|
127
|
+
if (answers.dockerRegistry !== undefined) {
|
|
128
|
+
merged.dockerRegistry = String(answers.dockerRegistry);
|
|
129
|
+
}
|
|
130
|
+
if (answers.presets !== undefined) {
|
|
131
|
+
merged.presets = String(answers.presets);
|
|
132
|
+
}
|
|
133
|
+
if (answers.polyfills !== undefined) {
|
|
134
|
+
merged.polyfills = Boolean(answers.polyfills);
|
|
135
|
+
}
|
|
136
|
+
if (answers.reactCompiler !== undefined) {
|
|
137
|
+
merged.reactCompiler = Boolean(answers.reactCompiler);
|
|
138
|
+
}
|
|
139
|
+
if (answers.install !== undefined) {
|
|
140
|
+
merged.install = Boolean(answers.install);
|
|
141
|
+
}
|
|
142
|
+
return merged;
|
|
143
|
+
}
|
|
144
|
+
function printBanner() {
|
|
145
|
+
console.log();
|
|
146
|
+
console.log(` ${chalk_1.default.bgCyan.black.bold(' create-arui-scripts-app ')} ${chalk_1.default.dim(`v${cliVersion}`)}`);
|
|
147
|
+
console.log(` ${chalk_1.default.dim('Создаем новый проект - ответьте на несколько вопросов.')}`);
|
|
148
|
+
console.log();
|
|
149
|
+
}
|
|
150
|
+
function printSuccess(context, targetDir, fileCount) {
|
|
151
|
+
const stack = [
|
|
152
|
+
chalk_1.default.cyan(context.useRtk ? 'React + RTK' : 'React'),
|
|
153
|
+
chalk_1.default.dim(context.clientOnly ? 'clientOnly' : 'SSR'),
|
|
154
|
+
chalk_1.default.dim(context.codeLoader),
|
|
155
|
+
chalk_1.default.dim(context.testRunner),
|
|
156
|
+
].join(chalk_1.default.dim(' · '));
|
|
157
|
+
console.log();
|
|
158
|
+
console.log(` ${chalk_1.default.green('✔')} ${chalk_1.default.bold('Готово!')} ${chalk_1.default.dim(`проект «${context.name}» создан`)}`);
|
|
159
|
+
console.log(` ${chalk_1.default.dim(targetDir)}`);
|
|
160
|
+
console.log(` ${chalk_1.default.dim(`${fileCount} файлов`)} ${chalk_1.default.dim('·')} ${stack}`);
|
|
161
|
+
}
|
|
162
|
+
// Путь для подсказки `cd`: null — цель совпадает с cwd, а относительный — если цель внутри cwd, иначе берем абсолютный
|
|
163
|
+
function resolveCdPath(baseCwd, targetDir) {
|
|
164
|
+
const relativeDir = path_1.default.relative(baseCwd, targetDir);
|
|
165
|
+
if (!relativeDir) {
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
if (relativeDir.startsWith('..') || path_1.default.isAbsolute(relativeDir)) {
|
|
169
|
+
return targetDir;
|
|
170
|
+
}
|
|
171
|
+
return relativeDir;
|
|
172
|
+
}
|
|
173
|
+
function printNextSteps(targetDir, baseCwd, answers, packageManager) {
|
|
174
|
+
const cdPath = resolveCdPath(baseCwd, targetDir);
|
|
175
|
+
const installCommand = packageManager === 'yarn' ? 'yarn' : 'npm install';
|
|
176
|
+
const startCommand = packageManager === 'yarn' ? 'yarn start' : 'npm start';
|
|
177
|
+
const steps = [];
|
|
178
|
+
if (cdPath) {
|
|
179
|
+
steps.push(`cd ${cdPath}`);
|
|
180
|
+
}
|
|
181
|
+
if (!answers.install) {
|
|
182
|
+
steps.push(installCommand);
|
|
183
|
+
}
|
|
184
|
+
steps.push(startCommand);
|
|
185
|
+
console.log();
|
|
186
|
+
console.log(` ${chalk_1.default.bold('Дальше')}`);
|
|
187
|
+
steps.forEach((step, index) => {
|
|
188
|
+
console.log(` ${chalk_1.default.dim(`${index + 1}.`)} ${chalk_1.default.cyan(step)}`);
|
|
189
|
+
});
|
|
190
|
+
console.log();
|
|
191
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.appComponentTemplate = appComponentTemplate;
|
|
4
|
+
function appComponentTemplate(ctx) {
|
|
5
|
+
const styleImport = ctx.cssModules
|
|
6
|
+
? "import styles from './app.module.css';"
|
|
7
|
+
: "import './app.css';";
|
|
8
|
+
const rootClass = ctx.cssModules ? '{styles.root}' : "'app'";
|
|
9
|
+
const titleClass = ctx.cssModules ? '{styles.title}' : "'app__title'";
|
|
10
|
+
const coreImports = `import { Button } from '@alfalab/core-components/button';
|
|
11
|
+
import { Gap } from '@alfalab/core-components/gap';
|
|
12
|
+
import { Typography } from '@alfalab/core-components/typography';`;
|
|
13
|
+
const view = (count) => ` <div className=${rootClass}>
|
|
14
|
+
<Typography.Title view='medium' tag='h1' className=${titleClass}>
|
|
15
|
+
{${JSON.stringify(ctx.name)}}
|
|
16
|
+
</Typography.Title>
|
|
17
|
+
|
|
18
|
+
<Gap size={16} />
|
|
19
|
+
|
|
20
|
+
<Typography.Text view='primary-medium'>Счетчик: {${count}}</Typography.Text>
|
|
21
|
+
|
|
22
|
+
<Gap size={16} />`;
|
|
23
|
+
if (ctx.useRtk) {
|
|
24
|
+
return `import React from 'react';
|
|
25
|
+
|
|
26
|
+
${coreImports}
|
|
27
|
+
|
|
28
|
+
import { useAppDispatch, useAppSelector } from '../store/hooks';
|
|
29
|
+
import { decrement, increment } from '../store/counter-slice';
|
|
30
|
+
|
|
31
|
+
${styleImport}
|
|
32
|
+
|
|
33
|
+
export function App() {
|
|
34
|
+
const count = useAppSelector((state) => state.counter.value);
|
|
35
|
+
const dispatch = useAppDispatch();
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
${view('count')}
|
|
39
|
+
|
|
40
|
+
<Button view='accent' size={48} onClick={() => dispatch(increment())}>
|
|
41
|
+
+1
|
|
42
|
+
</Button>{' '}
|
|
43
|
+
<Button view='secondary' size={48} onClick={() => dispatch(decrement())}>
|
|
44
|
+
-1
|
|
45
|
+
</Button>
|
|
46
|
+
</div>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
`;
|
|
50
|
+
}
|
|
51
|
+
return `import React, { useState } from 'react';
|
|
52
|
+
|
|
53
|
+
${coreImports}
|
|
54
|
+
|
|
55
|
+
${styleImport}
|
|
56
|
+
|
|
57
|
+
export function App() {
|
|
58
|
+
const [count, setCount] = useState(0);
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
${view('count')}
|
|
62
|
+
|
|
63
|
+
<Button view='accent' size={48} onClick={() => setCount((prev) => prev + 1)}>
|
|
64
|
+
+1
|
|
65
|
+
</Button>{' '}
|
|
66
|
+
<Button view='secondary' size={48} onClick={() => setCount((prev) => prev - 1)}>
|
|
67
|
+
-1
|
|
68
|
+
</Button>
|
|
69
|
+
</div>
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
`;
|
|
73
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.appStylesFileName = appStylesFileName;
|
|
4
|
+
exports.appStylesTemplate = appStylesTemplate;
|
|
5
|
+
function appStylesFileName(ctx) {
|
|
6
|
+
return ctx.cssModules ? 'app.module.css' : 'app.css';
|
|
7
|
+
}
|
|
8
|
+
function appStylesTemplate(ctx) {
|
|
9
|
+
if (ctx.cssModules) {
|
|
10
|
+
return `.root {
|
|
11
|
+
padding: 16px;
|
|
12
|
+
font-family: sans-serif;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.title {
|
|
16
|
+
margin: 0 0 12px;
|
|
17
|
+
font-size: 24px;
|
|
18
|
+
}
|
|
19
|
+
`;
|
|
20
|
+
}
|
|
21
|
+
return `.app {
|
|
22
|
+
padding: 16px;
|
|
23
|
+
font-family: sans-serif;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.app__title {
|
|
27
|
+
margin: 0 0 12px;
|
|
28
|
+
font-size: 24px;
|
|
29
|
+
}
|
|
30
|
+
`;
|
|
31
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.appTestTemplate = appTestTemplate;
|
|
4
|
+
function appTestTemplate(ctx) {
|
|
5
|
+
const vitestImport = ctx.testRunner === 'vitest' ? "import { describe, expect, it } from 'vitest';\n\n" : '';
|
|
6
|
+
return `${vitestImport}import { App } from '../app';
|
|
7
|
+
|
|
8
|
+
describe('App', () => {
|
|
9
|
+
it('описание теста', () => {
|
|
10
|
+
expect(typeof App).toBe('function');
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
`;
|
|
14
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.aruiScriptsConfigTemplate = aruiScriptsConfigTemplate;
|
|
4
|
+
// Безопасная вставка строки в конфиг
|
|
5
|
+
function tsString(value) {
|
|
6
|
+
return JSON.stringify(value);
|
|
7
|
+
}
|
|
8
|
+
function aruiScriptsConfigTemplate(ctx) {
|
|
9
|
+
const lines = [];
|
|
10
|
+
const clientBase = ctx.clientOnly ? './src' : './src/client';
|
|
11
|
+
if (ctx.clientOnly) {
|
|
12
|
+
lines.push(' clientOnly: true,');
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
lines.push(` clientEntry: ${tsString(clientBase)},`);
|
|
16
|
+
}
|
|
17
|
+
lines.push(` componentsTheme: ${tsString('./node_modules/@alfalab/core-components/themes/corp.css')},`);
|
|
18
|
+
if (ctx.codeLoader !== 'swc') {
|
|
19
|
+
lines.push(` codeLoader: ${tsString(ctx.codeLoader)},`);
|
|
20
|
+
}
|
|
21
|
+
if (ctx.clientServerPort !== 8080) {
|
|
22
|
+
lines.push(` clientServerPort: ${ctx.clientServerPort},`);
|
|
23
|
+
}
|
|
24
|
+
if (!ctx.clientOnly && ctx.serverPort !== 3000) {
|
|
25
|
+
lines.push(` serverPort: ${ctx.serverPort},`);
|
|
26
|
+
}
|
|
27
|
+
if (ctx.dockerRegistry) {
|
|
28
|
+
lines.push(` dockerRegistry: ${tsString(ctx.dockerRegistry)},`);
|
|
29
|
+
}
|
|
30
|
+
if (ctx.presets) {
|
|
31
|
+
lines.push(` presets: ${tsString(ctx.presets)},`);
|
|
32
|
+
}
|
|
33
|
+
if (ctx.polyfills) {
|
|
34
|
+
lines.push(` clientPolyfillsEntry: ${tsString(`${clientBase}/polyfills`)},`);
|
|
35
|
+
}
|
|
36
|
+
if (ctx.reactCompiler) {
|
|
37
|
+
lines.push(" experimentalReactCompiler: { target: '19' },");
|
|
38
|
+
}
|
|
39
|
+
const body = lines.length > 0 ? `\n${lines.join('\n')}\n` : '';
|
|
40
|
+
return `import { type PackageSettings } from 'arui-scripts';
|
|
41
|
+
|
|
42
|
+
const config: PackageSettings = {${body}};
|
|
43
|
+
|
|
44
|
+
export default config;
|
|
45
|
+
`;
|
|
46
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.clientEntryTemplate = clientEntryTemplate;
|
|
4
|
+
const HMR_BLOCK = `if (process.env.NODE_ENV !== 'production' && module.hot) {
|
|
5
|
+
module.hot.accept('./components/app', () => {
|
|
6
|
+
// eslint-disable-next-line global-require, @typescript-eslint/no-var-requires
|
|
7
|
+
const NextApp = require('./components/app').App;
|
|
8
|
+
|
|
9
|
+
render(NextApp);
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
`;
|
|
13
|
+
function clientEntryTemplate(ctx) {
|
|
14
|
+
return ctx.clientOnly ? clientOnlyEntryTemplate(ctx) : ssrEntryTemplate(ctx);
|
|
15
|
+
}
|
|
16
|
+
function ssrEntryTemplate(ctx) {
|
|
17
|
+
if (ctx.useRtk) {
|
|
18
|
+
return `import React from 'react';
|
|
19
|
+
import { hydrateRoot } from 'react-dom/client';
|
|
20
|
+
import { Provider } from 'react-redux';
|
|
21
|
+
|
|
22
|
+
import { App } from './components/app';
|
|
23
|
+
import { makeStore, type RootState } from './store';
|
|
24
|
+
|
|
25
|
+
declare global {
|
|
26
|
+
interface Window {
|
|
27
|
+
__PRELOADED_STATE__?: Partial<RootState>;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const store = makeStore(window.__PRELOADED_STATE__);
|
|
32
|
+
const targetElement = document.getElementById('react-app');
|
|
33
|
+
|
|
34
|
+
const root = hydrateRoot(
|
|
35
|
+
targetElement!,
|
|
36
|
+
<Provider store={store}>
|
|
37
|
+
<App />
|
|
38
|
+
</Provider>,
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
function render(AppComponent: typeof App) {
|
|
42
|
+
root.render(
|
|
43
|
+
<Provider store={store}>
|
|
44
|
+
<AppComponent />
|
|
45
|
+
</Provider>,
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
${HMR_BLOCK}`;
|
|
50
|
+
}
|
|
51
|
+
return `import React from 'react';
|
|
52
|
+
import { hydrateRoot } from 'react-dom/client';
|
|
53
|
+
|
|
54
|
+
import { App } from './components/app';
|
|
55
|
+
|
|
56
|
+
const targetElement = document.getElementById('react-app');
|
|
57
|
+
const root = hydrateRoot(targetElement!, <App />);
|
|
58
|
+
|
|
59
|
+
function render(AppComponent: typeof App) {
|
|
60
|
+
root.render(<AppComponent />);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
${HMR_BLOCK}`;
|
|
64
|
+
}
|
|
65
|
+
function clientOnlyEntryTemplate(ctx) {
|
|
66
|
+
if (ctx.useRtk) {
|
|
67
|
+
return `import React from 'react';
|
|
68
|
+
import { createRoot } from 'react-dom/client';
|
|
69
|
+
import { Provider } from 'react-redux';
|
|
70
|
+
|
|
71
|
+
import { App } from './components/app';
|
|
72
|
+
import { makeStore } from './store';
|
|
73
|
+
|
|
74
|
+
const store = makeStore();
|
|
75
|
+
const targetElement = document.getElementById('react-app');
|
|
76
|
+
const root = createRoot(targetElement!);
|
|
77
|
+
|
|
78
|
+
function render(AppComponent: typeof App) {
|
|
79
|
+
root.render(
|
|
80
|
+
<Provider store={store}>
|
|
81
|
+
<AppComponent />
|
|
82
|
+
</Provider>,
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
render(App);
|
|
87
|
+
|
|
88
|
+
${HMR_BLOCK}`;
|
|
89
|
+
}
|
|
90
|
+
return `import React from 'react';
|
|
91
|
+
import { createRoot } from 'react-dom/client';
|
|
92
|
+
|
|
93
|
+
import { App } from './components/app';
|
|
94
|
+
|
|
95
|
+
const targetElement = document.getElementById('react-app');
|
|
96
|
+
const root = createRoot(targetElement!);
|
|
97
|
+
|
|
98
|
+
function render(AppComponent: typeof App) {
|
|
99
|
+
root.render(<AppComponent />);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
render(App);
|
|
103
|
+
|
|
104
|
+
${HMR_BLOCK}`;
|
|
105
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type TemplateContext } from '../types';
|
|
2
|
+
export declare function gitignoreTemplate(): string;
|
|
3
|
+
export declare function globalDefinitionsTemplate(): string;
|
|
4
|
+
export declare function polyfillsTemplate(): string;
|
|
5
|
+
export declare function yarnrcTemplate(): string;
|
|
6
|
+
export declare function readmeTemplate(ctx: TemplateContext): string;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.gitignoreTemplate = gitignoreTemplate;
|
|
4
|
+
exports.globalDefinitionsTemplate = globalDefinitionsTemplate;
|
|
5
|
+
exports.polyfillsTemplate = polyfillsTemplate;
|
|
6
|
+
exports.yarnrcTemplate = yarnrcTemplate;
|
|
7
|
+
exports.readmeTemplate = readmeTemplate;
|
|
8
|
+
function gitignoreTemplate() {
|
|
9
|
+
return `node_modules
|
|
10
|
+
.build
|
|
11
|
+
build.tar
|
|
12
|
+
.cache-loader
|
|
13
|
+
|
|
14
|
+
.pnp.*
|
|
15
|
+
.yarn/*
|
|
16
|
+
!.yarn/patches
|
|
17
|
+
!.yarn/plugins
|
|
18
|
+
!.yarn/releases
|
|
19
|
+
!.yarn/sdks
|
|
20
|
+
!.yarn/versions
|
|
21
|
+
`;
|
|
22
|
+
}
|
|
23
|
+
function globalDefinitionsTemplate() {
|
|
24
|
+
return `declare module '*.png' {
|
|
25
|
+
const url: string;
|
|
26
|
+
export default url;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
declare module '*.svg' {
|
|
30
|
+
const url: string;
|
|
31
|
+
export default url;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
declare module '*.module.css' {
|
|
35
|
+
const styles: Record<string, string>;
|
|
36
|
+
export default styles;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
declare module '*.css';
|
|
40
|
+
`;
|
|
41
|
+
}
|
|
42
|
+
function polyfillsTemplate() {
|
|
43
|
+
return "import 'core-js/stable';\n";
|
|
44
|
+
}
|
|
45
|
+
function yarnrcTemplate() {
|
|
46
|
+
return `nodeLinker: node-modules
|
|
47
|
+
|
|
48
|
+
npmRegistryServer: "http://binary/artifactory/api/npm/npm/"
|
|
49
|
+
|
|
50
|
+
unsafeHttpWhitelist:
|
|
51
|
+
- binary
|
|
52
|
+
|
|
53
|
+
yarnPath: .yarn/releases/yarn-4.9.1.cjs
|
|
54
|
+
|
|
55
|
+
defaultSemverRangePrefix: ""
|
|
56
|
+
`;
|
|
57
|
+
}
|
|
58
|
+
function readmeTemplate(ctx) {
|
|
59
|
+
const testCommand = ctx.testRunner === 'jest' ? 'arui-scripts test' : 'arui-scripts test:vitest';
|
|
60
|
+
return `# ${ctx.name}
|
|
61
|
+
|
|
62
|
+
Проект создан с помощью arui-scripts.
|
|
63
|
+
|
|
64
|
+
## Команды
|
|
65
|
+
|
|
66
|
+
arui-scripts start - запуск dev-сервера
|
|
67
|
+
arui-scripts build - production-сборка
|
|
68
|
+
${testCommand}${' '.repeat(Math.max(1, 20 - testCommand.length))}- запуск тестов
|
|
69
|
+
|
|
70
|
+
## Установка
|
|
71
|
+
|
|
72
|
+
yarn install
|
|
73
|
+
`;
|
|
74
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.packageJsonTemplate = packageJsonTemplate;
|
|
4
|
+
function sortKeys(record) {
|
|
5
|
+
return Object.keys(record)
|
|
6
|
+
.sort()
|
|
7
|
+
.reduce((acc, key) => {
|
|
8
|
+
acc[key] = record[key];
|
|
9
|
+
return acc;
|
|
10
|
+
}, {});
|
|
11
|
+
}
|
|
12
|
+
function packageJsonTemplate(ctx) {
|
|
13
|
+
const scripts = {
|
|
14
|
+
start: 'arui-scripts start',
|
|
15
|
+
build: 'arui-scripts build',
|
|
16
|
+
test: ctx.testRunner === 'jest' ? 'arui-scripts test' : 'arui-scripts test:vitest',
|
|
17
|
+
};
|
|
18
|
+
if (ctx.dockerRegistry) {
|
|
19
|
+
scripts['docker-build'] = 'arui-scripts docker-build';
|
|
20
|
+
}
|
|
21
|
+
const pkg = {
|
|
22
|
+
name: ctx.name,
|
|
23
|
+
version: '0.1.0',
|
|
24
|
+
private: true,
|
|
25
|
+
scripts,
|
|
26
|
+
engines: {
|
|
27
|
+
node: '>=24.11.1',
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
if (ctx.testRunner === 'jest') {
|
|
31
|
+
pkg.jest = { preset: 'arui-scripts' };
|
|
32
|
+
}
|
|
33
|
+
pkg.dependencies = sortKeys(ctx.dependencies);
|
|
34
|
+
pkg.devDependencies = sortKeys(ctx.devDependencies);
|
|
35
|
+
return `${JSON.stringify(pkg, null, 4)}\n`;
|
|
36
|
+
}
|