@seedprotocol/sdk 0.4.19 → 0.4.21

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 (181) hide show
  1. package/dist/{ArweaveClient-CAdWVQnJ.js → ArweaveClient-Cz9ZLiEV.js} +3 -3
  2. package/dist/{ArweaveClient-CAdWVQnJ.js.map → ArweaveClient-Cz9ZLiEV.js.map} +1 -1
  3. package/dist/{ArweaveClient-V62RJhsZ.js → ArweaveClient-DxpJnJXU.js} +3 -3
  4. package/dist/{ArweaveClient-V62RJhsZ.js.map → ArweaveClient-DxpJnJXU.js.map} +1 -1
  5. package/dist/{Db-DS2GBY6h.js → Db-CXwQVLZv.js} +41 -4
  6. package/dist/Db-CXwQVLZv.js.map +1 -0
  7. package/dist/{Db-8N3-le9a.js → Db-DkTBncAM.js} +4 -4
  8. package/dist/{Db-8N3-le9a.js.map → Db-DkTBncAM.js.map} +1 -1
  9. package/dist/{EasClient-D1eibg8b.js → EasClient-DjpbHjU9.js} +2 -2
  10. package/dist/{EasClient-D1eibg8b.js.map → EasClient-DjpbHjU9.js.map} +1 -1
  11. package/dist/{EasClient-nOmY5meW.js → EasClient-JYkmHxu1.js} +2 -2
  12. package/dist/{EasClient-nOmY5meW.js.map → EasClient-JYkmHxu1.js.map} +1 -1
  13. package/dist/{FileManager-DSTAwkqw.js → FileManager-CKyoLrBP.js} +2 -2
  14. package/dist/{FileManager-DSTAwkqw.js.map → FileManager-CKyoLrBP.js.map} +1 -1
  15. package/dist/{FileManager-Cze8qmS1.js → FileManager-DHnyb040.js} +34 -5
  16. package/dist/FileManager-DHnyb040.js.map +1 -0
  17. package/dist/{ModelProperty-ChevZoUy.js → ModelProperty-DWtv9fQr.js} +24 -24
  18. package/dist/{ModelProperty-ChevZoUy.js.map → ModelProperty-DWtv9fQr.js.map} +1 -1
  19. package/dist/{PathResolver-3TuYA9yv.js → PathResolver-Ce4K9acQ.js} +2 -2
  20. package/dist/{PathResolver-3TuYA9yv.js.map → PathResolver-Ce4K9acQ.js.map} +1 -1
  21. package/dist/{PathResolver-C5gj9EU2.js → PathResolver-pmw--Ea2.js} +2 -2
  22. package/dist/{PathResolver-C5gj9EU2.js.map → PathResolver-pmw--Ea2.js.map} +1 -1
  23. package/dist/{QueryClient-BGv6JOls.js → QueryClient-OUjfvY3g.js} +2 -2
  24. package/dist/{QueryClient-BGv6JOls.js.map → QueryClient-OUjfvY3g.js.map} +1 -1
  25. package/dist/{QueryClient-By2vdhIz.js → QueryClient-unspcsWa.js} +2 -2
  26. package/dist/{QueryClient-By2vdhIz.js.map → QueryClient-unspcsWa.js.map} +1 -1
  27. package/dist/{Schema-BQ5W3aOW.js → Schema-CqqcEexA.js} +38 -38
  28. package/dist/{Schema-BQ5W3aOW.js.map → Schema-CqqcEexA.js.map} +1 -1
  29. package/dist/{SchemaValidationService-DQx83Cte.js → SchemaValidationService-Cb-b4kpD.js} +2 -2
  30. package/dist/{SchemaValidationService-DQx83Cte.js.map → SchemaValidationService-Cb-b4kpD.js.map} +1 -1
  31. package/dist/{backfillMetadataPropertyIds-CMsU83q9.js → backfillMetadataPropertyIds-CRyRez3h.js} +2 -2
  32. package/dist/{backfillMetadataPropertyIds-CMsU83q9.js.map → backfillMetadataPropertyIds-CRyRez3h.js.map} +1 -1
  33. package/dist/cjs/{ModelProperty-Cuj839nX.js → ModelProperty-sNx_ZQZX.js} +17 -17
  34. package/dist/cjs/{ModelProperty-Cuj839nX.js.map → ModelProperty-sNx_ZQZX.js.map} +1 -1
  35. package/dist/cjs/{Schema-TFe24NNG.js → Schema-B4RRA-0g.js} +20 -20
  36. package/dist/cjs/{Schema-TFe24NNG.js.map → Schema-B4RRA-0g.js.map} +1 -1
  37. package/dist/cjs/{SchemaValidationService-DVQrRpse.js → SchemaValidationService-DCflhpcI.js} +2 -2
  38. package/dist/cjs/{SchemaValidationService-DVQrRpse.js.map → SchemaValidationService-DCflhpcI.js.map} +1 -1
  39. package/dist/cjs/{backfillMetadataPropertyIds-BiXK4hT1.js → backfillMetadataPropertyIds-DhAXAuSf.js} +2 -2
  40. package/dist/cjs/{backfillMetadataPropertyIds-BiXK4hT1.js.map → backfillMetadataPropertyIds-DhAXAuSf.js.map} +1 -1
  41. package/dist/cjs/{getItem-FgLv9abh.js → getItem-lyM2x5pT.js} +5 -3
  42. package/dist/cjs/getItem-lyM2x5pT.js.map +1 -0
  43. package/dist/cjs/{getPublishPayload-h_Rz8nVX.js → getPublishPayload-DP2fm4q8.js} +125 -26
  44. package/dist/cjs/getPublishPayload-DP2fm4q8.js.map +1 -0
  45. package/dist/cjs/{getPublishUploads-DdSwst2x.js → getPublishUploads-DdVy-5fK.js} +69 -23
  46. package/dist/cjs/getPublishUploads-DdVy-5fK.js.map +1 -0
  47. package/dist/cjs/{getSegmentedItemProperties-Bu4P_MG8.js → getSegmentedItemProperties-DtHofn5i.js} +3 -3
  48. package/dist/cjs/{getSegmentedItemProperties-Bu4P_MG8.js.map → getSegmentedItemProperties-DtHofn5i.js.map} +1 -1
  49. package/dist/cjs/{index-pyKmk9hA.js → index-D1qR8xnb.js} +1055 -388
  50. package/dist/cjs/index-D1qR8xnb.js.map +1 -0
  51. package/dist/cjs/{index-CKJeh6ic.js → index-DTkoTvcq.js} +5 -3
  52. package/dist/cjs/index-DTkoTvcq.js.map +1 -0
  53. package/dist/cjs/{ownership-gfm5thj7.js → ownership-DanM_n8E.js} +4 -4
  54. package/dist/cjs/ownership-DanM_n8E.js.map +1 -0
  55. package/dist/cjs/{property-Dw0b_Sf8.js → property-BQokoaRe.js} +6 -4
  56. package/dist/cjs/{property-Dw0b_Sf8.js.map → property-BQokoaRe.js.map} +1 -1
  57. package/dist/db/drizzle/drizzle/0011_normalize_placeholder_uids.sql +9 -0
  58. package/dist/db/drizzle/drizzle/0012_html_embedded_image_co_publish.sql +10 -0
  59. package/dist/db/drizzle/drizzle/meta/_journal.json +14 -0
  60. package/dist/{getItem-Bd9U9Yih.js → getItem-VI3QqdZH.js} +5 -3
  61. package/dist/getItem-VI3QqdZH.js.map +1 -0
  62. package/dist/{getPublishPayload-eJL7ktes.js → getPublishPayload-DpYwi-rd.js} +129 -30
  63. package/dist/getPublishPayload-DpYwi-rd.js.map +1 -0
  64. package/dist/{getPublishUploads-CKm5dsL6.js → getPublishUploads-DS2dQ4Ho.js} +69 -23
  65. package/dist/getPublishUploads-DS2dQ4Ho.js.map +1 -0
  66. package/dist/{getSegmentedItemProperties-B74LN_bz.js → getSegmentedItemProperties-Bz5B4DSA.js} +3 -3
  67. package/dist/{getSegmentedItemProperties-B74LN_bz.js.map → getSegmentedItemProperties-Bz5B4DSA.js.map} +1 -1
  68. package/dist/{index-BvZCYMxA.js → index-BrD_NNaX.js} +1056 -395
  69. package/dist/index-BrD_NNaX.js.map +1 -0
  70. package/dist/index-Cqf_DxkJ.js +19 -0
  71. package/dist/index-Cqf_DxkJ.js.map +1 -0
  72. package/dist/{index-BQv2k74p.js → index-DdzhrbkF.js} +3 -2
  73. package/dist/index-DdzhrbkF.js.map +1 -0
  74. package/dist/main.cjs +1 -1
  75. package/dist/main.js +528 -41
  76. package/dist/main.js.map +1 -1
  77. package/dist/node.js +10 -10
  78. package/dist/{ownership-tVhYQomL.js → ownership-BK6suksO.js} +4 -4
  79. package/dist/ownership-BK6suksO.js.map +1 -0
  80. package/dist/{property-BOdk-wW1.js → property-C63Ddzap.js} +6 -6
  81. package/dist/{property-BOdk-wW1.js.map → property-C63Ddzap.js.map} +1 -1
  82. package/dist/{queries-DBqVwEdv.js → queries-BGuWjEqt.js} +2 -2
  83. package/dist/{queries-DBqVwEdv.js.map → queries-BGuWjEqt.js.map} +1 -1
  84. package/dist/seedSchema/HtmlEmbeddedImageCoPublishSchema.ts +25 -0
  85. package/dist/seedSchema/index.ts +1 -0
  86. package/dist/src/Item/Item.d.ts +2 -2
  87. package/dist/src/Item/Item.d.ts.map +1 -1
  88. package/dist/src/Item/service/actors/loadOrCreateItem.d.ts.map +1 -1
  89. package/dist/src/Item/service/itemMachineSingle.d.ts +1 -1
  90. package/dist/src/ItemProperty/ItemProperty.d.ts +2 -2
  91. package/dist/src/ItemProperty/ItemProperty.d.ts.map +1 -1
  92. package/dist/src/ItemProperty/service/propertyMachine.d.ts +1 -1
  93. package/dist/src/Model/Model.d.ts +1 -1
  94. package/dist/src/Model/index.d.ts +1 -0
  95. package/dist/src/Model/index.d.ts.map +1 -1
  96. package/dist/src/Model/service/modelMachine.d.ts +3 -3
  97. package/dist/src/ModelProperty/service/modelPropertyMachine.d.ts +2 -2
  98. package/dist/src/Schema/Schema.d.ts +1 -1
  99. package/dist/src/Schema/service/schemaMachine.d.ts +3 -3
  100. package/dist/src/browser/db/drizzleFiles.d.ts +3 -1
  101. package/dist/src/browser/db/drizzleFiles.d.ts.map +1 -1
  102. package/dist/src/browser/helpers/FileManager.d.ts.map +1 -1
  103. package/dist/src/client/ClientManager.d.ts.map +1 -1
  104. package/dist/src/client/actors/platformClassesInit.d.ts.map +1 -1
  105. package/dist/src/client/clientManagerMachine.d.ts.map +1 -1
  106. package/dist/src/client/events.d.ts +8 -0
  107. package/dist/src/client/events.d.ts.map +1 -0
  108. package/dist/src/db/read/batchLatestPublishedVersionBySeedLocalIds.d.ts +10 -0
  109. package/dist/src/db/read/batchLatestPublishedVersionBySeedLocalIds.d.ts.map +1 -0
  110. package/dist/src/db/read/getItem.d.ts.map +1 -1
  111. package/dist/src/db/read/getItemData.d.ts.map +1 -1
  112. package/dist/src/db/read/getItems.d.ts +9 -0
  113. package/dist/src/db/read/getItems.d.ts.map +1 -1
  114. package/dist/src/db/read/getLatestPublishedVersionRow.d.ts +11 -0
  115. package/dist/src/db/read/getLatestPublishedVersionRow.d.ts.map +1 -0
  116. package/dist/src/db/read/getMetadataAttestationUidsForSeedUid.d.ts.map +1 -1
  117. package/dist/src/db/read/getPublishPayload.d.ts.map +1 -1
  118. package/dist/src/db/read/getPublishPendingDiff.d.ts +3 -3
  119. package/dist/src/db/read/getPublishPendingDiff.d.ts.map +1 -1
  120. package/dist/src/db/read/getPublishUploads.d.ts +17 -3
  121. package/dist/src/db/read/getPublishUploads.d.ts.map +1 -1
  122. package/dist/src/db/read/getSeedPublishState.d.ts +21 -0
  123. package/dist/src/db/read/getSeedPublishState.d.ts.map +1 -0
  124. package/dist/src/db/read/subqueries/versionData.d.ts +7 -0
  125. package/dist/src/db/read/subqueries/versionData.d.ts.map +1 -1
  126. package/dist/src/db/write/applyPropertyAttestationUidsFromPublish.d.ts +17 -0
  127. package/dist/src/db/write/applyPropertyAttestationUidsFromPublish.d.ts.map +1 -0
  128. package/dist/src/db/write/updateSeedUid.d.ts +3 -1
  129. package/dist/src/db/write/updateSeedUid.d.ts.map +1 -1
  130. package/dist/src/db/write/updateVersionUid.d.ts +3 -1
  131. package/dist/src/db/write/updateVersionUid.d.ts.map +1 -1
  132. package/dist/src/helpers/ArweaveClient/uploadApiVerification.d.ts +5 -1
  133. package/dist/src/helpers/ArweaveClient/uploadApiVerification.d.ts.map +1 -1
  134. package/dist/src/helpers/constants.d.ts +2 -0
  135. package/dist/src/helpers/constants.d.ts.map +1 -1
  136. package/dist/src/helpers/easUid.d.ts +13 -0
  137. package/dist/src/helpers/easUid.d.ts.map +1 -0
  138. package/dist/src/helpers/htmlEmbeddedDataUriPublish.d.ts +55 -0
  139. package/dist/src/helpers/htmlEmbeddedDataUriPublish.d.ts.map +1 -0
  140. package/dist/src/helpers/index.d.ts +2 -0
  141. package/dist/src/helpers/index.d.ts.map +1 -1
  142. package/dist/src/helpers/mediaRef.d.ts +72 -0
  143. package/dist/src/helpers/mediaRef.d.ts.map +1 -0
  144. package/dist/src/helpers/ownership.d.ts +2 -2
  145. package/dist/src/helpers/property/index.d.ts +30 -0
  146. package/dist/src/helpers/property/index.d.ts.map +1 -1
  147. package/dist/src/helpers/publishConfig.d.ts +3 -4
  148. package/dist/src/helpers/publishConfig.d.ts.map +1 -1
  149. package/dist/src/helpers/waitForEntityIdle.d.ts.map +1 -1
  150. package/dist/src/index.d.ts +14 -2
  151. package/dist/src/index.d.ts.map +1 -1
  152. package/dist/src/interfaces/IItem.d.ts +2 -2
  153. package/dist/src/interfaces/IItem.d.ts.map +1 -1
  154. package/dist/src/seedSchema/HtmlEmbeddedImageCoPublishSchema.d.ts +122 -0
  155. package/dist/src/seedSchema/HtmlEmbeddedImageCoPublishSchema.d.ts.map +1 -0
  156. package/dist/src/seedSchema/index.d.ts +1 -0
  157. package/dist/src/seedSchema/index.d.ts.map +1 -1
  158. package/dist/src/services/write/writeProcessMachine.d.ts +1 -1
  159. package/dist/src/types/index.d.ts +6 -0
  160. package/dist/src/types/index.d.ts.map +1 -1
  161. package/dist/src/types/item.d.ts +3 -0
  162. package/dist/src/types/item.d.ts.map +1 -1
  163. package/dist/src/types/machines.d.ts +2 -0
  164. package/dist/src/types/machines.d.ts.map +1 -1
  165. package/package.json +2 -1
  166. package/dist/Db-DS2GBY6h.js.map +0 -1
  167. package/dist/FileManager-Cze8qmS1.js.map +0 -1
  168. package/dist/cjs/getItem-FgLv9abh.js.map +0 -1
  169. package/dist/cjs/getPublishPayload-h_Rz8nVX.js.map +0 -1
  170. package/dist/cjs/getPublishUploads-DdSwst2x.js.map +0 -1
  171. package/dist/cjs/index-CKJeh6ic.js.map +0 -1
  172. package/dist/cjs/index-pyKmk9hA.js.map +0 -1
  173. package/dist/cjs/ownership-gfm5thj7.js.map +0 -1
  174. package/dist/getItem-Bd9U9Yih.js.map +0 -1
  175. package/dist/getPublishPayload-eJL7ktes.js.map +0 -1
  176. package/dist/getPublishUploads-CKm5dsL6.js.map +0 -1
  177. package/dist/index-BQv2k74p.js.map +0 -1
  178. package/dist/index-BvZCYMxA.js.map +0 -1
  179. package/dist/index-BxfqPvtu.js +0 -19
  180. package/dist/index-BxfqPvtu.js.map +0 -1
  181. package/dist/ownership-tVhYQomL.js.map +0 -1
@@ -345,6 +345,8 @@ const INTERNAL_DATA_TYPES = {
345
345
  eas: 'bytes32',
346
346
  },
347
347
  };
