@seedprotocol/sdk 0.7.2 → 0.7.3-next.654.g52217f6

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 (166) hide show
  1. package/dist/{BasePathResolver-BdxCSIzn.js → BasePathResolver-CfSfMW5_.js} +7 -10
  2. package/dist/BasePathResolver-CfSfMW5_.js.map +1 -0
  3. package/dist/{ClientManager-ClCwwhwo.js → ClientManager-C-QXqUK9.js} +438 -153
  4. package/dist/ClientManager-C-QXqUK9.js.map +1 -0
  5. package/dist/{Item-B9Y4VuK1.js → Item-C7sUUu2B.js} +291 -105
  6. package/dist/Item-C7sUUu2B.js.map +1 -0
  7. package/dist/{ModelProperty-BMePcicQ.js → ModelProperty-DJxeOOrc.js} +28 -27
  8. package/dist/ModelProperty-DJxeOOrc.js.map +1 -0
  9. package/dist/{Schema-COsEXXaR.js → Schema-fXtvd-yL.js} +30 -30
  10. package/dist/{Schema-COsEXXaR.js.map → Schema-fXtvd-yL.js.map} +1 -1
  11. package/dist/{SchemaValidationService-DabGMzSE.js → SchemaValidationService-CvRS2HSO.js} +10 -9
  12. package/dist/{SchemaValidationService-DabGMzSE.js.map → SchemaValidationService-CvRS2HSO.js.map} +1 -1
  13. package/dist/{backfillMetadataPropertyIds-Ck6fumnm.js → backfillMetadataPropertyIds-SXW-8C64.js} +4 -4
  14. package/dist/{backfillMetadataPropertyIds-Ck6fumnm.js.map → backfillMetadataPropertyIds-SXW-8C64.js.map} +1 -1
  15. package/dist/cjs/{ModelProperty-BT6Un_MB.js → ModelProperty-DXZ39Wyv.js} +24 -23
  16. package/dist/cjs/{ModelProperty-BT6Un_MB.js.map → ModelProperty-DXZ39Wyv.js.map} +1 -1
  17. package/dist/cjs/{Schema-BXhXdUsA.js → Schema-DdP109QD.js} +26 -25
  18. package/dist/cjs/{Schema-BXhXdUsA.js.map → Schema-DdP109QD.js.map} +1 -1
  19. package/dist/cjs/{SchemaValidationService-CC18QDfc.js → SchemaValidationService-CSXxx7sQ.js} +5 -4
  20. package/dist/cjs/{SchemaValidationService-CC18QDfc.js.map → SchemaValidationService-CSXxx7sQ.js.map} +1 -1
  21. package/dist/cjs/{backfillMetadataPropertyIds-DEHC9ejq.js → backfillMetadataPropertyIds-CPYoaMl4.js} +6 -5
  22. package/dist/cjs/{backfillMetadataPropertyIds-DEHC9ejq.js.map → backfillMetadataPropertyIds-CPYoaMl4.js.map} +1 -1
  23. package/dist/cjs/{eas-C3CL0l7l.js → eas-B2YDQssV.js} +6 -5
  24. package/dist/cjs/{eas-C3CL0l7l.js.map → eas-B2YDQssV.js.map} +1 -1
  25. package/dist/cjs/{getItem-CrwWYCkj.js → getItem-DgnaQzbE.js} +5 -4
  26. package/dist/cjs/{getItem-CrwWYCkj.js.map → getItem-DgnaQzbE.js.map} +1 -1
  27. package/dist/cjs/{getPublishPayload-DRJh7WR0.js → getPublishPayload-CqlqRdot.js} +12 -11
  28. package/dist/cjs/{getPublishPayload-DRJh7WR0.js.map → getPublishPayload-CqlqRdot.js.map} +1 -1
  29. package/dist/cjs/getPublishUploads-DsXY9S4U.js +872 -0
  30. package/dist/cjs/getPublishUploads-DsXY9S4U.js.map +1 -0
  31. package/dist/cjs/{index-BA1RIYFG.js → index-BHaWOwNF.js} +6 -5
  32. package/dist/cjs/index-BHaWOwNF.js.map +1 -0
  33. package/dist/cjs/{index-Dls7aMjr.js → index-C4XlgCJ4.js} +1200 -528
  34. package/dist/cjs/index-C4XlgCJ4.js.map +1 -0
  35. package/dist/cjs/{property-ZerTWizX.js → property-fa0iju0J.js} +8 -7
  36. package/dist/cjs/{property-ZerTWizX.js.map → property-fa0iju0J.js.map} +1 -1
  37. package/dist/cjs/{publishDraftGraph-CPOAcQFf.js → publishDraftGraph-3ASwAlD7.js} +4 -4
  38. package/dist/cjs/{publishDraftGraph-CPOAcQFf.js.map → publishDraftGraph-3ASwAlD7.js.map} +1 -1
  39. package/dist/cjs/{resetAmbiguousLegacyItemData-adDl4LcT.js → resetAmbiguousLegacyItemData-Bu_MBBYt.js} +5 -4
  40. package/dist/cjs/{resetAmbiguousLegacyItemData-adDl4LcT.js.map → resetAmbiguousLegacyItemData-Bu_MBBYt.js.map} +1 -1
  41. package/dist/cjs/{resolveModelForSyncedSeed-DoNThPdL.js → resolveModelForSyncedSeed-BANIiuFU.js} +2 -2
  42. package/dist/cjs/{resolveModelForSyncedSeed-DoNThPdL.js.map → resolveModelForSyncedSeed-BANIiuFU.js.map} +1 -1
  43. package/dist/cjs/{syncDbWithEas-CYfPkus9.js → syncDbWithEas-CrmxxmUW.js} +10 -9
  44. package/dist/cjs/{syncDbWithEas-CYfPkus9.js.map → syncDbWithEas-CrmxxmUW.js.map} +1 -1
  45. package/dist/{configurePlatform-xU3Hsno3.js → configurePlatform-BRw2j0ZN.js} +7 -4
  46. package/dist/{configurePlatform-xU3Hsno3.js.map → configurePlatform-BRw2j0ZN.js.map} +1 -1
  47. package/dist/{db-W1g29qsM.js → db-D9K_f5cF.js} +14 -14
  48. package/dist/{db-W1g29qsM.js.map → db-D9K_f5cF.js.map} +1 -1
  49. package/dist/{eas-CSwV6MvB.js → eas-DHxfswCt.js} +8 -5
  50. package/dist/eas-DHxfswCt.js.map +1 -0
  51. package/dist/{getItem-BYQeM3DY.js → getItem-d6N_aM6S.js} +8 -5
  52. package/dist/{getItem-BYQeM3DY.js.map → getItem-d6N_aM6S.js.map} +1 -1
  53. package/dist/{getPublishPayload-D5CQZd-y.js → getPublishPayload-BHrxVtzY.js} +16 -16
  54. package/dist/{getPublishPayload-D5CQZd-y.js.map → getPublishPayload-BHrxVtzY.js.map} +1 -1
  55. package/dist/getPublishUploads-BEqRiKIS.js +657 -0
  56. package/dist/getPublishUploads-BEqRiKIS.js.map +1 -0
  57. package/dist/{index-Bev-hZF-.js → index-CiMEoGu3.js} +12 -11
  58. package/dist/index-CiMEoGu3.js.map +1 -0
  59. package/dist/{index-CSOQFAOn.js → index-DglvthOk.js} +2 -2
  60. package/dist/index-DglvthOk.js.map +1 -0
  61. package/dist/{index-DRXC5Mra.js → index-s15q14rm.js} +29 -29
  62. package/dist/{index-DRXC5Mra.js.map → index-s15q14rm.js.map} +1 -1
  63. package/dist/{index.browser-DO20vYuP.js → index.browser-Cm06tP4X.js} +553 -165
  64. package/dist/index.browser-Cm06tP4X.js.map +1 -0
  65. package/dist/{index.node-C4iyOhdo.js → index.node-C30dmFgn.js} +5 -5
  66. package/dist/{index.node-C4iyOhdo.js.map → index.node-C30dmFgn.js.map} +1 -1
  67. package/dist/main.cjs +4 -3
  68. package/dist/main.cjs.map +1 -1
  69. package/dist/main.js +32 -44
  70. package/dist/main.js.map +1 -1
  71. package/dist/mimeTypes-DHAHC4eZ.js +204 -0
  72. package/dist/mimeTypes-DHAHC4eZ.js.map +1 -0
  73. package/dist/node.js +13 -12
  74. package/dist/node.js.map +1 -1
  75. package/dist/platform.browser.js +9 -7
  76. package/dist/platform.browser.js.map +1 -1
  77. package/dist/platform.node.js +3 -3
  78. package/dist/{property-BT1zDSkd.js → property-DhmmYAvQ.js} +12 -9
  79. package/dist/property-DhmmYAvQ.js.map +1 -0
  80. package/dist/{publishDraftGraph-Bcfrdj7-.js → publishDraftGraph-yYP74WRt.js} +8 -8
  81. package/dist/{publishDraftGraph-Bcfrdj7-.js.map → publishDraftGraph-yYP74WRt.js.map} +1 -1
  82. package/dist/{resetAmbiguousLegacyItemData-Ci6PM_vC.js → resetAmbiguousLegacyItemData-Bk0QyDW8.js} +2 -2
  83. package/dist/{resetAmbiguousLegacyItemData-Ci6PM_vC.js.map → resetAmbiguousLegacyItemData-Bk0QyDW8.js.map} +1 -1
  84. package/dist/{resolveModelForSyncedSeed-CLlumTBq.js → resolveModelForSyncedSeed-8cAzvUFd.js} +2 -2
  85. package/dist/{resolveModelForSyncedSeed-CLlumTBq.js.map → resolveModelForSyncedSeed-8cAzvUFd.js.map} +1 -1
  86. package/dist/src/Item/Item.d.ts +1 -1
  87. package/dist/src/Item/Item.d.ts.map +1 -1
  88. package/dist/src/ItemProperty/service/actors/saveValueToDb/saveItemStorage.d.ts.map +1 -1
  89. package/dist/src/browser/helpers/FileManager.d.ts +4 -1
  90. package/dist/src/browser/helpers/FileManager.d.ts.map +1 -1
  91. package/dist/src/browser/helpers/tolerantWebAccess.d.ts +79 -4
  92. package/dist/src/browser/helpers/tolerantWebAccess.d.ts.map +1 -1
  93. package/dist/src/browser/workers/FileDownloader.d.ts +19 -4
  94. package/dist/src/browser/workers/FileDownloader.d.ts.map +1 -1
  95. package/dist/src/browser/workers/filesDownload.d.ts.map +1 -1
  96. package/dist/src/client/clientManagerMachine.d.ts.map +1 -1
  97. package/dist/src/db/migrateLegacyItemStorageRows.d.ts +57 -0
  98. package/dist/src/db/migrateLegacyItemStorageRows.d.ts.map +1 -0
  99. package/dist/src/db/read/getCompositeChildPaths.d.ts +13 -0
  100. package/dist/src/db/read/getCompositeChildPaths.d.ts.map +1 -0
  101. package/dist/src/db/read/getItems.d.ts.map +1 -1
  102. package/dist/src/db/read/getPublishUploads.d.ts +32 -3
  103. package/dist/src/db/read/getPublishUploads.d.ts.map +1 -1
  104. package/dist/src/db/read/summarizePublishWork.d.ts.map +1 -1
  105. package/dist/src/db/write/convertVerbatimItemStorageRow.d.ts +44 -0
  106. package/dist/src/db/write/convertVerbatimItemStorageRow.d.ts.map +1 -0
  107. package/dist/src/db/write/createNewItem.d.ts.map +1 -1
  108. package/dist/src/events/files/download.d.ts.map +1 -1
  109. package/dist/src/helpers/FileManager/BaseFileManager.d.ts +3 -3
  110. package/dist/src/helpers/FileManager/BaseFileManager.d.ts.map +1 -1
  111. package/dist/src/helpers/FileManager/IFileManager.d.ts +25 -1
  112. package/dist/src/helpers/FileManager/IFileManager.d.ts.map +1 -1
  113. package/dist/src/helpers/arweaveContentTags.d.ts +33 -0
  114. package/dist/src/helpers/arweaveContentTags.d.ts.map +1 -0
  115. package/dist/src/helpers/compositeUpload.d.ts +28 -0
  116. package/dist/src/helpers/compositeUpload.d.ts.map +1 -0
  117. package/dist/src/helpers/itemStorageFile.d.ts +57 -0
  118. package/dist/src/helpers/itemStorageFile.d.ts.map +1 -0
  119. package/dist/src/helpers/mapWithConcurrency.d.ts +7 -0
  120. package/dist/src/helpers/mapWithConcurrency.d.ts.map +1 -0
  121. package/dist/src/helpers/mimeTypes.d.ts +43 -0
  122. package/dist/src/helpers/mimeTypes.d.ts.map +1 -0
  123. package/dist/src/helpers/ownership.d.ts +19 -3
  124. package/dist/src/helpers/ownership.d.ts.map +1 -1
  125. package/dist/src/helpers/storageDir.d.ts +16 -0
  126. package/dist/src/helpers/storageDir.d.ts.map +1 -0
  127. package/dist/src/helpers/tabCoordinator.d.ts +5 -1
  128. package/dist/src/helpers/tabCoordinator.d.ts.map +1 -1
  129. package/dist/src/helpers/tabEvents.d.ts +23 -2
  130. package/dist/src/helpers/tabEvents.d.ts.map +1 -1
  131. package/dist/src/helpers/tabLocks.d.ts +11 -1
  132. package/dist/src/helpers/tabLocks.d.ts.map +1 -1
  133. package/dist/src/index.d.ts +6 -4
  134. package/dist/src/index.d.ts.map +1 -1
  135. package/dist/src/types/fileManager.d.ts +3 -14
  136. package/dist/src/types/fileManager.d.ts.map +1 -1
  137. package/dist/src/types/publish.d.ts +14 -0
  138. package/dist/src/types/publish.d.ts.map +1 -1
  139. package/dist/{syncDbWithEas-BQsXjGhe.js → syncDbWithEas--HUA9WNb.js} +15 -14
  140. package/dist/syncDbWithEas--HUA9WNb.js.map +1 -0
  141. package/dist/{tabEvents-C9qUKx_z.js → tabEvents-DguZpCCv.js} +338 -60
  142. package/dist/tabEvents-DguZpCCv.js.map +1 -0
  143. package/dist/tolerantWebAccess-BZYWt09Y.js +551 -0
  144. package/dist/tolerantWebAccess-BZYWt09Y.js.map +1 -0
  145. package/dist/{updateSeedRevokedAt-D6q0h7pj.js → updateSeedRevokedAt-D_EG-q3b.js} +3 -3
  146. package/dist/{updateSeedRevokedAt-D6q0h7pj.js.map → updateSeedRevokedAt-D_EG-q3b.js.map} +1 -1
  147. package/package.json +5 -5
  148. package/dist/BasePathResolver-BdxCSIzn.js.map +0 -1
  149. package/dist/ClientManager-ClCwwhwo.js.map +0 -1
  150. package/dist/Item-B9Y4VuK1.js.map +0 -1
  151. package/dist/ModelProperty-BMePcicQ.js.map +0 -1
  152. package/dist/cjs/getPublishUploads-Bh22D3zJ.js +0 -495
  153. package/dist/cjs/getPublishUploads-Bh22D3zJ.js.map +0 -1
  154. package/dist/cjs/index-BA1RIYFG.js.map +0 -1
  155. package/dist/cjs/index-Dls7aMjr.js.map +0 -1
  156. package/dist/eas-CSwV6MvB.js.map +0 -1
  157. package/dist/getPublishUploads-BGpDsrBp.js +0 -484
  158. package/dist/getPublishUploads-BGpDsrBp.js.map +0 -1
  159. package/dist/index-Bev-hZF-.js.map +0 -1
  160. package/dist/index-CSOQFAOn.js.map +0 -1
  161. package/dist/index.browser-DO20vYuP.js.map +0 -1
  162. package/dist/property-BT1zDSkd.js.map +0 -1
  163. package/dist/syncDbWithEas-BQsXjGhe.js.map +0 -1
  164. package/dist/tabEvents-C9qUKx_z.js.map +0 -1
  165. package/dist/tolerantWebAccess-B-9bwxbw.js +0 -160
  166. package/dist/tolerantWebAccess-B-9bwxbw.js.map +0 -1
