Opening a Workspace

Workspace.open() in its OpenOptions and positional forms, automatic create-vs-open with folder validation, and the three-tier path resolution (WATIVE_WORKSPACE_PATH, ./.wative2, ~/.wative2).

Workspace.open() is the single entry point for both creating a new workspace and opening an existing one — there is no separate create step. It auto-selects based on what it finds at the target location, resolves a default path when you give none, and returns either an unlocked or a locked workspace depending on whether you pass a password.

quick-start.ts
import { Workspace } from "wative-core";

// Options-object form
const ws = await Workspace.open({ path: "./my-wallet", password: "wsp-pwd" });

OpenOptions object vs positional

There are two co-existing call shapes.

Options object — the recommended form, taking an OpenOptions bag:

options-form.ts
const ws = await Workspace.open({ path: "./my-wallet", password: "wsp-pwd" });
FieldTypeNotes
providerProviderCustom storage backend. Mutually exclusive with path.
pathstringRoot path for the default provider. Mutually exclusive with provider. Omit both for the default location.
passwordstringWorkspace password. Omit to return a locked workspace and call unlock(pwd) later.

Passing both provider and path throws a WativeError with code === "PARAMETER_ERROR".

Positionalopen(providerOrRoot?, password?), where the first argument is a Provider instance, a root-path string, or omitted:

positional-form.ts
const ws = await Workspace.open("./my-wallet", "wsp-pwd");

The backend resolves as:

  • a Provider instance — used as-is, and the caller keeps ownership of it, OR
  • a string root path — wrapped in the default provider for the host, OR
  • omitted — resolved via the three-tier default-path strategy below.

Create-vs-open decision

When a password is supplied, open() inspects the target's structural state before unlocking and picks the safe action:

TargetAction
An existing wative workspaceOpen it and verify the password. A wrong password throws BAD_PASSWORD.
Empty, or does not existCreate a new workspace there.
A non-empty location that is not a wative workspaceRefuse with PARAMETER_ERROR rather than scaffolding a workspace into unrelated data.

That last row is the folder-validation guard: it stops a mistyped path from writing workspace files into a directory that already holds something else.

create-then-open.ts
// First call: directory is empty → creates the workspace.
let ws = await Workspace.open({ path: "./my-wallet", password: "wsp-pwd" });
await ws.lock();

// Second call: same directory is now a workspace → opens it.
ws = await Workspace.open({ path: "./my-wallet", password: "wsp-pwd" });

If the provider is already held by another live Workspace, open() refuses with UNSUPPORTED_OP — two workspaces on one container would overwrite each other's records. Call close() on the first workspace, or construct a separate provider.

Three-tier path resolution

When you call open() with no path and no provider, the default location is resolved on a filesystem host in this order:

WATIVE_WORKSPACE_PATH — if this environment variable is set and non-empty (trimmed), it always wins. A leading ~ / ~/ is expanded by the default provider.
<cwd>/.wative2 — the .wative2 directory under the current working directory, preferred when it already exists and is not a symlink.
<home>/.wative2 — the .wative2 directory under the user's home directory, the last-resort fallback and where a fresh machine lands.

Default-path resolution requires a Node.js runtime — it reads process.env, process.cwd(), and the home directory. In a non-Node runtime you must pass an explicit path or provider; otherwise open() throws PARAMETER_ERROR.

Unlocked vs locked open

Whether a password is present decides what state the returned workspace is in.

locked-open.ts
// No password → a locked workspace; unlock it later.
const ws = await Workspace.open({ path: "./my-wallet" });
ws.locked; // true

await ws.unlock("wsp-pwd");
ws.locked; // false

A no-password open() never hydrates and never inspects the container's contents — it just returns a locked handle. A password, if supplied, must be a non-empty string or open() throws PARAMETER_ERROR. See the Workspace lifecycle for what unlock, lock, and close do next.

Last updated on