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.
Files changed (50) hide show
  1. package/README.md +58 -0
  2. package/assets/.yarn/releases/yarn-4.9.1.cjs +948 -0
  3. package/bin/create-arui-scripts-app.js +3 -0
  4. package/build/build-context.d.ts +2 -0
  5. package/build/build-context.js +83 -0
  6. package/build/build-file-map.d.ts +3 -0
  7. package/build/build-file-map.js +49 -0
  8. package/build/cli.d.ts +1 -0
  9. package/build/cli.js +15 -0
  10. package/build/create-program.d.ts +5 -0
  11. package/build/create-program.js +103 -0
  12. package/build/defaults.d.ts +21 -0
  13. package/build/defaults.js +48 -0
  14. package/build/install-dependencies.d.ts +3 -0
  15. package/build/install-dependencies.js +39 -0
  16. package/build/questions.d.ts +3 -0
  17. package/build/questions.js +126 -0
  18. package/build/run.d.ts +9 -0
  19. package/build/run.js +191 -0
  20. package/build/templates/app-component.template.d.ts +2 -0
  21. package/build/templates/app-component.template.js +73 -0
  22. package/build/templates/app-styles.template.d.ts +3 -0
  23. package/build/templates/app-styles.template.js +31 -0
  24. package/build/templates/app-test.template.d.ts +2 -0
  25. package/build/templates/app-test.template.js +14 -0
  26. package/build/templates/arui-scripts-config.template.d.ts +2 -0
  27. package/build/templates/arui-scripts-config.template.js +46 -0
  28. package/build/templates/client-entry.template.d.ts +2 -0
  29. package/build/templates/client-entry.template.js +105 -0
  30. package/build/templates/misc.template.d.ts +6 -0
  31. package/build/templates/misc.template.js +74 -0
  32. package/build/templates/package-json.template.d.ts +2 -0
  33. package/build/templates/package-json.template.js +36 -0
  34. package/build/templates/server-entry.template.d.ts +2 -0
  35. package/build/templates/server-entry.template.js +115 -0
  36. package/build/templates/store.template.d.ts +3 -0
  37. package/build/templates/store.template.js +63 -0
  38. package/build/templates/tsconfig.template.d.ts +2 -0
  39. package/build/templates/tsconfig.template.js +14 -0
  40. package/build/templates/vitest-config.template.d.ts +1 -0
  41. package/build/templates/vitest-config.template.js +18 -0
  42. package/build/types.d.ts +34 -0
  43. package/build/types.js +2 -0
  44. package/build/validate-project-name.d.ts +1 -0
  45. package/build/validate-project-name.js +20 -0
  46. package/build/versions.d.ts +4 -0
  47. package/build/versions.js +7 -0
  48. package/build/write-files.d.ts +4 -0
  49. package/build/write-files.js +59 -0
  50. 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,2 @@
1
+ import { type TemplateContext } from '../types';
2
+ export declare function appComponentTemplate(ctx: TemplateContext): string;
@@ -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,3 @@
1
+ import { type TemplateContext } from '../types';
2
+ export declare function appStylesFileName(ctx: TemplateContext): string;
3
+ export declare function appStylesTemplate(ctx: TemplateContext): string;
@@ -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,2 @@
1
+ import { type TemplateContext } from '../types';
2
+ export declare function appTestTemplate(ctx: TemplateContext): string;
@@ -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,2 @@
1
+ import { type TemplateContext } from '../types';
2
+ export declare function aruiScriptsConfigTemplate(ctx: TemplateContext): string;
@@ -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,2 @@
1
+ import { type TemplateContext } from '../types';
2
+ export declare function clientEntryTemplate(ctx: TemplateContext): string;
@@ -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,2 @@
1
+ import { type TemplateContext } from '../types';
2
+ export declare function packageJsonTemplate(ctx: TemplateContext): string;
@@ -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
+ }
@@ -0,0 +1,2 @@
1
+ import { type TemplateContext } from '../types';
2
+ export declare function serverEntryTemplate(ctx: TemplateContext): string;