Runtime contract

API reference.

The default export is a browser class whose first instance becomes window.dbopfs. Importing the module creates that singleton automatically.

Default export

Singleton and constructor

Every example on this page is browser-console ready after completing Get started. Each method example obtains window.dbopfs and waits for readyPromise, so its prerequisites are visible in the copied code.

new DBOPFS(options={})

Creates the database when window.dbopfs is not already truthy. Otherwise, the constructor returns that existing value. A standard module import creates the singleton before caller code resumes, so browser applications normally use window.dbopfs rather than constructing another instance.

options.storage
Storage-manager adapter; defaults to navigator.storage.
options.applicationId
Explicit ID for adapters and tests. Browser pages should normally declare metadata instead.
options.documentObject
Document-like identity source; defaults to document.
options.arcane
Optional native Arcane bridge; defaults to globalThis.Arcane.
Returns
The new or existing DBOPFS instance.
Automatic singleton
var module=await import(
    '/vendor/dbopfs/arcane/modules/DBOPFS.js'
);
var DBOPFS=module.default;

await window.dbopfs.readyPromise;
console.log(window.dbopfs instanceof DBOPFS);
console.log(new DBOPFS()===window.dbopfs);

Browser module only. The module reads navigator at top level and relies on window, document, Worker APIs, and OPFS. It is not a Node.js database.

Instance state

Properties

PropertyTypeBehavior
readybooleanBecomes true after the app directory and default tables open.
readyPromisePromise<void>Persistent initialization promise; recommended for race-safe startup.
applicationIdstringResolved canonical application owner.
storagePathstringApp-relative path such as apps/my-app.
tablesobjectValues cached in JavaScript memory for this loaded page only. Other tabs do not refresh it. See Cache and fresh reads.
tables = updatesetterCalls set(update.tableName,update.fileName,update.value) without exposing the promise. Prefer await set() when failures matter.
Read every property
var db=window.dbopfs;
await db.readyPromise;

console.log({
    ready:db.ready,
    applicationId:db.applicationId,
    storagePath:db.storagePath,
    touchedValues:db.tables
});
Prefer set() over the tables setter
var db=window.dbopfs;
await db.readyPromise;

// Awaitable and recommended:
await db.set('notes','draft.txt','Hello');

// Starts a write but exposes no Promise:
db.tables={
    tableName:'notes',
    fileName:'background-draft.txt',
    value:'Best-effort write'
};

The tables setter is fire-and-forget. Even await (db.tables=update) does not wait for its internal write. Use await db.set() when completion or failure matters.

Lifecycle

Readiness event

dbopfs-ready

Dispatched on window after the database has opened and default directories exist.

detail.dbopfs
The singleton instance.
detail.applicationId
The resolved canonical app ID.
detail.storagePath
The app-relative OPFS directory.
Event detail
function reportScope(source){
    console.log(source.applicationId,source.storagePath);
}

if(window.dbopfs?.ready){
    reportScope(window.dbopfs);
}else{
    window.addEventListener(
        'dbopfs-ready',
        ({detail})=>reportScope(detail),
        {once:true}
    );
}

Parsed values

Record methods

set(tableName, fileName, value={}, append=false)

Asynchronously serializes non-string values, writes one file, refreshes its cached value, and serializes concurrent writes to the same table/key. See Async patterns for safe sequencing and parallel work.

Returns
Promise<any> with the value as read back by get().
Parsing
.json is parsed; .jsonl/.ndjson becomes an array; other names return text.
Write JSON and use the read-back value
var db=window.dbopfs;
await db.readyPromise;

var saved=await db.set(
    'users',
    'alex.json',
    {name:'Alex',active:true}
);
console.log(saved);

setMany(tableName, items)

Writes every own enumerable entry in items, using each property name as a filename.

Returns
Promise<PromiseSettledResult[]> in object-entry order.
Write a batch and inspect every result
var db=window.dbopfs;
await db.readyPromise;

var items={
    'appearance.json':{mode:'dark'},
    'locale.json':{language:'en-US'}
};
var results=await db.setMany('settings',items);

Object.keys(items).forEach((name,index)=>{
    console.log(name,results[index]);
});

get(tableName, fileName, force=false)

Asynchronously returns a cached value unless force is true or the key has no cached truthy value. Reads and parses the file when required.

Returns
Promise<any|null>. Missing files return null.
force
When true, bypasses the page-local cache and reads OPFS again.
Compare cached and fresh reads
var db=window.dbopfs;
await db.readyPromise;

