@wrongstack/persistence 0.309.1 → 0.310.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/atomic-write.d.ts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +56 -3
- package/dist/sqlite-runtime.d.ts +13 -0
- package/package.json +2 -2
package/dist/atomic-write.d.ts
CHANGED
|
@@ -40,6 +40,7 @@ export declare class PersistenceFsError extends Error {
|
|
|
40
40
|
*/
|
|
41
41
|
export declare function createPersistencePrimitives(options?: PersistencePrimitiveOptions): PersistencePrimitives;
|
|
42
42
|
export declare const atomicWrite: (targetPath: string, content: string | Uint8Array, opts?: AtomicWriteOptions) => Promise<void>;
|
|
43
|
+
export declare const atomicReplaceWithWriter: <T>(targetPath: string, write: (handle: fs.FileHandle) => Promise<T>, opts?: AtomicWriteOptions) => Promise<T>;
|
|
43
44
|
export declare const ensureDir: (dir: string) => Promise<void>;
|
|
44
45
|
export declare const withFileLock: <T>(targetPath: string, fn: () => Promise<T>, opts?: FileLockOptions) => Promise<T>;
|
|
45
46
|
//# sourceMappingURL=atomic-write.d.ts.map
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -80,7 +80,7 @@ function createPersistencePrimitives(options = {}) {
|
|
|
80
80
|
throw error;
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
|
-
async function
|
|
83
|
+
async function atomicReplaceWithWriter2(targetPath, write, opts = {}) {
|
|
84
84
|
await fs.mkdir(path.dirname(targetPath), { recursive: true });
|
|
85
85
|
const tmp = tempPathFor(targetPath);
|
|
86
86
|
try {
|
|
@@ -135,7 +135,9 @@ function createPersistencePrimitives(options = {}) {
|
|
|
135
135
|
await retryAfterBackoff();
|
|
136
136
|
continue;
|
|
137
137
|
}
|
|
138
|
-
if (code !== "EEXIST" && code !== "EPERM")
|
|
138
|
+
if (code !== "EEXIST" && code !== "EPERM" && code !== "EACCES" && code !== "EBUSY") {
|
|
139
|
+
throw error;
|
|
140
|
+
}
|
|
139
141
|
try {
|
|
140
142
|
const stat2 = await fs.stat(lockPath);
|
|
141
143
|
if (Date.now() - stat2.mtimeMs > staleMs) {
|
|
@@ -171,7 +173,7 @@ function createPersistencePrimitives(options = {}) {
|
|
|
171
173
|
await fs.unlink(lockPath).catch(() => void 0);
|
|
172
174
|
}
|
|
173
175
|
}
|
|
174
|
-
return { atomicWrite: atomicWrite2, atomicReplaceWithWriter, ensureDir: ensureDir2, withFileLock: withFileLock2 };
|
|
176
|
+
return { atomicWrite: atomicWrite2, atomicReplaceWithWriter: atomicReplaceWithWriter2, ensureDir: ensureDir2, withFileLock: withFileLock2 };
|
|
175
177
|
}
|
|
176
178
|
async function waitForLockRelease(lockPath, remainingMs) {
|
|
177
179
|
const parentDir = path.dirname(lockPath);
|
|
@@ -251,6 +253,7 @@ async function renameWithRetry(from, to) {
|
|
|
251
253
|
}
|
|
252
254
|
var defaultPrimitives = createPersistencePrimitives();
|
|
253
255
|
var atomicWrite = defaultPrimitives.atomicWrite;
|
|
256
|
+
var atomicReplaceWithWriter = defaultPrimitives.atomicReplaceWithWriter;
|
|
254
257
|
var ensureDir = defaultPrimitives.ensureDir;
|
|
255
258
|
var withFileLock = defaultPrimitives.withFileLock;
|
|
256
259
|
|
|
@@ -432,17 +435,67 @@ async function bindProjectEndpoint(options) {
|
|
|
432
435
|
)
|
|
433
436
|
};
|
|
434
437
|
}
|
|
438
|
+
|
|
439
|
+
// src/sqlite-runtime.ts
|
|
440
|
+
import { createRequire } from "node:module";
|
|
441
|
+
function databaseSyncFromNode(module) {
|
|
442
|
+
if (typeof module !== "object" || module === null || !("DatabaseSync" in module)) return null;
|
|
443
|
+
return typeof module.DatabaseSync === "function" ? module.DatabaseSync : null;
|
|
444
|
+
}
|
|
445
|
+
function databaseSyncFromBun(module) {
|
|
446
|
+
if (typeof module !== "object" || module === null || !("Database" in module)) return null;
|
|
447
|
+
if (typeof module.Database !== "function") return null;
|
|
448
|
+
const BunDatabase = module.Database;
|
|
449
|
+
function BunDatabaseSync(filename, options) {
|
|
450
|
+
const bunOptions = options?.readOnly ? { readonly: true, create: false, readwrite: false } : void 0;
|
|
451
|
+
return new BunDatabase(filename, bunOptions);
|
|
452
|
+
}
|
|
453
|
+
return BunDatabaseSync;
|
|
454
|
+
}
|
|
455
|
+
function loadRuntimeDatabaseSync(loadModule = createRequire(import.meta.url)) {
|
|
456
|
+
let nodeError;
|
|
457
|
+
try {
|
|
458
|
+
const Database = databaseSyncFromNode(loadModule("node:sqlite"));
|
|
459
|
+
if (Database) return Database;
|
|
460
|
+
nodeError = new Error("node:sqlite did not export DatabaseSync");
|
|
461
|
+
} catch (error) {
|
|
462
|
+
nodeError = error;
|
|
463
|
+
}
|
|
464
|
+
let bunError;
|
|
465
|
+
try {
|
|
466
|
+
const Database = databaseSyncFromBun(loadModule("bun:sqlite"));
|
|
467
|
+
if (Database) return Database;
|
|
468
|
+
bunError = new Error("bun:sqlite did not export Database");
|
|
469
|
+
} catch (error) {
|
|
470
|
+
bunError = error;
|
|
471
|
+
}
|
|
472
|
+
const describe = (error) => error instanceof Error ? error.message : String(error);
|
|
473
|
+
throw new Error(
|
|
474
|
+
`No supported synchronous SQLite runtime is available (node:sqlite: ${describe(nodeError)}; bun:sqlite: ${describe(bunError)}).`
|
|
475
|
+
);
|
|
476
|
+
}
|
|
477
|
+
function isRuntimeSqliteAvailable(loadModule) {
|
|
478
|
+
try {
|
|
479
|
+
loadRuntimeDatabaseSync(loadModule);
|
|
480
|
+
return true;
|
|
481
|
+
} catch {
|
|
482
|
+
return false;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
435
485
|
export {
|
|
436
486
|
PersistenceFsError,
|
|
437
487
|
SECRET_DIR_MODE,
|
|
438
488
|
SECRET_FILE_MODE,
|
|
439
489
|
assertUnixSocketPathWithinLimit,
|
|
490
|
+
atomicReplaceWithWriter,
|
|
440
491
|
atomicWrite,
|
|
441
492
|
bindProjectEndpoint,
|
|
442
493
|
checkUnixSocketPath,
|
|
443
494
|
createPersistencePrimitives,
|
|
444
495
|
ensureDir,
|
|
445
496
|
isProjectEndpointLive,
|
|
497
|
+
isRuntimeSqliteAvailable,
|
|
498
|
+
loadRuntimeDatabaseSync,
|
|
446
499
|
restrictDirPermissions,
|
|
447
500
|
restrictFilePermissions,
|
|
448
501
|
unixSocketPathLimit,
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { DatabaseSync } from 'node:sqlite';
|
|
2
|
+
type DatabaseSyncConstructor = typeof DatabaseSync;
|
|
3
|
+
type ModuleLoader = (specifier: string) => unknown;
|
|
4
|
+
/**
|
|
5
|
+
* Resolve the synchronous SQLite constructor for the active JavaScript runtime.
|
|
6
|
+
* Node uses `node:sqlite`; Bun uses a small constructor adapter over `bun:sqlite`.
|
|
7
|
+
* The SQL surface WrongStack relies on (`exec`, `prepare`, `get`, `all`, `run`,
|
|
8
|
+
* and `close`) is shared by both implementations.
|
|
9
|
+
*/
|
|
10
|
+
export declare function loadRuntimeDatabaseSync(loadModule?: ModuleLoader): DatabaseSyncConstructor;
|
|
11
|
+
export declare function isRuntimeSqliteAvailable(loadModule?: ModuleLoader): boolean;
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=sqlite-runtime.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wrongstack/persistence",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.310.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Dependency-free filesystem persistence primitives shared across WrongStack packages.",
|
|
6
6
|
"repository": {
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
},
|
|
36
36
|
"scripts": {
|
|
37
37
|
"build": "node ../../scripts/build-package.mjs",
|
|
38
|
-
"typecheck": "tsc --noEmit",
|
|
38
|
+
"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.test.json",
|
|
39
39
|
"test": "vitest run --config vitest.config.ts",
|
|
40
40
|
"clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\""
|
|
41
41
|
}
|