@seedprotocol/sdk 0.7.3-next.613.g79a8dfd → 0.7.4-next.711.gce2b766

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 (239) hide show
  1. package/dist/{db-CQt-gcAl.js → BasePathResolver-Cm4apKRb.js} +2041 -127
  2. package/dist/BasePathResolver-Cm4apKRb.js.map +1 -0
  3. package/dist/{ClientManager-DDA9956Y.js → ClientManager-i3nJASkg.js} +664 -277
  4. package/dist/ClientManager-i3nJASkg.js.map +1 -0
  5. package/dist/{Item-D4FigtYS.js → Item-DBFchXpC.js} +495 -219
  6. package/dist/Item-DBFchXpC.js.map +1 -0
  7. package/dist/{ModelProperty-BDt6AU2h.js → ModelProperty-BS49g01Y.js} +167 -47
  8. package/dist/ModelProperty-BS49g01Y.js.map +1 -0
  9. package/dist/{Schema-B8xqLWkL.js → Schema-CpMNEnUO.js} +53 -42
  10. package/dist/Schema-CpMNEnUO.js.map +1 -0
  11. package/dist/{SchemaValidationService-BPxkfDLU.js → SchemaValidationService-DieV4KL-.js} +13 -14
  12. package/dist/{SchemaValidationService-BPxkfDLU.js.map → SchemaValidationService-DieV4KL-.js.map} +1 -1
  13. package/dist/{backfillMetadataPropertyIds-DuTPcv8t.js → backfillMetadataPropertyIds-DSoOoTnX.js} +14 -7
  14. package/dist/{backfillMetadataPropertyIds-DuTPcv8t.js.map → backfillMetadataPropertyIds-DSoOoTnX.js.map} +1 -1
  15. package/dist/{configurePlatform-YcOiDQBZ.js → configurePlatform-D0lQGAMQ.js} +8 -7
  16. package/dist/{configurePlatform-YcOiDQBZ.js.map → configurePlatform-D0lQGAMQ.js.map} +1 -1
  17. package/dist/detachRowsBeforeDelete-S0q-DJPT.js +50 -0
  18. package/dist/detachRowsBeforeDelete-S0q-DJPT.js.map +1 -0
  19. package/dist/{eas-CpOD74Ke.js → eas-6pjU-OuX.js} +9 -8
  20. package/dist/eas-6pjU-OuX.js.map +1 -0
  21. package/dist/{getItem-B_OoFkd7.js → getItem-CxBNZ-WL.js} +13 -11
  22. package/dist/{getItem-B_OoFkd7.js.map → getItem-CxBNZ-WL.js.map} +1 -1
  23. package/dist/{getPublishPayload-Xl3sRkR-.js → getPublishPayload-CTCvRUoU.js} +50 -18
  24. package/dist/getPublishPayload-CTCvRUoU.js.map +1 -0
  25. package/dist/getPublishUploads-SFHCbf_y.js +648 -0
  26. package/dist/getPublishUploads-SFHCbf_y.js.map +1 -0
  27. package/dist/{index-Xl1_4Lmb.js → index-8O3Uow-Y.js} +125 -57
  28. package/dist/index-8O3Uow-Y.js.map +1 -0
  29. package/dist/{index-CSOQFAOn.js → index-AVFTVp1m.js} +2 -2
  30. package/dist/index-AVFTVp1m.js.map +1 -0
  31. package/dist/index-Cvt5UBz4.js +30 -0
  32. package/dist/index-Cvt5UBz4.js.map +1 -0
  33. package/dist/{index.browser-CjTe0vt1.js → index.browser-DBhxRoe8.js} +554 -165
  34. package/dist/index.browser-DBhxRoe8.js.map +1 -0
  35. package/dist/{index.node-Cfa7npS6.js → index.node-CJhlcNHM.js} +25 -13
  36. package/dist/index.node-CJhlcNHM.js.map +1 -0
  37. package/dist/main.js +30 -47
  38. package/dist/main.js.map +1 -1
  39. package/dist/mimeTypes-DHAHC4eZ.js +204 -0
  40. package/dist/mimeTypes-DHAHC4eZ.js.map +1 -0
  41. package/dist/node.js +19 -21
  42. package/dist/node.js.map +1 -1
  43. package/dist/platform.browser.js +13 -11
  44. package/dist/platform.browser.js.map +1 -1
  45. package/dist/platform.node.js +18 -5
  46. package/dist/platform.node.js.map +1 -1
  47. package/dist/{property-BrXkY1Rg.js → property-DwPD283A.js} +14 -12
  48. package/dist/property-DwPD283A.js.map +1 -0
  49. package/dist/{publishDraftGraph-X0Wr9txE.js → publishDraftGraph-BOn3_Occ.js} +6 -9
  50. package/dist/{publishDraftGraph-X0Wr9txE.js.map → publishDraftGraph-BOn3_Occ.js.map} +1 -1
  51. package/dist/{resetAmbiguousLegacyItemData-Ci6PM_vC.js → resetAmbiguousLegacyItemData-BkYmBeJc.js} +14 -3
  52. package/dist/{resetAmbiguousLegacyItemData-Ci6PM_vC.js.map → resetAmbiguousLegacyItemData-BkYmBeJc.js.map} +1 -1
  53. package/dist/{resolveModelForSyncedSeed-DFVdnYq8.js → resolveModelForSyncedSeed-BL24nLa7.js} +2 -2
  54. package/dist/{resolveModelForSyncedSeed-DFVdnYq8.js.map → resolveModelForSyncedSeed-BL24nLa7.js.map} +1 -1
  55. package/dist/src/Item/Item.d.ts +21 -3
  56. package/dist/src/Item/Item.d.ts.map +1 -1
  57. package/dist/src/Item/service/actors/runPublish.d.ts +11 -2
  58. package/dist/src/Item/service/actors/runPublish.d.ts.map +1 -1
  59. package/dist/src/Item/service/itemMachineSingle.d.ts +12 -2
  60. package/dist/src/Item/service/itemMachineSingle.d.ts.map +1 -1
  61. package/dist/src/ItemProperty/ItemProperty.d.ts +5 -3
  62. package/dist/src/ItemProperty/ItemProperty.d.ts.map +1 -1
  63. package/dist/src/ItemProperty/service/actors/saveValueToDb/analyzeInput.d.ts.map +1 -1
  64. package/dist/src/ItemProperty/service/actors/saveValueToDb/saveItemStorage.d.ts.map +1 -1
  65. package/dist/src/ItemProperty/service/propertyMachine.d.ts.map +1 -1
  66. package/dist/src/Model/Model.d.ts +10 -4
  67. package/dist/src/Model/Model.d.ts.map +1 -1
  68. package/dist/src/Model/index.d.ts +2 -2
  69. package/dist/src/ModelProperty/ModelProperty.d.ts +10 -2
  70. package/dist/src/ModelProperty/ModelProperty.d.ts.map +1 -1
  71. package/dist/src/ModelProperty/service/modelPropertyMachine.d.ts +3 -0
  72. package/dist/src/ModelProperty/service/modelPropertyMachine.d.ts.map +1 -1
  73. package/dist/src/Schema/Schema.d.ts +2 -2
  74. package/dist/src/Schema/Schema.d.ts.map +1 -1
  75. package/dist/src/Schema/index.d.ts +0 -1
  76. package/dist/src/Schema/index.d.ts.map +1 -1
  77. package/dist/src/browser/helpers/FileManager.d.ts +4 -1
  78. package/dist/src/browser/helpers/FileManager.d.ts.map +1 -1
  79. package/dist/src/browser/helpers/tolerantWebAccess.d.ts +79 -4
  80. package/dist/src/browser/helpers/tolerantWebAccess.d.ts.map +1 -1
  81. package/dist/src/browser/workers/FileDownloader.d.ts +19 -4
  82. package/dist/src/browser/workers/FileDownloader.d.ts.map +1 -1
  83. package/dist/src/browser/workers/filesDownload.d.ts.map +1 -1
  84. package/dist/src/client/ClientManager.d.ts +30 -11
  85. package/dist/src/client/ClientManager.d.ts.map +1 -1
  86. package/dist/src/client/actors/platformClassesInit.d.ts +6 -0
  87. package/dist/src/client/actors/platformClassesInit.d.ts.map +1 -1
  88. package/dist/src/client/actors/processSchemaFiles.d.ts.map +1 -1
  89. package/dist/src/client/actors/saveConfig.d.ts +13 -6
  90. package/dist/src/client/actors/saveConfig.d.ts.map +1 -1
  91. package/dist/src/client/clientManagerMachine.d.ts.map +1 -1
  92. package/dist/src/db/migrateLegacyItemStorageRows.d.ts +57 -0
  93. package/dist/src/db/migrateLegacyItemStorageRows.d.ts.map +1 -0
  94. package/dist/src/db/read/getCompositeChildPaths.d.ts +13 -0
  95. package/dist/src/db/read/getCompositeChildPaths.d.ts.map +1 -0
  96. package/dist/src/db/read/getItems.d.ts.map +1 -1
  97. package/dist/src/db/read/getPublishPayload.d.ts +1 -1
  98. package/dist/src/db/read/getPublishPayload.d.ts.map +1 -1
  99. package/dist/src/db/read/getPublishUploads.d.ts +32 -3
  100. package/dist/src/db/read/getPublishUploads.d.ts.map +1 -1
  101. package/dist/src/db/read/summarizePublishWork.d.ts.map +1 -1
  102. package/dist/src/db/write/claimUnpublishedDrafts.d.ts +2 -0
  103. package/dist/src/db/write/claimUnpublishedDrafts.d.ts.map +1 -1
  104. package/dist/src/db/write/convertVerbatimItemStorageRow.d.ts +44 -0
  105. package/dist/src/db/write/convertVerbatimItemStorageRow.d.ts.map +1 -0
  106. package/dist/src/db/write/createNewItem.d.ts.map +1 -1
  107. package/dist/src/eventBus.d.ts +5 -0
  108. package/dist/src/eventBus.d.ts.map +1 -1
  109. package/dist/src/events/files/download.d.ts.map +1 -1
  110. package/dist/src/helpers/FileManager/BaseFileManager.d.ts +3 -3
  111. package/dist/src/helpers/FileManager/BaseFileManager.d.ts.map +1 -1
  112. package/dist/src/helpers/FileManager/IFileManager.d.ts +25 -1
  113. package/dist/src/helpers/FileManager/IFileManager.d.ts.map +1 -1
  114. package/dist/src/helpers/arweaveContentTags.d.ts +33 -0
  115. package/dist/src/helpers/arweaveContentTags.d.ts.map +1 -0
  116. package/dist/src/helpers/cachedPropertyRefresh.d.ts +12 -0
  117. package/dist/src/helpers/cachedPropertyRefresh.d.ts.map +1 -0
  118. package/dist/src/helpers/compositeUpload.d.ts +28 -0
  119. package/dist/src/helpers/compositeUpload.d.ts.map +1 -0
  120. package/dist/src/helpers/db.d.ts +3 -0
  121. package/dist/src/helpers/db.d.ts.map +1 -1
  122. package/dist/src/helpers/easSdk.d.ts +16 -0
  123. package/dist/src/helpers/easSdk.d.ts.map +1 -0
  124. package/dist/src/helpers/entity/detachRowsBeforeDelete.d.ts +16 -0
  125. package/dist/src/helpers/entity/detachRowsBeforeDelete.d.ts.map +1 -0
  126. package/dist/src/helpers/entity/entityDestroy.d.ts +2 -0
  127. package/dist/src/helpers/entity/entityDestroy.d.ts.map +1 -1
  128. package/dist/src/helpers/itemStorageFile.d.ts +57 -0
  129. package/dist/src/helpers/itemStorageFile.d.ts.map +1 -0
  130. package/dist/src/helpers/mapWithConcurrency.d.ts +7 -0
  131. package/dist/src/helpers/mapWithConcurrency.d.ts.map +1 -0
  132. package/dist/src/helpers/mimeTypes.d.ts +43 -0
  133. package/dist/src/helpers/mimeTypes.d.ts.map +1 -0
  134. package/dist/src/helpers/ownership.d.ts +28 -4
  135. package/dist/src/helpers/ownership.d.ts.map +1 -1
  136. package/dist/src/helpers/property/index.d.ts +37 -51
  137. package/dist/src/helpers/property/index.d.ts.map +1 -1
  138. package/dist/src/helpers/publishConfig.d.ts +27 -8
  139. package/dist/src/helpers/publishConfig.d.ts.map +1 -1
  140. package/dist/src/helpers/storageDir.d.ts +16 -0
  141. package/dist/src/helpers/storageDir.d.ts.map +1 -0
  142. package/dist/src/helpers/tabCoordinator.d.ts +5 -1
  143. package/dist/src/helpers/tabCoordinator.d.ts.map +1 -1
  144. package/dist/src/helpers/tabEvents.d.ts +23 -2
  145. package/dist/src/helpers/tabEvents.d.ts.map +1 -1
  146. package/dist/src/helpers/updateSchema.d.ts +5 -0
  147. package/dist/src/helpers/updateSchema.d.ts.map +1 -1
  148. package/dist/src/helpers/waitForEntityIdle.d.ts +5 -0
  149. package/dist/src/helpers/waitForEntityIdle.d.ts.map +1 -1
  150. package/dist/src/imports/json.d.ts +9 -0
  151. package/dist/src/imports/json.d.ts.map +1 -1
  152. package/dist/src/index.d.ts +11 -7
  153. package/dist/src/index.d.ts.map +1 -1
  154. package/dist/src/interfaces/IItem.d.ts +7 -1
  155. package/dist/src/interfaces/IItem.d.ts.map +1 -1
  156. package/dist/src/node/db/Db.d.ts.map +1 -1
  157. package/dist/src/node/helpers/PathResolver.d.ts.map +1 -1
  158. package/dist/src/node/index.d.ts +8 -1
  159. package/dist/src/node/index.d.ts.map +1 -1
  160. package/dist/src/platform/index.browser.d.ts +2 -0
  161. package/dist/src/platform/index.browser.d.ts.map +1 -1
  162. package/dist/src/platform/index.node.d.ts +2 -0
  163. package/dist/src/platform/index.node.d.ts.map +1 -1
  164. package/dist/src/types/fileManager.d.ts +3 -14
  165. package/dist/src/types/fileManager.d.ts.map +1 -1
  166. package/dist/src/types/index.d.ts +12 -1
  167. package/dist/src/types/index.d.ts.map +1 -1
  168. package/dist/src/types/machines.d.ts +2 -0
  169. package/dist/src/types/machines.d.ts.map +1 -1
  170. package/dist/src/types/property.d.ts +8 -0
  171. package/dist/src/types/property.d.ts.map +1 -1
  172. package/dist/src/types/publish.d.ts +14 -0
  173. package/dist/src/types/publish.d.ts.map +1 -1
  174. package/dist/{syncDbWithEas-BU-jZ5bJ.js → syncDbWithEas-Bv2Fe38J.js} +17 -17
  175. package/dist/{syncDbWithEas-BU-jZ5bJ.js.map → syncDbWithEas-Bv2Fe38J.js.map} +1 -1
  176. package/dist/tabEvents-9s2WCYw-.js +335 -0
  177. package/dist/tabEvents-9s2WCYw-.js.map +1 -0
  178. package/dist/tolerantWebAccess-iUu80pAP.js +551 -0
  179. package/dist/tolerantWebAccess-iUu80pAP.js.map +1 -0
  180. package/dist/{updateSeedRevokedAt-iLpzae1i.js → updateSeedRevokedAt-zBfi931j.js} +3 -3
  181. package/dist/{updateSeedRevokedAt-iLpzae1i.js.map → updateSeedRevokedAt-zBfi931j.js.map} +1 -1
  182. package/package.json +11 -12
  183. package/src/node/easLodashRegister.js +4 -0
  184. package/dist/BasePathResolver-BdxCSIzn.js +0 -679
  185. package/dist/BasePathResolver-BdxCSIzn.js.map +0 -1
  186. package/dist/ClientManager-DDA9956Y.js.map +0 -1
  187. package/dist/Item-D4FigtYS.js.map +0 -1
  188. package/dist/ModelProperty-BDt6AU2h.js.map +0 -1
  189. package/dist/Schema-B8xqLWkL.js.map +0 -1
  190. package/dist/cjs/ModelProperty-B-cZm1yU.js +0 -1977
  191. package/dist/cjs/ModelProperty-B-cZm1yU.js.map +0 -1
  192. package/dist/cjs/Schema-STP972Xw.js +0 -5256
  193. package/dist/cjs/Schema-STP972Xw.js.map +0 -1
  194. package/dist/cjs/SchemaValidationService-CKNW1bKg.js +0 -778
  195. package/dist/cjs/SchemaValidationService-CKNW1bKg.js.map +0 -1
  196. package/dist/cjs/backfillMetadataPropertyIds-CP3y1skt.js +0 -89
  197. package/dist/cjs/backfillMetadataPropertyIds-CP3y1skt.js.map +0 -1
  198. package/dist/cjs/eas-CAnUC4wd.js +0 -138
  199. package/dist/cjs/eas-CAnUC4wd.js.map +0 -1
  200. package/dist/cjs/getItem-CWgb3e9G.js +0 -58
  201. package/dist/cjs/getItem-CWgb3e9G.js.map +0 -1
  202. package/dist/cjs/getPublishPayload-BsZWiJ03.js +0 -1603
  203. package/dist/cjs/getPublishPayload-BsZWiJ03.js.map +0 -1
  204. package/dist/cjs/getPublishUploads-BQr8aMVP.js +0 -495
  205. package/dist/cjs/getPublishUploads-BQr8aMVP.js.map +0 -1
  206. package/dist/cjs/index-nA5PxBSs.js +0 -70
  207. package/dist/cjs/index-nA5PxBSs.js.map +0 -1
  208. package/dist/cjs/index-usKaANAq.js +0 -22171
  209. package/dist/cjs/index-usKaANAq.js.map +0 -1
  210. package/dist/cjs/index.browser-BSf8HpnU.js +0 -22
  211. package/dist/cjs/index.browser-BSf8HpnU.js.map +0 -1
  212. package/dist/cjs/property-xMwPhQ5N.js +0 -327
  213. package/dist/cjs/property-xMwPhQ5N.js.map +0 -1
  214. package/dist/cjs/publishDraftGraph-BRWlR1KO.js +0 -403
  215. package/dist/cjs/publishDraftGraph-BRWlR1KO.js.map +0 -1
  216. package/dist/cjs/resetAmbiguousLegacyItemData-8nfkj9rz.js +0 -116
  217. package/dist/cjs/resetAmbiguousLegacyItemData-8nfkj9rz.js.map +0 -1
  218. package/dist/cjs/resolveModelForSyncedSeed-kYRuDWYw.js +0 -49
  219. package/dist/cjs/resolveModelForSyncedSeed-kYRuDWYw.js.map +0 -1
  220. package/dist/cjs/syncDbWithEas-DqRhV8o2.js +0 -886
  221. package/dist/cjs/syncDbWithEas-DqRhV8o2.js.map +0 -1
  222. package/dist/db-CQt-gcAl.js.map +0 -1
  223. package/dist/eas-CpOD74Ke.js.map +0 -1
  224. package/dist/getPublishPayload-Xl3sRkR-.js.map +0 -1
  225. package/dist/getPublishUploads-DHP01KgU.js +0 -484
  226. package/dist/getPublishUploads-DHP01KgU.js.map +0 -1
  227. package/dist/index-BGt4_oPO.js +0 -31
  228. package/dist/index-BGt4_oPO.js.map +0 -1
  229. package/dist/index-CSOQFAOn.js.map +0 -1
  230. package/dist/index-Xl1_4Lmb.js.map +0 -1
  231. package/dist/index.browser-CjTe0vt1.js.map +0 -1
  232. package/dist/index.node-Cfa7npS6.js.map +0 -1
  233. package/dist/main.cjs +0 -84
  234. package/dist/main.cjs.map +0 -1
  235. package/dist/property-BrXkY1Rg.js.map +0 -1
  236. package/dist/tabEvents-BZJMY5uK.js +0 -1344
  237. package/dist/tabEvents-BZJMY5uK.js.map +0 -1
  238. package/dist/tolerantWebAccess-BZ2RA_mb.js +0 -160
  239. package/dist/tolerantWebAccess-BZ2RA_mb.js.map +0 -1
