@delali/sirannon-db 0.3.5 → 0.3.6-next.78
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/backup/index.d.ts +5 -5
- package/dist/backup/index.mjs +5 -3
- package/dist/backup-scheduler/index.d.ts +2 -2
- package/dist/backup-scheduler/index.mjs +2 -2
- package/dist/chunk-22TYGH7J.mjs +55 -0
- package/dist/{chunk-SB3MIFLG.mjs → chunk-2ZQOZFX7.mjs} +29 -6
- package/dist/{chunk-UIDQGPJY.mjs → chunk-4O7WYZHN.mjs} +38 -3
- package/dist/{chunk-ZFFUVYYE.mjs → chunk-5DKWHT6K.mjs} +109 -1
- package/dist/chunk-5O4J6LQQ.mjs +35 -0
- package/dist/{chunk-CZL4D3BM.mjs → chunk-6CABU54O.mjs} +2 -2
- package/dist/{chunk-JAQ2I4OT.mjs → chunk-A5ULJVK7.mjs} +11 -11
- package/dist/{chunk-RLBKZZ24.mjs → chunk-AC7TKWNH.mjs} +1 -0
- package/dist/chunk-BKO4SCEC.mjs +99 -0
- package/dist/{chunk-KOTBP4AW.mjs → chunk-C7E4H6UN.mjs} +24 -4
- package/dist/{chunk-G4AG3ESO.mjs → chunk-FBA7P4ZA.mjs} +114 -149
- package/dist/{chunk-DKML5425.mjs → chunk-GBVB6WSC.mjs} +2 -2
- package/dist/chunk-I4JY5QPA.mjs +51 -0
- package/dist/{chunk-L6EX6K27.mjs → chunk-MO4APBYG.mjs} +54 -13
- package/dist/{chunk-RPWBYASV.mjs → chunk-MTOQ6QIS.mjs} +1 -1
- package/dist/chunk-MX77PGEN.mjs +60 -0
- package/dist/{chunk-BTUD6XQO.mjs → chunk-N3MHZV3B.mjs} +11 -29
- package/dist/{chunk-UHUDPQFI.mjs → chunk-OJXV4L3N.mjs} +1 -3
- package/dist/chunk-QF7WF7RJ.mjs +34 -0
- package/dist/chunk-RLBV4YTB.mjs +22 -0
- package/dist/{chunk-ISDT4RBD.mjs → chunk-ULUZUBON.mjs} +1 -1
- package/dist/{chunk-AP4367HK.mjs → chunk-VGRAAQX3.mjs} +4 -4
- package/dist/chunk-W74HFQFD.mjs +153 -0
- package/dist/chunk-Y4SP7CRF.mjs +9 -0
- package/dist/{chunk-JFVEGN7J.mjs → chunk-ZAUHAJ4G.mjs} +2 -1
- package/dist/{chunk-DDIHBUEN.mjs → chunk-ZWW53O5P.mjs} +19 -7
- package/dist/client/index.d.ts +8 -8
- package/dist/client/topology.d.ts +4 -4
- package/dist/{client-base-Doaqwrx3.d.ts → client-base-DJZbSY55.d.ts} +2 -2
- package/dist/{client-streams-MKPE4MXW.mjs → client-streams-F7IG3PTU.mjs} +13 -16
- package/dist/core/index.d.ts +48 -12
- package/dist/core/index.mjs +1812 -107
- package/dist/core/writer-worker.mjs +28 -4
- package/dist/{database-fz-8CJBP.d.ts → database-BZ96ZzAx.d.ts} +411 -184
- package/dist/{database-backup-BwTNiBm2.d.ts → database-backup-BhM8yJ1A.d.ts} +32 -2
- package/dist/driver/better-sqlite3.d.ts +11 -1
- package/dist/driver/better-sqlite3.mjs +212 -23
- package/dist/driver/bun.d.ts +1 -1
- package/dist/driver/bun.mjs +15 -22
- package/dist/driver/expo.d.ts +1 -1
- package/dist/driver/expo.mjs +185 -16
- package/dist/driver/node.d.ts +1 -1
- package/dist/driver/node.mjs +15 -62
- package/dist/driver/wa-sqlite.d.ts +1 -1
- package/dist/driver/wa-sqlite.mjs +14 -153
- package/dist/{change-tracker-Dpo99EI-.d.ts → errors-DLMAGQFb.d.ts} +200 -2
- package/dist/file-migrations/index.d.ts +1 -1
- package/dist/peer-refusal-RR37UOLV.mjs +1 -0
- package/dist/{protocol-DZSYSv0S.d.ts → protocol-DE10taas.d.ts} +1 -1
- package/dist/replication/coordinator/etcd.mjs +1 -1
- package/dist/replication/index.d.ts +7 -7
- package/dist/replication/index.mjs +66 -9
- package/dist/{restore-options-CcMukOLO.d.ts → restore-options-B6HV_5XT.d.ts} +6 -1
- package/dist/server/index.d.ts +10 -10
- package/dist/server/index.mjs +506 -350
- package/dist/{server-options-B9CsAZp5.d.ts → server-options-Bhdlvehe.d.ts} +14 -1
- package/dist/{server-streams-SBYCHWWM.mjs → server-streams-Q2AZAW3N.mjs} +6 -30
- package/dist/{sirannon-D0CjDULa.d.ts → sirannon-Ba1o2HUQ.d.ts} +5 -5
- package/dist/transport/grpc.d.ts +15 -4
- package/dist/transport/grpc.mjs +34 -37
- package/dist/transport/memory.d.ts +4 -3
- package/dist/transport/memory.mjs +8 -26
- package/dist/{types-DTmi7pXp.d.ts → types-BWyv_N18.d.ts} +189 -1
- package/dist/{types-BlZ9GG1a.d.ts → types-CDnlkVRK.d.ts} +8 -2
- package/package.json +17 -9
- package/dist/chunk-DBN57KVR.mjs +0 -171
- package/dist/chunk-W67A4H2E.mjs +0 -23
- package/dist/chunk-YW7IKQ7T.mjs +0 -62
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
import { groupMemberIds, isGroupMember, sameNodeIdSet, compatibilityAllowsPromotion, arraysEqual } from '../chunk-PJRCMG7L.mjs';
|
|
2
2
|
import { CoordinatorError, TopologyError, WriteConcernError, AuthorityError, SyncError, StalePrimaryError, NodeDrainingError, NodeNotInSyncError, ReadConcernError, ProtocolVersionMismatchError } from '../chunk-KU32OT4H.mjs';
|
|
3
3
|
export { AuthorityError, CoordinatorError, FailoverError, NoSafePrimaryError, NodeDrainingError, NodeNotInSyncError, ProtocolVersionMismatchError, ReadConcernError, StalePrimaryError, SyncError, TopologyError, TransportError, UnsafeRecoveryRequiredError, WriteConcernError } from '../chunk-KU32OT4H.mjs';
|
|
4
|
-
import { LWWResolver, BatchReader, BatchApplier, StampOps, writeOutcome, failedStatementOutcome, StatementRecorder, batchWriteOutcome, isWellFormedHlc, Transaction, loadPersistedHlc } from '../chunk-
|
|
5
|
-
export { LWWResolver } from '../chunk-
|
|
6
|
-
import '../chunk-
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
4
|
+
import { LWWResolver, BatchReader, BatchApplier, StampOps, writeOutcome, failedStatementOutcome, StatementRecorder, batchWriteOutcome, isWellFormedHlc, Transaction, loadPersistedHlc } from '../chunk-VGRAAQX3.mjs';
|
|
5
|
+
export { LWWResolver } from '../chunk-VGRAAQX3.mjs';
|
|
6
|
+
import { runWriterTransaction, execute, withoutRowCounts } from '../chunk-ZWW53O5P.mjs';
|
|
7
|
+
import { DumpOps, dumpSchema, tablesInFkOrder } from '../chunk-GBVB6WSC.mjs';
|
|
8
|
+
import { canonicaliseForChecksum, HLC, PkResolver, selectMaxChangeHlc, selectMaxColumnVersionHlc, selectMaxAppliedSourceSeq, upsertPeerAckedSeq, selectPeerAckedSeq, selectMaxChangeSeq, selectMaxNodeChangeSeq, selectMinPeerAckedSeq, upsertSyncTableStatus, upsertSyncMeta, selectSyncMetaRow, selectCompletedSyncTableNames, ensureChangesTable, ensureReplicationStateTables, ensureMetaTable, IDENTIFIER_RE, setForeignKeysEnabled, deleteSyncTableStates, extractDroppedTable, insertDdlChange, validateDdlSafety, prepareInsertAppliedChange, selectNewestHistoryChange, upsertQuarantined, deleteStampedChangesUpToSeq, deleteColumnVersions, upsertHistoryBase, deleteAppliedChangesAfterSeq, deletePeerState, upsertAnchoredTerm, selectPrimaryTermStart, selectMaxHistoryChangeSeq, deletePeerStates, upsertPrimaryTermStart, selectHistoryTransaction, selectMaxAppliedSourceSeqByNode, selectAnchoredTerm, selectQuarantined, selectHistoryBase, selectHistoryChangesAfterHlc, deleteHistoryChangesAfterHlc, deleteColumnVersionsAfterHlc, tablePkColumns, deletePrimaryTermStart, selectMaxAssignedChangeSeq } from '../chunk-MTOQ6QIS.mjs';
|
|
9
|
+
export { HLC } from '../chunk-MTOQ6QIS.mjs';
|
|
10
|
+
import '../chunk-5DKWHT6K.mjs';
|
|
11
11
|
import { ReplicationError, BatchValidationError } from '../chunk-BLMRNSUG.mjs';
|
|
12
12
|
export { BatchValidationError, ConflictError, ReplicationError } from '../chunk-BLMRNSUG.mjs';
|
|
13
|
-
import { CHANGES_TABLE, INTERNAL_TABLE_PREFIX, isReservedIdentifier, decodeTaggedValues } from '../chunk-
|
|
13
|
+
import { CHANGES_TABLE, INTERNAL_TABLE_PREFIX, isReservedIdentifier, decodeTaggedValues } from '../chunk-ZAUHAJ4G.mjs';
|
|
14
14
|
import '../chunk-GVCNMPOS.mjs';
|
|
15
15
|
import '../chunk-K43WJORM.mjs';
|
|
16
16
|
import { rowCountsOf } from '../chunk-E2GRX4ZD.mjs';
|
|
17
17
|
import '../chunk-HO2XTXVX.mjs';
|
|
18
|
+
import { EncryptionError } from '../chunk-5O4J6LQQ.mjs';
|
|
18
19
|
import '../chunk-KINDFBQP.mjs';
|
|
19
20
|
import { EventEmitter } from 'events';
|
|
20
21
|
import { randomBytes, randomUUID, createHash } from 'crypto';
|
|
@@ -2948,6 +2949,39 @@ var RejoinState = class {
|
|
|
2948
2949
|
quarantineRecorded = false;
|
|
2949
2950
|
};
|
|
2950
2951
|
|
|
2952
|
+
// src/replication/engine/encryption-refusal.ts
|
|
2953
|
+
var PLAINTEXT_PEER_MESSAGE = "This node holds an encrypted database, so it sends no batch and no snapshot to a peer that announces a plaintext database";
|
|
2954
|
+
var refusedPeers = /* @__PURE__ */ new WeakMap();
|
|
2955
|
+
function refusedBy(engine) {
|
|
2956
|
+
const existing = refusedPeers.get(engine);
|
|
2957
|
+
if (existing) return existing;
|
|
2958
|
+
const created = /* @__PURE__ */ new Set();
|
|
2959
|
+
refusedPeers.set(engine, created);
|
|
2960
|
+
return created;
|
|
2961
|
+
}
|
|
2962
|
+
function withholdsDataFrom(engine, peer) {
|
|
2963
|
+
return engine.database.encryptedFile && peer?.encrypted !== true;
|
|
2964
|
+
}
|
|
2965
|
+
function encryptionRequired(peerId) {
|
|
2966
|
+
return new EncryptionError(`${PLAINTEXT_PEER_MESSAGE}, and peer '${peerId}' announces one`, "ENCRYPTION_REQUIRED");
|
|
2967
|
+
}
|
|
2968
|
+
function refusePlaintextPeer(engine, peerId) {
|
|
2969
|
+
const refused = refusedBy(engine);
|
|
2970
|
+
const error = encryptionRequired(peerId);
|
|
2971
|
+
const transport = engine.config.transport;
|
|
2972
|
+
if (!refused.has(peerId)) {
|
|
2973
|
+
refused.add(peerId);
|
|
2974
|
+
engine.emitError({ error, operation: "encryption-required", peerId, recoverable: true });
|
|
2975
|
+
}
|
|
2976
|
+
transport.refusePeer?.(peerId, error).catch((err) => {
|
|
2977
|
+
const wrappedErr = err instanceof Error ? err : new Error(String(err));
|
|
2978
|
+
engine.emitError({ error: wrappedErr, operation: "encryption-required", peerId, recoverable: true });
|
|
2979
|
+
});
|
|
2980
|
+
}
|
|
2981
|
+
function forgetPeerRefusal(engine, peerId) {
|
|
2982
|
+
refusedPeers.get(engine)?.delete(peerId);
|
|
2983
|
+
}
|
|
2984
|
+
|
|
2951
2985
|
// src/replication/engine/sender-loop.ts
|
|
2952
2986
|
var SenderLoop = class {
|
|
2953
2987
|
constructor(engine) {
|
|
@@ -3009,6 +3043,10 @@ var SenderLoop = class {
|
|
|
3009
3043
|
if (!this.shouldReplicateTo(peerId, peerInfo.role)) {
|
|
3010
3044
|
continue;
|
|
3011
3045
|
}
|
|
3046
|
+
if (withholdsDataFrom(engine, peerInfo)) {
|
|
3047
|
+
refusePlaintextPeer(engine, peerId);
|
|
3048
|
+
continue;
|
|
3049
|
+
}
|
|
3012
3050
|
const peerState = engine.peerTracker.getPeerState(peerId);
|
|
3013
3051
|
if (peerState) {
|
|
3014
3052
|
engine.peerTracker.expireTimedOutBatches(peerId, nowMs, engine.ackTimeoutMs);
|
|
@@ -3240,6 +3278,7 @@ function wireTransportHandlers(engine) {
|
|
|
3240
3278
|
}
|
|
3241
3279
|
});
|
|
3242
3280
|
engine.config.transport.onPeerDisconnected((peerId) => {
|
|
3281
|
+
forgetPeerRefusal(engine, peerId);
|
|
3243
3282
|
engine.peerTracker.removePeer(peerId);
|
|
3244
3283
|
engine.syncServer.abortSessionsForPeer(peerId);
|
|
3245
3284
|
if (engine.syncState.phase === "syncing" && engine.syncState.sourcePeerId === peerId) {
|
|
@@ -3319,8 +3358,10 @@ async function recoverHlcFromDurableState(engine) {
|
|
|
3319
3358
|
if (maxObserved === null) return;
|
|
3320
3359
|
engine.hlc.receive(maxObserved);
|
|
3321
3360
|
}
|
|
3361
|
+
var databaseRegistrations = /* @__PURE__ */ new WeakMap();
|
|
3322
3362
|
async function startEngine(engine) {
|
|
3323
3363
|
if (engine.running) return;
|
|
3364
|
+
databaseRegistrations.set(engine, engine.database.registerReplicationEngine());
|
|
3324
3365
|
engine.running = true;
|
|
3325
3366
|
engine.history.active = false;
|
|
3326
3367
|
await startEngineSteps(engine);
|
|
@@ -3341,7 +3382,8 @@ async function startEngineSteps(engine) {
|
|
|
3341
3382
|
localRole: engine.config.topology.role,
|
|
3342
3383
|
groupId: engine.config.coordinator?.groupId ?? engine.config.transportConfig?.groupId,
|
|
3343
3384
|
primaryTerm: engine.coordinatorState?.primaryTerm ?? engine.config.transportConfig?.primaryTerm,
|
|
3344
|
-
protocolVersion: engine.config.coordinator?.compatibility?.protocolVersion ?? engine.config.transportConfig?.protocolVersion
|
|
3385
|
+
protocolVersion: engine.config.coordinator?.compatibility?.protocolVersion ?? engine.config.transportConfig?.protocolVersion,
|
|
3386
|
+
encrypted: engine.database.encryptedFile
|
|
3345
3387
|
};
|
|
3346
3388
|
await engine.config.transport.connect(engine.nodeId, transportConfig);
|
|
3347
3389
|
await refreshMemberAddresses(engine).catch(
|
|
@@ -3411,6 +3453,14 @@ async function startEngineSteps(engine) {
|
|
|
3411
3453
|
async function stopEngine(engine) {
|
|
3412
3454
|
if (!engine.running) return;
|
|
3413
3455
|
engine.running = false;
|
|
3456
|
+
try {
|
|
3457
|
+
await stopEngineSteps(engine);
|
|
3458
|
+
} finally {
|
|
3459
|
+
databaseRegistrations.get(engine)?.();
|
|
3460
|
+
databaseRegistrations.delete(engine);
|
|
3461
|
+
}
|
|
3462
|
+
}
|
|
3463
|
+
async function stopEngineSteps(engine) {
|
|
3414
3464
|
stopCoordinatorTimers(engine);
|
|
3415
3465
|
engine.syncJoiner.stopTimers();
|
|
3416
3466
|
engine.syncServer.abortAll();
|
|
@@ -3807,6 +3857,13 @@ var SyncServer = class {
|
|
|
3807
3857
|
const engine = this.engine;
|
|
3808
3858
|
const knownPeers = engine.config.transport.peers();
|
|
3809
3859
|
if (!knownPeers.has(fromPeerId)) return;
|
|
3860
|
+
if (withholdsDataFrom(engine, knownPeers.get(fromPeerId))) {
|
|
3861
|
+
const refusal = encryptionRequired(fromPeerId);
|
|
3862
|
+
await this.rejectSyncRequest(fromPeerId, request, `${refusal.code}: ${refusal.message}`).finally(
|
|
3863
|
+
() => refusePlaintextPeer(engine, fromPeerId)
|
|
3864
|
+
);
|
|
3865
|
+
return;
|
|
3866
|
+
}
|
|
3810
3867
|
if (engine.isCoordinatorMode()) {
|
|
3811
3868
|
try {
|
|
3812
3869
|
await engine.verifyPrimaryAuthority();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { B as BackupDestination, S as SQLiteDriver } from './types-
|
|
1
|
+
import { B as BackupDestination, S as SQLiteDriver, E as EncryptionOptions } from './types-BWyv_N18.js';
|
|
2
2
|
|
|
3
3
|
/** The progress of one restore, which Sirannon reports after every piece that it fetches and after every batch.
|
|
4
4
|
* @public
|
|
@@ -50,6 +50,11 @@ interface BackupRestoreOptions {
|
|
|
50
50
|
destinationTimeoutMs?: number;
|
|
51
51
|
/** Called after every piece that Sirannon fetches, and after every batch. */
|
|
52
52
|
onProgress?: (progress: BackupRestoreProgress) => void;
|
|
53
|
+
/**
|
|
54
|
+
* The key of the database that the restore rebuilds, which the backups of an encrypted database need. Sirannon
|
|
55
|
+
* opens the rebuilt file under this key, so the result holds ciphertext under the same key as the backups.
|
|
56
|
+
*/
|
|
57
|
+
encryption?: EncryptionOptions;
|
|
53
58
|
}
|
|
54
59
|
/** The report of one finished restore.
|
|
55
60
|
* @public
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { h as BackupChain, l as BackupChainRecord, p as BackupCycleStatus, C as BackupVerifyResult } from '../types-
|
|
2
|
-
import { b as BackupRestoreProgress, a as BackupRestoreReport } from '../restore-options-
|
|
3
|
-
import { a as TransactionStatement, Q as QueryResponse, E as ExecuteResponse, T as TransactionResponse, B as BatchResponse, L as LoadResponse, A as AckResponse } from '../protocol-
|
|
4
|
-
export { b as BatchRequest, c as ErrorResponse, d as ExecuteRequest, e as LoadRequest, f as QueryRequest, g as TransactionRequest, t as toExecuteResponse } from '../protocol-
|
|
5
|
-
import { S as Sirannon } from '../sirannon-
|
|
6
|
-
import { B as BulkLoadDurability, S as ServerOptions, W as WSHandlerOptions } from '../server-options-
|
|
1
|
+
import { h as BackupChain, l as BackupChainRecord, p as BackupCycleStatus, C as BackupVerifyResult } from '../types-BWyv_N18.js';
|
|
2
|
+
import { b as BackupRestoreProgress, a as BackupRestoreReport } from '../restore-options-B6HV_5XT.js';
|
|
3
|
+
import { a as TransactionStatement, Q as QueryResponse, E as ExecuteResponse, T as TransactionResponse, B as BatchResponse, L as LoadResponse, A as AckResponse } from '../protocol-DE10taas.js';
|
|
4
|
+
export { b as BatchRequest, c as ErrorResponse, d as ExecuteRequest, e as LoadRequest, f as QueryRequest, g as TransactionRequest, t as toExecuteResponse } from '../protocol-DE10taas.js';
|
|
5
|
+
import { S as Sirannon } from '../sirannon-Ba1o2HUQ.js';
|
|
6
|
+
import { B as BulkLoadDurability, S as ServerOptions, W as WSHandlerOptions } from '../server-options-Bhdlvehe.js';
|
|
7
7
|
import { W as WriteConcern, R as ReadConcern } from '../query-types-5B02ixH0.js';
|
|
8
|
-
import '../database-
|
|
9
|
-
import '../
|
|
10
|
-
import '../database-backup-
|
|
8
|
+
import '../database-BZ96ZzAx.js';
|
|
9
|
+
import '../errors-DLMAGQFb.js';
|
|
10
|
+
import '../database-backup-BhM8yJ1A.js';
|
|
11
11
|
import '../types-BG31TtrQ.js';
|
|
12
12
|
import '../types-CEJG0eFS.js';
|
|
13
13
|
import '../operation-registry-CGhNT-Sn.js';
|
|
@@ -495,6 +495,7 @@ declare class SirannonServer<Identity = unknown> {
|
|
|
495
495
|
private readonly authenticateHook;
|
|
496
496
|
private readonly acceptSql;
|
|
497
497
|
private readonly acceptBackupRestore;
|
|
498
|
+
private readonly encryptionChange;
|
|
498
499
|
private readonly acceptDeviceSync;
|
|
499
500
|
private readonly restoreRuns;
|
|
500
501
|
private readonly drain;
|
|
@@ -542,7 +543,6 @@ declare class SirannonServer<Identity = unknown> {
|
|
|
542
543
|
get listeningPort(): number;
|
|
543
544
|
private loadRuntime;
|
|
544
545
|
private registerRoutes;
|
|
545
|
-
private registerBackupRoutes;
|
|
546
546
|
private withCors;
|
|
547
547
|
private routeDeps;
|
|
548
548
|
private wrapDbRoute;
|