@@ -1,14 +1,17 @@
1
1
  import debug from 'debug';
2
- import { a as BaseDb, m as metadata, B as BaseFileManager, b as appState, D as ImageSize, E as EAS_SEED_DATA_SYNCED_TO_DB_EVENT } from './BasePathResolver-BdxCSIzn.js';
3
- import { isEasAttestationExplorerUrl, BaseArweaveClient, ensureReadGatewaySelected, getArweaveReadBaseUrls } from '@seedprotocol/arweave';
2
+ import { B as BaseDb, m as metadata, t as BaseFileManager, a as appState, D as ImageSize, E as EAS_SEED_DATA_SYNCED_TO_DB_EVENT } from './BasePathResolver-CfSfMW5_.js';
3
+ import { isEasAttestationExplorerUrl, BaseArweaveClient, ensureReadGatewaySelected, getArweaveReadBaseUrls, getTransactionTagsByIds } from '@seedprotocol/arweave';
4
4
  import { BaseQueryClient, BaseEasClient, GET_FILES_METADATA } from '@seedprotocol/eas';
5
5
  import { waitFor } from 'xstate';
6
6
  import 'pluralize';
7
- import { t as getAllAddressesFromDb, m as eventEmitter } from './db-W1g29qsM.js';
8
- import { and, eq, or, isNotNull } from 'drizzle-orm';
7
+ import { n as normalizeDataType, t as getAllAddressesFromDb, m as eventEmitter } from './db-D9K_f5cF.js';
8
+ import { and, eq, isNotNull, inArray, or } from 'drizzle-orm';
9
9
  import { customAlphabet } from 'nanoid';
