@delali/sirannon-db 0.1.3 → 0.1.5
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/README.md +655 -80
- package/dist/backup-scheduler/index.d.ts +3 -0
- package/dist/backup-scheduler/index.mjs +2 -0
- package/dist/change-tracker-CFTQ9TSn.d.ts +89 -0
- package/dist/chunk-3MCMONVP.mjs +115 -0
- package/dist/chunk-74UN4DIE.mjs +14 -0
- package/dist/chunk-ER7ODTDA.mjs +23 -0
- package/dist/chunk-FB2U2Q3Y.mjs +21 -0
- package/dist/chunk-GS7T5YMI.mjs +51 -0
- package/dist/chunk-O7BHI3CF.mjs +90 -0
- package/dist/chunk-PXKAKK2V.mjs +124 -0
- package/dist/chunk-UTO3ZAFS.mjs +514 -0
- package/dist/chunk-UVMVN3OT.mjs +111 -0
- package/dist/client/index.d.ts +137 -44
- package/dist/client/index.mjs +726 -26
- package/dist/core/index.d.ts +32 -241
- package/dist/core/index.mjs +294 -568
- package/dist/database-BVY1GqE7.d.ts +95 -0
- package/dist/driver/better-sqlite3.d.ts +8 -0
- package/dist/driver/better-sqlite3.mjs +63 -0
- package/dist/driver/bun.mjs +61 -0
- package/dist/driver/expo.mjs +55 -0
- package/dist/driver/node.d.ts +8 -0
- package/dist/driver/node.mjs +60 -0
- package/dist/driver/wa-sqlite.d.ts +34 -0
- package/dist/driver/wa-sqlite.mjs +141 -0
- package/dist/errors-C00ed08Q.d.ts +101 -0
- package/dist/file-migrations/index.d.ts +16 -0
- package/dist/file-migrations/index.mjs +128 -0
- package/dist/index-CLdNrcPz.d.ts +16 -0
- package/dist/replication/coordinator/etcd.d.ts +44 -0
- package/dist/replication/coordinator/etcd.mjs +650 -0
- package/dist/replication/index.d.ts +491 -0
- package/dist/replication/index.mjs +3784 -0
- package/dist/server/index.d.ts +121 -54
- package/dist/server/index.mjs +347 -114
- package/dist/sirannon-Cd-lK6T0.d.ts +31 -0
- package/dist/transport/grpc.d.ts +316 -0
- package/dist/transport/grpc.mjs +3341 -0
- package/dist/transport/memory.d.ts +221 -0
- package/dist/transport/memory.mjs +337 -0
- package/dist/types-B2byqt0B.d.ts +273 -0
- package/dist/types-BEu1I_9_.d.ts +139 -0
- package/dist/types-BFSsG77t.d.ts +29 -0
- package/dist/types-BeozgNPr.d.ts +26 -0
- package/dist/{types-DArCObcu.d.ts → types-D-74JiXb.d.ts} +80 -1
- package/dist/vfs-INWQ5DTE.mjs +2 -0
- package/package.json +106 -11
- package/dist/chunk-VI4UP4RR.mjs +0 -417
- package/dist/protocol-BX1H-_Mz.d.ts +0 -104
- package/dist/sirannon-BJ8Yd1Uf.d.ts +0 -148
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { MigrationError } from '../chunk-O7BHI3CF.mjs';
|
|
2
|
+
import { statSync, readdirSync, readFileSync } from 'fs';
|
|
3
|
+
import { resolve, join } from 'path';
|
|
4
|
+
|
|
5
|
+
var MIGRATION_FILENAME_PATTERN = /^(\d+)_(\w+)\.(up|down)\.sql$/;
|
|
6
|
+
function hasControlCharacters(s) {
|
|
7
|
+
for (let i = 0; i < s.length; i++) {
|
|
8
|
+
if (s.charCodeAt(i) <= 31) return true;
|
|
9
|
+
}
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
function scanDirectory(dirPath) {
|
|
13
|
+
if (hasControlCharacters(dirPath)) {
|
|
14
|
+
throw new MigrationError("Migration path contains invalid characters", 0, "MIGRATION_VALIDATION_ERROR");
|
|
15
|
+
}
|
|
16
|
+
const segments = dirPath.split(/[/\\]/);
|
|
17
|
+
if (segments.includes("..")) {
|
|
18
|
+
throw new MigrationError(
|
|
19
|
+
"Migration path must not contain directory traversal segments",
|
|
20
|
+
0,
|
|
21
|
+
"MIGRATION_VALIDATION_ERROR"
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
const resolvedPath = resolve(dirPath);
|
|
25
|
+
let stat;
|
|
26
|
+
try {
|
|
27
|
+
stat = statSync(resolvedPath);
|
|
28
|
+
} catch {
|
|
29
|
+
throw new MigrationError(`Migrations path does not exist: ${resolvedPath}`, 0);
|
|
30
|
+
}
|
|
31
|
+
if (!stat.isDirectory()) {
|
|
32
|
+
throw new MigrationError(`Migrations path is not a directory: ${resolvedPath}`, 0);
|
|
33
|
+
}
|
|
34
|
+
const entries = readdirSync(resolvedPath, { withFileTypes: true });
|
|
35
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
36
|
+
for (const entry of entries) {
|
|
37
|
+
if (!entry.isFile()) continue;
|
|
38
|
+
const match = MIGRATION_FILENAME_PATTERN.exec(entry.name);
|
|
39
|
+
if (!match) continue;
|
|
40
|
+
const version = parseInt(match[1], 10);
|
|
41
|
+
const name = match[2];
|
|
42
|
+
const direction = match[3];
|
|
43
|
+
if (!Number.isFinite(version) || version <= 0 || !Number.isSafeInteger(version)) {
|
|
44
|
+
throw new MigrationError(`Invalid migration version: ${match[1]}`, version, "MIGRATION_VALIDATION_ERROR");
|
|
45
|
+
}
|
|
46
|
+
const existing = grouped.get(version);
|
|
47
|
+
if (existing && existing.name !== name) {
|
|
48
|
+
throw new MigrationError(
|
|
49
|
+
`Duplicate migration version ${version}: '${existing.name}' and '${name}'`,
|
|
50
|
+
version,
|
|
51
|
+
"MIGRATION_DUPLICATE_VERSION"
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
const filePath = join(resolvedPath, entry.name);
|
|
55
|
+
if (!existing) {
|
|
56
|
+
grouped.set(version, {
|
|
57
|
+
name,
|
|
58
|
+
[direction === "up" ? "upPath" : "downPath"]: filePath
|
|
59
|
+
});
|
|
60
|
+
} else {
|
|
61
|
+
if (direction === "up") existing.upPath = filePath;
|
|
62
|
+
else existing.downPath = filePath;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const results = [];
|
|
66
|
+
for (const [version, entry] of grouped) {
|
|
67
|
+
if (!entry.upPath) {
|
|
68
|
+
throw new MigrationError(
|
|
69
|
+
`Migration version ${version} (${entry.name}) is missing an .up.sql file`,
|
|
70
|
+
version,
|
|
71
|
+
"MIGRATION_VALIDATION_ERROR"
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
results.push({
|
|
75
|
+
version,
|
|
76
|
+
name: entry.name,
|
|
77
|
+
upPath: entry.upPath,
|
|
78
|
+
downPath: entry.downPath ?? null
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
results.sort((a, b) => a.version - b.version);
|
|
82
|
+
return results;
|
|
83
|
+
}
|
|
84
|
+
function readUpMigrations(scanned) {
|
|
85
|
+
return scanned.map((entry) => {
|
|
86
|
+
const sql = readFileSync(entry.upPath, "utf-8").trim();
|
|
87
|
+
if (sql.length === 0) {
|
|
88
|
+
throw new MigrationError(`Migration file is empty: ${entry.upPath}`, entry.version, "MIGRATION_VALIDATION_ERROR");
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
version: entry.version,
|
|
92
|
+
name: entry.name,
|
|
93
|
+
up: sql
|
|
94
|
+
};
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
function readDownMigrations(scanned, versions) {
|
|
98
|
+
const versionSet = new Set(versions);
|
|
99
|
+
const filtered = scanned.filter((s) => versionSet.has(s.version));
|
|
100
|
+
return filtered.map((entry) => {
|
|
101
|
+
if (!entry.downPath) {
|
|
102
|
+
throw new MigrationError(
|
|
103
|
+
`Migration version ${entry.version} (${entry.name}) has no .down.sql file`,
|
|
104
|
+
entry.version,
|
|
105
|
+
"MIGRATION_NO_DOWN"
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
const downSql = readFileSync(entry.downPath, "utf-8").trim();
|
|
109
|
+
if (downSql.length === 0) {
|
|
110
|
+
throw new MigrationError(
|
|
111
|
+
`Down migration file is empty: ${entry.downPath}`,
|
|
112
|
+
entry.version,
|
|
113
|
+
"MIGRATION_VALIDATION_ERROR"
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
return {
|
|
117
|
+
version: entry.version,
|
|
118
|
+
name: entry.name,
|
|
119
|
+
up: "",
|
|
120
|
+
down: downSql
|
|
121
|
+
};
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
function loadMigrations(dirPath) {
|
|
125
|
+
return readUpMigrations(scanDirectory(dirPath));
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export { loadMigrations, readDownMigrations, readUpMigrations, scanDirectory };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { a as SQLiteConnection } from './types-BFSsG77t.js';
|
|
2
|
+
import { m as BackupScheduleOptions } from './types-D-74JiXb.js';
|
|
3
|
+
|
|
4
|
+
declare class BackupManager {
|
|
5
|
+
backup(conn: SQLiteConnection, destPath: string): Promise<void>;
|
|
6
|
+
generateFilename(): string;
|
|
7
|
+
rotate(dir: string, maxFiles: number): void;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
declare class BackupScheduler {
|
|
11
|
+
private readonly manager;
|
|
12
|
+
constructor(manager?: BackupManager);
|
|
13
|
+
schedule(conn: SQLiteConnection, options: BackupScheduleOptions): () => void;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export { BackupManager as B, BackupScheduler as a };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { IOptions } from 'etcd3';
|
|
2
|
+
import { C as ClusterCoordinator, A as AcquireControllerLeaseInput, a as AcquireControllerLeaseResult, R as RegisterNodeSessionInput, b as CoordinatorNodeSession, S as SetReplicationGroupStateInput, c as ReplicationGroupState, d as ReplicationGroupWatcher, e as CoordinatorWatchDisposer, f as CompareAndAdvancePrimaryTermInput, g as CompareAndAdvancePrimaryTermResult, U as UpdateInSyncSetInput, h as AdmitNodeToInSyncSetInput, i as UpdateNodeMaintenanceInput, P as PromoteEligibleReplicaInput } from '../../types-BEu1I_9_.js';
|
|
3
|
+
|
|
4
|
+
interface EtcdClusterCoordinatorOptions {
|
|
5
|
+
hosts: string | string[];
|
|
6
|
+
keyPrefix: string;
|
|
7
|
+
credentials?: IOptions['credentials'];
|
|
8
|
+
auth?: IOptions['auth'];
|
|
9
|
+
grpcOptions?: IOptions['grpcOptions'];
|
|
10
|
+
dialTimeoutMs?: number;
|
|
11
|
+
defaultCallTimeoutMs?: number;
|
|
12
|
+
allowInsecure?: boolean;
|
|
13
|
+
onWatcherError?: (error: Error) => void;
|
|
14
|
+
}
|
|
15
|
+
declare class EtcdClusterCoordinator implements ClusterCoordinator {
|
|
16
|
+
private readonly client;
|
|
17
|
+
private readonly namespace;
|
|
18
|
+
private readonly onWatcherError;
|
|
19
|
+
private readonly leases;
|
|
20
|
+
private readonly watchers;
|
|
21
|
+
constructor(options: EtcdClusterCoordinatorOptions);
|
|
22
|
+
tryAcquireControllerLease(input: AcquireControllerLeaseInput): Promise<AcquireControllerLeaseResult>;
|
|
23
|
+
renewLease(leaseId: string, ttlMs: number): Promise<boolean>;
|
|
24
|
+
releaseLease(leaseId: string): Promise<boolean>;
|
|
25
|
+
registerNodeSession(input: RegisterNodeSessionInput): Promise<CoordinatorNodeSession>;
|
|
26
|
+
getLiveNodeSession(clusterId: string, nodeId: string): Promise<CoordinatorNodeSession | null>;
|
|
27
|
+
deregisterNodeSession(clusterId: string, nodeId: string): Promise<void>;
|
|
28
|
+
setReplicationGroupState(input: SetReplicationGroupStateInput): Promise<ReplicationGroupState>;
|
|
29
|
+
getReplicationGroupState(clusterId: string, groupId: string): Promise<ReplicationGroupState | null>;
|
|
30
|
+
watchReplicationGroup(clusterId: string, groupId: string, watcher: ReplicationGroupWatcher): Promise<CoordinatorWatchDisposer>;
|
|
31
|
+
compareAndAdvancePrimaryTerm(input: CompareAndAdvancePrimaryTermInput): Promise<CompareAndAdvancePrimaryTermResult>;
|
|
32
|
+
updateInSyncSet(input: UpdateInSyncSetInput): Promise<ReplicationGroupState | null>;
|
|
33
|
+
admitNodeToInSyncSet(input: AdmitNodeToInSyncSetInput): Promise<ReplicationGroupState | null>;
|
|
34
|
+
updateNodeMaintenance(input: UpdateNodeMaintenanceInput): Promise<ReplicationGroupState | null>;
|
|
35
|
+
promoteEligibleReplica(input: PromoteEligibleReplicaInput): Promise<ReplicationGroupState>;
|
|
36
|
+
close(): Promise<void>;
|
|
37
|
+
private getLeaseFromKey;
|
|
38
|
+
private trackLease;
|
|
39
|
+
private updateGroupStateWithRetry;
|
|
40
|
+
private casGroupState;
|
|
41
|
+
}
|
|
42
|
+
declare function createEtcdCoordinator(options: EtcdClusterCoordinatorOptions): EtcdClusterCoordinator;
|
|
43
|
+
|
|
44
|
+
export { EtcdClusterCoordinator, type EtcdClusterCoordinatorOptions, createEtcdCoordinator };
|