Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .changeset/beige-bears-explain.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
'arui-scripts': major
---

Обновление тулчейна: Babel 8, Jest 30, отказ от EOL-пакетов, добавлена zod валидация конфигов

**breaking changes:**

- **Babel 8.** Все `@babel/*` → `^8.0.0`; удалены `@babel/plugin-syntax-dynamic-import` и `babel-core`.
- **Jest 30** (`jest`/`babel-jest`/`@types/jest` -> `^30`, `babel-loader` -> `^10`).

**Другие изменения:**

- EOL-зависимости заменены на нативные Node API (`fs-extra` -> `node:fs`, `shelljs` -> `node:child_process`, `rimraf` -> `node:fs.rm`); `chalk` `^2` -> `^4`.
- `core-js` `3.32` -> `3.49`.
- Конфиги валидируются и типизируются через `zod`: тип `AppConfigs` выводится из схемы, строгая проверка ключей с подсказками.
68 changes: 31 additions & 37 deletions packages/arui-scripts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,27 +22,26 @@
"bin": "./build/bin/index.js",
"dependencies": {
"@alfalab/postcss-custom-properties": "^9.1.2",
"@babel/core": "7.22.10",
"@babel/plugin-proposal-decorators": "^7.23.7",
"@babel/plugin-proposal-export-default-from": "^7.23.3",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/plugin-transform-class-properties": "^7.23.3",
"@babel/plugin-transform-export-namespace-from": "^7.23.4",
"@babel/plugin-transform-modules-commonjs": "7.22.5",
"@babel/plugin-transform-nullish-coalescing-operator": "^7.23.4",
"@babel/plugin-transform-numeric-separator": "^7.23.4",
"@babel/plugin-transform-object-rest-spread": "^7.23.4",
"@babel/plugin-transform-optional-chaining": "^7.23.4",
"@babel/plugin-transform-private-methods": "^7.23.3",
"@babel/plugin-transform-private-property-in-object": "^7.23.4",
"@babel/plugin-transform-proto-to-assign": "^7.23.3",
"@babel/plugin-transform-react-constant-elements": "^7.23.3",
"@babel/plugin-transform-react-inline-elements": "^7.23.3",
"@babel/plugin-transform-runtime": "^7.23.7",
"@babel/preset-env": "^7.23.8",
"@babel/preset-react": "^7.23.3",
"@babel/preset-typescript": "^7.23.3",
"@babel/runtime": "^7.26.10",
"@babel/core": "^8.0.0",
"@babel/plugin-proposal-decorators": "^8.0.0",
"@babel/plugin-proposal-export-default-from": "^8.0.0",
"@babel/plugin-transform-class-properties": "^8.0.0",
"@babel/plugin-transform-export-namespace-from": "^8.0.0",
"@babel/plugin-transform-modules-commonjs": "^8.0.0",
"@babel/plugin-transform-nullish-coalescing-operator": "^8.0.0",
"@babel/plugin-transform-numeric-separator": "^8.0.0",
"@babel/plugin-transform-object-rest-spread": "^8.0.0",
"@babel/plugin-transform-optional-chaining": "^8.0.0",
"@babel/plugin-transform-private-methods": "^8.0.0",
"@babel/plugin-transform-private-property-in-object": "^8.0.0",
"@babel/plugin-transform-proto-to-assign": "^8.0.0",
"@babel/plugin-transform-react-constant-elements": "^8.0.0",
"@babel/plugin-transform-react-inline-elements": "^8.0.0",
"@babel/plugin-transform-runtime": "^8.0.0",
"@babel/preset-env": "^8.0.0",
"@babel/preset-react": "^8.0.0",
"@babel/preset-typescript": "^8.0.0",
"@babel/runtime": "^8.0.0",
"@module-federation/runtime-tools": "^2.0.0",
"@pmmmwh/react-refresh-webpack-plugin": "0.6.2",
"@rsdoctor/rspack-plugin": "1.5.9",
Expand All @@ -54,30 +53,28 @@
"@swc/jest": "0.2.39",
"assets-webpack-plugin": "7.1.1",
"autoprefixer": "^10.3.16",
"babel-core": "^7.0.0-bridge.0",
"babel-jest": "28.1.3",
"babel-loader": "9.2.1",
"babel-jest": "^30.0.0",
"babel-loader": "^10.0.0",
"babel-plugin-istanbul": "^7.0.0",
"babel-plugin-react-compiler": "^1.0.0",
"babel-plugin-transform-react-remove-prop-types": "0.4.24",
"brotli-dict": "^1.1.4",
"case-sensitive-paths-webpack-plugin": "2.4.0",
"chalk": "^2.4.2",
"chalk": "^4.1.2",
"compression-webpack-plugin": "9.2.0",
"core-js": "3.32.0",
"core-js": "3.49.0",
"css-loader": "6.8.1",
"css-minimizer-webpack-plugin": "5.0.0",
"expose-loader": "3.1.0",
"filesize": "^6.4.0",
"fs-extra": "6.0.1",
"get-port": "7.2.0",
"html-webpack-plugin": "^5.6.0",
"image-minimizer-webpack-plugin": "^3.8.3",
"imagemin": "^8.0.1",
"imagemin-svgo": "^12.0.0",
"jest": "^29.7.0",
"jest-config": "^29.7.0",
"jest-resolve": "^29.7.0",
"jest": "^30.0.0",
"jest-config": "^30.0.0",
"jest-resolve": "^30.0.0",
"jest-snapshot-serializer-class-name-to-string": "1.0.0",
"lodash.merge": "4.6.2",
"mini-css-extract-plugin": "2.7.6",
Expand Down Expand Up @@ -105,40 +102,37 @@
"postcss-url": "^10.0.0",
"react-refresh": "0.10.0",
"react-refresh-typescript": "2.0.2",
"rimraf": "^2.7.1",
"rspack-manifest-plugin": "5.2.1",
"run-script-webpack-plugin": "0.0.11",
"semver": "^7.5.4",
"serialize-javascript": "^7.0.5",
"shelljs": "0.8.5",
"strip-ansi": "6.0.1",
"style-loader": "3.3.3",
"swc-loader": "^0.2.6",
"swc-plugin-coverage-instrument": "0.0.32",
"tar": "7.5.16",
"terser-webpack-plugin": "5.3.14",
"ts-checker-rspack-plugin": "^1.3.0",
"ts-jest": "29.1.0",
"ts-jest": "^29.4.0",
"ts-loader": "9.4.4",
"ts-node": "10.9.2",
"vite-tsconfig-paths": "^6.1.1",
"vitest": "^4.1.5",
"webpack-bundle-analyzer": "4.10.2",
"webpack-deduplication-plugin": "^0.0.8",
"webpack-node-externals": "3.0.0"
"webpack-node-externals": "3.0.0",
"zod": "^3.25.0"
},
"devDependencies": {
"@types/assets-webpack-plugin": "6.1.2",
"@types/case-sensitive-paths-webpack-plugin": "2.1.6",
"@types/compression-webpack-plugin": "4.0.1",
"@types/fs-extra": "^9.0.13",
"@types/jest": "^29.5.14",
"@types/jest": "^30.0.0",
"@types/lodash.merge": "^4.6.7",
"@types/node": "^20.19.0",
"@types/postcss-media-query-parser": "0.2.4",
"@types/semver": "^7.5.0",
"@types/serialize-javascript": "^5.0.4",
"@types/shelljs": "^0.8.12",
"@types/tar": "^4.0.5",
"@types/webpack-bundle-analyzer": "4.7.0",
"@types/webpack-node-externals": "^3.0.0",
Expand Down
26 changes: 17 additions & 9 deletions packages/arui-scripts/src/commands/archive-build/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { promises as fs, readdirSync } from 'fs';
import path from 'path';

import fs from 'fs-extra';
import tar from 'tar';

import { configs } from '../../configs/app-configs';
import { nginxConfTemplate } from '../../templates/nginx.conf.template';
import { startScript } from '../../templates/start.template';
import { exec } from '../util/exec';
import { emptyDir } from '../util/fs-helpers';
import { getPruningCommand } from '../util/yarn';

const tempDirName = '.archive-build';
Expand All @@ -25,7 +26,7 @@ const packageJsonPath = path.join(configs.cwd, packageJsonFileName);
console.time('Total time');
console.time('Setting up time');

await fs.emptyDir(pathToTempDir);
await emptyDir(pathToTempDir);

const nginxConf = configs.localNginxConf
? await fs.readFile(configs.localNginxConf, 'utf8')
Expand All @@ -34,7 +35,7 @@ const packageJsonPath = path.join(configs.cwd, packageJsonFileName);
await Promise.all([
fs.writeFile(nginxConfPath, nginxConf, 'utf8'),
fs.writeFile(startScriptPath, startScript, { encoding: 'utf8', mode: 0o555 }),
fs.remove(configs.buildPath),
fs.rm(configs.buildPath, { recursive: true, force: true }),
]);

console.timeEnd('Setting up time');
Expand All @@ -51,13 +52,20 @@ const packageJsonPath = path.join(configs.cwd, packageJsonFileName);
console.timeEnd('Remove build dependencies time');
console.time('Archive build time');
await Promise.all([
fs.copy(configs.buildPath, path.join(pathToTempDir, configs.buildPath)),
fs.copy(nodeModulesPath, path.join(pathToTempDir, nodeModulesDirName)),
fs.copy(packageJsonPath, path.join(pathToTempDir, packageJsonFileName)),
fs.cp(configs.buildPath, path.join(pathToTempDir, configs.buildPath), {
recursive: true,
}),
fs.cp(nodeModulesPath, path.join(pathToTempDir, nodeModulesDirName), {
recursive: true,
}),
fs.cp(packageJsonPath, path.join(pathToTempDir, packageJsonFileName), {
recursive: true,
}),
...configs.additionalBuildPath.map((additionalPath) =>
fs.copy(
fs.cp(
path.join(configs.cwd, additionalPath),
path.join(pathToTempDir, additionalPath),
{ recursive: true },
),
),
]);
Expand All @@ -66,14 +74,14 @@ const packageJsonPath = path.join(configs.cwd, packageJsonFileName);
file: configs.archiveName,
cwd: pathToTempDir,
},
fs.readdirSync(pathToTempDir),
readdirSync(pathToTempDir),
);

