beez-rp 0.2.0 → 0.3.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 +22 -0
- package/README.md +30 -4
- package/bin/beez-rp.js +10 -1
- package/package.json +7 -2
- package/src/constants/cli.js +1 -0
- package/src/constants/create-version.js +169 -0
- package/src/constants/guard-publish.js +29 -0
- package/src/constants/index.js +1 -0
- package/src/create-version/artifact.js +324 -0
- package/src/create-version/config.js +16 -0
- package/src/create-version/index.js +23 -2
- package/src/create-version/npm.js +359 -22
- package/src/create-version/plan.js +8 -1
- package/src/create-version/process.js +20 -7
- package/src/create-version/run.js +207 -13
- package/src/create-version/state.js +25 -2
- package/src/guard-publish.js +74 -0
- package/src/index.js +2 -0
- package/types/constants/cli.d.ts +1 -0
- package/types/constants/create-version.d.ts +118 -0
- package/types/constants/guard-publish.d.ts +25 -0
- package/types/constants/index.d.ts +1 -0
- package/types/create-version/artifact.d.ts +113 -0
- package/types/create-version/config.d.ts +4 -0
- package/types/create-version/index.d.ts +3 -2
- package/types/create-version/npm.d.ts +133 -8
- package/types/create-version/process.d.ts +10 -1
- package/types/create-version/run.d.ts +2 -0
- package/types/guard-publish.d.ts +48 -0
- package/types/index.d.ts +2 -0
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,28 @@ El formato sigue [Keep a Changelog](https://keepachangelog.com/es-ES/1.1.0/) y e
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.3.0] - 2026-09-27
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- `artifact` en `beez-rp.config.js`: con `publish: "npm"`, publica exactamente el tarball que dejó el paso `prepare` (por ejemplo `releases/{version}-{sha256}/{name}-{version}.tgz`) en vez de reempaquetar el working tree. Los proyectos lo empaquetan con `npm pack --ignore-scripts`.
|
|
14
|
+
- Antes de publicar ese tarball exige que `prepare` no haya modificado archivos versionados, rechaza paquetes que dependen de reescrituras de pnpm al empaquetar (`workspace:`/`catalog:`/`jsr:` o campos del manifest en `publishConfig` que solo pnpm sube a la raíz, como `exports`, `main`, `bin` o `types`; cualquier otra clave de `publishConfig` se acepta como configuración de npm), verifica el SHA-256 de su ruta cuando el patrón usa `{sha256}` y compara su SHA-512 con el `integrity` de `npm pack --dry-run --json --ignore-scripts` del commit de release. Durante esa comparación el tarball queda fuera de la raíz del paquete, así que se verifica aunque el paquete no tenga `files` y su carpeta no esté ignorada.
|
|
15
|
+
- `beez-rp guard-publish` (y `beez-rp/guard-publish`): guard de `prepublishOnly` que bloquea `pnpm publish`, yarn y bun con un mensaje que indica publicar con `pnpm create-version`; `create-version` quita `npm_config_user_agent` del entorno de `npm publish` para no bloquearse.
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- `publish: "npm"` usa una config de npm temporal que solo referencia `${NPM_TOKEN}`, asociada al registry donde se publica (`publishConfig["@scope:registry"]` de un paquete con scope, `publishConfig.registry` o, si no hay, el registry que resuelve la config de npm en el repo: `.npmrc` del proyecto, variables de entorno o config global): los proyectos ya no necesitan `.npmrc` y pnpm deja de advertir por credenciales en el repositorio. La confirmación 2FA de npm sigue siendo interactiva.
|
|
20
|
+
- El diagnóstico y la comprobación posterior a publicar consultan las versiones con `npm view --registry` en ese mismo registry, así que un paquete publicado en un registry propio ya no se vuelve a preparar y publicar. Con `NPM_TOKEN` (entorno o `.env`) esa consulta se autentica con la misma config temporal, así que también funciona con paquetes privados.
|
|
21
|
+
- El resumen final enlaza a npmjs.com solo cuando se publicó en `https://registry.npmjs.org/`; en otro registry muestra `Registro: <url>` con el paquete y la versión.
|
|
22
|
+
|
|
23
|
+
### Removed
|
|
24
|
+
|
|
25
|
+
- `.npmrc` del repositorio de beez-rp.
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
|
|
29
|
+
- Si `main` estaba atrás de `origin/main`, `create-version` lo actualiza y termina sin tocar la versión ni los tags (código de salida 0), pidiendo volver a correr `pnpm create-version`: así el diagnóstico, el plan, las migraciones y `beez-rp.config.(m)js` con sus módulos importados salen del código actualizado y no del `main` anterior.
|
|
30
|
+
|
|
9
31
|
## [0.2.0] - 2026-09-26
|
|
10
32
|
|
|
11
33
|
### Added
|
package/README.md
CHANGED
|
@@ -16,6 +16,7 @@ Proceso de release compartido por los proyectos Beez (beez-ui, TuTribu, Control
|
|
|
16
16
|
| `beez-rp/build-gate` | `decideBuild(previousVersion, currentVersion)` y `decideBuildForCheckout(repositoryRoot)` para el `ignoreCommand` de Vercel. |
|
|
17
17
|
| `beez-rp/changelog` | Lectura y release del bloque `## [Unreleased]` de `CHANGELOG.md` (Keep a Changelog). |
|
|
18
18
|
| `beez-rp/changelog-ai` | Prompt e invocación de Codex para completar `[Unreleased]` vacío. |
|
|
19
|
+
| `beez-rp/guard-publish` | `decidePublishGuard(userAgent)` del `prepublishOnly` que bloquea publicaciones con pnpm, yarn o bun. |
|
|
19
20
|
| `beez-rp/terminal-ui` | Cajas, filas, banner, spinner y selector interactivo sin dependencias. |
|
|
20
21
|
| `beez-rp/create-version` | Comando compartido de release: `runCreateVersion`, el planificador puro `buildReleasePlan`, el lector de estado y los tipos de `beez-rp.config.js`. |
|
|
21
22
|
| `beez-rp/testing` | Fixtures de versiones permitidas y rechazadas para los tests de cada proyecto. |
|
|
@@ -72,14 +73,14 @@ pnpm cv --dry-run # diagnóstico y plan, sin cambiar nada
|
|
|
72
73
|
|
|
73
74
|
El comando sale solo desde `main`, limpio y al día con origin (solo `CHANGELOG.md` puede quedar sin commitear). En una rama feature explica qué falta: pushear, abrir o mergear el PR (con `gh`).
|
|
74
75
|
|
|
75
|
-
1.
|
|
76
|
+
1. Si `main` está atrás de origin, lo actualiza en fast-forward y termina (código de salida 0) sin tocar la versión ni los tags: hay que volver a correr `pnpm create-version`, que en un proceso nuevo carga `beez-rp.config.(m)js`, sus módulos y el diagnóstico desde el código actualizado.
|
|
76
77
|
2. Aplica migraciones pendientes, si el proyecto tiene adaptador, después de pedir confirmación.
|
|
77
78
|
3. Si `[Unreleased]` está vacío, lo completa Codex a partir de los commits sin publicar.
|
|
78
79
|
4. Corre los `checks`.
|
|
79
80
|
5. Pide la versión, pasa `[Unreleased]` a `## [X.Y.Z] - AAAA-MM-DD` y crea el commit `X.Y.Z` con el tag anotado `vX.Y.Z`.
|
|
80
81
|
6. Corre `prepare`, sube `main` y el tag con `git push --atomic` y corre `publish`.
|
|
81
82
|
|
|
82
|
-
El último release es el último commit de `origin/main` que cambió el `version` de `package.json`, así que sirve con commits `X.Y.Z`, con otros asuntos de release y con versiones subidas a mano. Si algo falla después del commit, volver a correr el comando retoma solo lo que falta: el push de un commit de versión local o, con `registry: "npm"`, la preparación y publicación de una versión que npm todavía no tiene.
|
|
83
|
+
El último release es el último commit de `origin/main` que cambió el `version` de `package.json`, así que sirve con commits `X.Y.Z`, con otros asuntos de release y con versiones subidas a mano. Si algo falla después del commit, volver a correr el comando retoma solo lo que falta: el push de un commit de versión local o, con `registry: "npm"`, la preparación y publicación de una versión que npm todavía no tiene. Las versiones publicadas se consultan con `npm view --registry` en el mismo registry donde se publica (ver abajo), porque `npm view` no aplica el `publishConfig` del `package.json`.
|
|
83
84
|
|
|
84
85
|
### beez-rp.config.js
|
|
85
86
|
|
|
@@ -95,17 +96,42 @@ export default {
|
|
|
95
96
|
migrations: { check, apply, targetHint }, // adaptador de base de datos
|
|
96
97
|
prepare: ["pnpm release:prepare"], // comandos o función, sobre el commit de versión
|
|
97
98
|
publish: "npm", // npm publish con NPM_TOKEN, o una función
|
|
99
|
+
artifact: "releases/{version}-{sha256}/{name}-{version}.tgz", // con "npm": publica ese tarball verificado
|
|
98
100
|
summary: ["Vercel buildea {version}."], // líneas extra del resumen final
|
|
99
101
|
};
|
|
100
102
|
```
|
|
101
103
|
|
|
102
104
|
Solo `changelog.audience` es obligatorio. Los hooks (`migrations.check`, `migrations.apply`, `prepare`, `publish`) reciben `{ repositoryRoot, version, git, run, print, fail }`: `git` lee Git, `run("pnpm x")` corre un comando visible y devuelve su exit code, y `fail(mensaje, qué hacer)` corta el paso con una explicación. El config no necesita importar `beez-rp`.
|
|
103
105
|
|
|
104
|
-
`migrations.check` devuelve `{ status: "up-to-date" | "pending" | "unknown", pending, target, reason }`; después de `apply`, el comando vuelve a llamar a `check` y falla si siguen pendientes. `publish: "npm"` toma `NPM_TOKEN` del entorno o de un `.env` ignorado por Git,
|
|
106
|
+
`migrations.check` devuelve `{ status: "up-to-date" | "pending" | "unknown", pending, target, reason }`; después de `apply`, el comando vuelve a llamar a `check` y falla si siguen pendientes. `publish: "npm"` toma `NPM_TOKEN` del entorno o de un `.env` ignorado por Git. No hace falta `.npmrc`: el comando escribe una config de npm temporal fuera del repo que asocia `${NPM_TOKEN}` al registry donde realmente se publica, resuelto como npm: `publishConfig["@scope:registry"]` si el paquete tiene ese scope, si no `publishConfig.registry` y, si el `package.json` no declara ninguno, lo que devuelve `npm config get @scope:registry` (paquete con scope) o `npm config get registry` en la raíz del repo, que incluye el `.npmrc` del proyecto, las variables `npm_config_*` y la config global (como la publicación, no lee `~/.npmrc`, que se reemplaza por la config temporal); tiene que ser una URL http(s) válida o no se publica. Con `NPM_TOKEN` disponible, el diagnóstico también consulta `npm view` con esa config temporal, así que funciona con paquetes privados; sin token consulta sin autenticar. El resumen final enlaza a npmjs.com solo si el registry es `https://registry.npmjs.org/`; si no, muestra `Registro: <url>` con el paquete y la versión. Solo guarda esa referencia: npm la expande, el token nunca queda en disco ni en la línea de comandos, y la config se borra al terminar. npm hereda la terminal, así que la confirmación 2FA (navegador o código) funciona igual.
|
|
107
|
+
|
|
108
|
+
Sin `artifact`, `publish: "npm"` publica el working tree. Con `artifact` publica exactamente el tarball que dejó `prepare`. Los proyectos empaquetan siempre con npm: `prepare` construye (con pnpm o lo que use el proyecto) y después corre `npm pack --ignore-scripts`. `npm pack` es reproducible (el mismo commit da siempre los mismos bytes), así que la verificación es una comparación de hash. Después de `prepare` y antes de `npm publish`:
|
|
109
|
+
|
|
110
|
+
- Working tree: `git status --porcelain --untracked-files=no` tiene que estar vacío. `prepare` puede generar archivos ignorados o no versionados (`dist/`, `releases/`), pero no modificar archivos versionados como `package.json`; así lo que lee npm es exactamente el commit de release.
|
|
111
|
+
- Publicable con npm: si el `package.json` depende de algo que solo pnpm reescribe al empaquetar (especificadores `workspace:`, `catalog:` o `jsr:` en `dependencies`, `peerDependencies` u `optionalDependencies`, o campos del manifest dentro de `publishConfig` que pnpm sube a la raíz del `package.json` empaquetado), no se publica. Para npm, `publishConfig` es solo [configuración de npm](https://docs.npmjs.com/cli/v11/configuring-npm/package-json#publishconfig), así que se acepta cualquier clave (`registry`, `access`, `tag`, `provenance`, `@scope:registry`, `otp`...) salvo las que pnpm aplica al manifest: `name`, `bin`, `engines`, `type`, `imports`, `main`, `module`, `typings`, `types`, `exports`, `browser`, `esnext`, `es2015`, `unpkg`, `umd:main`, `os`, `cpu`, `libc` y `typesVersions` (lista de `PUBLISH_CONFIG_WHITELIST` en pnpm). Declaralos en la raíz del `package.json`.
|
|
112
|
+
- Ubicación: el patrón es relativo a la raíz, reemplaza `{version}` (obligatorio) y `{name}` (el nombre de archivo que usa `npm pack`: `@scope/pkg` pasa a `scope-pkg`), y dentro de un segmento acepta `*` y `{sha256}`. Si hay varios, toma el más reciente. La ruta solo puede tener letras, números, `.`, `-`, `_`, `@`, `+`, `~` y `/`.
|
|
113
|
+
- `{sha256}`: el SHA-256 del archivo tiene que coincidir con el de su ruta. Puede repetirse en un segmento o en varios; todas las apariciones tienen que declarar el mismo digest.
|
|
114
|
+
- Hash: beez-rp corre `npm pack --dry-run --json --ignore-scripts` en la raíz y compara su `integrity` (`sha512-<base64>`) con el SHA-512 del tarball. Durante ese dry run el tarball se mueve a un directorio temporal fuera del paquete y siempre vuelve a su ruta, aunque npm falle: sin una lista `files` ni una regla de `.npmignore`/`.gitignore` que excluya su carpeta, npm lo contaría como parte del paquete y la integrity nunca coincidiría. Después se publica desde su ruta original. Si difieren, el tarball no es lo que npm empaquetaría de este commit (por ejemplo, se armó con otra herramienta o antes de construir) y no se publica. Si npm falla o su salida no se puede leer, tampoco.
|
|
115
|
+
|
|
116
|
+
Ejemplo de `prepare` que deja `releases/{version}-{sha256}/{name}-{version}.tgz`: `pnpm build`, `npm pack --ignore-scripts --pack-destination releases/<version>-tmp/` y renombrar la carpeta con el SHA-256 del tarball.
|
|
117
|
+
|
|
118
|
+
Si no hay tarball o la verificación falla, no se publica nada y volver a correr el comando retoma preparación y publicación.
|
|
119
|
+
|
|
120
|
+
## Bloquear publicaciones con pnpm
|
|
121
|
+
|
|
122
|
+
`create-version` publica siempre con npm y verifica el tarball contra `npm pack --dry-run`, así que un `pnpm publish` manual saltearía esas garantías. Cada proyecto lo bloquea con:
|
|
123
|
+
|
|
124
|
+
```json
|
|
125
|
+
{ "scripts": { "prepublishOnly": "beez-rp guard-publish" } }
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
`beez-rp guard-publish` lee `npm_config_user_agent`: si empieza con `pnpm/`, `yarn/` o `bun/`, explica por stderr que se publica con `pnpm create-version` y sale con `1`; con `npm/`, sin la variable o con un valor desconocido sale con `0` sin imprimir nada. npm toma un `npm_config_user_agent` heredado como su config `user-agent`, por eso `create-version` lo quita del entorno de `npm publish`: así `pnpm create-version` no se bloquea a sí mismo.
|
|
129
|
+
|
|
130
|
+
Es una protección contra errores, no un candado: `--ignore-scripts` la esquiva a propósito. Aun así, un tarball empaquetado con pnpm no pasa la verificación de hash de `create-version`.
|
|
105
131
|
|
|
106
132
|
## Publicar beez-rp
|
|
107
133
|
|
|
108
|
-
beez-rp se publica con su propio comando (`beez-rp.config.js`: `checks: ["pnpm check"]`, `publish: "npm"`):
|
|
134
|
+
beez-rp se publica con su propio comando (`beez-rp.config.js`: `checks: ["pnpm check"]`, `publish: "npm"`). Su `prepublishOnly` es `node bin/beez-rp.js guard-publish`, porque no se instala a sí mismo:
|
|
109
135
|
|
|
110
136
|
```bash
|
|
111
137
|
pnpm cv
|
package/bin/beez-rp.js
CHANGED
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
* - `beez-rp create-version [--bump patch|minor|major | --set-version X.Y.Z] [--dry-run]`
|
|
11
11
|
* diagnoses the repository in the current directory and ships its release
|
|
12
12
|
* from `main`, following its `beez-rp.config.js`.
|
|
13
|
+
* - `beez-rp guard-publish` is the `prepublishOnly` guard: it exits with `1`
|
|
14
|
+
* and explains why when pnpm, yarn or bun publishes, and with `0` otherwise.
|
|
13
15
|
*
|
|
14
16
|
* @module beez-rp-cli
|
|
15
17
|
*/
|
|
@@ -18,14 +20,21 @@ import { decideBuildForCheckout } from "../src/build-gate.js";
|
|
|
18
20
|
import { BUILD_DECISION, DECISION_EXIT_CODE, GATE_FAILURE_EXIT_CODE } from "../src/constants/build-gate.js";
|
|
19
21
|
import { CLI_COMMAND } from "../src/constants/cli.js";
|
|
20
22
|
import { runCreateVersion } from "../src/create-version/run.js";
|
|
23
|
+
import { decidePublishGuardForEnvironment } from "../src/guard-publish.js";
|
|
21
24
|
|
|
22
25
|
/** Usage printed for unknown commands. */
|
|
23
|
-
const USAGE = `Usage: beez-rp ${CLI_COMMAND.ignoreBuild} | beez-rp ${CLI_COMMAND.createVersion} [options]`;
|
|
26
|
+
const USAGE = `Usage: beez-rp ${CLI_COMMAND.ignoreBuild} | beez-rp ${CLI_COMMAND.createVersion} [options] | beez-rp ${CLI_COMMAND.guardPublish}`;
|
|
24
27
|
|
|
25
28
|
const [command, ...commandArguments] = process.argv.slice(2);
|
|
26
29
|
|
|
27
30
|
if (command === CLI_COMMAND.createVersion) {
|
|
28
31
|
process.exitCode = await runCreateVersion({ repositoryRoot: process.cwd(), argv: commandArguments });
|
|
32
|
+
} else if (command === CLI_COMMAND.guardPublish) {
|
|
33
|
+
const decision = decidePublishGuardForEnvironment();
|
|
34
|
+
if (decision.message) {
|
|
35
|
+
console.error(decision.message);
|
|
36
|
+
}
|
|
37
|
+
process.exitCode = decision.exitCode;
|
|
29
38
|
} else if (command === CLI_COMMAND.ignoreBuild) {
|
|
30
39
|
try {
|
|
31
40
|
const decision = decideBuildForCheckout(process.cwd());
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "beez-rp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Dependency-free release process shared by the Beez projects: stable version rules, Vercel build gate, Keep a Changelog and terminal UI.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Guido Modarelli",
|
|
@@ -46,6 +46,10 @@
|
|
|
46
46
|
"types": "./types/testing.d.ts",
|
|
47
47
|
"default": "./src/testing.js"
|
|
48
48
|
},
|
|
49
|
+
"./guard-publish": {
|
|
50
|
+
"types": "./types/guard-publish.d.ts",
|
|
51
|
+
"default": "./src/guard-publish.js"
|
|
52
|
+
},
|
|
49
53
|
"./create-version": {
|
|
50
54
|
"types": "./types/create-version/index.d.ts",
|
|
51
55
|
"default": "./src/create-version/index.js"
|
|
@@ -71,7 +75,8 @@
|
|
|
71
75
|
"check": "pnpm typecheck && pnpm test",
|
|
72
76
|
"create-version": "node bin/beez-rp.js create-version",
|
|
73
77
|
"cv": "node bin/beez-rp.js create-version",
|
|
74
|
-
"prepack": "pnpm build:types"
|
|
78
|
+
"prepack": "pnpm build:types",
|
|
79
|
+
"prepublishOnly": "node bin/beez-rp.js guard-publish"
|
|
75
80
|
},
|
|
76
81
|
"devDependencies": {
|
|
77
82
|
"@types/node": "^24.13.4",
|
package/src/constants/cli.js
CHANGED
|
@@ -143,8 +143,177 @@ export const MAX_LISTED_ITEMS = 5;
|
|
|
143
143
|
/** Length of the abbreviated commit ids shown to the user. */
|
|
144
144
|
export const SHORT_SHA_LENGTH = 7;
|
|
145
145
|
|
|
146
|
+
/** Placeholders of the `artifact` pattern: the released version and the npm package name. */
|
|
147
|
+
export const ARTIFACT_VERSION_PLACEHOLDER = "{version}";
|
|
148
|
+
export const ARTIFACT_NAME_PLACEHOLDER = "{name}";
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Scope of a package name as `npm pack` and `pnpm pack` name the tarball: the
|
|
152
|
+
* leading `@` is dropped and the `/` becomes `-` (`@scope/pkg` → `scope-pkg`).
|
|
153
|
+
* The `scope` group keeps the scope without `@`.
|
|
154
|
+
*/
|
|
155
|
+
export const PACKAGE_SCOPE_PATTERN = /^@(?<scope>[^/]+)\//u;
|
|
156
|
+
|
|
157
|
+
/** Replacement of {@link PACKAGE_SCOPE_PATTERN} that yields the tarball base name prefix. */
|
|
158
|
+
export const PACKED_SCOPE_REPLACEMENT = "$<scope>-";
|
|
159
|
+
|
|
160
|
+
/** Wildcard of an `artifact` pattern segment, such as the checksum in `releases/{version}-*`. */
|
|
161
|
+
export const ARTIFACT_SEGMENT_WILDCARD = "*";
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Checksum placeholder: the SHA-256 of the archive, verified before publishing. It may repeat,
|
|
165
|
+
* in one segment or several, and every occurrence must declare the same digest.
|
|
166
|
+
*/
|
|
167
|
+
export const ARTIFACT_SHA256_PLACEHOLDER = "{sha256}";
|
|
168
|
+
|
|
169
|
+
/** Lowercase hexadecimal SHA-256 digest matched by {@link ARTIFACT_SHA256_PLACEHOLDER}. */
|
|
170
|
+
export const SHA256_HEX_PATTERN_SOURCE = "[0-9a-f]{64}";
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Characters allowed in an artifact path passed to `npm publish` through the Windows shell;
|
|
174
|
+
* `~` is allowed because npm package names (and so tarball names) may contain it.
|
|
175
|
+
*/
|
|
176
|
+
export const SAFE_ARTIFACT_PATH_PATTERN = /^[\w.@+~/-]+$/u;
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Prefix that makes npm read an artifact path as a local file: a bare
|
|
180
|
+
* `releases/x/pkg.tgz` operand is parsed as a package spec (a GitHub shorthand).
|
|
181
|
+
*/
|
|
182
|
+
export const LOCAL_PATH_PREFIX = "./";
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Arguments of the `npm pack` run that reports the integrity npm would pack from the release
|
|
186
|
+
* checkout: nothing is written and no lifecycle script runs, so it only reads what `prepare` left.
|
|
187
|
+
*/
|
|
188
|
+
export const NPM_PACK_DRY_RUN_ARGUMENTS = Object.freeze(["pack", "--dry-run", "--json", "--ignore-scripts"]);
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Prefix of the temporary directory, outside the package root, that holds the prepared archive
|
|
192
|
+
* while `npm pack --dry-run` runs, so npm never packs the archive into the package it describes.
|
|
193
|
+
*/
|
|
194
|
+
export const ARTIFACT_HOLDING_DIRECTORY_PREFIX = "beez-rp-artifact-";
|
|
195
|
+
|
|
196
|
+
/** Node.js error code of a `rename` across file systems, retried as copy and delete. */
|
|
197
|
+
export const CROSS_DEVICE_RENAME_ERROR_CODE = "EXDEV";
|
|
198
|
+
|
|
199
|
+
/** Hash algorithm of the npm `integrity` string (`sha512-<base64>`). */
|
|
200
|
+
export const NPM_INTEGRITY_ALGORITHM = "sha512";
|
|
201
|
+
|
|
202
|
+
/** npm `integrity` string as `npm pack --json` reports it. */
|
|
203
|
+
export const NPM_INTEGRITY_PATTERN = /^sha512-[A-Za-z0-9+/]+={0,2}$/u;
|
|
204
|
+
|
|
205
|
+
/** Manifest field whose keys npm applies as configuration when it publishes. */
|
|
206
|
+
export const PUBLISH_CONFIG_FIELD = "publishConfig";
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* `publishConfig` keys pnpm hoists onto the packed manifest root. npm treats every
|
|
210
|
+
* `publishConfig` key as npm configuration and never rewrites manifest fields with it, so a
|
|
211
|
+
* package that declares any of these would be published differently by npm than by `pnpm pack`.
|
|
212
|
+
* Any other key (`registry`, `access`, `tag`, `provenance`, `@scope:registry`, `otp`...) is npm
|
|
213
|
+
* configuration and is accepted.
|
|
214
|
+
*
|
|
215
|
+
* Source: `PUBLISH_CONFIG_WHITELIST` in pnpm v12.6.0
|
|
216
|
+
* (`pnpm/crates/exportable-manifest/src/create.rs`; same list as
|
|
217
|
+
* `releasing/exportable-manifest/src/overridePublishConfig.ts` in pnpm 11).
|
|
218
|
+
*
|
|
219
|
+
* @see https://github.com/pnpm/pnpm/blob/v12.6.0/pnpm/crates/exportable-manifest/src/create.rs
|
|
220
|
+
* @see https://docs.npmjs.com/cli/v11/configuring-npm/package-json#publishconfig
|
|
221
|
+
*/
|
|
222
|
+
export const PNPM_HOISTED_PUBLISH_CONFIG_KEYS = Object.freeze([
|
|
223
|
+
"name",
|
|
224
|
+
"bin",
|
|
225
|
+
"engines",
|
|
226
|
+
"type",
|
|
227
|
+
"imports",
|
|
228
|
+
"main",
|
|
229
|
+
"module",
|
|
230
|
+
"typings",
|
|
231
|
+
"types",
|
|
232
|
+
"exports",
|
|
233
|
+
"browser",
|
|
234
|
+
"esnext",
|
|
235
|
+
"es2015",
|
|
236
|
+
"unpkg",
|
|
237
|
+
"umd:main",
|
|
238
|
+
"os",
|
|
239
|
+
"cpu",
|
|
240
|
+
"libc",
|
|
241
|
+
"typesVersions",
|
|
242
|
+
]);
|
|
243
|
+
|
|
244
|
+
/** Dependency maps npm publishes as they are written in `package.json`. */
|
|
245
|
+
export const PUBLISHED_DEPENDENCY_FIELDS = Object.freeze(["dependencies", "peerDependencies", "optionalDependencies"]);
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Dependency specifiers only `pnpm pack` rewrites and npm publishes verbatim, which npm then
|
|
249
|
+
* cannot install (`EUNSUPPORTEDPROTOCOL`):
|
|
250
|
+
* - `catalog:` (dereferenced to the catalog entry);
|
|
251
|
+
* - `workspace:` (resolved to the linked package version), as the whole specifier or, in
|
|
252
|
+
* `peerDependencies`, as a segment of a compound range (`^1.0.0 || workspace:>=1.0.0`);
|
|
253
|
+
* - `jsr:` (turned into an `npm:@jsr/<scope>__<name>` alias).
|
|
254
|
+
*
|
|
255
|
+
* Source: `convert_dependency_for_publish` (catalog → workspace → jsr replacers) in pnpm v12.6.0
|
|
256
|
+
* `pnpm/crates/exportable-manifest/src/create.rs`, and `replace_workspace_protocol_peer_dependency`
|
|
257
|
+
* in `pnpm/crates/exportable-manifest/src/replace.rs`. No other protocol is rewritten there.
|
|
258
|
+
*
|
|
259
|
+
* @see https://github.com/pnpm/pnpm/blob/v12.6.0/pnpm/crates/exportable-manifest/src/create.rs
|
|
260
|
+
* @see https://github.com/pnpm/pnpm/blob/v12.6.0/pnpm/crates/exportable-manifest/src/replace.rs
|
|
261
|
+
*/
|
|
262
|
+
export const PNPM_PACK_REWRITTEN_SPECIFIER_PATTERN = /^(?:workspace|catalog|jsr):|\|\|\s*workspace:/u;
|
|
263
|
+
|
|
264
|
+
/** Public npm registry: npm's default, used when no config sets `@scope:registry` nor `registry`. */
|
|
265
|
+
export const DEFAULT_NPM_REGISTRY_URL = "https://registry.npmjs.org/";
|
|
266
|
+
|
|
267
|
+
/** Prefix of a package page on npmjs.com, linked in the summary of a release published to {@link DEFAULT_NPM_REGISTRY_URL}. */
|
|
268
|
+
export const NPMJS_PACKAGE_PAGE_URL = "https://www.npmjs.com/package/";
|
|
269
|
+
|
|
270
|
+
/** `publishConfig` key of the registry for every package, used when no scope-specific registry applies. */
|
|
271
|
+
export const PUBLISH_CONFIG_REGISTRY_KEY = "registry";
|
|
272
|
+
|
|
273
|
+
/** Suffix of the scope-specific `publishConfig` registry key, as in `@scope:registry`. */
|
|
274
|
+
export const SCOPED_REGISTRY_KEY_SUFFIX = ":registry";
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Registry URL allowed on the `npm view` command line built for the Windows shell: only characters
|
|
278
|
+
* without shell meaning (no `%`, `&`, `|`, `^`, quotes or spaces), after URL normalization.
|
|
279
|
+
*/
|
|
280
|
+
export const SHELL_SAFE_REGISTRY_URL_PATTERN = /^https?:\/\/[\w.~:/@+-]+$/u;
|
|
281
|
+
|
|
282
|
+
/** npm option that selects the registry `npm view` queries. */
|
|
283
|
+
export const NPM_REGISTRY_OPTION = "--registry";
|
|
284
|
+
|
|
285
|
+
/** npm option that replaces the user config (`~/.npmrc`) with the temporary one. */
|
|
286
|
+
export const NPM_USER_CONFIG_OPTION = "--userconfig";
|
|
287
|
+
|
|
288
|
+
/** npm subcommand that prints the effective value of a config key. */
|
|
289
|
+
export const NPM_CONFIG_GET_ARGUMENTS = Object.freeze(["config", "get"]);
|
|
290
|
+
|
|
291
|
+
/** What `npm config get` prints for a key no config source sets, such as an unused `@scope:registry`. */
|
|
292
|
+
export const NPM_UNSET_CONFIG_VALUE = "undefined";
|
|
293
|
+
|
|
294
|
+
/** Protocols a publish registry URL may use. */
|
|
295
|
+
export const NPM_REGISTRY_PROTOCOLS = Object.freeze(["http:", "https:"]);
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Value of the registry credential in the temporary npm config: npm expands `${NPM_TOKEN}` from
|
|
299
|
+
* the environment, so the token never reaches the disk or a command line.
|
|
300
|
+
*/
|
|
301
|
+
export const NPM_AUTH_TOKEN_REFERENCE = `\${${NPM_TOKEN_VARIABLE}}`;
|
|
302
|
+
|
|
303
|
+
/** Prefix of the temporary directory holding the publish-only npm user config. */
|
|
304
|
+
export const NPM_AUTH_DIRECTORY_PREFIX = "beez-rp-npm-auth-";
|
|
305
|
+
|
|
306
|
+
/** Characters that could break out of a quoted path on the Windows shell. */
|
|
307
|
+
export const UNSAFE_QUOTED_PATH_PATTERN = /["%]/u;
|
|
308
|
+
|
|
146
309
|
/** Placeholder replaced by the released version in `summary` lines. */
|
|
147
310
|
export const SUMMARY_VERSION_PLACEHOLDER = "{version}";
|
|
148
311
|
|
|
312
|
+
/**
|
|
313
|
+
* Shown when syncing `main` brought new commits: the run ends (exit code 0, it is not a failure)
|
|
314
|
+
* so the next one loads the updated configuration and diagnoses again.
|
|
315
|
+
*/
|
|
316
|
+
export const MAIN_SYNCED_RESTART_MESSAGE = `${MAIN_BRANCH} se actualizó desde origin: volvé a correr pnpm create-version para diagnosticar con el código y la configuración nuevos.`;
|
|
317
|
+
|
|
149
318
|
/** Exit code of a release stopped by a failed step, invalid arguments or configuration. */
|
|
150
319
|
export const FAILURE_EXIT_CODE = 1;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contract of `beez-rp guard-publish`, the `prepublishOnly` guard that keeps
|
|
3
|
+
* Beez packages from being published by a package manager other than npm.
|
|
4
|
+
*
|
|
5
|
+
* @module constants/guard-publish
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Environment variable package managers set for lifecycle scripts, for
|
|
10
|
+
* example `pnpm/12.6.0 npm/? node/v24.21.0 win32 x64`. npm also reads it as its
|
|
11
|
+
* `user-agent` config, so an inherited value survives `npm publish`.
|
|
12
|
+
*/
|
|
13
|
+
export const PACKAGE_MANAGER_USER_AGENT_VARIABLE = "npm_config_user_agent";
|
|
14
|
+
|
|
15
|
+
/** User agent prefix of npm, the only package manager allowed to publish. */
|
|
16
|
+
export const ALLOWED_PUBLISH_USER_AGENT_PREFIX = "npm/";
|
|
17
|
+
|
|
18
|
+
/** Package managers whose `publish` is blocked, keyed by their user agent prefix. */
|
|
19
|
+
export const BLOCKED_PUBLISH_PACKAGE_MANAGERS = Object.freeze({
|
|
20
|
+
"pnpm/": "pnpm",
|
|
21
|
+
"yarn/": "yarn",
|
|
22
|
+
"bun/": "bun",
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
/** Exit codes of `beez-rp guard-publish`. */
|
|
26
|
+
export const GUARD_PUBLISH_EXIT_CODE = Object.freeze({
|
|
27
|
+
allowed: 0,
|
|
28
|
+
blocked: 1,
|
|
29
|
+
});
|
package/src/constants/index.js
CHANGED
|
@@ -8,6 +8,7 @@ export * from "./build-gate.js";
|
|
|
8
8
|
export * from "./changelog.js";
|
|
9
9
|
export * from "./changelog-ai.js";
|
|
10
10
|
export * from "./cli.js";
|
|
11
|
+
export * from "./guard-publish.js";
|
|
11
12
|
export * from "./terminal-ui.js";
|
|
12
13
|
export * from "./versions.js";
|
|
13
14
|
export * from "./create-version.js";
|