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
DBOPFSinstance.
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
| Property | Type | Behavior |
|---|---|---|
ready | boolean | Becomes true after the app directory and default tables open. |
readyPromise | Promise<void> | Persistent initialization promise; recommended for race-safe startup. |
applicationId | string | Resolved canonical application owner. |
storagePath | string | App-relative path such as apps/my-app. |
tables | object | Values cached in JavaScript memory for this loaded page only. Other tabs do not refresh it. See Cache and fresh reads. |
tables = update | setter | Calls set(update.tableName,update.fileName,update.value) without exposing the promise. Prefer await set() when failures matter. |
var db=window.dbopfs;
await db.readyPromise;
console.log({
ready:db.ready,
applicationId:db.applicationId,
storagePath:db.storagePath,
touchedValues:db.tables
});
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.
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 byget().- Parsing
.jsonis parsed;.jsonl/.ndjsonbecomes an array; other names return text.
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.
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 returnnull.- force
- When true, bypasses the page-local cache and reads OPFS again.
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.
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}}.
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.
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[]>.
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.
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>.
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>.
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.
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>.
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}>.
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>.
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[]>.
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[]>.
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>.
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)); // 0deleteTable(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
memoriesalias points to physicalmemory; preferclear('memories')for that default 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.
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.
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
FileorBlobcreated by DBOPFS backup. - Returns
Promise<void>.- Merge
- Existing matching keys are overwritten; unrelated records remain. Restore is not atomic.
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 name | Meaning |
|---|---|
APP_DATA_SCOPE_REQUIRED | No explicit, declared, or native-bound application ID exists. |
APP_DATA_SCOPE_INVALID | An application ID violates the canonical pattern or 64-character limit. |
APP_DATA_SCOPE_MISMATCH | Two identity sources disagree. |
APP_DATA_STORAGE_UNAVAILABLE | The browser cannot expose an OPFS root/directory handle. |
NotFoundError | A raw file/table operation requested an entry that does not exist. get()null. |
NotSupportedError | The 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.