@delali/sirannon-db 0.1.7 → 0.2.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.
Files changed (72) hide show
  1. package/README.md +117 -969
  2. package/dist/backup-scheduler/index.d.ts +1 -1
  3. package/dist/backup-scheduler/index.mjs +2 -2
  4. package/dist/baseline-Br77Fnhb.d.ts +6 -0
  5. package/dist/{change-tracker-CbmaMO-N.d.ts → change-tracker-DKRVUC3l.d.ts} +5 -8
  6. package/dist/{chunk-DJLX6CAE.mjs → chunk-4ISB7XMA.mjs} +2 -1
  7. package/dist/chunk-5NOIGN5Y.mjs +18 -0
  8. package/dist/chunk-67M7KAH6.mjs +90 -0
  9. package/dist/{chunk-GEZUUIKV.mjs → chunk-D7LAYTKN.mjs} +5 -2
  10. package/dist/{chunk-4IGMIJQK.mjs → chunk-EBJXPQQO.mjs} +59 -20
  11. package/dist/{chunk-BNUTBHHH.mjs → chunk-FHWTZFI4.mjs} +1 -1
  12. package/dist/chunk-GVCNMPOS.mjs +130 -0
  13. package/dist/chunk-H237TXZW.mjs +1407 -0
  14. package/dist/{chunk-HHRMRFFR.mjs → chunk-H6PIVVDN.mjs} +353 -142
  15. package/dist/chunk-HR5CWTLC.mjs +661 -0
  16. package/dist/chunk-JU64Y7HM.mjs +299 -0
  17. package/dist/{chunk-CW6S3WL5.mjs → chunk-JZGINXTN.mjs} +7 -5
  18. package/dist/{chunk-CJLYFDP5.mjs → chunk-LFZ37BSX.mjs} +1 -1
  19. package/dist/chunk-LNY2VVHE.mjs +18 -0
  20. package/dist/chunk-NVQS53NT.mjs +665 -0
  21. package/dist/{chunk-H5AB6NIR.mjs → chunk-O7SLN3GI.mjs} +2 -15
  22. package/dist/chunk-OQVZBEBY.mjs +283 -0
  23. package/dist/{chunk-VLTICJOD.mjs → chunk-PIKHN33N.mjs} +1 -1
  24. package/dist/chunk-TJF5GZSV.mjs +187 -0
  25. package/dist/chunk-TUD5CJ76.mjs +126 -0
  26. package/dist/{chunk-YPYVQJ4C.mjs → chunk-UC3SCMIN.mjs} +9 -1
  27. package/dist/client/index.d.ts +216 -321
  28. package/dist/client/index.mjs +1192 -1342
  29. package/dist/client/topology.d.ts +61 -0
  30. package/dist/client/topology.mjs +682 -0
  31. package/dist/client-base-CLWmH5Ln.d.ts +234 -0
  32. package/dist/codegen/cli.d.ts +2 -0
  33. package/dist/codegen/cli.mjs +11 -0
  34. package/dist/codegen/index.d.ts +30 -0
  35. package/dist/codegen/index.mjs +5 -0
  36. package/dist/core/index.d.ts +37 -16
  37. package/dist/core/index.mjs +2322 -298
  38. package/dist/core/writer-worker.mjs +28 -6
  39. package/dist/{database-DuGp0Rtr.d.ts → database-BY0L5Q2n.d.ts} +59 -14
  40. package/dist/driver/better-sqlite3.d.ts +1 -1
  41. package/dist/driver/better-sqlite3.mjs +6 -6
  42. package/dist/driver/node.d.ts +1 -1
  43. package/dist/driver/node.mjs +6 -6
  44. package/dist/driver/wa-sqlite.d.ts +1 -136
  45. package/dist/{errors-5Nf5ZAEC.d.ts → errors-Bw5MdNCu.d.ts} +5 -1
  46. package/dist/file-migrations/index.d.ts +7 -5
  47. package/dist/file-migrations/index.mjs +42 -37
  48. package/dist/operation-registry-9DcvxcE5.d.ts +45 -0
  49. package/dist/primary-wins-DPAm2AKG.d.ts +61 -0
  50. package/dist/protocol-6KrSq2Hy.d.ts +66 -0
  51. package/dist/react/index.d.ts +20 -0
  52. package/dist/react/index.mjs +137 -0
  53. package/dist/replication/coordinator/etcd.d.ts +5 -3
  54. package/dist/replication/coordinator/etcd.mjs +554 -462
  55. package/dist/replication/index.d.ts +51 -105
  56. package/dist/replication/index.mjs +1415 -2061
  57. package/dist/server/index.d.ts +111 -87
  58. package/dist/server/index.mjs +1917 -489
  59. package/dist/server-options-1JHu8pid.d.ts +191 -0
  60. package/dist/{sirannon-4SspRvP5.d.ts → sirannon-DaQSyhbJ.d.ts} +7 -2
  61. package/dist/transport/grpc.d.ts +7 -4
  62. package/dist/transport/grpc.mjs +191 -97
  63. package/dist/transport/memory.d.ts +5 -134
  64. package/dist/transport/memory.mjs +3 -1
  65. package/dist/{types-BsjobKbl.d.ts → types-B7gmEsZW.d.ts} +8 -61
  66. package/dist/{types-BEu1I_9_.d.ts → types-BsVabqSI.d.ts} +1 -1
  67. package/dist/types-CL6piSnD.d.ts +43 -0
  68. package/dist/types-C_D8IhpO.d.ts +60 -0
  69. package/dist/{types-D_hQW1hr.d.ts → types-zhnRXrsb.d.ts} +55 -165
  70. package/package.json +44 -6
  71. package/dist/chunk-TKGHYWQ6.mjs +0 -35
  72. package/dist/types-D4p4UyDK.d.ts +0 -26