10
10
  import { alphanumeric } from 'nanoid-dictionary';
11
11
  import '@seedprotocol/query';
12
+ import { sha256 } from '@noble/hashes/sha256';
13
+ import { sha3_256 } from '@noble/hashes/sha3';
14
+ import { bytesToHex } from '@noble/hashes/utils';
12
15
  import { throttle } from 'lodash-es';
13
16
 
14
17
  /** Same rules as getCorrectId in helpers/index (avoid barrel circular import). */
@@ -409,6 +412,124 @@ const supportsOpfsFileDownloads = () => {
409
412
  return isBrowser() || isElectronRenderer();
410
413
  };
411
414
 
415
+ /**
416
+ * Tag every Seed upload carries with the hex digest of its data. Producers: the SDK's
417
+ * `getPublishUploadData` / `getPublishUploads` (and through them both the L1 transaction path and
418
+ * the bundler / DataItem path in `@seedprotocol/publish`). Consumer: the files download
419
+ * (`events/files/download.ts` and the download worker), which verifies downloaded bytes against it
420
+ * and copies a verified value into `metadata.content_hash`.
421
+ */
422
+ const CONTENT_SHA256_TAG = 'Content-SHA-256';
423
+ const CONTENT_TYPE_TAG = 'Content-Type';
424
+ /**
425
+ * Lowercase hex SHA-256 of `data`: the value of the {@link CONTENT_SHA256_TAG} tag.
426
+ *
427
+ * Uses @noble/hashes rather than WebCrypto so it also works outside secure contexts (WebCrypto's
428
+ * `crypto.subtle` is missing on plain-http origins); the digest is the same.
429
+ *
430
+ * In SDK 0.7.2 and earlier the L1 transaction path (`getPublishUploads`) wrote SHA3-256 under this tag name
431
+ * while the bundler path wrote SHA-256. Uploads from that path still carry SHA3-256 digests; use
432
+ * {@link contentSha256TagMatches} to check a tag value against bytes.
433
+ */
434
+ const getContentSha256 = (data) => bytesToHex(sha256(data));
435
+ /**
436
+ * True when `tagValue` (a {@link CONTENT_SHA256_TAG} value read from Arweave) is the digest of
437
+ * `data`. Accepts SHA-256 and, for uploads made by SDK 0.7.2 and earlier through the L1 transaction path,
438
+ * SHA3-256.
439
+ */
440
+ const contentSha256TagMatches = (data, tagValue) => {
441
+ const expected = tagValue.trim().toLowerCase();
442
+ if (!expected)
443
+ return false;
444
+ return getContentSha256(data) === expected || bytesToHex(sha3_256(data)) === expected;
445
+ };
446
+ /**
447
+ * Tags for one upload, in the order every upload uses: content hash, content type, then any
448
+ * configured extra tags (e.g. App-Name from `arweaveUploadTags`).
449
+ */
450
+ const buildArweaveContentTags = (contentHash, contentType, extra) => {
451
+ const tags = [];
452
+ if (contentHash)
453
+ tags.push({ name: CONTENT_SHA256_TAG, value: contentHash });
454
+ if (contentType)
455
+ tags.push({ name: CONTENT_TYPE_TAG, value: contentType });
456
+ if (extra?.length)
457
+ tags.push(...extra);
458
+ return tags;
459
+ };
460
+
461
+ /** Subdirectory of the files root that holds a storage seed's file, by its data type. */
462
+ const getStorageSubdirForDataType = (dataType) => {
463
+ switch (normalizeDataType(dataType ?? undefined)) {
464
+ case 'Image':
465
+ return 'images';
466
+ case 'Html':
467
+ return 'html';
468
+ case 'Json':
469
+ return 'json';
470
+ case 'File':
471
+ default:
472
+ // Unknown types are generic files; `images/` is only for what the SDK knows is an image.
473
+ return 'files';
474
+ }
475
+ };
476
+ /** Absolute directory for a storage seed's file (`images/`, `files/`, `html/` or `json/` under the files root). */
477
+ const getStorageDirForDataType = (dataType) => BaseFileManager.getFilesPath(getStorageSubdirForDataType(dataType));
478
+ /**
479
+ * Subdirectory (relative to the files root, no leading slash) for an ItemStorage property's file:
480
+ * its model's `storage.path` (`localStorageDir`), else `files`.
481
+ */
482
+ const getItemStorageSubdir = (localStorageDir) => (localStorageDir ?? '').replace(/^\/+/, '').replace(/\/+$/, '') || 'files';
483
+ /**
484
+ * File name a local save gives an ItemStorage property: `<seedUid or seedLocalId><extension>`
485
+ * (see saveItemStorage). Downloaded content is named after its transaction instead
486
+ * (`<txId><extension>`, see syncDbWithEas), which is what the metadata row's refResolvedValue says.
487
+ */
488
+ const getItemStorageLocalFileName = (seedId, filenameSuffix) => `${seedId}${filenameSuffix ?? ''}`;
489
+
490
+ /** Rows per query: well under SQLite's bound-parameter limit. */
491
+ const CHUNK_SIZE = 400;
492
+ /**
493
+ * Where the download worker saves each child of a composite upload, by transaction id then child
494
+ * (property) name: a path relative to the files root.
495
+ *
496
+ * The paths come from the ItemStorage rows sync derives from a `storage_transaction_id`
497
+ * attestation (see `createMetadataRecordsForStorageTransactionId`): property value = the
498
+ * transaction id, `refResolvedValue` = `<txId><extension>`, `localStorageDir` = the model's storage
499
+ * directory. Those rows are what hydration reads, so a child saved here is found as that property's
500
+ * file. Transactions with no such rows are left out; the worker then falls back to the legacy
501
+ * html / json layout.
502
+ */
503
+ const getCompositeChildPaths = async (transactionIds) => {
504
+ const out = {};
505
+ const appDb = BaseDb.getAppDb();
506
+ if (!appDb || transactionIds.length === 0)
507
+ return out;
508
+ for (let i = 0; i < transactionIds.length; i += CHUNK_SIZE) {
509
+ const chunk = transactionIds.slice(i, i + CHUNK_SIZE);
510
+ const rows = await appDb
511
+ .select({
512
+ transactionId: metadata.propertyValue,
513
+ propertyName: metadata.propertyName,
514
+ refResolvedValue: metadata.refResolvedValue,
515
+ localStorageDir: metadata.localStorageDir,
516
+ })
517
+ .from(metadata)
518
+ .where(and(isNotNull(metadata.derivedFromUid), isNotNull(metadata.refResolvedValue), inArray(metadata.propertyValue, chunk)));
519
+ for (const row of rows) {
520
+ const { transactionId, propertyName, refResolvedValue } = row;
521
+ if (!transactionId || !propertyName || !refResolvedValue)
522
+ continue;
523
+ // A file name, never a path: anything else is not where the SDK would look.
524
+ if (refResolvedValue.includes('/') || refResolvedValue.includes('\\'))
525
+ continue;
526
+ const byName = (out[transactionId] ?? (out[transactionId] = {}));
527
+ byName[propertyName] ?? (byName[propertyName] = `${getItemStorageSubdir(row.localStorageDir)}/${refResolvedValue}`);
528
+ }
529
+ }
530
+ return out;
531
+ };
532
+
412
533
  const logger$4 = debug('seedSdk:files:download');