var cached=await db.get('users','alex.json');
var fresh=await db.get('users','alex.json',true);
console.log({cached,fresh});

getMany(tableName, fileNames)

Reads each requested filename with get().

Returns
Promise<PromiseSettledResult[]> in filename order.
Read several keys
var db=window.dbopfs;
await db.readyPromise;

var names=['appearance.json','locale.json'];
var results=await db.getMany('settings',names);

names.forEach((name,index)=>{
    console.log(name,results[index]);
});

getAll(tableName='')

With a table name, returns every record in that directory. Without one, discovers physical tables and returns a nested object.

Returns
Promise<Object>.
All tables
Shape: {tableName:{fileName:value}}.
Read one table or the app database
var db=window.dbopfs;
await db.readyPromise;

console.log(await db.getAll('notes'));
console.log(await db.getAll());

delete(tableName, fileName)

Removes one cache entry and attempts to remove the matching file. A missing file is treated as success. Other removal errors are logged and suppressed by the preserved runtime.

Returns
Promise<true>. The value means the method completed; it is not independent proof that removal succeeded.
Create and safely delete an example
var db=window.dbopfs;
await db.readyPromise;

var name=`delete-${crypto.randomUUID()}.txt`;
await db.set('api-examples',name,'temporary');
console.log(await db.delete('api-examples',name));

deleteMany(tableName, fileNames)

Deletes the requested keys independently.

Returns
Promise<PromiseSettledResult[]>.
Create and delete an isolated batch
var db=window.dbopfs;
await db.readyPromise;

var prefix=crypto.randomUUID();
var items={
    [`${prefix}-one.txt`]:'one',
    [`${prefix}-two.txt`]:'two'
};
await db.setMany('api-examples',items);

var results=await db.deleteMany(
    'api-examples',
    Object.keys(items)
);
console.log(results);

filterKeyIncludes(tableName, substring='')

Reads records whose filenames contain the exact case-sensitive substring.

Returns
Promise<Object> keyed by filename.
Find matching keys
var db=window.dbopfs;
await db.readyPromise;

var matches=await db.filterKeyIncludes(
    'notes',
    'meeting'
);
console.log(matches);

hasKey(tableName, key)

Checks whether the named file handle exists. The preserved runtime returns false for any caught error, not only a missing key.

Returns
Promise<boolean>.
Check one key
var db=window.dbopfs;
await db.readyPromise;

var exists=await db.hasKey(
    'notes',
    'meeting.json'
);
console.log(exists);

count(tableName)

Counts entries yielded by the table directory.

Returns
Promise<number>.
Count records
var db=window.dbopfs;
await db.readyPromise;

console.log(await db.count('notes'));

Raw bytes and metadata

File methods

writeFile(tableName, fileName, fileData='', append=false)

Writes raw data through createWritable(), or through the co-located worker when the asynchronous writable surface is unavailable. It does not refresh or invalidate parsed entries in the page-local cache.

Returns
Promise<true>.
append
Preserves existing bytes and writes at the current file size.
Write and append raw content
var db=window.dbopfs;
await db.readyPromise;

var name=`raw-${crypto.randomUUID()}.txt`;
var first=new Blob(['first line\n'],{type:'text/plain'});

await db.writeFile('documents',name,first);
await db.writeFile('documents',name,'second line\n',true);
console.log(await db.readFile('documents',name));

readFile(tableName, fileName)

Returns the underlying browser file. The worker fallback reconstructs a File from transferred bytes.

Returns
Promise<File>.
Read a browser File
var db=window.dbopfs;
await db.readyPromise;

var name=`read-${crypto.randomUUID()}.txt`;
await db.writeFile('documents',name,'Hello from OPFS');

var file=await db.readFile('documents',name);
console.log({
    name:file.name,
    size:file.size,
    text:await file.text()
});

getFileMetadata(tableName, fileName)

Reads metadata available through the browser File API. Creation time is not exposed.

Returns
Promise<{lastModified:number|null,size:number|null,type:string}>.
Inspect file metadata
var db=window.dbopfs;
await db.readyPromise;

var name=`metadata-${crypto.randomUUID()}.txt`;
await db.writeFile('documents',name,'metadata example');

var metadata=await db.getFileMetadata('documents',name);
console.log(metadata);

Directories

Table methods

getTableHandle(tableName)

Waits for readiness, returns a registered handle, matches a default alias to its physical handle, or creates the named directory.

Returns
Promise<FileSystemDirectoryHandle>.
Open or create a table directory
var db=window.dbopfs;
await db.readyPromise;