@@ -1,4 +1,4 @@
1
- import { e as SQLiteConnection, f as BackupScheduleOptions } from '../types-D_hQW1hr.js';
1
+ import { e as SQLiteConnection, f as BackupScheduleOptions } from '../types-zhnRXrsb.js';
2
2
 
3
3
  declare class BackupManager {
4
4
  backup(conn: SQLiteConnection, destPath: string): Promise<void>;
@@ -1,2 +1,2 @@
1
- export { BackupScheduler } from '../chunk-VLTICJOD.mjs';
2
- import '../chunk-YPYVQJ4C.mjs';
1
+ export { BackupScheduler } from '../chunk-PIKHN33N.mjs';
2
+ import '../chunk-UC3SCMIN.mjs';
@@ -0,0 +1,6 @@
1
+ interface BaselineFileOption {
2
+ version: number;
3
+ through: number;
4
+ }
5
+
6
+ export type { BaselineFileOption as B };
@@ -1,10 +1,9 @@
1
- import { e as SQLiteConnection, C as ChangeEvent } from './types-D_hQW1hr.js';
1
+ import { e as SQLiteConnection, h as ChangeEvent } from './types-zhnRXrsb.js';
2
2
 
3
3
  interface ChangeTrackerOptions {
4
4
  retention?: number;
5
5
  changesTable?: string;
6
6
  pollBatchSize?: number;
7
- replication?: boolean;
8
7
  }
9
8
 
10
9
  declare class ChangeTracker {
@@ -13,11 +12,12 @@ declare class ChangeTracker {
13
12
  private readonly retentionMs;
14
13
  private readonly changesTable;
15
14
  private readonly pollBatchSize;
16
- private readonly replication;
17
15
  private changesTableReady;
16
+ private changesTableEnsured;
18
17
  private watchedTablesCache;
19
18
  private readonly stmtCache;
20
19
  private pruneBoundary;
20
+ private lastPollAtTxBoundary;
21
21
  constructor(options?: ChangeTrackerOptions);
22
22
  watch(conn: SQLiteConnection, table: string): Promise<void>;
23
23
  unwatch(conn: SQLiteConnection, table: string): Promise<void>;
@@ -69,6 +69,7 @@ declare class ChangeTracker {
69
69
  */
70
70
  pruneDroppedTables(conn: SQLiteConnection, tables: readonly string[]): Promise<void>;
71
71
  poll(conn: SQLiteConnection): Promise<ChangeEvent[]>;
72
+ get pollEndedAtTxBoundary(): boolean;
72
73
  /** The highest seq already polled; live subscribers receive events beyond it. */
73
74
  get cursor(): bigint;
74
75
  /**
@@ -77,9 +78,9 @@ declare class ChangeTracker {
77
78
  * resuming subscriber without disturbing the shared poll cursor.
78
79
  */
79
80
  readSince(conn: SQLiteConnection, table: string, afterSeq: bigint, upToSeq: bigint, limit: number): Promise<ChangeEvent[]>;
81
+ readSinceTables(conn: SQLiteConnection, tables: readonly string[], afterSeq: bigint, upToSeq: bigint, limit: number): Promise<ChangeEvent[]>;
80
82
  /** The lowest retained seq, or `null` when the change log is empty. */
81
83
  getMinSeq(conn: SQLiteConnection): Promise<bigint | null>;
82
- private rowToEvent;
83
84
  advanceToLatest(conn: SQLiteConnection): Promise<void>;
84
85
  cleanup(conn: SQLiteConnection): Promise<number>;
85
86
  setPruneBoundary(seq: bigint): void;
@@ -89,10 +90,6 @@ declare class ChangeTracker {
89
90
  private assertIdentifier;
90
91
  private detectChangesTable;
91
92
  private ensureChangesTable;
92
- private getColumns;
93
- private getPkColumns;
94
- private dropTriggers;
95
- private getStmt;
96
93
  private installTriggers;
97
94
  }
98
95
 
@@ -1,4 +1,5 @@
1
1
  // src/core/worker/protocol.ts
2
+ var WORKER_CANCELLED_CODE = "WRITER_WORKER_CANCELLED";
2
3
  function serializeError(err) {
3
4
  if (err instanceof Error) {
4
5
  const code = err.code;
@@ -17,4 +18,4 @@ function deserializeError(error) {
17
18
  return err;
18
19
  }
19
20
 
20
- export { deserializeError, serializeError };
21
+ export { WORKER_CANCELLED_CODE, deserializeError, serializeError };
@@ -0,0 +1,18 @@
1
+ import { SirannonError } from './chunk-UC3SCMIN.mjs';
2
+
3
+ // src/core/sync/errors.ts
4
+ var ReplicationError = class extends SirannonError {
5
+ constructor(message, code = "REPLICATION_ERROR", details) {
6
+ super(message, code);
7
+ this.details = details;
8
+ this.name = "ReplicationError";
9
+ }
10
+ };
11
+ var BatchValidationError = class extends ReplicationError {
12
+ constructor(message) {
13
+ super(message, "BATCH_VALIDATION_ERROR");
14
+ this.name = "BatchValidationError";
15
+ }
16
+ };
17
+
18
+ export { BatchValidationError, ReplicationError };
@@ -0,0 +1,90 @@
1
+ import { MigrationError } from './chunk-UC3SCMIN.mjs';
2
+
3
+ // src/core/migrations/baseline.ts
4
+ var SQLITE_USER_VERSION_MAX = 2147483647;
5
+ function resolveEffectiveBaseline(sorted) {
6
+ const baselines = [];
7
+ for (const migration of sorted) {
8
+ const baseline = migration.baseline;
9
+ if (baseline === void 0) continue;
10
+ if (!Number.isSafeInteger(baseline.through) || baseline.through < 1) {
11
+ throw new MigrationError(
12
+ `Baseline migration ${migration.version}_${migration.name} has an invalid through version: ${baseline.through}`,
13
+ migration.version,
14
+ "MIGRATION_VALIDATION_ERROR"
15
+ );
16
+ }
17
+ if (baseline.through >= migration.version) {
18
+ throw new MigrationError(
19
+ `Baseline migration ${migration.version}_${migration.name} must use a version above the history it supersedes (through ${baseline.through})`,
20
+ migration.version,
21
+ "MIGRATION_VALIDATION_ERROR"
22
+ );
23
+ }
24
+ baselines.push(migration);
25
+ }
26
+ if (baselines.length === 0) return void 0;
27
+ for (const baseline of baselines) {
28
+ const through = baseline.baseline;
29
+ if (through === void 0) continue;
30
+ for (const migration of sorted) {
31
+ if (migration === baseline) continue;
32
+ if (migration.version > through.through && migration.version < baseline.version) {
33
+ throw new MigrationError(
34
+ `Migration ${migration.version}_${migration.name} falls inside baseline ${baseline.version}_${baseline.name}'s superseded range (above ${through.through}, below ${baseline.version})`,
35
+ migration.version,
36
+ "MIGRATION_VALIDATION_ERROR"
37
+ );
38
+ }
39
+ }
40
+ }
41
+ return baselines[baselines.length - 1];
42
+ }
43
+ function applyBaselineOption(migrations, baseline) {
44
+ if (baseline === void 0) return migrations;
45
+ const target = migrations.find((m) => m.version === baseline.version);
46
+ if (target === void 0) {
47
+ throw new MigrationError(
48
+ `Baseline version ${baseline.version} does not match any migration in the set`,
49
+ baseline.version,
50
+ "MIGRATION_VALIDATION_ERROR"
51
+ );
52
+ }
53
+ target.baseline = { through: baseline.through };
54
+ return migrations;
55
+ }
56
+ function planPendingMigrations(sorted, effectiveBaseline, appliedVersions) {
57
+ const baseline = effectiveBaseline?.baseline;
58
+ if (effectiveBaseline === void 0 || baseline === void 0) {
59
+ return sorted.filter((m) => !appliedVersions.has(m.version));
60
+ }
61
+ const through = baseline.through;
62
+ if (appliedVersions.size === 0) {
63
+ return [effectiveBaseline, ...sorted.filter((m) => m.baseline === void 0 && m.version > through)];
64
+ }
65
+ if (appliedVersions.has(effectiveBaseline.version)) {
66
+ return sorted.filter((m) => m.baseline === void 0 && m.version > through && !appliedVersions.has(m.version));
67
+ }
68
+ let highestApplied = 0;
69
+ for (const version of appliedVersions) {
70
+ if (version > highestApplied) highestApplied = version;
71
+ }
72
+ const pendingBelow = highestApplied >= through ? [] : sorted.filter((m) => m.baseline === void 0 && m.version <= through && !appliedVersions.has(m.version));
73
+ let highestReachable = highestApplied;
74
+ for (const migration of pendingBelow) {
75
+ if (migration.version > highestReachable) highestReachable = migration.version;
76
+ }
77
+ if (highestReachable < through) {
78
+ throw new MigrationError(
79
+ `Database history reaches version ${highestReachable} but baseline ${effectiveBaseline.version}_${effectiveBaseline.name} supersedes history through version ${through}; the migrations bridging the gap are missing from the input`,
80
+ effectiveBaseline.version,
81
+ "MIGRATION_BASELINE_GAP"
82
+ );
83
+ }
84
+ const pendingAbove = sorted.filter(
85
+ (m) => m.baseline === void 0 && m.version > through && !appliedVersions.has(m.version)
86
+ );
87
+ return [...pendingBelow, ...pendingAbove];
88
+ }
89
+
90
+ export { SQLITE_USER_VERSION_MAX, applyBaselineOption, planPendingMigrations, resolveEffectiveBaseline };
@@ -1,4 +1,4 @@
1
- import { ForbiddenSqlError } from './chunk-YPYVQJ4C.mjs';
1
+ import { ForbiddenSqlError } from './chunk-UC3SCMIN.mjs';
2
2
 
3
3
  // src/core/internal-tables.ts
4
4
  var INTERNAL_TABLE_PREFIX = "_sirannon_";
@@ -9,7 +9,10 @@ var PEER_STATE_TABLE = "_sirannon_peer_state";
9
9
  var APPLIED_CHANGES_TABLE = "_sirannon_applied_changes";
10
10
  var COLUMN_VERSIONS_TABLE = "_sirannon_column_versions";
11
11
  var SYNC_STATE_TABLE = "_sirannon_sync_state";
12
+ var DEVICE_CURSORS_TABLE = "_sirannon_device_cursors";
13
+ var STAGED_CHANGES_TABLE = "_sirannon_staged_changes";
12
14
  var CDC_TRIGGER_PREFIX = "_sirannon_trg_";
15
+ var LIVE_PROBE_TABLE_PREFIX = "_sirannon_live_probe_";
13
16
  var SIRANNON_PREFIX = "_sirannon";
14
17
  var SQLITE_PREFIX = "sqlite_";
15
18
  var SIRANNON_MESSAGE = "Access to internal tables is not permitted: identifiers beginning with '_sirannon' are reserved";
@@ -265,4 +268,4 @@ function decodeHexBytes(hex) {
265
268
  return bytes;
266
269
  }
267
270
 
268
- export { APPLIED_CHANGES_TABLE, CDC_TRIGGER_PREFIX, CHANGES_TABLE, COLUMN_VERSIONS_TABLE, INTERNAL_TABLE_PREFIX, META_TABLE, MIGRATIONS_TABLE, PEER_STATE_TABLE, SAFE_INT_BOUND_TEXT, SYNC_STATE_TABLE, assertSqlAllowed, decodeTaggedValues, encodeTaggedValues, encodeWireRowsInPlace, isReservedIdentifier };
271
+ export { APPLIED_CHANGES_TABLE, CDC_TRIGGER_PREFIX, CHANGES_TABLE, COLUMN_VERSIONS_TABLE, DEVICE_CURSORS_TABLE, INTERNAL_TABLE_PREFIX, LIVE_PROBE_TABLE_PREFIX, META_TABLE, MIGRATIONS_TABLE, PEER_STATE_TABLE, SAFE_INT_BOUND_TEXT, STAGED_CHANGES_TABLE, SYNC_STATE_TABLE, assertSqlAllowed, decodeTaggedValues, encodeTaggedValues, encodeWireRowsInPlace, isReservedIdentifier };
@@ -1,6 +1,6 @@
1
- import { deserializeError } from './chunk-DJLX6CAE.mjs';
2
- import { BackupManager, BackupScheduler } from './chunk-VLTICJOD.mjs';
3
- import { SirannonError } from './chunk-YPYVQJ4C.mjs';
1
+ import { BackupManager, BackupScheduler } from './chunk-PIKHN33N.mjs';
2
+ import { WORKER_CANCELLED_CODE, deserializeError } from './chunk-4ISB7XMA.mjs';
3
+ import { SirannonError } from './chunk-UC3SCMIN.mjs';
4
4
  import { Worker } from 'worker_threads';
5
5
  import { existsSync } from 'fs';
6
6
  import { resolve, dirname, join, sep } from 'path';
@@ -142,24 +142,65 @@ var WriterWorker = class _WriterWorker {
142
142
  const entry = this.pending.get(res.id);
143
143
  if (!entry) return;
144
144
  this.pending.delete(res.id);
145
- if (entry.timer) clearTimeout(entry.timer);
146
- if (res.ok) entry.resolve(res.value);
147
- else entry.reject(deserializeError(res.error));
145
+ clearPendingTimers(entry);
146
+ if (res.ok) {
147
+ entry.resolve(res.value);
148
+ return;
149
+ }
150
+ if (res.error.code === WORKER_CANCELLED_CODE) {
151
+ entry.reject(
152
+ new SirannonError(
153
+ `The writer worker could not take this operation within ${this.timeoutMs}ms; it was not applied and is safe to retry`,
154
+ "WRITE_OVERLOADED"
155
+ )
156
+ );
157
+ return;
158
+ }
159
+ entry.reject(deserializeError(res.error));
148
160
  }
149
161
  rejectPending(id, err) {
150
162
  const entry = this.pending.get(id);
151
163
  if (!entry) return;
152
164
  this.pending.delete(id);
153
- if (entry.timer) clearTimeout(entry.timer);
165
+ clearPendingTimers(entry);
154
166
  entry.reject(err);
155
167
  }
168
+ unresponsiveError(waitedMs) {
169
+ return new SirannonError(
170
+ `Writer worker did not respond within ${waitedMs}ms; the operation's outcome is unknown`,
171
+ "WRITER_WORKER_TIMEOUT"
172
+ );
173
+ }
174
+ // On the deadline the host cancels the operation, which drops work the
175
+ // worker has not started, then allows one further timeout as a grace window.
176
+ // An operation still running when that window closes is rejected as
177
+ // indeterminate, because the write may or may not have reached the disk.
178
+ onDeadline(id) {
179
+ const entry = this.pending.get(id);
180
+ if (!entry) return;
181
+ const worker = this.worker;
182
+ if (!entry.cancellable || !worker) {
183
+ this.rejectPending(id, this.unresponsiveError(this.timeoutMs));
184
+ return;
185
+ }
186
+ try {
187
+ worker.postMessage({ kind: "cancel", id });
188
+ } catch {
189
+ this.rejectPending(id, this.unresponsiveError(this.timeoutMs));
190
+ return;
191
+ }
192
+ entry.graceTimer = setTimeout(() => {
193
+ this.rejectPending(id, this.unresponsiveError(this.timeoutMs * 2));
194
+ }, this.timeoutMs);
195
+ entry.graceTimer.unref?.();
196
+ }
156
197
  fault(errLike) {
157
198
  if (this.closed || this.fatal) return;
158
199
  const err = errLike instanceof Error ? errLike : new SirannonError(String(errLike), "WRITER_WORKER_ERROR");
159
200
  const dead = this.worker;
160
201
  this.worker = null;
161
202
  for (const entry of this.pending.values()) {
162
- if (entry.timer) clearTimeout(entry.timer);
203
+ clearPendingTimers(entry);
163
204
  entry.reject(err);
164
205
  }
165
206
  this.pending.clear();
@@ -197,18 +238,11 @@ var WriterWorker = class _WriterWorker {
197
238
  return new Promise((resolve2, reject) => {
198
239
  let timer = null;
199
240
  if (this.timeoutMs > 0) {
200
- timer = setTimeout(() => {
201
- this.rejectPending(
202
- id,
203
- new SirannonError(
204
- `Writer worker did not respond within ${this.timeoutMs}ms; the operation's outcome is unknown`,
205
- "WRITER_WORKER_TIMEOUT"
206
- )
207
- );
208
- }, this.timeoutMs);
241
+ timer = setTimeout(() => this.onDeadline(id), this.timeoutMs);
209
242
  timer.unref?.();
210
243
  }
211
- this.pending.set(id, { resolve: resolve2, reject, timer });
244
+ const cancellable = request.kind !== "open" && request.kind !== "close";
245
+ this.pending.set(id, { resolve: resolve2, reject, timer, graceTimer: null, cancellable });
212
246
  try {
213
247
  worker.postMessage(message);
214
248
  } catch (err) {
@@ -247,7 +281,8 @@ var WriterWorker = class _WriterWorker {
247
281
  units: units.map((unit) => ({
248
282
  statements: unit.statements.map((statement) => ({
249
283
  sql: statement.sql,
250
- params: statement.params ? [...statement.params] : []
284
+ params: statement.params ? [...statement.params] : [],
285
+ ...statement.trusted === true ? { trusted: true } : {}
251
286
  }))
252
287
  }))
253
288
  }),
@@ -289,12 +324,16 @@ var WriterWorker = class _WriterWorker {
289
324
  }
290
325
  this.worker = null;
291
326
  for (const entry of this.pending.values()) {
292
- if (entry.timer) clearTimeout(entry.timer);
327
+ clearPendingTimers(entry);
293
328
  entry.reject(new SirannonError("Writer worker is closed", "WRITER_WORKER_CLOSED"));
294
329
  }
295
330
  this.pending.clear();
296
331
  }
297
332
  };
333
+ function clearPendingTimers(entry) {
334
+ if (entry.timer) clearTimeout(entry.timer);
335
+ if (entry.graceTimer) clearTimeout(entry.graceTimer);
336
+ }
298
337
  function nodeWriterContext() {
299
338
  const held = new AsyncLocalStorage();
300
339
  return {
@@ -1,4 +1,4 @@
1
- import { SirannonError } from './chunk-YPYVQJ4C.mjs';
1
+ import { SirannonError } from './chunk-UC3SCMIN.mjs';
2
2
 
3
3
  // src/core/driver/define.ts
4
4
  function defineDriver(config) {
@@ -0,0 +1,130 @@
1
+ // src/core/sync/sha256.ts
2
+ var K = new Uint32Array([
3
+ 1116352408,
4
+ 1899447441,
5
+ 3049323471,
6
+ 3921009573,
7
+ 961987163,
8
+ 1508970993,
9
+ 2453635748,
10
+ 2870763221,
11
+ 3624381080,
12
+ 310598401,
13
+ 607225278,
14
+ 1426881987,
15
+ 1925078388,
16
+ 2162078206,
17
+ 2614888103,
18
+ 3248222580,
19
+ 3835390401,
20
+ 4022224774,
21
+ 264347078,
22
+ 604807628,
23
+ 770255983,
24
+ 1249150122,
25
+ 1555081692,
26
+ 1996064986,
27
+ 2554220882,
28
+ 2821834349,
29
+ 2952996808,
30
+ 3210313671,
31
+ 3336571891,
32
+ 3584528711,
33
+ 113926993,
34
+ 338241895,
35
+ 666307205,
36
+ 773529912,
37
+ 1294757372,
38
+ 1396182291,
39
+ 1695183700,
40
+ 1986661051,
41
+ 2177026350,
42
+ 2456956037,
43
+ 2730485921,
44
+ 2820302411,
45
+ 3259730800,
46
+ 3345764771,
47
+ 3516065817,
48
+ 3600352804,
49
+ 4094571909,
50
+ 275423344,
51
+ 430227734,
52
+ 506948616,
53
+ 659060556,
54
+ 883997877,
55
+ 958139571,
56
+ 1322822218,
57
+ 1537002063,
58
+ 1747873779,
59
+ 1955562222,
60
+ 2024104815,
61
+ 2227730452,
62
+ 2361852424,
63
+ 2428436474,
64
+ 2756734187,
65
+ 3204031479,
66
+ 3329325298
67
+ ]);
68
+ function rotr(x, n) {
69
+ return x >>> n | x << 32 - n;
70
+ }
71
+ function sha256Hex(input) {
72
+ const data = new TextEncoder().encode(input);
73
+ const bitLength = data.length * 8;
74
+ const paddedLength = (data.length + 8 >> 6) + 1 << 6;
75
+ const padded = new Uint8Array(paddedLength);
76
+ padded.set(data);
77
+ padded[data.length] = 128;
78
+ const view = new DataView(padded.buffer);
79
+ view.setUint32(paddedLength - 8, Math.floor(bitLength / 4294967296), false);
80
+ view.setUint32(paddedLength - 4, bitLength >>> 0, false);
81
+ const state = new Uint32Array([
82
+ 1779033703,
83
+ 3144134277,
84
+ 1013904242,
85
+ 2773480762,
86
+ 1359893119,
87
+ 2600822924,
88
+ 528734635,
89
+ 1541459225
90
+ ]);
91
+ const w = new Uint32Array(64);
92
+ for (let offset = 0; offset < paddedLength; offset += 64) {
93
+ for (let i = 0; i < 16; i++) {
94
+ w[i] = view.getUint32(offset + i * 4, false);
95
+ }
96
+ for (let i = 16; i < 64; i++) {
97
+ const s0 = rotr(w[i - 15], 7) ^ rotr(w[i - 15], 18) ^ w[i - 15] >>> 3;
98
+ const s1 = rotr(w[i - 2], 17) ^ rotr(w[i - 2], 19) ^ w[i - 2] >>> 10;
99
+ w[i] = w[i - 16] + s0 + w[i - 7] + s1 >>> 0;
100
+ }
101
+ let [a, b, c, d, e, f, g, h] = state;
102
+ for (let i = 0; i < 64; i++) {
103
+ const s1 = rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25);
104
+ const ch = e & f ^ ~e & g;
105
+ const temp1 = h + s1 + ch + K[i] + w[i] >>> 0;
106
+ const s0 = rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22);
107
+ const maj = a & b ^ a & c ^ b & c;
108
+ const temp2 = s0 + maj >>> 0;
109
+ h = g;
110
+ g = f;
111
+ f = e;
112
+ e = d + temp1 >>> 0;
113
+ d = c;
114
+ c = b;
115
+ b = a;
116
+ a = temp1 + temp2 >>> 0;
117
+ }
118
+ state[0] = state[0] + a >>> 0;
119
+ state[1] = state[1] + b >>> 0;
120
+ state[2] = state[2] + c >>> 0;
121
+ state[3] = state[3] + d >>> 0;
122
+ state[4] = state[4] + e >>> 0;
123
+ state[5] = state[5] + f >>> 0;
124
+ state[6] = state[6] + g >>> 0;
125
+ state[7] = state[7] + h >>> 0;
126
+ }
127
+ return Array.from(state, (word) => word.toString(16).padStart(8, "0")).join("");
128
+ }
129
+
130
+ export { sha256Hex };