From ffe54661a79cf10004df8a87eb1b1afdda15ed57 Mon Sep 17 00:00:00 2001 From: Silvio Tomatis Date: Fri, 13 Mar 2026 12:47:53 +0100 Subject: [PATCH 1/2] feat: harden fork package publishing --- .github/workflows/publish-dev.yaml | 61 ++++++++ .npmrc | 1 + README.md | 16 ++ package.json | 2 +- packages/crsqlite-wasm/package.json | 3 + packages/logger-provider/package.json | 3 + packages/rx-tbl/package.json | 3 + packages/ws-browserdb/package.json | 3 + packages/ws-client/package.json | 3 + packages/ws-common/package.json | 3 + packages/ws-server/package.json | 3 + packages/xplat-api/package.json | 3 + scripts/publish/config.sh | 22 +++ scripts/publish/publish.sh | 208 ++++++++++++++++++++++++++ 14 files changed, 333 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/publish-dev.yaml create mode 100644 .npmrc create mode 100755 scripts/publish/config.sh create mode 100755 scripts/publish/publish.sh diff --git a/.github/workflows/publish-dev.yaml b/.github/workflows/publish-dev.yaml new file mode 100644 index 0000000..b5a075f --- /dev/null +++ b/.github/workflows/publish-dev.yaml @@ -0,0 +1,61 @@ +name: Publish dev snapshots + +on: + workflow_dispatch: + push: + branches: + - librocco/main + +concurrency: + group: publish-dev-${{ github.ref }} + cancel-in-progress: true + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - name: Checkout vlcn-js + uses: actions/checkout@v4 + with: + fetch-depth: 0 + submodules: recursive + path: js + + - name: Checkout typed-sql sibling + uses: actions/checkout@v4 + with: + path: typed-sql + repository: vlcn-io/typed-sql + + - name: Install wabt + run: sudo apt-get update && sudo apt-get install -y wabt + + - name: Install Rust nightly + uses: actions-rs/toolchain@v1 + with: + toolchain: nightly-2023-10-05 + override: true + + - name: Setup Node and pnpm cache + uses: actions/setup-node@v4 + with: + node-version: 22 + cache: pnpm + cache-dependency-path: js/pnpm-lock.yaml + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: 9.15.9 + + - name: Configure registry auth + run: | + echo "//npm.codemyriad.io/:_authToken=${{ secrets.VERDACCIO_TOKEN }}" >> ~/.npmrc + + - name: Build + working-directory: js + run: make + + - name: Publish dev snapshots + working-directory: js + run: ./scripts/publish/publish.sh dev diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..2473986 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +registry=https://npm.codemyriad.io/ diff --git a/README.md b/README.md index d71b55e..51bcf40 100644 --- a/README.md +++ b/README.md @@ -112,3 +112,19 @@ git clone --recurse-submodules git@github.com:vlcn-io/workspace.git Running `make` in that directory will get you set up. Ensure you have the rust nightly toolchain installed and activated before running make. +## Fork publishing + +The codemyriad fork publishes forked `@vlcn.io/*` packages to `https://npm.codemyriad.io/`. + +Development snapshot publishes use the current repo commit SHA in the prerelease version, for example `0.2.2-dev.20260313.abcd1234`. Stable fork releases use an explicit `myriad.N` suffix, for example `0.2.2-myriad.1`. + +From a fork checkout with `typed-sql` available as a sibling repo and registry auth configured outside the repo: + +```bash +make +DRY_RUN=true ./scripts/publish/publish.sh dev +./scripts/publish/publish.sh dev +MYRIAD_N=1 ./scripts/publish/publish.sh myriad +``` + +The publish script refuses to reuse an existing `name@version`, which prevents the same version from being republished with different contents. diff --git a/package.json b/package.json index 3c3e15e..194d149 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "private": true, "version": "0.0.0", - "packageManager": "pnpm@7.9.0", + "packageManager": "pnpm@9.15.9", "engines": { "node": ">=19", "pnpm": ">=7" diff --git a/packages/crsqlite-wasm/package.json b/packages/crsqlite-wasm/package.json index 998c574..6a0e293 100644 --- a/packages/crsqlite-wasm/package.json +++ b/packages/crsqlite-wasm/package.json @@ -28,6 +28,9 @@ "url": "git@github.com:vlcn-io/js.git", "directory": "https://github.com/vlcn-io/js/tree/main/js/browser/crsqlite" }, + "publishConfig": { + "registry": "https://npm.codemyriad.io/" + }, "dependencies": { "@vlcn.io/wa-sqlite": "workspace:*", "@vlcn.io/xplat-api": "workspace:*", diff --git a/packages/logger-provider/package.json b/packages/logger-provider/package.json index 56445cf..ad68714 100644 --- a/packages/logger-provider/package.json +++ b/packages/logger-provider/package.json @@ -19,6 +19,9 @@ "url": "git@github.com:vlcn-io/js.git", "directory": "https://github.com/vlcn-io/js/tree/main/js/packages/logger-provider" }, + "publishConfig": { + "registry": "https://npm.codemyriad.io/" + }, "dependencies": { "winston": "^3.10.0" }, diff --git a/packages/rx-tbl/package.json b/packages/rx-tbl/package.json index e1cad1a..f0c52ea 100644 --- a/packages/rx-tbl/package.json +++ b/packages/rx-tbl/package.json @@ -23,6 +23,9 @@ "url": "git@github.com:vlcn-io/js.git", "directory": "https://github.com/vlcn-io/js/tree/main/js/rx-tbl" }, + "publishConfig": { + "registry": "https://npm.codemyriad.io/" + }, "dependencies": { "@vlcn.io/xplat-api": "workspace:*" } diff --git a/packages/ws-browserdb/package.json b/packages/ws-browserdb/package.json index 0dd7be4..bc302b1 100644 --- a/packages/ws-browserdb/package.json +++ b/packages/ws-browserdb/package.json @@ -20,6 +20,9 @@ "url": "git@github.com:vlcn-io/js.git", "directory": "https://github.com/vlcn-io/js/tree/main/js/packages/ws-browserdb" }, + "publishConfig": { + "registry": "https://npm.codemyriad.io/" + }, "dependencies": { "@types/throttle-debounce": "^5.0.0", "@vlcn.io/ws-client": "workspace:*", diff --git a/packages/ws-client/package.json b/packages/ws-client/package.json index ce7fba3..e9db4a3 100644 --- a/packages/ws-client/package.json +++ b/packages/ws-client/package.json @@ -24,6 +24,9 @@ "url": "git@github.com:vlcn-io/js.git", "directory": "https://github.com/vlcn-io/js/tree/main/js/packages/ws-client" }, + "publishConfig": { + "registry": "https://npm.codemyriad.io/" + }, "dependencies": { "@types/throttle-debounce": "^5.0.0", "@vlcn.io/ws-common": "workspace:*" diff --git a/packages/ws-common/package.json b/packages/ws-common/package.json index 8fbd483..0f37aca 100644 --- a/packages/ws-common/package.json +++ b/packages/ws-common/package.json @@ -20,6 +20,9 @@ "url": "git@github.com:vlcn-io/js.git", "directory": "https://github.com/vlcn-io/js/tree/main/js/packages/ws-client" }, + "publishConfig": { + "registry": "https://npm.codemyriad.io/" + }, "dependencies": { "lib0": "^0.2.73" }, diff --git a/packages/ws-server/package.json b/packages/ws-server/package.json index 436d6b4..c16d56c 100644 --- a/packages/ws-server/package.json +++ b/packages/ws-server/package.json @@ -20,6 +20,9 @@ "url": "git@github.com:vlcn-io/js.git", "directory": "https://github.com/vlcn-io/js/tree/main/js/packages/ws-server" }, + "publishConfig": { + "registry": "https://npm.codemyriad.io/" + }, "dependencies": { "@types/better-sqlite3": "^7.6.8", "@vlcn.io/crsqlite": "workspace:*", diff --git a/packages/xplat-api/package.json b/packages/xplat-api/package.json index 9a6f7ce..a3689ca 100644 --- a/packages/xplat-api/package.json +++ b/packages/xplat-api/package.json @@ -24,6 +24,9 @@ "url": "git@github.com:vlcn-io/js.git", "directory": "https://github.com/vlcn-io/js/tree/main/js/xplat-api" }, + "publishConfig": { + "registry": "https://npm.codemyriad.io/" + }, "dependencies": { "comlink": "^4.4.1" } diff --git a/scripts/publish/config.sh b/scripts/publish/config.sh new file mode 100755 index 0000000..a4a95ac --- /dev/null +++ b/scripts/publish/config.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +# Configuration for publishing the codemyriad fork of vlcn-js. + +REGISTRY_URL="${REGISTRY_URL:-https://npm.codemyriad.io/}" +DEV_DIST_TAG="${DEV_DIST_TAG:-dev}" +MYRIAD_DIST_TAG="${MYRIAD_DIST_TAG:-myriad}" + +# Packages are ordered topologically so workspace protocol dependencies +# resolve to already-published versions during the run. +PUBLISH_PACKAGES=( + "@vlcn.io/xplat-api:packages/xplat-api" + "@vlcn.io/ws-common:packages/ws-common" + "@vlcn.io/wa-sqlite:deps/wa-sqlite" + "@vlcn.io/crsqlite:deps/cr-sqlite/core" + "@vlcn.io/logger-provider:packages/logger-provider" + "@vlcn.io/rx-tbl:packages/rx-tbl" + "@vlcn.io/ws-client:packages/ws-client" + "@vlcn.io/crsqlite-wasm:packages/crsqlite-wasm" + "@vlcn.io/ws-server:packages/ws-server" + "@vlcn.io/ws-browserdb:packages/ws-browserdb" +) diff --git a/scripts/publish/publish.sh b/scripts/publish/publish.sh new file mode 100755 index 0000000..7756467 --- /dev/null +++ b/scripts/publish/publish.sh @@ -0,0 +1,208 @@ +#!/usr/bin/env bash +# +# Publish forked @vlcn.io packages to npm.codemyriad.io under unique versions. +# +# Usage: +# ./scripts/publish/publish.sh dev +# MYRIAD_N=1 ./scripts/publish/publish.sh myriad +# +# Environment variables: +# DRY_RUN=true Stamp and check versions but skip publish +# MYRIAD_N=1 Required for the "myriad" track +# +# Prerequisites: +# - pnpm, npm, jq, git available on PATH +# - registry auth configured outside the repo +# - deps/cr-sqlite and deps/wa-sqlite submodules initialized +# - build already completed for packages that need generated output + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" + +# shellcheck source=./config.sh +source "$SCRIPT_DIR/config.sh" + +usage() { + echo "Usage: $0 " >&2 +} + +require_cmd() { + local cmd="$1" + if ! command -v "$cmd" >/dev/null 2>&1; then + echo "Error: required command '$cmd' is not available" >&2 + exit 1 + fi +} + +pkg_name() { + echo "${1%%:*}" +} + +pkg_dir() { + echo "$REPO_ROOT/${1##*:}" +} + +require_cmd git +require_cmd jq +require_cmd npm +require_cmd pnpm + +TRACK="${1:-}" +if [[ -z "$TRACK" ]]; then + usage + exit 1 +fi + +case "$TRACK" in + dev|myriad) + ;; + *) + echo "Error: track must be 'dev' or 'myriad', got '$TRACK'" >&2 + usage + exit 1 + ;; +esac + +for required_pkg in "$REPO_ROOT/deps/cr-sqlite/core/package.json" "$REPO_ROOT/deps/wa-sqlite/package.json"; do + if [[ ! -f "$required_pkg" ]]; then + echo "Error: missing $required_pkg. Run 'git submodule update --init --recursive' first." >&2 + exit 1 + fi +done + +DRY_RUN="${DRY_RUN:-false}" +SHORT_SHA="$(git -C "$REPO_ROOT" rev-parse --short=8 HEAD)" + +case "$TRACK" in + dev) + DATE_STAMP="$(date -u +%Y%m%d)" + VERSION_SUFFIX="dev.${DATE_STAMP}.${SHORT_SHA}" + DIST_TAG="$DEV_DIST_TAG" + ;; + myriad) + if [[ -z "${MYRIAD_N:-}" ]]; then + echo "Error: MYRIAD_N must be set for the myriad track" >&2 + exit 1 + fi + VERSION_SUFFIX="myriad.${MYRIAD_N}" + DIST_TAG="$MYRIAD_DIST_TAG" + ;; +esac + +WORKTREE_STATE="$(git -C "$REPO_ROOT" status --short --ignore-submodules=none)" +if [[ -n "$WORKTREE_STATE" ]]; then + echo "Warning: worktree is not clean before stamping versions:" >&2 + echo "$WORKTREE_STATE" >&2 + echo "Publishing will still use commit SHA $SHORT_SHA. Make sure that is intentional." >&2 + echo "" >&2 +fi + +echo "==> Track: $TRACK" +echo "==> Version suffix: $VERSION_SUFFIX" +echo "==> Source SHA: $SHORT_SHA" +echo "==> Registry: $REGISTRY_URL" +echo "==> Dist tag: $DIST_TAG" +echo "==> Dry run: $DRY_RUN" +echo "" + +stamp_version() { + local pkg_json="$1" + local base_version + local new_version + base_version="$(jq -r '.version' "$pkg_json")" + new_version="${base_version}-${VERSION_SUFFIX}" + jq --arg v "$new_version" '.version = $v' "$pkg_json" > "${pkg_json}.tmp" + mv "${pkg_json}.tmp" "$pkg_json" + echo "$new_version" +} + +check_registry() { + local name="$1" + local version="$2" + if npm view "${name}@${version}" version --registry "$REGISTRY_URL" >/dev/null 2>&1; then + echo "Error: ${name}@${version} already exists on ${REGISTRY_URL}" >&2 + return 1 + fi +} + +STAMPED_FILES=() +BACKUP_FILES=() +BACKUP_DIR="$(mktemp -d)" + +cleanup() { + if [[ ${#STAMPED_FILES[@]} -gt 0 ]]; then + echo "" + echo "==> Restoring package.json files..." + for i in "${!STAMPED_FILES[@]}"; do + cp "${BACKUP_FILES[$i]}" "${STAMPED_FILES[$i]}" + done + fi + + if [[ -d "$BACKUP_DIR" ]]; then + rm -rf "$BACKUP_DIR" + fi +} +trap cleanup EXIT + +declare -A VERSION_MAP + +echo "==> Stamping versions..." +for entry in "${PUBLISH_PACKAGES[@]}"; do + name="$(pkg_name "$entry")" + dir="$(pkg_dir "$entry")" + pkg_json="$dir/package.json" + + if [[ ! -f "$pkg_json" ]]; then + echo "Error: $pkg_json not found" >&2 + exit 1 + fi + + backup_path="$BACKUP_DIR/$(printf '%03d.json' "${#STAMPED_FILES[@]}")" + cp "$pkg_json" "$backup_path" + + new_version="$(stamp_version "$pkg_json")" + VERSION_MAP["$name"]="$new_version" + STAMPED_FILES+=("$pkg_json") + BACKUP_FILES+=("$backup_path") + + echo " ${name}@${new_version}" +done + +echo "" +echo "==> Checking registry for existing versions..." +for entry in "${PUBLISH_PACKAGES[@]}"; do + name="$(pkg_name "$entry")" + version="${VERSION_MAP[$name]}" + + check_registry "$name" "$version" + echo " ${name}@${version} - available" +done + +echo "" +if [[ "$DRY_RUN" == "true" ]]; then + echo "==> DRY RUN: skipping publish" + for entry in "${PUBLISH_PACKAGES[@]}"; do + name="$(pkg_name "$entry")" + dir="$(pkg_dir "$entry")" + echo " Would publish ${name}@${VERSION_MAP[$name]} from $dir" + done + exit 0 +fi + +echo "==> Publishing..." +for entry in "${PUBLISH_PACKAGES[@]}"; do + name="$(pkg_name "$entry")" + dir="$(pkg_dir "$entry")" + version="${VERSION_MAP[$name]}" + + echo " Publishing ${name}@${version}..." + pnpm publish "$dir" \ + --registry "$REGISTRY_URL" \ + --tag "$DIST_TAG" \ + --no-git-checks +done + +echo "" +echo "==> Done" From a29af30d513ea27aa5a7bf7c4052ac5475fbc1dd Mon Sep 17 00:00:00 2001 From: Silvio Tomatis Date: Fri, 13 Mar 2026 12:59:06 +0100 Subject: [PATCH 2/2] fix: pin rust toolchain in js tests --- .github/workflows/js-tests.yaml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/js-tests.yaml b/.github/workflows/js-tests.yaml index 44fc3b9..1cab0e9 100644 --- a/.github/workflows/js-tests.yaml +++ b/.github/workflows/js-tests.yaml @@ -39,8 +39,14 @@ jobs: if: runner.os == 'macOS' run: brew install wabt; brew install make; printf '%s\n%s\n' "/usr/local/opt/make/libexec/gnubin" "$(cat $GITHUB_PATH)" > $GITHUB_PATH + - name: Install Rust Toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: nightly-2023-10-05 + override: true + - name: Install wasm-pack - run: cargo install wasm-pack + run: cargo install wasm-pack --version 0.13.1 --locked - name: Setup Node uses: actions/setup-node@v3