From 458d8f546e9ef218bd1a1f78cddc799f2c006b38 Mon Sep 17 00:00:00 2001 From: Scott Andrews Date: Sun, 20 Sep 2026 21:29:21 -0400 Subject: [PATCH] Publish interface Use the interface package version as the pre-release component version. Set current version to 0.2.0-dev as the imported interfaces consume wasi@0.3. Combine debug modules into the same ghcr repository as the regular component, distinguished with a semver build label. Signed-off-by: Scott Andrews --- .github/workflows/ci.yaml | 163 +++++------ Cargo.toml | 3 + Makefile | 37 ++- components/stderr-to-stdout/src/lib.rs | 2 +- components/stdout-to-stderr/src/lib.rs | 2 +- .../componentized-cli-0.2.0-dev/package.wit | 7 + .../wit/deps/wasi-cli-0.3.0/package.wit | 256 ++++++++++++++++++ .../wit/deps/wasi-clocks-0.3.0/package.wit | 43 +++ .../deps/wasi-filesystem-0.3.0/package.wit | 149 ++++++++++ .../wit/deps/wasi-random-0.3.0/package.wit | 18 ++ .../wit/deps/wasi-sockets-0.3.0/package.wit | 116 ++++++++ components/wit/worlds.wit | 11 + components/wkg.lock | 12 + components/wkg.toml | 2 + wit/worlds.wit | 9 +- 15 files changed, 728 insertions(+), 102 deletions(-) create mode 100644 components/wit/deps/componentized-cli-0.2.0-dev/package.wit create mode 100644 components/wit/deps/wasi-cli-0.3.0/package.wit create mode 100644 components/wit/deps/wasi-clocks-0.3.0/package.wit create mode 100644 components/wit/deps/wasi-filesystem-0.3.0/package.wit create mode 100644 components/wit/deps/wasi-random-0.3.0/package.wit create mode 100644 components/wit/deps/wasi-sockets-0.3.0/package.wit create mode 100644 components/wit/worlds.wit create mode 100644 components/wkg.lock create mode 100644 components/wkg.toml diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index dcca7e6..a141571 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -1,100 +1,105 @@ name: CI on: - push: + push: branches: - - '**' - - '!dependabot/**' + - "**" + - "!dependabot/**" tags: - - 'v[0-9]+\.[0-9]+\.[0-9]+-?**' + - 'v[0-9]+\.[0-9]+\.[0-9]+-?**' pull_request: {} jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v7 - - uses: actions-rust-lang/setup-rust-toolchain@v2 - - name: Install cargo binstall - uses: cargo-bins/cargo-binstall@main - - name: Install wkg - run: cargo binstall --force wkg - - name: Install wasm-tools - run: cargo binstall --force wasm-tools - - name: Install wac-cli - run: cargo binstall --force wac-cli - - name: Fetch wit - run: make wit - - name: Check for drift in generated wit - run: git diff --exit-code . - - name: Build components - run: make components - - name: Collect components.tar - run: tar -cvf ../components.tar *.wasm* - working-directory: ./lib - - name: Upload components.tar - uses: actions/upload-artifact@v7 - with: - name: components.tar - path: components.tar - retention-days: 7 - - name: Capture WIT - working-directory: ./lib - run: | - for component in *.wasm ; do - echo "::group::${component} ($(du -h ${component} | cut -f1 ))" - wasm-tools component wit "${component}" - echo "::endgroup::" - done - - name: Build test components - run: make test + - uses: actions/checkout@v7 + - uses: actions-rust-lang/setup-rust-toolchain@v2 + - name: Install cargo binstall + uses: cargo-bins/cargo-binstall@main + - name: Install wkg + run: cargo binstall --force wkg + - name: Install wasm-tools + run: cargo binstall --force wasm-tools + - name: Sync wit + run: make wit + - name: Check for drift in generated wit + run: git diff --exit-code . + - name: Build components + run: make components + - name: Collect components.tar + run: tar -cvf ../components.tar *.wasm* + working-directory: ./lib + - name: Upload components.tar + uses: actions/upload-artifact@v7 + with: + name: components.tar + path: components.tar + retention-days: 7 + - name: Test + run: make test + - name: Capture WIT + working-directory: ./lib + run: | + for component in *.wasm ; do + echo "::group::${component} ($(du -h ${component} | cut -f1 ))" + wasm-tools component wit "${component}" + echo "::endgroup::" + done publish: if: github.event_name == 'push' && ( startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main' ) needs: - - build + - build permissions: contents: write packages: write id-token: write runs-on: ubuntu-latest steps: - - uses: actions/checkout@v7 - - uses: actions-rust-lang/setup-rust-toolchain@v2 - - name: Install cargo binstall - uses: cargo-bins/cargo-binstall@main - - name: Install wkg - run: cargo binstall --force wkg - - name: Install cosign - uses: sigstore/cosign-installer@v4.1.2 - - name: Get tag version - if: startsWith(github.ref, 'refs/tags/') - id: get_version - run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//} - - name: Download components.tar - uses: actions/download-artifact@v8 - with: - name: components.tar - - name: Extract components - run: tar -xvf components.tar -C lib - - name: Login to GitHub Container Registry - uses: docker/login-action@v4 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: Publish components to gchr.io - run: make publish - env: - REPOSITORY: "ghcr.io/${{ github.repository }}" - VERSION: "${{ case(github.ref == 'refs/heads/main', 'dev', steps.get_version.outputs.VERSION) }}" - - name: Draft GitHub Release - if: startsWith(github.ref, 'refs/tags/') - uses: softprops/action-gh-release@v3 - with: - draft: true - files: | - lib/*.wasm - components.tar - fail_on_unmatched_files: true - token: ${{ secrets.GITHUB_TOKEN }} + - uses: actions/checkout@v7 + - uses: actions-rust-lang/setup-rust-toolchain@v2 + - name: Install cargo binstall + uses: cargo-bins/cargo-binstall@main + - name: Install wkg + run: cargo binstall --force wkg + - name: Install wasm-tools + run: cargo binstall --force wasm-tools + - name: Install cosign + uses: sigstore/cosign-installer@v4.1.2 + - name: Download components.tar + uses: actions/download-artifact@v8 + with: + name: components.tar + - name: Extract components + run: tar -xvf components.tar -C lib + - name: Get interface version + id: interface_version + run: echo "VERSION=$( wasm-tools component wit lib/interface.wasm --json | jq -r "[.packages[] | select(.name | contains(\"${GITHUB_REPOSITORY/\//:}@\"))][0].name" | cut -d'@' -f2 )" >> $GITHUB_OUTPUT + - name: Get tag version + if: startsWith(github.ref, 'refs/tags/') + id: tag_version + run: echo "VERSION=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_OUTPUT + - name: Login to GitHub Container Registry + uses: docker/login-action@v4 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Publish components to gchr.io + # only publish tags and pre-releases from main + if: startsWith(github.ref, 'refs/tags/') || (github.ref == 'refs/heads/main' && contains(steps.interface_version.outputs.VERSION, '-')) + run: make publish + env: + REPOSITORY: "ghcr.io/${{ github.repository }}" + VERSION: "${{ case(github.ref == 'refs/heads/main', steps.interface_version.outputs.VERSION, steps.tag_version.outputs.VERSION) }}" + - name: Draft GitHub Release + if: startsWith(github.ref, 'refs/tags/') + uses: softprops/action-gh-release@v3 + with: + draft: true + files: | + lib/*.wasm + components.tar + fail_on_unmatched_files: true + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/Cargo.toml b/Cargo.toml index 4426ec2..22732cd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,9 @@ resolver = "2" members = [ "components/*", ] +exclude = [ + "components/wit", +] [workspace.dependencies] wit-bindgen = "0.62.0" diff --git a/Makefile b/Makefile index c1c8734..f31a554 100644 --- a/Makefile +++ b/Makefile @@ -19,19 +19,19 @@ test: @echo "TODO add tests" .PHONY: components -components: $(foreach component,$(COMPONENTS),lib/$(component).wasm $(foreach component,$(COMPONENTS),lib/$(component).debug.wasm)) +components: lib/interface.wasm $(foreach component,$(COMPONENTS),lib/$(component).wasm lib/$(component).debug.wasm) define BUILD_COMPONENT .PHONY: components/$1 components/$1: lib/$1.wasm lib/$1.debug.wasm -lib/$1.wasm: Cargo.toml Cargo.lock wit/deps $(shell find components/$1 -type f) +lib/$1.wasm: Cargo.toml Cargo.lock components/wit/deps $(shell find components/$1 -type f) cargo build -p $1 --target wasm32-unknown-unknown --release wasm-tools component new target/wasm32-unknown-unknown/release/$(subst -,_,$1).wasm -o lib/$1.wasm cp components/$1/README.md lib/$1.wasm.md -lib/$1.debug.wasm: Cargo.toml Cargo.lock wit/deps $(shell find components/$1 -type f) +lib/$1.debug.wasm: Cargo.toml Cargo.lock components/wit/deps $(shell find components/$1 -type f) cargo build -p $1 --target wasm32-unknown-unknown wasm-tools component new target/wasm32-unknown-unknown/debug/$(subst -,_,$1).wasm -o lib/$1.debug.wasm cp components/$1/README.md lib/$1.debug.wasm.md @@ -40,15 +40,21 @@ endef $(foreach component,$(COMPONENTS),$(eval $(call BUILD_COMPONENT,$(component)))) +lib/interface.wasm: wit/deps README.md + wkg build -o lib/interface.wasm + cp README.md lib/interface.wasm.md .PHONY: wit -wit: wit/deps +wit: wit/deps components/wit/deps wit/deps: wkg.toml $(shell find wit -type f -name "*.wit" -not -path "deps") - wkg wit fetch + wkg fetch -.PHONY: publish -publish: $(shell find lib -type f -name "*.wasm" | sed -e 's:^lib/:publish-:g') +components/wit/deps: wit/deps components/wkg.toml $(shell find components/wit -type f -name "*.wit" -not -path "deps") + ( cd components && wkg fetch ) + +.PHONY: publish ## Publish each component in the lib directory +publish: $(shell find lib -maxdepth 1 -type f -name "*.wasm" | sed -e 's:^lib/:publish-:g') .PHONY: publish-% publish-%: @@ -59,25 +65,28 @@ ifndef REPOSITORY $(error REPOSITORY is undefined) endif @$(eval FILE := $(@:publish-%=%)) - @$(eval COMPONENT := $(FILE:%.wasm=%)) + @$(eval COMPONENT := $(if $(filter %.debug.wasm,$(FILE)),$(FILE:%.debug.wasm=%),$(FILE:%.wasm=%))) + @$(eval TITLE := $(if $(filter %.debug.wasm,$(FILE)),$(COMPONENT) (debug),$(COMPONENT))) @$(eval DESCRIPTION := $(shell head -n 3 "lib/${FILE}.md" | tail -n 1)) @$(eval REVISION := $(shell git rev-parse HEAD)$(shell git diff --quiet HEAD && echo "+dirty")) - @$(eval TAG := $(patsubst v%,%,$(subst +,_,$(VERSION)))) + @$(eval COMPONENT_VERSION := $(if $(filter %.debug.wasm,$(FILE)),${VERSION}+debug,${VERSION})) + @$(eval TAG := $(patsubst v%,%,$(subst +,_,$(COMPONENT_VERSION)))) + @$(eval IMAGE := $(if $(filter interface.wasm,$(FILE)),${REPOSITORY}:${TAG},${REPOSITORY}/${COMPONENT}:${TAG})) - @echo "::group::${FILE} -> ${REPOSITORY}/${COMPONENT}:${TAG}" + @echo "::group::${FILE} -> ${IMAGE}" @DIGEST=$$( \ wkg oci push \ - --annotation "org.opencontainers.image.title=${COMPONENT}" \ + --annotation "org.opencontainers.image.title=${TITLE}" \ --annotation "org.opencontainers.image.description=${DESCRIPTION}" \ - --annotation "org.opencontainers.image.version=${VERSION}" \ + --annotation "org.opencontainers.image.version=${COMPONENT_VERSION}" \ --annotation "org.opencontainers.image.source=https://github.com/${GITHUB_REPOSITORY}.git" \ --annotation "org.opencontainers.image.revision=${REVISION}" \ --annotation "org.opencontainers.image.licenses=Apache-2.0" \ - "${REPOSITORY}/${COMPONENT}:${TAG}" \ + "${IMAGE}" \ "lib/${FILE}" \ 2>&1 \ | tee /dev/stderr \ | grep -o 'sha256:[a-f0-9]\{64\}' \ ) ; \ - cosign sign --yes "${REPOSITORY}/${COMPONENT}:${TAG}@$${DIGEST}" + cosign sign --yes "${IMAGE}@$${DIGEST}" @echo "::endgroup::" diff --git a/components/stderr-to-stdout/src/lib.rs b/components/stderr-to-stdout/src/lib.rs index e1efe16..b474713 100644 --- a/components/stderr-to-stdout/src/lib.rs +++ b/components/stderr-to-stdout/src/lib.rs @@ -23,7 +23,7 @@ impl Guest for StderrToStdout { } wit_bindgen::generate!({ - path: "../../wit", + path: "../wit", world: "stderr-to-stdout", merge_structurally_equal_types: true, generate_all diff --git a/components/stdout-to-stderr/src/lib.rs b/components/stdout-to-stderr/src/lib.rs index 7c65b6a..40f58f1 100644 --- a/components/stdout-to-stderr/src/lib.rs +++ b/components/stdout-to-stderr/src/lib.rs @@ -23,7 +23,7 @@ impl Guest for StdoutToStderr { } wit_bindgen::generate!({ - path: "../../wit", + path: "../wit", world: "stdout-to-stderr", merge_structurally_equal_types: true, generate_all diff --git a/components/wit/deps/componentized-cli-0.2.0-dev/package.wit b/components/wit/deps/componentized-cli-0.2.0-dev/package.wit new file mode 100644 index 0000000..868db96 --- /dev/null +++ b/components/wit/deps/componentized-cli-0.2.0-dev/package.wit @@ -0,0 +1,7 @@ +package componentized:cli@0.2.0-dev; + +world imports { + import wasi:cli/types@0.3.0; + import wasi:cli/stdout@0.3.0; + import wasi:cli/stderr@0.3.0; +} diff --git a/components/wit/deps/wasi-cli-0.3.0/package.wit b/components/wit/deps/wasi-cli-0.3.0/package.wit new file mode 100644 index 0000000..7aae56c --- /dev/null +++ b/components/wit/deps/wasi-cli-0.3.0/package.wit @@ -0,0 +1,256 @@ +package wasi:cli@0.3.0; + +@since(version = 0.3.0) +interface environment { + /// Get the POSIX-style environment variables. + /// + /// Each environment variable is provided as a pair of string variable names + /// and string value. + /// + /// Morally, these are a value import, but until value imports are available + /// in the component model, this import function should return the same + /// values each time it is called. + @since(version = 0.3.0) + get-environment: func() -> list>; + + /// Get the POSIX-style arguments to the program. + @since(version = 0.3.0) + get-arguments: func() -> list; + + /// Return a path that programs should use as their initial current working + /// directory, interpreting `.` as shorthand for this. + @since(version = 0.3.0) + get-initial-cwd: func() -> option; +} + +@since(version = 0.3.0) +interface exit { + /// Exit the current instance and any linked instances. + @since(version = 0.3.0) + exit: func(status: result); + + /// Exit the current instance and any linked instances, reporting the + /// specified status code to the host. + /// + /// The meaning of the code depends on the context, with 0 usually meaning + /// "success", and other values indicating various types of failure. + /// + /// This function does not return; the effect is analogous to a trap, but + /// without the connotation that something bad has happened. + @since(version = 0.3.0) + exit-with-code: func(status-code: u8); +} + +@since(version = 0.3.0) +interface run { + /// Run the program. + @since(version = 0.3.0) + run: async func() -> result; +} + +@since(version = 0.3.0) +interface types { + @since(version = 0.3.0) + enum error-code { + /// Input/output error + io, + /// Invalid or incomplete multibyte or wide character + illegal-byte-sequence, + /// Broken pipe + pipe, + } +} + +@since(version = 0.3.0) +interface stdin { + use types.{error-code}; + + /// Return a stream for reading from stdin. + /// + /// This function returns a stream which provides data read from stdin, + /// and a future to signal read results. + /// + /// If the stream's readable end is dropped the future will resolve to success. + /// + /// If the stream's writable end is dropped the future will either resolve to + /// success if stdin was closed by the writer or to an error-code if reading + /// failed for some other reason. + /// + /// Multiple streams may be active at the same time. The behavior of concurrent + /// reads is implementation-specific. + @since(version = 0.3.0) + read-via-stream: func() -> tuple, future>>; +} + +@since(version = 0.3.0) +interface stdout { + use types.{error-code}; + + /// Write the given stream to stdout. + /// + /// If the stream's writable end is dropped this function will either return + /// success once the entire contents of the stream have been written or an + /// error-code representing a failure. + /// + /// Otherwise if there is an error the readable end of the stream will be + /// dropped and this function will return an error-code. + @since(version = 0.3.0) + write-via-stream: func(data: stream) -> future>; +} + +@since(version = 0.3.0) +interface stderr { + use types.{error-code}; + + /// Write the given stream to stderr. + /// + /// If the stream's writable end is dropped this function will either return + /// success once the entire contents of the stream have been written or an + /// error-code representing a failure. + /// + /// Otherwise if there is an error the readable end of the stream will be + /// dropped and this function will return an error-code. + @since(version = 0.3.0) + write-via-stream: func(data: stream) -> future>; +} + +/// Terminal input. +/// +/// In the future, this may include functions for disabling echoing, +/// disabling input buffering so that keyboard events are sent through +/// immediately, querying supported features, and so on. +@since(version = 0.3.0) +interface terminal-input { + /// The input side of a terminal. + @since(version = 0.3.0) + resource terminal-input; +} + +/// Terminal output. +/// +/// In the future, this may include functions for querying the terminal +/// size, being notified of terminal size changes, querying supported +/// features, and so on. +@since(version = 0.3.0) +interface terminal-output { + /// The output side of a terminal. + @since(version = 0.3.0) + resource terminal-output; +} + +/// An interface providing an optional `terminal-input` for stdin as a +/// link-time authority. +@since(version = 0.3.0) +interface terminal-stdin { + @since(version = 0.3.0) + use terminal-input.{terminal-input}; + + /// If stdin is connected to a terminal, return a `terminal-input` handle + /// allowing further interaction with it. + @since(version = 0.3.0) + get-terminal-stdin: func() -> option; +} + +/// An interface providing an optional `terminal-output` for stdout as a +/// link-time authority. +@since(version = 0.3.0) +interface terminal-stdout { + @since(version = 0.3.0) + use terminal-output.{terminal-output}; + + /// If stdout is connected to a terminal, return a `terminal-output` handle + /// allowing further interaction with it. + @since(version = 0.3.0) + get-terminal-stdout: func() -> option; +} + +/// An interface providing an optional `terminal-output` for stderr as a +/// link-time authority. +@since(version = 0.3.0) +interface terminal-stderr { + @since(version = 0.3.0) + use terminal-output.{terminal-output}; + + /// If stderr is connected to a terminal, return a `terminal-output` handle + /// allowing further interaction with it. + @since(version = 0.3.0) + get-terminal-stderr: func() -> option; +} + +@since(version = 0.3.0) +world imports { + @since(version = 0.3.0) + import environment; + @since(version = 0.3.0) + import exit; + @since(version = 0.3.0) + import types; + @since(version = 0.3.0) + import stdin; + @since(version = 0.3.0) + import stdout; + @since(version = 0.3.0) + import stderr; + @since(version = 0.3.0) + import terminal-input; + @since(version = 0.3.0) + import terminal-output; + @since(version = 0.3.0) + import terminal-stdin; + @since(version = 0.3.0) + import terminal-stdout; + @since(version = 0.3.0) + import terminal-stderr; + import wasi:clocks/types@0.3.0; + import wasi:clocks/monotonic-clock@0.3.0; + import wasi:clocks/system-clock@0.3.0; + @unstable(feature = clocks-timezone) + import wasi:clocks/timezone@0.3.0; + import wasi:filesystem/types@0.3.0; + import wasi:filesystem/preopens@0.3.0; + import wasi:sockets/types@0.3.0; + import wasi:sockets/ip-name-lookup@0.3.0; + import wasi:random/random@0.3.0; + import wasi:random/insecure@0.3.0; + import wasi:random/insecure-seed@0.3.0; +} +@since(version = 0.3.0) +world command { + @since(version = 0.3.0) + import environment; + @since(version = 0.3.0) + import exit; + @since(version = 0.3.0) + import types; + @since(version = 0.3.0) + import stdin; + @since(version = 0.3.0) + import stdout; + @since(version = 0.3.0) + import stderr; + @since(version = 0.3.0) + import terminal-input; + @since(version = 0.3.0) + import terminal-output; + @since(version = 0.3.0) + import terminal-stdin; + @since(version = 0.3.0) + import terminal-stdout; + @since(version = 0.3.0) + import terminal-stderr; + import wasi:clocks/types@0.3.0; + import wasi:clocks/monotonic-clock@0.3.0; + import wasi:clocks/system-clock@0.3.0; + @unstable(feature = clocks-timezone) + import wasi:clocks/timezone@0.3.0; + import wasi:filesystem/types@0.3.0; + import wasi:filesystem/preopens@0.3.0; + import wasi:sockets/types@0.3.0; + import wasi:sockets/ip-name-lookup@0.3.0; + import wasi:random/random@0.3.0; + import wasi:random/insecure@0.3.0; + import wasi:random/insecure-seed@0.3.0; + + @since(version = 0.3.0) + export run; +} diff --git a/components/wit/deps/wasi-clocks-0.3.0/package.wit b/components/wit/deps/wasi-clocks-0.3.0/package.wit new file mode 100644 index 0000000..871adf0 --- /dev/null +++ b/components/wit/deps/wasi-clocks-0.3.0/package.wit @@ -0,0 +1,43 @@ +package wasi:clocks@0.3.0; + +interface types { + type duration = u64; +} + +interface monotonic-clock { + use types.{duration}; + + type mark = u64; + + now: func() -> mark; + + get-resolution: func() -> duration; + + wait-until: async func(when: mark); + + wait-for: async func(how-long: duration); +} + +interface system-clock { + use types.{duration}; + + record instant { + seconds: s64, + nanoseconds: u32, + } + + now: func() -> instant; + + get-resolution: func() -> duration; +} + +interface timezone { + use system-clock.{instant}; + + iana-id: func() -> option; + + utc-offset: func(when: instant) -> option; + + to-debug-string: func() -> string; +} + diff --git a/components/wit/deps/wasi-filesystem-0.3.0/package.wit b/components/wit/deps/wasi-filesystem-0.3.0/package.wit new file mode 100644 index 0000000..492d2ca --- /dev/null +++ b/components/wit/deps/wasi-filesystem-0.3.0/package.wit @@ -0,0 +1,149 @@ +package wasi:filesystem@0.3.0; + +interface types { + use wasi:clocks/system-clock@0.3.0.{instant}; + + type filesize = u64; + + variant descriptor-type { + block-device, + character-device, + directory, + fifo, + symbolic-link, + regular-file, + socket, + other(option), + } + + flags descriptor-flags { + read, + write, + file-integrity-sync, + data-integrity-sync, + requested-write-sync, + mutate-directory, + } + + flags path-flags { + symlink-follow, + } + + flags open-flags { + create, + directory, + exclusive, + truncate, + } + + type link-count = u64; + + record descriptor-stat { + %type: descriptor-type, + link-count: link-count, + size: filesize, + data-access-timestamp: option, + data-modification-timestamp: option, + status-change-timestamp: option, + } + + variant new-timestamp { + no-change, + now, + timestamp(instant), + } + + record directory-entry { + %type: descriptor-type, + name: string, + } + + variant error-code { + access, + already, + bad-descriptor, + busy, + deadlock, + quota, + exist, + file-too-large, + illegal-byte-sequence, + in-progress, + interrupted, + invalid, + io, + is-directory, + loop, + too-many-links, + message-size, + name-too-long, + no-device, + no-entry, + no-lock, + insufficient-memory, + insufficient-space, + not-directory, + not-empty, + not-recoverable, + unsupported, + no-tty, + no-such-device, + overflow, + not-permitted, + pipe, + read-only, + invalid-seek, + text-file-busy, + cross-device, + other(option), + } + + enum advice { + normal, + sequential, + random, + will-need, + dont-need, + no-reuse, + } + + record metadata-hash-value { + lower: u64, + upper: u64, + } + + resource descriptor { + read-via-stream: func(offset: filesize) -> tuple, future>>; + write-via-stream: func(data: stream, offset: filesize) -> future>; + append-via-stream: func(data: stream) -> future>; + advise: async func(offset: filesize, length: filesize, advice: advice) -> result<_, error-code>; + sync-data: async func() -> result<_, error-code>; + get-flags: async func() -> result; + get-type: async func() -> result; + set-size: async func(size: filesize) -> result<_, error-code>; + set-times: async func(data-access-timestamp: new-timestamp, data-modification-timestamp: new-timestamp) -> result<_, error-code>; + read-directory: func() -> tuple, future>>; + sync: async func() -> result<_, error-code>; + create-directory-at: async func(path: string) -> result<_, error-code>; + stat: async func() -> result; + stat-at: async func(path-flags: path-flags, path: string) -> result; + set-times-at: async func(path-flags: path-flags, path: string, data-access-timestamp: new-timestamp, data-modification-timestamp: new-timestamp) -> result<_, error-code>; + link-at: async func(old-path-flags: path-flags, old-path: string, new-descriptor: borrow, new-path: string) -> result<_, error-code>; + open-at: async func(path-flags: path-flags, path: string, open-flags: open-flags, %flags: descriptor-flags) -> result; + readlink-at: async func(path: string) -> result; + remove-directory-at: async func(path: string) -> result<_, error-code>; + rename-at: async func(old-path: string, new-descriptor: borrow, new-path: string) -> result<_, error-code>; + symlink-at: async func(old-path: string, new-path: string) -> result<_, error-code>; + unlink-file-at: async func(path: string) -> result<_, error-code>; + is-same-object: async func(other: borrow) -> bool; + metadata-hash: async func() -> result; + metadata-hash-at: async func(path-flags: path-flags, path: string) -> result; + } +} + +interface preopens { + use types.{descriptor}; + + get-directories: func() -> list>; +} + diff --git a/components/wit/deps/wasi-random-0.3.0/package.wit b/components/wit/deps/wasi-random-0.3.0/package.wit new file mode 100644 index 0000000..f6cfb81 --- /dev/null +++ b/components/wit/deps/wasi-random-0.3.0/package.wit @@ -0,0 +1,18 @@ +package wasi:random@0.3.0; + +interface random { + get-random-bytes: func(max-len: u64) -> list; + + get-random-u64: func() -> u64; +} + +interface insecure { + get-insecure-random-bytes: func(max-len: u64) -> list; + + get-insecure-random-u64: func() -> u64; +} + +interface insecure-seed { + get-insecure-seed: func() -> tuple; +} + diff --git a/components/wit/deps/wasi-sockets-0.3.0/package.wit b/components/wit/deps/wasi-sockets-0.3.0/package.wit new file mode 100644 index 0000000..da14ae8 --- /dev/null +++ b/components/wit/deps/wasi-sockets-0.3.0/package.wit @@ -0,0 +1,116 @@ +package wasi:sockets@0.3.0; + +interface types { + use wasi:clocks/types@0.3.0.{duration}; + + variant error-code { + access-denied, + not-supported, + invalid-argument, + out-of-memory, + timeout, + invalid-state, + address-not-bindable, + address-in-use, + remote-unreachable, + connection-refused, + connection-broken, + connection-reset, + connection-aborted, + datagram-too-large, + other(option), + } + + enum ip-address-family { + ipv4, + ipv6, + } + + type ipv4-address = tuple; + + type ipv6-address = tuple; + + variant ip-address { + ipv4(ipv4-address), + ipv6(ipv6-address), + } + + record ipv4-socket-address { + port: u16, + address: ipv4-address, + } + + record ipv6-socket-address { + port: u16, + flow-info: u32, + address: ipv6-address, + scope-id: u32, + } + + variant ip-socket-address { + ipv4(ipv4-socket-address), + ipv6(ipv6-socket-address), + } + + resource tcp-socket { + create: static func(address-family: ip-address-family) -> result; + bind: func(local-address: ip-socket-address) -> result<_, error-code>; + connect: async func(remote-address: ip-socket-address) -> result<_, error-code>; + listen: func() -> result, error-code>; + send: func(data: stream) -> future>; + receive: func() -> tuple, future>>; + get-local-address: func() -> result; + get-remote-address: func() -> result; + get-is-listening: func() -> bool; + get-address-family: func() -> ip-address-family; + set-listen-backlog-size: func(value: u64) -> result<_, error-code>; + get-keep-alive-enabled: func() -> result; + set-keep-alive-enabled: func(value: bool) -> result<_, error-code>; + get-keep-alive-idle-time: func() -> result; + set-keep-alive-idle-time: func(value: duration) -> result<_, error-code>; + get-keep-alive-interval: func() -> result; + set-keep-alive-interval: func(value: duration) -> result<_, error-code>; + get-keep-alive-count: func() -> result; + set-keep-alive-count: func(value: u32) -> result<_, error-code>; + get-hop-limit: func() -> result; + set-hop-limit: func(value: u8) -> result<_, error-code>; + get-receive-buffer-size: func() -> result; + set-receive-buffer-size: func(value: u64) -> result<_, error-code>; + get-send-buffer-size: func() -> result; + set-send-buffer-size: func(value: u64) -> result<_, error-code>; + } + + resource udp-socket { + create: static func(address-family: ip-address-family) -> result; + bind: func(local-address: ip-socket-address) -> result<_, error-code>; + connect: func(remote-address: ip-socket-address) -> result<_, error-code>; + disconnect: func() -> result<_, error-code>; + send: async func(data: list, remote-address: option) -> result<_, error-code>; + receive: async func() -> result, ip-socket-address>, error-code>; + get-local-address: func() -> result; + get-remote-address: func() -> result; + get-address-family: func() -> ip-address-family; + get-unicast-hop-limit: func() -> result; + set-unicast-hop-limit: func(value: u8) -> result<_, error-code>; + get-receive-buffer-size: func() -> result; + set-receive-buffer-size: func(value: u64) -> result<_, error-code>; + get-send-buffer-size: func() -> result; + set-send-buffer-size: func(value: u64) -> result<_, error-code>; + } +} + +interface ip-name-lookup { + use types.{ip-address}; + + variant error-code { + access-denied, + invalid-argument, + name-unresolvable, + temporary-resolver-failure, + permanent-resolver-failure, + other(option), + } + + resolve-addresses: async func(name: string) -> result, error-code>; +} + diff --git a/components/wit/worlds.wit b/components/wit/worlds.wit new file mode 100644 index 0000000..f44537b --- /dev/null +++ b/components/wit/worlds.wit @@ -0,0 +1,11 @@ +package componentized:cli-components; + +world stderr-to-stdout { + import wasi:cli/stdout@0.3.0; + export wasi:cli/stderr@0.3.0; +} + +world stdout-to-stderr { + import wasi:cli/stderr@0.3.0; + export wasi:cli/stdout@0.3.0; +} diff --git a/components/wkg.lock b/components/wkg.lock new file mode 100644 index 0000000..c886d90 --- /dev/null +++ b/components/wkg.lock @@ -0,0 +1,12 @@ +# This file is automatically generated. +# It is not intended for manual editing. +version = 1 + +[[packages]] +name = "wasi:cli" +registry = "wasi.dev" + +[[packages.versions]] +requirement = "=0.3.0" +version = "0.3.0" +digest = "sha256:3a2d58743b67a057f7210b9a73d3b21b34ec7895ffe34d1cb092927307156e40" diff --git a/components/wkg.toml b/components/wkg.toml new file mode 100644 index 0000000..9ff1d87 --- /dev/null +++ b/components/wkg.toml @@ -0,0 +1,2 @@ +[overrides] +"componentized:cli" = { path = "../wit" } diff --git a/wit/worlds.wit b/wit/worlds.wit index 656317f..ebd0584 100644 --- a/wit/worlds.wit +++ b/wit/worlds.wit @@ -1,11 +1,6 @@ -package componentized:cli; +package componentized:cli@0.2.0-dev; -world stderr-to-stdout { +world imports { import wasi:cli/stdout@0.3.0; - export wasi:cli/stderr@0.3.0; -} - -world stdout-to-stderr { import wasi:cli/stderr@0.3.0; - export wasi:cli/stdout@0.3.0; }