Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 26 additions & 10 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1912,6 +1912,11 @@ jobs:

GOOS=windows GOARCH=amd64 make build-grpc VERSION="$VERSION" COMMIT="$COMMIT" BUILD_TIME="$BUILD_TIME" GO_VERSION="$GO_VERSION"
mv bin/sysml-grpc dist/grpc/sysml-grpc-windows-amd64.exe

# The Node client ships this combined WebAssembly module and matching Go runtime.
mkdir -p dist/wasm
make build-release-wasm VERSION="$VERSION" COMMIT="$COMMIT" BUILD_TIME="$BUILD_TIME" GO_VERSION="$GO_VERSION"
mv bin/wasm/release/sysml-wasm.wasm bin/wasm/release/wasm_exec.js dist/wasm/

# Create tarballs
cd dist
Expand Down Expand Up @@ -1984,7 +1989,7 @@ jobs:
*) fail "$binary" "it reports '${reported}'" ;;
esac
done
for binary in dist/sysml-* dist/grpc/sysml-grpc-*; do
for binary in dist/sysml-* dist/grpc/sysml-grpc-* dist/wasm/sysml-wasm.wasm; do
case "$binary" in
*.tar.gz|*.zip|*.sha256) continue ;;
dist/sysml-linux-amd64|dist/sysml-lsp-linux-amd64) continue ;;
Expand Down Expand Up @@ -2034,6 +2039,8 @@ jobs:
# the only checksum opensysml reads.
(cd grpc && sha256sum sysml-grpc-* >> ../SHA256SUMS.txt)
(cd grpc && for f in sysml-grpc-*; do sha256sum "$f" > "$f.sha256"; done)
(cd wasm && sha256sum sysml-wasm.wasm wasm_exec.js >> ../SHA256SUMS.txt)
(cd wasm && for f in sysml-wasm.wasm wasm_exec.js; do sha256sum "$f" > "$f.sha256"; done)
cat SHA256SUMS.txt