var handle=await db.getTableHandle('projects');
console.log(handle.kind,handle.name);

getTableNames(discover=false)

Returns registered aliases by default. With discover=true, enumerates physical directories and registers newly discovered handles.

Returns
Promise<string[]>.
Compare aliases with physical directories
var db=window.dbopfs;
await db.readyPromise;

console.log(await db.getTableNames());
console.log(await db.getTableNames(true));

getAllKeys(tableName)

Enumerates names in one table.

Returns
Promise<string[]>.
List every key in a table
var db=window.dbopfs;
await db.readyPromise;

console.log(await db.getAllKeys('notes'));

clear(tableName)

Deletes every entry in one table while retaining the directory. Individual deletion failures may be logged and suppressed by the preserved runtime.

Returns
Promise<void>.
Clear only a throwaway example table
var db=window.dbopfs;
await db.readyPromise;

var table=`api-clear-${crypto.randomUUID()}`;
await db.set(table,'temporary.txt','temporary');
await db.clear(table);
console.log(await db.count(table)); // 0

deleteTable(tableName)

Recursively attempts to remove a table and clears its registered cache/handle. Operational errors are logged and suppressed by the preserved runtime.

Returns
Promise<true>. The value means the method completed; it does not independently verify removal.
Literal name
The removal call uses the supplied directory name. The default memories alias points to physical memory; prefer clear('memories') for that default table.
Create and delete an isolated table
var db=window.dbopfs;
await db.readyPromise;

var table=`api-delete-${crypto.randomUUID()}`;
await db.set(table,'temporary.txt','temporary');
console.log(await db.deleteTable(table));

clearAllStorage()

Deletes all entries below the current application directory, resets caches and locks, then recreates the default tables.

Returns
Promise<DBOPFS>.
Scope
Current apps/<application-id> directory only.
Confirm before clearing the whole app database
var db=window.dbopfs;
await db.readyPromise;

if(confirm(`Delete every record in ${db.storagePath}?`)){
    var sameDatabase=await db.clearAllStorage();
    console.log(sameDatabase===db);
}

Destructive: create a backup first. This clears every table in the current application-ID folder.

Portable payload

Backup methods

downloadCompressedPNG(name='DBOPFS-backup')

Discovers current app tables, streams their JSON through CompressionStream('deflate'), stores the byte length and payload in PNG pixel channels, and starts a browser download.

Returns
Promise<void>.
Filename
<name>-YYYY-MM-DD-hh-mm-ss.png.
Start a browser backup download
var db=window.dbopfs;
await db.readyPromise;

await db.downloadCompressedPNG(
    `${db.applicationId}-backup`
);

restoreFromPNG(file)

Decodes a DBOPFS backup, inflates its JSON, and calls setMany() for each table. Individual item failures may be logged while the outer restore still resolves.

file
A File or Blob created by DBOPFS backup.
Returns
Promise<void>.
Merge
Existing matching keys are overwritten; unrelated records remain. Restore is not atomic.
Pick and restore a PNG backup
var db=window.dbopfs;
await db.readyPromise;

var picker=document.createElement('input');
picker.type='file';
picker.accept='image/png';
picker.onchange=async()=>{
    var file=picker.files[0];

    if(file&&confirm(`Merge into ${db.storagePath}?`)){
        await db.restoreFromPNG(file);
        console.log('Restore finished');
    }
};
picker.click();

Value-level backup: the PNG stores JSON values discovered through DBOPFS. It is not a byte-for-byte filesystem image and does not preserve raw binary bytes, MIME metadata, or timestamps.

Failure contract

Errors and limits

Code or nameMeaning
APP_DATA_SCOPE_REQUIREDNo explicit, declared, or native-bound application ID exists.
APP_DATA_SCOPE_INVALIDAn application ID violates the canonical pattern or 64-character limit.
APP_DATA_SCOPE_MISMATCHTwo identity sources disagree.
APP_DATA_STORAGE_UNAVAILABLEThe browser cannot expose an OPFS root/directory handle.
NotFoundErrorA raw file/table operation requested an entry that does not exist. get()null.
NotSupportedErrorThe worker fallback cannot obtain a synchronous OPFS access handle.
  • Quota, eviction, retention, and persistence grants belong to the browser.
  • App folders do not isolate hostile scripts that already share an origin.
  • There is no schema validation, query language, transaction spanning multiple keys, encryption, replication, or synchronization.
  • Batch methods are not atomic. Inspect every result and implement application-specific compensation if partial success is unacceptable.