Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weโ€™ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PM-12967] Create bitwarden-wasm-internal #1089

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 6 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
76 changes: 76 additions & 0 deletions .github/workflows/build-wasm-internal.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
---
name: Build @bitwarden/sdk-internal

on:
pull_request:
push:
branches:
- "main"
- "rc"
- "hotfix-rc"
workflow_dispatch:

defaults:
run:
shell: bash
working-directory: crates/bitwarden-wasm-internal

jobs:
build:
name: Building @bitwarden/sdk-wasm-internal
runs-on: ubuntu-22.04

steps:
- name: Checkout repo
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

- name: Setup Node
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
node-version: 20
registry-url: "https://npm.pkg.github.com"
cache: "npm"

- name: Install dependencies
run: npm i -g binaryen

- name: Install rust
uses: dtolnay/rust-toolchain@7b1c307e0dcbda6122208f10795a713336a9b35a # stable
with:
toolchain: stable
targets: wasm32-unknown-unknown

- name: Cache cargo registry
uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3
with:
key: wasm-cargo-cache

- name: Install wasm-bindgen-cli
run: cargo install wasm-bindgen-cli

- name: Build
run: ./build.sh -r

- name: Upload artifact
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
with:
name: sdk-bitwarden-wasm-internal
path: ${{ github.workspace }}/languages/js/sdk-internal/*
if-no-files-found: error

- name: Set version
if: ${{ github.ref == 'refs/heads/main' }}
# Fetches current version from registry and uses prerelease to bump it
run: |
npm version --no-git-tag-version $(npm view @bitwarden/sdk-internal@latest version)
npm version --no-git-tag-version prerelease
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
working-directory: languages/js/sdk-internal

- name: Publish NPM
if: ${{ github.ref == 'refs/heads/main' }}
run: npm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
working-directory: languages/js/sdk-internal
Comment on lines +71 to +76
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should split the build and publish workflows. If it's needed to publish it on every push to main, I suggest triggering the publishing workflow here. An example of that can be found in the build-swift.yml workflow:

- name: Trigger Swift release
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
github-token: ${{ steps.retrieve-secret-pat.outputs.github-pat-bitwarden-devops-bot-repo-scope }}
script: |
await github.rest.actions.createWorkflowDispatch({
owner: 'bitwarden',
repo: 'sdk',
workflow_id: 'release-swift.yml',
ref: 'main',
inputs: {
'build-run-id': '${{ github.run_id }}',
'pre-release': 'true'
}
})

BTW is it released to npmjs.com or to github packages?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently gh packages, but we will probably change it to npmjs.

4 changes: 4 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
target
languages/*
!languages/js
languages/js/*
!languages/js/sdk-internal
languages/js/sdk-internal/bitwarden_wasm_internal_bg.wasm.js
schemas
/crates/bitwarden-napi/src-ts/bitwarden_client/schemas.ts
about.hbs
Expand Down
51 changes: 51 additions & 0 deletions Cargo.lock

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

5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ bitwarden-send = { path = "crates/bitwarden-send", version = "=1.0.0" }
bitwarden-sm = { path = "crates/bitwarden-sm", version = "=1.0.0" }
bitwarden-vault = { path = "crates/bitwarden-vault", version = "=1.0.0" }

wasm-bindgen = { version = ">=0.2.91, <0.3", features = ["serde-serialize"] }
tsify-next = { version = ">=0.5.4, <0.6", features = [
"js",
], default-features = false }

[workspace.lints.clippy]
unused_async = "deny"
unwrap_used = "deny"
Expand Down
3 changes: 3 additions & 0 deletions crates/bitwarden-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ no-memory-hardening = [
] # Disable memory hardening features
uniffi = ["bitwarden-crypto/uniffi", "dep:uniffi"] # Uniffi bindings
secrets = [] # Secrets manager API
wasm = ["dep:wasm-bindgen", "dep:tsify-next"] # WASM support

[dependencies]
base64 = ">=0.22.1, <0.23"
Expand Down Expand Up @@ -51,8 +52,10 @@ thiserror = ">=1.0.40, <2.0"
uniffi = { version = "=0.28.1", optional = true, features = ["tokio"] }
uuid = { version = ">=1.3.3, <2.0", features = ["serde"] }
validator = { version = "0.18.1", features = ["derive"] }
wasm-bindgen = { workspace = true, optional = true }
zeroize = { version = ">=1.7.0, <2.0", features = ["derive", "aarch64"] }
zxcvbn = { version = ">=3.0.1, <4.0", optional = true }
tsify-next = { workspace = true, optional = true }

[target.'cfg(not(target_arch="wasm32"))'.dependencies]
# By default, we use rustls as the TLS stack and rust-platform-verifier to support user-installed root certificates
Expand Down
10 changes: 10 additions & 0 deletions crates/bitwarden-core/src/client/client_settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@
#[derive(Serialize, Deserialize, Debug, JsonSchema)]
#[serde(default, rename_all = "camelCase", deny_unknown_fields)]
#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
#[cfg_attr(
feature = "wasm",
derive(tsify_next::Tsify),

Check warning on line 24 in crates/bitwarden-core/src/client/client_settings.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-core/src/client/client_settings.rs#L24

Added line #L24 was not covered by tests
tsify(into_wasm_abi, from_wasm_abi)
)]
pub struct ClientSettings {
/// The identity url of the targeted Bitwarden instance. Defaults to `https://identity.bitwarden.com`
pub identity_url: String,
Expand All @@ -44,6 +49,11 @@
#[allow(non_camel_case_types)]
#[derive(Serialize, Deserialize, Copy, Clone, Debug, JsonSchema)]
#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
#[cfg_attr(
feature = "wasm",
derive(tsify_next::Tsify),

Check warning on line 54 in crates/bitwarden-core/src/client/client_settings.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-core/src/client/client_settings.rs#L54

Added line #L54 was not covered by tests
tsify(into_wasm_abi, from_wasm_abi)
)]
pub enum DeviceType {
Android = 0,
iOS = 1,
Expand Down
28 changes: 28 additions & 0 deletions crates/bitwarden-wasm-internal/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
[package]
name = "bitwarden-wasm-internal"
version = "0.1.0"
publish = false

authors.workspace = true
edition.workspace = true
rust-version.workspace = true
homepage.workspace = true
repository.workspace = true
license-file.workspace = true
keywords.workspace = true

[lib]
crate-type = ["cdylib"]

[dependencies]
bitwarden = { workspace = true, features = ["internal", "wasm"] }
console_error_panic_hook = "0.1.7"
console_log = { version = "1.0.0", features = ["color"] }
js-sys = "0.3.68"
log = "0.4.20"
serde_json = ">=1.0.96, <2.0"
wasm-bindgen = { version = "0.2.91", features = ["serde-serialize"] }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: should this use the workspace version?

wasm-bindgen = { workspace = true }

I haven't seen this syntax before, but I saw that you did this in crates/bitwarden-core/Cargo.toml

wasm-bindgen-futures = "0.4.41"

[lints]
workspace = true
25 changes: 25 additions & 0 deletions crates/bitwarden-wasm-internal/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# bitwarden-wasm-internal

**Note:** This is only for internal use. Bitwarden will not provide any support for this crate.

Requirements:

- `wasm32-unknown-unknown` rust target.
- `wasm-bindgen-cli` installed.
- `binaryen` installed for `wasm-opt` and `wasm2js`.

```bash
rustup target add wasm32-unknown-unknown
cargo install -f wasm-bindgen-cli
brew install binaryen
```

#### Build

```bash
# dev
./build.sh

# release
./build.sh -r
```
26 changes: 26 additions & 0 deletions crates/bitwarden-wasm-internal/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Move to the root of the repository
cd "$(dirname "$0")"
cd ../../

if [ "$1" != "-r" ]; then
# Dev
cargo build -p bitwarden-wasm-internal --target wasm32-unknown-unknown
wasm-bindgen --target bundler --out-dir languages/js/sdk-internal ./target/wasm32-unknown-unknown/debug/bitwarden_wasm_internal.wasm
wasm-bindgen --target nodejs --out-dir languages/js/sdk-internal/node ./target/wasm32-unknown-unknown/debug/bitwarden_wasm_internal.wasm
else
# Release
cargo build -p bitwarden-wasm-internal --target wasm32-unknown-unknown --release
wasm-bindgen --target bundler --out-dir languages/js/sdk-internal ./target/wasm32-unknown-unknown/release/bitwarden_wasm_internal.wasm
wasm-bindgen --target nodejs --out-dir languages/js/sdk-internal/node ./target/wasm32-unknown-unknown/release/bitwarden_wasm_internal.wasm
fi

# Format
npx prettier --write ./languages/js/sdk-internal

# Optimize size
wasm-opt -Os ./languages/js/sdk-internal/bitwarden_wasm_internal_bg.wasm -o ./languages/js/sdk-internal/bitwarden_wasm_internal_bg.wasm
wasm-opt -Os ./languages/js/sdk-internal/node/bitwarden_wasm_internal_bg.wasm -o ./languages/js/sdk-internal/node/bitwarden_wasm_internal_bg.wasm

# Transpile to JS
wasm2js ./languages/js/sdk-internal/bitwarden_wasm_internal_bg.wasm -o ./languages/js/sdk-internal/bitwarden_wasm_internal_bg.wasm.js
npx terser ./languages/js/sdk-internal/bitwarden_wasm_internal_bg.wasm.js -o ./languages/js/sdk-internal/bitwarden_wasm_internal_bg.wasm.js
57 changes: 57 additions & 0 deletions crates/bitwarden-wasm-internal/src/client.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
extern crate console_error_panic_hook;
use std::rc::Rc;

use bitwarden::{Client, ClientSettings};
use log::{set_max_level, Level};
use wasm_bindgen::prelude::*;

#[wasm_bindgen]

Check warning on line 8 in crates/bitwarden-wasm-internal/src/client.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-wasm-internal/src/client.rs#L8

Added line #L8 was not covered by tests
pub enum LogLevel {
Trace,
Debug,
Info,
Warn,
Error,
}

fn convert_level(level: LogLevel) -> Level {
match level {
LogLevel::Trace => Level::Trace,
LogLevel::Debug => Level::Debug,
LogLevel::Info => Level::Info,
LogLevel::Warn => Level::Warn,
LogLevel::Error => Level::Error,

Check warning on line 23 in crates/bitwarden-wasm-internal/src/client.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-wasm-internal/src/client.rs#L17-L23

Added lines #L17 - L23 were not covered by tests
}
}

Check warning on line 25 in crates/bitwarden-wasm-internal/src/client.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-wasm-internal/src/client.rs#L25

Added line #L25 was not covered by tests

// Rc<...> is to avoid needing to take ownership of the Client during our async run_command
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question/issue?: We don't have a run_command anymore?

// function https://github.com/rustwasm/wasm-bindgen/issues/2195#issuecomment-799588401
#[wasm_bindgen]

Check warning on line 29 in crates/bitwarden-wasm-internal/src/client.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-wasm-internal/src/client.rs#L29

Added line #L29 was not covered by tests
pub struct BitwardenClient(Rc<Client>);

#[wasm_bindgen]

Check warning on line 32 in crates/bitwarden-wasm-internal/src/client.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-wasm-internal/src/client.rs#L32

Added line #L32 was not covered by tests
impl BitwardenClient {
#[wasm_bindgen(constructor)]
pub fn new(settings: Option<ClientSettings>, log_level: Option<LogLevel>) -> Self {
console_error_panic_hook::set_once();
let log_level = convert_level(log_level.unwrap_or(LogLevel::Info));
if let Err(_e) = console_log::init_with_level(log_level) {
set_max_level(log_level.to_level_filter())
}

Check warning on line 40 in crates/bitwarden-wasm-internal/src/client.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-wasm-internal/src/client.rs#L35-L40

Added lines #L35 - L40 were not covered by tests

Self(Rc::new(Client::new(settings)))
}

Check warning on line 43 in crates/bitwarden-wasm-internal/src/client.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-wasm-internal/src/client.rs#L42-L43

Added lines #L42 - L43 were not covered by tests

/// Test method, echoes back the input
pub fn echo(&self, msg: String) -> String {
msg
}

Check warning on line 48 in crates/bitwarden-wasm-internal/src/client.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-wasm-internal/src/client.rs#L46-L48

Added lines #L46 - L48 were not covered by tests

/// Test method, calls http endpoint
pub async fn http_get(&self, url: String) -> Result<String, String> {
let client = self.0.internal.get_http_client();
let res = client.get(&url).send().await.map_err(|e| e.to_string())?;

Check warning on line 53 in crates/bitwarden-wasm-internal/src/client.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-wasm-internal/src/client.rs#L51-L53

Added lines #L51 - L53 were not covered by tests

res.text().await.map_err(|e| e.to_string())
}

Check warning on line 56 in crates/bitwarden-wasm-internal/src/client.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-wasm-internal/src/client.rs#L55-L56

Added lines #L55 - L56 were not covered by tests
}
1 change: 1 addition & 0 deletions crates/bitwarden-wasm-internal/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mod client;
7 changes: 6 additions & 1 deletion crates/bitwarden/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,12 @@ uniffi = [
"bitwarden-send/uniffi",
"bitwarden-vault/uniffi",
] # Uniffi bindings
secrets = ["bitwarden-core/secrets", "dep:bitwarden-sm", "dep:bitwarden-generators"] # Secrets manager API
secrets = [
"bitwarden-core/secrets",
"dep:bitwarden-sm",
"dep:bitwarden-generators",
] # Secrets manager API
wasm = ["bitwarden-core/wasm"] # WASM support

[dependencies]
bitwarden-api-api = { workspace = true }
Expand Down
6 changes: 6 additions & 0 deletions languages/js/sdk-internal/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
bitwarden_wasm_internal_bg.js
bitwarden_wasm_internal_bg.wasm
bitwarden_wasm_internal_bg.wasm.d.ts
bitwarden_wasm_internal_bg.wasm.js
bitwarden_wasm_internal.d.ts
bitwarden_wasm_internal.js
8 changes: 8 additions & 0 deletions languages/js/sdk-internal/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { __wbg_set_wasm } from "./bitwarden_wasm_internal_bg.js";

// In order to support a fallback strategy for web we need to conditionally load the wasm file
export function init(wasm) {
__wbg_set_wasm(wasm);
}

export * from "./bitwarden_wasm_internal_bg.js";
Loading
Loading