From 12baee7051308aec41841b21c9fccde00a53af67 Mon Sep 17 00:00:00 2001 From: Stuart Corbishley Date: Tue, 20 Oct 2026 07:33:01 +0200 Subject: [PATCH 1/4] Rewrite CLAUDE.md to match the current repo Fixes stale commands and facts, adds how to run a single test and the integration suites, explains how the CLI, worker and engine fit together, and drops material that restates package.json or the directory layout. --- CLAUDE.md | 183 ++++++++++++++---------------------------------------- 1 file changed, 48 insertions(+), 135 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 5e314906f..8e716399b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,165 +1,78 @@ -# OpenFn Kit +# CLAUDE.md -This monorepo contains the core packages that power OpenFn's workflow automation platform. OpenFn is a Digital Public Good trusted by NGOs and governments in 40+ countries to automate data integration workflows. +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. -## Architecture +OpenFn kit is the pnpm monorepo behind OpenFn's workflow automation: the CLI, the Runtime that executes jobs, and the Worker that runs jobs in production for Lightning (OpenFn's web platform). -The repository has three main packages: **CLI**, **Runtime**, and **Worker**. The CLI and Worker are both frontends for executing workflows - the CLI for local development, the Worker for production execution via Lightning (the web platform). Both wrap the Runtime as their execution engine. The Worker uses engine-multi to wrap the Runtime for multi-process execution. +## How the pieces fit -## Core Packages +- **@openfn/runtime** executes a workflow plan in a sandboxed Node VM. A workflow is a graph of steps (jobs) joined by conditional edges. A job is an array of operations, each a function from state to state. State is never mutated between jobs. +- **@openfn/compiler** turns job DSL into a standard ES module that imports from its adaptor (an npm package such as `@openfn/language-http`) and exports the operations array. +- **@openfn/cli** is the local frontend. It compiles jobs itself and calls the runtime in-process. +- **@openfn/ws-worker** is the production frontend. It is stateless: it claims runs from Lightning over websockets and reports events back, and Lightning owns all persistence. It never imports the compiler. It hands plans to **@openfn/engine-multi**, which compiles and runs each one in a worker thread inside a child process. +- **@openfn/project** models local projects and workspaces (`Workspace`, `Project`, YAML parsing, diffs, version hashes). The CLI's `project` handlers in `packages/cli/src/projects/` are thin layers over it, and this is the most actively developed area of the repo. Sync with Lightning uses its v2 endpoint. +- Supporting: `lexicon` (shared types), `logger`, `lightning-mock` (fake Lightning for worker tests), `deploy` and `describe-package` (both being phased out). -- **[@openfn/cli](packages/cli)** - Command-line interface for local development. Run, test, compile, and deploy workflows. -- **[@openfn/runtime](packages/runtime)** - Core execution engine. Safely executes jobs in a sandboxed VM environment. -- **[@openfn/ws-worker](packages/ws-worker)** - WebSocket worker connecting Lightning to the Runtime. Stateless server that pulls runs from Lightning's queue. See [.claude/event-processor.md](.claude/event-processor.md) for event processing details. -- **[@openfn/engine-multi](packages/engine-multi)** - Multi-process runtime wrapper used by ws-worker for concurrent workflow execution. -- **[@openfn/compiler](packages/compiler)** - Transforms OpenFn job DSL into executable JavaScript modules. +Every internal dependency is `workspace:*` and resolves to the dependency's built `dist/`, not its `src/`. engine-multi also runs its worker processes from `dist/`. -## Supporting Packages +## Commands -- **@openfn/lexicon** - Shared TypeScript types -- **@openfn/logger** - Structured logging utilities -- **@openfn/describe-package** - TypeScript analysis for adaptor docs (to be phased out) -- **@openfn/deploy** - Deployment logic for Lightning (soon to be deprecated) -- **@openfn/project** - Models and understands local OpenFn projects -- **@openfn/lightning-mock** - Mock Lightning server for testing - -## AI Assistant - -- Keep responses terse and do not over-explain. Users will ask for more guidance if they need it. -- Always present users a short action plan and ask for confirmation before doing it -- Keep the human in the loop at all times. Stop regularly and check for guidance. - -## Key Concepts - -**Workflows** are sequences of **jobs** that process data through steps. Each **job** is an array of **operations** (functions that transform state). State flows between jobs based on conditional edges. - -**Adaptors** are npm packages (e.g., `@openfn/language-http`) providing operations for specific systems. The CLI auto-installs them as needed. - -The **Compiler** transforms job DSL code into standard ES modules with imports and operation arrays. - -## Working with Projects - -A **workspace** holds one or more local **projects** that sync with Lightning. The CLI `project` subcommand (package: `@openfn/project`) is the most actively-developed area of the repo; handlers live in `packages/cli/src/projects/`. Sync uses Lightning's v2 endpoint. +Node is pinned in `.tool-versions` (use `asdf`), and pnpm switches itself to the version pinned in `packageManager` (install any pnpm with `npm install -g pnpm`; corepack no longer ships with Node). ```bash -openfn project list # List projects in the current workspace -openfn project pull [project] # Pull from Lightning to the filesystem (fetch + checkout) -openfn project fetch [project] # Download project state without expanding it -openfn project checkout # Switch the active project in the workspace -openfn project deploy [project] # Deploy the checked-out project to Lightning -openfn project clean # Delete the workflows folder and re-checkout the active project -openfn project version [workflow] # Show the version hash of a workflow +pnpm install +pnpm build # all packages +pnpm --filter @openfn/cli build # one package +pnpm test # all package tests +pnpm test:types # tsc per package +pnpm format / pnpm test:format # prettier write / check (there is no eslint) +pnpm _typesync # after changing dependencies ``` -New subcommands follow the existing pattern in `packages/cli/src/projects/` (`list.ts` is the simplest reference). - -## Development Setup - -### Prerequisites - -- Node.js 24 (pinned in `.tool-versions`; `package.json` engines still allows `>=18`). Use `asdf`. -- pnpm (enable with `corepack enable`) - -### Common Commands +Tests use ava with the shared root `ava.config.js`, which runs `test/**/*test.ts` straight from `src/` via `@swc-node/register`. Because workspace deps come from `dist/`, run `pnpm build` first when a test crosses packages or uses engine-multi. When unsure, build. ```bash -# Root -pnpm install # Install dependencies -pnpm build # Build all packages -pnpm test # Run all tests -pnpm format # Format all packages with Prettier -pnpm changeset # Add a changeset for your PR - -# CLI -cd packages/cli -pnpm openfn test # Run from source -pnpm install:global # Install as 'openfnx' for testing - -# Worker -cd packages/ws-worker -pnpm start # Connect to localhost:4000 -pnpm start -l mock # Use mock Lightning -pnpm start --no-loop # Disable auto-fetch -curl -X POST http://localhost:2222/claim # Manual claim +cd packages/project +pnpm ava test/util/config.test.ts # one file +pnpm ava test/util/config.test.ts -m "name*" # tests matching a title ``` -### Environment Variables - -**CLI:** -- `OPENFN_REPO_DIR` - CLI adaptor storage -- `OPENFN_ADAPTORS_REPO` - Local adaptors monorepo path -- `OPENFN_API_KEY` - API key for Lightning deployment -- `OPENFN_ENDPOINT` - Lightning URL (default: app.openfn.org) - -**Worker:** -- `WORKER_SECRET` - Worker authentication secret -- Many other `WORKER_*` vars (capacity, port, backoff, max payload, Sentry DSN, …) — see `packages/ws-worker/src/util/cli.ts`. - -## Repository Structure - -``` -packages/ -├── cli/ # CLI entry: cli.ts, commands.ts, projects/, options.ts -├── runtime/ # Runtime entry: index.ts, runtime.ts, modules/linker -├── ws-worker/ # Worker entry: start.ts, server.ts, api/, events/ -├── compiler/ # Job DSL compiler -├── engine-multi/ # Multi-process wrapper -├── lexicon/ # Shared TypeScript types -└── logger/ # Logging utilities -``` - -## Testing & Releases - -```bash -pnpm test # All tests -pnpm test:types # Type checking -pnpm test:integration # Integration tests -cd packages/cli && pnpm test:watch # Watch mode -``` +ws-worker and engine-multi run with `--serial`; keep new tests there compatible with that. -## Testing Best Practice +### Running things locally -- Ensure tests are valuable before generating them. Focus on what's important. -- Treat tests as documentation: they should show how the function is expected to work -- Keep tests focuses: test one thing in each test -- This repo contains extensive testing: check for similar patterns in the same package before improvising +- **CLI**: `cd packages/cli && pnpm openfn ` runs the built `dist/`, so rebuild (or `pnpm build:watch`) after changes. `pnpm install:global` from root installs a global `openfnx` for testing; remove it with `npm uninstall -g @openfn/clix`. +- **Worker**: `cd packages/ws-worker && pnpm start` connects to Lightning at `localhost:4000`. `-l mock` uses the mock Lightning, `--mock` uses a mock engine, and `--no-loop` stops auto-claiming so you can trigger claims with `curl -X POST http://localhost:2222/claim`. Options and their `WORKER_*` env vars are in `packages/ws-worker/src/util/cli.ts`. +- CLI env vars (`OPENFN_API_KEY`, `OPENFN_ENDPOINT`, `OPENFN_REPO_DIR`, `OPENFN_ADAPTORS_REPO`, and others) are defined in `packages/cli/src/options.ts` and `packages/cli/src/projects/options.ts`. -## Additional Documentation +### Integration tests -**Changesets**: Run `pnpm changeset` when submitting PRs. Releases publish automatically to npm on merge to main. +These live in `integration-tests/` (`cli`, `execute`, `worker`, `legacy-deploy`) and run against built packages. Always `pnpm build` first. -Changeset release notes must be a **single, short, high-level sentence** - vague is fine (e.g. `added new "compile-test" command to the CLI` or `Tighten guards against shell injection vectors`). Do not list files, functions, or implementation detail. For breaking changes only, you may add a short migration guide after the sentence. See the package `CHANGELOG.md` files for the house style. +- `pnpm test:integration` from root runs them all. +- In `integration-tests/cli`, `pnpm test:dev` uses the local `packages/cli/dist`. Plain `pnpm test` expects a globally installed `openfn`, which is how CI runs it: `pnpm pack:local` then install the tarball globally. -The [.claude](.claude) folder contains detailed guides: +## Adding a CLI command -- **[event-processor.md](.claude/event-processor.md)** - Worker event processing deep-dive (ordering, batching) — companion to `packages/ws-worker/CLAUDE.md` -- **[yaml-formats.md](.claude/yaml-formats.md)** - v1 vs v2 project YAML formats: structure, detection logic, and conversion paths -- **[unit-testing-jobs.md](.claude/unit-testing-jobs.md)** - How to compile job for unit-testing +Commands are yargs modules registered in `packages/cli/src/cli.ts`. Each module calls `ensure('', ...)` (`util/command-builders.ts`) to set `argv.command`, and `packages/cli/src/commands.ts` dispatches that string to a handler. A new `project` subcommand needs all three of: -Key packages also carry their own `CLAUDE.md` (runtime, engine-multi, ws-worker), auto-loaded when you work in them. +1. a yargs module added in `packages/cli/src/projects/command.ts`; +2. the handler exported from `packages/cli/src/projects/index.ts`; +3. an entry in the `handlers` map and the `CommandList` union in `commands.ts`. -## Code Standards +`packages/cli/src/projects/list.ts` is the simplest example to copy. -- **Formatting**: Use Prettier (`pnpm format`) -- **TypeScript**: Required for all new code -- **TypeSync**: Run `pnpm _typesync` after modifying dependencies -- **Tests**: Each package's tests run against its own `src/` via `@swc-node/register` (no build of the package under test needed). BUT workspace `@openfn/*` deps resolve to their built `dist/`, and `engine-multi` runs its worker processes from `dist/` — so run `pnpm build` first when tests cross packages or use the engine. When unsure, build. -- **Independence**: Keep packages loosely coupled where possible +## Changesets and releases -## Architecture Principles +Every PR that changes a published package needs a changeset (`pnpm changeset`). The release note is a **single, short, high-level sentence**, and vague is fine (e.g. `added new "compile-test" command to the CLI`). Leave out files, functions and implementation detail. Breaking changes may add a short migration guide after the sentence. The package `CHANGELOG.md` files show the house style. -- **Separation of Concerns**: CLI and Worker are frontends; Runtime is the shared execution backend -- **Sandboxing**: Runtime uses Node's VM module for isolation -- **State Immutability**: State cannot be mutated between jobs -- **Portability**: Compiled jobs are standard ES modules -- **Zero Persistence (Worker)**: Worker is stateless; Lightning handles persistence -- **Multi-Process Isolation**: Worker uses engine-multi for concurrent workflow execution +Releases are prepared by hand on a release branch: run `pnpm changeset version`, check the changelogs, run `pnpm install`, and commit. Merging to main then publishes to npm and builds the worker Docker image. A brand-new package must be published once first with `pnpm publish:new`; see `README.md`. -## Contributing +## Further guides -1. Make changes -2. Run `pnpm test` -3. Add changeset: `pnpm changeset` -4. Open PR at https://github.com/openfn/kit +Read these before working in the matching area: -**Resources**: [docs.openfn.org](https://docs.openfn.org) | [app.openfn.org](https://app.openfn.org) | [github.com/openfn/kit](https://github.com/openfn/kit) +- [.claude/event-processor.md](.claude/event-processor.md): how the worker orders and batches events sent to Lightning. +- [.claude/yaml-formats.md](.claude/yaml-formats.md): v1 vs v2 project YAML, how each is detected, and how they convert. +- [.claude/unit-testing-jobs.md](.claude/unit-testing-jobs.md): compiling a job so it can be unit tested. +- `packages/runtime`, `packages/engine-multi` and `packages/ws-worker` each have their own `CLAUDE.md`, loaded automatically when you work there. From a5997d1c70865e47daab3852bf48d08262aba39c Mon Sep 17 00:00:00 2001 From: Stuart Corbishley Date: Tue, 20 Oct 2026 07:33:08 +0200 Subject: [PATCH 2/4] Fix stale typesync and runtime-manager references The typesync script is `_typesync`, and runtime-manager was renamed to engine-multi long ago, so the worker's start:watch was watching a path that no longer exists. --- README.md | 2 +- packages/ws-worker/README.md | 2 +- packages/ws-worker/package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 42e1e85ba..8fdcee997 100644 --- a/README.md +++ b/README.md @@ -127,7 +127,7 @@ This repo uses `typesync` to ensure that all packages have an appropriate `@type This must be run MANUALLY (See https://github.com/OpenFn/kit/issues/333) -On every add, update and remove. you should do `pnpm run typesync` from the repo root. +On every add, update and remove. you should do `pnpm _typesync` from the repo root. Note that @types packages only synchronise with the major and minor versions of a package. So for `@types/x@major.minor.patch`, `major` and `minor` refer to the versions of the corresponding package `x`, and `patch` is the version number of the actual types package. diff --git a/packages/ws-worker/README.md b/packages/ws-worker/README.md index b11b611eb..0bd17d0a3 100644 --- a/packages/ws-worker/README.md +++ b/packages/ws-worker/README.md @@ -109,7 +109,7 @@ You can start a dev server (which rebuilds on save) by running: pnpm start:watch ``` -This will wrap a real runtime engine into the server. It will rebuild when the Worker Engine code changes (although you'll have to `pnpm build:watch` in `runtime-manager`). This will use the repo at `WORKER_REPO_DIR` (or a default path in /tmp) +This will wrap a real runtime engine into the server. It will rebuild when the Worker Engine code changes (although you'll have to `pnpm build:watch` in `engine-multi`). This will use the repo at `WORKER_REPO_DIR` (or a default path in /tmp) ### Disabling auto-fetch diff --git a/packages/ws-worker/package.json b/packages/ws-worker/package.json index 1d31e658a..9a07513dc 100644 --- a/packages/ws-worker/package.json +++ b/packages/ws-worker/package.json @@ -14,7 +14,7 @@ "build:watch": "pnpm build --watch", "start": "node --loader @swc-node/register/esm src/start.ts", "start:prod": "node dist/start.js", - "start:watch": "nodemon -e ts,js --watch ../runtime-manager/dist --watch ./src --exec 'pnpm start'", + "start:watch": "nodemon -e ts,js --watch ../engine-multi/dist --watch ./src --exec 'pnpm start'", "pack": "pnpm pack --pack-destination ../../dist" }, "bin": { From 7e2acab3a8d5a047f6c07e19c226ada5a3753061 Mon Sep 17 00:00:00 2001 From: Stuart Corbishley Date: Tue, 20 Oct 2026 07:33:08 +0200 Subject: [PATCH 3/4] Install pnpm without corepack Corepack no longer ships with Node from v25. pnpm reads packageManager and switches itself to the pinned version, so any installed pnpm will do: CI uses the one preinstalled in the cimg/node images, and the worker image installs the pinned version with npm. Refs #1563 --- .circleci/config.yml | 3 --- Dockerfile | 2 +- README.md | 4 ++-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 41d5e1fdc..3c836c967 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -21,9 +21,6 @@ jobs: # Add steps to the job # See: https://circleci.com/docs/2.0/configuration-reference/#steps steps: - - run: - name: Install pnpm - command: sudo npm install -g corepack@latest && sudo corepack enable - checkout - restore_cache: # See the configuration reference documentation for more details on using restore_cache and save_cache steps diff --git a/Dockerfile b/Dockerfile index 4b6db835a..3bb4b610f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,9 @@ FROM node:24-alpine AS base ENV PNPM_HOME="/pnpm" ENV PATH="$PNPM_HOME:$PATH" -RUN corepack enable COPY . /app WORKDIR /app +RUN npm install -g "$(node -p "require('./package.json').packageManager.split('+')[0]")" # TODO: use prod optimized build? ---------------------------------------------- # FROM base AS build diff --git a/README.md b/README.md index 8fdcee997..f83586595 100644 --- a/README.md +++ b/README.md @@ -39,9 +39,9 @@ We use [`pnpm`](https://pnpm.io/installation), a fast, disk space efficient pack ## Installing -This repo uses node corepack to ensure pnpm v8 is used +Install pnpm globally. When run inside this repo, pnpm reads the `packageManager` field in `package.json` and switches itself to the pinned version. -- `$ corepack enable` +- `$ npm install -g pnpm` - `$ pnpm install` - `$ pnpm build` From 801938e31ed8aa0516c406a5927aa688bffa3631 Mon Sep 17 00:00:00 2001 From: Joe Clark Date: Tue, 20 Oct 2026 12:01:12 +0100 Subject: [PATCH 4/4] drive pnpm version from devengines declaring the vesion on devengines.packagemanager seems to work better with pnpm. it'll automatically download the correct version, so all users can read pnpm frm the same place No need for asdf (which js dev community won't use) or corepack this way. The docker build has been simplified and should also use the declared pnpm version --- Dockerfile | 2 +- package.json | 15 +++++- pnpm-lock.yaml | 122 ++++++++++++++++++++++++------------------------- 3 files changed, 75 insertions(+), 64 deletions(-) diff --git a/Dockerfile b/Dockerfile index 3bb4b610f..27bca2850 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,7 +3,7 @@ ENV PNPM_HOME="/pnpm" ENV PATH="$PNPM_HOME:$PATH" COPY . /app WORKDIR /app -RUN npm install -g "$(node -p "require('./package.json').packageManager.split('+')[0]")" +RUN npm install -g pnpm # TODO: use prod optimized build? ---------------------------------------------- # FROM base AS build diff --git a/package.json b/package.json index f3d638003..3febabd3b 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,18 @@ "version": "1.0.0", "private": true, "description": "Packages to support OpenFn v2", + "devEngines": { + "runtime": { + "name": "node", + "version": "26.x", + "onFail": "warn" + }, + "packageManager": { + "name": "pnpm", + "version": "12.14.0", + "onFail": "download" + } + }, "scripts": { "build": "pnpm run clean && pnpm -r --filter=./packages/* run build", "clean:local": "rimraf dist/**/*", @@ -40,6 +52,5 @@ "semver": "^7.7.4", "tar-stream": "^3.1.8", "yargs": "^17.7.2" - }, - "packageManager": "pnpm@12.6.0+sha512.3ef68f951cb111ac204b4a5a16f0b2ddf0da56a96e0413e81d855d9f0b55ef926714709028e1cd00c405c2c5fb7b9e8ec4dc46777c805d0373c2f2ff00fd20ec" + } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4a741c902..e9436f991 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,153 +7,153 @@ importers: configDependencies: {} packageManagerDependencies: pnpm: - specifier: 12.6.0 - version: 12.6.0 + specifier: 12.14.0 + version: 12.14.0 packages: - '@pnpm/exe.android-arm64@12.6.0': - resolution: {integrity: sha512-kviIHft9h02q+7N2In7tSL9T/HRUSGwYmU74YPtsWU5ee7vgqPyC0JT6RRX6miW+NxX1CvHgQxg69qq1qTLJYQ==} + '@pnpm/exe.android-arm64@12.14.0': + resolution: {integrity: sha512-+iSh7x21C3A2hqc+Z0ZmbKTcn6YNlzrXM142PsnQH/dLj0DYxFzoBvc6XAnL/yfQ5nnH2ebBiRj/zVxr61fZbQ==} cpu: [arm64] os: [android] - '@pnpm/exe.android-x64@12.6.0': - resolution: {integrity: sha512-CT8aJKLq2mtZFE71pr4E5Z2xHL8uGnRGr+NclDqsXlVF4SVcQ2QAs14mWi0C8gjT4hbmi+Q0lJRRIkMAWfjjng==} + '@pnpm/exe.android-x64@12.14.0': + resolution: {integrity: sha512-qT+0LqEr2wBVaxcG2T8cX/R8SSRz2Rvpp8nRR4fh8tnGUZRch87gFmsHUAoSQh7w6j1h0qTjrA384j4xi8frvw==} cpu: [x64] os: [android] - '@pnpm/exe.darwin-arm64@12.6.0': - resolution: {integrity: sha512-rafpVkjzugKBMxSvGQd5wK1x5eOTkD/+lcJIFHeQhvd+BJ8kDisOOvwhQDrpGd4vd2Fx+hhW0P2Ptt638OlhFg==} + '@pnpm/exe.darwin-arm64@12.14.0': + resolution: {integrity: sha512-tnrdUB8ecJoehuKKqi1YHCBVl61xtJ9XVGcx5EviC6fWO4DeGI8GtXrjvJxDBM3nuVjJeWistgsUp/N142x4sw==} cpu: [arm64] os: [darwin] - '@pnpm/exe.darwin-x64@12.6.0': - resolution: {integrity: sha512-72Jpuv1m24gI8zUNcaylYpBWEhBzz1VPhnDIU2GYM2eRP+KsOqVLwV78i+JrihI39zY2NNXmaN4eAKX1inpaDQ==} + '@pnpm/exe.darwin-x64@12.14.0': + resolution: {integrity: sha512-vlBfGkruqQRsEHTW43cPwpYd7QlbIJ//cvpAdb3bVXkI8SgTPoXhCnc05m+ZNiPrrEkBsX/t7KHw9aXpkzPm3Q==} cpu: [x64] os: [darwin] - '@pnpm/exe.freebsd-x64@12.6.0': - resolution: {integrity: sha512-LON4QgNy1w/XF4uySZIyC/5hEB0oGdelXsY9tSKqstER+2j2X2oHz67skD11RRd/HWFRtMr64shQZ4I9ZoZ0zg==} + '@pnpm/exe.freebsd-x64@12.14.0': + resolution: {integrity: sha512-Qg5rxBrGYl6Tfso+EyygPf84fY1Fzy55E/0or+iuYKtnf0vc0MlHJfVIlT7pBukMRntQHRik7hUi0Z4s7AlJsw==} cpu: [x64] os: [freebsd] - '@pnpm/exe.linux-arm64-musl@12.6.0': - resolution: {integrity: sha512-BdDpX+DeaMUc5x6WNcE6FkmFy36NwrBbBvwsZU737Zt3u1fTY+iKFPchjEQNCM4rT6q6xvF2oN3ZwExGsJCkxQ==} + '@pnpm/exe.linux-arm64-musl@12.14.0': + resolution: {integrity: sha512-DRIe4yQkXBGA/PhVJdzlbnllxBdAtnMMvTVLLcGpsK5FvJz9kxD2Hyxtn68ovmNkVX06f6p45cQwfm3wx2jn1A==} cpu: [arm64] os: [linux] libc: [musl] - '@pnpm/exe.linux-arm64@12.6.0': - resolution: {integrity: sha512-8h2sNoIhHDpHDYqZZCh9PXr6krqW10btb0GHVGuw710muDHlFAHMtUG2ogmaHge6zJG1xgY4Y7mwX5g/LWvrYg==} + '@pnpm/exe.linux-arm64@12.14.0': + resolution: {integrity: sha512-7joGShZ44Nk3WpNU+60JoOPjCXlgxhJAq11S2UiVtwCUDgTer1yTPPfxGW8pxaD6046actYLIYDbZNlubHWs0A==} cpu: [arm64] os: [linux] libc: [glibc] - '@pnpm/exe.linux-ppc64@12.6.0': - resolution: {integrity: sha512-ld6xgcEhFCFrsVsJhbmdmR714PnsEspO/Ij8w0/D7OSiz2hYGu3fZd5tKRxOI5m6H6Gl0/RRFAPncTHbsgXVjQ==} + '@pnpm/exe.linux-ppc64@12.14.0': + resolution: {integrity: sha512-gSoryn7ySdXd//gjgf3MvvA8ZerJayaSbuMZMtAWq4vb2/wlVEgpl0Kvqt54y58TRj533Qjq2txKgnxd4JyoAQ==} cpu: [ppc64] os: [linux] libc: [glibc] - '@pnpm/exe.linux-riscv64@12.6.0': - resolution: {integrity: sha512-HIbImydoC3J8NFt+8MXfhTCf5rO6NjCMyinSAHac0VmV8uCHw+kbQkyAzxV84rzz9ZOzmBOnj0b1N461UIYGsw==} + '@pnpm/exe.linux-riscv64@12.14.0': + resolution: {integrity: sha512-EMjew1H9WqQ7pL+tYqCPwiuB+0PeCiJRV7fyWeuFw0wwYUajFBjcaPO3IGAVu9sdmJDU+e+HYv/Zey6aKae0Vw==} cpu: [riscv64] os: [linux] libc: [glibc] - '@pnpm/exe.linux-s390x@12.6.0': - resolution: {integrity: sha512-DjSqT7+BZ/lWcDHwNMuzsRVfyxUimh+D54Xw4tSWbdVVQhtWtNMUyI93LVnwCmsoEpar2gC3SFeAgywx37svKQ==} + '@pnpm/exe.linux-s390x@12.14.0': + resolution: {integrity: sha512-shYOj/SFoXD35fHe0pWr2JofwSXulC0BnEIXLj2QokDi0EF//AfKsui35yKIkTEl+s2VJybc3PO4iJNhKIj5Qw==} cpu: [s390x] os: [linux] libc: [glibc] - '@pnpm/exe.linux-x64-musl@12.6.0': - resolution: {integrity: sha512-31lKeGPmRE6xfV6I3VjaEGVFRei14pl/zgoFDK4w+UkbJqOuNl2Ht3O1GuqNIg3Gl14qTEb4kZRAYFHXifDx9A==} + '@pnpm/exe.linux-x64-musl@12.14.0': + resolution: {integrity: sha512-btZiZ2Ot0llKK1ndSfA5i3IRX7/S0VrmzseNH/BJ4c+Cady+S81H6vvU1zByggHMyqQhC8OgxO5PiIY7D9bH0Q==} cpu: [x64] os: [linux] libc: [musl] - '@pnpm/exe.linux-x64@12.6.0': - resolution: {integrity: sha512-qFWBneHJAJ73W4whtbaFOL1M/7DBC6ILHXuxc7ZPtEhfPuT1zeZiGrmKHoMAfJA+mcm6xhOFljqVTUS+00Jabw==} + '@pnpm/exe.linux-x64@12.14.0': + resolution: {integrity: sha512-F6K8e/jWxiuEYJaQtRRUG9ynBSTEHa+t7Lf86MKuOO5UA7WVVMbi+oB8nY6iKW++ncWS2yG6T9faXZGxqNsfoQ==} cpu: [x64] os: [linux] libc: [glibc] - '@pnpm/exe.win32-arm64@12.6.0': - resolution: {integrity: sha512-OhfefXEEykZlslSUhR8PPRe6MVPV3Oink/dVfIecE5velpc7j80cZYsHlaDrtRDcm3TPwQHkaRW1SJ1efX9oFg==} + '@pnpm/exe.win32-arm64@12.14.0': + resolution: {integrity: sha512-DOjlkVB6TtTKeAAe0hNZXn5S7YqESmo1Z6SGbR4BZNQ4isRg31XVHjX2RFTbY8gnZq68IwzyLmPqlEjMmYxofg==} cpu: [arm64] os: [win32] - '@pnpm/exe.win32-x64@12.6.0': - resolution: {integrity: sha512-L2tuyrD2+Imgxs3VK/ST/2L3xD6vDP0ktJQxM0TaGw7TbAQEMq+RMc8iK6Ew7Id579uzjJe8jSfJID2ZGsOHCA==} + '@pnpm/exe.win32-x64@12.14.0': + resolution: {integrity: sha512-/LSX6mew/sLf08XqcjemuklNKf1K/Ftpgj4//hK/HKzI2dKbmxDB27a/2OaQ5a0O3/3OFzlssXDziZsi+yVBwQ==} cpu: [x64] os: [win32] - pnpm@12.6.0: - resolution: {integrity: sha512-PvaPlRyxEawgS0paFvCy3fDaVqluBBPoHYVdnwtV75JnFHCQKOHNAMQFwsX7e56OxNxGd3yAXQNzwvL/AP0g7A==} + pnpm@12.14.0: + resolution: {integrity: sha512-wYum2HmT09Fky16JSPMrLAbuhUSH4GzY2GeBNC+z5btGNDZwNHEehoArqpw3vqkGzhkprQjXCITJfYAd8TOJpg==} engines: {node: '>=18.*'} hasBin: true snapshots: - '@pnpm/exe.android-arm64@12.6.0': + '@pnpm/exe.android-arm64@12.14.0': optional: true - '@pnpm/exe.android-x64@12.6.0': + '@pnpm/exe.android-x64@12.14.0': optional: true - '@pnpm/exe.darwin-arm64@12.6.0': + '@pnpm/exe.darwin-arm64@12.14.0': optional: true - '@pnpm/exe.darwin-x64@12.6.0': + '@pnpm/exe.darwin-x64@12.14.0': optional: true - '@pnpm/exe.freebsd-x64@12.6.0': + '@pnpm/exe.freebsd-x64@12.14.0': optional: true - '@pnpm/exe.linux-arm64-musl@12.6.0': + '@pnpm/exe.linux-arm64-musl@12.14.0': optional: true - '@pnpm/exe.linux-arm64@12.6.0': + '@pnpm/exe.linux-arm64@12.14.0': optional: true - '@pnpm/exe.linux-ppc64@12.6.0': + '@pnpm/exe.linux-ppc64@12.14.0': optional: true - '@pnpm/exe.linux-riscv64@12.6.0': + '@pnpm/exe.linux-riscv64@12.14.0': optional: true - '@pnpm/exe.linux-s390x@12.6.0': + '@pnpm/exe.linux-s390x@12.14.0': optional: true - '@pnpm/exe.linux-x64-musl@12.6.0': + '@pnpm/exe.linux-x64-musl@12.14.0': optional: true - '@pnpm/exe.linux-x64@12.6.0': + '@pnpm/exe.linux-x64@12.14.0': optional: true - '@pnpm/exe.win32-arm64@12.6.0': + '@pnpm/exe.win32-arm64@12.14.0': optional: true - '@pnpm/exe.win32-x64@12.6.0': + '@pnpm/exe.win32-x64@12.14.0': optional: true - pnpm@12.6.0: + pnpm@12.14.0: optionalDependencies: - '@pnpm/exe.android-arm64': 12.6.0 - '@pnpm/exe.android-x64': 12.6.0 - '@pnpm/exe.darwin-arm64': 12.6.0 - '@pnpm/exe.darwin-x64': 12.6.0 - '@pnpm/exe.freebsd-x64': 12.6.0 - '@pnpm/exe.linux-arm64': 12.6.0 - '@pnpm/exe.linux-arm64-musl': 12.6.0 - '@pnpm/exe.linux-ppc64': 12.6.0 - '@pnpm/exe.linux-riscv64': 12.6.0 - '@pnpm/exe.linux-s390x': 12.6.0 - '@pnpm/exe.linux-x64': 12.6.0 - '@pnpm/exe.linux-x64-musl': 12.6.0 - '@pnpm/exe.win32-arm64': 12.6.0 - '@pnpm/exe.win32-x64': 12.6.0 + '@pnpm/exe.android-arm64': 12.14.0 + '@pnpm/exe.android-x64': 12.14.0 + '@pnpm/exe.darwin-arm64': 12.14.0 + '@pnpm/exe.darwin-x64': 12.14.0 + '@pnpm/exe.freebsd-x64': 12.14.0 + '@pnpm/exe.linux-arm64': 12.14.0 + '@pnpm/exe.linux-arm64-musl': 12.14.0 + '@pnpm/exe.linux-ppc64': 12.14.0 + '@pnpm/exe.linux-riscv64': 12.14.0 + '@pnpm/exe.linux-s390x': 12.14.0 + '@pnpm/exe.linux-x64': 12.14.0 + '@pnpm/exe.linux-x64-musl': 12.14.0 + '@pnpm/exe.win32-arm64': 12.14.0 + '@pnpm/exe.win32-x64': 12.14.0 --- lockfileVersion: '9.0'