diff --git a/.eslintignore b/.eslintignore index abd028a4e..491fc3597 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,4 +1,2 @@ node_modules lib -es2020 -commonjs diff --git a/.eslintrc b/.eslintrc index 72d9d9392..a497d99fb 100644 --- a/.eslintrc +++ b/.eslintrc @@ -2,7 +2,7 @@ "root": true, "parser": "@typescript-eslint/parser", "parserOptions": { - "project": "./packages/*/tsconfig.json" + "project": ["./packages/*/tsconfig.json", "./tsconfig.scripts.json"] }, "plugins": ["@typescript-eslint", "eslint-plugin-tsdoc", "deprecation", "import"], "extends": [ diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8d280fdf9..84aca7932 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -181,7 +181,7 @@ jobs: run: pnpm run build --ignore @temporalio/core-bridge - name: Publish to Verdaccio - run: node scripts/publish-to-verdaccio.js --registry-dir ${{ steps.tmp-dir.outputs.dir }}/npm-registry + run: pnpm tsx scripts/publish-to-verdaccio.ts --registry-dir ${{ steps.tmp-dir.outputs.dir }}/npm-registry - name: Install Temporal CLI uses: temporalio/setup-temporal@v0 @@ -222,8 +222,8 @@ jobs: # Sample 1: hello-world to local server - name: Instantiate sample project using verdaccio artifacts - Hello World run: | - node scripts/init-from-verdaccio.js --registry-dir ${{ steps.tmp-dir.outputs.dir }}/npm-registry --sample https://github.com/temporalio/samples-typescript/tree/main/hello-world --target-dir ${{ steps.tmp-dir.outputs.dir }}/sample-hello-world - node scripts/test-example.js --work-dir "${{ steps.tmp-dir.outputs.dir }}/sample-hello-world" + pnpm tsx scripts/init-from-verdaccio.ts --registry-dir ${{ steps.tmp-dir.outputs.dir }}/npm-registry --sample https://github.com/temporalio/samples-typescript/tree/main/hello-world --target-dir ${{ steps.tmp-dir.outputs.dir }}/sample-hello-world + pnpm tsx scripts/test-example.ts --work-dir "${{ steps.tmp-dir.outputs.dir }}/sample-hello-world" # Sample 2: hello-world-mtls to cloud server - name: Instantiate sample project using verdaccio artifacts - Hello World MTLS @@ -233,9 +233,9 @@ jobs: exit 0 fi - node scripts/create-certs-dir.js ${{ steps.tmp-dir.outputs.dir }}/certs - node scripts/init-from-verdaccio.js --registry-dir ${{ steps.tmp-dir.outputs.dir }}/npm-registry --sample https://github.com/temporalio/samples-typescript/tree/main/hello-world-mtls --target-dir ${{ steps.tmp-dir.outputs.dir }}/sample-hello-world-mtls - node scripts/test-example.js --work-dir "${{ steps.tmp-dir.outputs.dir }}/sample-hello-world-mtls" + pnpm tsx scripts/create-certs-dir.ts ${{ steps.tmp-dir.outputs.dir }}/certs + pnpm tsx scripts/init-from-verdaccio.ts --registry-dir ${{ steps.tmp-dir.outputs.dir }}/npm-registry --sample https://github.com/temporalio/samples-typescript/tree/main/hello-world-mtls --target-dir ${{ steps.tmp-dir.outputs.dir }}/sample-hello-world-mtls + pnpm tsx scripts/test-example.ts --work-dir "${{ steps.tmp-dir.outputs.dir }}/sample-hello-world-mtls" env: # These env vars are used by the hello-world-mtls sample TEMPORAL_ADDRESS: ${{ vars.TEMPORAL_CLIENT_NAMESPACE }}.tmprl.cloud:7233 @@ -255,8 +255,8 @@ jobs: # Sample 3: fetch-esm to local server - name: Instantiate sample project using verdaccio artifacts - Fetch ESM run: | - node scripts/init-from-verdaccio.js --registry-dir ${{ steps.tmp-dir.outputs.dir }}/npm-registry --sample https://github.com/temporalio/samples-typescript/tree/main/fetch-esm --target-dir ${{ steps.tmp-dir.outputs.dir }}/sample-fetch-esm - node scripts/test-example.js --work-dir "${{ steps.tmp-dir.outputs.dir }}/sample-fetch-esm" --script-name workflow-local --expected-output "Hello World And Hello Wonderful Temporal!" + pnpm tsx scripts/init-from-verdaccio.ts --registry-dir ${{ steps.tmp-dir.outputs.dir }}/npm-registry --sample https://github.com/temporalio/samples-typescript/tree/main/fetch-esm --target-dir ${{ steps.tmp-dir.outputs.dir }}/sample-fetch-esm + pnpm tsx scripts/test-example.ts --work-dir "${{ steps.tmp-dir.outputs.dir }}/sample-fetch-esm" --script-name workflow-local --expected-output "Hello World And Hello Wonderful Temporal!" # End samples diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 921cc7e54..023a99e11 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -181,7 +181,7 @@ jobs: run: pnpm run build --ignore @temporalio/core-bridge - name: Publish to Verdaccio - run: node scripts/publish-to-verdaccio.js --registry-dir ./tmp/registry + run: pnpm tsx scripts/publish-to-verdaccio.ts --registry-dir ./tmp/registry - name: Save Verdaccio repo artifact uses: actions/upload-artifact@v4 @@ -250,7 +250,7 @@ jobs: # Note: here, `npx create` fails on windows if shell is bash. - name: Instantiate sample project using verdaccio artifacts - run: node scripts/init-from-verdaccio.js --registry-dir ./tmp/registry --sample ${{ matrix.sample }} --target-dir ${{ runner.temp }}/example + run: pnpm tsx scripts/init-from-verdaccio.ts --registry-dir ./tmp/registry --sample ${{ matrix.sample }} --target-dir ${{ runner.temp }}/example - name: Install Temporal CLI if: matrix.server == 'cli' @@ -269,7 +269,7 @@ jobs: # We write the certs to disk because it serves the sample. Written into /tmp/temporal-certs - name: Create certs dir shell: bash - run: node scripts/create-certs-dir.js "${{ runner.temp }}/certs" + run: pnpm tsx scripts/create-certs-dir.ts "${{ runner.temp }}/certs" if: matrix.server == 'cloud' env: # These env vars are used by the hello-world-mtls sample @@ -279,14 +279,14 @@ jobs: TEMPORAL_CLIENT_KEY: ${{ secrets.TEMPORAL_CLIENT_KEY }} - name: Test run a workflow (non-cloud) - run: node scripts/test-example.js --work-dir "${{ runner.temp }}/example" + run: pnpm tsx scripts/test-example.ts --work-dir "${{ runner.temp }}/example" shell: bash if: matrix.server == 'cli' - name: Test run a workflow (cloud) if: matrix.server == 'cloud' # The required environment variables must be present for releases (this must be run from the official repo) - run: node scripts/test-example.js --work-dir "${{ runner.temp }}/example" + run: pnpm tsx scripts/test-example.ts --work-dir "${{ runner.temp }}/example" shell: bash env: # These env vars are used by the hello-world-mtls sample diff --git a/.prettierignore b/.prettierignore index 9d1a89b9e..d2ed9bae7 100644 --- a/.prettierignore +++ b/.prettierignore @@ -4,8 +4,6 @@ packages/core-bridge/target packages/core-bridge/bridge-macros/target sdk-core lib -es2020 -commonjs .docusaurus packages/*/CHANGELOG.md packages/docs/docs/api diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1dcff892a..6844b70cf 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -93,13 +93,10 @@ If building fails, resetting your environment may help: pnpm dlx lerna clean -y && pnpm install --frozen-lockfile ``` -If `pnpm install` fails in `@temporalio/core-bridge` on the command `node ./scripts/build.js`, you may +If `pnpm install` fails in `@temporalio/core-bridge` on the command `pnpm tsx ./scripts/build.ts`, you may need to do `rustup update`. -To update to the latest version of the Core SDK, run `git submodule update` followed by `npm run build` to recompile. - -> For cross compilation on MacOS follow [these instructions](https://github.com/temporalio/sdk-typescript/blob/main/docs/building.md) -> (only required for publishing packages). +To update to the latest version of the Core SDK, run `git submodule update` followed by `pnpm run build` to recompile. ## Development @@ -135,14 +132,17 @@ To replicate the `test-npm-init` CI test locally, you can start with the below s > If you've run `npx @temporalio/create` before, you may need to delete the version of the package that's stored in `~/.npm/_npx/`. ``` -rm -rf /tmp/registry pnpm install --frozen-lockfile pnpm run rebuild -node scripts/publish-to-verdaccio.js --registry-dir /tmp/registry -node scripts/init-from-verdaccio.js --registry-dir /tmp/registry --sample hello-world -cd /tmp/registry/example -npm run build -node ~/path-to/sdk-typescript/scripts/test-example.js --work-dir /tmp/registry/example + +TMP_DIR=$( mktemp -d ) + +pnpm tsx scripts/publish-to-verdaccio.ts --registry-dir "$TMP_DIR" +pnpm tsx scripts/init-from-verdaccio.ts --registry-dir "$TMP_DIR" --sample hello-world + +cd "$TMP_DIR/example" +pnpm run build +pnpm tsx scripts/test-example.ts --work-dir "$TMP_DIR/example" ``` ### Style Guide @@ -195,7 +195,9 @@ To install both tools: `npm i -g npm-check npm-check-updates`. ## Publishing -First, follow the instructions in [docs/building.md](docs/building.md). +First, download the latest native artifacts from GitHub Actions. + +Then run the following commands: ```sh cargo install git-cliff @@ -249,7 +251,7 @@ ls packages/core-bridge/releases/ pnpm exec lerna version patch --force-publish='*' # or major|minor|etc, or leave out to be prompted. either way, you get a confirmation dialog. git checkout -B fix-deps -node scripts/prepublish.mjs +pnpm tsx scripts/prepublish.ts git commit -am 'Fix dependencies' pnpm exec lerna publish from-package # add `--dist-tag next` for pre-release versions git checkout - diff --git a/docs/building.md b/docs/building.md deleted file mode 100644 index 81181ac2a..000000000 --- a/docs/building.md +++ /dev/null @@ -1,32 +0,0 @@ -## Building `temporal_sdk_typescript_bridge` - -`temporal_sdk_typescript_bridge` is a native Node.js module written in Rust using [neon](https://neon-bindings.com/). -One of the advantages of using Rust is that it's easy to cross compile to various platforms and architectures. - -By using Node.js' `n-api` we get a binary which _should_ work on all supported Node versions thanks to `n-api`'s [ABI stability](https://nodejs.org/en/docs/guides/abi-stability/). - -### Prerequisites for M1 Macs - -1. Install rosetta with `softwareupdate --install-rosetta` -1. Make sure you have brew under Rosetta alongside your M1 brew intallation
- See: https://github.com/Homebrew/brew/issues/9173
- `arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"` - -### Setting up a Rust cross-compilation MacOS build environment - -1. Download [rustup](https://rustup.rs/). -1. Run `rustup target add x86_64-apple-darwin` - if you're using a mac with an M1 chip -1. Run `rustup target add aarch64-apple-darwin` - if you're using a mac with an Intel chip
- **NOTE:** you can only compile for aarch64 if you have MacOS Big Sur or later -1. Run `rustup target add x86_64-pc-windows-gnu` -1. Run `rustup target add x86_64-unknown-linux-gnu` -1. Run `rustup target add aarch64-unknown-linux-gnu` -1. Run `brew tap messense/macos-cross-toolchains` -1. Run `brew install x86_64-unknown-linux-gnu` to enable Linux x86_64 compilation -1. Run `brew install aarch64-unknown-linux-gnu` to enable Linux aarch64 compilation -1. Run `brew install mingw-w64` to enable Windows compilation on Intel Macs
- Or `arch -x86_64 /usr/local/bin/brew install mingw-w64` on M1 Macs -1. Configure cargo for the Windows and Linux build targets - `cp etc/mac-cargo-config.toml ~/.cargo/config.toml` -1. Install the project's dependencies with `NPM_CONFIG_FOREGROUND_SCRIPTS=true npm ci` if you haven't already -1. Build the the bridge with `CC_aarch64_unknown_linux_gnu=aarch64-unknown-linux-gnu-gcc CC_x86_64_unknown_linux_gnu=x86_64-unknown-linux-gnu-gcc npx lerna run --stream build-rust -- --target all` diff --git a/etc/mac-cargo-config.toml b/etc/mac-cargo-config.toml deleted file mode 100644 index ccbdd9a1b..000000000 --- a/etc/mac-cargo-config.toml +++ /dev/null @@ -1,7 +0,0 @@ -# Copy this file to ~/.cargo/config.toml in order to cross-compile for Linux and Windows -[target.x86_64-unknown-linux-gnu] -linker = "x86_64-linux-gnu-gcc" -[target.aarch64-unknown-linux-gnu] -linker = "aarch64-linux-gnu-gcc" -[target.x86_64-pc-windows-gnu] -linker = "/usr/local/bin/x86_64-w64-mingw32-gcc" diff --git a/package.json b/package.json index adc8273f5..6c9e8725b 100644 --- a/package.json +++ b/package.json @@ -24,17 +24,16 @@ "rebuild": "pnpm run clean && pnpm run build", "build": "lerna run --stream build", "build.watch": "pnpm run build:protos && tsc --build --watch packages/*/tsconfig.json", - "build:protos": "node ./packages/proto/scripts/compile-proto.js", + "build:protos": "tsx ./packages/proto/scripts/compile-proto.ts", "test": "lerna run --stream test", "test.watch": "lerna run --stream test.watch", "ci-stress": "node ./packages/test/lib/load/run-all-stress-ci-scenarios.js", "ci-nightly": "node ./packages/test/lib/load/run-all-nightly-scenarios.js", - "wait-namespace": "node ./scripts/wait-on-temporal.mjs", "lint": "eslint packages/*/src --ext .ts --no-error-on-unmatched-pattern --fix && prettier --write . && lerna run --no-bail --stream lint", "lint.check": "eslint packages/*/src --ext .ts --no-error-on-unmatched-pattern && prettier --end-of-line auto --check . && lerna run --no-bail --stream lint.check", "lint.prune": "ts-prune --error -p tsconfig.prune.json --ignore \"used in module\" --skip \".d.ts\"", "format": "prettier --write . && lerna run --no-bail --stream format", - "clean": "node ./scripts/clean.mjs", + "clean": "tsx ./scripts/clean.ts", "docs": "cd packages/docs && pnpm run maybe-install-deps-and-build-docs", "ava": "pnpm -C packages/test exec ava" }, @@ -80,6 +79,7 @@ "lerna": "^8.2.4", "prettier": "^3.1.1", "ts-prune": "^0.10.3", + "tsx": "^4.20.6", "typescript": "^5.6.3", "verdaccio": "^6.2.2" }, diff --git a/packages/core-bridge/package.json b/packages/core-bridge/package.json index 2537e193b..0967aef1d 100644 --- a/packages/core-bridge/package.json +++ b/packages/core-bridge/package.json @@ -5,10 +5,9 @@ "main": "index.js", "types": "lib/index.d.ts", "scripts": { - "build-rust": "node ./scripts/build.js --force", + "build-rust": "tsx ./scripts/build.ts --force", "build": "pnpm run build-rust", "build-rust-release": "pnpm run build-rust --release", - "install": "node ./scripts/build.js", "format": "cargo fmt", "lint": "cargo clippy --fix --allow-staged", "lint.check": "cargo clippy" @@ -23,10 +22,12 @@ "license": "MIT", "dependencies": { "@grpc/grpc-js": "^1.12.4", - "@temporalio/common": "workspace:*", + "@temporalio/common": "workspace:*" + }, + "devDependencies": { "arg": "^5.0.2", - "cargo-cp-artifact": "^0.1.8", - "which": "^4.0.0" + "cargo-cp-artifact": "^0.1.9", + "tsx": "^4.20.6" }, "bugs": { "url": "https://github.com/temporalio/sdk-typescript/issues" diff --git a/packages/core-bridge/scripts/build.js b/packages/core-bridge/scripts/build.ts similarity index 79% rename from packages/core-bridge/scripts/build.js rename to packages/core-bridge/scripts/build.ts index a6271fcb7..6e2e2eb75 100644 --- a/packages/core-bridge/scripts/build.js +++ b/packages/core-bridge/scripts/build.ts @@ -1,10 +1,9 @@ -const path = require('path'); -const arg = require('arg'); -const fs = require('fs'); -const which = require('which'); -const { spawnSync } = require('child_process'); -const { version } = require('../package.json'); -const { targets, getPrebuiltPath, getPrebuiltTargetName, PrebuildError } = require('../common'); +import * as path from 'node:path'; +import * as fs from 'node:fs'; +import arg from 'arg'; +import cargoCpArtifact from 'cargo-cp-artifact'; +import { version } from '../package.json'; +import { targets, getPrebuiltPath, getPrebuiltTargetName, PrebuildError } from '../common'; process.chdir(path.resolve(__dirname, '..')); @@ -54,7 +53,7 @@ if (unsupportedTargets.length) { const forceBuild = args['--force']; const buildRelease = args['--release'] || process.env.BUILD_CORE_RELEASE !== undefined; -function compile(requestedTarget) { +function compile(requestedTarget?: string) { if (!fs.existsSync('sdk-core/Cargo.toml')) { throw new Error('Missing sdk-core/Cargo.toml. Did you forget to run `git submodule update --init --recursive`?'); } @@ -83,16 +82,12 @@ function compile(requestedTarget) { ...(buildRelease ? ['--release'] : []), ...(target ? ['--target', target] : []), ]; - const cmd = which.sync('cargo-cp-artifact'); - console.log('Running', cmd, argv); - const { status, error } = spawnSync(cmd, argv, { - stdio: 'inherit', - shell: process.platform === 'win32', + console.log('Running cargo-cp-artifact', argv); + + cargoCpArtifact(argv, { + env: process.env, }); - if (status !== 0 || error) { - throw new Error(`Failed to build${target ? ' for ' + target : ''}: status code ${status}`, error); - } } if (requestedTargets.length > 0) { diff --git a/packages/proto/package.json b/packages/proto/package.json index 32207b8b2..1233214fe 100644 --- a/packages/proto/package.json +++ b/packages/proto/package.json @@ -10,7 +10,7 @@ "lib/" ], "scripts": { - "build": "node ./scripts/compile-proto.js" + "build": "pnpm tsx ./scripts/compile-proto.ts" }, "keywords": [ "temporal", diff --git a/packages/proto/scripts/compile-proto.js b/packages/proto/scripts/compile-proto.ts similarity index 89% rename from packages/proto/scripts/compile-proto.js rename to packages/proto/scripts/compile-proto.ts index ea86ef355..cb7acac82 100644 --- a/packages/proto/scripts/compile-proto.js +++ b/packages/proto/scripts/compile-proto.ts @@ -1,10 +1,10 @@ -const { rm, readFile, writeFile } = require('fs/promises'); -const { resolve } = require('path'); -const { promisify } = require('util'); -const glob = require('glob'); -const { statSync, mkdirSync } = require('fs'); -const pbjs = require('protobufjs-cli/pbjs'); -const pbts = require('protobufjs-cli/pbts'); +import { rm, readFile, writeFile } from 'node:fs/promises'; +import { statSync, mkdirSync } from 'node:fs'; +import { resolve } from 'node:path'; +import { promisify } from 'node:util'; +import * as glob from 'glob'; +import * as pbjs from 'protobufjs-cli/pbjs'; +import * as pbts from 'protobufjs-cli/pbts'; const outputDir = resolve(__dirname, '../protos'); const jsOutputFile = resolve(outputDir, 'json-module.js'); @@ -12,7 +12,7 @@ const tempFile = resolve(outputDir, 'temp.js'); const protoBaseDir = resolve(__dirname, '../../core-bridge/sdk-core/crates/common/protos'); -function mtime(path) { +function mtime(path: string) { try { return statSync(path).mtimeMs; } catch (err) { @@ -23,7 +23,7 @@ function mtime(path) { } } -async function compileProtos(dtsOutputFile, ...args) { +async function compileProtos(dtsOutputFile: string, ...args: string[]) { const pbjsArgs = [ ...['--wrap', 'commonjs'], '--force-long', diff --git a/packages/test/package.json b/packages/test/package.json index 06cf53dd5..c37a3f7c1 100644 --- a/packages/test/package.json +++ b/packages/test/package.json @@ -6,7 +6,7 @@ "scripts": { "build": "pnpm run \"/^build:.*/\"", "build:ts": "tsc --build", - "build:protos": "node ./scripts/compile-proto.js", + "build:protos": "pnpm tsx ./scripts/compile-proto.ts", "test": "ava ./lib/test-*.js", "test.watch": "ava --watch ./lib/test-*.js" }, diff --git a/packages/test/scripts/compile-proto.js b/packages/test/scripts/compile-proto.ts similarity index 81% rename from packages/test/scripts/compile-proto.js rename to packages/test/scripts/compile-proto.ts index 6ef96474b..7badba7a5 100644 --- a/packages/test/scripts/compile-proto.js +++ b/packages/test/scripts/compile-proto.ts @@ -1,13 +1,13 @@ // Script to do the equivalent of: // pbjs -t json-module -w commonjs -r test -o protos/json-module.js protos/*.proto // pbjs -t static-module protos/*.proto | pbts -o protos/root.d.ts - -const { resolve } = require('path'); -const { promisify } = require('util'); -const glob = require('glob'); -const { statSync, mkdirsSync } = require('fs-extra'); -const { rm } = require('fs/promises'); -const pbjs = require('protobufjs-cli/pbjs'); -const pbts = require('protobufjs-cli/pbts'); +import { resolve } from 'node:path'; +import { promisify } from 'node:util'; +import { rm } from 'node:fs/promises'; +import * as glob from 'glob'; +import { statSync, mkdirsSync } from 'fs-extra'; +import * as pbjs from 'protobufjs-cli/pbjs'; +import * as pbts from 'protobufjs-cli/pbts'; const outputDir = resolve(__dirname, '../protos'); const moduleOutputFile = resolve(outputDir, 'json-module.js'); @@ -16,7 +16,7 @@ const tempFile = resolve(outputDir, 'temp.js'); const protoBaseDir = resolve(__dirname, '../protos'); const protoFiles = glob.sync('*.proto', { cwd: protoBaseDir, absolute: true, root: '' }); -function mtime(path) { +function mtime(path: string) { try { return statSync(path).mtimeMs; } catch (err) { @@ -27,7 +27,7 @@ function mtime(path) { } } -async function compileProtos(outputFile, ...args) { +async function compileProtos(outputFile: string, ...args: string[]) { const pbjsArgs = [ ...args, '--wrap', diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fad2defa0..13f68d5af 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -126,6 +126,9 @@ importers: ts-prune: specifier: ^0.10.3 version: 0.10.3 + tsx: + specifier: ^4.20.6 + version: 4.20.6 typescript: specifier: ^5.6.3 version: 5.6.3 @@ -225,15 +228,16 @@ importers: '@temporalio/common': specifier: workspace:* version: link:../common + devDependencies: arg: specifier: ^5.0.2 version: 5.0.2 cargo-cp-artifact: - specifier: ^0.1.8 - version: 0.1.8 - which: - specifier: ^4.0.0 - version: 4.0.0 + specifier: ^0.1.9 + version: 0.1.9 + tsx: + specifier: ^4.20.6 + version: 4.20.6 packages/create-project: dependencies: @@ -823,6 +827,162 @@ packages: '@emnapi/wasi-threads@1.0.4': resolution: {integrity: sha512-PJR+bOmMOPH8AtcTGAyYNiuJ3/Fcoj2XN/gBEWzDIKh254XO+mM9XoXHk5GNEhodxeMznbg7BlRojVbKN+gC6g==} + '@esbuild/aix-ppc64@0.25.12': + resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.25.12': + resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.25.12': + resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.25.12': + resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.25.12': + resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.25.12': + resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.25.12': + resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.25.12': + resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.25.12': + resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.25.12': + resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.25.12': + resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.25.12': + resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.25.12': + resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.25.12': + resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.25.12': + resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.25.12': + resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.25.12': + resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.25.12': + resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.25.12': + resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.25.12': + resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.25.12': + resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.25.12': + resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.25.12': + resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.25.12': + resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.25.12': + resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.25.12': + resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@eslint-community/eslint-utils@4.4.0': resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -2143,8 +2303,8 @@ packages: caniuse-lite@1.0.30001620: resolution: {integrity: sha512-WJvYsOjd1/BYUY6SNGUosK9DUidBPDTnOARHp3fSmFO1ekdxaY6nKRttEVrfMmYi80ctS0kz1wiWmm14fVc3ew==} - cargo-cp-artifact@0.1.8: - resolution: {integrity: sha512-3j4DaoTrsCD1MRkTF2Soacii0Nx7UHCce0EwUf4fHnggwiE4fbmF2AbnfzayR36DF8KGadfh7M/Yfy625kgPlA==} + cargo-cp-artifact@0.1.9: + resolution: {integrity: sha512-6F+UYzTaGB+awsTXg0uSJA1/b/B3DDJzpKVRu0UmyI7DmNeaAl2RFHuTGIN6fEgpadRxoXGb7gbC1xo4C3IdyA==} hasBin: true caseless@0.12.0: @@ -2678,6 +2838,11 @@ packages: resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} engines: {node: '>= 0.4'} + esbuild@0.25.12: + resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} + engines: {node: '>=18'} + hasBin: true + escalade@3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} engines: {node: '>=6'} @@ -3053,6 +3218,9 @@ packages: resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} engines: {node: '>= 0.4'} + get-tsconfig@4.13.0: + resolution: {integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==} + get-tsconfig@4.7.2: resolution: {integrity: sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==} @@ -5240,6 +5408,11 @@ packages: peerDependencies: typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' + tsx@4.20.6: + resolution: {integrity: sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg==} + engines: {node: '>=18.0.0'} + hasBin: true + tuf-js@2.2.1: resolution: {integrity: sha512-GwIJau9XaA8nLVbUXsN3IlFi7WmQ48gBUrl3FTkkL/XLu/POhBzfmX9hd33FNMX1qAsfl6ozO1iMmW9NC8YniA==} engines: {node: ^16.14.0 || >=18.0.0} @@ -5735,6 +5908,84 @@ snapshots: dependencies: tslib: 2.6.2 + '@esbuild/aix-ppc64@0.25.12': + optional: true + + '@esbuild/android-arm64@0.25.12': + optional: true + + '@esbuild/android-arm@0.25.12': + optional: true + + '@esbuild/android-x64@0.25.12': + optional: true + + '@esbuild/darwin-arm64@0.25.12': + optional: true + + '@esbuild/darwin-x64@0.25.12': + optional: true + + '@esbuild/freebsd-arm64@0.25.12': + optional: true + + '@esbuild/freebsd-x64@0.25.12': + optional: true + + '@esbuild/linux-arm64@0.25.12': + optional: true + + '@esbuild/linux-arm@0.25.12': + optional: true + + '@esbuild/linux-ia32@0.25.12': + optional: true + + '@esbuild/linux-loong64@0.25.12': + optional: true + + '@esbuild/linux-mips64el@0.25.12': + optional: true + + '@esbuild/linux-ppc64@0.25.12': + optional: true + + '@esbuild/linux-riscv64@0.25.12': + optional: true + + '@esbuild/linux-s390x@0.25.12': + optional: true + + '@esbuild/linux-x64@0.25.12': + optional: true + + '@esbuild/netbsd-arm64@0.25.12': + optional: true + + '@esbuild/netbsd-x64@0.25.12': + optional: true + + '@esbuild/openbsd-arm64@0.25.12': + optional: true + + '@esbuild/openbsd-x64@0.25.12': + optional: true + + '@esbuild/openharmony-arm64@0.25.12': + optional: true + + '@esbuild/sunos-x64@0.25.12': + optional: true + + '@esbuild/win32-arm64@0.25.12': + optional: true + + '@esbuild/win32-ia32@0.25.12': + optional: true + + '@esbuild/win32-x64@0.25.12': + optional: true + '@eslint-community/eslint-utils@4.4.0(eslint@8.57.1)': dependencies: eslint: 8.57.1 @@ -7436,7 +7687,7 @@ snapshots: caniuse-lite@1.0.30001620: {} - cargo-cp-artifact@0.1.8: {} + cargo-cp-artifact@0.1.9: {} caseless@0.12.0: {} @@ -7971,6 +8222,35 @@ snapshots: is-date-object: 1.0.5 is-symbol: 1.0.4 + esbuild@0.25.12: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.12 + '@esbuild/android-arm': 0.25.12 + '@esbuild/android-arm64': 0.25.12 + '@esbuild/android-x64': 0.25.12 + '@esbuild/darwin-arm64': 0.25.12 + '@esbuild/darwin-x64': 0.25.12 + '@esbuild/freebsd-arm64': 0.25.12 + '@esbuild/freebsd-x64': 0.25.12 + '@esbuild/linux-arm': 0.25.12 + '@esbuild/linux-arm64': 0.25.12 + '@esbuild/linux-ia32': 0.25.12 + '@esbuild/linux-loong64': 0.25.12 + '@esbuild/linux-mips64el': 0.25.12 + '@esbuild/linux-ppc64': 0.25.12 + '@esbuild/linux-riscv64': 0.25.12 + '@esbuild/linux-s390x': 0.25.12 + '@esbuild/linux-x64': 0.25.12 + '@esbuild/netbsd-arm64': 0.25.12 + '@esbuild/netbsd-x64': 0.25.12 + '@esbuild/openbsd-arm64': 0.25.12 + '@esbuild/openbsd-x64': 0.25.12 + '@esbuild/openharmony-arm64': 0.25.12 + '@esbuild/sunos-x64': 0.25.12 + '@esbuild/win32-arm64': 0.25.12 + '@esbuild/win32-ia32': 0.25.12 + '@esbuild/win32-x64': 0.25.12 + escalade@3.1.1: {} escape-html@1.0.3: {} @@ -8431,6 +8711,10 @@ snapshots: call-bind: 1.0.7 get-intrinsic: 1.3.0 + get-tsconfig@4.13.0: + dependencies: + resolve-pkg-maps: 1.0.0 + get-tsconfig@4.7.2: dependencies: resolve-pkg-maps: 1.0.0 @@ -10871,6 +11155,13 @@ snapshots: tslib: 1.14.1 typescript: 5.6.3 + tsx@4.20.6: + dependencies: + esbuild: 0.25.12 + get-tsconfig: 4.13.0 + optionalDependencies: + fsevents: 2.3.3 + tuf-js@2.2.1: dependencies: '@tufjs/models': 2.0.1 diff --git a/scripts/clean.mjs b/scripts/clean.ts similarity index 86% rename from scripts/clean.mjs rename to scripts/clean.ts index f3ac880bb..b62653ab0 100644 --- a/scripts/clean.mjs +++ b/scripts/clean.ts @@ -1,11 +1,10 @@ import { resolve } from 'node:path'; import { readdirSync, readFileSync, rmSync } from 'node:fs'; import { spawnSync } from 'node:child_process'; -import { URL, fileURLToPath } from 'node:url'; import arg from 'arg'; -import JSON5 from 'json5'; +import { parse as parseJson5 } from 'json5'; -const packagesPath = fileURLToPath(new URL('../packages', import.meta.url)); +const packagesPath = resolve(__dirname, '../packages'); function cleanTsGeneratedFiles() { for (const pkg of readdirSync(packagesPath)) { @@ -14,9 +13,9 @@ function cleanTsGeneratedFiles() { let files; try { files = readdirSync(packagePath); - } catch (e) { + } catch (e: unknown) { // Skip over non-directory files like .DS_Store - if (e?.code === 'ENOTDIR') { + if ((e as NodeJS.ErrnoException)?.code === 'ENOTDIR') { continue; } else { throw e; @@ -26,7 +25,7 @@ function cleanTsGeneratedFiles() { for (const file of files) { if (/^tsconfig(.*).json$/.test(file)) { const filePath = resolve(packagePath, file); - const tsconfig = JSON5.parse(readFileSync(filePath)); + const tsconfig = parseJson5(readFileSync(filePath, 'utf8')); const { outDir } = tsconfig.compilerOptions; if (outDir) { const outPath = resolve(packagePath, outDir); @@ -60,4 +59,3 @@ const components = new Set(only === undefined || only.length === 0 ? ['ts', 'pro if (components.has('ts')) cleanTsGeneratedFiles(); if (components.has('proto')) cleanProtoGeneratedFiles(); if (components.has('rust')) cleanCompiledRustFiles(); -if (components.has('test-server')) cleanTestServer(); diff --git a/scripts/create-certs-dir.js b/scripts/create-certs-dir.js deleted file mode 100644 index f8f107055..000000000 --- a/scripts/create-certs-dir.js +++ /dev/null @@ -1,9 +0,0 @@ -// Create /tmp/temporal-certs and populate it with certs from env vars. -// Used in CI flow to store the Cloud certs from GH secret into local files for testing the mTLS sample. -const fs = require('fs-extra'); - -const targetDir = process.argv[2] ?? '/tmp/temporal-certs'; - -fs.mkdirsSync(targetDir); -fs.writeFileSync(`${targetDir}/client.pem`, process.env.TEMPORAL_CLIENT_CERT); -fs.writeFileSync(`${targetDir}/client.key`, process.env.TEMPORAL_CLIENT_KEY); diff --git a/scripts/create-certs-dir.ts b/scripts/create-certs-dir.ts new file mode 100644 index 000000000..bd83b2048 --- /dev/null +++ b/scripts/create-certs-dir.ts @@ -0,0 +1,13 @@ +// Create /tmp/temporal-certs and populate it with certs from env vars. +// Used in CI flow to store the Cloud certs from GH secret into local files for testing the mTLS sample. +import { mkdirsSync, writeFileSync } from 'fs-extra'; + +if (!process.env.TEMPORAL_CLIENT_CERT || !process.env.TEMPORAL_CLIENT_KEY) { + throw new Error('TEMPORAL_CLIENT_CERT and TEMPORAL_CLIENT_KEY must be set'); +} + +const targetDir = process.argv[2] ?? '/tmp/temporal-certs'; + +mkdirsSync(targetDir); +writeFileSync(`${targetDir}/client.pem`, process.env.TEMPORAL_CLIENT_CERT); +writeFileSync(`${targetDir}/client.key`, process.env.TEMPORAL_CLIENT_KEY); diff --git a/scripts/gen-docs.js b/scripts/gen-docs.js deleted file mode 100644 index fecc8eefe..000000000 --- a/scripts/gen-docs.js +++ /dev/null @@ -1,50 +0,0 @@ -const path = require('path'); -const typedoc = require('typedoc'); - -/// Generate docs for a single package. -/// This may not run concurrently because it changes the directory to the package root -async function genDocs(package = 'meta', outputDir) { - const root = path.resolve(__dirname, '../packages', package); - const oldpwd = process.cwd(); - try { - process.chdir(root); - - const app = new typedoc.Application(); - app.options.addReader(new typedoc.TSConfigReader()); - - app.bootstrap({ - tsconfig: 'tsconfig.json', - entryPoints: ['src/index.ts'], - excludePrivate: true, - excludeProtected: true, - hideGenerator: true, - disableSources: true, - hideBreadcrumbs: true, - }); - - const project = app.convert(); - - // Project may not have converted correctly - if (!project) { - throw new Error('Failed to convert app'); - } - - // Rendered docs - await app.generateDocs(project, outputDir); - } finally { - process.chdir(oldpwd); - } -} - -async function main() { - const outputDir = process.argv[2]; - if (!outputDir) { - throw new Error('Usage: gen-docs '); - } - await genDocs('meta', outputDir); -} - -main().catch((err) => { - console.error(err); - process.exit(1); -}); diff --git a/scripts/init-from-verdaccio.js b/scripts/init-from-verdaccio.ts similarity index 73% rename from scripts/init-from-verdaccio.js rename to scripts/init-from-verdaccio.ts index 141ecb3b5..878197e9b 100644 --- a/scripts/init-from-verdaccio.js +++ b/scripts/init-from-verdaccio.ts @@ -1,14 +1,16 @@ -const { resolve, dirname } = require('path'); -const { writeFileSync } = require('fs'); -const { withRegistry, getArgs } = require('./registry'); -const { spawnNpx } = require('./utils'); +import { resolve, dirname } from 'node:path'; +import { writeFileSync } from 'node:fs'; +import { getArgs, withRegistry } from './registry'; +import { spawnNpx } from './utils'; + +// Force samples to use the same version of @temporalio/* packages as the one +// we are testing. This is required when testing against a pre-release version, +// which would not be otherwise matched by specifier like ^1.8.0. +// eslint-disable-next-line import/order +import { version } from '../lerna.json'; async function main() { const { registryDir, targetDir, initArgs } = await getArgs(); - // Force samples to use the same version of @temporalio/* packages as the one - // we are testing. This is required when testing against a pre-release version, - // which would not be otherwise matched by specifier like ^1.8.0. - const { version } = require('../lerna.json'); await withRegistry(registryDir, async () => { console.log('spawning npx @temporalio/create with args:', initArgs); @@ -30,8 +32,6 @@ async function main() { [`@temporalio/create@${version}`, targetDir, '--no-git-init', '--sdk-version', version, ...initArgs], { stdio: 'inherit', - stdout: 'inherit', - stderr: 'inherit', cwd: dirname(targetDir), env: { ...process.env, diff --git a/scripts/prepublish.mjs b/scripts/prepublish.mjs deleted file mode 100644 index cea0f2f4c..000000000 --- a/scripts/prepublish.mjs +++ /dev/null @@ -1,24 +0,0 @@ -import fs from 'node:fs/promises'; -import path from 'node:path'; -import { URL, fileURLToPath } from 'node:url'; - -const rootPath = fileURLToPath(new URL('..', import.meta.url)); -const packagesPath = path.join(rootPath, 'packages'); -const lernaJsonPath = path.join(rootPath, 'lerna.json'); - -const { version } = JSON.parse(await fs.readFile(lernaJsonPath, 'utf8')); - -const packages = await fs.readdir(packagesPath); -for (const dir of packages) { - const packageJsonPath = path.join(packagesPath, dir, 'package.json'); - const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8')); - for (const depType of ['dependencies', 'devDependencies', 'peerDependencies']) { - for (const dep of Object.keys(packageJson[depType] ?? {})) { - if (dep.startsWith('@temporalio/')) { - packageJson[depType][dep] = `${version}`; - } - } - } - const replacedContent = JSON.stringify(packageJson, null, 2); - await fs.writeFile(packageJsonPath, replacedContent + '\n'); -} diff --git a/scripts/prepublish.ts b/scripts/prepublish.ts new file mode 100644 index 000000000..641c75c4e --- /dev/null +++ b/scripts/prepublish.ts @@ -0,0 +1,28 @@ +import fs from 'node:fs/promises'; +import path, { resolve } from 'node:path'; +import { version } from '../lerna.json'; + +async function main() { + const rootPath = resolve(__dirname, '..'); + const packagesPath = path.join(rootPath, 'packages'); + + const packages = await fs.readdir(packagesPath); + for (const dir of packages) { + const packageJsonPath = path.join(packagesPath, dir, 'package.json'); + const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8')); + for (const depType of ['dependencies', 'devDependencies', 'peerDependencies']) { + for (const dep of Object.keys(packageJson[depType] ?? {})) { + if (dep.startsWith('@temporalio/')) { + packageJson[depType][dep] = `${version}`; + } + } + } + const replacedContent = JSON.stringify(packageJson, null, 2); + await fs.writeFile(packageJsonPath, replacedContent + '\n'); + } +} + +main().catch((err) => { + console.error(err); + process.exit(1); +}); diff --git a/scripts/publish-to-verdaccio.js b/scripts/publish-to-verdaccio.ts similarity index 72% rename from scripts/publish-to-verdaccio.js rename to scripts/publish-to-verdaccio.ts index 02a1624ca..4229ea6af 100644 --- a/scripts/publish-to-verdaccio.js +++ b/scripts/publish-to-verdaccio.ts @@ -1,14 +1,12 @@ -const { withRegistry, getArgs } = require('./registry'); -const { spawnNpx } = require('./utils'); +import { getArgs, withRegistry } from './registry'; +import { spawnNpx } from './utils'; -async function main() { +async function main(): Promise { const { registryDir } = await getArgs(); await withRegistry(registryDir, async () => { try { await spawnNpx(['lerna', 'publish', 'from-package', '--yes', '--registry', 'http://127.0.0.1:4873/'], { stdio: 'inherit', - stdout: 'inherit', - stderr: 'inherit', }); } catch (e) { console.error(e); diff --git a/scripts/registry.js b/scripts/registry.ts similarity index 65% rename from scripts/registry.js rename to scripts/registry.ts index 63cc027b8..d6be0c458 100644 --- a/scripts/registry.js +++ b/scripts/registry.ts @@ -1,20 +1,26 @@ -const path = require('path'); -const { tmpdir } = require('os'); -const { mkdtemp } = require('fs-extra'); -const arg = require('arg'); -const { runServer } = require('verdaccio'); -const { mkdirSync } = require('fs'); +import path from 'node:path'; +import { tmpdir } from 'node:os'; +import { mkdirSync } from 'node:fs'; +import { mkdtemp } from 'fs-extra'; +import arg from 'arg'; +import { runServer } from 'verdaccio'; + +interface VerdaccioServer { + listen: (port: number, callback: () => void) => void; + on: (event: string, listener: (...args: any[]) => void) => void; + close: () => Promise; +} class Registry { - constructor(app, workdir) { - this.app = app; - this.workdir = workdir; - } + constructor( + public readonly app: VerdaccioServer, + public readonly workdir: string + ) {} - static async create(workdir) { + static async create(workdir: string): Promise { mkdirSync(workdir, { recursive: true }); - const app = await runServer({ + const app = (await runServer({ self_path: workdir, storage: path.resolve(workdir, 'storage'), @@ -36,9 +42,9 @@ class Registry { }, max_body_size: '200mb', - }); + })) as unknown as VerdaccioServer; - await new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { try { app.listen(4873, resolve); app.on('error', reject); @@ -55,7 +61,7 @@ class Registry { } } -async function withRegistry(testDir, fn) { +export async function withRegistry(testDir: string, fn: () => Promise): Promise { console.log('Starting local registry'); const registry = await Registry.create(testDir); try { @@ -79,7 +85,7 @@ async function createTempRegistryDir() { /** * Parse and return command line arguments */ -async function getArgs() { +export async function getArgs(): Promise<{ registryDir: string; targetDir: string; initArgs: string[] }> { const opts = arg( { '--registry-dir': String, @@ -91,5 +97,3 @@ async function getArgs() { const targetDir = opts['--target-dir'] ?? path.join(registryDir, 'example'); return { registryDir, targetDir, initArgs: opts._.length > 0 ? opts._ : [] }; } - -module.exports = { getArgs, withRegistry }; diff --git a/scripts/test-example.js b/scripts/test-example.ts similarity index 68% rename from scripts/test-example.js rename to scripts/test-example.ts index 914d88a57..886f48c2a 100644 --- a/scripts/test-example.js +++ b/scripts/test-example.ts @@ -1,11 +1,11 @@ -const { spawn: spawnChild, spawnSync } = require('child_process'); -const arg = require('arg'); -const { shell, kill, sleep, waitOnChild } = require('./utils'); +import { ChildProcess, spawn, spawnSync } from 'node:child_process'; +import arg from 'arg'; +import { shell, kill, sleep, waitOnChild } from './utils'; const npm = /^win/.test(process.platform) ? 'npm.cmd' : 'npm'; -function createWorker(workdir) { - return spawnChild(npm, ['start'], { +export function createWorker(workdir: string): ChildProcess { + return spawn(npm, ['start'], { cwd: workdir, stdio: 'inherit', shell, @@ -13,7 +13,7 @@ function createWorker(workdir) { }); } -async function withWorker(workdir, fn) { +export async function withWorker(workdir: string, fn: () => Promise): Promise { console.log('Starting worker'); const worker = createWorker(workdir); try { @@ -23,7 +23,7 @@ async function withWorker(workdir, fn) { } } -async function test(workdir, scriptName, expectedOutput) { +export async function test(workdir: string, scriptName: string, expectedOutput: string): Promise { const { status, output } = spawnSync(npm, ['run', scriptName], { cwd: workdir, shell, @@ -33,12 +33,12 @@ async function test(workdir, scriptName, expectedOutput) { if (status !== 0) { throw new Error('Failed to run workflow'); } - if (!output[1].includes(`${expectedOutput}\n`)) { + if (!output[1]?.includes(`${expectedOutput}\n`)) { throw new Error(`Invalid output: "${output[1]}"`); } } -async function main() { +async function main(): Promise { const opts = arg({ '--work-dir': String, '--script-name': String, diff --git a/scripts/utils.js b/scripts/utils.ts similarity index 61% rename from scripts/utils.js rename to scripts/utils.ts index ce5ed0d65..515a81639 100644 --- a/scripts/utils.js +++ b/scripts/utils.ts @@ -1,33 +1,42 @@ -const { spawn } = require('child_process'); +import { ChildProcess, spawn, SpawnOptions } from 'node:child_process'; -class ChildProcessError extends Error { - constructor(message, code, signal) { +export class ChildProcessError extends Error { + constructor( + message: string, + public readonly code: number | null, + public readonly signal: NodeJS.Signals | null + ) { super(message); this.name = 'ChildProcessError'; - this.code = code; - this.signal = signal; } } -const shell = /^win/.test(process.platform); -const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); +export const shell = /^win/.test(process.platform); -async function waitOnChild(child) { +export async function sleep(ms: number): Promise { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +export async function waitOnChild(child: ChildProcess): Promise { return new Promise((resolve, reject) => { - child.on('exit', (code, signal) => { + child.on('exit', (code: number, signal: NodeJS.Signals) => { if (code === 0) { resolve(); } else { - reject(new ChildProcessError('Process failed', code, signal)); + reject(new ChildProcessError('Process failed', code, signal as NodeJS.Signals)); } }); child.on('error', reject); }); } -async function kill(child, signal = 'SIGINT') { +export async function kill(child: ChildProcess, signal: NodeJS.Signals = 'SIGINT'): Promise { + if (typeof child.pid !== 'number') { + throw new TypeError('Expected child with pid'); + } + + // -PID not supported on Windows if (process.platform === 'win32') { - // -PID not supported on Windows process.kill(child.pid, signal); } else { process.kill(-child.pid, signal); @@ -35,7 +44,7 @@ async function kill(child, signal = 'SIGINT') { try { await waitOnChild(child); - } catch (err) { + } catch (err: unknown) { const signalNumber = getSignalNumber(signal); // Ignore the error if it simply indicates process termination due to the signal we just sent. @@ -49,22 +58,20 @@ async function kill(child, signal = 'SIGINT') { } } -function getSignalNumber(signal) { +function getSignalNumber(signal: NodeJS.Signals): number { // We don't need any other signals for now, and probably never will, so no need to list them all. // But if any other signals ends up being needed, look at `man 3 signal` for the complete list. const SIGNAL_NUMBERS = { SIGINT: 2, SIGTERM: 15, - }; + } as Record; if (signal in SIGNAL_NUMBERS) return SIGNAL_NUMBERS[signal]; throw new TypeError(`Unknown signal in getSignalNumber: '${signal}'. Please add a case for that signal.`); } -async function spawnNpx(args, opts) { +export async function spawnNpx(args: string[], opts: SpawnOptions): Promise { const npx = /^win/.test(process.platform) ? 'npx.cmd' : 'npx'; const npxArgs = ['--prefer-offline', '--timing=true', '--yes', '--', ...args]; await waitOnChild(spawn(npx, npxArgs, { ...opts, shell })); } - -module.exports = { kill, spawnNpx, waitOnChild, ChildProcessError, shell, sleep }; diff --git a/scripts/wait-on-temporal.mjs b/scripts/wait-on-temporal.mjs deleted file mode 100644 index f729e952a..000000000 --- a/scripts/wait-on-temporal.mjs +++ /dev/null @@ -1,43 +0,0 @@ -// This is an ESM and has the mjs extension so it can be run in commonjs and ESM projects alike -import { Connection } from '@temporalio/client'; - -const maxAttempts = 100; -const retryIntervalSecs = 1; -const runId = '26323773-ab30-4442-9a20-c5640b31a7a3'; - -// Starting with 1.20, we should no longer need to wait on namespace -// TODO: Remove all of this once we are confident that this is no longer required -try { - for (let attempt = 1; attempt <= maxAttempts; ++attempt) { - try { - const client = await Connection.connect(); - // Workaround for describeNamespace returning even though namespace is not registered yet - // See: https://github.com/temporalio/temporal/issues/1336 - await client.workflowService.getWorkflowExecutionHistory({ - namespace: 'default', - execution: { workflowId: 'fake', runId }, - }); - } catch (err) { - if ( - err.details && - (err.details.includes('workflow history not found') || - err.details.includes('Workflow executionsRow not found') || - err.details.includes('operation GetCurrentExecution') || - err.details.includes('operation GetWorkflowExecution encountered not found') || - err.details.includes(runId)) - ) { - break; - } - if (attempt === maxAttempts) { - throw err; - } - await new Promise((resolve) => setTimeout(resolve, retryIntervalSecs * 1000)); - } - } -} catch (err) { - console.error('Failed to connect', err); - process.exit(1); -} - -console.log('Connected'); -process.exit(0); diff --git a/tsconfig.scripts.json b/tsconfig.scripts.json new file mode 100644 index 000000000..1a7fb6d2a --- /dev/null +++ b/tsconfig.scripts.json @@ -0,0 +1,12 @@ +{ + "extends": "@tsconfig/node18/tsconfig.json", + "compilerOptions": { + "module": "commonjs", + "moduleResolution": "node", + "types": ["node"], + "rootDir": "./", + "noEmit": true, + "resolveJsonModule": true + }, + "include": ["./scripts/*.ts", "./packages/*/scripts/*.ts"] +}