Skip to content
API reference

app-storage

Import
import * as api from "@fungi.computer/oyster/app-storage";
Kind Export Description
type alias AppStorageBinding The App storage handle in env.APP_STORAGE.
type alias AppStorageWriter Trusted backend writer: owners may also edit the Team layer; lifecycle has no member.
type alias AppStorageAdmission Trusted live App admission, never supplied by the App or an HTTP body.
type alias AppStorageInstallationAdmission Trusted installation lifecycle admission, with no member identity or private layer.
constant appStorageSchemaStatements SQLite tables, indexes and initial revision state used by the App storage owner.
function appStorageWritable() Whether writer may mutate scope; anything else is owner_required.
function purgeAppStorageInCommit() Called only inside the installation owner’s delete transaction.
function purgeAppMemberStorageInCommit() Called only inside the membership owner’s removal transaction.
function createAppStorage() One SQLite owner for scoped App values; its views bind the admitted member.

AppStorageBindingtype alias

Section titled “AppStorageBinding”
Signature
type AppStorageBinding = Readonly<{
read: Promise<
AppStorageResult<{
value: Schema.Codec<Schema.Json, Schema.Json, never, never>;
source: Schema.Literals<readonly ["member", "team", "none"]>;
team: Schema.NullOr<
Schema.Struct<{
value: Schema.Codec<Schema.Json, Schema.Json, never, never>;
revision: Schema.Int;
}>
>;
member: Schema.NullOr<
Schema.Struct<{
value: Schema.Codec<Schema.Json, Schema.Json, never, never>;
revision: Schema.Int;
}>
>;
canWriteTeam: Schema.Boolean;
}>
>;
write: Promise<
AppStorageResult<{
revision: number;
}>
>;
reset: Promise<
AppStorageResult<{
revision: number;
}>
>;
}>;

The App storage handle in env.APP_STORAGE.


AppStorageWritertype alias

Section titled “AppStorageWriter”
Signature
type AppStorageWriter =
| Readonly<{
kind: "member";
memberId: string;
isOwner: boolean;
}>
| Readonly<{
kind: "lifecycle";
handler: string;
}>;

Trusted backend writer: owners may also edit the Team layer; lifecycle has no member.


AppStorageAdmissiontype alias

Section titled “AppStorageAdmission”
Signature
type AppStorageAdmission = Readonly<{
address: string;
appId: string;
memberId: string;
membershipVersion: number;
isOwner: boolean;
keys: readonly AppStorageKey[];
assertCurrent: () => void;
}>;

Trusted live App admission, never supplied by the App or an HTTP body.


AppStorageInstallationAdmissiontype alias

Section titled “AppStorageInstallationAdmission”
Signature
type AppStorageInstallationAdmission = Pick<
AppStorageAdmission,
"address" | "appId" | "keys" | "assertCurrent"
>;

Trusted installation lifecycle admission, with no member identity or private layer.

appStorageSchemaStatementsconstant

Section titled “appStorageSchemaStatements”
Signature
const appStorageSchemaStatements: readonly [
"CREATE TABLE IF NOT EXISTS hub_app_storage (\n address TEXT NOT NULL, app_id TEXT NOT NULL, key TEXT NOT NULL,\n scope TEXT NOT NULL CHECK(scope IN ('team','member')), member_id TEXT NOT NULL, membership_version INTEGER NOT NULL,\n value TEXT NOT NULL, revision INTEGER NOT NULL, bytes INTEGER NOT NULL,\n PRIMARY KEY(address,app_id,key,scope,member_id,membership_version),\n CHECK((scope='team' AND member_id='' AND membership_version=0) OR (scope='member' AND member_id<>'' AND membership_version>0))) STRICT",
"CREATE INDEX IF NOT EXISTS hub_app_storage_member ON hub_app_storage(member_id) WHERE scope='member'",
"CREATE TABLE IF NOT EXISTS hub_app_storage_clock (id INTEGER PRIMARY KEY CHECK(id=1), revision INTEGER NOT NULL) STRICT",
"INSERT OR IGNORE INTO hub_app_storage_clock VALUES(1,0)",
"CREATE TABLE IF NOT EXISTS hub_app_storage_writes (address TEXT NOT NULL, member_id TEXT NOT NULL, membership_version INTEGER NOT NULL, started_at INTEGER NOT NULL, count INTEGER NOT NULL, PRIMARY KEY(address,member_id,membership_version)) STRICT",
];

SQLite tables, indexes and initial revision state used by the App storage owner.

appStorageWritable()function

Section titled “appStorageWritable()”
Signature
function appStorageWritable(writer, scope): boolean;

Whether writer may mutate scope; anything else is owner_required.

Parameter Type
writer AppStorageWriter
scope "member" | "team"

boolean


purgeAppStorageInCommit()function

Section titled “purgeAppStorageInCommit()”
Signature
function purgeAppStorageInCommit(sql, address): void;

Called only inside the installation owner’s delete transaction.

Parameter Type
sql Readonly<{ exec: (statement, …bindings) => WatchdogSqliteCursor; }>
address string

void


purgeAppMemberStorageInCommit()function

Section titled “purgeAppMemberStorageInCommit()”
Signature
function purgeAppMemberStorageInCommit(sql, memberId, throughVersion): void;

Called only inside the membership owner’s removal transaction.

Parameter Type
sql Readonly<{ exec: (statement, …bindings) => WatchdogSqliteCursor; }>
memberId string
throughVersion number

void


createAppStorage()function

Section titled “createAppStorage()”
Signature
function createAppStorage(options): object;

One SQLite owner for scoped App values; its views bind the admitted member.

Parameter Type Description
options { sql: Readonly<{ exec: (statement, …bindings) => WatchdogSqliteCursor; }>; now?: () => number; commit: <A>(body) => Effect<A, Error>; } -
options.sql Readonly<{ exec: (statement, …bindings) => WatchdogSqliteCursor; }> The SQLite connection shared with installation and membership changes.
options.now? () => number Millisecond clock used for the existing per-principal write-rate limit.
options.commit <A>(body) => Effect<A, Error> Commit the supplied mutation atomically before publishing its invalidation.
Name Type Description
purgeInstallation() (address) => void Remove an installation’s values and write counters inside its delete transaction.
purgeMember() (memberId, throughVersion) => void Remove a member’s private values and counters through the revoked membership version.
openInstallation() (authorize) => object Bind a lifecycle view to fresh installation admission; only declared team layers are accessible.
open() (authorize) => object Bind a member view to live admission, declared keys and the current membership version.