console.timeEnd('Archive build time');
console.time('Cleanup time');

// remove temp directory
await fs.remove(pathToTempDir);
await fs.rm(pathToTempDir, { recursive: true, force: true });

console.timeEnd('Cleanup time');
console.timeEnd('Total time');
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import fs from 'fs-extra';
import { promises as fs } from 'fs';

import { configs } from '../../configs/app-configs';
import { nginxBaseConfTemplate } from '../../templates/base-nginx.conf.template';
Expand Down Expand Up @@ -31,7 +31,7 @@ import { exec } from '../util/exec';
});

await exec(getDockerBuildCommand({ tempDirName, imageFullName }));
await fs.remove(pathToTempDir);
await fs.rm(pathToTempDir, { recursive: true, force: true });

// guard against pushing the image during tests
if (!configs.debug) {
Expand All @@ -40,7 +40,7 @@ import { exec } from '../util/exec';

console.timeEnd('Total time');
} catch (err) {
await fs.remove(pathToTempDir);
await fs.rm(pathToTempDir, { recursive: true, force: true });
console.error('Error during docker-build.');
if (configs.debug) {
console.error(err);
Expand Down
8 changes: 4 additions & 4 deletions packages/arui-scripts/src/commands/docker-build/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import fs from 'fs-extra';
import { promises as fs } from 'fs';

import { configs } from '../../configs/app-configs';
import { nginxBaseConfTemplate } from '../../templates/base-nginx.conf.template';
Expand Down Expand Up @@ -32,7 +32,7 @@ import { getPruningCommand } from '../util/yarn';
addNodeModulesToDockerIgnore: false,
});