@@ -1,17 +1,21 @@
1
1
  import { waitFor, fromCallback, setup, assign, stateIn, createActor, isMachineSnapshot } from 'xstate';
2
- import { a as BaseDb, v as versions, m as metadata, r as seeds, s as schemas, j as models, g as modelSchemas, Z as ZERO_BYTES32, I as INTERNAL_PROPERTY_NAMES, B as BaseFileManager, D as ImageSize, p as properties, x as INTERNAL_DATA_TYPES, i as modelUids, C as INTERNAL_STORAGE_MODEL_FILE_IDS, P as PROPERTY_NAMES_EXEMPT_FROM_ID_SUFFIX_STRIP } from './BasePathResolver-BdxCSIzn.js';
2
+ import { n as normalizeDataType, E as BaseDb, C as versions, m as metadata, A as seeds, z as schemas, s as models, q as modelSchemas, aQ as getOwnedAddressesFromDb, a9 as ZERO_BYTES32, aB as normalizeAddressList, a0 as normalizeHexAddress, ay as getAddressesForItemsFilter, H as toSnakeCase$1, ad as INTERNAL_PROPERTY_NAMES, J as BaseFileManager, aS as getStorageTransactionIdForSeedUid, aT as convertTxIdToImage, i as isDataType, X as normalizePublisher, ax as ensureImageLocal, ap as ImageSize, aU as downloadTransactionIdWithDedupe, u as properties, M as ModelPropertyDataTypes, $ as generateId, ag as INTERNAL_DATA_TYPES, r as modelUids, L as resolveItemModelFileId, aV as getPropertyIdForSchemaFileId, K as getPropertyIdForModelAndName, aW as getDataTypeFromString, aX as getMimeType, am as INTERNAL_STORAGE_MODEL_FILE_IDS, V as getItemStorageSubdir, W as getItemStorageLocalFileName, g as normalizePropertyRecordSchema, aY as PROPERTY_NAMES_EXEMPT_FROM_ID_SUFFIX_STRIP, a5 as getCorrectId, G as eventEmitter, ae as isStorageSeedRef } from './BasePathResolver-Cm4apKRb.js';
3
3
  import { or, isNull, eq, max, count, and, getTableColumns, sql, desc, inArray, isNotNull, gt } from 'drizzle-orm';
4
4
  import pluralize from 'pluralize';
5
- import { n as normalizeDataType, W as getOwnedAddressesFromDb, E as normalizeAddressList, u as normalizeHexAddress, z as getAddressesForItemsFilter, k as isDataType, s as normalizePublisher, M as ModelPropertyDataTypes, r as resolveItemModelFileId, X as getPropertyIdForSchemaFileId, o as getPropertyIdForModelAndName, l as normalizePropertyRecordSchema, m as eventEmitter } from './db-CQt-gcAl.js';
6
5
  import debug from 'debug';
7
6
  import { BehaviorSubject } from 'rxjs';
8
7
  import { startCase, upperFirst, camelCase, orderBy } from 'lodash-es';
9
8
  import { toSnakeCase } from 'drizzle-orm/casing';
10
9
  import { isValidEasAttestationUid, isPlaceholderUid, BaseQueryClient, BaseEasClient, GET_SCHEMAS, getEasSchemaUidForSchemaDefinition, getSchemaUidForModelFromCache, cachedSchemaLookup, setSchemaUidForModel, getEasSchemaUidForExactDefinition } from '@seedprotocol/eas';
11
- import { t as toSnakeCase$1, H as getStorageTransactionIdForSeedUid, I as convertTxIdToImage, h as ensureImageLocal, J as downloadTransactionIdWithDedupe, b as generateId, K as getDataTypeFromString, M as getMimeType, N as notifyFileSaved, g as getCorrectId, a as isStorageSeedRef } from './tabEvents-BZJMY5uK.js';
12
10
  import { fetchArweaveRawTextAcrossGateways } from '@seedprotocol/arweave';
11
+ import { d as notifyFileSaved, f as withTabLock } from './tabEvents-9s2WCYw-.js';
13
12
  import { modelPropertiesToObject } from './model-DGMe-TTm.js';
14
13
 
14
+ /**
15
+ * Default readyTimeout for create/find/all with waitForReady. Loads that touch OPFS and the DB can take
16
+ * several seconds on slow devices and CI runners; a load that is really stuck still errors.
17
+ */
18
+ const DEFAULT_READY_TIMEOUT_MS = 15000;
15
19
  /**
16
20
  * Wait for an entity's state machine to reach 'idle' state
17
21
  * @param entity - Entity instance with getService() method
@@ -19,7 +23,7 @@ import { modelPropertiesToObject } from './model-DGMe-TTm.js';
19
23
  * @returns Promise that resolves when entity reaches idle, or rejects on error/timeout
20
24
  */
