@breeztech/breez-sdk-spark 0.14.0 → 0.15.1

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 (37) hide show
  1. package/breez-sdk-spark.tgz +0 -0
  2. package/bundler/breez_sdk_spark_wasm.d.ts +114 -40
  3. package/bundler/breez_sdk_spark_wasm.js +1 -1
  4. package/bundler/breez_sdk_spark_wasm_bg.js +118 -104
  5. package/bundler/breez_sdk_spark_wasm_bg.wasm +0 -0
  6. package/bundler/breez_sdk_spark_wasm_bg.wasm.d.ts +12 -11
  7. package/deno/breez_sdk_spark_wasm.d.ts +114 -40
  8. package/deno/breez_sdk_spark_wasm.js +118 -104
  9. package/deno/breez_sdk_spark_wasm_bg.wasm +0 -0
  10. package/deno/breez_sdk_spark_wasm_bg.wasm.d.ts +12 -11
  11. package/nodejs/breez_sdk_spark_wasm.d.ts +114 -40
  12. package/nodejs/breez_sdk_spark_wasm.js +121 -106
  13. package/nodejs/breez_sdk_spark_wasm_bg.wasm +0 -0
  14. package/nodejs/breez_sdk_spark_wasm_bg.wasm.d.ts +12 -11
  15. package/nodejs/index.mjs +3 -2
  16. package/nodejs/mysql-session-manager/index.cjs +26 -8
  17. package/nodejs/mysql-session-manager/migrations.cjs +40 -3
  18. package/nodejs/mysql-storage/index.cjs +67 -48
  19. package/nodejs/mysql-storage/migrations.cjs +220 -85
  20. package/nodejs/mysql-token-store/index.cjs +133 -68
  21. package/nodejs/mysql-token-store/migrations.cjs +309 -80
  22. package/nodejs/mysql-tree-store/index.cjs +76 -41
  23. package/nodejs/mysql-tree-store/migrations.cjs +254 -71
  24. package/nodejs/postgres-session-manager/index.cjs +27 -9
  25. package/nodejs/postgres-session-manager/migrations.cjs +45 -6
  26. package/nodejs/postgres-storage/index.cjs +81 -62
  27. package/nodejs/postgres-storage/migrations.cjs +207 -79
  28. package/nodejs/postgres-token-store/index.cjs +111 -67
  29. package/nodejs/postgres-token-store/migrations.cjs +153 -61
  30. package/nodejs/postgres-tree-store/index.cjs +60 -42
  31. package/nodejs/postgres-tree-store/migrations.cjs +130 -46
  32. package/package.json +1 -1
  33. package/ssr/index.js +14 -9
  34. package/web/breez_sdk_spark_wasm.d.ts +126 -51
  35. package/web/breez_sdk_spark_wasm.js +118 -104
  36. package/web/breez_sdk_spark_wasm_bg.wasm +0 -0
  37. package/web/breez_sdk_spark_wasm_bg.wasm.d.ts +12 -11
