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.