413
534
  const AUTO_BULK_DOWNLOAD_THROTTLE_MS = 10000;
414
535
  /** Avoid refetch-on-every-call: transient empty indexer responses were overwriting good cache (see trailing throttle ~10s after success). */
@@ -425,8 +546,8 @@ const syncDbFiles = async (endpoints) => {
425
546
  const getAppDbReady = async () => {
426
547
  if (!BaseDb.isAppDbReady()) {
427
548
  // Wait for ClientManager to be ready (DB_INIT state or later)
428
- const _mod_0 = await import('./ClientManager-ClCwwhwo.js');
429
- const _ns_0 = _mod_0.H;
549
+ const _mod_0 = await import('./ClientManager-C-QXqUK9.js');
550
+ const _ns_0 = _mod_0.J;
430
551
  const clientManagerMod = _ns_0;
431
552
  const { getClient } = clientManagerMod;
432
553
  const clientManager = getClient();
@@ -561,76 +682,117 @@ const parseTransactionIdsFromMetadata = (filesMetadata, excludedTransactions) =>
561
682
  }
562
683
  return transactionIds;
563
684
  };
564
- const downloadTransactionIds = async (rawTransactionIds, options) => {
565
- if (!supportsOpfsFileDownloads()) {
566
- return false;
685
+ /** Content-SHA-256 tag values for the transactions that have one, from one batched tag lookup (cached). */
686
+ const getExpectedContentHashes = async (transactionIds) => {
687
+ const queryClient = BaseQueryClient.getQueryClient();
688
+ const tagsById = new Map();
689
+ const toFetch = [];
690
+ for (const transactionId of transactionIds) {
691
+ // Tags never change once a transaction is indexed, so a cached lookup stays good.
692
+ const cached = queryClient.getQueryData?.(['getTransactionTags', transactionId]);
693
+ if (cached)
694
+ tagsById.set(transactionId, cached);
695
+ else
696
+ toFetch.push(transactionId);
697
+ }
698
+ if (toFetch.length > 0) {
699
+ try {
700
+ const fetched = await getTransactionTagsByIds(toFetch, {
701
+ client: BaseArweaveClient.getArweaveClient(),
702
+ onError: (error) => logger$4('[download] transaction tags lookup failed', error),
703
+ });
704
+ for (const [transactionId, tags] of fetched) {
705
+ tagsById.set(transactionId, tags);
706
+ // Seed the per-transaction cache entry (the client interface has no setQueryData).
707
+ void queryClient
708
+ .fetchQuery({ queryKey: ['getTransactionTags', transactionId], queryFn: async () => tags })
709
+ .catch(() => { });
710
+ }
711
+ }
712
+ catch (error) {
713
+ logger$4('[download] transaction tags lookup failed', error);
714
+ }
567
715
  }
568
- const transactionIds = Array.from(new Set(rawTransactionIds.filter((tx) => !!tx && tx.trim().length > 0)));
569
- if (transactionIds.length === 0) {
570
- return false;
716
+ const out = {};
717
+ for (const [transactionId, tags] of tagsById) {
718
+ const value = tags.find((tag) => tag.name === CONTENT_SHA256_TAG)?.value?.trim();
719
+ if (value)
720
+ out[transactionId] = value;
571
721
  }
572
- const excludedTransactions = await getExcludedTransactions();
573
- const queryClient = BaseQueryClient.getQueryClient();
574
- const transactionIdsToDownload = [];
575
- await ensureReadGatewaySelected();
722
+ return out;
723
+ };
724
+ /** Store the (now verified) Content-SHA-256 of each downloaded transaction on its metadata row. */
725
+ const recordVerifiedContentHashes = async (transactionIds, expectedContentHashes) => {
576
726
  for (const transactionId of transactionIds) {
577
- if (excludedTransactions.has(transactionId)) {
727
+ const contentHash = expectedContentHashes[transactionId];
728
+ if (!contentHash)
578
729
  continue;
579
- }
580
730
  try {
581
- // Browser: do not call getTransactionStatus() — many gateways (e.g. g8way.io) redirect or omit
582
- // CORS headers, so fetch() fails and we would wrongly exclude txs. The OPFS worker fetch decides success.
583
- let tags = [];
584
- try {
585
- tags = await queryClient.fetchQuery({
586
- queryKey: ['getTransactionTags', transactionId],
587
- queryFn: async () => BaseArweaveClient.getTransactionTags(transactionId),
588
- });
589
- }
590
- catch {
591
- tags = [];
592
- }
593
- if (tags && tags.length > 0) {
594
- for (const { name, value } of tags) {
595
- if (name !== 'Content-SHA-256')
596
- continue;
597
- const metadataRecord = await getMetadata({
598
- storageTransactionId: transactionId,
599
- });
600
- if (metadataRecord) {
601
- await saveMetadata(metadataRecord, {
602
- contentHash: value,
603
- });
604
- }
605
- }
731
+ const metadataRecord = await getMetadata({ storageTransactionId: transactionId });
732
+ if (metadataRecord) {
733
+ await saveMetadata(metadataRecord, { contentHash });
606
734
  }
607
- transactionIdsToDownload.push(transactionId);
608
735
  }
609
736
  catch (error) {
610
737
  logger$4(error);
611
738
  }
612
739
  }
740
+ };
741
+ const downloadTransactionIds = async (rawTransactionIds, options) => {
742
+ if (!supportsOpfsFileDownloads()) {
743
+ return false;
744
+ }
745
+ const transactionIds = Array.from(new Set(rawTransactionIds.filter((tx) => !!tx && tx.trim().length > 0)));
746
+ if (transactionIds.length === 0) {
747
+ return false;
748
+ }
749
+ const excludedTransactions = await getExcludedTransactions();
750
+ await ensureReadGatewaySelected();
751
+ // Browser: do not call getTransactionStatus() — many gateways (e.g. g8way.io) redirect or omit
752
+ // CORS headers, so fetch() fails and we would wrongly exclude txs. The OPFS worker fetch decides success.
753
+ const transactionIdsToDownload = transactionIds.filter((id) => !excludedTransactions.has(id));
613
754
  if (transactionIdsToDownload.length === 0) {
614
755
  return false;
615
756
  }
757
+ // One batched lookup for every upload's Content-SHA-256 tag; downloads are verified against it.
758
+ // Missing tags (old uploads, or a just-published one not indexed yet) just mean no verification.
759
+ const expectedContentHashes = await getExpectedContentHashes(transactionIdsToDownload);
616
760
  // Preferred gateways first: a just-published item is only on the gateway it was uploaded through.
617
761
  const arweaveBaseUrls = getArweaveReadBaseUrls();
762
+ // Where each ItemStorage child of a composite goes (the worker cannot read the DB or the schema).
763
+ const compositeChildPaths = await getCompositeChildPaths(transactionIdsToDownload).catch((error) => {
764
+ logger$4('[download] composite child paths lookup failed', error);
765
+ return {};
766
+ });
767
+ let result;
618
768
  if (transactionIdsToDownload.length === 1) {
619
- await BaseFileManager.downloadFileByTransactionId({
620
- transactionId: transactionIdsToDownload[0],
769
+ const transactionId = transactionIdsToDownload[0];
770
+ result = await BaseFileManager.downloadFileByTransactionId({
771
+ transactionId,
621
772
  arweaveHost: BaseArweaveClient.getBaseUrl(),
622
773
  arweaveBaseUrls,
623
774
  excludedTransactions,
775
+ expectedContentHash: expectedContentHashes[transactionId],
776
+ compositeChildPaths: compositeChildPaths[transactionId],
624
777
  });
625
778
  }
626
779
  else {
627
- await BaseFileManager.downloadAllFiles({
780
+ result = await BaseFileManager.downloadAllFiles({
628
781
  transactionIds: transactionIdsToDownload,
629
782
  arweaveHost: BaseArweaveClient.getBaseUrl(),
630
783
  arweaveBaseUrls,
631
784
  excludedTransactions,
785
+ expectedContentHashes,
786
+ compositeChildPaths,
632
787
  });
633
788
  }
789
+ if (result) {
790
+ for (const transactionId of result.hashMismatchTransactionIds) {
791
+ // Not saved by the worker; left for a later run (a gateway may serve the right bytes then).
792
+ logger$4(`[download] ${transactionId}: downloaded bytes do not match Content-SHA-256; skipped`);
793
+ }
794
+ await recordVerifiedContentHashes(result.verifiedTransactionIds, expectedContentHashes);
795
+ }
634
796
  if (options?.resizeAllImages !== false) {
635
797
  await BaseFileManager.resizeAllImages({
636
798
  width: 480,
@@ -715,6 +877,7 @@ const downloadAllFilesBinaryRequestHandler = async (addressesHintOrPayload) => {
715
877
  await BaseFileManager.createDirIfNotExists(BaseFileManager.getFilesPath('html'));
716
878
  await BaseFileManager.createDirIfNotExists(BaseFileManager.getFilesPath('json'));
717
879
  await BaseFileManager.createDirIfNotExists(BaseFileManager.getFilesPath('images'));
880
+ await BaseFileManager.createDirIfNotExists(BaseFileManager.getFilesPath('files'));
718
881
  const excludedTransactions = await getExcludedTransactions();
719
882
  const fromEas = parseTransactionIdsFromMetadata(filesMetadata ?? [], excludedTransactions);
720
883
  const fromLocal = await collectTransactionIdsFromLocalMetadata();
@@ -1106,7 +1269,9 @@ function parseAddressesPersistedPayload(value) {
1106
1269
  * database and OPFS tree; the browser releases a tab's locks when it closes or crashes, so a lock
1107
1270
  * can't go stale. See docs/MULTI_TAB.md.
1108
1271
  *
1109
- * Where Web Locks are missing, `fn` runs directly. (Node has them too, scoped to the process.)
1272
+ * Node has Web Locks from 24.5, scoped to the process. Where they're missing (older Node, old
1273
+ * browsers), sections still run one at a time within this JS realm (see `withProcessLock`), which
1274
+ * covers a single Node process but not other tabs or worker threads.
1110
1275
  * Not re-entrant: requesting a name the caller already holds waits forever, so take each lock
1111
1276
  * only at the outermost call site.
1112
1277
  */
@@ -1130,7 +1295,7 @@ class TabLockTimeoutError extends Error {
1130
1295
  async function withTabLock(name, fn, { timeoutMs = TAB_LOCK_WAIT_TIMEOUT_MS } = {}) {
1131
1296
  const locks = typeof navigator !== 'undefined' ? navigator.locks : undefined;
1132
1297
  if (!locks)
1133
- return fn();
1298
+ return withProcessLock(name, fn, { timeoutMs });
1134
1299
  try {
1135
1300
  // The timeout bounds the wait only; once granted, fn runs to completion. Infinity waits for as
1136
1301
  // long as the holder runs (it can't outlive its tab).
@@ -1144,8 +1309,52 @@ async function withTabLock(name, fn, { timeoutMs = TAB_LOCK_WAIT_TIMEOUT_MS } =
1144
1309
  throw error;
1145
1310
  }
1146
1311
  }
1312
+ /** Tail of each name's queue: resolves once every section queued so far has finished or given up. */
1313
+ const processLockTails = new Map();
1314
+ /**
1315
+ * The `withTabLock` fallback without Web Locks: an exclusive, first-come-first-served lock per name
1316
+ * within this JS realm. Like Web Locks, `timeoutMs` bounds the wait only, and a waiter that times
1317
+ * out doesn't let later waiters in before the current holder finishes.
1318
+ */
1319
+ async function withProcessLock(name, fn, { timeoutMs = TAB_LOCK_WAIT_TIMEOUT_MS } = {}) {
1320
+ const previous = processLockTails.get(name) ?? Promise.resolve();
1321
+ let release;
1322
+ const done = new Promise((resolve) => (release = resolve));
1323
+ const tail = previous.then(() => done);
1324
+ processLockTails.set(name, tail);
1325
+ void tail.then(() => {
1326
+ if (processLockTails.get(name) === tail)
1327
+ processLockTails.delete(name);
1328
+ });
1329
+ try {
1330
+ await waitForTurn(previous, name, timeoutMs);
1331
+ }
1332
+ catch (error) {
1333
+ release();
1334
+ throw error;
1335
+ }
1336
+ try {
1337
+ return await fn();
1338
+ }
1339
+ finally {
1340
+ release();
1341
+ }
1342
+ }
1343
+ function waitForTurn(previous, name, timeoutMs) {
1344
+ if (!Number.isFinite(timeoutMs))
1345
+ return previous;
1346
+ let timer;
1347
+ const timedOut = new Promise((_, reject) => {
1348
+ timer = setTimeout(() => reject(new TabLockTimeoutError(name, timeoutMs)), timeoutMs);
1349
+ });
1350
+ return Promise.race([previous, timedOut]).finally(() => clearTimeout(timer));
1351
+ }
1147
1352
 
1148
1353
  const logger$1 = debug('seedSdk:helpers:tabCoordinator');
1354
+ /** Identifies this tab (this page's SDK instance) in the messages it sends. */
1355
+ const TAB_ID = typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function'
1356
+ ? crypto.randomUUID()
1357
+ : `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
1149
1358
  let state;
1150
1359
  let leader = false;
1151
1360
  let leaderWaiters = [];
@@ -1164,6 +1373,10 @@ function startTabCoordination({ filesDir, mode = 'coordinate' }) {
1164
1373
  }
1165
1374
  const channel = new BroadcastChannel(`seed:tabs:${dbKey}`);
1166
1375
  channel.onmessage = (event) => {
1376
+ // A BroadcastChannel never hears itself, but another channel object in this page would (a
1377
+ // second channel opened by a test, or the same module loaded twice): skip our own messages.
1378
+ if (event.data?.from === TAB_ID)
1379
+ return;
1167
1380
  for (const handler of messageHandlers)
1168
1381
  handler(event.data);
1169
1382
  };
@@ -1201,7 +1414,11 @@ function whenLeaderTab() {
1201
1414
  }
1202
1415
  /** Sends to the other tabs of this database; a no-op when not coordinating. */
1203
1416
  function postTabMessage(message) {
1204
- state?.channel?.postMessage(message);
1417
+ state?.channel?.postMessage({ ...message, from: TAB_ID });
1418
+ }
1419
+ /** Whether postTabMessage reaches other tabs (a browser tab coordinating with Web Locks). */
1420
+ function isPostingTabMessages() {
1421
+ return !!state?.channel;
1205
1422
  }
1206
1423
  function onTabMessage(handler) {
1207
1424
  messageHandlers.add(handler);
@@ -1232,12 +1449,11 @@ function emitAcrossTabs(name, payload) {
1232
1449
  postTabMessage({ type: 'event', name, payload });
1233
1450
  }
1234
1451
  /**
1235
- * A file saved through this tab's file system: emits `file-saved` here (as before) and tells other
1236
- * tabs, whose caches don't see it.
1452
+ * A file saved through this tab's file system: emits `file-saved` here. Other tabs hear about it
1453
+ * from the file system itself (see queueFilesChangedNotice), once the write has reached OPFS.
1237
1454
  */
1238
1455
  function notifyFileSaved(filePath) {
1239
1456
  eventEmitter.emit('file-saved', filePath);
1240
- postTabMessage({ type: 'files-changed', paths: [filePath] });
1241
1457
  }
1242
1458
  /**
1243
1459
  * Files written straight to OPFS by a worker: refreshes this tab's file-system cache, emits
@@ -1248,20 +1464,68 @@ async function notifyFilesWrittenOutsideCache(paths) {
1248
1464
  return;
1249
1465
  await BaseFileManager.invalidateCachedPaths(paths);
1250
1466
  eventEmitter.emit(FILES_CHANGED_EVENT, paths);
1251
- postTabMessage({ type: 'files-changed', paths });
1467
+ queueFilesChangedNotice(paths);
1468
+ }
1469
+ /**
1470
+ * How long changed paths gather before one `files-changed` message goes out. Counted from the
1471
+ * first queued path, so a steady stream of writes still sends once per window, never later.
1472
+ */
1473
+ const FILES_CHANGED_FLUSH_MS = 25;
1474
+ /** Keeps a message for a huge batch (a bulk download) from being one giant structured clone. */
1475
+ const FILES_CHANGED_MAX_PATHS = 500;
1476
+ let pendingChangedPaths = new Set();
1477
+ let flushTimer;
1478
+ let flushOnPageHide = false;
1479
+ /**
1480
+ * Tells other tabs that these absolute ZenFS paths changed in OPFS, so they drop and re-read their
1481
+ * cached copies (the sync API's in-memory copy in particular). The browser file system calls this
1482
+ * for every file it writes, truncates or removes (`TolerantWebAccessFS.onOpfsChange`, wired in
1483
+ * `BrowserFileManager.initializeFileSystem`), after the change reached OPFS. Paths are coalesced
1484
+ * for FILES_CHANGED_FLUSH_MS, so bulk writes (migrations, schema processing, downloads) send a few
1485
+ * messages rather than one per write.
1486
+ *
1487
+ * Defense in depth only: a tab that misses a message still sees the change on its next async
1488
+ * stat() (see TolerantWebAccessFS.stat). A no-op unless this tab coordinates with others.
1489
+ */
1490
+ function queueFilesChangedNotice(paths) {
1491
+ if (!isPostingTabMessages())
1492
+ return;
1493
+ for (const path of paths)
1494
+ pendingChangedPaths.add(path);
1495
+ if (flushTimer !== undefined || pendingChangedPaths.size === 0)
1496
+ return;
1497
+ flushTimer = setTimeout(flushFilesChangedNotices, FILES_CHANGED_FLUSH_MS);
1498
+ if (!flushOnPageHide && typeof addEventListener === 'function') {
1499
+ flushOnPageHide = true;
1500
+ // A tab closing inside the window still sends what it wrote.
1501
+ addEventListener('pagehide', flushFilesChangedNotices);
1502
+ }
1503
+ }
1504
+ /** Sends the queued paths now (page hide, tests). */
1505
+ function flushFilesChangedNotices() {
1506
+ if (flushTimer !== undefined)
1507
+ clearTimeout(flushTimer);
1508
+ flushTimer = undefined;
1509
+ if (pendingChangedPaths.size === 0)
1510
+ return;
1511
+ const paths = [...pendingChangedPaths];
1512
+ pendingChangedPaths = new Set();
1513
+ for (let i = 0; i < paths.length; i += FILES_CHANGED_MAX_PATHS) {
1514
+ postTabMessage({ type: 'files-changed', paths: paths.slice(i, i + FILES_CHANGED_MAX_PATHS) });
1515
+ }
1252
1516
  }
1253
1517
  /** Refreshes this tab's in-memory state for an event another tab emitted, before re-emitting it. */
1254
1518
  async function catchUpOn(name, payload) {
1255
1519
  if (name === EAS_SEED_DATA_SYNCED_TO_DB_EVENT) {
1256
- const _mod_1 = await import('./Item-B9Y4VuK1.js');
1257
- const _ns_1 = _mod_1.Y;
1520
+ const _mod_1 = await import('./Item-C7sUUu2B.js');
1521
+ const _ns_1 = _mod_1.a2;
1258
1522
  const { Item } = _ns_1;
1259
1523
  await Item.rehydrateCachedItemsFromDbAfterEasSync();
1260
1524
  }
1261
1525
  else if (name === LOCAL_COPIES_REMOVED_EVENT) {
1262
1526
  const { removedSeedLocalIds = [], removedSeedUids = [] } = (payload ?? {});
1263
- const _mod_2 = await import('./Item-B9Y4VuK1.js');
1264
- const _ns_2 = _mod_2.Y;
1527
+ const _mod_2 = await import('./Item-C7sUUu2B.js');
1528
+ const _ns_2 = _mod_2.a2;
1265
1529
  const { Item } = _ns_2;
1266
1530
  Item.dropCachedInstancesForSeedIds([...removedSeedLocalIds, ...removedSeedUids]);
1267
1531
  }
@@ -1291,6 +1555,7 @@ function listenForOtherTabsEvents() {
1291
1555
  });
1292
1556
  }
1293
1557
  else if (message.type === 'files-changed') {
1558
+ // Only refreshes caches: never writes, so never sends files-changed back.
1294
1559
  void BaseFileManager.invalidateCachedPaths(message.paths)
1295
1560
  .catch((error) => logger('refreshing changed files failed', error))
1296
1561
  .then(() => eventEmitter.emit(FILES_CHANGED_EVENT, message.paths));
@@ -1298,5 +1563,18 @@ function listenForOtherTabsEvents() {
1298
1563
  });
1299
1564
  }
1300
1565
 
1301
- export { ADDRESSES_PERSISTED_EVENT as A, isNode as B, isBrowser as C, startTabCoordination as D, downloadAllFilesRequestHandler as E, FILES_CHANGED_EVENT as F, downloadAllFilesBinaryRequestHandler as G, getStorageTransactionIdForSeedUid as H, convertTxIdToImage as I, downloadTransactionIdWithDedupe as J, getDataTypeFromString as K, LOCAL_COPIES_REMOVED_EVENT as L, getMimeType as M, notifyFileSaved as N, download as O, generateId$1 as P, TabLockTimeoutError as T, isStorageSeedRef as a, generateId as b, getArweaveUrlForTransaction as c, classifyMediaRef as d, emitAcrossTabs as e, closestImageSize as f, getCorrectId as g, ensureImageLocal as h, isPublishedSeedRef as i, getFeedItemStringField as j, isLeaderTab as k, normalizeArweaveTxIdForEnsure as l, normalizeFeedItemFields as m, normalizeRelationPropertyValue as n, resolveMediaRef as o, parseAddressesPersistedPayload as p, withDbTabLock as q, resolveSeedIdsFromRefString as r, scheduleBulkFilesDownloadFromEasSync as s, toSnakeCase as t, notifyFilesWrittenOutsideCache as u, withSeedDbLock as v, whenLeaderTab as w, postTabMessage as x, onTabMessage as y, listenForOtherTabsEvents as z };
1302
- //# sourceMappingURL=tabEvents-C9qUKx_z.js.map
1566
+ var tabEvents = /*#__PURE__*/Object.freeze({
1567
+ __proto__: null,
1568
+ FILES_CHANGED_EVENT: FILES_CHANGED_EVENT,
1569
+ FILES_CHANGED_FLUSH_MS: FILES_CHANGED_FLUSH_MS,
1570
+ FILES_CHANGED_MAX_PATHS: FILES_CHANGED_MAX_PATHS,
1571
+ emitAcrossTabs: emitAcrossTabs,
1572
+ flushFilesChangedNotices: flushFilesChangedNotices,
1573
+ listenForOtherTabsEvents: listenForOtherTabsEvents,
1574
+ notifyFileSaved: notifyFileSaved,
1575
+ notifyFilesWrittenOutsideCache: notifyFilesWrittenOutsideCache,
1576
+ queueFilesChangedNotice: queueFilesChangedNotice
1577
+ });
1578
+
1579
+ export { ADDRESSES_PERSISTED_EVENT as A, whenLeaderTab as B, CONTENT_SHA256_TAG as C, withDbTabLock as D, notifyFilesWrittenOutsideCache as E, FILES_CHANGED_EVENT as F, withSeedDbLock as G, postTabMessage as H, onTabMessage as I, listenForOtherTabsEvents as J, isNode as K, LOCAL_COPIES_REMOVED_EVENT as L, isBrowser as M, startTabCoordination as N, downloadAllFilesRequestHandler as O, downloadAllFilesBinaryRequestHandler as P, getStorageTransactionIdForSeedUid as Q, convertTxIdToImage as R, downloadTransactionIdWithDedupe as S, TabLockTimeoutError as T, getDataTypeFromString as U, getMimeType as V, notifyFileSaved as W, withTabLock as X, download as Y, generateId$1 as Z, tabEvents as _, getItemStorageSubdir as a, buildArweaveContentTags as b, getItemStorageLocalFileName as c, getContentSha256 as d, getCorrectId as e, isStorageSeedRef as f, getStorageDirForDataType as g, emitAcrossTabs as h, isPublishedSeedRef as i, generateId as j, getArweaveUrlForTransaction as k, CONTENT_TYPE_TAG as l, classifyMediaRef as m, normalizeRelationPropertyValue as n, closestImageSize as o, contentSha256TagMatches as p, ensureImageLocal as q, resolveSeedIdsFromRefString as r, scheduleBulkFilesDownloadFromEasSync as s, toSnakeCase as t, getFeedItemStringField as u, isLeaderTab as v, normalizeArweaveTxIdForEnsure as w, normalizeFeedItemFields as x, parseAddressesPersistedPayload as y, resolveMediaRef as z };
1580
+ //# sourceMappingURL=tabEvents-DguZpCCv.js.map