Phase 1 of pulseflare migration: decouple core logic from bun:sqlite.
- Add PulseDatabase/PulseStatement interfaces in database.ts
- Replace 'import { Database } from bun:sqlite' with PulseDatabase alias
in defs.ts, projection-engine.ts, guard-projection.ts
- Update PulseStore.getDatabase() and ScopedStore.scopeDatabase() return
types to PulseDatabase
- store.ts retains bun:sqlite as concrete implementation
- Export PulseDatabase/PulseStatement from package index
- All existing tests pass unchanged
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Abstract database interface for Pulse.
|
||||
*
|
||||
* Decouples core logic from bun:sqlite so alternative backends
|
||||
* (e.g. Cloudflare D1) can provide their own implementation.
|
||||
*/
|
||||
|
||||
export interface PulseStatement {
|
||||
get(...params: any[]): any;
|
||||
all(...params: any[]): any[];
|
||||
run(...params: any[]): { changes: number; lastInsertRowid: number | bigint };
|
||||
}
|
||||
|
||||
export interface PulseDatabase {
|
||||
exec(sql: string): void;
|
||||
prepare(sql: string): PulseStatement;
|
||||
run(sql: string, ...params: any[]): void;
|
||||
transaction<T>(fn: () => T): (...args: any[]) => T;
|
||||
close(): void;
|
||||
readonly inTransaction: boolean;
|
||||
}
|
||||
Vendored
+1
-1
@@ -4,7 +4,7 @@
|
||||
* Append-only definition tables for objects, events, and projections.
|
||||
* Content-addressed versioning with code_rev binding.
|
||||
*/
|
||||
import type { Database } from 'bun:sqlite';
|
||||
import type { PulseDatabase as Database } from './database.js';
|
||||
export interface ObjectDef {
|
||||
name: string;
|
||||
codeRev: string;
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
* Content-addressed versioning with code_rev binding.
|
||||
*/
|
||||
|
||||
import type { Database } from 'bun:sqlite';
|
||||
import { createHash } from 'node:crypto';
|
||||
import jsonata from 'jsonata';
|
||||
import type { PulseDatabase as Database } from './database.js';
|
||||
|
||||
// ── Types ──────────────────────────────────────────────────────
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Core logic delegated to guard-core.ts (pure, portable).
|
||||
*/
|
||||
|
||||
import type { Database } from 'bun:sqlite';
|
||||
import type { PulseDatabase as Database } from './database.js';
|
||||
import {
|
||||
checkGuardsCore,
|
||||
clearGuardExpressionCache as clearCoreCache,
|
||||
|
||||
@@ -899,6 +899,10 @@ export function createRule<S, E, T>(
|
||||
return (prev, curr, inner) => logic(accessor(prev), accessor(curr), inner);
|
||||
}
|
||||
|
||||
// ── Database Abstraction ────────────────────────────────────────
|
||||
|
||||
export type { PulseDatabase, PulseStatement } from './database.js';
|
||||
|
||||
// ── Storage ────────────────────────────────────────────────────
|
||||
|
||||
export {
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
* Incremental fold engine for projections with JSONata expressions.
|
||||
* Projections are first-class citizens with their own state table.
|
||||
*/
|
||||
import type { Database } from 'bun:sqlite';
|
||||
import type { PulseDatabase as Database } from './database.js';
|
||||
/** Clear the compiled expression cache (useful for testing). */
|
||||
export declare function clearExpressionCache(): void;
|
||||
export interface ProjectionState {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* Projections are first-class citizens with their own state table.
|
||||
*/
|
||||
|
||||
import type { Database } from 'bun:sqlite';
|
||||
import type { PulseDatabase as Database } from './database.js';
|
||||
import jsonata, { type Expression } from 'jsonata';
|
||||
import { getProjectionDef } from './defs.js';
|
||||
|
||||
|
||||
Vendored
+3
-2
@@ -5,6 +5,7 @@
|
||||
* content-addressed object store (CAS) on disk via SHA-256 hashes.
|
||||
*/
|
||||
import { Database } from 'bun:sqlite';
|
||||
import type { PulseDatabase } from './database.js';
|
||||
export interface EventRecord {
|
||||
id: number;
|
||||
occurredAt: number;
|
||||
@@ -99,8 +100,8 @@ export interface CreateScopedStoreOptions {
|
||||
export interface ScopedStore {
|
||||
scope(name: string): PulseStore;
|
||||
listScopes(): string[];
|
||||
/** Get underlying Database for scope (used by projection engine) */
|
||||
scopeDatabase(name: string): Database;
|
||||
/** Get underlying database for scope (used by projection engine) */
|
||||
scopeDatabase(name: string): PulseDatabase;
|
||||
putObject(data: unknown): Promise<string>;
|
||||
getObject(hash: string): Promise<unknown | null>;
|
||||
close(): Promise<void>;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
import { Database } from 'bun:sqlite';
|
||||
import type { PulseDatabase } from './database.js';
|
||||
import { createHash } from 'node:crypto';
|
||||
import {
|
||||
existsSync,
|
||||
@@ -108,8 +109,8 @@ export interface PulseStore {
|
||||
/** Read data from CAS store by hash. Returns null if not found. */
|
||||
getObject(hash: string): Promise<unknown | null>;
|
||||
|
||||
/** Get the underlying bun:sqlite Database handle (for guard projections etc.) */
|
||||
getDatabase(): Database;
|
||||
/** Get the underlying database handle (for guard projections etc.) */
|
||||
getDatabase(): PulseDatabase;
|
||||
|
||||
/** Close the database */
|
||||
close(): Promise<void>;
|
||||
@@ -544,8 +545,8 @@ export interface ScopedStore {
|
||||
scope(name: string): PulseStore;
|
||||
listScopes(): string[];
|
||||
|
||||
/** Get underlying Database for scope (used by projection engine) */
|
||||
scopeDatabase(name: string): Database;
|
||||
/** Get underlying database for scope (used by projection engine) */
|
||||
scopeDatabase(name: string): PulseDatabase;
|
||||
|
||||
putObject(data: unknown): Promise<string>;
|
||||
getObject(hash: string): Promise<unknown | null>;
|
||||
|
||||
Reference in New Issue
Block a user