## Summary - **Cloudflare R2 Migration**: - Migrated `static.ermnvldmr.com` asset storage to Cloudflare R2 bucket `com-ermnvldmr-static` (location `WEUR`). - Added support for `COM_ERMNVLDMR_STATIC_PUBLIC_URL` fallback in `@ermnvldmr/cli` to properly format public asset URLs for non-dotted bucket names. - Relocated public CA cert to `/dev/ssl/certs/ErmnvldmrDevelopmentRootCA.pem` and updated `REMOTE_ROOT_CA_URL` references in `@ermnvldmr/rsbuild-config` and `ensure-dev-certs.mjs`. - Configured R2 CORS policies using wildcards (`https://*.ermnvldmr.com`, `https://ermnvldmr.com`, `https://localhost.ermnvldmr.com*`, `http://localhost*`, `https://direct.yandex.ru`, `https://*.direct.yandex.ru`, `https://localhost.yandex.ru*`). - Enforced minimum TLS 1.2 on zone `ermnvldmr.com`. - Updated encrypted `.env.dev` and GitHub secrets in both `deytenit/ermnvldmr.com` and `deytenit/apex.ermnvldmr.com`. - **Multi-locale SSG Support**: - Added `NormalModuleReplacementPlugin` to SSR runner in `@ermnvldmr/ssg` for automatic `.en.mdx` -> `.${locale}.mdx` substitution during Russian builds. - Added page metadata extraction (`getPageOptions`) in `@ermnvldmr/ssg` for pre-rendered `<title>` and `<meta name="description">` tags. - Added unit test suite for `createPage` and updated `services/www` build scripts (`build:all`, `build:en`, `build:ru`, `dev:en`, `dev:ru`).
@ermnvldmr/cli
An extensible, configuration-driven CLI toolkit designed specifically for the ermnvldmr monorepo.
Overview
The @ermnvldmr/cli package provides a unified way to declare, manage, and execute scripts across different packages and services in the monorepo. Instead of cluttering package.json with complex bash scripts or maintaining ad-hoc Node.js script files, developers can define their package's commands in a strongly-typed .config/cli.ts file.
Under the hood, it uses Commander.js for argument parsing and JITI for seamless, dynamic TypeScript execution.
Features
- Centralized Configuration: Define all commands in a single
.config/cli.tsfile per package. - Type-Safe Builders: Use
bashCommandandnodeCommandbuilders to get strict TypeScript inference. - Bash & Node Support: Easily execute shell scripts (via
execa) or arbitrary asynchronous Node.js functions. - Commander Integration: Automatically registers commands, descriptions, and arguments into a robust CLI interface.
Installation
This package is intended to be used as a development dependency within the monorepo's workspace packages.
pnpm add -D @ermnvldmr/cli --workspace
Usage
1. Create a Configuration File
Create a .config/cli.ts file in the root of your package/service (e.g., packages/ui/.config/cli.ts).
import { defineCli, bashCommand, nodeCommand } from '@ermnvldmr/cli';
export default defineCli({
commands: [
bashCommand({
name: 'hello',
description: 'Prints a hello message via bash',
script: 'echo "Hello from Bash!"'
}),
nodeCommand({
name: 'build:custom',
description: 'Runs a custom node build step',
options: [
{
flags: '--minify',
description: 'Enable minification',
defaultValue: false
}
],
action: async (options) => {
console.log('Building with node...');
if (options.minify) {
console.log('Minification enabled!');
}
}
})
]
});
2. Run the CLI
You can invoke the CLI directly using pnpm exec from the package directory:
pnpm exec ermnvldmr-cli hello
pnpm exec ermnvldmr-cli build:custom --minify
Alternatively, you can wire it into your package.json scripts:
{
"scripts": {
"cli": "ermnvldmr-cli",
"hello": "ermnvldmr-cli hello"
}
}
API Reference
defineCli(config: CliConfig)
An identity helper function that provides strict TypeScript type-inference for your configuration object. It returns the configuration unmodified.
bashCommand(config: Omit<BashCommandConfig, 'type'>)
A builder function for defining shell commands.
script: The exact bash string to execute. It will be executed usingexecawithshell: trueandstdio: 'inherit'.
nodeCommand(config: Omit<NodeCommandConfig, 'type'>)
A builder function for defining arbitrary JavaScript/TypeScript actions.
action: An asynchronous function(options: Record<string, unknown>) => Promise<void> | voidthat executes when the command is invoked.
Development
This package adheres to the global monorepo standards outlined in GEMINI.md:
- Strict TypeScript: No
anytypes are permitted. - TSDoc: All exported members must include comprehensive TSDoc comments.
- TDD: Modifications and new builders should be accompanied by Vitest unit tests.