348
+ /** Full property names ending in `Id` that must not be stripped to a “base” name for `allProperties` keys. */
349
+ const PROPERTY_NAMES_EXEMPT_FROM_ID_SUFFIX_STRIP = new Set(['storageTransactionId']);
348
350
  const INTERNAL_PROPERTY_NAMES = [
349
351
  'localId',
350
352
  'uid',
@@ -423,6 +425,7 @@ var constants = /*#__PURE__*/Object.freeze({
423
425
  INTERNAL_PROPERTY_NAMES: INTERNAL_PROPERTY_NAMES,
424
426
  INTERNAL_SCHEMA_IDS: INTERNAL_SCHEMA_IDS,
425
427
  get ImageSize () { return ImageSize; },
428
+ PROPERTY_NAMES_EXEMPT_FROM_ID_SUFFIX_STRIP: PROPERTY_NAMES_EXEMPT_FROM_ID_SUFFIX_STRIP,
426
429
  SCHEMA_NJK: SCHEMA_NJK,
427
430
  SCHEMA_TS: SCHEMA_TS,
428
431
  SEED_CONFIG_FALLBACKS: SEED_CONFIG_FALLBACKS,
@@ -602,14 +605,19 @@ function getUploadApiArweaveDataUrl(baseUrl, txOrDataItemId) {
602
605
  const id = encodeURIComponent(txOrDataItemId);
603
606
  return `${base}/api/upload/arweave/data/${id}`;
604
607
  }
608
+ const DEFAULT_UPLOAD_STATUS_TIMEOUT_MS = 45000;
605
609
  /**
606
610
  * Presence check against the upload API data route (same semantics as
607
611
  * {@link BaseArweaveClient.getTransactionStatus} for gateways: 200 = present, 404 = missing).
608
612
  */
609
- async function getUploadPipelineTransactionStatus(uploadApiBaseUrl, txOrDataItemId) {
613
+ async function getUploadPipelineTransactionStatus(uploadApiBaseUrl, txOrDataItemId, options) {
610
614
  const url = getUploadApiArweaveDataUrl(uploadApiBaseUrl, txOrDataItemId);
615
+ const timeoutMs = options?.timeoutMs ?? DEFAULT_UPLOAD_STATUS_TIMEOUT_MS;
616
+ const controller = new AbortController();
617
+ const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
611
618
  try {
612
- const response = await fetch(url);
619
+ const response = await fetch(url, { signal: controller.signal });
620
+ clearTimeout(timeoutId);
613
621
  if (response.status === 404) {
614
622
  return { status: 404, confirmed: null };
615
623
  }
@@ -621,7 +629,11 @@ async function getUploadPipelineTransactionStatus(uploadApiBaseUrl, txOrDataItem
621
629
  }
622
630
  return { status: 200, confirmed: null };
623
631
  }
624
- catch {
632
+ catch (err) {
633
+ clearTimeout(timeoutId);
634
+ if (err instanceof Error && err.name === 'AbortError') {
635
+ return { status: 504, confirmed: null };
636
+ }
625
637
  return { status: 500, confirmed: null };
626
638
  }
627
639
  }
@@ -763,8 +775,18 @@ async function waitForEntityIdle(entity, options = {}) {
763
775
  const { timeout = 5000, throwOnError = true } = options;
764
776
  const service = entity.getService();
765
777
  const currentSnapshot = service.getSnapshot();
778
+ const isSnapshotIdle = (snapshot) => {
779
+ if (!('value' in snapshot) || snapshot.value !== 'idle') {
780
+ return false;
781
+ }
782
+ // ItemProperty: same condition as ItemProperty.save() — nested "saving" uses object state values
783
+ if (snapshot.context?.isSaving) {
784
+ return false;
785
+ }
786
+ return true;
787
+ };
766
788
  // Check current state first - if already idle, return immediately
767
- if ('value' in currentSnapshot && currentSnapshot.value === 'idle') {
789
+ if (isSnapshotIdle(currentSnapshot)) {
768
790
  return;
769
791
  }
770
792
  if ('value' in currentSnapshot && currentSnapshot.value === 'error') {
@@ -781,13 +803,18 @@ async function waitForEntityIdle(entity, options = {}) {
781
803
  }
782
804
  return true; // Accept error state if not throwing
783
805
  }
784
- return 'value' in snapshot && snapshot.value === 'idle';
806
+ return isSnapshotIdle(snapshot);
785
807
  }, { timeout });
786
808
  }
787
809
  catch (error) {
788
810
  if (error.message === 'Entity failed to load') {
789
811
  throw error;
790
812
  }
813
+ const msg = typeof error?.message === 'string' ? error.message : '';
814
+ const isWaitForTimeout = msg.includes('Timeout') || msg.toLowerCase().includes('timed out');
815
+ if (!throwOnError && isWaitForTimeout) {
816
+ return;
817
+ }
791
818
  throw new Error(`Entity loading timeout after ${timeout}ms`);
792
819
  }
793
820
  }
@@ -939,6 +966,11 @@ const TStorageType = typebox.Type.Union([
939
966
  typebox.Type.Literal('ItemStorage'), // Looks for a storageTransactionId property on the item
940
967
  typebox.Type.Literal('PropertyStorage'), // Looks for a storageTransactionId value on the property
941
968
  ]);
969
+ /** How publish handles `data:image/*` URIs inside Html storage. Only applies when `dataType === 'Html'`. */
970
+ const THtmlEmbeddedDataUriPolicy = typebox.Type.Union([
971
+ typebox.Type.Literal('materialize'),
972
+ typebox.Type.Literal('preserve'),
973
+ ]);
942
974
  const TProperty = typebox.Type.Object({
943
975
  id: typebox.Type.Optional(typebox.Type.String()), // schemaFileId (string) - public ID
944
976
  _dbId: typebox.Type.Optional(typebox.Type.Number()), // Database integer ID - internal only
@@ -956,6 +988,8 @@ const TProperty = typebox.Type.Object({
956
988
  filenameSuffix: typebox.Type.Optional(typebox.Type.String()),
957
989
  validation: typebox.Type.Optional(TValidationRules),
958
990
  required: typebox.Type.Optional(typebox.Type.Boolean()),
991
+ /** When set on an Html property: `materialize` uploads embedded images as Image seeds and rewrites src; `preserve` leaves data URIs. */
992
+ htmlEmbeddedDataUriPolicy: typebox.Type.Optional(THtmlEmbeddedDataUriPolicy),
959
993
  });
960
994
  const TPropertyConstructor = typebox.Type.Function([
961
995
  typebox.Type.Optional(typebox.Type.Union([typebox.Type.String(), TStorageType, typebox.Type.Undefined()])),
@@ -963,6 +997,14 @@ const TPropertyConstructor = typebox.Type.Function([
963
997
  typebox.Type.Optional(typebox.Type.Union([typebox.Type.String(), typebox.Type.Boolean()])),
964
998
  ], TProperty);
965
999
  const TPropertyDefs = typebox.Type.Record(TPropertyDataType, TPropertyConstructor);
1000
+ function htmlPropertyFactory(opts) {
1001
+ return {
1002
+ dataType: exports.ModelPropertyDataTypes.Html,
1003
+ ...(opts?.htmlEmbeddedDataUriPolicy
1004
+ ? { htmlEmbeddedDataUriPolicy: opts.htmlEmbeddedDataUriPolicy }
1005
+ : {}),
1006
+ };
1007
+ }
966
1008
  const Property = {
967
1009
  Text: (storageType, localStorageDir, filenameSuffix) => ({
968
1010
  dataType: exports.ModelPropertyDataTypes.Text,
@@ -995,7 +1037,8 @@ const Property = {
995
1037
  Image: () => ({ dataType: exports.ModelPropertyDataTypes.Image }),
996
1038
  Boolean: () => ({ dataType: exports.ModelPropertyDataTypes.Boolean }),
997
1039
  Date: () => ({ dataType: exports.ModelPropertyDataTypes.Date }),
998
- Html: () => ({ dataType: exports.ModelPropertyDataTypes.Html }),
1040
+ Html: htmlPropertyFactory,
1041
+ /** `Html` opts are not representable in `TPropertyConstructor`; keep runtime shape via double assert. */
999
1042
  };
1000
1043
  const PropertyMetadataKey = Symbol('property');
1001
1044
  const PropertyConstructor = (propertyType) => {
@@ -1014,6 +1057,7 @@ const Relation = (ref, refValueType, required) => PropertyConstructor(Property.R
1014
1057
  const List = (refValueType, ref) => PropertyConstructor(Property.List(refValueType, ref));
1015
1058
  const Boolean$1 = () => PropertyConstructor(Property.Boolean());
1016
1059
  const Date$1 = () => PropertyConstructor(Property.Date());
1060
+ const Html = (opts) => PropertyConstructor(htmlPropertyFactory(opts));
1017
1061
 
1018
1062
  /**
1019
1063
  * For a schema property key like `authors` (List of Relation to Identity), returns the
@@ -1188,7 +1232,505 @@ function resolveSeedIdsFromRefString(s) {
1188
1232
  if (LOCAL_SEED_REF.test(s) && !s.startsWith('0x')) {
1189
1233
  return { seedLocalId: s };
1190
1234
  }
1191
- return {};
1235
+ return {};
1236
+ }
1237
+
1238
+ const seeds = sqliteCore.sqliteTable('seeds', {
1239
+ localId: sqliteCore.text('local_id').unique(),
1240
+ uid: sqliteCore.text('uid'),
1241
+ schemaUid: sqliteCore.text('schema_uid'),
1242
+ type: sqliteCore.text('type'),
1243
+ publisher: sqliteCore.text('publisher'),
1244
+ attestationRaw: sqliteCore.text('attestation_raw'),
1245
+ attestationCreatedAt: sqliteCore.int('attestation_created_at'),
1246
+ createdAt: sqliteCore.int('created_at'),
1247
+ updatedAt: sqliteCore.int('updated_at'),
1248
+ _markedForDeletion: sqliteCore.int('_marked_for_deletion'),
1249
+ revokedAt: sqliteCore.int('revoked_at'),
1250
+ });
1251
+
1252
+ const versions = sqliteCore.sqliteTable('versions', {
1253
+ localId: sqliteCore.text('local_id').unique(),
1254
+ uid: sqliteCore.text('uid'),
1255
+ seedLocalId: sqliteCore.text('seed_local_id'),
1256
+ seedUid: sqliteCore.text('seed_uid'),
1257
+ seedType: sqliteCore.text('seed_type'),
1258
+ note: sqliteCore.text('note'),
1259
+ createdAt: sqliteCore.int('created_at'),
1260
+ updatedAt: sqliteCore.int('updated_at'),
1261
+ attestationCreatedAt: sqliteCore.int('attestation_created_at'),
1262
+ attestationRaw: sqliteCore.text('attestation_raw'),
1263
+ publisher: sqliteCore.text('publisher'),
1264
+ });
1265
+
1266
+ const metadata$1 = sqliteCore.sqliteTable('metadata', {
1267
+ localId: sqliteCore.text('local_id').unique(),
1268
+ uid: sqliteCore.text('uid'),
1269
+ propertyId: sqliteCore.integer('property_id').references(() => properties.id),
1270
+ propertyName: sqliteCore.text('property_name'),
1271
+ propertyValue: sqliteCore.text('property_value'),
1272
+ schemaUid: sqliteCore.text('schema_uid'),
1273
+ modelType: sqliteCore.text('model_type'),
1274
+ seedLocalId: sqliteCore.text('seed_local_id'),
1275
+ seedUid: sqliteCore.text('seed_uid'),
1276
+ versionLocalId: sqliteCore.text('version_local_id'),
1277
+ versionUid: sqliteCore.text('version_uid'),
1278
+ easDataType: sqliteCore.text('eas_data_type'),
1279
+ refValueType: sqliteCore.text('ref_value_type'),
1280
+ refModelUid: sqliteCore.text('ref_schema_uid'),
1281
+ refSeedType: sqliteCore.text('ref_seed_type'),
1282
+ refResolvedValue: sqliteCore.text('ref_resolved_value'),
1283
+ refResolvedDisplayValue: sqliteCore.text('ref_resolved_display_value'),
1284
+ localStorageDir: sqliteCore.text('local_storage_dir'),
1285
+ attestationRaw: sqliteCore.text('attestation_raw'),
1286
+ attestationCreatedAt: sqliteCore.int('attestation_created_at'),
1287
+ contentHash: sqliteCore.text('content_hash'),
1288
+ createdAt: sqliteCore.int('created_at'),
1289
+ updatedAt: sqliteCore.int('updated_at'),
1290
+ publisher: sqliteCore.text('publisher'),
1291
+ });
1292
+
1293
+ const appState = sqliteCore.sqliteTable('appState', {
1294
+ key: sqliteCore.text('key').unique(),
1295
+ value: sqliteCore.text('value'),
1296
+ createdAt: sqliteCore.int('created_at'),
1297
+ updatedAt: sqliteCore.int('updated_at'),
1298
+ });
1299
+
1300
+ const modelUids = sqliteCore.sqliteTable('model_uids', {
1301
+ id: sqliteCore.int('id').primaryKey({ autoIncrement: true }),
1302
+ uid: sqliteCore.text('uid').notNull(),
1303
+ modelId: sqliteCore.int('model_id')
1304
+ .notNull()
1305
+ .unique()
1306
+ .references(() => models$1.id),
1307
+ });
1308
+ const modelRelations = drizzleOrm.relations(modelUids, ({ one }) => ({
1309
+ model: one(models$1),
1310
+ }));
1311
+
1312
+ const propertyUids = sqliteCore.sqliteTable('property_uids', {
1313
+ id: sqliteCore.int('id').primaryKey({ autoIncrement: true }),
1314
+ uid: sqliteCore.text('uid').notNull(),
1315
+ propertyId: sqliteCore.int('property_id')
1316
+ .notNull()
1317
+ .unique()
1318
+ .references(() => properties.id),
1319
+ });
1320
+ const propertyUidRelations = drizzleOrm.relations(propertyUids, ({ one }) => ({
1321
+ property: one(properties),
1322
+ }));
1323
+
1324
+ const config = sqliteCore.sqliteTable('config', {
1325
+ id: sqliteCore.integer('id').primaryKey({ autoIncrement: true }),
1326
+ key: sqliteCore.text('key').notNull(),
1327
+ text: sqliteCore.text('text'),
1328
+ json: sqliteCore.text('json'),
1329
+ blob: sqliteCore.blob('blob'),
1330
+ });
1331
+
1332
+ const schemas = sqliteCore.sqliteTable('schemas', {
1333
+ id: sqliteCore.integer('id').primaryKey({ autoIncrement: true }),
1334
+ name: sqliteCore.text('name').notNull(),
1335
+ version: sqliteCore.integer('version').notNull(),
1336
+ schemaFileId: sqliteCore.text('schema_file_id'), // ID from JSON file for change tracking - must be unique
1337
+ schemaData: sqliteCore.text('schema_data'), // Full JSON schema content (SchemaFileFormat as JSON string)
1338
+ isDraft: sqliteCore.integer('is_draft', { mode: 'boolean' }), // true if schema is in draft/editing state, false if published to file
1339
+ isEdited: sqliteCore.integer('is_edited', { mode: 'boolean' }), // true if schema has been edited locally, false if matches schema file
1340
+ createdAt: sqliteCore.int('created_at'),
1341
+ updatedAt: sqliteCore.int('updated_at'),
1342
+ }, (table) => {
1343
+ return {
1344
+ uniqueSchemaFileId: sqliteCore.unique('unique_schema_schema_file_id').on(table.schemaFileId),
1345
+ };
1346
+ });
1347
+
1348
+ var SchemaSchema = /*#__PURE__*/Object.freeze({
1349
+ __proto__: null,
1350
+ schemas: schemas
1351
+ });
1352
+
1353
+ const modelSchemas = sqliteCore.sqliteTable('model_schemas', {
1354
+ id: sqliteCore.integer('id').primaryKey({ autoIncrement: true }),
1355
+ modelId: sqliteCore.integer('model_id').references(() => models$1.id),
1356
+ schemaId: sqliteCore.integer('schema_id').references(() => schemas.id),
1357
+ });
1358
+
1359
+ var ModelSchemaSchema = /*#__PURE__*/Object.freeze({
1360
+ __proto__: null,
1361
+ modelSchemas: modelSchemas
1362
+ });
1363
+
1364
+ const publishProcesses = sqliteCore.sqliteTable('publish_processes', {
1365
+ id: sqliteCore.int('id').primaryKey({ autoIncrement: true }),
1366
+ seedLocalId: sqliteCore.text('seed_local_id').notNull(),
1367
+ modelName: sqliteCore.text('model_name').notNull(),
1368
+ schemaId: sqliteCore.text('schema_id'),
1369
+ status: sqliteCore.text('status').notNull(), // 'in_progress' | 'completed' | 'failed' | 'interrupted'
1370
+ startedAt: sqliteCore.int('started_at').notNull(),
1371
+ completedAt: sqliteCore.int('completed_at'),
1372
+ errorMessage: sqliteCore.text('error_message'),
1373
+ errorStep: sqliteCore.text('error_step'),
1374
+ errorDetails: sqliteCore.text('error_details'),
1375
+ persistedSnapshot: sqliteCore.text('persisted_snapshot').notNull(),
1376
+ seedId: sqliteCore.text('seed_id'),
1377
+ existingSeedUid: sqliteCore.text('existing_seed_uid'),
1378
+ createdAt: sqliteCore.int('created_at'),
1379
+ updatedAt: sqliteCore.int('updated_at'),
1380
+ });
1381
+
1382
+ const uploadProcesses = sqliteCore.sqliteTable('upload_processes', {
1383
+ id: sqliteCore.int('id').primaryKey({ autoIncrement: true }),
1384
+ reimbursementConfirmed: sqliteCore.int('reimbursement_confirmed').notNull(), // 0 or 1 for boolean
1385
+ reimbursementTransactionId: sqliteCore.text('reimbursement_transaction_id'),
1386
+ transactionKeys: sqliteCore.text('transaction_keys'),
1387
+ persistedSnapshot: sqliteCore.text('persisted_snapshot').notNull(), // JSON string
1388
+ createdAt: sqliteCore.int('created_at'),
1389
+ updatedAt: sqliteCore.int('updated_at'),
1390
+ });
1391
+
1392
+ /** Background job: resolve L1 tx id and wait for L1 confirmation after bundler publish. */
1393
+ const arweaveL1FinalizeJobs = sqliteCore.sqliteTable('arweave_l1_finalize_jobs', {
1394
+ id: sqliteCore.int('id').primaryKey({ autoIncrement: true }),
1395
+ seedLocalId: sqliteCore.text('seed_local_id').notNull(),
1396
+ dataItemId: sqliteCore.text('data_item_id').notNull(),
1397
+ /** L1 bundle / anchor transaction id from gateway GraphQL `bundledIn.id`. */
1398
+ l1TransactionId: sqliteCore.text('l1_transaction_id'),
1399
+ bundleId: sqliteCore.text('bundle_id'),
1400
+ versionLocalId: sqliteCore.text('version_local_id'),
1401
+ itemPropertyName: sqliteCore.text('item_property_name'),
1402
+ /** `pending_l1` | `confirmed` | `failed` */
1403
+ phase: sqliteCore.text('phase').notNull(),
1404
+ statusJson: sqliteCore.text('status_json'),
1405
+ errorMessage: sqliteCore.text('error_message'),
1406
+ createdAt: sqliteCore.int('created_at').notNull(),
1407
+ updatedAt: sqliteCore.int('updated_at').notNull(),
1408
+ }, (table) => ({
1409
+ dataItemIdUnique: sqliteCore.uniqueIndex('arweave_l1_finalize_jobs_data_item_id_unique').on(table.dataItemId),
1410
+ }));
1411
+
1412
+ /**
1413
+ * Links Image seeds materialized from Html `data:image/*` URIs to the parent Item seed for co-publish.
1414
+ * Rows are removed after a successful publish (see clearHtmlEmbeddedImageCoPublishRows).
1415
+ */
1416
+ const htmlEmbeddedImageCoPublish = sqliteCore.sqliteTable('html_embedded_image_co_publish', {
1417
+ id: sqliteCore.int('id').primaryKey({ autoIncrement: true }),
1418
+ parentSeedLocalId: sqliteCore.text('parent_seed_local_id').notNull(),
1419
+ htmlSeedLocalId: sqliteCore.text('html_seed_local_id').notNull(),
1420
+ imageSeedLocalId: sqliteCore.text('image_seed_local_id').notNull(),
1421
+ /** Stable dedup key (e.g. sha256 of data URI or normalized URI string). */
1422
+ stableKey: sqliteCore.text('stable_key').notNull(),
1423
+ createdAt: sqliteCore.int('created_at').notNull(),
1424
+ }, (t) => [
1425
+ sqliteCore.uniqueIndex('html_embed_co_pub_parent_html_stable').on(t.parentSeedLocalId, t.htmlSeedLocalId, t.stableKey),
1426
+ ]);
1427
+
1428
+ var schema$1 = /*#__PURE__*/Object.freeze({
1429
+ __proto__: null,
1430
+ appState: appState,
1431
+ arweaveL1FinalizeJobs: arweaveL1FinalizeJobs,
1432
+ config: config,
1433
+ htmlEmbeddedImageCoPublish: htmlEmbeddedImageCoPublish,
1434
+ metadata: metadata$1,
1435
+ modelRelations: modelRelations,
1436
+ modelSchemas: modelSchemas,
1437
+ modelUids: modelUids,
1438
+ models: models$1,
1439
+ modelsRelations: modelsRelations,
1440
+ properties: properties,
1441
+ propertiesRelations: propertiesRelations,
1442
+ propertyUidRelations: propertyUidRelations,
1443
+ propertyUids: propertyUids,
1444
+ publishProcesses: publishProcesses,
1445
+ schemas: schemas,
1446
+ seeds: seeds,
1447
+ uploadProcesses: uploadProcesses,
1448
+ versions: versions
1449
+ });
1450
+
1451
+ const seedUidToStorageTransactionId = new Map();
1452
+ const getStorageTransactionIdForSeedUid = async (seedUid) => {
1453
+ if (seedUidToStorageTransactionId.has(seedUid)) {
1454
+ return seedUidToStorageTransactionId.get(seedUid);
1455
+ }
1456
+ const appDb = BaseDb.getAppDb();
1457
+ const results = (await appDb
1458
+ .select({
1459
+ storageTransactionId: metadata$1.propertyValue,
1460
+ })
1461
+ .from(metadata$1)
1462
+ .where(drizzleOrm.and(drizzleOrm.eq(metadata$1.seedUid, seedUid), drizzleOrm.eq(metadata$1.propertyName, 'storageTransactionId'))));
1463
+ if (!results || results.length === 0) {
1464
+ return;
1465
+ }
1466
+ seedUidToStorageTransactionId.set(seedUid, results[0].storageTransactionId);
1467
+ return results[0].storageTransactionId;
1468
+ };
1469
+
1470
+ const logger$A = debug('seedSdk:helpers:mediaRef');
1471
+ /** Typical Arweave transaction id: 43 URL-safe base64 characters. */
1472
+ const ARWEAVE_TX_ID = /^[a-zA-Z0-9_-]{43}$/;
1473
+ function trimOrEmpty(raw) {
1474
+ if (raw == null)
1475
+ return '';
1476
+ return typeof raw === 'string' ? raw.trim() : String(raw).trim();
1477
+ }
1478
+ function coalesceStringField(item, key) {
1479
+ const v = item[key];
1480
+ if (v == null)
1481
+ return '';
1482
+ if (typeof v === 'string')
1483
+ return v.trim();
1484
+ if (typeof v === 'number' || typeof v === 'boolean')
1485
+ return String(v);
1486
+ return '';
1487
+ }
1488
+ /**
1489
+ * Try JSON relation payloads and plain relation id strings.
1490
+ */
1491
+ function unwrapRelationString(raw) {
1492
+ const t = raw.trim();
1493
+ if (!t)
1494
+ return t;
1495
+ try {
1496
+ const parsed = JSON.parse(t);
1497
+ const fromObj = normalizeRelationPropertyValue(parsed);
1498
+ if (fromObj)
1499
+ return fromObj;
1500
+ }
1501
+ catch {
1502
+ // not JSON
1503
+ }
1504
+ return t;
1505
+ }
1506
+ /**
1507
+ * Pure, sync classification of a media-related string from feeds or XML.
1508
+ */
1509
+ function classifyMediaRef(raw, options) {
1510
+ const s = trimOrEmpty(raw);
1511
+ if (!s) {
1512
+ return { kind: 'empty' };
1513
+ }
1514
+ const treatAs = options?.treatAs;
1515
+ if (treatAs === 'url') {
1516
+ return { kind: 'url', href: s };
1517
+ }
1518
+ if (treatAs === 'arweaveTx') {
1519
+ return { kind: 'arweaveTxId', txId: s };
1520
+ }
1521
+ if (treatAs === 'seedUid') {
1522
+ if (s.startsWith('0x') && s.length === 66) {
1523
+ return { kind: 'seedUid', uid: s };
1524
+ }
1525
+ return { kind: 'unknown', raw: s };
1526
+ }
1527
+ if (s.startsWith('http://') || s.startsWith('https://') || s.startsWith('blob:') || s.startsWith('data:')) {
1528
+ return { kind: 'url', href: s };
1529
+ }
1530
+ const unwrapped = unwrapRelationString(s);
1531
+ const ids = resolveSeedIdsFromRefString(unwrapped);
1532
+ if (ids.seedUid) {
1533
+ return { kind: 'seedUid', uid: ids.seedUid };
1534
+ }
1535
+ if (ids.seedLocalId) {
1536
+ return { kind: 'seedLocalId', localId: ids.seedLocalId };
1537
+ }
1538
+ if (unwrapped.startsWith('0x') && unwrapped.length === 66) {
1539
+ return { kind: 'seedUid', uid: unwrapped };
1540
+ }
1541
+ if (ARWEAVE_TX_ID.test(unwrapped) && !unwrapped.startsWith('0x')) {
1542
+ return { kind: 'arweaveTxId', txId: unwrapped };
1543
+ }
1544
+ return { kind: 'unknown', raw: s };
1545
+ }
1546
+ /**
1547
+ * Same as convertTxIdToImage but local to this module to avoid circular imports with helpers/index.
1548
+ */
1549
+ async function tryLocalBlobUrlFromTxId(txId) {
1550
+ const imageFilePath = BaseFileManager.getFilesPath('images', txId);
1551
+ const fileExists = await BaseFileManager.pathExists(imageFilePath);
1552
+ if (!fileExists) {
1553
+ logger$A(`[tryLocalBlobUrlFromTxId] ${imageFilePath} does not exist`);
1554
+ return undefined;
1555
+ }
1556
+ const buffer = await BaseFileManager.readFileAsBuffer(imageFilePath);
1557
+ let arrayBuffer;
1558
+ if (buffer instanceof Blob) {
1559
+ arrayBuffer = await buffer.arrayBuffer();
1560
+ }
1561
+ else if (buffer instanceof ArrayBuffer) {
1562
+ arrayBuffer = buffer;
1563
+ }
1564
+ else {
1565
+ const sliced = buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
1566
+ if (sliced instanceof SharedArrayBuffer) {
1567
+ const uint8Array = new Uint8Array(sliced);
1568
+ arrayBuffer = uint8Array.buffer.slice(0);
1569
+ }
1570
+ else {
1571
+ arrayBuffer = sliced;
1572
+ }
1573
+ }
1574
+ const uint = new Uint8Array(arrayBuffer);
1575
+ const imageBlob = new Blob([uint]);
1576
+ return URL.createObjectURL(imageBlob);
1577
+ }
1578
+ async function resolveTxId(txId) {
1579
+ const local = await tryLocalBlobUrlFromTxId(txId);
1580
+ if (local) {
1581
+ return { status: 'ready', href: local, source: 'localBlob' };
1582
+ }
1583
+ return {
1584
+ status: 'ready',
1585
+ href: BaseArweaveClient.getRawUrl(txId),
1586
+ source: 'gateway',
1587
+ };
1588
+ }
1589
+ /**
1590
+ * Resolve a classified media reference to a display URL (https/blob/data), using local files when present.
1591
+ */
1592
+ async function resolveMediaRef(raw, options) {
1593
+ const classification = classifyMediaRef(raw, options);
1594
+ switch (classification.kind) {
1595
+ case 'empty':
1596
+ return { status: 'empty' };
1597
+ case 'url':
1598
+ return {
1599
+ status: 'ready',
1600
+ href: classification.href,
1601
+ source: 'direct',
1602
+ };
1603
+ case 'seedLocalId':
1604
+ return {
1605
+ status: 'unresolved',
1606
+ reason: 'seed_local_id_not_portable',
1607
+ classification,
1608
+ };
1609
+ case 'unknown':
1610
+ return {
1611
+ status: 'unresolved',
1612
+ reason: 'unknown_ref',
1613
+ classification,
1614
+ };
1615
+ case 'arweaveTxId':
1616
+ return resolveTxId(classification.txId);
1617
+ case 'seedUid': {
1618
+ const appDb = BaseDb.getAppDb();
1619
+ if (!appDb) {
1620
+ return {
1621
+ status: 'unresolved',
1622
+ reason: 'seed_uid_requires_app_db',
1623
+ classification,
1624
+ };
1625
+ }
1626
+ const storageTransactionId = await getStorageTransactionIdForSeedUid(classification.uid);
1627
+ if (!storageTransactionId) {
1628
+ return {
1629
+ status: 'unresolved',
1630
+ reason: 'seed_uid_no_storage_transaction',
1631
+ classification,
1632
+ };
1633
+ }
1634
+ return resolveTxId(storageTransactionId);
1635
+ }
1636
+ default:
1637
+ return {
1638
+ status: 'unresolved',
1639
+ reason: 'unknown_ref',
1640
+ classification,
1641
+ };
1642
+ }
1643
+ }
1644
+ /**
1645
+ * Read a string field from a parsed item, trying camelCase and snake_case keys.
1646
+ */
1647
+ function getFeedItemStringField(item, key) {
1648
+ const direct = coalesceStringField(item, key);
1649
+ if (direct)
1650
+ return direct;
1651
+ const snake = key.replace(/[A-Z]/g, (l) => `_${l.toLowerCase()}`);
1652
+ if (snake !== key) {
1653
+ const alt = coalesceStringField(item, snake);
1654
+ if (alt)
1655
+ return alt;
1656
+ }
1657
+ const parts = key.split('_');
1658
+ if (parts.length > 1) {
1659
+ const camel = parts[0] + parts.slice(1).map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join('');
1660
+ const alt2 = coalesceStringField(item, camel);
1661
+ if (alt2)
1662
+ return alt2;
1663
+ }
1664
+ return '';
1665
+ }
1666
+ /**
1667
+ * Apply a field manifest to a plain feed item: classify media/file fields; pass through html/text.
1668
+ */
1669
+ function normalizeFeedItemFields(item, manifest) {
1670
+ const out = {};
1671
+ for (const [fieldKey, descriptor] of Object.entries(manifest)) {
1672
+ const raw = getFeedItemStringField(item, fieldKey);
1673
+ if (!raw) {
1674
+ out[fieldKey] = undefined;
1675
+ continue;
1676
+ }
1677
+ if (descriptor.role === 'html') {
1678
+ out[fieldKey] = { role: 'html', raw };
1679
+ continue;
1680
+ }
1681
+ if (descriptor.role === 'text') {
1682
+ out[fieldKey] = { role: 'text', raw };
1683
+ continue;
1684
+ }
1685
+ const classification = classifyMediaRef(raw, { treatAs: descriptor.treatAs });
1686
+ out[fieldKey] = {
1687
+ role: descriptor.role,
1688
+ raw,
1689
+ classification,
1690
+ };
1691
+ }
1692
+ return out;
1693
+ }
1694
+
1695
+ /**
1696
+ * True when the value is not a real EAS attestation UID stored in SQLite
1697
+ * (missing, empty, legacy 'NULL' sentinel, or zero bytes32).
1698
+ */
1699
+ function isPlaceholderUid(value) {
1700
+ if (value == null || value === '')
1701
+ return true;
1702
+ if (value === 'NULL')
1703
+ return true;
1704
+ const v = value.trim();
1705
+ if (v === '')
1706
+ return true;
1707
+ if (v.toLowerCase() === ZERO_BYTES32.toLowerCase())
1708
+ return true;
1709
+ return false;
1710
+ }
1711
+ /**
1712
+ * Strict EAS attestation UID: 0x-prefixed 32-byte hex (case-insensitive 0x / hex body).
1713
+ * Excludes placeholders and ZERO_BYTES32.
1714
+ */
1715
+ function isValidEasAttestationUid(value) {
1716
+ if (isPlaceholderUid(value))
1717
+ return false;
1718
+ const v = String(value).trim();
1719
+ if (!/^0x/i.test(v))
1720
+ return false;
1721
+ const hex = v.slice(2);
1722
+ if (hex.length !== 64)
1723
+ return false;
1724
+ return /^[0-9a-fA-F]{64}$/.test(hex);
1725
+ }
1726
+ /** Normalize bytes32 hex strings for case-insensitive comparison (schema UIDs, etc.). */
1727
+ function normalizeBytes32Hex(value) {
1728
+ if (value == null || value === '')
1729
+ return '';
1730
+ const raw = String(value).trim();
1731
+ const body = raw.startsWith('0x') || raw.startsWith('0X') ? raw.slice(2) : raw;
1732
+ const hex = body.replace(/[^0-9a-fA-F]/g, '0').padStart(64, '0').slice(-64);
1733
+ return ('0x' + hex).toLowerCase();
1192
1734
  }
1193
1735
 
1194
1736
  function pickLatestPropertyAttestationsByRefAndSchema(attestations) {
@@ -1378,6 +1920,7 @@ var index = /*#__PURE__*/Object.freeze({
1378
1920
  BaseFileManager: BaseFileManager,
1379
1921
  BaseQueryClient: BaseQueryClient,
1380
1922
  capitalizeFirstLetter: capitalizeFirstLetter,
1923
+ classifyMediaRef: classifyMediaRef,
1381
1924
  convertTxIdToImage: convertTxIdToImage,
1382
1925
  generateId: generateId,
1383
1926
  getAlternatePropertyNameForInstanceLookup: getAlternatePropertyNameForInstanceLookup,
@@ -1386,6 +1929,7 @@ var index = /*#__PURE__*/Object.freeze({
1386
1929
  getCorrectId: getCorrectId,
1387
1930
  getDataTypeFromString: getDataTypeFromString,
1388
1931
  getExecutionTime: getExecutionTime,
1932
+ getFeedItemStringField: getFeedItemStringField,
1389
1933
  getGetAdditionalSyncAddresses: getGetAdditionalSyncAddresses,
1390
1934
  getGetPublisherForNewSeeds: getGetPublisherForNewSeeds,
1391
1935
  getMetadataPropertyNamesForQuery: getMetadataPropertyNamesForQuery,
@@ -1399,13 +1943,18 @@ var index = /*#__PURE__*/Object.freeze({
1399
1943
  identifyString: identifyString,
1400
1944
  isArweaveL1AnchoringComplete: isArweaveL1AnchoringComplete,
1401
1945
  isBinary: isBinary,
1946
+ isPlaceholderUid: isPlaceholderUid,
1947
+ isValidEasAttestationUid: isValidEasAttestationUid,
1402
1948
  listRelationStoragePropertyName: listRelationStoragePropertyName,
1403
1949
  needsMetadataIdSuffix: needsMetadataIdSuffix,
1950
+ normalizeBytes32Hex: normalizeBytes32Hex,
1951
+ normalizeFeedItemFields: normalizeFeedItemFields,
1404
1952
  normalizeRelationPropertyValue: normalizeRelationPropertyValue,
1405
1953
  normalizeUploadApiBaseUrl: normalizeUploadApiBaseUrl,
1406
1954
  parseEasRelationPropertyName: parseEasRelationPropertyName,
1407
1955
  pickLatestPropertyAttestationsByRefAndSchema: pickLatestPropertyAttestationsByRefAndSchema,
1408
1956
  queryArweaveGatewayTransaction: queryArweaveGatewayTransaction,
1957
+ resolveMediaRef: resolveMediaRef,
1409
1958
  resolveMetadataRecord: resolveMetadataRecord,
1410
1959
  resolveSeedIdsFromRefString: resolveSeedIdsFromRefString,
1411
1960
  resolveStorageNameToSchemaName: resolveStorageNameToSchemaName,
@@ -1431,7 +1980,7 @@ const createPropertyInstances = async (propertyFileIds) => {
1431
1980
  return;
1432
1981
  }
1433
1982
  try {
1434
- const mod = await Promise.resolve().then(function () { return require('./ModelProperty-Cuj839nX.js'); });
1983
+ const mod = await Promise.resolve().then(function () { return require('./ModelProperty-sNx_ZQZX.js'); });
1435
1984
  const ModelProperty = mod?.ModelProperty ?? mod?.default;
1436
1985
  if (!ModelProperty) {
1437
1986
  logger$y('createPropertyInstances: ModelProperty not available from dynamic import');
@@ -1615,7 +2164,7 @@ const loadOrCreateModel = xstate.fromCallback(({ sendBack, input: { context } })
1615
2164
  // Step 2: Fallback to Schema context (only if database doesn't have the model)
1616
2165
  // This handles the case where model exists in schema file but not yet in database
1617
2166
  try {
1618
- const schemaMod = await Promise.resolve().then(function () { return require('./Schema-TFe24NNG.js'); });
2167
+ const schemaMod = await Promise.resolve().then(function () { return require('./Schema-B4RRA-0g.js'); });
1619
2168
  const { Schema } = schemaMod;
1620
2169
  const schema = Schema.create(schemaName, { waitForReady: false });
1621
2170
  const schemaSnapshot = schema.getService().getSnapshot();
@@ -1859,7 +2408,7 @@ const loadOrCreateModel = xstate.fromCallback(({ sendBack, input: { context } })
1859
2408
  }
1860
2409
  // Mark schema as draft when a new model is created so saveNewVersion() can persist it
1861
2410
  try {
1862
- const schemaMod = await Promise.resolve().then(function () { return require('./Schema-TFe24NNG.js'); });
2411
+ const schemaMod = await Promise.resolve().then(function () { return require('./Schema-B4RRA-0g.js'); });
1863
2412
  const { Schema } = schemaMod;
1864
2413
  const schema = Schema.create(schemaName, { waitForReady: false });
1865
2414
  schema.getService().send({ type: 'markAsDraft', propertyKey: 'schema:models' });
@@ -1903,10 +2452,10 @@ const validateModel = xstate.fromCallback(({ sendBack, input: { context } }) =>
1903
2452
  const _validateModel = async () => {
1904
2453
  try {
1905
2454
  // Use dynamic imports to break circular dependencies
1906
- const validationServiceMod = await Promise.resolve().then(function () { return require('./SchemaValidationService-DVQrRpse.js'); });
2455
+ const validationServiceMod = await Promise.resolve().then(function () { return require('./SchemaValidationService-DCflhpcI.js'); });
1907
2456
  const { SchemaValidationService } = validationServiceMod;
1908
2457
  const validationService = new SchemaValidationService();
1909
- const schemaMod = await Promise.resolve().then(function () { return require('./Schema-TFe24NNG.js'); });
2458
+ const schemaMod = await Promise.resolve().then(function () { return require('./Schema-B4RRA-0g.js'); });
1910
2459
  const { Schema } = schemaMod;
1911
2460
  // Validate model structure
1912
2461
  const structureResult = validationService.validateModelStructure(context);
@@ -2016,7 +2565,7 @@ const createModelProperties = xstate.fromCallback(({ sendBack, input }) => {
2016
2565
  return;
2017
2566
  }
2018
2567
  logger$w(`Creating ${Object.keys(propertyDefinitions).length} properties for model "${modelName}" (id: ${_dbId})`);
2019
- const mod = await Promise.resolve().then(function () { return require('./ModelProperty-Cuj839nX.js'); });
2568
+ const mod = await Promise.resolve().then(function () { return require('./ModelProperty-sNx_ZQZX.js'); });
2020
2569
  const ModelProperty = mod?.ModelProperty ?? mod?.default;
2021
2570
  if (!ModelProperty) {
2022
2571
  logger$w('ModelProperty not available from dynamic import');
@@ -2120,7 +2669,7 @@ const validateEntity = xstate.fromPromise(async ({ input }) => {
2120
2669
  const structureMsg = `[validateEntity] Validating model structure`;
2121
2670
  logger$v(structureMsg);
2122
2671
  // Use existing Model validation
2123
- const validationServiceMod = await Promise.resolve().then(function () { return require('./SchemaValidationService-DVQrRpse.js'); });
2672
+ const validationServiceMod = await Promise.resolve().then(function () { return require('./SchemaValidationService-DCflhpcI.js'); });
2124
2673
  const { SchemaValidationService } = validationServiceMod;
2125
2674
  const validationService = new SchemaValidationService();
2126
2675
  // Validate model structure
@@ -2138,7 +2687,7 @@ const validateEntity = xstate.fromPromise(async ({ input }) => {
2138
2687
  if (entityInput.entityData.schemaName) {
2139
2688
  try {
2140
2689
  logger$v(`[validateEntity] Validating model against schema "${entityInput.entityData.schemaName}"`);
2141
- const schemaMod = await Promise.resolve().then(function () { return require('./Schema-TFe24NNG.js'); });
2690
+ const schemaMod = await Promise.resolve().then(function () { return require('./Schema-B4RRA-0g.js'); });
2142
2691
  const { Schema } = schemaMod;
2143
2692
  const schema = Schema.create(entityInput.entityData.schemaName, {
2144
2693
  waitForReady: false,
@@ -2174,7 +2723,7 @@ const validateEntity = xstate.fromPromise(async ({ input }) => {
2174
2723
  }
2175
2724
  else if (entityInput.entityType === 'modelProperty') {
2176
2725
  // Use existing ModelProperty validation
2177
- const validationServiceMod = await Promise.resolve().then(function () { return require('./SchemaValidationService-DVQrRpse.js'); });
2726
+ const validationServiceMod = await Promise.resolve().then(function () { return require('./SchemaValidationService-DCflhpcI.js'); });
2178
2727
  const { SchemaValidationService } = validationServiceMod;
2179
2728
  const validationService = new SchemaValidationService();
2180
2729
  // Validate property structure
@@ -2189,7 +2738,7 @@ const validateEntity = xstate.fromPromise(async ({ input }) => {
2189
2738
  // If schema name and model name provided, validate against schema
2190
2739
  if (entityInput.entityData._schemaName && entityInput.entityData.modelName) {
2191
2740
  try {
2192
- const schemaMod = await Promise.resolve().then(function () { return require('./Schema-TFe24NNG.js'); });
2741
+ const schemaMod = await Promise.resolve().then(function () { return require('./Schema-B4RRA-0g.js'); });
2193
2742
  const { Schema } = schemaMod;
2194
2743
  const schema = Schema.create(entityInput.entityData._schemaName, {
2195
2744
  waitForReady: false,
@@ -2218,7 +2767,7 @@ const validateEntity = xstate.fromPromise(async ({ input }) => {
2218
2767
  }
2219
2768
  else if (entityInput.entityType === 'schema') {
2220
2769
  // Schema validation - use existing validation
2221
- const validationServiceMod = await Promise.resolve().then(function () { return require('./SchemaValidationService-DVQrRpse.js'); });
2770
+ const validationServiceMod = await Promise.resolve().then(function () { return require('./SchemaValidationService-DCflhpcI.js'); });
2222
2771
  const { SchemaValidationService } = validationServiceMod;
2223
2772
  const validationService = new SchemaValidationService();
2224
2773
  const schemaResult = validationService.validateSchema(entityInput.entityData);
@@ -2247,202 +2796,6 @@ const validateEntity = xstate.fromPromise(async ({ input }) => {
2247
2796
  // @ts-ignore - XState v5 type inference bug: fromPromise incorrectly expects output type to match input type
2248
2797
  });
2249
2798
 
2250
- const seeds = sqliteCore.sqliteTable('seeds', {
2251
- localId: sqliteCore.text('local_id').unique(),
2252
- uid: sqliteCore.text('uid'),
2253
- schemaUid: sqliteCore.text('schema_uid'),
2254
- type: sqliteCore.text('type'),
2255
- publisher: sqliteCore.text('publisher'),
2256
- attestationRaw: sqliteCore.text('attestation_raw'),
2257
- attestationCreatedAt: sqliteCore.int('attestation_created_at'),
2258
- createdAt: sqliteCore.int('created_at'),
2259
- updatedAt: sqliteCore.int('updated_at'),
2260
- _markedForDeletion: sqliteCore.int('_marked_for_deletion'),
2261
- revokedAt: sqliteCore.int('revoked_at'),
2262
- });
2263
-
2264
- const versions = sqliteCore.sqliteTable('versions', {
2265
- localId: sqliteCore.text('local_id').unique(),
2266
- uid: sqliteCore.text('uid'),
2267
- seedLocalId: sqliteCore.text('seed_local_id'),
2268
- seedUid: sqliteCore.text('seed_uid'),
2269
- seedType: sqliteCore.text('seed_type'),
2270
- note: sqliteCore.text('note'),
2271
- createdAt: sqliteCore.int('created_at'),
2272
- updatedAt: sqliteCore.int('updated_at'),
2273
- attestationCreatedAt: sqliteCore.int('attestation_created_at'),
2274
- attestationRaw: sqliteCore.text('attestation_raw'),
2275
- publisher: sqliteCore.text('publisher'),
2276
- });
2277
-
2278
- const metadata$1 = sqliteCore.sqliteTable('metadata', {
2279
- localId: sqliteCore.text('local_id').unique(),
2280
- uid: sqliteCore.text('uid'),
2281
- propertyId: sqliteCore.integer('property_id').references(() => properties.id),
2282
- propertyName: sqliteCore.text('property_name'),
2283
- propertyValue: sqliteCore.text('property_value'),
2284
- schemaUid: sqliteCore.text('schema_uid'),
2285
- modelType: sqliteCore.text('model_type'),
2286
- seedLocalId: sqliteCore.text('seed_local_id'),
2287
- seedUid: sqliteCore.text('seed_uid'),
2288
- versionLocalId: sqliteCore.text('version_local_id'),
2289
- versionUid: sqliteCore.text('version_uid'),
2290
- easDataType: sqliteCore.text('eas_data_type'),
2291
- refValueType: sqliteCore.text('ref_value_type'),
2292
- refModelUid: sqliteCore.text('ref_schema_uid'),
2293
- refSeedType: sqliteCore.text('ref_seed_type'),
2294
- refResolvedValue: sqliteCore.text('ref_resolved_value'),
2295
- refResolvedDisplayValue: sqliteCore.text('ref_resolved_display_value'),
2296
- localStorageDir: sqliteCore.text('local_storage_dir'),
2297
- attestationRaw: sqliteCore.text('attestation_raw'),
2298
- attestationCreatedAt: sqliteCore.int('attestation_created_at'),
2299
- contentHash: sqliteCore.text('content_hash'),
2300
- createdAt: sqliteCore.int('created_at'),
2301
- updatedAt: sqliteCore.int('updated_at'),
2302
- publisher: sqliteCore.text('publisher'),
2303
- });
2304
-
2305
- const appState = sqliteCore.sqliteTable('appState', {
2306
- key: sqliteCore.text('key').unique(),
2307
- value: sqliteCore.text('value'),
2308
- createdAt: sqliteCore.int('created_at'),
2309
- updatedAt: sqliteCore.int('updated_at'),
2310
- });
2311
-
2312
- const modelUids = sqliteCore.sqliteTable('model_uids', {
2313
- id: sqliteCore.int('id').primaryKey({ autoIncrement: true }),
2314
- uid: sqliteCore.text('uid').notNull(),
2315
- modelId: sqliteCore.int('model_id')
2316
- .notNull()
2317
- .unique()
2318
- .references(() => models$1.id),
2319
- });
2320
- const modelRelations = drizzleOrm.relations(modelUids, ({ one }) => ({
2321
- model: one(models$1),
2322
- }));
2323
-
2324
- const propertyUids = sqliteCore.sqliteTable('property_uids', {
2325
- id: sqliteCore.int('id').primaryKey({ autoIncrement: true }),
2326
- uid: sqliteCore.text('uid').notNull(),
2327
- propertyId: sqliteCore.int('property_id')
2328
- .notNull()
2329
- .unique()
2330
- .references(() => properties.id),
2331
- });
2332
- const propertyUidRelations = drizzleOrm.relations(propertyUids, ({ one }) => ({
2333
- property: one(properties),
2334
- }));
2335
-
2336
- const config = sqliteCore.sqliteTable('config', {
2337
- id: sqliteCore.integer('id').primaryKey({ autoIncrement: true }),
2338
- key: sqliteCore.text('key').notNull(),
2339
- text: sqliteCore.text('text'),
2340
- json: sqliteCore.text('json'),
2341
- blob: sqliteCore.blob('blob'),
2342
- });
2343
-
2344
- const schemas = sqliteCore.sqliteTable('schemas', {
2345
- id: sqliteCore.integer('id').primaryKey({ autoIncrement: true }),
2346
- name: sqliteCore.text('name').notNull(),
2347
- version: sqliteCore.integer('version').notNull(),
2348
- schemaFileId: sqliteCore.text('schema_file_id'), // ID from JSON file for change tracking - must be unique
2349
- schemaData: sqliteCore.text('schema_data'), // Full JSON schema content (SchemaFileFormat as JSON string)
2350
- isDraft: sqliteCore.integer('is_draft', { mode: 'boolean' }), // true if schema is in draft/editing state, false if published to file
2351
- isEdited: sqliteCore.integer('is_edited', { mode: 'boolean' }), // true if schema has been edited locally, false if matches schema file
2352
- createdAt: sqliteCore.int('created_at'),
2353
- updatedAt: sqliteCore.int('updated_at'),
2354
- }, (table) => {
2355
- return {
2356
- uniqueSchemaFileId: sqliteCore.unique('unique_schema_schema_file_id').on(table.schemaFileId),
2357
- };
2358
- });
2359
-
2360
- var SchemaSchema = /*#__PURE__*/Object.freeze({
2361
- __proto__: null,
2362
- schemas: schemas
2363
- });
2364
-
2365
- const modelSchemas = sqliteCore.sqliteTable('model_schemas', {
2366
- id: sqliteCore.integer('id').primaryKey({ autoIncrement: true }),
2367
- modelId: sqliteCore.integer('model_id').references(() => models$1.id),
2368
- schemaId: sqliteCore.integer('schema_id').references(() => schemas.id),
2369
- });
2370
-
2371
- var ModelSchemaSchema = /*#__PURE__*/Object.freeze({
2372
- __proto__: null,
2373
- modelSchemas: modelSchemas
2374
- });
2375
-
2376
- const publishProcesses = sqliteCore.sqliteTable('publish_processes', {
2377
- id: sqliteCore.int('id').primaryKey({ autoIncrement: true }),
2378
- seedLocalId: sqliteCore.text('seed_local_id').notNull(),
2379
- modelName: sqliteCore.text('model_name').notNull(),
2380
- schemaId: sqliteCore.text('schema_id'),
2381
- status: sqliteCore.text('status').notNull(), // 'in_progress' | 'completed' | 'failed' | 'interrupted'
2382
- startedAt: sqliteCore.int('started_at').notNull(),
2383
- completedAt: sqliteCore.int('completed_at'),
2384
- errorMessage: sqliteCore.text('error_message'),
2385
- errorStep: sqliteCore.text('error_step'),
2386
- errorDetails: sqliteCore.text('error_details'),
2387
- persistedSnapshot: sqliteCore.text('persisted_snapshot').notNull(),
2388
- seedId: sqliteCore.text('seed_id'),
2389
- existingSeedUid: sqliteCore.text('existing_seed_uid'),
2390
- createdAt: sqliteCore.int('created_at'),
2391
- updatedAt: sqliteCore.int('updated_at'),
2392
- });
2393
-
2394
- const uploadProcesses = sqliteCore.sqliteTable('upload_processes', {
2395
- id: sqliteCore.int('id').primaryKey({ autoIncrement: true }),
2396
- reimbursementConfirmed: sqliteCore.int('reimbursement_confirmed').notNull(), // 0 or 1 for boolean
2397
- reimbursementTransactionId: sqliteCore.text('reimbursement_transaction_id'),
2398
- transactionKeys: sqliteCore.text('transaction_keys'),
2399
- persistedSnapshot: sqliteCore.text('persisted_snapshot').notNull(), // JSON string
2400
- createdAt: sqliteCore.int('created_at'),
2401
- updatedAt: sqliteCore.int('updated_at'),
2402
- });
2403
-
2404
- /** Background job: resolve L1 tx id and wait for L1 confirmation after bundler publish. */
2405
- const arweaveL1FinalizeJobs = sqliteCore.sqliteTable('arweave_l1_finalize_jobs', {
2406
- id: sqliteCore.int('id').primaryKey({ autoIncrement: true }),
2407
- seedLocalId: sqliteCore.text('seed_local_id').notNull(),
2408
- dataItemId: sqliteCore.text('data_item_id').notNull(),
2409
- /** L1 bundle / anchor transaction id from gateway GraphQL `bundledIn.id`. */
2410
- l1TransactionId: sqliteCore.text('l1_transaction_id'),
2411
- bundleId: sqliteCore.text('bundle_id'),
2412
- versionLocalId: sqliteCore.text('version_local_id'),
2413
- itemPropertyName: sqliteCore.text('item_property_name'),
2414
- /** `pending_l1` | `confirmed` | `failed` */
2415
- phase: sqliteCore.text('phase').notNull(),
2416
- statusJson: sqliteCore.text('status_json'),
2417
- errorMessage: sqliteCore.text('error_message'),
2418
- createdAt: sqliteCore.int('created_at').notNull(),
2419
- updatedAt: sqliteCore.int('updated_at').notNull(),
2420
- }, (table) => ({
2421
- dataItemIdUnique: sqliteCore.uniqueIndex('arweave_l1_finalize_jobs_data_item_id_unique').on(table.dataItemId),
2422
- }));
2423
-
2424
- var schema$1 = /*#__PURE__*/Object.freeze({
2425
- __proto__: null,
2426
- appState: appState,
2427
- arweaveL1FinalizeJobs: arweaveL1FinalizeJobs,
2428
- config: config,
2429
- metadata: metadata$1,
2430
- modelRelations: modelRelations,
2431
- modelSchemas: modelSchemas,
2432
- modelUids: modelUids,
2433
- models: models$1,
2434
- modelsRelations: modelsRelations,
2435
- properties: properties,
2436
- propertiesRelations: propertiesRelations,
2437
- propertyUidRelations: propertyUidRelations,
2438
- propertyUids: propertyUids,
2439
- publishProcesses: publishProcesses,
2440
- schemas: schemas,
2441
- seeds: seeds,
2442
- uploadProcesses: uploadProcesses,
2443
- versions: versions
2444
- });
2445
-
2446
2799
  const logger$u = debug('seedSdk:helpers:db');
2447
2800
  /**
2448
2801
  * Resolve property_id from model name/type and property name.
@@ -4366,7 +4719,7 @@ const writeToDatabase = xstate.fromCallback(({ sendBack, input }) => {
4366
4719
  // initial write completes is not overwritten by the stale requestWrite payload.
4367
4720
  let dataToWrite = input.entityData;
4368
4721
  try {
4369
- const mod = await Promise.resolve().then(function () { return require('./ModelProperty-Cuj839nX.js'); });
4722
+ const mod = await Promise.resolve().then(function () { return require('./ModelProperty-sNx_ZQZX.js'); });
4370
4723
  const ModelProperty = mod?.ModelProperty ?? mod?.default;
4371
4724
  if (ModelProperty && typeof ModelProperty.getById === 'function') {
4372
4725
  const instance = ModelProperty.getById(input.entityId);
@@ -4746,7 +5099,7 @@ const modelMachine = xstate.setup({
4746
5099
  // Create ModelProperty instances for any new property IDs
4747
5100
  if (Array.isArray(newPropertyIds) && newPropertyIds.length > 0) {
4748
5101
  // Import and create instances asynchronously (fire-and-forget)
4749
- Promise.resolve().then(function () { return require('./ModelProperty-Cuj839nX.js'); }).then(({ ModelProperty }) => {
5102
+ Promise.resolve().then(function () { return require('./ModelProperty-sNx_ZQZX.js'); }).then(({ ModelProperty }) => {
4750
5103
  const createPromises = newPropertyIds.map(async (propertyFileId) => {
4751
5104
  try {
4752
5105
  const property = await ModelProperty.createById(propertyFileId);
@@ -5780,9 +6133,9 @@ const createVersion = async ({ seedLocalId, seedUid, seedType, uid, }) => {
5780
6133
  localId: newVersionLocalId,
5781
6134
  createdAt: Date.now(),
5782
6135
  seedLocalId,
5783
- seedUid: seedUid ?? 'NULL',
6136
+ seedUid: seedUid ?? null,
5784
6137
  seedType,
5785
- uid: uid || 'NULL',
6138
+ uid: uid ?? null,
5786
6139
  ...(publisher != null && publisher !== '' && { publisher }),
5787
6140
  });
5788
6141
  return newVersionLocalId;
@@ -5797,12 +6150,12 @@ const hydrateNewItem = xstate.fromCallback(({ sendBack, input: { context } }) =>
5797
6150
  }
5798
6151
  newSeedLocalId = await createSeed({
5799
6152
  type: modelName.toLowerCase(),
5800
- seedUid: seedUid ?? 'NULL',
6153
+ ...(seedUid && seedUid !== 'NULL' ? { seedUid } : {}),
5801
6154
  });
5802
6155
  await createVersion({
5803
6156
  seedLocalId: newSeedLocalId,
5804
6157
  seedType: modelName.toLowerCase(),
5805
- uid: versionUid ?? 'NULL',
6158
+ ...(versionUid && versionUid !== 'NULL' ? { uid: versionUid } : {}),
5806
6159
  });
5807
6160
  };
5808
6161
  _hydrateNewItem().then(() => {
@@ -5934,28 +6287,145 @@ const reload = xstate.fromCallback(({ sendBack, input: { context } }) => {
5934
6287
  });
5935
6288
  });
5936
6289
 
6290
+ /**
6291
+ * Per-seed aggregates (all versions) plus the latest version row by
6292
+ * (created_at DESC, local_id DESC) via max(created_at) then max(local_id) tie-break.
6293
+ *
6294
+ * For `publishedVersionUid` / `publishedVersionLocalId` on list rows, see `getItemsData`
6295
+ * (batched resolution aligned with `getLatestPublishedVersionRow`).
6296
+ */
5937
6297
  const getVersionData$1 = () => {
5938
6298
  const appDb = BaseDb.getAppDb();
6299
+ const versionStats = appDb.$with('version_stats').as(appDb
6300
+ .select({
6301
+ seedLocalId: versions.seedLocalId,
6302
+ versionsCount: drizzleOrm.count(versions.localId).as('versionsCount'),
6303
+ lastVersionPublishedAt: drizzleOrm.max(versions.attestationCreatedAt).as('lastVersionPublishedAt'),
6304
+ lastLocalUpdateAt: drizzleOrm.max(versions.createdAt).as('lastLocalUpdateAt'),
6305
+ maxCreatedAt: drizzleOrm.max(versions.createdAt).as('maxCreatedAt'),
6306
+ })
6307
+ .from(versions)
6308
+ .groupBy(versions.seedLocalId));
6309
+ const latestVersionIds = appDb.$with('latest_version_ids').as(appDb
6310
+ .with(versionStats)
6311
+ .select({
6312
+ seedLocalId: versions.seedLocalId,
6313
+ latestVersionLocalId: drizzleOrm.max(versions.localId).as('latestVersionLocalId'),
6314
+ })
6315
+ .from(versions)
6316
+ .innerJoin(versionStats, drizzleOrm.and(drizzleOrm.eq(versions.seedLocalId, versionStats.seedLocalId), drizzleOrm.eq(versions.createdAt, versionStats.maxCreatedAt)))
6317
+ .groupBy(versions.seedLocalId));
5939
6318
  return appDb.$with('versionData').as(appDb
6319
+ .with(versionStats, latestVersionIds)
6320
+ .select({
6321
+ seedLocalId: versionStats.seedLocalId,
6322
+ seedUid: versions.seedUid,
6323
+ latestVersionUid: versions.uid,
6324
+ latestVersionLocalId: latestVersionIds.latestVersionLocalId,
6325
+ versionsCount: versionStats.versionsCount,
6326
+ lastVersionPublishedAt: versionStats.lastVersionPublishedAt,
6327
+ lastLocalUpdateAt: versionStats.lastLocalUpdateAt,
6328
+ })
6329
+ .from(versionStats)
6330
+ .innerJoin(latestVersionIds, drizzleOrm.eq(versionStats.seedLocalId, latestVersionIds.seedLocalId))
6331
+ .innerJoin(versions, drizzleOrm.and(drizzleOrm.eq(versions.seedLocalId, latestVersionIds.seedLocalId), drizzleOrm.eq(versions.localId, latestVersionIds.latestVersionLocalId))));
6332
+ };
6333
+
6334
+ var versionData = /*#__PURE__*/Object.freeze({
6335
+ __proto__: null,
6336
+ getVersionData: getVersionData$1
6337
+ });
6338
+
6339
+ const getMetadataLatest = ({ seedLocalId, seedUid }) => {
6340
+ const appDb = BaseDb.getAppDb();
6341
+ const whereClauses = [];
6342
+ if (seedLocalId && seedUid) {
6343
+ const orClause = drizzleOrm.or(drizzleOrm.eq(metadata$1.seedLocalId, seedLocalId), drizzleOrm.eq(metadata$1.seedUid, seedUid));
6344
+ if (orClause)
6345
+ whereClauses.push(orClause);
6346
+ }
6347
+ else if (seedLocalId) {
6348
+ whereClauses.push(drizzleOrm.eq(metadata$1.seedLocalId, seedLocalId));
6349
+ }
6350
+ else if (seedUid) {
6351
+ whereClauses.push(drizzleOrm.eq(metadata$1.seedUid, seedUid));
6352
+ }
6353
+ const metadataColumns = drizzleOrm.getTableColumns(metadata$1);
6354
+ return appDb.$with('metadataLatest').as(appDb
5940
6355
  .select({
5941
- seedLocalId: versions.seedLocalId,
5942
- seedUid: versions.seedUid,
5943
- latestVersionUid: versions.uid,
5944
- latestVersionLocalId: versions.localId,
5945
- versionsCount: drizzleOrm.count(versions.localId).as('versionsCount'),
5946
- lastVersionPublishedAt: drizzleOrm.max(versions.attestationCreatedAt).as('lastVersionPublishedAt'),
5947
- lastLocalUpdateAt: drizzleOrm.max(versions.createdAt).as('lastLocalUpdateAt'),
6356
+ ...metadataColumns,
6357
+ rowNum: drizzleOrm.sql.raw(`
6358
+ ROW_NUMBER() OVER (
6359
+ PARTITION BY property_name
6360
+ ORDER BY COALESCE(attestation_created_at, created_at) DESC
6361
+ )
6362
+ `).as('rowNum')
5948
6363
  })
5949
- .from(versions)
5950
- .groupBy(versions.seedLocalId));
6364
+ .from(metadata$1)
6365
+ .where(drizzleOrm.and(...whereClauses)));
5951
6366
  };
5952
6367
 
5953
- var versionData = /*#__PURE__*/Object.freeze({
6368
+ var metadataLatest = /*#__PURE__*/Object.freeze({
5954
6369
  __proto__: null,
5955
- getVersionData: getVersionData$1
6370
+ getMetadataLatest: getMetadataLatest
5956
6371
  });
5957
6372
 
5958
6373
  const logger$q = debug('seedSdk:item:actors:loadOrCreateItem');
6374
+ /**
6375
+ * Maps metadata.property_name to the ItemProperty Map key (same rules as the instance loop below).
6376
+ */
6377
+ function normalizeMetadataRowToInstanceKey(metaRow, propertySchemas) {
6378
+ let propertyName = metaRow.propertyName;
6379
+ if (!propertyName)
6380
+ return undefined;
6381
+ const listSchemaKey = resolveStorageNameToSchemaName(propertySchemas, propertyName);
6382
+ if (listSchemaKey) {
6383
+ propertyName = listSchemaKey;
6384
+ }
6385
+ else {
6386
+ const baseName = toSchemaPropertyName(propertyName);
6387
+ const refSeedType = metaRow.refSeedType;
6388
+ const isRefTypeFromMeta = refSeedType === 'file' ||
6389
+ refSeedType === 'image' ||
6390
+ refSeedType === 'relation' ||
6391
+ refSeedType === 'html';
6392
+ if (baseName && (propertySchemas[baseName] || isRefTypeFromMeta)) {
6393
+ propertyName = baseName;
6394
+ }
6395
+ }
6396
+ return propertyName;
6397
+ }
6398
+ function metadataValueStrength(row) {
6399
+ const v = row?.propertyValue;
6400
+ if (v == null || v === '')
6401
+ return 0;
6402
+ return String(v).trim().length;
6403
+ }
6404
+ /** When storage + schema names map to the same key, prefer non-empty, then richer payload, then newer row. */
6405
+ function pickBetterMetadataRowForSameInstance(a, b) {
6406
+ const sa = metadataValueStrength(a);
6407
+ const sb = metadataValueStrength(b);
6408
+ if (sa > 0 && sb === 0)
6409
+ return a;
6410
+ if (sb > 0 && sa === 0)
6411
+ return b;
6412
+ if (sa !== sb)
6413
+ return sa > sb ? a : b;
6414
+ const ta = a.attestationCreatedAt ?? a.createdAt ?? 0;
6415
+ const tb = b.attestationCreatedAt ?? b.createdAt ?? 0;
6416
+ return ta >= tb ? a : b;
6417
+ }
6418
+ function dedupeMetadataRowsByInstanceKey(metadataRows, propertySchemas) {
6419
+ const byKey = new Map();
6420
+ for (const metaRow of metadataRows) {
6421
+ const key = normalizeMetadataRowToInstanceKey(metaRow, propertySchemas);
6422
+ if (!key)
6423
+ continue;
6424
+ const existing = byKey.get(key);
6425
+ byKey.set(key, existing ? pickBetterMetadataRowForSameInstance(existing, metaRow) : metaRow);
6426
+ }
6427
+ return Array.from(byKey.values());
6428
+ }
5959
6429
  /**
5960
6430
  * Create ItemProperty instances for all metadata records plus placeholder instances
5961
6431
  * for model schema properties that have no metadata. Ensures items (e.g. Image) have
@@ -5991,7 +6461,7 @@ const createItemPropertyInstances = async (metadataRows, seedLocalId, seedUid, m
5991
6461
  const schemaNameToTry = model$1?.schemaName;
5992
6462
  if (schemaNameToTry) {
5993
6463
  try {
5994
- const { Schema } = await Promise.resolve().then(function () { return require('./Schema-TFe24NNG.js'); });
6464
+ const { Schema } = await Promise.resolve().then(function () { return require('./Schema-B4RRA-0g.js'); });
5995
6465
  const schemaInstance = Schema.create(schemaNameToTry, { waitForReady: false });
5996
6466
  const schemaContext = schemaInstance.getService().getSnapshot().context;
5997
6467
  if (schemaContext.models?.[modelName]?.properties) {
@@ -6040,13 +6510,14 @@ const createItemPropertyInstances = async (metadataRows, seedLocalId, seedUid, m
6040
6510
  }
6041
6511
  }
6042
6512
  if (Object.keys(propertySchemas).length === 0) {
6043
- const schemaMod = await Promise.resolve().then(function () { return require('./index-CKJeh6ic.js'); });
6513
+ const schemaMod = await Promise.resolve().then(function () { return require('./index-DTkoTvcq.js'); });
6044
6514
  const { ModelPropertyDataTypes } = schemaMod;
6045
6515
  const KNOWN_MODEL_FALLBACKS = {
6046
6516
  Post: {
6047
6517
  html: { dataType: ModelPropertyDataTypes.Html },
6048
6518
  summary: { dataType: ModelPropertyDataTypes.Text },
6049
6519
  title: { dataType: ModelPropertyDataTypes.Text },
6520
+ authors: { dataType: ModelPropertyDataTypes.List, ref: 'Identity' },
6050
6521
  },
6051
6522
  };
6052
6523
  if (KNOWN_MODEL_FALLBACKS[modelName]) {
@@ -6055,17 +6526,14 @@ const createItemPropertyInstances = async (metadataRows, seedLocalId, seedUid, m
6055
6526
  }
6056
6527
  }
6057
6528
  }
6058
- // Build map of metadata by propertyName for lookup
6059
- const metadataByProperty = new Map();
6060
- for (const metaRow of metadataRows) {
6061
- if (metaRow.propertyName) {
6062
- metadataByProperty.set(metaRow.propertyName, metaRow);
6063
- }
6064
- }
6529
+ // Collapse rows that map to the same instance key (e.g. authorIdentityIds + authors -> authors).
6530
+ // ItemProperty.create cache does not sync propertyValue on hit; processing order would otherwise
6531
+ // let an empty "authors" row overwrite a populated storage row.
6532
+ const dedupedMetadataRows = dedupeMetadataRowsByInstanceKey(metadataRows, propertySchemas);
6065
6533
  // Create instances for all metadata records
6066
6534
  // For File/Image/Relation, metadata is stored with Id suffix (e.g. "textId") but schema defines base name ("text").
6067
6535
  // Normalize to schema name so we don't create duplicate properties (text + textId).
6068
- for (const metaRow of metadataRows) {
6536
+ for (const metaRow of dedupedMetadataRows) {
6069
6537
  try {
6070
6538
  let propertyName = metaRow.propertyName;
6071
6539
  if (!propertyName) {
@@ -6089,7 +6557,7 @@ const createItemPropertyInstances = async (metadataRows, seedLocalId, seedUid, m
6089
6557
  // Infer propertyRecordSchema from metadata when schema is missing (enables persistence)
6090
6558
  let propSchema = propertySchemas[propertyName];
6091
6559
  if (!propSchema && isRefTypeFromMeta) {
6092
- const schemaMod = await Promise.resolve().then(function () { return require('./index-CKJeh6ic.js'); });
6560
+ const schemaMod = await Promise.resolve().then(function () { return require('./index-DTkoTvcq.js'); });
6093
6561
  const { ModelPropertyDataTypes } = schemaMod;
6094
6562
  propSchema = {
6095
6563
  dataType: refSeedType === 'html' ? ModelPropertyDataTypes.Html
@@ -6279,18 +6747,26 @@ const loadOrCreateItem = xstate.fromCallback(({ sendBack, input: { context } })
6279
6747
  });
6280
6748
  return;
6281
6749
  }
6282
- // Step 3: Query metadata table to find all metadata records that reference that version
6750
+ // Step 3: Latest metadata row per property_name for this seed (matches loadOrCreateProperty /
6751
+ // getItemProperties). Strict version_local_id = latest would drop properties whose rows lag version bumps.
6752
+ const metadataLatest = getMetadataLatest({
6753
+ seedLocalId: resolvedSeedLocalId,
6754
+ seedUid: resolvedSeedUid,
6755
+ });
6283
6756
  const metadataRecords = await db
6757
+ .with(metadataLatest)
6284
6758
  .select()
6285
- .from(metadata$1)
6286
- .where(drizzleOrm.and(drizzleOrm.eq(metadata$1.seedLocalId, resolvedSeedLocalId), drizzleOrm.eq(metadata$1.versionLocalId, latestVersionLocalId)));
6287
- logger$q(`Found ${metadataRecords.length} metadata records for version ${latestVersionLocalId}`);
6759
+ .from(metadataLatest)
6760
+ .where(drizzleOrm.eq(metadataLatest.rowNum, 1));
6761
+ logger$q(`Found ${metadataRecords.length} latest-per-property metadata rows for seed ${resolvedSeedLocalId} (latestVersionLocalId=${latestVersionLocalId} used for placeholders only)`);
6288
6762
  // Step 4: Create ItemProperty instances from metadata records + placeholders for model schema properties
6289
6763
  // Always call when we have a valid version so placeholders are created for properties without metadata
6290
6764
  const propertyInstances = await createItemPropertyInstances(metadataRecords, resolvedSeedLocalId, resolvedSeedUid, modelName, latestVersionLocalId, latestVersionUid);
6291
6765
  // Step 4b: Wait for all property machines to reach idle so HTML/File content is loaded before Item is ready.
6292
6766
  // Without this, post.html returns seed ID on first render because loadOrCreateProperty hasn't finished.
6293
- await Promise.all(Array.from(propertyInstances.values()).map((prop) => waitForEntityIdle(prop, { timeout: 5000, throwOnError: false })));
6767
+ // Publish/attestation can keep properties in `saving` for many seconds; 5s caused timeouts during EAS work.
6768
+ const propertyIdleTimeoutMs = 120000;
6769
+ await Promise.all(Array.from(propertyInstances.values()).map((prop) => waitForEntityIdle(prop, { timeout: propertyIdleTimeoutMs, throwOnError: false })));
6294
6770
  // Step 5: Return loaded item data with property instances
6295
6771
  sendBack({
6296
6772
  type: 'loadOrCreateItemSuccess',
@@ -6307,6 +6783,7 @@ const loadOrCreateItem = xstate.fromCallback(({ sendBack, input: { context } })
6307
6783
  createdAt: seedRecord.createdAt || Date.now(),
6308
6784
  publisher: seedRecord.publisher ?? undefined,
6309
6785
  revokedAt: seedRecord.revokedAt ?? undefined,
6786
+ // One id per property_name (latest row), not the full set of rows for latest version
6310
6787
  _metadataIds: metadataRecords.map((r) => r.localId || r.uid).filter(Boolean),
6311
6788
  propertyInstances,
6312
6789
  },
@@ -6337,9 +6814,9 @@ const runPublish = xstate.fromCallback(({ sendBack, input: { context } }) => {
6337
6814
  sendBack({ type: 'publishError', error: new Error(`Item not found for seedLocalId: ${seedLocalId}`) });
6338
6815
  return;
6339
6816
  }
6340
- const getPublishUploadsMod = await Promise.resolve().then(function () { return require('./getPublishUploads-DdSwst2x.js'); });
6817
+ const getPublishUploadsMod = await Promise.resolve().then(function () { return require('./getPublishUploads-DdVy-5fK.js'); });
6341
6818
  const { getPublishUploads } = getPublishUploadsMod;
6342
- const getPublishPayloadMod = await Promise.resolve().then(function () { return require('./getPublishPayload-h_Rz8nVX.js'); });
6819
+ const getPublishPayloadMod = await Promise.resolve().then(function () { return require('./getPublishPayload-DP2fm4q8.js'); });
6343
6820
  const { getPublishPayload } = getPublishPayloadMod;
6344
6821
  const uploads = await getPublishUploads(item);
6345
6822
  let uploadedTransactions = [];
@@ -6631,40 +7108,6 @@ const itemMachineSingle = xstate.setup({
6631
7108
  },
6632
7109
  });
6633
7110
 
6634
- const getMetadataLatest = ({ seedLocalId, seedUid }) => {
6635
- const appDb = BaseDb.getAppDb();
6636
- const whereClauses = [];
6637
- if (seedLocalId && seedUid) {
6638
- const orClause = drizzleOrm.or(drizzleOrm.eq(metadata$1.seedLocalId, seedLocalId), drizzleOrm.eq(metadata$1.seedUid, seedUid));
6639
- if (orClause)
6640
- whereClauses.push(orClause);
6641
- }
6642
- else if (seedLocalId) {
6643
- whereClauses.push(drizzleOrm.eq(metadata$1.seedLocalId, seedLocalId));
6644
- }
6645
- else if (seedUid) {
6646
- whereClauses.push(drizzleOrm.eq(metadata$1.seedUid, seedUid));
6647
- }
6648
- const metadataColumns = drizzleOrm.getTableColumns(metadata$1);
6649
- return appDb.$with('metadataLatest').as(appDb
6650
- .select({
6651
- ...metadataColumns,
6652
- rowNum: drizzleOrm.sql.raw(`
6653
- ROW_NUMBER() OVER (
6654
- PARTITION BY property_name
6655
- ORDER BY COALESCE(attestation_created_at, created_at) DESC
6656
- )
6657
- `).as('rowNum')
6658
- })
6659
- .from(metadata$1)
6660
- .where(drizzleOrm.and(...whereClauses)));
6661
- };
6662
-
6663
- var metadataLatest = /*#__PURE__*/Object.freeze({
6664
- __proto__: null,
6665
- getMetadataLatest: getMetadataLatest
6666
- });
6667
-
6668
7111
  const getItemProperties = async ({ seedLocalId, seedUid, edited, }) => {
6669
7112
  const appDb = BaseDb.getAppDb();
6670
7113
  const whereClauses = [drizzleOrm.isNotNull(metadata$1.propertyName)];
@@ -6719,6 +7162,35 @@ const getSeedData = async ({ seedLocalId, seedUid }) => {
6719
7162
  return rows[0];
6720
7163
  };
6721
7164
 
7165
+ /**
7166
+ * Latest version row for the seed (by createdAt) whose uid is a real EAS attestation id.
7167
+ * Skips legacy 'NULL' / ZERO_BYTES32 placeholders and non-bytes32 strings.
7168
+ */
7169
+ async function getLatestPublishedVersionRow(seedLocalId) {
7170
+ const appDb = BaseDb.getAppDb();
7171
+ if (!appDb || !seedLocalId)
7172
+ return null;
7173
+ const vRows = await appDb
7174
+ .select({
7175
+ localId: versions.localId,
7176
+ uid: versions.uid,
7177
+ attestationCreatedAt: versions.attestationCreatedAt,
7178
+ })
7179
+ .from(versions)
7180
+ .where(drizzleOrm.eq(versions.seedLocalId, seedLocalId))
7181
+ .orderBy(drizzleOrm.desc(versions.createdAt));
7182
+ for (const vr of vRows) {
7183
+ if (vr.uid && isValidEasAttestationUid(vr.uid)) {
7184
+ return {
7185
+ uid: vr.uid,
7186
+ localId: vr.localId ?? null,
7187
+ attestationCreatedAt: vr.attestationCreatedAt ?? null,
7188
+ };
7189
+ }
7190
+ }
7191
+ return null;
7192
+ }
7193
+
6722
7194
  const logger$o = debug('seedSdk:db:read:getItemData');
6723
7195
  const getItemData = async ({ modelName, seedLocalId, seedUid, }) => {
6724
7196
  if (!seedLocalId && !seedUid) {
@@ -6787,21 +7259,51 @@ const getItemData = async ({ modelName, seedLocalId, seedUid, }) => {
6787
7259
  lastVersionPublishedAt: null,
6788
7260
  latestVersionUid: null,
6789
7261
  latestVersionLocalId: null,
7262
+ publishedVersionUid: null,
7263
+ publishedVersionLocalId: null,
7264
+ lastLocalUpdateAt: null,
6790
7265
  };
6791
7266
  try {
6792
- const versionRows = await appDb
7267
+ const allVersions = await appDb
6793
7268
  .select({
6794
- versionsCount: drizzleOrm.count(versions.localId).as('versionsCount'),
6795
- lastVersionPublishedAt: drizzleOrm.max(versions.attestationCreatedAt).as('lastVersionPublishedAt'),
6796
- latestVersionUid: drizzleOrm.max(versions.uid).as('latestVersionUid'),
6797
- latestVersionLocalId: drizzleOrm.max(versions.localId).as('latestVersionLocalId'),
7269
+ localId: versions.localId,
7270
+ uid: versions.uid,
7271
+ createdAt: versions.createdAt,
7272
+ attestationCreatedAt: versions.attestationCreatedAt,
6798
7273
  })
6799
7274
  .from(versions)
6800
- .where(drizzleOrm.eq(versions.seedLocalId, resolvedSeedLocalId))
6801
- .groupBy(versions.seedLocalId)
6802
- .limit(1);
6803
- if (versionRows && versionRows.length > 0) {
6804
- versionRow = versionRows[0];
7275
+ .where(drizzleOrm.eq(versions.seedLocalId, resolvedSeedLocalId));
7276
+ if (allVersions.length > 0) {
7277
+ const sorted = [...allVersions].sort((a, b) => {
7278
+ const ca = a.createdAt ?? 0;
7279
+ const cb = b.createdAt ?? 0;
7280
+ if (cb !== ca)
7281
+ return cb - ca;
7282
+ return String(b.localId ?? '').localeCompare(String(a.localId ?? ''));
7283
+ });
7284
+ const latest = sorted[0];
7285
+ let lastPub = null;
7286
+ for (const v of allVersions) {
7287
+ const t = v.attestationCreatedAt;
7288
+ if (t != null && (lastPub == null || t > lastPub))
7289
+ lastPub = t;
7290
+ }
7291
+ let lastLocal = 0;
7292
+ for (const v of allVersions) {
7293
+ const t = v.createdAt ?? 0;
7294
+ if (t > lastLocal)
7295
+ lastLocal = t;
7296
+ }
7297
+ const published = await getLatestPublishedVersionRow(resolvedSeedLocalId);
7298
+ versionRow = {
7299
+ versionsCount: allVersions.length,
7300
+ lastVersionPublishedAt: lastPub,
7301
+ latestVersionUid: latest.uid ?? null,
7302
+ latestVersionLocalId: latest.localId ?? null,
7303
+ publishedVersionUid: published?.uid ?? null,
7304
+ publishedVersionLocalId: published?.localId ?? null,
7305
+ lastLocalUpdateAt: lastLocal || null,
7306
+ };
6805
7307
  }
6806
7308
  }
6807
7309
  catch (error) {
@@ -6833,11 +7335,65 @@ const getItemData = async ({ modelName, seedLocalId, seedUid, }) => {
6833
7335
  return itemData;
6834
7336
  };
6835
7337
 
7338
+ /**
7339
+ * One round-trip for list views: for each seed, the same row as {@link getLatestPublishedVersionRow}
7340
+ * (newest `created_at` whose `uid` is a valid EAS attestation id).
7341
+ */
7342
+ async function batchLatestPublishedVersionBySeedLocalIds(seedLocalIds) {
7343
+ const out = new Map();
7344
+ if (seedLocalIds.length === 0)
7345
+ return out;
7346
+ const appDb = BaseDb.getAppDb();
7347
+ if (!appDb)
7348
+ return out;
7349
+ const rows = await appDb
7350
+ .select({
7351
+ seedLocalId: versions.seedLocalId,
7352
+ localId: versions.localId,
7353
+ uid: versions.uid,
7354
+ createdAt: versions.createdAt,
7355
+ })
7356
+ .from(versions)
7357
+ .where(drizzleOrm.inArray(versions.seedLocalId, seedLocalIds));
7358
+ const bySeed = new Map();
7359
+ for (const r of rows) {
7360
+ const sid = r.seedLocalId;
7361
+ if (!sid)
7362
+ continue;
7363
+ const list = bySeed.get(sid) ?? [];
7364
+ list.push(r);
7365
+ bySeed.set(sid, list);
7366
+ }
7367
+ for (const [sid, list] of bySeed) {
7368
+ const sorted = [...list].sort((a, b) => {
7369
+ const ca = a.createdAt ?? 0;
7370
+ const cb = b.createdAt ?? 0;
7371
+ if (cb !== ca)
7372
+ return cb - ca;
7373
+ return String(b.localId ?? '').localeCompare(String(a.localId ?? ''));
7374
+ });
7375
+ const hit = sorted.find((r) => r.uid && isValidEasAttestationUid(r.uid));
7376
+ if (hit?.uid) {
7377
+ out.set(sid, { uid: hit.uid, localId: hit.localId ?? null });
7378
+ }
7379
+ }
7380
+ return out;
7381
+ }
7382
+
7383
+ /**
7384
+ * List item rows for list UIs. Only includes seeds that have at least one version.
7385
+ *
7386
+ * - `includeEas: false` (default): drafts only — `seeds.uid` is null, empty, legacy `'NULL'`, or zero-bytes32.
7387
+ * On-chain seeds (real EAS seed UID) require `includeEas: true`.
7388
+ * - `latestVersionUid` / `latestVersionLocalId`: head version **row** by `created_at` (may be unattested).
7389
+ * - `publishedVersionUid` / `publishedVersionLocalId`: filled in a second batched read (same rules as
7390
+ * `getLatestPublishedVersionRow`).
7391
+ */
6836
7392
  const getItemsData = async ({ modelName, deleted, includeEas = false, addressFilter, }) => {
6837
7393
  const appDb = BaseDb.getAppDb();
6838
7394
  const conditions = [];
6839
7395
  if (!includeEas) {
6840
- conditions.push(drizzleOrm.or(drizzleOrm.isNull(seeds.uid), drizzleOrm.eq(seeds.uid, '')));
7396
+ conditions.push(drizzleOrm.or(drizzleOrm.isNull(seeds.uid), drizzleOrm.eq(seeds.uid, ''), drizzleOrm.eq(seeds.uid, 'NULL'), drizzleOrm.eq(seeds.uid, ZERO_BYTES32)));
6841
7397
  }
6842
7398
  if (modelName) {
6843
7399
  conditions.push(drizzleOrm.eq(seeds.type, casing.toSnakeCase(modelName)));
@@ -6886,10 +7442,20 @@ const getItemsData = async ({ modelName, deleted, includeEas = false, addressFil
6886
7442
  .from(seeds)
6887
7443
  .leftJoin(versionData, drizzleOrm.eq(seeds.localId, versionData.seedLocalId))
6888
7444
  .where(drizzleOrm.and(drizzleOrm.gt(versionData.versionsCount, 0), ...conditions))
6889
- .orderBy(drizzleOrm.sql.raw('COALESCE(attestation_created_at, created_at) DESC'))
6890
- .groupBy(seeds.localId);
7445
+ .orderBy(drizzleOrm.sql.raw('COALESCE(attestation_created_at, created_at) DESC'));
6891
7446
  const itemsData = (await query);
6892
- return itemsData;
7447
+ const seedIds = itemsData
7448
+ .map((r) => r.seedLocalId)
7449
+ .filter((id) => typeof id === 'string' && id !== '');
7450
+ const publishedBySeed = await batchLatestPublishedVersionBySeedLocalIds(seedIds);
7451
+ return itemsData.map((row) => {
7452
+ const pub = row.seedLocalId ? publishedBySeed.get(row.seedLocalId) : undefined;
7453
+ return {
7454
+ ...row,
7455
+ publishedVersionUid: pub?.uid,
7456
+ publishedVersionLocalId: pub?.localId ?? undefined,
7457
+ };
7458
+ });
6893
7459
  };
6894
7460
 
6895
7461
  const resolveRemoteStorage = xstate.fromCallback(({ sendBack, input: { context } }) => {
@@ -7056,25 +7622,6 @@ const initialize = xstate.fromCallback(({ sendBack, input: { context } }) => {
7056
7622
  });
7057
7623
  });
7058
7624
 
7059
- const seedUidToStorageTransactionId = new Map();
7060
- const getStorageTransactionIdForSeedUid = async (seedUid) => {
7061
- if (seedUidToStorageTransactionId.has(seedUid)) {
7062
- return seedUidToStorageTransactionId.get(seedUid);
7063
- }
7064
- const appDb = BaseDb.getAppDb();
7065
- const results = (await appDb
7066
- .select({
7067
- storageTransactionId: metadata$1.propertyValue,
7068
- })
7069
- .from(metadata$1)
7070
- .where(drizzleOrm.and(drizzleOrm.eq(metadata$1.seedUid, seedUid), drizzleOrm.eq(metadata$1.propertyName, 'storageTransactionId'))));
7071
- if (!results || results.length === 0) {
7072
- return;
7073
- }
7074
- seedUidToStorageTransactionId.set(seedUid, results[0].storageTransactionId);
7075
- return results[0].storageTransactionId;
7076
- };
7077
-
7078
7625
  const getRelationValueData = async (propertyValue) => {
7079
7626
  const appDb = BaseDb.getAppDb();
7080
7627
  const rows = (await appDb
@@ -7104,7 +7651,7 @@ const resolveRelatedValue = xstate.fromCallback(({ sendBack, input: { context }
7104
7651
  const { isRelation, propertyValue, propertyName, seedUid, propertyRecordSchema, populatedFromDb, schemaUid, } = context;
7105
7652
  const _resolveRelatedValue = async () => {
7106
7653
  // Use dynamic import to break circular dependency
7107
- const schemaMod = await Promise.resolve().then(function () { return require('./index-CKJeh6ic.js'); });
7654
+ const schemaMod = await Promise.resolve().then(function () { return require('./index-DTkoTvcq.js'); });
7108
7655
  const { ModelPropertyDataTypes } = schemaMod;
7109
7656
  if (!propertyValue || !isRelation || populatedFromDb) {
7110
7657
  return;
@@ -7480,7 +8027,7 @@ const hydrateFromDb = xstate.fromCallback(({ sendBack, input: { context } }) =>
7480
8027
  // to use dynamically imported ModelPropertyDataTypes
7481
8028
  const _hydrateFromDb = async () => {
7482
8029
  // Use dynamic import to break circular dependency
7483
- const schemaMod = await Promise.resolve().then(function () { return require('./index-CKJeh6ic.js'); });
8030
+ const schemaMod = await Promise.resolve().then(function () { return require('./index-DTkoTvcq.js'); });
7484
8031
  const { ModelPropertyDataTypes } = schemaMod;
7485
8032
  const appDb = BaseDb.getAppDb();
7486
8033
  const whereClauses = [];
@@ -7785,7 +8332,7 @@ const loadOrCreateProperty = xstate.fromCallback(({ sendBack, input: { context }
7785
8332
  };
7786
8333
  // Merge with schema from file/DB to get validation rules (enum, pattern, etc.) - properties table doesn't store these
7787
8334
  try {
7788
- const { getPropertySchema } = await Promise.resolve().then(function () { return require('./property-Dw0b_Sf8.js'); });
8335
+ const { getPropertySchema } = await Promise.resolve().then(function () { return require('./property-BQokoaRe.js'); });
7789
8336
  let schemaFromFile = await getPropertySchema(normalizedModelName, propertyName);
7790
8337
  if (!schemaFromFile?.validation) {
7791
8338
  // Fallback: get validation from schemaData in database (Schema context may not be loaded yet)
@@ -8169,9 +8716,9 @@ const analyzeInput = xstate.fromCallback(({ sendBack, input: { context, event }
8169
8716
  }
8170
8717
  const _analyzeInput = async () => {
8171
8718
  // Use dynamic import to break circular dependency
8172
- const schemaMod = await Promise.resolve().then(function () { return require('./index-CKJeh6ic.js'); });
8719
+ const schemaMod = await Promise.resolve().then(function () { return require('./index-DTkoTvcq.js'); });
8173
8720
  const { ModelPropertyDataTypes } = schemaMod;
8174
- const { SchemaValidationService } = await Promise.resolve().then(function () { return require('./SchemaValidationService-DVQrRpse.js'); });
8721
+ const { SchemaValidationService } = await Promise.resolve().then(function () { return require('./SchemaValidationService-DCflhpcI.js'); });
8175
8722
  let propertyName = propertyNameRaw;
8176
8723
  if (!propertyName) {
8177
8724
  throw new Error('propertyName is required');
@@ -8369,7 +8916,7 @@ const createMetadata = async (metadataValues, propertyRecordSchema, options) =>
8369
8916
  propertyRecordSchema?.validation &&
8370
8917
  metadataValues.propertyValue != null &&
8371
8918
  metadataValues.propertyValue !== '') {
8372
- const { SchemaValidationService } = await Promise.resolve().then(function () { return require('./SchemaValidationService-DVQrRpse.js'); });
8919
+ const { SchemaValidationService } = await Promise.resolve().then(function () { return require('./SchemaValidationService-DCflhpcI.js'); });
8373
8920
  const validationService = new SchemaValidationService();
8374
8921
  const validationResult = validationService.validatePropertyValue(metadataValues.propertyValue, propertyRecordSchema.dataType, propertyRecordSchema.validation, propertyRecordSchema.refValueType);
8375
8922
  if (!validationResult.isValid && validationResult.errors.length > 0) {
@@ -8956,7 +9503,7 @@ const saveRelation = xstate.fromCallback(({ sendBack, input: { context, event }
8956
9503
  }
8957
9504
  const _saveRelation = async () => {
8958
9505
  // Use dynamic import to break circular dependency
8959
- const schemaMod = await Promise.resolve().then(function () { return require('./index-CKJeh6ic.js'); });
9506
+ const schemaMod = await Promise.resolve().then(function () { return require('./index-DTkoTvcq.js'); });
8960
9507
  const { ModelPropertyDataTypes } = schemaMod;
8961
9508
  if (!propertyNameRaw) {
8962
9509
  throw new Error('propertyName is required');
@@ -9971,7 +10518,9 @@ class ItemProperty {
9971
10518
  }
9972
10519
  }
9973
10520
  }
9974
- if (!this._alias && propertyName.endsWith('Id')) {
10521
+ if (!this._alias &&
10522
+ propertyName.endsWith('Id') &&
10523
+ !PROPERTY_NAMES_EXEMPT_FROM_ID_SUFFIX_STRIP.has(propertyName)) {
9975
10524
  this._alias = propertyName.slice(0, -2);
9976
10525
  }
9977
10526
  else if (!this._alias && propertyName.endsWith('Ids')) {
@@ -9988,7 +10537,7 @@ class ItemProperty {
9988
10537
  return;
9989
10538
  }
9990
10539
  // Use dynamic import to break circular dependency
9991
- const schemaMod = await Promise.resolve().then(function () { return require('./index-CKJeh6ic.js'); });
10540
+ const schemaMod = await Promise.resolve().then(function () { return require('./index-DTkoTvcq.js'); });
9992
10541
  const { ModelPropertyDataTypes } = schemaMod;
9993
10542
  const { context } = snapshot;
9994
10543
  const { propertyRecordSchema } = context;
@@ -10845,7 +11394,7 @@ class ItemProperty {
10845
11394
  }
10846
11395
  async save() {
10847
11396
  const ctx = this._getSnapshotContext();
10848
- const { assertItemOwned } = await Promise.resolve().then(function () { return require('./ownership-gfm5thj7.js'); });
11397
+ const { assertItemOwned } = await Promise.resolve().then(function () { return require('./ownership-DanM_n8E.js'); });
10849
11398
  await assertItemOwned({
10850
11399
  seedLocalId: ctx?.seedLocalId ?? undefined,
10851
11400
  seedUid: ctx?.seedUid ?? undefined,
@@ -11082,7 +11631,7 @@ const deleteItem = async ({ seedLocalId, seedUid }) => {
11082
11631
  * Updates seedUid and optionally publisher. Publisher is immutable once set:
11083
11632
  * we never overwrite an existing publisher (set at creation or from attestation).
11084
11633
  */
11085
- const updateSeedUid = async ({ seedLocalId, seedUid, publisher, }) => {
11634
+ const updateSeedUid = async ({ seedLocalId, seedUid, publisher, attestationCreatedAt, }) => {
11086
11635
  if (!seedLocalId || !seedUid) {
11087
11636
  return;
11088
11637
  }
@@ -11103,6 +11652,7 @@ const updateSeedUid = async ({ seedLocalId, seedUid, publisher, }) => {
11103
11652
  .set({
11104
11653
  uid: seedUid,
11105
11654
  ...(shouldSetPublisher && { publisher }),
11655
+ ...(attestationCreatedAt != null && { attestationCreatedAt }),
11106
11656
  updatedAt: Date.now(),
11107
11657
  })
11108
11658
  .where(drizzleOrm.eq(seeds.localId, seedLocalId));
@@ -11183,7 +11733,7 @@ class Item {
11183
11733
  });
11184
11734
  };
11185
11735
  this.unpublish = async () => {
11186
- const { assertItemOwned } = await Promise.resolve().then(function () { return require('./ownership-gfm5thj7.js'); });
11736
+ const { assertItemOwned } = await Promise.resolve().then(function () { return require('./ownership-DanM_n8E.js'); });
11187
11737
  const { getRevokeExecutor } = await Promise.resolve().then(function () { return publishConfig; });
11188
11738
  await assertItemOwned(this);
11189
11739
  const seedUid = this.seedUid;
@@ -11207,7 +11757,7 @@ class Item {
11207
11757
  this._service.send({ type: 'updateContext', revokedAt });
11208
11758
  };
11209
11759
  this.publish = async () => {
11210
- const { assertItemOwned } = await Promise.resolve().then(function () { return require('./ownership-gfm5thj7.js'); });
11760
+ const { assertItemOwned } = await Promise.resolve().then(function () { return require('./ownership-DanM_n8E.js'); });
11211
11761
  await assertItemOwned(this);
11212
11762
  this._service.send({ type: 'startPublish' });
11213
11763
  return new Promise((resolve, reject) => {
@@ -11241,23 +11791,28 @@ class Item {
11241
11791
  });
11242
11792
  });
11243
11793
  };
11244
- this.getPublishUploads = async () => {
11794
+ this.getPublishUploads = async (options) => {
11245
11795
  // Use dynamic import to break circular dependency
11246
- const getPublishUploadsMod = await Promise.resolve().then(function () { return require('./getPublishUploads-DdSwst2x.js'); });
11796
+ const getPublishUploadsMod = await Promise.resolve().then(function () { return require('./getPublishUploads-DdVy-5fK.js'); });
11247
11797
  const { getPublishUploads } = getPublishUploadsMod;
11248
- return await getPublishUploads(this);
11798
+ return await getPublishUploads(this, [], undefined, options);
11249
11799
  };
11250
11800
  this.getPublishPayload = async (uploadedTransactions, options) => {
11251
- const getPublishPayloadMod = await Promise.resolve().then(function () { return require('./getPublishPayload-h_Rz8nVX.js'); });
11801
+ const getPublishPayloadMod = await Promise.resolve().then(function () { return require('./getPublishPayload-DP2fm4q8.js'); });
11252
11802
  const { getPublishPayload } = getPublishPayloadMod;
11253
11803
  return await getPublishPayload(this, uploadedTransactions, options);
11254
11804
  };
11255
- this.persistSeedUid = async (publisher) => {
11805
+ this.persistSeedUid = async (publisher, attestationCreatedAtMs) => {
11256
11806
  const ctx = this._getSnapshotContext();
11257
11807
  const seedLocalId = ctx.seedLocalId;
11258
11808
  const seedUid = ctx.seedUid;
11259
11809
  if (seedLocalId && seedUid && typeof seedUid === 'string' && seedUid.length > 0) {
11260
- await updateSeedUid({ seedLocalId, seedUid, publisher });
11810
+ await updateSeedUid({
11811
+ seedLocalId,
11812
+ seedUid,
11813
+ publisher,
11814
+ ...(attestationCreatedAtMs != null && { attestationCreatedAt: attestationCreatedAtMs }),
11815
+ });
11261
11816
  }
11262
11817
  };
11263
11818
  const { modelName, seedUid, schemaUid, seedLocalId, latestVersionLocalId, latestVersionUid, modelInstance, publisher, } = initialValues;
@@ -11301,7 +11856,9 @@ class Item {
11301
11856
  transformedKey = key.slice(0, -3); // Remove 'Ids'
11302
11857
  transformedKey = pluralize(transformedKey);
11303
11858
  }
11304
- if (!propertyInstance.alias && key.endsWith('Id')) {
11859
+ if (!propertyInstance.alias &&
11860
+ key.endsWith('Id') &&
11861
+ !PROPERTY_NAMES_EXEMPT_FROM_ID_SUFFIX_STRIP.has(key)) {
11305
11862
  transformedKey = key.slice(0, -2); // Remove 'Id'
11306
11863
  }
11307
11864
  propertiesObj[transformedKey] = propertyInstance;
@@ -11375,9 +11932,8 @@ class Item {
11375
11932
  const modelPropertyNames = this._getModelPropertyNames(schemaNameForModel);
11376
11933
  const schemaKeys = modelPropertyNames.length > 0 ? modelPropertyNames : Object.keys(propertySchemas);
11377
11934
  // Normalize Id-suffix keys from initialValues: metadata stores textId but schema defines text
11378
- const ID_SUFFIX_NO_NORMALIZE = new Set(['storageTransactionId']);
11379
11935
  const normalizedKeysFromInitial = keysFromInitial.map((key) => {
11380
- if (key.endsWith('Id') && !ID_SUFFIX_NO_NORMALIZE.has(key)) {
11936
+ if (key.endsWith('Id') && !PROPERTY_NAMES_EXEMPT_FROM_ID_SUFFIX_STRIP.has(key)) {
11381
11937
  const baseName = key.slice(0, -2);
11382
11938
  if (schemaKeys.length > 0 && schemaKeys.includes(baseName))
11383
11939
  return baseName;
@@ -11433,7 +11989,18 @@ class Item {
11433
11989
  }
11434
11990
  if (!waitForReady)
11435
11991
  return instance;
11436
- await waitForEntityIdle(instance, { timeout: readyTimeout });
11992
+ try {
11993
+ await waitForEntityIdle(instance, { timeout: readyTimeout });
11994
+ }
11995
+ catch (err) {
11996
+ try {
11997
+ instance.unload();
11998
+ }
11999
+ catch {
12000
+ /* best-effort cache cleanup */
12001
+ }
12002
+ throw err;
12003
+ }
11437
12004
  return instance;
11438
12005
  }
11439
12006
  if (!this.instanceCache.has(seedId)) {
@@ -11531,7 +12098,18 @@ class Item {
11531
12098
  });
11532
12099
  if (!waitForReady)
11533
12100
  return proxiedInstance;
11534
- await waitForEntityIdle(proxiedInstance, { timeout: readyTimeout });
12101
+ try {
12102
+ await waitForEntityIdle(proxiedInstance, { timeout: readyTimeout });
12103
+ }
12104
+ catch (err) {
12105
+ try {
12106
+ proxiedInstance.unload();
12107
+ }
12108
+ catch {
12109
+ /* best-effort cache cleanup */
12110
+ }
12111
+ throw err;
12112
+ }
11535
12113
  return proxiedInstance;
11536
12114
  }
11537
12115
  }
@@ -11703,7 +12281,18 @@ class Item {
11703
12281
  });
11704
12282
  if (!waitForReady)
11705
12283
  return proxiedInstance;
11706
- await waitForEntityIdle(proxiedInstance, { timeout: readyTimeout });
12284
+ try {
12285
+ await waitForEntityIdle(proxiedInstance, { timeout: readyTimeout });
12286
+ }
12287
+ catch (err) {
12288
+ try {
12289
+ proxiedInstance.unload();
12290
+ }
12291
+ catch {
12292
+ /* best-effort cache cleanup */
12293
+ }
12294
+ throw err;
12295
+ }
11707
12296
  return proxiedInstance;
11708
12297
  }
11709
12298
  /**
@@ -12138,6 +12727,14 @@ class Item {
12138
12727
  }
12139
12728
  setupState.subscriptionSetUp = true;
12140
12729
  logger(`[Item._setupLiveQuerySubscription] Setting up liveQuery for seedLocalId: ${seedLocalId}`);
12730
+ const itemActor = this._service;
12731
+ const sendToItemMachine = (event) => {
12732
+ const status = itemActor.getSnapshot().status;
12733
+ if (status === 'stopped' || status === 'done') {
12734
+ return;
12735
+ }
12736
+ itemActor.send(event);
12737
+ };
12141
12738
  try {
12142
12739
  const seedSchemaMod = await Promise.resolve().then(function () { return schema$1; });
12143
12740
  const { seeds, versions, metadata } = seedSchemaMod;
@@ -12213,7 +12810,7 @@ class Item {
12213
12810
  }
12214
12811
  }
12215
12812
  // Update context with latest version info
12216
- this._service.send({
12813
+ sendToItemMachine({
12217
12814
  type: 'updateContext',
12218
12815
  latestVersionLocalId: currentVersionLocalId,
12219
12816
  latestVersionUid: seedRecord.latestVersionUid,
@@ -12268,7 +12865,7 @@ class Item {
12268
12865
  const seedRow = seedRows[0];
12269
12866
  logger(`[Item._setupLiveQuerySubscription] Seed updated in database`);
12270
12867
  // Update context with seed data
12271
- this._service.send({
12868
+ sendToItemMachine({
12272
12869
  type: 'updateContext',
12273
12870
  seedLocalId: seedRow.localId,
12274
12871
  seedUid: seedRow.uid || undefined,
@@ -12339,7 +12936,7 @@ class Item {
12339
12936
  modelName: itemModelName,
12340
12937
  });
12341
12938
  if (property) {
12342
- this._service.send({
12939
+ sendToItemMachine({
12343
12940
  type: 'addPropertyInstance',
12344
12941
  propertyName,
12345
12942
  propertyInstance: property,
@@ -12358,7 +12955,7 @@ class Item {
12358
12955
  }
12359
12956
  }
12360
12957
  // Update context with latest version info
12361
- this._service.send({
12958
+ sendToItemMachine({
12362
12959
  type: 'updateContext',
12363
12960
  latestVersionLocalId,
12364
12961
  latestVersionUid: latestVersion.uid || undefined,
@@ -12448,7 +13045,7 @@ class Item {
12448
13045
  * Destroy the item: soft delete in DB, remove from caches, clean up subscriptions, stop service.
12449
13046
  */
12450
13047
  async destroy() {
12451
- const { assertItemOwned } = await Promise.resolve().then(function () { return require('./ownership-gfm5thj7.js'); });
13048
+ const { assertItemOwned } = await Promise.resolve().then(function () { return require('./ownership-DanM_n8E.js'); });
12452
13049
  await assertItemOwned(this);
12453
13050
  const context = this._getSnapshotContext();
12454
13051
  const cacheKey = context.seedUid || context.seedLocalId;
@@ -12509,37 +13106,6 @@ function normalizeAddressConfig(addresses) {
12509
13106
  };
12510
13107
  }
12511
13108
 
12512
- const isNode = () => {
12513
- return (typeof process !== 'undefined' &&
12514
- process.versions != null &&
12515
- process.versions.node != null);
12516
- };
12517
- const isBrowser = () => {
12518
- return !isElectron() && typeof document !== 'undefined' && typeof window !== 'undefined';
12519
- };
12520
- const isElectron = () => {
12521
- return typeof process !== 'undefined' && process.versions != null && process.versions.electron != null;
12522
- };
12523
-
12524
- /**
12525
- * @deprecated Use BaseArweaveClient.setHost() instead.
12526
- * This function is kept for backward compatibility but will be removed in a future version.
12527
- */
12528
- const setArweaveDomain = (newDomain) => {
12529
- BaseArweaveClient.setHost(newDomain);
12530
- };
12531
-
12532
- const logger$h = debug('seedSdk:services:events');
12533
- const handleServiceSaveState = (event) => {
12534
- const { state, serviceId } = event;
12535
- logger$h(`[browser] [service.saveState.request] serviceId: ${serviceId}`);
12536
- // TODO: This is called from Node as well. Do we need it? If so, need to generalize this to all platforms.
12537
- // localStorage.setItem(`seed_sdk_service_${serviceId}`, JSON.stringify(state))
12538
- };
12539
- const setupServicesEventHandlers = () => {
12540
- eventEmitter.addListener('service.saveState.request', handleServiceSaveState);
12541
- };
12542
-
12543
13109
  // Dynamic import to break circular dependency: Model -> BaseItem -> ... -> getModelSchemas -> Model
12544
13110
  // import { Model } from '@/Model/Model'
12545
13111
  const schemaStringToModelRecord = new Map();
@@ -13110,6 +13676,37 @@ const syncDbWithEasHandler = lodashEs.throttle(async (_) => {
13110
13676
  trailing: false,
13111
13677
  });
13112
13678
 
13679
+ const isNode = () => {
13680
+ return (typeof process !== 'undefined' &&
13681
+ process.versions != null &&
13682
+ process.versions.node != null);
13683
+ };
13684
+ const isBrowser = () => {
13685
+ return !isElectron() && typeof document !== 'undefined' && typeof window !== 'undefined';
13686
+ };
13687
+ const isElectron = () => {
13688
+ return typeof process !== 'undefined' && process.versions != null && process.versions.electron != null;
13689
+ };
13690
+
13691
+ /**
13692
+ * @deprecated Use BaseArweaveClient.setHost() instead.
13693
+ * This function is kept for backward compatibility but will be removed in a future version.
13694
+ */
13695
+ const setArweaveDomain = (newDomain) => {
13696
+ BaseArweaveClient.setHost(newDomain);
13697
+ };
13698
+
13699
+ const logger$h = debug('seedSdk:services:events');
13700
+ const handleServiceSaveState = (event) => {
13701
+ const { state, serviceId } = event;
13702
+ logger$h(`[browser] [service.saveState.request] serviceId: ${serviceId}`);
13703
+ // TODO: This is called from Node as well. Do we need it? If so, need to generalize this to all platforms.
13704
+ // localStorage.setItem(`seed_sdk_service_${serviceId}`, JSON.stringify(state))
13705
+ };
13706
+ const setupServicesEventHandlers = () => {
13707
+ eventEmitter.addListener('service.saveState.request', handleServiceSaveState);
13708
+ };
13709
+
13113
13710
  const setupAllItemsEventHandlers = () => {
13114
13711
  eventEmitter.addListener('syncDbWithEas', syncDbWithEasHandler);
13115
13712
  };
@@ -13270,6 +13867,7 @@ const platformClassesInit = xstate.fromCallback(({ sendBack, input: { context, e
13270
13867
  dbConfig,
13271
13868
  schemaFile,
13272
13869
  schema,
13870
+ syncFromEasOnAddressChange: options.syncFromEasOnAddressChange ?? false,
13273
13871
  } });
13274
13872
  if (arweaveDomain) {
13275
13873
  setArweaveDomain(arweaveDomain);
@@ -16085,8 +16683,64 @@ const processSchemaFiles = xstate.fromCallback(({ sendBack, input: { context } }
16085
16683
  };
16086
16684
  });
16087
16685
 
16686
+ /** Emitted by the client manager after `app_state.addresses` is written (post-`setAddresses`). */
16687
+ const ADDRESSES_PERSISTED_EVENT = 'addresses.persisted';
16688
+ function parseAddressesPersistedPayload(value) {
16689
+ if (!value || typeof value !== 'object') {
16690
+ return { owned: [], watched: [] };
16691
+ }
16692
+ const v = value;
16693
+ const owned = Array.isArray(v.owned)
16694
+ ? v.owned.filter((a) => typeof a === 'string')
16695
+ : [];
16696
+ const watched = Array.isArray(v.watched)
16697
+ ? v.watched.filter((a) => typeof a === 'string')
16698
+ : [];
16699
+ return { owned, watched };
16700
+ }
16701
+
16088
16702
  const { UNINITIALIZED, PLATFORM_CLASSES_INIT, FILE_SYSTEM_INIT, DB_INIT, SAVE_CONFIG, PROCESS_SCHEMA_FILES, ADD_MODELS_TO_STORE, ADD_MODELS_TO_DB, IDLE, } = exports.ClientManagerState;
16089
16703
  const { UPDATE_CONTEXT, PLATFORM_CLASSES_READY, FILE_SYSTEM_READY, DB_READY, SAVE_CONFIG_SUCCESS, SAVE_APP_STATE_SUCCESS, SET_ADDRESSES, ADD_MODELS_TO_STORE_SUCCESS, ADD_MODELS_TO_DB_SUCCESS, PROCESS_SCHEMA_FILES_SUCCESS, } = ClientManagerEvents;
16704
+ const logSyncAfterAddressSave = debug("seedSdk:client:clientManagerMachine:syncAfterAddressSave");
16705
+ function addressesFromPersistedAddressValue(value) {
16706
+ if (!value || typeof value !== "object")
16707
+ return [];
16708
+ const v = value;
16709
+ const owned = Array.isArray(v.owned)
16710
+ ? v.owned.filter((a) => typeof a === "string")
16711
+ : [];
16712
+ const watched = Array.isArray(v.watched)
16713
+ ? v.watched.filter((a) => typeof a === "string")
16714
+ : [];
16715
+ const seen = new Set();
16716
+ const out = [];
16717
+ for (const a of [...owned, ...watched]) {
16718
+ const k = a.toLowerCase();
16719
+ if (!seen.has(k)) {
16720
+ seen.add(k);
16721
+ out.push(a);
16722
+ }
16723
+ }
16724
+ return out;
16725
+ }
16726
+ function maybeRunSyncFromEasAfterAddressSave({ context, event, }) {
16727
+ if (!context.syncFromEasOnAddressChange)
16728
+ return;
16729
+ if (event.key !== "addresses")
16730
+ return;
16731
+ const merged = addressesFromPersistedAddressValue(event.value);
16732
+ if (merged.length === 0)
16733
+ return;
16734
+ void runSyncFromEas({ addresses: merged }).catch((err) => {
16735
+ logSyncAfterAddressSave("runSyncFromEas after address save failed", err);
16736
+ });
16737
+ }
16738
+ function emitAddressesPersistedIfAddressesKey(event) {
16739
+ if (event.key !== "addresses")
16740
+ return;
16741
+ const payload = parseAddressesPersistedPayload(event.value);
16742
+ eventEmitter.emit(ADDRESSES_PERSISTED_EVENT, payload);
16743
+ }
16090
16744
  const clientManagerMachine = xstate.setup({
16091
16745
  types: {
16092
16746
  context: {},
@@ -16245,12 +16899,18 @@ const clientManagerMachine = xstate.setup({
16245
16899
  }),
16246
16900
  on: {
16247
16901
  [SAVE_APP_STATE_SUCCESS]: {
16248
- actions: xstate.assign(({ event }) => {
16249
- const { key, value } = event;
16250
- return {
16251
- isSaving: false
16252
- };
16253
- }),
16902
+ actions: [
16903
+ xstate.assign(({ event }) => {
16904
+ return {
16905
+ isSaving: false,
16906
+ };
16907
+ }),
16908
+ ({ context, event }) => maybeRunSyncFromEasAfterAddressSave({
16909
+ context,
16910
+ event: event,
16911
+ }),
16912
+ ({ event }) => emitAddressesPersistedIfAddressesKey(event),
16913
+ ],
16254
16914
  },
16255
16915
  [SET_ADDRESSES]: {
16256
16916
  actions: [
@@ -16289,6 +16949,7 @@ const clientManager = xstate.createActor(clientManagerMachine, {
16289
16949
  isInitialized: false,
16290
16950
  addressesSet: false,
16291
16951
  isSaving: false,
16952
+ syncFromEasOnAddressChange: false,
16292
16953
  }
16293
16954
  });
16294
16955
  const subscription = clientManager.subscribe((snapshot) => {
@@ -16337,6 +16998,7 @@ const clientInstance = {
16337
16998
  isInitialized: false,
16338
16999
  addressesSet: false,
16339
17000
  isSaving: false,
17001
+ syncFromEasOnAddressChange: false,
16340
17002
  endpoints: undefined,
16341
17003
  addresses: undefined,
16342
17004
  ownedAddresses: undefined,
@@ -16623,7 +17285,7 @@ const saveDraftLogger = debug('seedSdk:model:saveDraftToDb');
16623
17285
  // Lazy import cache for ModelProperty to avoid circular dependency
16624
17286
  // Eagerly start loading to minimize delay on first access
16625
17287
  let ModelPropertyClass = null;
16626
- const modelPropertyImportPromise = Promise.resolve().then(function () { return require('./ModelProperty-Cuj839nX.js'); })
17288
+ const modelPropertyImportPromise = Promise.resolve().then(function () { return require('./ModelProperty-sNx_ZQZX.js'); })
16627
17289
  .then(module => {
16628
17290
  ModelPropertyClass = module.ModelProperty;
16629
17291
  return ModelPropertyClass;
@@ -16640,7 +17302,7 @@ function getModelProperty() {
16640
17302
  }
16641
17303
  // Lazy import cache for Schema to avoid circular dependency
16642
17304
  let SchemaClass = null;
16643
- const schemaImportPromise = Promise.resolve().then(function () { return require('./Schema-TFe24NNG.js'); })
17305
+ const schemaImportPromise = Promise.resolve().then(function () { return require('./Schema-B4RRA-0g.js'); })
16644
17306
  .then(module => {
16645
17307
  SchemaClass = module.Schema;
16646
17308
  return SchemaClass;
@@ -18594,7 +19256,7 @@ class Db extends BaseDb {
18594
19256
  // You can inspect what will happen before applying
18595
19257
  await apply();
18596
19258
  this.db = db;
18597
- const { backfillMetadataPropertyIds } = await Promise.resolve().then(function () { return require('./backfillMetadataPropertyIds-BiXK4hT1.js'); });
19259
+ const { backfillMetadataPropertyIds } = await Promise.resolve().then(function () { return require('./backfillMetadataPropertyIds-DhAXAuSf.js'); });
18598
19260
  await backfillMetadataPropertyIds();
18599
19261
  return this.db;
18600
19262
  }
@@ -19241,7 +19903,7 @@ const getTsImport = async (filePath) => {
19241
19903
 
19242
19904
  // Get the directory of this file to resolve relative paths
19243
19905
  // @ts-ignore - rollup plugin-typescript doesn't recognize import.meta with module: "preserve"
19244
- const __filename$1 = url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cjs/index-pyKmk9hA.js', document.baseURI).href)));
19906
+ const __filename$1 = url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cjs/index-D1qR8xnb.js', document.baseURI).href)));
19245
19907
  path.dirname(__filename$1);
19246
19908
  const commandExists = (command) => {
19247
19909
  try {
@@ -19714,6 +20376,7 @@ exports.Date = Date$1;
19714
20376
  exports.Db = Db;
19715
20377
  exports.File = File$1;
19716
20378
  exports.FileManager = FileManager;
20379
+ exports.Html = Html;
19717
20380
  exports.INIT_SCRIPT_SUCCESS_MESSAGE = INIT_SCRIPT_SUCCESS_MESSAGE;
19718
20381
  exports.INTERNAL_DATA_TYPES = INTERNAL_DATA_TYPES;
19719
20382
  exports.INTERNAL_PROPERTY_NAMES = INTERNAL_PROPERTY_NAMES;
@@ -19734,6 +20397,7 @@ exports.Relation = Relation;
19734
20397
  exports.SCHEMA_TS = SCHEMA_TS;
19735
20398
  exports.SEEDPROTOCOL_Seed_Protocol_v1 = SEEDPROTOCOL_Seed_Protocol_v1;
19736
20399
  exports.SEED_PROTOCOL_SCHEMA_NAME = SEED_PROTOCOL_SCHEMA_NAME;
20400
+ exports.THtmlEmbeddedDataUriPolicy = THtmlEmbeddedDataUriPolicy;
19737
20401
  exports.TModelSchema = TModelSchema;
19738
20402
  exports.TModelValues = TModelValues;
19739
20403
  exports.TProperty = TProperty;
@@ -19772,6 +20436,7 @@ exports.getEasSchemaUidForModel = getEasSchemaUidForModel;
19772
20436
  exports.getEasSchemaUidForSchemaDefinition = getEasSchemaUidForSchemaDefinition;
19773
20437
  exports.getGetAdditionalSyncAddresses = getGetAdditionalSyncAddresses;
19774
20438
  exports.getItemData = getItemData;
20439
+ exports.getLatestPublishedVersionRow = getLatestPublishedVersionRow;
19775
20440
  exports.getLatestSchemaVersion = getLatestSchemaVersion;
19776
20441
  exports.getModelId = getModelId;
19777
20442
  exports.getModelIdByFileId = getModelIdByFileId;
@@ -19780,8 +20445,10 @@ exports.getPropertyData = getPropertyData$1;
19780
20445
  exports.getPropertyIdForModelAndName = getPropertyIdForModelAndName;
19781
20446
  exports.getRefValueType = getRefValueType;
19782
20447
  exports.getTsImport = getTsImport;
20448
+ exports.htmlEmbeddedImageCoPublish = htmlEmbeddedImageCoPublish;
19783
20449
  exports.importJsonSchema = importJsonSchema;
19784
20450
  exports.isInternalSchema = isInternalSchema;
20451
+ exports.isValidEasAttestationUid = isValidEasAttestationUid;
19785
20452
  exports.listCompleteSchemaFiles = listCompleteSchemaFiles;
19786
20453
  exports.loadAllSchemasFromDb = loadAllSchemasFromDb;
19787
20454
  exports.loadModelsFromDbForSchema = loadModelsFromDbForSchema;
@@ -19816,4 +20483,4 @@ exports.versions = versions;
19816
20483
  exports.waitForEntityIdle = waitForEntityIdle;
19817
20484
  exports.withSeed = withSeed;
19818
20485
  exports.writeProcessMachine = writeProcessMachine;
19819
- //# sourceMappingURL=index-pyKmk9hA.js.map
20486
+ //# sourceMappingURL=index-D1qR8xnb.js.map