@breeztech/breez-sdk-spark 0.15.0 → 0.16.1-dev1
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/breez-sdk-spark.tgz +0 -0
- package/bundler/breez_sdk_spark_wasm.d.ts +511 -215
- package/bundler/breez_sdk_spark_wasm.js +1 -1
- package/bundler/breez_sdk_spark_wasm_bg.js +567 -414
- package/bundler/breez_sdk_spark_wasm_bg.wasm +0 -0
- package/bundler/breez_sdk_spark_wasm_bg.wasm.d.ts +55 -46
- package/bundler/storage/index.js +205 -15
- package/deno/breez_sdk_spark_wasm.d.ts +511 -215
- package/deno/breez_sdk_spark_wasm.js +567 -414
- package/deno/breez_sdk_spark_wasm_bg.wasm +0 -0
- package/deno/breez_sdk_spark_wasm_bg.wasm.d.ts +55 -46
- package/nodejs/breez_sdk_spark_wasm.d.ts +511 -215
- package/nodejs/breez_sdk_spark_wasm.js +578 -421
- package/nodejs/breez_sdk_spark_wasm_bg.wasm +0 -0
- package/nodejs/breez_sdk_spark_wasm_bg.wasm.d.ts +55 -46
- package/nodejs/index.js +10 -10
- package/nodejs/index.mjs +12 -8
- package/nodejs/mysql-session-store/errors.cjs +13 -0
- package/nodejs/{mysql-session-manager → mysql-session-store}/index.cjs +24 -21
- package/nodejs/{mysql-session-manager → mysql-session-store}/migrations.cjs +17 -11
- package/nodejs/mysql-session-store/package.json +9 -0
- package/nodejs/mysql-storage/index.cjs +229 -111
- package/nodejs/mysql-storage/migrations.cjs +37 -2
- package/nodejs/mysql-token-store/index.cjs +99 -79
- package/nodejs/mysql-token-store/migrations.cjs +59 -2
- package/nodejs/mysql-tree-store/index.cjs +15 -9
- package/nodejs/mysql-tree-store/migrations.cjs +16 -2
- package/nodejs/package.json +2 -2
- package/nodejs/postgres-session-store/errors.cjs +13 -0
- package/nodejs/{postgres-session-manager → postgres-session-store}/index.cjs +23 -23
- package/nodejs/{postgres-session-manager → postgres-session-store}/migrations.cjs +14 -14
- package/nodejs/postgres-session-store/package.json +9 -0
- package/nodejs/postgres-storage/index.cjs +174 -107
- package/nodejs/postgres-storage/migrations.cjs +24 -0
- package/nodejs/postgres-token-store/index.cjs +89 -64
- package/nodejs/postgres-token-store/migrations.cjs +44 -0
- package/nodejs/storage/index.cjs +167 -113
- package/nodejs/storage/migrations.cjs +23 -0
- package/package.json +6 -1
- package/ssr/index.js +52 -28
- package/web/breez_sdk_spark_wasm.d.ts +566 -261
- package/web/breez_sdk_spark_wasm.js +567 -414
- package/web/breez_sdk_spark_wasm_bg.wasm +0 -0
- package/web/breez_sdk_spark_wasm_bg.wasm.d.ts +55 -46
- package/web/passkey-prf-provider/index.d.ts +203 -0
- package/web/passkey-prf-provider/index.js +733 -0
- package/web/storage/index.js +205 -15
- package/nodejs/mysql-session-manager/errors.cjs +0 -13
- package/nodejs/mysql-session-manager/package.json +0 -9
- package/nodejs/postgres-session-manager/errors.cjs +0 -13
- package/nodejs/postgres-session-manager/package.json +0 -9
package/web/storage/index.js
CHANGED
|
@@ -457,6 +457,94 @@ class MigrationManager {
|
|
|
457
457
|
}
|
|
458
458
|
}
|
|
459
459
|
},
|
|
460
|
+
{
|
|
461
|
+
// Recovery migration for the missing "contacts" object store.
|
|
462
|
+
//
|
|
463
|
+
// The original "Create contacts store" migration above was INSERTED into
|
|
464
|
+
// the middle of this array (at index 12) instead of being appended, in
|
|
465
|
+
// SDK 0.11.0. That index was already occupied by the "Clear cached
|
|
466
|
+
// lightning address for LnurlInfo schema change" migration, which had
|
|
467
|
+
// shipped one release earlier in SDK 0.10.0 (dbVersion 13).
|
|
468
|
+
//
|
|
469
|
+
// Migration array indices map 1:1 to DB version transitions, so any
|
|
470
|
+
// database that ran 0.10.0 reached version 13 and, on upgrading to
|
|
471
|
+
// 0.11.0+ (dbVersion 14), ran only migrations[13] — permanently skipping
|
|
472
|
+
// the newly-inserted migrations[12]. Those databases never got a
|
|
473
|
+
// "contacts" object store, so every contact operation fails with
|
|
474
|
+
// NotFoundError.
|
|
475
|
+
//
|
|
476
|
+
// This migration is correctly appended and idempotently (re)creates the
|
|
477
|
+
// store, so affected databases recover on their next upgrade while
|
|
478
|
+
// unaffected databases treat it as a no-op. Keep the original migration
|
|
479
|
+
// in place; do not delete or reorder it.
|
|
480
|
+
name: "Create contacts store (recovery for skipped migration)",
|
|
481
|
+
upgrade: (db) => {
|
|
482
|
+
if (!db.objectStoreNames.contains("contacts")) {
|
|
483
|
+
const contactsStore = db.createObjectStore("contacts", { keyPath: "id" });
|
|
484
|
+
contactsStore.createIndex("name_identifier", ["name", "paymentIdentifier"], { unique: false });
|
|
485
|
+
contactsStore.createIndex("name", "name", { unique: false });
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
},
|
|
489
|
+
{
|
|
490
|
+
// Add deposit_vout to distinguish deposits sharing a funding tx. The
|
|
491
|
+
// new field is carried inside the JSON `details` blob. We can't safely
|
|
492
|
+
// backfill vout on the existing blobs: we never stored the original SSP
|
|
493
|
+
// output_index, and vout=0 is a valid output index — defaulting would
|
|
494
|
+
// silently mislabel. Instead we clear `details` on legacy deposit blobs
|
|
495
|
+
// so the read path returns `details: None` (matches what the SQL
|
|
496
|
+
// backends do by leaving the payments row but having no matching
|
|
497
|
+
// payment_details_deposit row). Reset the bitcoin sync offset so the
|
|
498
|
+
// resync re-fetches the SSP user_request and the upsert rewrites the
|
|
499
|
+
// blob with the proper vout.
|
|
500
|
+
name: "Clear legacy deposit details and reset sync offset for vout",
|
|
501
|
+
upgrade: (db, transaction) => {
|
|
502
|
+
if (db.objectStoreNames.contains("payments")) {
|
|
503
|
+
const paymentStore = transaction.objectStore("payments");
|
|
504
|
+
const cursorRequest = paymentStore.openCursor();
|
|
505
|
+
cursorRequest.onsuccess = (event) => {
|
|
506
|
+
const cursor = event.target.result;
|
|
507
|
+
if (!cursor) return;
|
|
508
|
+
const payment = cursor.value;
|
|
509
|
+
let details = null;
|
|
510
|
+
if (payment.details && typeof payment.details === "string") {
|
|
511
|
+
try {
|
|
512
|
+
details = JSON.parse(payment.details);
|
|
513
|
+
} catch (e) {
|
|
514
|
+
details = null;
|
|
515
|
+
}
|
|
516
|
+
} else {
|
|
517
|
+
details = payment.details;
|
|
518
|
+
}
|
|
519
|
+
if (details && details.type === "deposit") {
|
|
520
|
+
payment.details = null;
|
|
521
|
+
cursor.update(payment);
|
|
522
|
+
}
|
|
523
|
+
cursor.continue();
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
if (db.objectStoreNames.contains("settings")) {
|
|
527
|
+
const settingsStore = transaction.objectStore("settings");
|
|
528
|
+
const getRequest = settingsStore.get("sync_offset");
|
|
529
|
+
|
|
530
|
+
getRequest.onsuccess = () => {
|
|
531
|
+
const syncCache = getRequest.result;
|
|
532
|
+
if (syncCache && syncCache.value) {
|
|
533
|
+
try {
|
|
534
|
+
const syncInfo = JSON.parse(syncCache.value);
|
|
535
|
+
syncInfo.offset = 0;
|
|
536
|
+
settingsStore.put({
|
|
537
|
+
key: "sync_offset",
|
|
538
|
+
value: JSON.stringify(syncInfo),
|
|
539
|
+
});
|
|
540
|
+
} catch (e) {
|
|
541
|
+
// If parsing fails, just continue
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
};
|
|
545
|
+
}
|
|
546
|
+
},
|
|
547
|
+
},
|
|
460
548
|
];
|
|
461
549
|
}
|
|
462
550
|
}
|
|
@@ -480,7 +568,12 @@ class IndexedDBStorage {
|
|
|
480
568
|
this.db = null;
|
|
481
569
|
this.migrationManager = null;
|
|
482
570
|
this.logger = logger;
|
|
483
|
-
|
|
571
|
+
// IMPORTANT: the migrations array in MigrationManager is append-only. The
|
|
572
|
+
// migration at array index N is the upgrade step from DB version N to N+1,
|
|
573
|
+
// so existing databases depend on indices never shifting. Never insert,
|
|
574
|
+
// reorder, or delete a migration — only append. dbVersion MUST equal the
|
|
575
|
+
// number of migrations (enforced by the guard in initialize()).
|
|
576
|
+
this.dbVersion = 18; // Current schema version (= migration count)
|
|
484
577
|
}
|
|
485
578
|
|
|
486
579
|
/**
|
|
@@ -495,6 +588,17 @@ class IndexedDBStorage {
|
|
|
495
588
|
throw new StorageError("IndexedDB is not available in this environment");
|
|
496
589
|
}
|
|
497
590
|
|
|
591
|
+
// Guard: dbVersion must equal the migration count. If they drift apart, the
|
|
592
|
+
// upgrade loop either skips the trailing migration(s) or requests a version
|
|
593
|
+
// no migration fills in. Fail fast — this is a programming error.
|
|
594
|
+
const migrationCount = new MigrationManager(null, StorageError).migrations.length;
|
|
595
|
+
if (this.dbVersion !== migrationCount) {
|
|
596
|
+
throw new StorageError(
|
|
597
|
+
`dbVersion (${this.dbVersion}) must equal the migration count (${migrationCount}). ` +
|
|
598
|
+
`Migrations are append-only: append a new migration and bump dbVersion to match.`
|
|
599
|
+
);
|
|
600
|
+
}
|
|
601
|
+
|
|
498
602
|
return new Promise((resolve, reject) => {
|
|
499
603
|
const request = indexedDB.open(this.dbName, this.dbVersion);
|
|
500
604
|
|
|
@@ -802,31 +906,98 @@ class IndexedDBStorage {
|
|
|
802
906
|
});
|
|
803
907
|
}
|
|
804
908
|
|
|
805
|
-
async
|
|
909
|
+
async applyPaymentUpdate(payment) {
|
|
806
910
|
if (!this.db) {
|
|
807
911
|
throw new StorageError("Database not initialized");
|
|
808
912
|
}
|
|
809
913
|
|
|
810
914
|
return new Promise((resolve, reject) => {
|
|
915
|
+
let shouldEmit = false;
|
|
916
|
+
let settled = false;
|
|
811
917
|
const transaction = this.db.transaction("payments", "readwrite");
|
|
812
918
|
const store = transaction.objectStore("payments");
|
|
813
919
|
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
920
|
+
const rejectOnce = (message, error) => {
|
|
921
|
+
if (settled) {
|
|
922
|
+
return;
|
|
923
|
+
}
|
|
924
|
+
settled = true;
|
|
925
|
+
reject(new StorageError(message, error));
|
|
819
926
|
};
|
|
820
927
|
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
928
|
+
transaction.oncomplete = () => {
|
|
929
|
+
if (settled) {
|
|
930
|
+
return;
|
|
931
|
+
}
|
|
932
|
+
settled = true;
|
|
933
|
+
resolve(shouldEmit);
|
|
934
|
+
};
|
|
935
|
+
|
|
936
|
+
transaction.onerror = () => {
|
|
937
|
+
rejectOnce(
|
|
938
|
+
`Failed to apply payment update '${payment.id}': ${transaction.error?.message || "Unknown error"
|
|
939
|
+
}`,
|
|
940
|
+
transaction.error
|
|
941
|
+
);
|
|
942
|
+
};
|
|
943
|
+
|
|
944
|
+
transaction.onabort = () => {
|
|
945
|
+
rejectOnce(
|
|
946
|
+
`Payment update transaction aborted for '${payment.id}': ${transaction.error?.message || "Unknown error"
|
|
947
|
+
}`,
|
|
948
|
+
transaction.error
|
|
949
|
+
);
|
|
950
|
+
};
|
|
951
|
+
|
|
952
|
+
const getRequest = store.get(payment.id);
|
|
953
|
+
|
|
954
|
+
getRequest.onsuccess = () => {
|
|
955
|
+
const storedPayment = getRequest.result;
|
|
956
|
+
const stored = storedPayment
|
|
957
|
+
? this._normalizePaymentStatus(storedPayment.status)
|
|
958
|
+
: null;
|
|
959
|
+
const next = this._normalizePaymentStatus(payment.status);
|
|
960
|
+
|
|
961
|
+
let shouldPersist;
|
|
962
|
+
if (stored == null) {
|
|
963
|
+
shouldPersist = true;
|
|
964
|
+
shouldEmit = true;
|
|
965
|
+
} else if (stored === next) {
|
|
966
|
+
console.debug(
|
|
967
|
+
`Skipping redundant payment event: id=${payment.id} status=${next}`
|
|
968
|
+
);
|
|
969
|
+
shouldPersist = true;
|
|
970
|
+
shouldEmit = false;
|
|
971
|
+
} else if (this._isFinalPaymentStatus(stored)) {
|
|
972
|
+
console.warn(
|
|
973
|
+
`Skipping payment update (would replace terminal status): id=${payment.id} stored=${stored} new=${next}`
|
|
974
|
+
);
|
|
975
|
+
shouldPersist = false;
|
|
976
|
+
shouldEmit = false;
|
|
977
|
+
} else {
|
|
978
|
+
shouldPersist = true;
|
|
979
|
+
shouldEmit = true;
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
if (!shouldPersist) {
|
|
983
|
+
return;
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
const putRequest = store.put(this._paymentToStore(payment));
|
|
987
|
+
putRequest.onerror = () => {
|
|
988
|
+
rejectOnce(
|
|
989
|
+
`Failed to persist payment update '${payment.id}': ${putRequest.error?.message || "Unknown error"
|
|
827
990
|
}`,
|
|
828
|
-
|
|
829
|
-
)
|
|
991
|
+
putRequest.error
|
|
992
|
+
);
|
|
993
|
+
};
|
|
994
|
+
};
|
|
995
|
+
|
|
996
|
+
getRequest.onerror = () => {
|
|
997
|
+
rejectOnce(
|
|
998
|
+
`Failed to read payment '${payment.id}' before update: ${getRequest.error?.message || "Unknown error"
|
|
999
|
+
}`,
|
|
1000
|
+
getRequest.error
|
|
830
1001
|
);
|
|
831
1002
|
};
|
|
832
1003
|
});
|
|
@@ -2021,6 +2192,25 @@ class IndexedDBStorage {
|
|
|
2021
2192
|
|
|
2022
2193
|
// ===== Private Helper Methods =====
|
|
2023
2194
|
|
|
2195
|
+
_paymentToStore(payment) {
|
|
2196
|
+
// Ensure details and method are serialized properly
|
|
2197
|
+
return {
|
|
2198
|
+
...payment,
|
|
2199
|
+
details: payment.details ? JSON.stringify(payment.details) : null,
|
|
2200
|
+
method: payment.method ? JSON.stringify(payment.method) : null,
|
|
2201
|
+
};
|
|
2202
|
+
}
|
|
2203
|
+
|
|
2204
|
+
_normalizePaymentStatus(status) {
|
|
2205
|
+
return typeof status === "string" ? status.toLowerCase() : status;
|
|
2206
|
+
}
|
|
2207
|
+
|
|
2208
|
+
_isFinalPaymentStatus(status) {
|
|
2209
|
+
const normalized = this._normalizePaymentStatus(status);
|
|
2210
|
+
return normalized === "completed" || normalized === "failed";
|
|
2211
|
+
}
|
|
2212
|
+
|
|
2213
|
+
|
|
2024
2214
|
_matchesFilters(payment, request) {
|
|
2025
2215
|
// Filter by payment type
|
|
2026
2216
|
if (request.typeFilter && request.typeFilter.length > 0) {
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
// errors.cjs - Session manager error wrapper with cause chain support
|
|
2
|
-
class SessionManagerError extends Error {
|
|
3
|
-
constructor(message, cause = null) {
|
|
4
|
-
super(message);
|
|
5
|
-
this.name = 'SessionManagerError';
|
|
6
|
-
this.cause = cause;
|
|
7
|
-
if (Error.captureStackTrace) {
|
|
8
|
-
Error.captureStackTrace(this, SessionManagerError);
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
module.exports = { SessionManagerError };
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
// errors.cjs - Session manager error wrapper with cause chain support
|
|
2
|
-
class SessionManagerError extends Error {
|
|
3
|
-
constructor(message, cause = null) {
|
|
4
|
-
super(message);
|
|
5
|
-
this.name = 'SessionManagerError';
|
|
6
|
-
this.cause = cause;
|
|
7
|
-
if (Error.captureStackTrace) {
|
|
8
|
-
Error.captureStackTrace(this, SessionManagerError);
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
module.exports = { SessionManagerError };
|