21
25
  async function waitForEntityIdle(entity, options = {}) {
22
- const { timeout = 5000, throwOnError = true } = options;
26
+ const { timeout = DEFAULT_READY_TIMEOUT_MS, throwOnError = true } = options;
23
27
  const service = entity.getService();
24
28
  const currentSnapshot = service.getSnapshot();
25
29
  const isSnapshotIdle = (snapshot) => {
@@ -93,10 +97,20 @@ async function getPublisherForNewSeedsWithTimeout() {
93
97
  return undefined;
94
98
  }
95
99
  }
100
+ let publishExecutor = null;
101
+ function setPublishExecutor(executor) {
102
+ publishExecutor = executor;
103
+ }
104
+ function getPublishExecutor() {
105
+ return publishExecutor;
106
+ }
107
+ const PUBLISH_NOT_CONFIGURED_MESSAGE = 'Publishing is not configured. item.publish() needs @seedprotocol/publish: call initPublish() from it, or mount <PublishProvider config={...}>, before publishing.';
96
108
  let uploadExecutor = null;
109
+ /** @deprecated See UploadExecutor. */
97
110
  function setUploadExecutor(executor) {
98
111
  uploadExecutor = executor;
99
112
  }
113
+ /** @deprecated See UploadExecutor. */
100
114
  function getUploadExecutor() {
101
115
  return uploadExecutor;
102
116
  }
@@ -117,13 +131,16 @@ function getGetAdditionalSyncAddresses() {
117
131
 
118
132
  var publishConfig = /*#__PURE__*/Object.freeze({
119
133
  __proto__: null,
134
+ PUBLISH_NOT_CONFIGURED_MESSAGE: PUBLISH_NOT_CONFIGURED_MESSAGE,
120
135
  getGetAdditionalSyncAddresses: getGetAdditionalSyncAddresses,
121
136
  getGetPublisherForNewSeeds: getGetPublisherForNewSeeds,
137
+ getPublishExecutor: getPublishExecutor,
122
138
  getPublisherForNewSeedsWithTimeout: getPublisherForNewSeedsWithTimeout,
123
139
  getRevokeExecutor: getRevokeExecutor,
124
140
  getUploadExecutor: getUploadExecutor,
125
141
  setAdditionalSyncAddresses: setAdditionalSyncAddresses,
126
142
  setGetPublisherForNewSeeds: setGetPublisherForNewSeeds,
143
+ setPublishExecutor: setPublishExecutor,
127
144
  setRevokeExecutor: setRevokeExecutor,
128
145
  setUploadExecutor: setUploadExecutor
129
146
  });
@@ -708,7 +725,7 @@ const createItemPropertyInstances = async (metadataRows, seedLocalId, seedUid, m
708
725
  const itemPropertyMod = await Promise.resolve().then(function () { return ItemProperty$1; });
709
726
  const { ItemProperty } = itemPropertyMod;
710
727
  const { modelPropertiesToObject } = await import('./model-DGMe-TTm.js');
711
- const _mod_0 = await import('./index-Xl1_4Lmb.js');
728
+ const _mod_0 = await import('./index-8O3Uow-Y.js');
712
729
  const _ns_0 = _mod_0.f;
713
730
  const { Model } = _ns_0;
714
731
  // Resolve Model and build property schemas (use getByNameAsync for models not yet in cache)
@@ -726,7 +743,7 @@ const createItemPropertyInstances = async (metadataRows, seedLocalId, seedUid, m
726
743
  const schemaNameToTry = schemaName ?? model?.schemaName;
727
744
  if (schemaNameToTry) {
728
745
  try {
729
- const _mod_1 = await import('./Schema-B8xqLWkL.js');
746
+ const _mod_1 = await import('./Schema-CpMNEnUO.js');
730
747
  const _ns_1 = _mod_1.b;
731
748
  const { Schema } = _ns_1;
732
749
  const schemaInstance = Schema.create(schemaNameToTry, { waitForReady: false });
@@ -742,8 +759,8 @@ const createItemPropertyInstances = async (metadataRows, seedLocalId, seedUid, m
742
759
  }
743
760
  if (Object.keys(propertySchemas).length === 0) {
744
761
  try {
745
- const _mod_2 = await import('./ClientManager-DDA9956Y.js');
746
- const _ns_2 = _mod_2.G;
762
+ const _mod_2 = await import('./ClientManager-i3nJASkg.js');
763
+ const _ns_2 = _mod_2.K;
747
764
  const { loadAllSchemasFromDb } = _ns_2;
748
765
  const allSchemas = await loadAllSchemasFromDb();
749
766
  for (const { schema: schemaFile } of allSchemas) {
@@ -763,11 +780,11 @@ const createItemPropertyInstances = async (metadataRows, seedLocalId, seedUid, m
763
780
  }
764
781
  if (Object.keys(propertySchemas).length === 0) {
765
782
  try {
766
- const _mod_3 = await import('./ClientManager-DDA9956Y.js');
767
- const _ns_3 = _mod_3.G;
783
+ const _mod_3 = await import('./ClientManager-i3nJASkg.js');
784
+ const _ns_3 = _mod_3.K;
768
785
  const { listCompleteSchemaFiles } = _ns_3;
769
- const _mod_4 = await import('./BasePathResolver-BdxCSIzn.js');
770
- const _ns_4 = _mod_4.O;
786
+ const _mod_4 = await import('./BasePathResolver-Cm4apKRb.js');
787
+ const _ns_4 = _mod_4.a_;
771
788
  const { BaseFileManager } = _ns_4;
772
789
  const schemaFiles = await listCompleteSchemaFiles();
773
790
  for (const { filePath } of schemaFiles) {
@@ -787,7 +804,7 @@ const createItemPropertyInstances = async (metadataRows, seedLocalId, seedUid, m
787
804
  }
788
805
  }
789
806
  if (Object.keys(propertySchemas).length === 0) {
790
- const schemaMod = await import('./index-BGt4_oPO.js');
807
+ const schemaMod = await import('./index-Cvt5UBz4.js');
791
808
  const { ModelPropertyDataTypes } = schemaMod;
792
809
  const KNOWN_MODEL_FALLBACKS = {
793
810
  Post: {
@@ -804,7 +821,7 @@ const createItemPropertyInstances = async (metadataRows, seedLocalId, seedUid, m
804
821
  }
805
822
  }
806
823
  // Fallbacks above may return schema-file shape ({ type, model, items }); normalize to dataType/ref/refValueType.
807
- const { normalizePropertyRecordSchema } = await import('./property-BrXkY1Rg.js');
824
+ const { normalizePropertyRecordSchema } = await import('./property-DwPD283A.js');
808
825
  propertySchemas = Object.fromEntries(Object.entries(propertySchemas).map(([name, def]) => [name, normalizePropertyRecordSchema(def)]));
809
826
  // Collapse rows that map to the same instance key (e.g. authorIdentityIds + authors -> authors).
810
827
  // ItemProperty.create cache does not sync propertyValue on hit; processing order would otherwise
@@ -837,7 +854,7 @@ const createItemPropertyInstances = async (metadataRows, seedLocalId, seedUid, m
837
854
  // Infer propertyRecordSchema from metadata when schema is missing (enables persistence)
838
855
  let propSchema = propertySchemas[propertyName];
839
856
  if (!propSchema && isRefTypeFromMeta) {
840
- const schemaMod = await import('./index-BGt4_oPO.js');
857
+ const schemaMod = await import('./index-Cvt5UBz4.js');
841
858
  const { ModelPropertyDataTypes } = schemaMod;
842
859
  propSchema = {
843
860
  dataType: refSeedType === 'html' ? ModelPropertyDataTypes.Html
@@ -1089,48 +1106,36 @@ const loadOrCreateItem = fromCallback(({ sendBack, input: { context } }) => {
1089
1106
  });
1090
1107
 
1091
1108
  const logger$7 = debug('seedSdk:Item:runPublish');
1092
- const runPublish = fromCallback(({ sendBack, input: { context } }) => {
1109
+ /**
1110
+ * Runs the publish for item.publish() by handing the item to the PublishExecutor that
1111
+ * @seedprotocol/publish registers, which uploads to Arweave and writes to EAS.
1112
+ */
1113
+ const runPublish = fromCallback(({ sendBack, input: { context, item: itemFromEvent, options } }) => {
1093
1114
  const { seedLocalId } = context;
1094
1115
  const _runPublish = async () => {
1095
1116
  if (!seedLocalId) {
1096
1117
  sendBack({ type: 'publishError', error: new Error('Item has no seedLocalId') });
1097
1118
  return;
1098
1119
  }
1120
+ const executor = getPublishExecutor();
1121
+ if (!executor) {
1122
+ sendBack({ type: 'publishError', error: new Error(PUBLISH_NOT_CONFIGURED_MESSAGE) });
1123
+ return;
1124
+ }
1099
1125
  try {
1100
- const itemMod = await Promise.resolve().then(function () { return Item$1; });
1101
- const { Item } = itemMod;
1102
- const item = await Item.find({ seedLocalId });
1126
+ // item.publish() sends its own instance; look it up only if startPublish came without one.
1127
+ const item = itemFromEvent ??
1128
+ (await (await Promise.resolve().then(function () { return Item$1; })).Item.find({ seedLocalId }));
1103
1129
  if (!item) {
1104
- sendBack({ type: 'publishError', error: new Error(`Item not found for seedLocalId: ${seedLocalId}`) });
1130
+ sendBack({ type: 'publishError', error: new Error(`Item not found: ${seedLocalId}`) });
1105
1131
  return;
1106
1132
  }
1107
- const getPublishUploadsMod = await import('./getPublishUploads-DHP01KgU.js');
1108
- const { getPublishUploads } = getPublishUploadsMod;
1109
- const _mod_5 = await import('./getPublishPayload-Xl3sRkR-.js');
1110
- const _ns_5 = _mod_5.g;
1111
- const getPublishPayloadMod = _ns_5;
1112
- const { getPublishPayload } = getPublishPayloadMod;
1113
- const uploads = await getPublishUploads(item);
1114
- let uploadedTransactions = [];
1115
- const executor = getUploadExecutor();
1116
- if (executor && uploads.length > 0) {
1117
- for (const upload of uploads) {
1118
- const { txId } = await executor(upload);
1119
- uploadedTransactions.push({
1120
- txId,
1121
- seedLocalId: upload.seedLocalId,
1122
- versionLocalId: upload.versionLocalId,
1123
- });
1124
- }
1125
- }
1126
- await getPublishPayload(item, uploadedTransactions);
1127
- logger$7('runPublish: payload prepared (upload/EAS submit stubbed)');
1133
+ await executor(item, options);
1128
1134
  sendBack({ type: 'publishSuccess' });
1129
1135
  }
1130
- catch (err) {
1131
- const error = err instanceof Error ? err : new Error(String(err));
1136
+ catch (error) {
1132
1137
  logger$7('runPublish error:', error);
1133
- sendBack({ type: 'publishError', error });
1138
+ sendBack({ type: 'publishError', error: error instanceof Error ? error : new Error(String(error)) });
1134
1139
  }
1135
1140
  };
1136
1141
  _runPublish();
@@ -1258,7 +1263,11 @@ const itemMachineSingle = setup({
1258
1263
  },
1259
1264
  invoke: {
1260
1265
  src: 'runPublish',
1261
- input: ({ context }) => ({ context }),
1266
+ input: ({ context, event }) => ({
1267
+ context,
1268
+ item: event.item,
1269
+ options: event.options,
1270
+ }),
1262
1271
  },
1263
1272
  },
1264
1273
  waitingForDb: {
@@ -1656,6 +1665,17 @@ async function batchLatestPublishedVersionBySeedLocalIds(seedLocalIds) {
1656
1665
  }
1657
1666
 
1658
1667
  const READ_ONLY_ERROR = 'Item is read-only: you do not own this item';
1668
+ /**
1669
+ * Thrown by write operations (save, destroy, publish, unpublish) on an item none
1670
+ * of the client's addresses own. See isItemOwned for what counts as owned.
1671
+ */
1672
+ class OwnershipError extends Error {
1673
+ constructor(message = READ_ONLY_ERROR) {
1674
+ super(message);
1675
+ this.name = 'OwnershipError';
1676
+ Object.setPrototypeOf(this, OwnershipError.prototype);
1677
+ }
1678
+ }
1659
1679
  async function getSeedRowForItem(item) {
1660
1680
  const appDb = BaseDb.getAppDb();
1661
1681
  if (!appDb)
@@ -1731,8 +1751,9 @@ function isSeedRowOwned(row, ownedAddresses) {
1731
1751
  return publisherIsInOwnedSet(publisher, ownedAddresses);
1732
1752
  }
1733
1753
  /**
1734
- * SQL for `addressFilter: 'owned' | 'watched'`. Empty list → no rows (`1=0`).
1735
- * Compares `lower(publisher)` so checksummed rows match persisted lowercase owned.
1754
+ * SQL for an address list on `publisher`. Empty list → no rows (`1=0`).
1755
+ * Compares `lower(publisher)` so checksummed rows match persisted lowercase addresses.
1756
+ * Used for `addressFilter: 'watched'`; `'owned'` uses {@link ownedSeedsSql}.
1736
1757
  */
1737
1758
  function publisherInAddressListSql(column, addresses) {
1738
1759
  const normalized = normalizeAddressList(addresses);
@@ -1741,10 +1762,37 @@ function publisherInAddressListSql(column, addresses) {
1741
1762
  }
1742
1763
  return inArray(sql `lower(${column})`, normalized);
1743
1764
  }
1744
- /** Owned-list SQL on `seeds.publisher`. */
1765
+ /**
1766
+ * @deprecated Matches `seeds.publisher` only. Use {@link ownedSeedsSql}, which agrees
1767
+ * with {@link isSeedRowOwned} (empty owned → local unsealed drafts; attester fallback).
1768
+ */
1745
1769
  function ownedPublisherSql(ownedAddresses) {
1746
1770
  return publisherInAddressListSql(seeds.publisher, ownedAddresses);
1747
1771
  }
1772
+ /** SQL form of {@link isPlaceholderUid}: null, `''`, `'NULL'`, or zero bytes32 (trimmed, any case). */
1773
+ function placeholderUidSql(column) {
1774
+ return or(isNull(column), eq(column, 'NULL'), sql `trim(${column}) = ''`, sql `lower(trim(${column})) = ${ZERO_BYTES32.toLowerCase()}`);
1775
+ }
1776
+ const isBlankSql = (column) => or(isNull(column), eq(column, ''));
1777
+ /** SQL form of {@link isLocalUnsealedDraft} on `seeds`. */
1778
+ function localUnsealedDraftSql() {
1779
+ return and(isBlankSql(seeds.publisher), placeholderUidSql(seeds.uid), isBlankSql(seeds.attestationRaw));
1780
+ }
1781
+ /**
1782
+ * SQL for `addressFilter: 'owned'`: a row passes exactly when {@link isSeedRowOwned} is true.
1783
+ * - Empty owned → local unsealed drafts (pre-connect authoring), not every row.
1784
+ * - Owned set → `lower(trim(publisher))` in the set, or, when publisher is blank, the
1785
+ * `attestationRaw.attester` ({@link resolvePublisherFromSeedRow}). `json_valid` guards
1786
+ * `json_extract`, which throws on malformed JSON.
1787
+ */
1788
+ function ownedSeedsSql(ownedAddresses) {
1789
+ const normalized = normalizeAddressList(ownedAddresses);
1790
+ if (normalized.length === 0) {
1791
+ return localUnsealedDraftSql();
1792
+ }
1793
+ const attester = sql `CASE WHEN json_valid(${seeds.attestationRaw}) THEN lower(trim(json_extract(${seeds.attestationRaw}, '$.attester'))) END`;
1794
+ return or(inArray(sql `lower(trim(${seeds.publisher}))`, normalized), and(isBlankSql(seeds.publisher), inArray(attester, normalized)));
1795
+ }
1748
1796
  /**
1749
1797
  * Checks if the current user owns the item (publisher is in persisted owned addresses).
1750
1798
  *
@@ -1766,22 +1814,27 @@ async function isItemOwned(item) {
1766
1814
  return isSeedRowOwned(row, ownedAddresses);
1767
1815
  }
1768
1816
  /**
1769
- * Throws if the item is not owned. Use before write operations (publish, save, destroy).
1817
+ * Throws OwnershipError if the item is not owned. Use before write operations
1818
+ * (publish, save, destroy).
1770
1819
  */
1771
1820
  async function assertItemOwned(item) {
1772
1821
  const owned = await isItemOwned(item);
1773
1822
  if (!owned) {
1774
- throw new Error(READ_ONLY_ERROR);
1823
+ throw new OwnershipError();
1775
1824
  }
1776
1825
  }
1777
1826
 
1778
1827
  var ownership = /*#__PURE__*/Object.freeze({
1779
1828
  __proto__: null,
1829
+ OwnershipError: OwnershipError,
1780
1830
  assertItemOwned: assertItemOwned,
1781
1831
  isItemOwned: isItemOwned,
1782
1832
  isLocalUnsealedDraft: isLocalUnsealedDraft,
1783
1833
  isSeedRowOwned: isSeedRowOwned,
1834
+ localUnsealedDraftSql: localUnsealedDraftSql,
1784
1835
  ownedPublisherSql: ownedPublisherSql,
1836
+ ownedSeedsSql: ownedSeedsSql,
1837
+ placeholderUidSql: placeholderUidSql,
1785
1838
  publisherInAddressListSql: publisherInAddressListSql,
1786
1839
  publisherIsInOwnedSet: publisherIsInOwnedSet,
1787
1840
  resolvePublisherFromSeedRow: resolvePublisherFromSeedRow
@@ -1801,15 +1854,15 @@ const getItemsData = async ({ modelName, modelFileId, schemaName, deleted, inclu
1801
1854
  const appDb = BaseDb.getAppDb();
1802
1855
  const conditions = [];
1803
1856
  if (!includeEas) {
1804
- conditions.push(or(isNull(seeds.uid), eq(seeds.uid, ''), eq(seeds.uid, 'NULL'), eq(seeds.uid, ZERO_BYTES32)));
1857
+ conditions.push(placeholderUidSql(seeds.uid));
1805
1858
  }
1806
1859
  if (modelName) {
1807
1860
  conditions.push(eq(seeds.type, toSnakeCase(modelName)));
1808
1861
  }
1809
1862
  if (!modelFileId && schemaName && modelName) {
1810
- const _mod_6 = await import('./db-CQt-gcAl.js');
1811
- const _ns_6 = _mod_6.Y;
1812
- const { resolveModelRecord } = _ns_6;
1863
+ const _mod_5 = await import('./BasePathResolver-Cm4apKRb.js');
1864
+ const _ns_5 = _mod_5.b1;
1865
+ const { resolveModelRecord } = _ns_5;
1813
1866
  modelFileId = (await resolveModelRecord(modelName, { schemaName }))?.schemaFileId ?? undefined;
1814
1867
  if (!modelFileId)
1815
1868
  return []; // that schema has no such model
@@ -1819,7 +1872,7 @@ const getItemsData = async ({ modelName, modelFileId, schemaName, deleted, inclu
1819
1872
  }
1820
1873
  if (addressFilter === 'owned') {
1821
1874
  const ownedAddresses = await getAddressesForItemsFilter('owned');
1822
- conditions.push(publisherInAddressListSql(seeds.publisher, ownedAddresses));
1875
+ conditions.push(ownedSeedsSql(ownedAddresses));
1823
1876
  }
1824
1877
  else if (addressFilter === 'watched') {
1825
1878
  const watchedAddresses = await getAddressesForItemsFilter('watched');
@@ -2090,7 +2143,7 @@ const resolveRelatedValue = fromCallback(({ sendBack, input: { context } }) => {
2090
2143
  const { isRelation, propertyValue, propertyName, seedUid, propertyRecordSchema, populatedFromDb, schemaUid, } = context;
2091
2144
  const _resolveRelatedValue = async () => {
2092
2145
  // Use dynamic import to break circular dependency
2093
- const schemaMod = await import('./index-BGt4_oPO.js');
2146
+ const schemaMod = await import('./index-Cvt5UBz4.js');
2094
2147
  const { ModelPropertyDataTypes } = schemaMod;
2095
2148
  if (!propertyValue || !isRelation || populatedFromDb) {
2096
2149
  return;
@@ -2525,9 +2578,9 @@ async function readHtmlBodyFromChildStorageArweave(seedLocalId) {
2525
2578
  /* offline / bad tx id */
2526
2579
  }
2527
2580
  try {
2528
- const _mod_7 = await import('./tabEvents-BZJMY5uK.js');
2529
- const _ns_7 = _mod_7.O;
2530
- const { downloadTransactionIdWithDedupe } = _ns_7;
2581
+ const _mod_6 = await import('./BasePathResolver-Cm4apKRb.js');
2582
+ const _ns_6 = _mod_6.b3;
2583
+ const { downloadTransactionIdWithDedupe } = _ns_6;
2531
2584
  await downloadTransactionIdWithDedupe(txId);
2532
2585
  const retryFp = BaseFileManager.getFilesPath('html', `${seedLocalId}.html`);
2533
2586
  if (await BaseFileManager.pathExists(retryFp)) {
@@ -2586,7 +2639,7 @@ const hydrateFromDb = fromCallback(({ sendBack, input: { context } }) => {
2586
2639
  // to use dynamically imported ModelPropertyDataTypes
2587
2640
  const _hydrateFromDb = async () => {
2588
2641
  // Use dynamic import to break circular dependency
2589
- const schemaMod = await import('./index-BGt4_oPO.js');
2642
+ const schemaMod = await import('./index-Cvt5UBz4.js');
2590
2643
  const { ModelPropertyDataTypes } = schemaMod;
2591
2644
  const appDb = BaseDb.getAppDb();
2592
2645
  const whereClauses = [];
@@ -2865,13 +2918,13 @@ const loadOrCreateProperty = fromCallback(({ sendBack, input: { context } }) =>
2865
2918
  const modelNameForNew = context.modelName;
2866
2919
  if (modelNameForNew) {
2867
2920
  try {
2868
- const _mod_8 = await import('./index-Xl1_4Lmb.js');
2869
- const _ns_8 = _mod_8.f;
2870
- const { Model } = _ns_8;
2921
+ const _mod_7 = await import('./index-8O3Uow-Y.js');
2922
+ const _ns_7 = _mod_7.f;
2923
+ const { Model } = _ns_7;
2871
2924
  const { modelPropertiesToObject } = await import('./model-DGMe-TTm.js');
2872
- const _mod_9 = await import('./db-CQt-gcAl.js');
2873
- const _ns_9 = _mod_9.Y;
2874
- const { resolveItemModelFileId } = _ns_9;
2925
+ const _mod_8 = await import('./BasePathResolver-Cm4apKRb.js');
2926
+ const _ns_8 = _mod_8.b1;
2927
+ const { resolveItemModelFileId } = _ns_8;
2875
2928
  const normalizedModelName = upperFirst(camelCase(modelNameForNew));
2876
2929
  const itemModelFileId = await resolveItemModelFileId({
2877
2930
  modelFileId: context.modelFileId,
@@ -2923,9 +2976,9 @@ const loadOrCreateProperty = fromCallback(({ sendBack, input: { context } }) =>
2923
2976
  // It ends up in the context below, and later lookups by name (Model.getByName) can't match it.
2924
2977
  const modelName = context.modelName || (metadataRecord.modelType ? upperFirst(camelCase(metadataRecord.modelType)) : undefined);
2925
2978
  // Model names are only unique per schema: pin lookups to the item's own model row.
2926
- const _mod_10 = await import('./db-CQt-gcAl.js');
2927
- const _ns_10 = _mod_10.Y;
2928
- const { resolveItemModelFileId, resolveModelRecord } = _ns_10;
2979
+ const _mod_9 = await import('./BasePathResolver-Cm4apKRb.js');
2980
+ const _ns_9 = _mod_9.b1;
2981
+ const { resolveItemModelFileId, resolveModelRecord } = _ns_9;
2929
2982
  const modelFileId = await resolveItemModelFileId({
2930
2983
  modelFileId: context.modelFileId,
2931
2984
  seedLocalId: seedLocalId ?? metadataRecord.seedLocalId,
@@ -2969,18 +3022,18 @@ const loadOrCreateProperty = fromCallback(({ sendBack, input: { context } }) =>
2969
3022
  };
2970
3023
  // Merge with schema from file/DB to get validation rules (enum, pattern, etc.) - properties table doesn't store these
2971
3024
  try {
2972
- const { getPropertySchema } = await import('./property-BrXkY1Rg.js');
3025
+ const { getPropertySchema } = await import('./property-DwPD283A.js');
2973
3026
  let schemaFromFile = await getPropertySchema(normalizedModelName, propertyName, {
2974
3027
  modelFileId: modelRecord?.schemaFileId ?? modelFileId,
2975
3028
  });
2976
3029
  if (!schemaFromFile?.validation) {
2977
3030
  // Fallback: get validation from schemaData in database (Schema context may not be loaded yet)
2978
- const _mod_11 = await import('./BasePathResolver-BdxCSIzn.js');
2979
- const _ns_11 = _mod_11.Q;
2980
- const { schemas: schemasTable } = _ns_11;
2981
- const _mod_12 = await import('./BasePathResolver-BdxCSIzn.js');
2982
- const _ns_12 = _mod_12.R;
2983
- const { modelSchemas } = _ns_12;
3031
+ const _mod_10 = await import('./BasePathResolver-Cm4apKRb.js');
3032
+ const _ns_10 = _mod_10.a$;
3033
+ const { schemas: schemasTable } = _ns_10;
3034
+ const _mod_11 = await import('./BasePathResolver-Cm4apKRb.js');
3035
+ const _ns_11 = _mod_11.b0;
3036
+ const { modelSchemas } = _ns_11;
2984
3037
  const modelSchemaRows = await db
2985
3038
  .select({ schemaId: modelSchemas.schemaId })
2986
3039
  .from(modelSchemas)
@@ -3019,9 +3072,9 @@ const loadOrCreateProperty = fromCallback(({ sendBack, input: { context } }) =>
3019
3072
  }
3020
3073
  if (!propertyRecordSchema && modelName) {
3021
3074
  try {
3022
- const _mod_13 = await import('./index-Xl1_4Lmb.js');
3023
- const _ns_13 = _mod_13.f;
3024
- const { Model } = _ns_13;
3075
+ const _mod_12 = await import('./index-8O3Uow-Y.js');
3076
+ const _ns_12 = _mod_12.f;
3077
+ const { Model } = _ns_12;
3025
3078
  const { modelPropertiesToObject } = await import('./model-DGMe-TTm.js');
3026
3079
  const normalizedModelName = upperFirst(camelCase(modelName));
3027
3080
  // Try PascalCase first ("post" -> "Post"); then findByModelType for names with spaces ("new_model" -> "New model")
@@ -3395,10 +3448,16 @@ const analyzeInput = fromCallback(({ sendBack, input: { context, event } }) => {
3395
3448
  throw new Error('Missing propertyRecordSchema');
3396
3449
  }
3397
3450
  const _analyzeInput = async () => {
3451
+ // Assignment writes straight to the DB, so check ownership here as save()/destroy()/publish() do.
3452
+ const { isItemOwned, OwnershipError } = await Promise.resolve().then(function () { return ownership; });
3453
+ if (!(await isItemOwned({ seedLocalId: seedLocalId ?? undefined, seedUid: context.seedUid ?? undefined }))) {
3454
+ sendBack({ type: 'saveFailed', error: new OwnershipError() });
3455
+ return false;
3456
+ }
3398
3457
  // Use dynamic import to break circular dependency
3399
- const schemaMod = await import('./index-BGt4_oPO.js');
3458
+ const schemaMod = await import('./index-Cvt5UBz4.js');
3400
3459
  const { ModelPropertyDataTypes } = schemaMod;
3401
- const { SchemaValidationService } = await import('./SchemaValidationService-BPxkfDLU.js');
3460
+ const { SchemaValidationService } = await import('./SchemaValidationService-DieV4KL-.js');
3402
3461
  let propertyName = propertyNameRaw;
3403
3462
  if (!propertyName) {
3404
3463
  throw new Error('propertyName is required');
@@ -3552,6 +3611,8 @@ const analyzeInput = fromCallback(({ sendBack, input: { context, event } }) => {
3552
3611
  if (isDone) {
3553
3612
  sendBack({ type: 'saveValueToDbSuccess' });
3554
3613
  }
3614
+ }, (error) => {
3615
+ sendBack({ type: 'saveFailed', error });
3555
3616
  });
3556
3617
  });
3557
3618
 
@@ -3688,7 +3749,7 @@ const createMetadata = async (metadataValues, propertyRecordSchema, options) =>
3688
3749
  propertyRecordSchema?.validation &&
3689
3750
  metadataValues.propertyValue != null &&
3690
3751
  metadataValues.propertyValue !== '') {
3691
- const { SchemaValidationService } = await import('./SchemaValidationService-BPxkfDLU.js');
3752
+ const { SchemaValidationService } = await import('./SchemaValidationService-DieV4KL-.js');
3692
3753
  const validationService = new SchemaValidationService();
3693
3754
  const validationResult = validationService.validatePropertyValue(metadataValues.propertyValue, normalizeDataType(propertyRecordSchema.dataType), propertyRecordSchema.validation, propertyRecordSchema.refValueType
3694
3755
  ? normalizeDataType(String(propertyRecordSchema.refValueType))
@@ -4270,7 +4331,7 @@ const saveRelation = fromCallback(({ sendBack, input: { context, event } }) => {
4270
4331
  }
4271
4332
  const _saveRelation = async () => {
4272
4333
  // Use dynamic import to break circular dependency
4273
- const schemaMod = await import('./index-BGt4_oPO.js');
4334
+ const schemaMod = await import('./index-Cvt5UBz4.js');
4274
4335
  const { ModelPropertyDataTypes } = schemaMod;
4275
4336
  if (!propertyNameRaw) {
4276
4337
  throw new Error('propertyName is required');
@@ -4361,6 +4422,86 @@ const getItemPropertyData = async (props) => {
4361
4422
  return queryRows[0];
4362
4423
  };
4363
4424
 
4425
+ /** Absolute path of the file {@link writeItemStorageFile} writes for `target`. */
4426
+ const getItemStorageFilePath = (target) => BaseFileManager.getFilesPath(getItemStorageSubdir(target.localStorageDir), target.fileName || getItemStorageLocalFileName(target.seedId, target.filenameSuffix));
4427
+ /**
4428
+ * Write an ItemStorage property's content to its local file, where saveItemStorage, reads, publish
4429
+ * (resolveItemStorageChildFile) and download all look for it. Returns what the metadata row records:
4430
+ * `refResolvedValue` (the file name) and `localStorageDir` (with a leading slash).
4431
+ *
4432
+ * Callers that also update the file's metadata row hold {@link withItemStorageFileLock} around
4433
+ * both, so another writer of the same file can't land in between.
4434
+ */
4435
+ const writeItemStorageFile = async (target, content) => {
4436
+ const dir = getItemStorageSubdir(target.localStorageDir);
4437
+ const fileName = target.fileName || getItemStorageLocalFileName(target.seedId, target.filenameSuffix);
4438
+ await BaseFileManager.createDirIfNotExists(BaseFileManager.getFilesPath(dir));
4439
+ const filePath = BaseFileManager.getFilesPath(dir, fileName);
4440
+ await BaseFileManager.saveFile(filePath, content);
4441
+ return { fileName, filePath, localStorageDir: target.localStorageDir || `/${dir}` };
4442
+ };
4443
+ /**
4444
+ * Lock name for one ItemStorage file: `seed:item-storage:<absolute file path>`. The path starts
4445
+ * with the files root, which also names the database (`<filesDir>/db/seed.db`), so the name is
4446
+ * per database as well as per file.
4447
+ */
4448
+ const itemStorageFileLockName = (filePath) => `seed:item-storage:${filePath}`;
4449
+ /**
4450
+ * Runs `fn` holding the lock of one ItemStorage file, across tabs (Web Locks) and within this JS
4451
+ * realm (an in-process queue where Web Locks are missing, e.g. Node < 24.5; see `withTabLock`).
4452
+ *
4453
+ * Writers of a local draft's file (saveItemStorage, convertVerbatimItemStorageRow, createNewItem)
4454
+ * hold it across "read the row → write the file → update the row", so the file and the row end
4455
+ * with the same writer's content. See docs/MULTI_TAB.md.
4456
+ *
4457
+ * Lock ordering: this lock is always the innermost. It may be taken while holding a broader lock
4458
+ * (`seed:item-storage-migration:<db>`, `seed:publish:<seedLocalId>`), never the other way round,
4459
+ * and no other lock (nor a second file lock) is requested while it is held. Keep the section to
4460
+ * local DB and file I/O: no network. Not re-entrant.
4461
+ */
4462
+ function withItemStorageFileLock(filePath, fn) {
4463
+ return withTabLock(itemStorageFileLockName(filePath), fn);
4464
+ }
4465
+ /** Lock attempts before giving up when the row's target file keeps changing under us. */
4466
+ const ROW_LOCK_ATTEMPTS = 3;
4467
+ const readRow = async (localId) => {
4468
+ const rows = await BaseDb.getAppDb()
4469
+ .select()
4470
+ .from(metadata)
4471
+ .where(eq(metadata.localId, localId))
4472
+ .limit(1);
4473
+ return rows[0];
4474
+ };
4475
+ /**
4476
+ * Runs `fn` with a fresh read of metadata row `localId`, holding the lock of the file that row's
4477
+ * content goes to. `fileOf` names that file (absolute path) for a row, or returns undefined when
4478
+ * there is nothing to write (then `fn` isn't called and the result is undefined).
4479
+ *
4480
+ * The file depends on the row, so the row is read once to pick the lock and again once it is held;
4481
+ * if the row now points at another file (another writer changed it meanwhile), the lock is
4482
+ * released and taken again for that file.
4483
+ */
4484
+ async function withLockedItemStorageRow(localId, fileOf, fn) {
4485
+ for (let attempt = 0; attempt < ROW_LOCK_ATTEMPTS; attempt++) {
4486
+ const row = await readRow(localId);
4487
+ const filePath = row && fileOf(row);
4488
+ if (!filePath)
4489
+ return undefined;
4490
+ const outcome = await withItemStorageFileLock(filePath, async () => {
4491
+ const fresh = await readRow(localId);
4492
+ const freshPath = fresh && fileOf(fresh);
4493
+ if (!freshPath)
4494
+ return { done: true, value: undefined };
4495
+ if (freshPath !== filePath)
4496
+ return { done: false };
4497
+ return { done: true, value: await fn(fresh, filePath) };
4498
+ });
4499
+ if (outcome.done)
4500
+ return outcome.value;
4501
+ }
4502
+ throw new Error(`ItemStorage file of metadata row ${localId} kept changing; not written`);
4503
+ }
4504
+
4364
4505
  /** A local edit: no attestation uid of its own and not derived from one. */
4365
4506
  const isLocalDraft = (row) => !row.uid && row.derivedFromUid == null;
4366
4507
  const saveItemStorage = fromCallback(({ sendBack, input: { context, event } }) => {
@@ -4414,22 +4555,25 @@ const saveItemStorage = fromCallback(({ sendBack, input: { context, event } }) =
4414
4555
  const latest = [...queryRows].sort(compareMetadataRowsLatestFirst)[0];
4415
4556
  propertyData = latest && isLocalDraft(latest) ? latest : undefined;
4416
4557
  if (!propertyData && newValue) {
4417
- const filename = `${draftSeedUid || draftSeedLocalId}${propertyRecordSchema.filenameSuffix}`;
4418
- const dir = propertyRecordSchema.localStorageDir?.replace(/^\//, '') || 'files';
4419
- await BaseFileManager.createDirIfNotExists(BaseFileManager.getFilesPath(dir));
4420
- const writeToPath = BaseFileManager.getFilesPath(dir, filename);
4421
- await BaseFileManager.saveFile(writeToPath, newValue);
4422
- propertyData = await createMetadata({
4423
- propertyName,
4424
- propertyValue: filename,
4425
- modelType: (modelName ?? knownRow?.modelType ?? '').toLowerCase() || undefined,
4426
- seedLocalId: draftSeedLocalId,
4427
- seedUid: draftSeedUid,
4428
- versionLocalId,
4429
- versionUid,
4558
+ const target = {
4559
+ seedId: draftSeedUid || draftSeedLocalId,
4430
4560
  localStorageDir: propertyRecordSchema.localStorageDir,
4431
- refValueType: 'file',
4432
- }, propertyRecordSchema);
4561
+ filenameSuffix: propertyRecordSchema.filenameSuffix,
4562
+ };
4563
+ propertyData = await withItemStorageFileLock(getItemStorageFilePath(target), async () => {
4564
+ const { fileName: filename } = await writeItemStorageFile(target, newValue);
4565
+ return createMetadata({
4566
+ propertyName,
4567
+ propertyValue: filename,
4568
+ modelType: (modelName ?? knownRow?.modelType ?? '').toLowerCase() || undefined,
4569
+ seedLocalId: draftSeedLocalId,
4570
+ seedUid: draftSeedUid,
4571
+ versionLocalId,
4572
+ versionUid,
4573
+ localStorageDir: propertyRecordSchema.localStorageDir,
4574
+ refValueType: 'file',
4575
+ }, propertyRecordSchema);
4576
+ });
4433
4577
  }
4434
4578
  }
4435
4579
  else if (propertyData && !isLocalDraft(propertyData)) {
@@ -4438,31 +4582,64 @@ const saveItemStorage = fromCallback(({ sendBack, input: { context, event } }) =
4438
4582
  if (!propertyData) {
4439
4583
  throw new Error(`No metadata row to save ${propertyName} to`);
4440
4584
  }
4441
- const localStorageDir = propertyRecordSchema.localStorageDir || propertyData.localStorageDir;
4442
- const fileName = propertyData.refResolvedValue ||
4443
- `${propertyData.seedUid || propertyData.seedLocalId}${propertyRecordSchema.filenameSuffix}`;
4444
- if (!localStorageDir || !fileName) {
4445
- throw new Error(`Missing localStorageDir: ${localStorageDir} or fileName: ${fileName}`);
4446
- }
4447
- const dir = localStorageDir.replace(/^\//, '');
4448
- await BaseFileManager.createDirIfNotExists(BaseFileManager.getFilesPath(dir));
4449
- const filePath = BaseFileManager.getFilesPath(dir, fileName);
4450
- try {
4451
- await BaseFileManager.saveFile(filePath, newValue);
4452
- }
4453
- catch (error) {
4454
- const fs = await BaseFileManager.getFs();
4455
- fs.writeFileSync(filePath, newValue);
4456
- }
4457
- await appDb
4458
- .update(metadata)
4459
- .set({
4460
- refResolvedValue: fileName,
4461
- })
4462
- .where(eq(metadata.localId, propertyData.localId));
4585
+ // No storage.path: the `files` directory, as resolveItemStorageChildFile and download assume.
4586
+ const localStorageDirOf = (row) => propertyRecordSchema.localStorageDir || row.localStorageDir || '/files';
4587
+ const fileNameOf = (row) => {
4588
+ if (row.refResolvedValue)
4589
+ return row.refResolvedValue;
4590
+ const seedId = row.seedUid || row.seedLocalId;
4591
+ return seedId ? getItemStorageLocalFileName(seedId, propertyRecordSchema.filenameSuffix) : undefined;
4592
+ };
4593
+ if (!fileNameOf(propertyData)) {
4594
+ throw new Error(`Missing a seed id to name the ${propertyName} file after`);
4595
+ }
4596
+ // Read the row, write the file and update the row under the file's lock, so a conversion of a
4597
+ // legacy row (migration, publish) or another save of this file, in this tab or another, can't
4598
+ // land in between and leave the file with older content than the row says.
4599
+ const saved = await withLockedItemStorageRow(propertyData.localId, (row) => {
4600
+ const fileName = fileNameOf(row);
4601
+ return fileName && BaseFileManager.getFilesPath(getItemStorageSubdir(localStorageDirOf(row)), fileName);
4602
+ }, async (row, filePath) => {
4603
+ const localStorageDir = localStorageDirOf(row);
4604
+ const fileName = fileNameOf(row);
4605
+ try {
4606
+ await writeItemStorageFile({ seedId: row.seedUid || row.seedLocalId || '', localStorageDir, fileName }, newValue);
4607
+ }
4608
+ catch (error) {
4609
+ const fs = await BaseFileManager.getFs();
4610
+ fs.writeFileSync(filePath, newValue);
4611
+ }
4612
+ // A legacy row (made before Item.create saved ItemStorage values) holds the old content itself
4613
+ // in propertyValue. The file is the content now: drop it, or a fresh load shows the old text
4614
+ // until the file is read. A row whose propertyValue is the file name keeps it.
4615
+ const clearsVerbatimValue = !row.refResolvedValue &&
4616
+ row.propertyValue != null &&
4617
+ row.propertyValue !== '' &&
4618
+ row.propertyValue !== fileName;
4619
+ // The row says where the file is (read back by hydration, the browser's metadata live query
4620
+ // and publish); without localStorageDir the live query would clear it from the context.
4621
+ await appDb
4622
+ .update(metadata)
4623
+ .set({
4624
+ refResolvedValue: fileName,
4625
+ localStorageDir,
4626
+ // Same shape as a row the migration or publish converted (convertVerbatimItemStorageRow).
4627
+ ...(clearsVerbatimValue && { propertyValue: null, refValueType: 'file' }),
4628
+ })
4629
+ .where(eq(metadata.localId, row.localId));
4630
+ return { fileName, localStorageDir };
4631
+ });
4632
+ // The row went away (or lost its seed ids) before the lock was granted.
4633
+ if (!saved)
4634
+ throw new Error(`No metadata row to save ${propertyName} to`);
4635
+ const { fileName, localStorageDir } = saved;
4463
4636
  sendBack({
4464
4637
  type: 'updateContext',
4465
4638
  renderValue: newValue,
4639
+ // Where the file is, right away: localStoragePath (and so publish uploads) must not wait for
4640
+ // the browser's metadata live query, which Node does not have at all.
4641
+ refResolvedValue: fileName,
4642
+ localStorageDir,
4466
4643
  // Point the property at the draft row when the edit moved off a published row.
4467
4644
  ...(propertyData.localId !== localId && { localId: propertyData.localId }),
4468
4645
  });
@@ -4532,9 +4709,23 @@ const propertyMachine = setup({
4532
4709
  isSaving: true,
4533
4710
  _saveError: undefined,
4534
4711
  _saveValidationErrors: undefined,
4712
+ _valueBeforeSave: ({ event }) => event.before,
4535
4713
  }),
4536
4714
  target: '.saving',
4537
4715
  },
4716
+ /** analyzeInput refused (item not owned) or failed before writing: restore the shown value. */
4717
+ saveFailed: {
4718
+ target: '.idle',
4719
+ actions: assign(({ context, event }) => {
4720
+ const error = event.error;
4721
+ return {
4722
+ isSaving: false,
4723
+ _saveError: error instanceof Error ? { message: error.message, name: error.name } : { message: String(error) },
4724
+ ...(context._valueBeforeSave ?? {}),
4725
+ _valueBeforeSave: undefined,
4726
+ };
4727
+ }),
4728
+ },
4538
4729
  updateContext: {
4539
4730
  actions: assign(({ context, event }) => {
4540
4731
  const newContext = Object.assign({}, context);
@@ -4834,12 +5025,12 @@ const getPropertyData = async ({ propertyName, seedLocalId, seedUid, modelName,
4834
5025
  let names = [...getMetadataPropertyNamesForQuery(propertyName)];
4835
5026
  if (modelName) {
4836
5027
  try {
4837
- const _mod_14 = await import('./index-Xl1_4Lmb.js');
4838
- const _ns_14 = _mod_14.f;
4839
- const { Model } = _ns_14;
4840
- const _mod_15 = await import('./db-CQt-gcAl.js');
4841
- const _ns_15 = _mod_15.Y;
4842
- const { resolveItemModelFileId } = _ns_15;
5028
+ const _mod_13 = await import('./index-8O3Uow-Y.js');
5029
+ const _ns_13 = _mod_13.f;
5030
+ const { Model } = _ns_13;
5031
+ const _mod_14 = await import('./BasePathResolver-Cm4apKRb.js');
5032
+ const _ns_14 = _mod_14.b1;
5033
+ const { resolveItemModelFileId } = _ns_14;
4843
5034
  // Model names are only unique per schema: use the seed's own model when it is recorded.
4844
5035
  const modelFileId = await resolveItemModelFileId({ seedLocalId, seedUid });
4845
5036
  const model = await Model.resolveAsync(modelName, { modelFileId });
@@ -4999,6 +5190,8 @@ function forceRemoveFromCaches(instance, config) {
4999
5190
  /**
5000
5191
  * Run the service event sequence and stop the service:
5001
5192
  * destroyStarted -> doDestroy -> (destroyError on failure) -> stop.
5193
+ * A doDestroy failure is recorded on the service (destroyError) and rethrown, so destroy()
5194
+ * rejects instead of resolving with the rows still in the DB.
5002
5195
  * Event names must match what the entity machines expect.
5003
5196
  */
5004
5197
  async function runDestroyLifecycle(instance, config) {
@@ -5009,6 +5202,7 @@ async function runDestroyLifecycle(instance, config) {
5009
5202
  }
5010
5203
  catch (error) {
5011
5204
  service.send({ type: 'destroyError', error });
5205
+ throw error;
5012
5206
  }
5013
5207
  finally {
5014
5208
  try {
@@ -5028,9 +5222,9 @@ const HTML_PROP_SEED_UID_RE = /^0x[a-fA-F0-9]{64}$/;
5028
5222
  */
5029
5223
  const resolvePropertyRecordSchemaFromSchemaData = async (modelName, propertyName, modelType, schemaName) => {
5030
5224
  try {
5031
- const _mod_16 = await import('./ClientManager-DDA9956Y.js');
5032
- const _ns_16 = _mod_16.G;
5033
- const { loadAllSchemasFromDb } = _ns_16;
5225
+ const _mod_15 = await import('./ClientManager-i3nJASkg.js');
5226
+ const _ns_15 = _mod_15.K;
5227
+ const { loadAllSchemasFromDb } = _ns_15;
5034
5228
  const allSchemas = await loadAllSchemasFromDb();
5035
5229
  const modelNameAlt = modelType ? upperFirst(camelCase(modelType)) : '';
5036
5230
  for (const { schema } of allSchemas) {
@@ -5082,13 +5276,13 @@ hints = {}) => {
5082
5276
  return undefined;
5083
5277
  }
5084
5278
  try {
5085
- const _mod_17 = await import('./index-Xl1_4Lmb.js');
5086
- const _ns_17 = _mod_17.f;
5087
- const { Model } = _ns_17;
5279
+ const _mod_16 = await import('./index-8O3Uow-Y.js');
5280
+ const _ns_16 = _mod_16.f;
5281
+ const { Model } = _ns_16;
5088
5282
  const { modelPropertiesToObject } = await import('./model-DGMe-TTm.js');
5089
- const _mod_18 = await import('./db-CQt-gcAl.js');
5090
- const _ns_18 = _mod_18.Y;
5091
- const { resolveItemModelFileId } = _ns_18;
5283
+ const _mod_17 = await import('./BasePathResolver-Cm4apKRb.js');
5284
+ const _ns_17 = _mod_17.b1;
5285
+ const { resolveItemModelFileId } = _ns_17;
5092
5286
  const modelFileId = await resolveItemModelFileId(hints);
5093
5287
  let model = modelFileId
5094
5288
  ? await Model.resolveAsync(modelName || modelTypeToModelName(modelType ?? ''), { modelFileId })
@@ -5246,7 +5440,7 @@ class ItemProperty {
5246
5440
  return;
5247
5441
  }
5248
5442
  // Use dynamic import to break circular dependency
5249
- const schemaMod = await import('./index-BGt4_oPO.js');
5443
+ const schemaMod = await import('./index-Cvt5UBz4.js');
5250
5444
  const { ModelPropertyDataTypes } = schemaMod;
5251
5445
  const { context } = snapshot;
5252
5446
  const { propertyRecordSchema } = context;
@@ -5417,9 +5611,9 @@ class ItemProperty {
5417
5611
  const normalizedRefValueType = normalizeDataType(propertyRecordSchema?.refValueType);
5418
5612
  const propertyNames = getMetadataPropertyNamesForQuery(propertyName, normalizedDataType, normalizedRefValueType);
5419
5613
  const propertyNameVariant = propertyNames.length > 1 ? propertyNames[1] : undefined;
5420
- const _mod_19 = await import('./index-CSOQFAOn.js');
5421
- const _ns_19 = _mod_19.s;
5422
- const seedSchemaMod = _ns_19;
5614
+ const _mod_18 = await import('./index-AVFTVp1m.js');
5615
+ const _ns_18 = _mod_18.s;
5616
+ const seedSchemaMod = _ns_18;
5423
5617
  const { metadata } = seedSchemaMod;
5424
5618
  const drizzleMod = await import('drizzle-orm');
5425
5619
  const { eq, and, or } = drizzleMod;
@@ -5633,9 +5827,9 @@ class ItemProperty {
5633
5827
  const ctx = this._service.getSnapshot().context;
5634
5828
  let modelFileId;
5635
5829
  try {
5636
- const _mod_20 = await import('./db-CQt-gcAl.js');
5637
- const _ns_20 = _mod_20.Y;
5638
- const { resolveItemModelFileId } = _ns_20;
5830
+ const _mod_19 = await import('./BasePathResolver-Cm4apKRb.js');
5831
+ const _ns_19 = _mod_19.b1;
5832
+ const { resolveItemModelFileId } = _ns_19;
5639
5833
  modelFileId = await resolveItemModelFileId({
5640
5834
  modelFileId: ctx.modelFileId,
5641
5835
  seedLocalId: ctx.seedLocalId,
@@ -5748,7 +5942,7 @@ class ItemProperty {
5748
5942
  }
5749
5943
  static create(props, options) {
5750
5944
  const waitForReady = options?.waitForReady !== false;
5751
- const readyTimeout = options?.readyTimeout ?? 5000;
5945
+ const readyTimeout = options?.readyTimeout ?? DEFAULT_READY_TIMEOUT_MS;
5752
5946
  const { propertyName, seedLocalId, seedUid, versionLocalId, versionUid } = props;
5753
5947
  if (!propertyName || (!seedLocalId && !seedUid)) {
5754
5948
  if (!waitForReady)
@@ -5934,7 +6128,7 @@ class ItemProperty {
5934
6128
  }
5935
6129
  return undefined;
5936
6130
  }
5937
- static async find({ propertyName, seedLocalId, seedUid, modelName: modelNameOption, waitForReady = true, readyTimeout = 5000, }) {
6131
+ static async find({ propertyName, seedLocalId, seedUid, modelName: modelNameOption, waitForReady = true, readyTimeout = DEFAULT_READY_TIMEOUT_MS, }) {
5938
6132
  if ((!seedLocalId && !seedUid) || !propertyName) {
5939
6133
  return undefined;
5940
6134
  }
@@ -5988,7 +6182,7 @@ class ItemProperty {
5988
6182
  * Loads property data via getItemProperties, creates instances via create, optionally waits for idle.
5989
6183
  */
5990
6184
  static async all(params, options) {
5991
- const { waitForReady = false, readyTimeout = 5000 } = options ?? {};
6185
+ const { waitForReady = false, readyTimeout = DEFAULT_READY_TIMEOUT_MS } = options ?? {};
5992
6186
  const { seedLocalId, seedUid } = params;
5993
6187
  if (!seedLocalId && !seedUid) {
5994
6188
  return [];
@@ -5996,9 +6190,9 @@ class ItemProperty {
5996
6190
  const propertiesData = await getItemProperties({ seedLocalId, seedUid });
5997
6191
  const instances = [];
5998
6192
  const seenNormalized = new Set();
5999
- const _mod_21 = await import('./db-CQt-gcAl.js');
6000
- const _ns_21 = _mod_21.Y;
6001
- const { resolveItemModelFileId } = _ns_21;
6193
+ const _mod_20 = await import('./BasePathResolver-Cm4apKRb.js');
6194
+ const _ns_20 = _mod_20.b1;
6195
+ const { resolveItemModelFileId } = _ns_20;
6002
6196
  const itemModelFileId = await resolveItemModelFileId({ seedLocalId, seedUid });
6003
6197
  for (const data of propertiesData) {
6004
6198
  const d = data;
@@ -6014,9 +6208,9 @@ class ItemProperty {
6014
6208
  }
6015
6209
  else if (baseName) {
6016
6210
  try {
6017
- const _mod_22 = await import('./index-Xl1_4Lmb.js');
6018
- const _ns_22 = _mod_22.f;
6019
- const { Model } = _ns_22;
6211
+ const _mod_21 = await import('./index-8O3Uow-Y.js');
6212
+ const _ns_21 = _mod_21.f;
6213
+ const { Model } = _ns_21;
6020
6214
  const { modelPropertiesToObject } = await import('./model-DGMe-TTm.js');
6021
6215
  const model = await Model.resolveAsync(modelName, { modelFileId });
6022
6216
  if (model?.properties) {
@@ -6031,9 +6225,9 @@ class ItemProperty {
6031
6225
  }
6032
6226
  if (modelName && propertyName) {
6033
6227
  try {
6034
- const _mod_23 = await import('./index-Xl1_4Lmb.js');
6035
- const _ns_23 = _mod_23.f;
6036
- const { Model } = _ns_23;
6228
+ const _mod_22 = await import('./index-8O3Uow-Y.js');
6229
+ const _ns_22 = _mod_22.f;
6230
+ const { Model } = _ns_22;
6037
6231
  const { modelPropertiesToObject } = await import('./model-DGMe-TTm.js');
6038
6232
  const model = await Model.resolveAsync(modelName, { modelFileId });
6039
6233
  if (model?.properties?.length) {
@@ -6189,6 +6383,8 @@ class ItemProperty {
6189
6383
  if (currentValue === value) {
6190
6384
  return;
6191
6385
  }
6386
+ // Restored if the save is refused (item not owned) or fails.
6387
+ const before = { propertyValue: context.propertyValue, renderValue: context.renderValue };
6192
6388
  // Update context immediately so UI shows the value before save completes
6193
6389
  this._service.send({
6194
6390
  type: 'updateContext',
@@ -6207,7 +6403,7 @@ class ItemProperty {
6207
6403
  if (!schema)
6208
6404
  return false;
6209
6405
  this._service.send({ type: 'updateContext', propertyRecordSchema: schema });
6210
- this._service.send({ type: 'save', newValue: value });
6406
+ this._service.send({ type: 'save', newValue: value, before });
6211
6407
  return true;
6212
6408
  }, () => false);
6213
6409
  this._pendingSchemaSave = pending;
@@ -6220,6 +6416,7 @@ class ItemProperty {
6220
6416
  this._service.send({
6221
6417
  type: 'save',
6222
6418
  newValue: value,
6419
+ before,
6223
6420
  });
6224
6421
  }
6225
6422
  }
@@ -6329,10 +6526,17 @@ class ItemProperty {
6329
6526
  }
6330
6527
  }
6331
6528
  /**
6332
- * Destroy the item property: remove from caches, delete metadata from DB, remove from parent Item, stop service.
6529
+ * Destroy the item property: remove from caches, delete its metadata rows (every version of
6530
+ * this item's value) from the DB, remove it from the parent Item, and stop the service.
6531
+ * Throws OwnershipError if none of the client's addresses own the item.
6333
6532
  */
6334
6533
  async destroy() {
6335
6534
  const context = this._getSnapshotContext();
6535
+ const { assertItemOwned } = await Promise.resolve().then(function () { return ownership; });
6536
+ await assertItemOwned({
6537
+ seedLocalId: context.seedLocalId ?? undefined,
6538
+ seedUid: context.seedUid ?? undefined,
6539
+ });
6336
6540
  const cacheKey = ItemProperty.cacheKey(context.seedUid || context.seedLocalId || '', context.propertyName || '');
6337
6541
  const cacheKeys = cacheKey && cacheKey !== 'Item__' ? [cacheKey] : [];
6338
6542
  clearDestroySubscriptions(this, {
@@ -6353,17 +6557,16 @@ class ItemProperty {
6353
6557
  if (!propertyName || (!seedLocalId && !seedUid))
6354
6558
  return;
6355
6559
  if (db) {
6356
- const _mod_24 = await import('./index-CSOQFAOn.js');
6357
- const _ns_24 = _mod_24.s;
6358
- const seedSchemaMod = _ns_24;
6560
+ const _mod_23 = await import('./index-AVFTVp1m.js');
6561
+ const _ns_23 = _mod_23.s;
6562
+ const seedSchemaMod = _ns_23;
6359
6563
  const { metadata } = seedSchemaMod;
6360
6564
  const drizzleMod = await import('drizzle-orm');
6361
- const { and, eq, or } = drizzleMod;
6565
+ const { and, eq } = drizzleMod;
6362
6566
  const conditions = [eq(metadata.propertyName, propertyName)];
6363
- if (seedLocalId && seedUid) {
6364
- conditions.push(or(eq(metadata.seedLocalId, seedLocalId), eq(metadata.seedUid, seedUid)));
6365
- }
6366
- else if (seedLocalId) {
6567
+ // Match this item's local rows only. Matching seedUid too would also delete rows of
6568
+ // other local copies of the same seed (e.g. duplicate EAS syncs).
6569
+ if (seedLocalId) {
6367
6570
  conditions.push(eq(metadata.seedLocalId, seedLocalId));
6368
6571
  }
6369
6572
  else if (seedUid) {
@@ -6399,9 +6602,9 @@ const createNewItem = async ({ modelName, modelFileId, ...propertyData }) => {
6399
6602
  }
6400
6603
  const seedType = toSnakeCase(modelName);
6401
6604
  // Dynamic import to break circular dependency
6402
- const _mod_25 = await import('./index-Xl1_4Lmb.js');
6403
- const _ns_25 = _mod_25.f;
6404
- const modelMod = _ns_25;
6605
+ const _mod_24 = await import('./index-8O3Uow-Y.js');
6606
+ const _ns_24 = _mod_24.f;
6607
+ const modelMod = _ns_24;
6405
6608
  const { Model } = modelMod;
6406
6609
  const model = await Model.resolveAsync(modelName, { modelFileId });
6407
6610
  const propertySchemas = model?.properties ? modelPropertiesToObject(model.properties) : undefined;
@@ -6420,13 +6623,38 @@ const createNewItem = async ({ modelName, modelFileId, ...propertyData }) => {
6420
6623
  for (const propertyName of allPropertyNames) {
6421
6624
  const propertyValue = propertyData[propertyName];
6422
6625
  const propertyRecordSchema = propertySchemas?.[propertyName];
6423
- await createMetadata({
6626
+ // ItemStorage content lives in the property's file (`<seedLocalId><extension>`), as a save puts
6627
+ // it; the row records where. Stored verbatim in the row, publish would never upload it.
6628
+ const isItemStorageValue = propertyRecordSchema?.storageType === 'ItemStorage' &&
6629
+ propertyValue != null &&
6630
+ propertyValue !== '';
6631
+ const insertRow = (storageFields) => createMetadata({
6424
6632
  seedLocalId: newSeedId,
6425
6633
  versionLocalId: newVersionId,
6426
6634
  propertyName,
6427
- propertyValue,
6635
+ propertyValue: storageFields ? undefined : propertyValue,
6636
+ ...storageFields,
6428
6637
  modelName,
6429
6638
  }, propertyRecordSchema, { skipValidation: true, modelFileId });
6639
+ if (!isItemStorageValue) {
6640
+ await insertRow();
6641
+ continue;
6642
+ }
6643
+ // File and row under the file's lock, like every writer of a local draft's file (see
6644
+ // withItemStorageFileLock). The seed is new, so nothing else should be writing it yet.
6645
+ const target = {
6646
+ seedId: newSeedId,
6647
+ localStorageDir: propertyRecordSchema.localStorageDir,
6648
+ filenameSuffix: propertyRecordSchema.filenameSuffix,
6649
+ };
6650
+ await withItemStorageFileLock(getItemStorageFilePath(target), async () => {
6651
+ const written = await writeItemStorageFile(target, propertyValue);
6652
+ await insertRow({
6653
+ refResolvedValue: written.fileName,
6654
+ localStorageDir: written.localStorageDir,
6655
+ refValueType: 'file',
6656
+ });
6657
+ });
6430
6658
  }
6431
6659
  return {
6432
6660
  modelName,
@@ -6444,7 +6672,7 @@ const createNewItem = async ({ modelName, modelFileId, ...propertyData }) => {
6444
6672
  * @returns Entity instance if found, undefined otherwise
6445
6673
  */
6446
6674
  async function findEntity(config, params, options = {}) {
6447
- const { waitForReady = true, readyTimeout = 5000 } = options;
6675
+ const { waitForReady = true, readyTimeout = DEFAULT_READY_TIMEOUT_MS } = options;
6448
6676
  let instance;
6449
6677
  // Try ID lookup first (most specific)
6450
6678
  if (params.id) {
@@ -6557,9 +6785,9 @@ const getModel = () => {
6557
6785
  // the fragile `import(...).then(n => n.X)` chunk-namespace pattern.
6558
6786
  if (!modelImportPromise) {
6559
6787
  modelImportPromise = (async () => {
6560
- const _mod_26 = await import('./index-Xl1_4Lmb.js');
6561
- const _ns_26 = _mod_26.f;
6562
- const mod = _ns_26;
6788
+ const _mod_25 = await import('./index-8O3Uow-Y.js');
6789
+ const _ns_25 = _mod_25.f;
6790
+ const mod = _ns_25;
6563
6791
  ModelClass = mod.Model;
6564
6792
  return mod;
6565
6793
  })();
@@ -6590,10 +6818,16 @@ const getModel = () => {
6590
6818
  };
6591
6819
  // Define tracked properties for the Proxy
6592
6820
  // These properties will be read from/written to the actor context
6593
- /** Raw File/Image/Html content (not already a storage seed reference) needs ItemProperty.save(). */
6594
- function needsStorageSavePipeline(dataType, value) {
6821
+ /**
6822
+ * Initial values that need ItemProperty.save() rather than a verbatim metadata row: raw File/Image/Html
6823
+ * content (not already a storage seed reference) becomes a storage seed, and an ItemStorage property's
6824
+ * content goes into its file (`<seedLocalId><extension>`), where publish and reads look for it.
6825
+ */
6826
+ function needsStorageSavePipeline(dataType, value, storageType) {
6595
6827
  if (value == null || value === '')
6596
6828
  return false;
6829
+ if (storageType === 'ItemStorage')
6830
+ return true;
6597
6831
  const isStorageType = isDataType(dataType, ModelPropertyDataTypes.File) ||
6598
6832
  isDataType(dataType, ModelPropertyDataTypes.Image) ||
6599
6833
  isDataType(dataType, ModelPropertyDataTypes.Html);
@@ -6669,29 +6903,41 @@ class Item {
6669
6903
  latestVersionUid: head?.uid ?? undefined,
6670
6904
  });
6671
6905
  };
6672
- this.publish = async () => {
6906
+ /**
6907
+ * Upload this item's files to Arweave and write its attestations to EAS.
6908
+ *
6909
+ * Requires @seedprotocol/publish. Its `initPublish()` (or `<PublishProvider config>`)
6910
+ * registers the PublishExecutor this delegates to; without it, publish() throws
6911
+ * PUBLISH_NOT_CONFIGURED_MESSAGE. `options` are passed to that package unchanged (its
6912
+ * CreatePublishOptions: signers, Arweave tags, `publishMode`, `onPublished`, ...).
6913
+ *
6914
+ * Resolves when the publish has finished, and rejects with the publish package's error
6915
+ * if it failed. Throws OwnershipError if none of the client's addresses own the item.
6916
+ */
6917
+ this.publish = async (options) => {
6673
6918
  const { assertItemOwned } = await Promise.resolve().then(function () { return ownership; });
6919
+ const { getPublishExecutor, PUBLISH_NOT_CONFIGURED_MESSAGE } = await Promise.resolve().then(function () { return publishConfig; });
6674
6920
  await assertItemOwned(this);
6675
- this._service.send({ type: 'startPublish' });
6921
+ if (!getPublishExecutor()) {
6922
+ throw new Error(PUBLISH_NOT_CONFIGURED_MESSAGE);
6923
+ }
6924
+ const current = this._service.getSnapshot().value;
6925
+ if (current !== 'idle') {
6926
+ throw new Error(current === 'publishing'
6927
+ ? 'Item is already being published.'
6928
+ : `Item is not ready to publish (state: ${current}).`);
6929
+ }
6676
6930
  return new Promise((resolve, reject) => {
6931
+ // Subscribe before sending: subscribe() does not replay the current snapshot,
6932
+ // so a subscription made after startPublish could miss the 'publishing' state.
6677
6933
  let wasPublishing = false;
6678
- const timeoutMs = 300000; // 5 minutes, match previous handler timeout
6679
- const timeoutId = setTimeout(() => {
6680
- unsub.unsubscribe();
6681
- if (!wasPublishing) {
6682
- reject(new Error('Publish did not start (timeout)'));
6683
- }
6684
- else {
6685
- reject(new Error('Publish timed out'));
6686
- }
6687
- }, timeoutMs);
6688
6934
  const unsub = this._service.subscribe((snapshot) => {
6689
6935
  const value = snapshot.value;
6690
6936
  if (value === 'publishing') {
6691
6937
  wasPublishing = true;
6938
+ return;
6692
6939
  }
6693
6940
  if (value === 'idle' && wasPublishing) {
6694
- clearTimeout(timeoutId);
6695
6941
  unsub.unsubscribe();
6696
6942
  const ctx = snapshot.context;
6697
6943
  if (ctx._publishError) {
@@ -6702,18 +6948,19 @@ class Item {
6702
6948
  }
6703
6949
  }
6704
6950
  });
6951
+ this._service.send({ type: 'startPublish', item: this, options });
6705
6952
  });
6706
6953
  };
6707
6954
  this.getPublishUploads = async (options) => {
6708
6955
  // Use dynamic import to break circular dependency
6709
- const getPublishUploadsMod = await import('./getPublishUploads-DHP01KgU.js');
6956
+ const getPublishUploadsMod = await import('./getPublishUploads-SFHCbf_y.js');
6710
6957
  const { getPublishUploads } = getPublishUploadsMod;
6711
6958
  return await getPublishUploads(this, [], undefined, options);
6712
6959
  };
6713
6960
  this.getPublishPayload = async (uploadedTransactions, options) => {
6714
- const _mod_27 = await import('./getPublishPayload-Xl3sRkR-.js');
6715
- const _ns_27 = _mod_27.g;
6716
- const getPublishPayloadMod = _ns_27;
6961
+ const _mod_26 = await import('./getPublishPayload-CTCvRUoU.js');
6962
+ const _ns_26 = _mod_26.g;
6963
+ const getPublishPayloadMod = _ns_26;
6717
6964
  const { getPublishPayload } = getPublishPayloadMod;
6718
6965
  return await getPublishPayload(this, uploadedTransactions, options);
6719
6966
  };
@@ -7070,7 +7317,7 @@ class Item {
7070
7317
  }
7071
7318
  static async create(props, options) {
7072
7319
  const waitForReady = options?.waitForReady !== false;
7073
- const readyTimeout = options?.readyTimeout ?? 5000;
7320
+ const readyTimeout = options?.readyTimeout ?? DEFAULT_READY_TIMEOUT_MS;
7074
7321
  if (!props.modelName && props.type) {
7075
7322
  props.modelName = startCase(props.type);
7076
7323
  }
@@ -7243,12 +7490,13 @@ class Item {
7243
7490
  // Get property names directly from database to make Item independent from Model
7244
7491
  let propertyNames = [];
7245
7492
  const dataTypeByPropertyName = new Map();
7493
+ const storageTypeByPropertyName = new Map();
7246
7494
  const db = BaseDb.getAppDb();
7247
7495
  if (db && props.modelName) {
7248
7496
  // Model names are only unique per schema: resolve the exact models row from the most specific scope.
7249
- const _mod_28 = await import('./db-CQt-gcAl.js');
7250
- const _ns_28 = _mod_28.Y;
7251
- const { resolveModelRecord } = _ns_28;
7497
+ const _mod_27 = await import('./BasePathResolver-Cm4apKRb.js');
7498
+ const _ns_27 = _mod_27.b1;
7499
+ const { resolveModelRecord } = _ns_27;
7252
7500
  const modelRecord = await resolveModelRecord(props.modelName, {
7253
7501
  modelFileId: props.modelFileId ?? modelInstance?.id,
7254
7502
  schemaName: schemaName ?? modelInstance?.schemaName,
@@ -7260,12 +7508,12 @@ class Item {
7260
7508
  // Scope the constructor's Model lookup to this model's schema (as getItemData does on reload),
7261
7509
  // so a same-named model cached from another schema can't supply the property set.
7262
7510
  if (modelRecord && !props.schemaName) {
7263
- const _mod_29 = await import('./BasePathResolver-BdxCSIzn.js');
7264
- const _ns_29 = _mod_29.R;
7265
- const { modelSchemas } = _ns_29;
7266
- const _mod_30 = await import('./BasePathResolver-BdxCSIzn.js');
7267
- const _ns_30 = _mod_30.Q;
7268
- const { schemas: schemasTable } = _ns_30;
7511
+ const _mod_28 = await import('./BasePathResolver-Cm4apKRb.js');
7512
+ const _ns_28 = _mod_28.b0;
7513
+ const { modelSchemas } = _ns_28;
7514
+ const _mod_29 = await import('./BasePathResolver-Cm4apKRb.js');
7515
+ const _ns_29 = _mod_29.a$;
7516
+ const { schemas: schemasTable } = _ns_29;
7269
7517
  const schemaRows = await db
7270
7518
  .select({ schemaName: schemasTable.name })
7271
7519
  .from(modelSchemas)
@@ -7278,13 +7526,19 @@ class Item {
7278
7526
  }
7279
7527
  if (modelRecords.length > 0 && modelRecords[0].id) {
7280
7528
  const propertyRecords = await db
7281
- .select({ name: properties.name, dataType: properties.dataType })
7529
+ .select({
7530
+ name: properties.name,
7531
+ dataType: properties.dataType,
7532
+ storageType: properties.storageType,
7533
+ })
7282
7534
  .from(properties)
7283
7535
  .where(eq(properties.modelId, modelRecords[0].id));
7284
7536
  propertyNames = propertyRecords.map((r) => r.name).filter((name) => Boolean(name));
7285
7537
  for (const r of propertyRecords) {
7286
7538
  if (r.name && r.dataType)
7287
7539
  dataTypeByPropertyName.set(r.name, r.dataType);
7540
+ if (r.name && r.storageType)
7541
+ storageTypeByPropertyName.set(r.name, r.storageType);
7288
7542
  }
7289
7543
  }
7290
7544
  }
@@ -7293,7 +7547,8 @@ class Item {
7293
7547
  modelFileId: props.modelFileId,
7294
7548
  };
7295
7549
  // File/Image/Html values that are raw content (html string, data URI, URL, File) must go through
7296
- // the property's save pipeline to become storage seeds; createNewItem would store them verbatim.
7550
+ // the property's save pipeline to become storage seeds, and ItemStorage values to be written to
7551
+ // their file with the property context pointing at it (as `prop.value = v; await prop.save()`).
7297
7552
  const pipelineValues = [];
7298
7553
  // Only include properties that are in the model schema
7299
7554
  // Exclude modelInstance, modelName, and schemaName as they're metadata, not item properties
@@ -7303,7 +7558,7 @@ class Item {
7303
7558
  continue;
7304
7559
  }
7305
7560
  if (propertyNames.length === 0 || propertyNames.includes(key)) {
7306
- if (needsStorageSavePipeline(dataTypeByPropertyName.get(key), value)) {
7561
+ if (needsStorageSavePipeline(dataTypeByPropertyName.get(key), value, storageTypeByPropertyName.get(key))) {
7307
7562
  pipelineValues.push([key, value]);
7308
7563
  continue;
7309
7564
  }
@@ -7435,7 +7690,7 @@ class Item {
7435
7690
  return proxiedInstance;
7436
7691
  }
7437
7692
  /**
7438
- * Run each File/Image/Html initial value through its ItemProperty save pipeline (sequentially, to
7693
+ * Run each File/Image/Html/ItemStorage initial value through its ItemProperty save pipeline (sequentially, to
7439
7694
  * avoid SQLite write contention). Rejects on the first failure; the item itself has been created.
7440
7695
  */
7441
7696
  static async savePipelineValues(item, pipelineValues, timeout) {
@@ -7559,7 +7814,7 @@ class Item {
7559
7814
  modelName,
7560
7815
  });
7561
7816
  }
7562
- static async find({ modelName, seedLocalId, seedUid, waitForReady = true, readyTimeout = 5000, }) {
7817
+ static async find({ modelName, seedLocalId, seedUid, waitForReady = true, readyTimeout = DEFAULT_READY_TIMEOUT_MS, }) {
7563
7818
  if (!seedLocalId && !seedUid) {
7564
7819
  return undefined;
7565
7820
  }
@@ -7585,7 +7840,7 @@ class Item {
7585
7840
  }
7586
7841
  }
7587
7842
  static async all(modelName, deleted, options) {
7588
- const { waitForReady = false, readyTimeout = 5000, includeEas = false, addressFilter, modelFileId, schemaName, } = options ?? {};
7843
+ const { waitForReady = false, readyTimeout = DEFAULT_READY_TIMEOUT_MS, includeEas = false, addressFilter, modelFileId, schemaName, } = options ?? {};
7589
7844
  const itemsData = await getItemsData({ modelName, modelFileId, schemaName, deleted, includeEas, addressFilter });
7590
7845
  const itemInstances = [];
7591
7846
  for (const itemData of itemsData) {
@@ -7609,9 +7864,9 @@ class Item {
7609
7864
  if (!appDb || Item.instanceCache.size === 0) {
7610
7865
  return;
7611
7866
  }
7612
- const _mod_31 = await import('./index-CSOQFAOn.js');
7613
- const _ns_31 = _mod_31.s;
7614
- const { metadata } = _ns_31;
7867
+ const _mod_30 = await import('./index-AVFTVp1m.js');
7868
+ const _ns_30 = _mod_30.s;
7869
+ const { metadata } = _ns_30;
7615
7870
  const { eq, and } = await import('drizzle-orm');
7616
7871
  const dedupedInstances = new Map();
7617
7872
  for (const entry of Item.instanceCache.values()) {
@@ -7770,8 +8025,27 @@ class Item {
7770
8025
  });
7771
8026
  state.definedPropertyNames.add(propertyName);
7772
8027
  }
7773
- static async publish(item) {
7774
- await item.publish();
8028
+ /** Same as `item.publish(options)`; requires @seedprotocol/publish. */
8029
+ /**
8030
+ * Set `publisher` on loaded Items for these seeds (after claimUnpublishedDrafts stamped
8031
+ * their rows). Items that aren't loaded read it from the DB when they load.
8032
+ */
8033
+ static setPublisherForCachedSeeds(seedLocalIds, publisher) {
8034
+ const normalized = normalizePublisher(publisher);
8035
+ if (!normalized)
8036
+ return;
8037
+ for (const seedLocalId of seedLocalIds) {
8038
+ const item = Item.getById(seedLocalId);
8039
+ if (!item)
8040
+ continue;
8041
+ const status = item.getService().getSnapshot().status;
8042
+ if (status === 'stopped' || status === 'done')
8043
+ continue;
8044
+ item.getService().send({ type: 'updateContext', publisher: normalized });
8045
+ }
8046
+ }
8047
+ static async publish(item, options) {
8048
+ await item.publish(options);
7775
8049
  }
7776
8050
  get serviceContext() {
7777
8051
  const snapshot = this._service.getSnapshot();
@@ -8068,9 +8342,9 @@ class Item {
8068
8342
  itemActor.send(event);
8069
8343
  };
8070
8344
  try {
8071
- const _mod_32 = await import('./index-CSOQFAOn.js');
8072
- const _ns_32 = _mod_32.s;
8073
- const seedSchemaMod = _ns_32;
8345
+ const _mod_31 = await import('./index-AVFTVp1m.js');
8346
+ const _ns_31 = _mod_31.s;
8347
+ const seedSchemaMod = _ns_31;
8074
8348
  const { seeds, versions, metadata } = seedSchemaMod;
8075
8349
  const drizzleMod = await import('drizzle-orm');
8076
8350
  const { eq, and } = drizzleMod;
@@ -8161,7 +8435,7 @@ class Item {
8161
8435
  // Watch the seed row by local id: its uid changes when an unpublished item is published
8162
8436
  // again (a new seed attestation), and a watch on the uid would stop seeing the row.
8163
8437
  const seeds$ = BaseDb.liveQuery((sql) => sql `
8164
- SELECT local_id as localId, uid, schema_uid as schemaUid, revoked_at as revokedAt
8438
+ SELECT local_id as localId, uid, schema_uid as schemaUid, revoked_at as revokedAt, publisher
8165
8439
  FROM seeds
8166
8440
  WHERE local_id = ${watchedSeedLocalId}
8167
8441
  `);
@@ -8211,6 +8485,8 @@ class Item {
8211
8485
  seedLocalId: seedRow.localId,
8212
8486
  schemaUid: seedRow.schemaUid || undefined,
8213
8487
  revokedAt: seedRow.revokedAt ?? undefined,
8488
+ // claimUnpublishedDrafts (here or in another tab) stamps drafts' publisher.
8489
+ ...(seedRow.publisher ? { publisher: seedRow.publisher } : {}),
8214
8490
  });
8215
8491
  },
8216
8492
  error: (error) => {
@@ -8421,5 +8697,5 @@ var Item$1 = /*#__PURE__*/Object.freeze({
8421
8697
  Item: Item
8422
8698
  });
8423
8699
 
8424
- export { getRevokeExecutor as A, getUploadExecutor as B, ClientManagerState as C, getVersionData$1 as D, isItemOwned as E, isLocalUnsealedDraft as F, isSeedRowOwned as G, ownedPublisherSql as H, Item as I, pickLatestMetadataRowPerProperty as J, propertyMachine as K, publisherInAddressListSql as L, METADATA_LATEST_FIRST_ORDER_SQL as M, publisherIsInOwnedSet as N, setAdditionalSyncAddresses as O, setGetPublisherForNewSeeds as P, setRevokeExecutor as Q, setUploadExecutor as R, getInvariantSafePropertyDescriptor as S, clearDestroySubscriptions as T, unloadEntity as U, ClientManagerEvents as V, resolvePublisherFromSeedRow as W, getPropertyData$1 as X, Item$1 as Y, getEasSchemaUidForModel as a, getLatestPublishedVersionRow as b, chunkValues as c, rowsPerInsert as d, getGetAdditionalSyncAddresses as e, ItemProperty as f, getItemData as g, ItemPropertySaveValidationError as h, isVersionRevoked as i, waitForEntityIdle as j, createReactiveProxy as k, listRelationEasPropertyName as l, findEntity as m, forceRemoveFromCaches as n, runDestroyLifecycle as o, parseListPropertyValueFromStorage as p, compareMetadataRowsLatestFirst as q, resolveStorageNameToSchemaName as r, selectInBatches as s, isPublishedMetadataRow as t, MachineIds as u, createNewItem as v, writeInBatches as w, getEasSchemaForItemProperty as x, getGetPublisherForNewSeeds as y, getMetadataLatest as z };
8425
- //# sourceMappingURL=Item-D4FigtYS.js.map
8700
+ export { getInvariantSafePropertyDescriptor as $, getGetPublisherForNewSeeds as A, getMetadataLatest as B, ClientManagerState as C, DEFAULT_READY_TIMEOUT_MS as D, getPublishExecutor as E, getRevokeExecutor as F, getUploadExecutor as G, getVersionData$1 as H, Item as I, isLocalUnsealedDraft as J, isSeedRowOwned as K, localUnsealedDraftSql as L, METADATA_LATEST_FIRST_ORDER_SQL as M, ownedPublisherSql as N, OwnershipError as O, PUBLISH_NOT_CONFIGURED_MESSAGE as P, ownedSeedsSql as Q, pickLatestMetadataRowPerProperty as R, placeholderUidSql as S, propertyMachine as T, publisherInAddressListSql as U, publisherIsInOwnedSet as V, setAdditionalSyncAddresses as W, setGetPublisherForNewSeeds as X, setPublishExecutor as Y, setRevokeExecutor as Z, setUploadExecutor as _, chunkValues as a, clearDestroySubscriptions as a0, unloadEntity as a1, ClientManagerEvents as a2, withLockedItemStorageRow as a3, getItemStorageFilePath as a4, writeItemStorageFile as a5, resolvePublisherFromSeedRow as a6, getPropertyData$1 as a7, Item$1 as a8, rowsPerInsert as b, compareMetadataRowsLatestFirst as c, getGetAdditionalSyncAddresses as d, ItemProperty as e, ItemPropertySaveValidationError as f, getItemData as g, assertItemOwned as h, isItemOwned as i, getEasSchemaUidForModel as j, getLatestPublishedVersionRow as k, listRelationEasPropertyName as l, isVersionRevoked as m, waitForEntityIdle as n, createReactiveProxy as o, parseListPropertyValueFromStorage as p, findEntity as q, resolveStorageNameToSchemaName as r, selectInBatches as s, forceRemoveFromCaches as t, runDestroyLifecycle as u, isPublishedMetadataRow as v, writeInBatches as w, MachineIds as x, createNewItem as y, getEasSchemaForItemProperty as z };
8701
+ //# sourceMappingURL=Item-DBFchXpC.js.map