# The distribution was stamped from the binaries before the manifest
Expand Down Expand Up @@ -2134,7 +2141,7 @@ jobs:
command: |
export PATH="$(go env GOPATH)/bin:$PATH"
cd dist
for artifact in opensysml-linux-amd64.tar.gz grpc/sysml-grpc-linux-amd64 opensysml-*-py3-none-any.whl; do
for artifact in opensysml-linux-amd64.tar.gz grpc/sysml-grpc-linux-amd64 wasm/sysml-wasm.wasm opensysml-*-py3-none-any.whl; do
cosign verify-blob-attestation "$artifact" \
--bundle provenance.intoto.json.bundle \
--type slsaprovenance1 \
Expand Down Expand Up @@ -2191,6 +2198,7 @@ jobs:
paths:
- dist/SHA256SUMS.txt
- dist/grpc/*.sha256
- dist/wasm/*.sha256
- dist/opensysml-*-py3-none-any.whl
- dist/opensysml-[0-9]*.tar.gz
- unless:
Expand Down Expand Up @@ -2250,6 +2258,8 @@ jobs:
echo "Publishing ${version} to the '${dist_tag}' dist-tag"
# Proves the workspace carries the release binaries and sidecars.
ls -l dist/grpc/sysml-grpc-*
ls -l dist/wasm/sysml-wasm.wasm dist/wasm/wasm_exec.js \
dist/wasm/sysml-wasm.wasm.sha256 dist/wasm/wasm_exec.js.sha256

- run:
name: Require the publishing token
Expand All @@ -2267,17 +2277,19 @@ jobs:
name: Refuse a version already on the registry
command: |
# The package names come from package.json, not a literal list:
# the client itself plus the optionalDependencies that carry the
# platform binaries. Anything but six means the manifest drifted.
# the client, platform binaries and optional WASM peer. Anything
# but seven means the manifest drifted.
names=$(node -e "
const pkg = require('./client/node/package.json');
const platforms = Object.keys(pkg.optionalDependencies || {})
.filter(n => n.startsWith(pkg.name + '-sysml-grpc-'));
console.log([pkg.name, ...platforms].join('\n'));
const wasm = Object.keys(pkg.peerDependencies || {})
.filter(n => n.startsWith(pkg.name + '-wasm'));
console.log([pkg.name, ...platforms, ...wasm].join('\n'));
")
count=$(echo "$names" | wc -l)
if [ "$count" -ne 6 ]; then
echo "Error: expected 6 packages to publish (client + 5 platform),"
if [ "$count" -ne 7 ]; then
echo "Error: expected 7 packages to publish (client + 5 platform + WASM),"
echo "package.json yields $count:"
echo "$names"
exit 1
Expand All @@ -2303,12 +2315,12 @@ jobs:
npm test

- run:
name: Build the per-platform packages
name: Build the platform and WASM packages
command: |
# These are build-release's bytes; the generator checks each one
# against its .sha256 sidecar before packaging it.
cd client/node
npm run platform-packages -- --binaries ../../dist/grpc
npm run platform-packages -- --binaries ../../dist/grpc --wasm ../../dist/wasm

- run:
name: Authenticate to npm
Expand All @@ -2323,8 +2335,9 @@ jobs:
# No --provenance: the npm CLI only mints attestations on GitHub Actions and
# GitLab CI/CD, and it fails rather than publish unattested when asked here.
- run:
name: Publish the per-platform packages
name: Publish the WASM and per-platform packages
command: |
npm publish client/node/packages/sysml-wasm --access public --tag "$NPM_DIST_TAG"
for directory in client/node/packages/sysml-grpc-*; do
npm publish "$directory" --access public --tag "$NPM_DIST_TAG"
done
Expand All @@ -2340,6 +2353,7 @@ jobs:
- run:
name: "REHEARSAL: pack every package"
command: |
npm pack client/node/packages/sysml-wasm --dry-run
for directory in client/node/packages/sysml-grpc-*; do
npm pack "$directory" --dry-run
done
Expand Down Expand Up @@ -2673,6 +2687,7 @@ jobs:
# The opensysml wheel, the same bytes publish-pypi uploads.
mv dist/*.whl dist/release/
mv dist/grpc/* dist/release/
mv dist/wasm/* dist/release/
mv dist/SHA256SUMS.txt dist/release/
# The signature over that manifest, which the Python client verifies
# before it trusts a digest from it.
Expand Down Expand Up @@ -2708,6 +2723,7 @@ jobs:
name: "REHEARSAL: check the release assets and the GitHub token"
command: |
ls dist/SHA256SUMS.txt > /dev/null
ls dist/wasm/sysml-wasm.wasm dist/wasm/wasm_exec.js > /dev/null
set -- dist/opensysml-*-py3-none-any.whl
if [ ! -f "$1" ] || [ $# -ne 1 ]; then
echo "Error: expected exactly one dist/opensysml-*-py3-none-any.whl"
Expand Down
32 changes: 28 additions & 4 deletions .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,11 @@ jobs:
printf '%s\n' " [this workflow run]($RUN_URL). Every binary reports \`$VERSION\`."
echo
printf '%s' "The snapshot is replaced each night and is never the \`latest\` release; Homebrew,"
printf '%s' " PyPI, npm and the Windows installer follow the stable line only. The"
printf '%s' " PyPI, npm and the Windows installer follow the stable line only."
if [[ -f dist/wasm/sysml-wasm.wasm ]]; then
printf '%s' " The \`sysml-wasm.wasm\` module and matching \`wasm_exec.js\` are available in its assets."
fi
printf '%s' " The"
printf '%s' " [snapshot page](https://opensysml.org/project/nightly/) explains what it is, how"
printf '%s' " to verify it and what to expect from it; the"
printf '%s\n' " [install guide](https://opensysml.org/guide/01-install/) covers the stable releases."
Expand Down Expand Up @@ -245,6 +249,28 @@ jobs:
DATE: ${{ steps.version.outputs.date }}
run: |
sha=$(git rev-parse HEAD)
assets=(
dist/*.tar.gz
dist/*.zip
dist/opensysml-sysml.vsix
dist/SHA256SUMS.txt
dist/SHA256SUMS.txt.bundle
dist/grpc/sysml-grpc-*
)
if [[ -f dist/wasm/sysml-wasm.wasm ]]; then
assets+=(
dist/wasm/sysml-wasm.wasm
dist/wasm/wasm_exec.js
dist/wasm/sysml-wasm.wasm.sha256
dist/wasm/wasm_exec.js.sha256
)
fi
for asset in "${assets[@]}"; do
if [[ ! -f "$asset" ]]; then
printf '::error::Missing release asset: %s\n' "$asset"
exit 1
fi
done
if gh release view "$TAG" --json tagName >/dev/null 2>&1; then
gh release delete "$TAG" --yes
fi
Expand All @@ -256,7 +282,5 @@ jobs:
--notes-file notes.md \
--prerelease \
--latest=false \
dist/*.tar.gz dist/*.zip dist/opensysml-sysml.vsix \
dist/SHA256SUMS.txt dist/SHA256SUMS.txt.bundle \
dist/grpc/sysml-grpc-*
"${assets[@]}"
gh release view "$TAG" --json url,assets --jq '.url, (.assets[].name)'
9 changes: 8 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: all build build-sysml build-prod build-wasm-prod build-lsp build-grpc build-engine build-core build-syntax build-sysml-wasm build-wasm build-wasm-wasip1 build-wasm-js wasm-check static-check windows-versioninfo-check man man-check install-tree pgo-profile conformance conformance-pkg conformance-rust conformance-julia conformance-matlab test test-shard coverage lint clean install help fuml-expected python-test python-coverage scripts-coverage node-coverage python-install proto proto-buf python-proto proto-ts proto-rust proto-lint proto-breaking vscode-grammar vscode-build vscode-package docs docs-install docs-serve docs-engine-assets docs-counts docs-check changelog-check changelog-render self-model
.PHONY: all build build-sysml build-prod build-wasm-prod build-lsp build-grpc build-engine build-core build-syntax build-sysml-wasm build-release-wasm build-wasm build-wasm-wasip1 build-wasm-js wasm-check static-check windows-versioninfo-check man man-check install-tree pgo-profile conformance conformance-pkg conformance-rust conformance-julia conformance-matlab test test-shard coverage lint clean install help fuml-expected python-test python-coverage scripts-coverage node-coverage python-install proto proto-buf python-proto proto-ts proto-rust proto-lint proto-breaking vscode-grammar vscode-build vscode-package docs docs-install docs-serve docs-engine-assets docs-counts docs-check changelog-check changelog-render self-model

# Version information
# Only release tags describe a build; the moving `nightly` tag is not a version.
Expand Down Expand Up @@ -141,6 +141,13 @@ build-sysml-wasm: ## Build bin/sysml-wasm natively (opt-in; not released)
$(GO_BUILD) -o $(BIN_DIR)/sysml-wasm ./cmd/sysml-wasm
@echo "✓ Built $(BIN_DIR)/sysml-wasm ($(VERSION))"

build-release-wasm: ## Build release bin/wasm/release/sysml-wasm.wasm and wasm_exec.js
@echo "Building release WebAssembly assets..."
@mkdir -p $(WASM_DIR)/release
GOOS=js GOARCH=wasm $(GO_BUILD) -trimpath -o $(WASM_DIR)/release/sysml-wasm.wasm ./cmd/sysml-wasm
@cp "$(shell go env GOROOT)/lib/wasm/wasm_exec.js" $(WASM_DIR)/release/wasm_exec.js
@echo "✓ Built $(WASM_DIR)/release/sysml-wasm.wasm and wasm_exec.js ($(VERSION))"

build-syntax: ## Build bin/sysml-syntax natively (opt-in; not released)
@echo "Building sysml-syntax..."
@mkdir -p $(BIN_DIR)
Expand Down
3 changes: 3 additions & 0 deletions changes/unreleased/sysml-wasm-release.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- **Publish the combined WebAssembly module.** Stable and nightly releases ship the module and matching Go
runtime, npm publishes them as `@openmbee/opensysml-wasm`, and Node `connectWasm()` resolves the
installed package automatically.
38 changes: 34 additions & 4 deletions client/node/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,11 +181,25 @@ other capability-gated operations fail with `MissingCapabilityError`, and a
direct unsupported RPC fails with `UNIMPLEMENTED`.
The adapter uses JSON encoding; requesting protobuf encoding is refused.

In Node, `connectWasm()` runs a worker thread by default:
In Node, install the optional `@openmbee/opensysml-wasm` package at the same
version as this client. `connectWasm()` resolves its module and matching Go
runtime automatically and runs a worker thread by default:

```bash
npm install @openmbee/opensysml@<version> @openmbee/opensysml-wasm@<version>
```

```ts
import { connectWasm } from "@openmbee/opensysml";

await using connection = await connectWasm();
const model = await connection.loads("package Demo { part def Car; }");
```

To use a module from another source, pass both the module and its matching Go
runtime:

```ts
await using connection = await connectWasm({
wasm: "./sysml-wasm.wasm",
wasmExec: "/path/to/the/matching/wasm_exec.js",
Expand Down Expand Up @@ -222,9 +236,25 @@ If the page loads `wasm_exec.js` itself, omit `wasmExec` to use the installed Go
constructor.

The browser worker module can be bundled from
`@openmbee/opensysml/browser/wasm-worker`. The combined module measures about
7.8 MB gzipped and 5.5 MB with Brotli. A package containing the matching WASM
and Go runtime artifacts will be published separately in a future release.
`@openmbee/opensysml/browser/wasm-worker`. Bundle the module and runtime from
the npm package with:

```ts
const wasm = new URL("@openmbee/opensysml-wasm/sysml-wasm.wasm", import.meta.url);
const wasmExec = new URL("@openmbee/opensysml-wasm/wasm_exec.js", import.meta.url);
```

Or fetch both from jsDelivr, replacing `<version>` with the matching package
version:

```text
https://cdn.jsdelivr.net/npm/@openmbee/opensysml-wasm@<version>/sysml-wasm.wasm
https://cdn.jsdelivr.net/npm/@openmbee/opensysml-wasm@<version>/wasm_exec.js
```

Browser callers pass those URLs as `wasm` and `wasmExec`; browser package
resolution is not automatic. The combined module measures about 7.8 MB gzipped
and 5.5 MB with Brotli.

## Protobuf, not JSON

Expand Down
11 changes: 11 additions & 0 deletions client/node/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions client/node/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@
"@sigstore/tuf": "4.0.2",
"@sigstore/verify": "3.1.1"
},
"peerDependencies": {
"@openmbee/opensysml-wasm": "0.9.1"
},
"peerDependenciesMeta": {
"@openmbee/opensysml-wasm": {
"optional": true
}
},
"devDependencies": {
"@bufbuild/protoc-gen-es": "2.14.0",
"@types/make-fetch-happen": "^10.0.4",
Expand Down
Loading
Loading