await fs.remove(configs.buildPath);
await fs.rm(configs.buildPath, { recursive: true, force: true });

console.timeEnd('Setting up time');
console.time('Build application time');
Expand All @@ -59,7 +59,7 @@ import { getPruningCommand } from '../util/yarn';
console.time('Cleanup time');

// remove temp directory
await fs.remove(pathToTempDir);
await fs.rm(pathToTempDir, { recursive: true, force: true });

// guard against pushing the image during tests
if (!configs.debug) {
Expand All @@ -69,7 +69,7 @@ import { getPruningCommand } from '../util/yarn';
console.timeEnd('Cleanup time');
console.timeEnd('Total time');
} catch (err) {
await fs.remove(pathToTempDir);
await fs.rm(pathToTempDir, { recursive: true, force: true });
console.error('Error during docker-build.');
if (configs.debug) {
console.error(err);
Expand Down
25 changes: 10 additions & 15 deletions packages/arui-scripts/src/commands/util/docker-build.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { existsSync, promises as fs } from 'fs';
import path from 'path';

import fs from 'fs-extra';
import satisfies from 'semver/functions/satisfies';
import shell from 'shelljs';

import { configs } from '../../configs/app-configs';
import {
baseNginxConfigFileName,
nginxConfigFileName,
} from '../../configs/app-configs/get-defaults';

import { getCommandOutput } from './exec';
import { createFile, emptyDir } from './fs-helpers';

export function getBuildParamsFromArgs() {
let imageVersion = configs.version;
let imageName = configs.name;
Expand Down Expand Up @@ -70,7 +72,7 @@ export async function prepareFilesForDocker({
allowLocalStartScript,
addNodeModulesToDockerIgnore,
}: PrepareFilesForDockerParams) {
await fs.emptyDir(pathToTempDir);
await emptyDir(pathToTempDir);

let nginxBaseConf = '';

Expand Down Expand Up @@ -122,17 +124,10 @@ export async function prepareFilesForDocker({
}

export function dockerVersionSatisfies(request: string) {
const dockerServerVersion = shell.exec("docker version --format '{{.Server.Version}}'", {
silent: true,
});
const dockerClientVersion = shell.exec("docker version --format '{{.Client.Version}}'", {
silent: true,
});
const dockerServerVersion = getCommandOutput("docker version --format '{{.Server.Version}}'");
const dockerClientVersion = getCommandOutput("docker version --format '{{.Client.Version}}'");

return (
satisfies(dockerServerVersion.toString(), request) &&
satisfies(dockerClientVersion.toString(), request)
);
return satisfies(dockerServerVersion, request) && satisfies(dockerClientVersion, request);
}

type DockerBuildCommandParams = {
Expand All @@ -157,13 +152,13 @@ export function getDockerBuildCommand({ tempDirName, imageFullName }: DockerBuil
}

async function getAndModifyDockerIgnoreContent(dockerIgnoreFilePath: string) {
if (fs.existsSync(dockerIgnoreFilePath)) {
if (existsSync(dockerIgnoreFilePath)) {
return fs
.readFile(dockerIgnoreFilePath, 'utf-8')
.then((ignores) => `${ignores}\nnode_modules`);
}

await fs.createFile(dockerIgnoreFilePath);
await createFile(dockerIgnoreFilePath);

return 'node_modules';
}
21 changes: 19 additions & 2 deletions packages/arui-scripts/src/commands/util/exec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import shell from 'shelljs';
import { execSync, spawn } from 'child_process';

export function exec(command: string) {
return new Promise((resolve, reject) => {
console.log(`Executing command: ${command}`);
shell.exec(command, (code) => {
const child = spawn(command, { shell: true, stdio: 'inherit' });

child.on('error', reject);
child.on('close', (code) => {
if (code === 0) {
return resolve(code);
}
Expand All @@ -12,3 +15,17 @@ export function exec(command: string) {
});
});
}

/**
* Синхронно выполняет команду и возвращает её stdout (без вывода в консоль).
* Возвращает пустую строку, если команда завершилась с ошибкой или не найдена.
*/
export function getCommandOutput(command: string): string {
try {
return execSync(command, { stdio: ['ignore', 'pipe', 'ignore'] })
.toString()
.trim();
} catch {
return '';
}
}
Loading
Loading