@@ -64,7 +64,7 @@ class PostgresTokenStore {
64
64
  * identifying the tenant. All reads and writes are scoped by this.
65
65
  * @param {object} [logger]
66
66
  */
67
- constructor(pool, identity, logger = null) {
67
+ constructor(pool, identity, logger = null, runMigration = true) {
68
68
  if (!identity || identity.length !== 33) {
69
69
  throw new TokenStoreError(
70
70
  "tenant identity (33-byte secp256k1 pubkey) is required"
@@ -74,6 +74,7 @@ class PostgresTokenStore {
74
74
  this.identity = Buffer.from(identity);
75
75
  this.lockKey = _identityLockKey(TOKEN_STORE_LOCK_PREFIX, identity);
76
76
  this.logger = logger;
77
+ this.runMigration = runMigration;
77
78
  }
78
79
 
79
80
  /**
@@ -81,8 +82,10 @@ class PostgresTokenStore {
81
82
  */
82
83
  async initialize() {
83
84
  try {
84
- const migrationManager = new TokenStoreMigrationManager(this.logger);
85
- await migrationManager.migrate(this.pool, this.identity);
85
+ if (this.runMigration) {
86
+ const migrationManager = new TokenStoreMigrationManager(this.logger);
87
+ await migrationManager.migrate(this.pool, this.identity);
88
+ }
86
89
  return this;
87
90
  } catch (error) {
88
91
  throw new TokenStoreError(
@@ -176,12 +179,12 @@ class PostgresTokenStore {
176
179
  const swapCheckResult = await client.query(
177
180
  `SELECT
178
181
  EXISTS(
179
- SELECT 1 FROM token_reservations
182
+ SELECT 1 FROM brz_token_reservations
180
183
  WHERE user_id = $1 AND purpose = 'Swap'
181
184
  ) AS has_active_swap,
182
185
  COALESCE(
183
186
  (SELECT last_completed_at >= $2
184
- FROM token_swap_status WHERE user_id = $1),
187
+ FROM brz_token_swap_status WHERE user_id = $1),
185
188
  FALSE
186
189
  ) AS swap_completed`,
187
190
  [this.identity, refreshTimestamp]
@@ -194,20 +197,20 @@ class PostgresTokenStore {
194
197
  // Clean up old spent markers
195
198
  const cleanupCutoff = new Date(refreshTimestamp.getTime() - SPENT_MARKER_CLEANUP_THRESHOLD_MS);
196
199
  await client.query(
197
- "DELETE FROM token_spent_outputs WHERE user_id = $1 AND spent_at < $2",
200
+ "DELETE FROM brz_token_spent_outputs WHERE user_id = $1 AND spent_at < $2",
198
201
  [this.identity, cleanupCutoff]
199
202
  );
200
203
 
201
204
  // Get recent spent output IDs (spent_at >= refresh_timestamp)
202
205
  const spentResult = await client.query(
203
- "SELECT output_id FROM token_spent_outputs WHERE user_id = $1 AND spent_at >= $2",
206
+ "SELECT output_id FROM brz_token_spent_outputs WHERE user_id = $1 AND spent_at >= $2",
204
207
  [this.identity, refreshTimestamp]
205
208
  );
206
209
  const spentIds = new Set(spentResult.rows.map((r) => r.output_id));
207
210
 
208
211
  // Delete non-reserved outputs added BEFORE the refresh started
209
212
  await client.query(
210
- "DELETE FROM token_outputs WHERE user_id = $1 AND reservation_id IS NULL AND added_at < $2",
213
+ "DELETE FROM brz_token_outputs WHERE user_id = $1 AND reservation_id IS NULL AND added_at < $2",
211
214
  [this.identity, refreshTimestamp]
212
215
  );
213
216
 
@@ -222,8 +225,8 @@ class PostgresTokenStore {
222
225
  // Reconcile reservations: find reserved outputs that no longer exist
223
226
  const reservedRows = await client.query(
224
227
  `SELECT r.id, o.id AS output_id
225
- FROM token_reservations r
226
- JOIN token_outputs o
228
+ FROM brz_token_reservations r
229
+ JOIN brz_token_outputs o
227
230
  ON o.reservation_id = r.id AND o.user_id = r.user_id
228
231
  WHERE r.user_id = $1`,
229
232
  [this.identity]
@@ -257,11 +260,11 @@ class PostgresTokenStore {
257
260
  // Delete outputs whose reservations are being removed entirely
258
261
  if (reservationsToDelete.length > 0) {
259
262
  await client.query(
260
- "DELETE FROM token_outputs WHERE user_id = $1 AND reservation_id = ANY($2)",
263
+ "DELETE FROM brz_token_outputs WHERE user_id = $1 AND reservation_id = ANY($2)",
261
264
  [this.identity, reservationsToDelete]
262
265
  );
263
266
  await client.query(
264
- "DELETE FROM token_reservations WHERE user_id = $1 AND id = ANY($2)",
267
+ "DELETE FROM brz_token_reservations WHERE user_id = $1 AND id = ANY($2)",
265
268
  [this.identity, reservationsToDelete]
266
269
  );
267
270
  }
@@ -269,14 +272,14 @@ class PostgresTokenStore {
269
272
  // Delete individual reserved outputs that no longer exist
270
273
  if (outputsToRemoveFromReservation.length > 0) {
271
274
  await client.query(
272
- "DELETE FROM token_outputs WHERE user_id = $1 AND id = ANY($2)",
275
+ "DELETE FROM brz_token_outputs WHERE user_id = $1 AND id = ANY($2)",
273
276
  [this.identity, outputsToRemoveFromReservation]
274
277
  );
275
278
 
276
279
  // Check if any reservations are now empty
277
280
  const emptyReservations = await client.query(
278
- `SELECT r.id FROM token_reservations r
279
- LEFT JOIN token_outputs o
281
+ `SELECT r.id FROM brz_token_reservations r
282
+ LEFT JOIN brz_token_outputs o
280
283
  ON o.reservation_id = r.id AND o.user_id = r.user_id
281
284
  WHERE r.user_id = $1 AND o.id IS NULL`,
282
285
  [this.identity]
@@ -284,7 +287,7 @@ class PostgresTokenStore {
284
287
  const emptyIds = emptyReservations.rows.map((r) => r.id);
285
288
  if (emptyIds.length > 0) {
286
289
  await client.query(
287
- "DELETE FROM token_reservations WHERE user_id = $1 AND id = ANY($2)",
290
+ "DELETE FROM brz_token_reservations WHERE user_id = $1 AND id = ANY($2)",
288
291
  [this.identity, emptyIds]
289
292
  );
290
293
  }
@@ -292,7 +295,7 @@ class PostgresTokenStore {
292
295
 
293
296
  // Collect IDs of currently reserved outputs (that survived reconciliation)
294
297
  const reservedOutputIdsResult = await client.query(
295
- "SELECT id FROM token_outputs WHERE user_id = $1 AND reservation_id IS NOT NULL",
298
+ "SELECT id FROM brz_token_outputs WHERE user_id = $1 AND reservation_id IS NOT NULL",
296
299
  [this.identity]
297
300
  );
298
301
  const reservedOutputIds = new Set(
@@ -301,11 +304,11 @@ class PostgresTokenStore {
301
304
 
302
305
  // Delete orphan metadata (per-tenant)
303
306
  await client.query(
304
- `DELETE FROM token_metadata
307
+ `DELETE FROM brz_token_metadata
305
308
  WHERE user_id = $1
306
309
  AND identifier NOT IN (
307
310
  SELECT DISTINCT token_identifier
308
- FROM token_outputs WHERE user_id = $1
311
+ FROM brz_token_outputs WHERE user_id = $1
309
312
  )`,
310
313
  [this.identity]
311
314
  );
@@ -359,10 +362,10 @@ class PostgresTokenStore {
359
362
  ELSE 0
360
363
  END
361
364
  ), 0)::text AS balance
362
- FROM token_metadata m
363
- JOIN token_outputs o
365
+ FROM brz_token_metadata m
366
+ JOIN brz_token_outputs o
364
367
  ON o.token_identifier = m.identifier AND o.user_id = m.user_id
365
- LEFT JOIN token_reservations r
368
+ LEFT JOIN brz_token_reservations r
366
369
  ON o.reservation_id = r.id AND o.user_id = r.user_id
367
370
  WHERE m.user_id = $1
368
371
  GROUP BY m.identifier, m.issuer_public_key, m.name, m.ticker,
@@ -401,10 +404,10 @@ class PostgresTokenStore {
401
404
  o.token_public_key, o.token_amount, o.token_identifier,
402
405
  o.prev_tx_hash, o.prev_tx_vout, o.reservation_id,
403
406
  r.purpose
404
- FROM token_metadata m
405
- LEFT JOIN token_outputs o
407
+ FROM brz_token_metadata m
408
+ LEFT JOIN brz_token_outputs o
406
409
  ON o.token_identifier = m.identifier AND o.user_id = m.user_id
407
- LEFT JOIN token_reservations r
410
+ LEFT JOIN brz_token_reservations r
408
411
  ON o.reservation_id = r.id AND o.user_id = r.user_id
409
412
  WHERE m.user_id = $1
410
413
  ORDER BY m.identifier, o.token_amount::NUMERIC ASC`,
@@ -478,10 +481,10 @@ class PostgresTokenStore {
478
481
  o.token_public_key, o.token_amount, o.token_identifier,
479
482
  o.prev_tx_hash, o.prev_tx_vout, o.reservation_id,
480
483
  r.purpose
481
- FROM token_metadata m
482
- LEFT JOIN token_outputs o
484
+ FROM brz_token_metadata m
485
+ LEFT JOIN brz_token_outputs o
483
486
  ON o.token_identifier = m.identifier AND o.user_id = m.user_id
484
- LEFT JOIN token_reservations r
487
+ LEFT JOIN brz_token_reservations r
485
488
  ON o.reservation_id = r.id AND o.user_id = r.user_id
486
489
  WHERE m.user_id = $2 AND ${whereClause}
487
490
  ORDER BY o.token_amount::NUMERIC ASC`,
@@ -530,31 +533,57 @@ class PostgresTokenStore {
530
533
  * Insert token outputs (upsert metadata, insert outputs with ON CONFLICT DO NOTHING).
531
534
  * @param {{metadata: Object, outputs: Array}} tokenOutputs
532
535
  */
533
- async insertTokenOutputs(tokenOutputs) {
536
+ /**
537
+ * Atomically remove spent outputs and insert new outputs.
538
+ * @param {Array<[string, number]>} outputsToRemove - Array of [prevTxHash, prevTxVout] tuples
539
+ * @param {Object|null} outputsToAdd - Token outputs to insert (with metadata)
540
+ * @returns {Promise<void>}
541
+ */
542
+ async updateTokenOutputs(outputsToRemove, outputsToAdd) {
534
543
  try {
535
544
  await this._withTransaction(async (client) => {
536
- await this._upsertMetadata(client, tokenOutputs.metadata);
537
-
538
- const outputIds = tokenOutputs.outputs.map((o) => o.output.id);
539
- if (outputIds.length > 0) {
540
- await client.query(
541
- "DELETE FROM token_spent_outputs WHERE user_id = $1 AND output_id = ANY($2)",
542
- [this.identity, outputIds]
543
- );
545
+ // 1. Remove spent outputs and mark as spent.
546
+ if (outputsToRemove && outputsToRemove.length > 0) {
547
+ for (const [txHash, vout] of outputsToRemove) {
548
+ const result = await client.query(
549
+ "DELETE FROM brz_token_outputs WHERE user_id = $1 AND prev_tx_hash = $2 AND prev_tx_vout = $3 RETURNING id",
550
+ [this.identity, txHash, vout]
551
+ );
552
+ if (result.rows.length > 0) {
553
+ const outputId = result.rows[0].id;
554
+ await client.query(
555
+ "INSERT INTO brz_token_spent_outputs (user_id, output_id, spent_at) VALUES ($1, $2, NOW()) ON CONFLICT DO NOTHING",
556
+ [this.identity, outputId]
557
+ );
558
+ }
559
+ }
544
560
  }
545
561
 
546
- for (const output of tokenOutputs.outputs) {
547
- await this._insertSingleOutput(
548
- client,
549
- tokenOutputs.metadata.identifier,
550
- output
551
- );
562
+ // 2. Insert new outputs.
563
+ if (outputsToAdd) {
564
+ await this._upsertMetadata(client, outputsToAdd.metadata);
565
+
566
+ const outputIds = outputsToAdd.outputs.map((o) => o.output.id);
567
+ if (outputIds.length > 0) {
568
+ await client.query(
569
+ "DELETE FROM brz_token_spent_outputs WHERE user_id = $1 AND output_id = ANY($2)",
570
+ [this.identity, outputIds]
571
+ );
572
+ }
573
+
574
+ for (const output of outputsToAdd.outputs) {
575
+ await this._insertSingleOutput(
576
+ client,
577
+ outputsToAdd.metadata.identifier,
578
+ output
579
+ );
580
+ }
552
581
  }
553
582
  });
554
583
  } catch (error) {
555
584
  if (error instanceof TokenStoreError) throw error;
556
585
  throw new TokenStoreError(
557
- `Failed to insert token outputs: ${error.message}`,
586
+ `Failed to update token outputs: ${error.message}`,
558
587
  error
559
588
  );
560
589
  }
@@ -592,7 +621,7 @@ class PostgresTokenStore {
592
621
 
593
622
  // Get metadata
594
623
  const metadataResult = await client.query(
595
- "SELECT * FROM token_metadata WHERE user_id = $1 AND identifier = $2",
624
+ "SELECT * FROM brz_token_metadata WHERE user_id = $1 AND identifier = $2",
596
625
  [this.identity, tokenIdentifier]
597
626
  );
598
627
 
@@ -610,7 +639,7 @@ class PostgresTokenStore {
610
639
  o.withdraw_bond_sats, o.withdraw_relative_block_locktime,
611
640
  o.token_public_key, o.token_amount, o.token_identifier,
612
641
  o.prev_tx_hash, o.prev_tx_vout
613
- FROM token_outputs o
642
+ FROM brz_token_outputs o
614
643
  WHERE o.user_id = $1
615
644
  AND o.token_identifier = $2
616
645
  AND o.reservation_id IS NULL`,
@@ -700,7 +729,7 @@ class PostgresTokenStore {
700
729
  const reservationId = this._generateId();
701
730
 
702
731
  await client.query(
703
- "INSERT INTO token_reservations (user_id, id, purpose) VALUES ($1, $2, $3)",
732
+ "INSERT INTO brz_token_reservations (user_id, id, purpose) VALUES ($1, $2, $3)",
704
733
  [this.identity, reservationId, purpose]
705
734
  );
706
735
 
@@ -708,7 +737,7 @@ class PostgresTokenStore {
708
737
  const selectedIds = selectedOutputs.map((o) => o.output.id);
709
738
  if (selectedIds.length > 0) {
710
739
  await client.query(
711
- "UPDATE token_outputs SET reservation_id = $1 WHERE user_id = $3 AND id = ANY($2)",
740
+ "UPDATE brz_token_outputs SET reservation_id = $1 WHERE user_id = $3 AND id = ANY($2)",
712
741
  [reservationId, selectedIds, this.identity]
713
742
  );
714
743
  }
@@ -741,13 +770,13 @@ class PostgresTokenStore {
741
770
  // ACTION (column-list SET NULL is PG15+ and a whole-row SET NULL would
742
771
  // null user_id, which is NOT NULL).
743
772
  await client.query(
744
- "UPDATE token_outputs SET reservation_id = NULL WHERE user_id = $1 AND reservation_id = $2",
773
+ "UPDATE brz_token_outputs SET reservation_id = NULL WHERE user_id = $1 AND reservation_id = $2",
745
774
  [this.identity, id]
746
775
  );
747
776
 
748
777
  // Delete the reservation
749
778
  await client.query(
750
- "DELETE FROM token_reservations WHERE user_id = $1 AND id = $2",
779
+ "DELETE FROM brz_token_reservations WHERE user_id = $1 AND id = $2",
751
780
  [this.identity, id]
752
781
  );
753
782
  });
@@ -768,12 +797,12 @@ class PostgresTokenStore {
768
797
  try {
769
798
  // _withWriteTransaction acquires the advisory lock so this serializes
770
799
  // against `setTokensOutputs`. Without it, a concurrent setTokensOutputs
771
- // could read token_spent_outputs before our marker commits and re-insert
800
+ // could read brz_token_spent_outputs before our marker commits and re-insert
772
801
  // the just-spent output as Available.
773
802
  await this._withWriteTransaction(async (client) => {
774
803
  // Get reservation purpose
775
804
  const reservationResult = await client.query(
776
- "SELECT purpose FROM token_reservations WHERE user_id = $1 AND id = $2",
805
+ "SELECT purpose FROM brz_token_reservations WHERE user_id = $1 AND id = $2",
777
806
  [this.identity, id]
778
807
  );
779
808
  if (reservationResult.rows.length === 0) {
@@ -783,14 +812,14 @@ class PostgresTokenStore {
783
812
 
784
813
  // Get reserved output IDs and mark them as spent
785
814
  const reservedOutputsResult = await client.query(
786
- "SELECT id FROM token_outputs WHERE user_id = $1 AND reservation_id = $2",
815
+ "SELECT id FROM brz_token_outputs WHERE user_id = $1 AND reservation_id = $2",
787
816
  [this.identity, id]
788
817
  );
789
818
  const reservedOutputIds = reservedOutputsResult.rows.map((r) => r.id);
790
819
 
791
820
  if (reservedOutputIds.length > 0) {
792
821
  await client.query(
793
- `INSERT INTO token_spent_outputs (user_id, output_id)
822
+ `INSERT INTO brz_token_spent_outputs (user_id, output_id)
794
823
  SELECT $2, output_id FROM UNNEST($1::text[]) AS t(output_id)
795
824
  ON CONFLICT DO NOTHING`,
796
825
  [reservedOutputIds, this.identity]
@@ -799,13 +828,13 @@ class PostgresTokenStore {
799
828
 
800
829
  // Delete reserved outputs
801
830
  await client.query(
802
- "DELETE FROM token_outputs WHERE user_id = $1 AND reservation_id = $2",
831
+ "DELETE FROM brz_token_outputs WHERE user_id = $1 AND reservation_id = $2",
803
832
  [this.identity, id]
804
833
  );
805
834
 
806
835
  // Delete the reservation
807
836
  await client.query(
808
- "DELETE FROM token_reservations WHERE user_id = $1 AND id = $2",
837
+ "DELETE FROM brz_token_reservations WHERE user_id = $1 AND id = $2",
809
838
  [this.identity, id]
810
839
  );
811
840
 
@@ -813,7 +842,7 @@ class PostgresTokenStore {
813
842
  // tenant that joined after migration 2 (and thus has no row) gets one.
814
843
  if (isSwap) {
815
844
  await client.query(
816
- `INSERT INTO token_swap_status (user_id, last_completed_at)
845
+ `INSERT INTO brz_token_swap_status (user_id, last_completed_at)
817
846
  VALUES ($1, NOW())
818
847
  ON CONFLICT (user_id) DO UPDATE
819
848
  SET last_completed_at = EXCLUDED.last_completed_at`,
@@ -823,11 +852,11 @@ class PostgresTokenStore {
823
852
 
824
853
  // Clean up orphaned metadata (per-tenant)
825
854
  await client.query(
826
- `DELETE FROM token_metadata
855
+ `DELETE FROM brz_token_metadata
827
856
  WHERE user_id = $1
828
857
  AND identifier NOT IN (
829
858
  SELECT DISTINCT token_identifier
830
- FROM token_outputs WHERE user_id = $1
859
+ FROM brz_token_outputs WHERE user_id = $1
831
860
  )`,
832
861
  [this.identity]
833
862
  );
@@ -882,17 +911,17 @@ class PostgresTokenStore {
882
911
  */
883
912
  async _cleanupStaleReservations(client) {
884
913
  await client.query(
885
- `UPDATE token_outputs SET reservation_id = NULL
914
+ `UPDATE brz_token_outputs SET reservation_id = NULL
886
915
  WHERE user_id = $2
887
916
  AND reservation_id IN (
888
- SELECT id FROM token_reservations
917
+ SELECT id FROM brz_token_reservations
889
918
  WHERE user_id = $2
890
919
  AND created_at < NOW() - make_interval(secs => $1)
891
920
  )`,
892
921
  [RESERVATION_TIMEOUT_SECS, this.identity]
893
922
  );
894
923
  await client.query(
895
- `DELETE FROM token_reservations
924
+ `DELETE FROM brz_token_reservations
896
925
  WHERE user_id = $2
897
926
  AND created_at < NOW() - make_interval(secs => $1)`,
898
927
  [RESERVATION_TIMEOUT_SECS, this.identity]
@@ -904,7 +933,7 @@ class PostgresTokenStore {
904
933
  */
905
934
  async _upsertMetadata(client, metadata) {
906
935
  await client.query(
907
- `INSERT INTO token_metadata
936
+ `INSERT INTO brz_token_metadata
908
937
  (user_id, identifier, issuer_public_key, name, ticker, decimals, max_supply,
909
938
  is_freezable, creation_entity_public_key)
910
939
  VALUES ($9, $1, $2, $3, $4, $5, $6, $7, $8)
@@ -935,7 +964,7 @@ class PostgresTokenStore {
935
964
  */
936
965
  async _insertSingleOutput(client, tokenIdentifier, output) {
937
966
  await client.query(
938
- `INSERT INTO token_outputs
967
+ `INSERT INTO brz_token_outputs
939
968
  (user_id, id, token_identifier, owner_public_key, revocation_commitment,
940
969
  withdraw_bond_sats, withdraw_relative_block_locktime,
941
970
  token_public_key, token_amount, prev_tx_hash, prev_tx_vout, added_at)
@@ -1015,7 +1044,12 @@ async function createPostgresTokenStore(config, identity, logger = null) {
1015
1044
  connectionTimeoutMillis: config.createTimeoutSecs * 1000,
1016
1045
  idleTimeoutMillis: config.recycleTimeoutSecs * 1000,
1017
1046
  });
1018
- return createPostgresTokenStoreWithPool(pool, identity, logger);
1047
+ return createPostgresTokenStoreWithPool(
1048
+ pool,
1049
+ identity,
1050
+ logger,
1051
+ config.runMigration !== false
1052
+ );
1019
1053
  }
1020
1054
 
1021
1055
  /**
@@ -1026,8 +1060,18 @@ async function createPostgresTokenStore(config, identity, logger = null) {
1026
1060
  * @param {object} [logger] - Optional logger
1027
1061
  * @returns {Promise<PostgresTokenStore>}
1028
1062
  */
1029
- async function createPostgresTokenStoreWithPool(pool, identity, logger = null) {
1030
- const store = new PostgresTokenStore(pool, identity, logger);
1063
+ async function createPostgresTokenStoreWithPool(
1064
+ pool,
1065
+ identity,
1066
+ logger = null,
1067
+ runMigration = true
1068
+ ) {
1069
+ const store = new PostgresTokenStore(
1070
+ pool,
1071
+ identity,
1072
+ logger,
1073
+ runMigration
1074
+ );
1031
1075
  await store.initialize();
1032
1076
  return store;
1033
1077
  }