AI Decision System
Replayable, offline-verifiable records for AI-assisted go/no-go decisions: experiment promotions, typed model answers and human-approved actions.
翻译准备中
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证Save-game persistence for Capacitor games on SQLite everywhere: sql.js and IndexedDB on the web, native SQLite or SQLCipher on iOS and Android.
翻译准备中
取自仓库 README
正在加载完整 README。 以下为已保存的摘录。
Save-game persistence for Capacitor games. One API
stores saves in SQLite on every platform: jeep-sqlite
over sql.js and IndexedDB on the web, and native SQLite
(optionally SQLCipher-encrypted) on iOS and Android.查看完整 README ↗Save-game persistence for Capacitor games. One API stores saves in SQLite on every platform: jeep-sqlite over sql.js and IndexedDB on the web, and native SQLite (optionally SQLCipher-encrypted) on iOS and Android.
@capacitor-community/sqlite, opened
lazily and isolating corrupt rows instead of failing the whole list.N → N+1 steps that are validated, frozen
and walked to the exact target version, so old saves load safely.@capacitor/preferences for small
settings.Documentation · API · Architecture · Changelog
npm install persistence-save @capacitor/core @capacitor-community/sqlite @capacitor/preferences
The three Capacitor packages are peer dependencies of the root entry. The 0.2
line is verified against @capacitor/core 8.5, @capacitor-community/sqlite
8.1 and @capacitor/preferences 8.0. Node.js 22, 24 and 26 are supported.
The autosave scheduler and the snapshot-migration walker have their own
entries, persistence-save/autosave and persistence-save/migrations, which
load no Capacitor code. The Capacitor peers are optional, so a game without
Capacitor installs persistence-save alone and imports those. A game on
another Capacitor major can import them too, but an optional peer is still
checked when it is present: the install reports the peers unmet (a warning by
default, an error under strict-peer-dependencies). The root entry needs the
8.x peers.
On the web, copy both WebAssembly assets into the directory you pass as
wasmAssetsPath (for example with your bundler's static-copy step):
node_modules/persistence-save/dist/assets/sql-wasm.wasm
node_modules/persistence-save/dist/assets/sql-wasm-browser.wasm
They are also exported as persistence-save/assets/sql-wasm.wasm and
persistence-save/assets/sql-wasm-browser.wasm.
import { createPersistence } from 'persistence-save';
interface State {
name: string;
gold: number;
}
interface Snapshot extends State {
version: number;
}
const saves = createPersistence<State, Snapshot>({
dbName: 'com.example.game_v1',
snapshotVersion: 2,
serialize: (state) => ({ version: 2, ...state }),
deserialize: ({ name, gold }) => ({ name, gold }),
migrations: {
1: (old) => ({ ...old, version: 2, gold: old.gold ?? 0 }),
},
});
await saves.save('Slot 1', { name: 'Player One', gold: 7 });
const [latest] = await saves.list(); // newest first; corrupt rows are isolated, not thrown
const record = latest ? await saves.load(latest.id) : null;
console.log(record?.snapshot.gold); // 7
Every source version, target version and migration output is a safe integer.
Each migration receives a deeply frozen clone and is a pure N → N+1 step.
Mutation attempts, null or non-object output, skips, overshoots, fractions, and
a walk that does not end exactly at the target are rejected as typed version
errors. Reading an older save migrates it in memory without rewriting the stored
row; only an explicit save() writes the current format.
serialize() is validated before SQLite is opened: it must return a non-array
object whose version exactly equals snapshotVersion. Snapshot size caps are
measured in UTF-8 bytes on both read and write.
Games with their own SQLite tables can pass an idempotent
initializeSchema(connection) callback and use withConnection() and flush()
for their own statements. This keeps one connection manager and one web-store
flush path. encryptionKeyPreference keeps an existing native SQLCipher key
name when you adopt the package in a game that already encrypts its database.
Preferences store strings, so serialize structured values explicitly, and always use a stable reverse-domain namespace:
import { createPreferencesKv } from 'persistence-save';
const settings = createPreferencesKv('com.example.game');
await settings.set('audio.muted', 'false');
import { createAutoSaveScheduler } from 'persistence-save';
const autosave = createAutoSaveScheduler({
provider: () => (inMenu ? null : currentState()), // null skips the write
save: (state) => saves.save('AutoSave', state),
debounceMs: 400,
});
autosave.schedule(); // after a mutation; bursts coalesce into one write
autosave.scheduleThrottled('player.health', 2_000); // per-frame callers
addEventListener('pagehide', () => void autosave.flush()); // always saves
await autosave.flushPending(); // wait for a queued save; writes nothing if none is
autosave.pending; // true while a debounced or throttled save is queued
The scheduler takes any save, so it works over your own storage too, from
the Capacitor-free entry:
import { createAutoSaveScheduler } from 'persistence-save/autosave';
import { migrateSnapshot } from 'persistence-save/migrations';
See the API reference for every option.
mise install # or: npm install --global corepack && corepack enable
pnpm install
pnpm verify
pnpm verify runs Biome, markdownlint, strict TypeScript, the tests with
coverage, the ESM, CommonJS and type builds, publint, Are The Types Wrong, and
a packed-consumer proof. That proof packs the package, installs the tarball with
the exact Capacitor peers into a clean project with an empty home directory and
only the public registry, then runs the ESM and CommonJS entry points,
typechecks a separately written consumer, and compiles both WebAssembly assets.
pnpm test:web-cold-reload separately packs the built package, starts a clean
Vite consumer and uses a headed, muted Chromium session to prove that a flushed
save has IndexedDB bytes and reopens in a freshly navigated JavaScript realm.
Set PERSISTENCE_SAVE_CONSUMER_SOURCE=persistence-save@<version> to run the same
proof against a published version.
See CONTRIBUTING.md. Releases are automated with Release Please and published to npm with provenance.
MIT. The bundled sql.js WebAssembly binaries are MIT-licensed by the sql.js authors; see THIRD_PARTY_NOTICES.md.