@seedprotocol/sdk 0.7.8-next.1071.g2a141c1 → 0.7.8

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 (211) hide show
  1. package/dist/{ClientManager-Bv15o3Oz.js → ClientManager-B1r_8P5Z.js} +37 -40
  2. package/dist/ClientManager-B1r_8P5Z.js.map +1 -0
  3. package/dist/{Item-tX3kpbj4.js → Item-CjTEShfk.js} +384 -399
  4. package/dist/Item-CjTEShfk.js.map +1 -0
  5. package/dist/{ModelProperty-N-3gBfu5.js → ModelProperty-C3749Wjq.js} +36 -36
  6. package/dist/{ModelProperty-N-3gBfu5.js.map → ModelProperty-C3749Wjq.js.map} +1 -1
  7. package/dist/{Schema-CY3OxwKS.js → Schema-CX9CTtho.js} +35 -35
  8. package/dist/{Schema-CY3OxwKS.js.map → Schema-CX9CTtho.js.map} +1 -1
  9. package/dist/{SchemaValidationService-BR2ABK2r.js → SchemaValidationService-T5mqnY8q.js} +6 -6
  10. package/dist/{SchemaValidationService-BR2ABK2r.js.map → SchemaValidationService-T5mqnY8q.js.map} +1 -1
  11. package/dist/{backfillMetadataPropertyIds-vc_1RoDT.js → backfillMetadataPropertyIds-DWWkh-Ex.js} +3 -3
  12. package/dist/{backfillMetadataPropertyIds-vc_1RoDT.js.map → backfillMetadataPropertyIds-DWWkh-Ex.js.map} +1 -1
  13. package/dist/{tabEvents-BuorBItJ.js → changeFeed-DcsZ7deG.js} +369 -10
  14. package/dist/changeFeed-DcsZ7deG.js.map +1 -0
  15. package/dist/{configurePlatform-D-Pj9gTx.js → configurePlatform-AWild9o4.js} +2 -2
  16. package/dist/{configurePlatform-D-Pj9gTx.js.map → configurePlatform-AWild9o4.js.map} +1 -1
  17. package/dist/db/drizzle/0022_add_read_indexes.sql +5 -0
  18. package/dist/db/drizzle/0023_add_entity_changes.sql +48 -0
  19. package/dist/db/drizzle/meta/0022_snapshot.json +1585 -0
  20. package/dist/db/drizzle/meta/0023_snapshot.json +1645 -0
  21. package/dist/db/drizzle/meta/_journal.json +14 -0
  22. package/dist/{detachRowsBeforeDelete-sK1ye2W6.js → detachRowsBeforeDelete-Bo_pky-R.js} +2 -2
  23. package/dist/{detachRowsBeforeDelete-sK1ye2W6.js.map → detachRowsBeforeDelete-Bo_pky-R.js.map} +1 -1
  24. package/dist/dist/{ClientManager-Bv15o3Oz.d.ts → ClientManager-B1r_8P5Z.d.ts} +1 -1
  25. package/dist/dist/ClientManager-B1r_8P5Z.d.ts.map +1 -0
  26. package/dist/dist/{Item-tX3kpbj4.d.ts → Item-CjTEShfk.d.ts} +3 -2
  27. package/dist/dist/Item-CjTEShfk.d.ts.map +1 -0
  28. package/dist/dist/{ModelProperty-N-3gBfu5.d.ts → ModelProperty-C3749Wjq.d.ts} +1 -1
  29. package/dist/dist/{ModelProperty-N-3gBfu5.d.ts.map → ModelProperty-C3749Wjq.d.ts.map} +1 -1
  30. package/dist/dist/{Schema-CY3OxwKS.d.ts → Schema-CX9CTtho.d.ts} +2 -2
  31. package/dist/dist/{Schema-CY3OxwKS.d.ts.map → Schema-CX9CTtho.d.ts.map} +1 -1
  32. package/dist/dist/{SchemaValidationService-BR2ABK2r.d.ts → SchemaValidationService-T5mqnY8q.d.ts} +1 -1
  33. package/dist/dist/{SchemaValidationService-BR2ABK2r.d.ts.map → SchemaValidationService-T5mqnY8q.d.ts.map} +1 -1
  34. package/dist/dist/{backfillMetadataPropertyIds-vc_1RoDT.d.ts → backfillMetadataPropertyIds-DWWkh-Ex.d.ts} +1 -1
  35. package/dist/dist/backfillMetadataPropertyIds-DWWkh-Ex.d.ts.map +1 -0
  36. package/dist/dist/{tabEvents-BuorBItJ.d.ts → changeFeed-DcsZ7deG.d.ts} +101 -36
  37. package/dist/dist/changeFeed-DcsZ7deG.d.ts.map +1 -0
  38. package/dist/dist/{configurePlatform-D-Pj9gTx.d.ts → configurePlatform-AWild9o4.d.ts} +1 -1
  39. package/dist/dist/configurePlatform-AWild9o4.d.ts.map +1 -0
  40. package/dist/dist/{detachRowsBeforeDelete-sK1ye2W6.d.ts → detachRowsBeforeDelete-Bo_pky-R.d.ts} +1 -1
  41. package/dist/dist/detachRowsBeforeDelete-Bo_pky-R.d.ts.map +1 -0
  42. package/dist/dist/{eas-BSQxj7gN.d.ts → eas--9vtNkma.d.ts} +1 -1
  43. package/dist/dist/eas--9vtNkma.d.ts.map +1 -0
  44. package/dist/dist/{errors-a4Tj6hly.d.ts → errors-rIWK7gwJ.d.ts} +1 -1
  45. package/dist/dist/{errors-a4Tj6hly.d.ts.map → errors-rIWK7gwJ.d.ts.map} +1 -1
  46. package/dist/dist/{getItem-Ctps9gSs.d.ts → getItem-5j22EWWE.d.ts} +1 -1
  47. package/dist/dist/getItem-5j22EWWE.d.ts.map +1 -0
  48. package/dist/dist/{getPublishPayload-C2g5pPD2.d.ts → getPublishPayload-BGl2SaGK.d.ts} +1 -1
  49. package/dist/dist/{getPublishPayload-C2g5pPD2.d.ts.map → getPublishPayload-BGl2SaGK.d.ts.map} +1 -1
  50. package/dist/dist/{getPublishUploads-CaJHy3SL.d.ts → getPublishUploads-DVsDx6Xf.d.ts} +1 -1
  51. package/dist/dist/{getPublishUploads-CaJHy3SL.d.ts.map → getPublishUploads-DVsDx6Xf.d.ts.map} +1 -1
  52. package/dist/dist/{index-s73wD_LC.d.ts → index-C0SetTd1.d.ts} +1190 -1065
  53. package/dist/dist/index-C0SetTd1.d.ts.map +1 -0
  54. package/dist/dist/{index-BgEwcREa.d.ts → index-CJK3F_MK.d.ts} +13 -13
  55. package/dist/dist/index-CJK3F_MK.d.ts.map +1 -0
  56. package/dist/dist/{index-B6hPWSM4.d.ts → index-CZQrNqvq.d.ts} +130 -13
  57. package/dist/dist/{index-B6hPWSM4.d.ts.map → index-CZQrNqvq.d.ts.map} +1 -1
  58. package/dist/dist/{index-bOwhhJJL.d.ts → index-Dp4uyZYx.d.ts} +5 -5
  59. package/dist/dist/index-Dp4uyZYx.d.ts.map +1 -0
  60. package/dist/dist/{index.browser-C7iZp7mx.d.ts → index.browser-Ll71Y_Dl.d.ts} +391 -39
  61. package/dist/dist/{index.browser-C7iZp7mx.d.ts.map → index.browser-Ll71Y_Dl.d.ts.map} +1 -1
  62. package/dist/dist/{index.node-MPVTJR2J.d.ts → index.node-CgltN0cC.d.ts} +517 -49
  63. package/dist/dist/{index.node-MPVTJR2J.d.ts.map → index.node-CgltN0cC.d.ts.map} +1 -1
  64. package/dist/dist/modelPropertyRecordSchemas-C_lYTzMr.d.ts +7 -0
  65. package/dist/dist/modelPropertyRecordSchemas-C_lYTzMr.d.ts.map +1 -0
  66. package/dist/dist/platform.browser.d.ts +2 -2
  67. package/dist/dist/platform.node.d.ts +2 -2
  68. package/dist/dist/{property-mP9mOZ2L.d.ts → property-pcDxNEpy.d.ts} +3 -3
  69. package/dist/dist/property-pcDxNEpy.d.ts.map +1 -0
  70. package/dist/dist/{propertyValidationRules-DwzrYA7c.d.ts → propertyValidationRules-BEjN0f3-.d.ts} +6 -1
  71. package/dist/dist/propertyValidationRules-BEjN0f3-.d.ts.map +1 -0
  72. package/dist/dist/{publishDraftGraph-BzYVblZZ.d.ts → publishDraftGraph-I5yKe1Xz.d.ts} +1 -1
  73. package/dist/dist/{publishDraftGraph-BzYVblZZ.d.ts.map → publishDraftGraph-I5yKe1Xz.d.ts.map} +1 -1
  74. package/dist/dist/{resetAmbiguousLegacyItemData-B_IUQA09.d.ts → resetAmbiguousLegacyItemData-0Tin9-JK.d.ts} +1 -1
  75. package/dist/dist/resetAmbiguousLegacyItemData-0Tin9-JK.d.ts.map +1 -0
  76. package/dist/dist/{resolveModelForSyncedSeed-H-4tmU6l.d.ts → resolveModelForSyncedSeed-C5KXn6ex.d.ts} +1 -1
  77. package/dist/dist/resolveModelForSyncedSeed-C5KXn6ex.d.ts.map +1 -0
  78. package/dist/dist/{syncDbWithEas-y5VF623G.d.ts → syncDbWithEas-b4fESZ7C.d.ts} +1 -1
  79. package/dist/dist/syncDbWithEas-b4fESZ7C.d.ts.map +1 -0
  80. package/dist/dist/{tolerantWebAccess-DoI7QYT-.d.ts → tolerantWebAccess-CIpS7RLk.d.ts} +1 -1
  81. package/dist/dist/{tolerantWebAccess-DoI7QYT-.d.ts.map → tolerantWebAccess-CIpS7RLk.d.ts.map} +1 -1
  82. package/dist/dist/{updateSeedRevokedAt-BIzkbsUd.d.ts → updateSeedRevokedAt-CR4zwn-6.d.ts} +1 -1
  83. package/dist/dist/updateSeedRevokedAt-CR4zwn-6.d.ts.map +1 -0
  84. package/dist/{eas-BSQxj7gN.js → eas--9vtNkma.js} +3 -3
  85. package/dist/{eas-BSQxj7gN.js.map → eas--9vtNkma.js.map} +1 -1
  86. package/dist/{errors-a4Tj6hly.js → errors-rIWK7gwJ.js} +35 -35
  87. package/dist/{errors-a4Tj6hly.js.map → errors-rIWK7gwJ.js.map} +1 -1
  88. package/dist/{getItem-Ctps9gSs.js → getItem-5j22EWWE.js} +5 -5
  89. package/dist/{getItem-Ctps9gSs.js.map → getItem-5j22EWWE.js.map} +1 -1
  90. package/dist/{getPublishPayload-C2g5pPD2.js → getPublishPayload-BGl2SaGK.js} +14 -14
  91. package/dist/{getPublishPayload-C2g5pPD2.js.map → getPublishPayload-BGl2SaGK.js.map} +1 -1
  92. package/dist/{getPublishUploads-CaJHy3SL.js → getPublishUploads-DVsDx6Xf.js} +7 -7
  93. package/dist/{getPublishUploads-CaJHy3SL.js.map → getPublishUploads-DVsDx6Xf.js.map} +1 -1
  94. package/dist/{index-s73wD_LC.js → index-C0SetTd1.js} +52 -13
  95. package/dist/index-C0SetTd1.js.map +1 -0
  96. package/dist/{index-BgEwcREa.js → index-CJK3F_MK.js} +8 -8
  97. package/dist/index-CJK3F_MK.js.map +1 -0
  98. package/dist/{index-B6hPWSM4.js → index-CZQrNqvq.js} +3 -2
  99. package/dist/index-CZQrNqvq.js.map +1 -0
  100. package/dist/{index-bOwhhJJL.js → index-Dp4uyZYx.js} +8 -8
  101. package/dist/index-Dp4uyZYx.js.map +1 -0
  102. package/dist/{index.browser-C7iZp7mx.js → index.browser-Ll71Y_Dl.js} +243 -18
  103. package/dist/index.browser-Ll71Y_Dl.js.map +1 -0
  104. package/dist/{index.node-MPVTJR2J.js → index.node-CgltN0cC.js} +50 -15
  105. package/dist/index.node-CgltN0cC.js.map +1 -0
  106. package/dist/main.js +23 -30
  107. package/dist/main.js.map +1 -1
  108. package/dist/modelPropertyRecordSchemas-C_lYTzMr.js +94 -0
  109. package/dist/modelPropertyRecordSchemas-C_lYTzMr.js.map +1 -0
  110. package/dist/node.js +11 -11
  111. package/dist/platform.browser.js +5 -5
  112. package/dist/platform.node.js +4 -4
  113. package/dist/{property-mP9mOZ2L.js → property-pcDxNEpy.js} +7 -7
  114. package/dist/{property-mP9mOZ2L.js.map → property-pcDxNEpy.js.map} +1 -1
  115. package/dist/propertyValidationRules-BEjN0f3-.js +73 -0
  116. package/dist/propertyValidationRules-BEjN0f3-.js.map +1 -0
  117. package/dist/{publishDraftGraph-BzYVblZZ.js → publishDraftGraph-I5yKe1Xz.js} +6 -6
  118. package/dist/{publishDraftGraph-BzYVblZZ.js.map → publishDraftGraph-I5yKe1Xz.js.map} +1 -1
  119. package/dist/{resetAmbiguousLegacyItemData-B_IUQA09.js → resetAmbiguousLegacyItemData-0Tin9-JK.js} +2 -2
  120. package/dist/{resetAmbiguousLegacyItemData-B_IUQA09.js.map → resetAmbiguousLegacyItemData-0Tin9-JK.js.map} +1 -1
  121. package/dist/{resolveModelForSyncedSeed-H-4tmU6l.js → resolveModelForSyncedSeed-C5KXn6ex.js} +2 -2
  122. package/dist/{resolveModelForSyncedSeed-H-4tmU6l.js.map → resolveModelForSyncedSeed-C5KXn6ex.js.map} +1 -1
  123. package/dist/seedSchema/EntityChangeSchema.ts +28 -0
  124. package/dist/seedSchema/MetadataSchema.ts +12 -4
  125. package/dist/seedSchema/SeedSchema.ts +9 -3
  126. package/dist/seedSchema/VersionSchema.ts +9 -4
  127. package/dist/seedSchema/index.ts +1 -0
  128. package/dist/src/Item/Item.d.ts +2 -1
  129. package/dist/src/Item/Item.d.ts.map +1 -1
  130. package/dist/src/Item/service/actors/loadOrCreateItem.d.ts.map +1 -1
  131. package/dist/src/ItemProperty/ItemProperty.d.ts.map +1 -1
  132. package/dist/src/ItemProperty/service/actors/loadOrCreateProperty.d.ts.map +1 -1
  133. package/dist/src/ItemProperty/service/actors/modelPropertyRecordSchemas.d.ts +21 -0
  134. package/dist/src/ItemProperty/service/actors/modelPropertyRecordSchemas.d.ts.map +1 -0
  135. package/dist/src/browser/db/Db.d.ts +2 -2
  136. package/dist/src/browser/db/Db.d.ts.map +1 -1
  137. package/dist/src/browser/db/changeFeed.d.ts +77 -0
  138. package/dist/src/browser/db/changeFeed.d.ts.map +1 -0
  139. package/dist/src/browser/db/drizzleFiles.d.ts +4 -2
  140. package/dist/src/browser/db/drizzleFiles.d.ts.map +1 -1
  141. package/dist/src/db/write/applyArweaveL1TransactionIdLocal.d.ts.map +1 -1
  142. package/dist/src/db/write/claimUnpublishedDrafts.d.ts.map +1 -1
  143. package/dist/src/db/write/createMetadata.d.ts.map +1 -1
  144. package/dist/src/db/write/createSeed.d.ts.map +1 -1
  145. package/dist/src/db/write/createVersion.d.ts.map +1 -1
  146. package/dist/src/db/write/restoreDataItemIdsOverwrittenByL1.d.ts.map +1 -1
  147. package/dist/src/db/write/saveMetadata.d.ts.map +1 -1
  148. package/dist/src/db/write/updateItemPropertyValue.d.ts.map +1 -1
  149. package/dist/src/db/write/updateSeedRevokedAt.d.ts.map +1 -1
  150. package/dist/src/db/write/updateSeedUid.d.ts.map +1 -1
  151. package/dist/src/db/write/updateVersionUid.d.ts.map +1 -1
  152. package/dist/src/events/item/syncDbWithEas.d.ts.map +1 -1
  153. package/dist/src/helpers/propertyValidationRules.d.ts +8 -0
  154. package/dist/src/helpers/propertyValidationRules.d.ts.map +1 -1
  155. package/dist/src/helpers/timing.d.ts +36 -0
  156. package/dist/src/helpers/timing.d.ts.map +1 -1
  157. package/dist/src/index.d.ts +2 -0
  158. package/dist/src/index.d.ts.map +1 -1
  159. package/dist/src/node/db/singleConnectionTransactions.d.ts +6 -0
  160. package/dist/src/node/db/singleConnectionTransactions.d.ts.map +1 -1
  161. package/dist/src/outbox/itemAppliers.d.ts.map +1 -1
  162. package/dist/src/outbox/outbox.d.ts +2 -0
  163. package/dist/src/outbox/outbox.d.ts.map +1 -1
  164. package/dist/src/outbox/pendingValues.d.ts.map +1 -1
  165. package/dist/src/seedSchema/EntityChangeSchema.d.ts +126 -0
  166. package/dist/src/seedSchema/EntityChangeSchema.d.ts.map +1 -0
  167. package/dist/src/seedSchema/MetadataSchema.d.ts +4 -4
  168. package/dist/src/seedSchema/MetadataSchema.d.ts.map +1 -1
  169. package/dist/src/seedSchema/SeedSchema.d.ts +4 -4
  170. package/dist/src/seedSchema/SeedSchema.d.ts.map +1 -1
  171. package/dist/src/seedSchema/VersionSchema.d.ts +4 -4
  172. package/dist/src/seedSchema/VersionSchema.d.ts.map +1 -1
  173. package/dist/src/seedSchema/index.d.ts +1 -0
  174. package/dist/src/seedSchema/index.d.ts.map +1 -1
  175. package/dist/{syncDbWithEas-y5VF623G.js → syncDbWithEas-b4fESZ7C.js} +17 -23
  176. package/dist/syncDbWithEas-b4fESZ7C.js.map +1 -0
  177. package/dist/{tolerantWebAccess-DoI7QYT-.js → tolerantWebAccess-CIpS7RLk.js} +6 -6
  178. package/dist/{tolerantWebAccess-DoI7QYT-.js.map → tolerantWebAccess-CIpS7RLk.js.map} +1 -1
  179. package/dist/{updateSeedRevokedAt-BIzkbsUd.js → updateSeedRevokedAt-CR4zwn-6.js} +5 -6
  180. package/dist/updateSeedRevokedAt-CR4zwn-6.js.map +1 -0
  181. package/package.json +6 -6
  182. package/dist/ClientManager-Bv15o3Oz.js.map +0 -1
  183. package/dist/Item-tX3kpbj4.js.map +0 -1
  184. package/dist/dist/ClientManager-Bv15o3Oz.d.ts.map +0 -1
  185. package/dist/dist/Item-tX3kpbj4.d.ts.map +0 -1
  186. package/dist/dist/backfillMetadataPropertyIds-vc_1RoDT.d.ts.map +0 -1
  187. package/dist/dist/configurePlatform-D-Pj9gTx.d.ts.map +0 -1
  188. package/dist/dist/detachRowsBeforeDelete-sK1ye2W6.d.ts.map +0 -1
  189. package/dist/dist/eas-BSQxj7gN.d.ts.map +0 -1
  190. package/dist/dist/getItem-Ctps9gSs.d.ts.map +0 -1
  191. package/dist/dist/index-BgEwcREa.d.ts.map +0 -1
  192. package/dist/dist/index-bOwhhJJL.d.ts.map +0 -1
  193. package/dist/dist/index-s73wD_LC.d.ts.map +0 -1
  194. package/dist/dist/property-mP9mOZ2L.d.ts.map +0 -1
  195. package/dist/dist/propertyValidationRules-DwzrYA7c.d.ts.map +0 -1
  196. package/dist/dist/resetAmbiguousLegacyItemData-B_IUQA09.d.ts.map +0 -1
  197. package/dist/dist/resolveModelForSyncedSeed-H-4tmU6l.d.ts.map +0 -1
  198. package/dist/dist/syncDbWithEas-y5VF623G.d.ts.map +0 -1
  199. package/dist/dist/tabEvents-BuorBItJ.d.ts.map +0 -1
  200. package/dist/dist/updateSeedRevokedAt-BIzkbsUd.d.ts.map +0 -1
  201. package/dist/index-B6hPWSM4.js.map +0 -1
  202. package/dist/index-BgEwcREa.js.map +0 -1
  203. package/dist/index-bOwhhJJL.js.map +0 -1
  204. package/dist/index-s73wD_LC.js.map +0 -1
  205. package/dist/index.browser-C7iZp7mx.js.map +0 -1
  206. package/dist/index.node-MPVTJR2J.js.map +0 -1
  207. package/dist/propertyValidationRules-DwzrYA7c.js +0 -51
  208. package/dist/propertyValidationRules-DwzrYA7c.js.map +0 -1
  209. package/dist/syncDbWithEas-y5VF623G.js.map +0 -1
  210. package/dist/tabEvents-BuorBItJ.js.map +0 -1
  211. package/dist/updateSeedRevokedAt-BIzkbsUd.js.map +0 -1
@@ -1,12 +1,12 @@
1
- import debug from 'debug';
1
+ import { v as timingNow, x as timingSince, y as timingLogger, z as TAB_ID, o as onTabMessage, c as whenLeaderTab, a as isLeaderTab, k as postTabMessage, f as createSessionObjectUrl, t as timingMarks, B as timed, u as notifyFileSaved, C as revokeSessionObjectUrl, b as watchEntityRows, D as queryEntityRows, E as isSessionObjectUrl, G as timedDb } from './changeFeed-DcsZ7deG.js';
2
2
  import { waitFor, fromCallback, setup, assign, stateIn, createActor, isMachineSnapshot } from 'xstate';
3
- import { F as BaseDb, E as versions, m as metadata, B as seeds, G as resolveStorageNameToSchemaName, b2 as toSchemaPropertyName, i as isDataType, ai as generateId, u as pendingWrites, b3 as isSqliteBusyError, A as schemas, s as models, q as modelSchemas, b0 as getOwnedAddressesFromDb, a3 as ZERO_BYTES32, aH as normalizeAddressList, aj as normalizeHexAddress, aE as getAddressesForItemsFilter, a7 as INTERNAL_PROPERTY_NAMES, b4 as easSchemaDefinitionForProperty, N as BaseFileManager, b5 as getStorageTransactionIdForSeedUid, b6 as convertTxIdToImage, ad as normalizePublisher, ab as listRelationEasPropertyName, n as normalizeDataType, L as resolveItemModelFileId, b7 as getPropertyIdForSchemaFileId, K as getPropertyIdForModelAndName, a_ as getMetadataPropertyNamesForQuery, aD as ensureImageLocal, av as ImageSize, b8 as downloadTransactionIdWithDedupe, b9 as resolveMetadataRecord, v as properties, M as ModelPropertyDataTypes, I as eventEmitter, r as modelUids, ak as toMetadataPropertyName, ba as getDataTypeFromString, bb as getMimeType, Y as INTERNAL_STORAGE_MODEL_FILE_IDS, g as normalizePropertyRecordSchema, bc as listRelationStoragePropertyName, bd as PROPERTY_NAMES_EXEMPT_FROM_ID_SUFFIX_STRIP, R as getCorrectId, a0 as getItemStorageSubdir, a1 as getItemStorageLocalFileName, be as toItemPropertyKey, bf as getAlternatePropertyNameForInstanceLookup, a8 as isStorageSeedRef } from './index-s73wD_LC.js';
3
+ import { G as BaseDb, F as versions, m as metadata, C as seeds, H as resolveStorageNameToSchemaName, b5 as toSchemaPropertyName, i as isDataType, aj as generateId, v as pendingWrites, aq as isSqliteBusyError, B as schemas, t as models, r as modelSchemas, b3 as getOwnedAddressesFromDb, a5 as ZERO_BYTES32, aJ as normalizeAddressList, ak as normalizeHexAddress, aG as getAddressesForItemsFilter, a8 as INTERNAL_PROPERTY_NAMES, b6 as easSchemaDefinitionForProperty, Q as BaseFileManager, b7 as getStorageTransactionIdForSeedUid, b8 as convertTxIdToImage, ae as normalizePublisher, ac as listRelationEasPropertyName, n as normalizeDataType, O as resolveItemModelFileId, b9 as getPropertyIdForSchemaFileId, N as getPropertyIdForModelAndName, b1 as getMetadataPropertyNamesForQuery, aF as ensureImageLocal, ax as ImageSize, ba as downloadTransactionIdWithDedupe, bb as resolveMetadataRecord, M as ModelPropertyDataTypes, J as eventEmitter, s as modelUids, al as toMetadataPropertyName, bc as getDataTypeFromString, bd as getMimeType, _ as INTERNAL_STORAGE_MODEL_FILE_IDS, g as normalizePropertyRecordSchema, be as listRelationStoragePropertyName, bf as PROPERTY_NAMES_EXEMPT_FROM_ID_SUFFIX_STRIP, V as getCorrectId, a2 as getItemStorageSubdir, a3 as getItemStorageLocalFileName, bg as toItemPropertyKey, bh as getAlternatePropertyNameForInstanceLookup, w as properties, a9 as isStorageSeedRef } from './index-C0SetTd1.js';
4
4
  import { or, isNull, eq, max, count, and, getTableColumns, sql, asc, inArray, lt, isNotNull, desc, gt } from 'drizzle-orm';
5
5
  import pluralize from 'pluralize';
6
+ import debug from 'debug';
6
7
  import { BehaviorSubject } from 'rxjs';
7
8
  import { startCase, upperFirst, camelCase, orderBy } from 'lodash-es';
8
9
  import { isValidEasAttestationUid, easName, isPlaceholderUid, getEasSchemaUidForSchemaDefinition, getEasSchemaUidForExactDefinition, getSchemaUidForModelFromCache, setSchemaUidForModel, cachedSchemaLookup, BaseQueryClient, BaseEasClient, GET_SCHEMAS } from '@seedprotocol/eas';
9
- import { h as TAB_ID, o as onTabMessage, w as whenLeaderTab, i as isLeaderTab, d as postTabMessage, c as createSessionObjectUrl, g as notifyFileSaved, r as revokeSessionObjectUrl, j as isSessionObjectUrl } from './tabEvents-BuorBItJ.js';
10
10
  import { fetchArweaveRawTextAcrossGateways } from '@seedprotocol/arweave';
11
11
  import { modelPropertiesToObject } from './model-oHA3YhOd.js';
12
12
 
@@ -290,32 +290,6 @@ function createReactiveProxy(config) {
290
290
  return proxy;
291
291
  }
292
292
 
293
- /**
294
- * Phase timings for item creates, finds and property saves, and ready waits that timed out but
295
- * were allowed to continue, under `DEBUG=seedSdk:timing`. Timing lines are `<label> <ms>ms` plus
296
- * any details, so an app can report where a slow call spent its time.
297
- */
298
- const timingLogger = debug('seedSdk:timing');
299
- const now = () => (typeof performance !== 'undefined' ? performance.now() : Date.now());
300
- /** Runs `fn` and logs how long it took (also when it throws). Costs nothing when the namespace is off. */
301
- async function timed(label, fn, details) {
302
- if (!timingLogger.enabled)
303
- return fn();
304
- const start = now();
305
- let failed = false;
306
- try {
307
- return await fn();
308
- }
309
- catch (error) {
310
- failed = true;
311
- throw error;
312
- }
313
- finally {
314
- const extra = details?.();
315
- timingLogger(`${label} ${Math.round(now() - start)}ms${failed ? ' (failed)' : ''}${extra ? ` ${extra}` : ''}`);
316
- }
317
- }
318
-
319
293
  const ENV = (typeof process !== 'undefined' && process.env)
320
294
  ? process.env
321
295
  : (typeof window !== 'undefined' && window.env)
@@ -647,7 +621,7 @@ const createItemPropertyInstances = async (metadataRows, seedLocalId, seedUid, m
647
621
  const itemPropertyMod = await Promise.resolve().then(function () { return ItemProperty$1; });
648
622
  const { ItemProperty } = itemPropertyMod;
649
623
  const { modelPropertiesToObject } = await import('./model-oHA3YhOd.js');
650
- const _mod_0 = await import('./errors-a4Tj6hly.js');
624
+ const _mod_0 = await import('./errors-rIWK7gwJ.js');
651
625
  const _ns_0 = _mod_0.i;
652
626
  const { Model } = _ns_0;
653
627
  // Resolve Model and build property schemas (use getByNameAsync for models not yet in cache)
@@ -665,7 +639,7 @@ const createItemPropertyInstances = async (metadataRows, seedLocalId, seedUid, m
665
639
  const schemaNameToTry = schemaName ?? model?.schemaName;
666
640
  if (schemaNameToTry) {
667
641
  try {
668
- const _mod_1 = await import('./Schema-CY3OxwKS.js');
642
+ const _mod_1 = await import('./Schema-CX9CTtho.js');
669
643
  const _ns_1 = _mod_1.b;
670
644
  const { Schema } = _ns_1;
671
645
  const schemaInstance = Schema.create(schemaNameToTry, { waitForReady: false, hold: false });
@@ -681,7 +655,7 @@ const createItemPropertyInstances = async (metadataRows, seedLocalId, seedUid, m
681
655
  }
682
656
  if (Object.keys(propertySchemas).length === 0) {
683
657
  try {
684
- const _mod_2 = await import('./ClientManager-Bv15o3Oz.js');
658
+ const _mod_2 = await import('./ClientManager-B1r_8P5Z.js');
685
659
  const _ns_2 = _mod_2.X;
686
660
  const { loadAllSchemasFromDb } = _ns_2;
687
661
  const allSchemas = await loadAllSchemasFromDb();
@@ -702,11 +676,11 @@ const createItemPropertyInstances = async (metadataRows, seedLocalId, seedUid, m
702
676
  }
703
677
  if (Object.keys(propertySchemas).length === 0) {
704
678
  try {
705
- const _mod_3 = await import('./ClientManager-Bv15o3Oz.js');
679
+ const _mod_3 = await import('./ClientManager-B1r_8P5Z.js');
706
680
  const _ns_3 = _mod_3.X;
707
681
  const { listCompleteSchemaFiles } = _ns_3;
708
- const _mod_4 = await import('./index-s73wD_LC.js');
709
- const _ns_4 = _mod_4.bi;
682
+ const _mod_4 = await import('./index-C0SetTd1.js');
683
+ const _ns_4 = _mod_4.bk;
710
684
  const { BaseFileManager } = _ns_4;
711
685
  const schemaFiles = await listCompleteSchemaFiles();
712
686
  for (const { filePath } of schemaFiles) {
@@ -726,7 +700,7 @@ const createItemPropertyInstances = async (metadataRows, seedLocalId, seedUid, m
726
700
  }
727
701
  }
728
702
  if (Object.keys(propertySchemas).length === 0) {
729
- const schemaMod = await import('./index-bOwhhJJL.js');
703
+ const schemaMod = await import('./index-Dp4uyZYx.js');
730
704
  const { ModelPropertyDataTypes } = schemaMod;
731
705
  const KNOWN_MODEL_FALLBACKS = {
732
706
  Post: {
@@ -743,7 +717,7 @@ const createItemPropertyInstances = async (metadataRows, seedLocalId, seedUid, m
743
717
  }
744
718
  }
745
719
  // Fallbacks above may return schema-file shape ({ type, model, items }); normalize to dataType/ref/refValueType.
746
- const { normalizePropertyRecordSchema } = await import('./property-mP9mOZ2L.js');
720
+ const { normalizePropertyRecordSchema } = await import('./property-pcDxNEpy.js');
747
721
  propertySchemas = Object.fromEntries(Object.entries(propertySchemas).map(([name, def]) => [name, normalizePropertyRecordSchema(def)]));
748
722
  // Collapse rows that map to the same instance key (e.g. authorIdentityIds + authors -> authors).
749
723
  // ItemProperty.create cache does not sync propertyValue on hit; processing order would otherwise
@@ -776,7 +750,7 @@ const createItemPropertyInstances = async (metadataRows, seedLocalId, seedUid, m
776
750
  // Infer propertyRecordSchema from metadata when schema is missing (enables persistence)
777
751
  let propSchema = propertySchemas[propertyName];
778
752
  if (!propSchema && isRefTypeFromMeta) {
779
- const schemaMod = await import('./index-bOwhhJJL.js');
753
+ const schemaMod = await import('./index-Dp4uyZYx.js');
780
754
  const { ModelPropertyDataTypes } = schemaMod;
781
755
  propSchema = {
782
756
  dataType: refSeedType === 'html' ? ModelPropertyDataTypes.Html
@@ -880,6 +854,7 @@ const loadOrCreateItem = fromCallback(({ sendBack, input: { context } }) => {
880
854
  else if (seedUid) {
881
855
  whereClauses.push(eq(seeds.uid, seedUid));
882
856
  }
857
+ const timingStart = timingNow();
883
858
  const seedRecords = await db
884
859
  .select()
885
860
  .from(seeds)
@@ -913,6 +888,7 @@ const loadOrCreateItem = fromCallback(({ sendBack, input: { context } }) => {
913
888
  const schemaUid = seedRecord.schemaUid || undefined;
914
889
  const modelFileId = seedRecord.modelFileId || context.modelFileId || undefined;
915
890
  const modelScope = { modelFileId, schemaName: context.schemaName };
891
+ const seedMs = timingSince(timingStart);
916
892
  // Step 2: Query versions table to find all versions for that seed
917
893
  const versionData = getVersionData$1();
918
894
  const versionRecords = await db
@@ -980,6 +956,7 @@ const loadOrCreateItem = fromCallback(({ sendBack, input: { context } }) => {
980
956
  }
981
957
  // Step 3: Latest metadata row per property_name for this seed (matches loadOrCreateProperty /
982
958
  // getItemProperties). Strict version_local_id = latest would drop properties whose rows lag version bumps.
959
+ const versionsMs = timingSince(timingStart) - seedMs;
983
960
  const metadataLatest = getMetadataLatest({
984
961
  seedLocalId: resolvedSeedLocalId,
985
962
  seedUid: resolvedSeedUid,
@@ -990,6 +967,7 @@ const loadOrCreateItem = fromCallback(({ sendBack, input: { context } }) => {
990
967
  .from(metadataLatest)
991
968
  .where(eq(metadataLatest.rowNum, 1));
992
969
  logger$b(`Found ${metadataRecords.length} latest-per-property metadata rows for seed ${resolvedSeedLocalId} (latestVersionLocalId=${latestVersionLocalId} used for placeholders only)`);
970
+ const metadataMs = timingSince(timingStart) - seedMs - versionsMs;
993
971
  // Step 4: Create ItemProperty instances from metadata records + placeholders for model schema properties
994
972
  // Always call when we have a valid version so placeholders are created for properties without metadata
995
973
  const propertyInstances = await createItemPropertyInstances(metadataRecords, resolvedSeedLocalId, resolvedSeedUid, modelName, latestVersionLocalId, latestVersionUid, modelScope);
@@ -998,6 +976,10 @@ const loadOrCreateItem = fromCallback(({ sendBack, input: { context } }) => {
998
976
  // Publish/attestation can keep properties in `saving` for many seconds; 5s caused timeouts during EAS work.
999
977
  const propertyIdleTimeoutMs = 120000;
1000
978
  Promise.all(Array.from(propertyInstances.values()).map((prop) => waitForEntityIdle(prop, { timeout: propertyIdleTimeoutMs, throwOnError: false }))).catch(() => { });
979
+ if (timingLogger.enabled) {
980
+ const totalMs = timingSince(timingStart);
981
+ timingLogger(`item ${resolvedSeedLocalId} loadOrCreateItem ${totalMs}ms: seed ${seedMs}, versions ${versionsMs}, metadata ${metadataMs}, ${propertyInstances.size} property instances ${totalMs - seedMs - versionsMs - metadataMs}`);
982
+ }
1001
983
  // Step 5: Return loaded item data with property instances
1002
984
  sendBack({
1003
985
  type: 'loadOrCreateItemSuccess',
@@ -1349,6 +1331,10 @@ function registerOutboxApplier(kind, applier) {
1349
1331
  appliers.delete(kind);
1350
1332
  };
1351
1333
  }
1334
+ /** Bumped before every append in this tab, so a pending-value read begun earlier isn't reused after it. */
1335
+ let appendGeneration = 0;
1336
+ /** How many appends this tab has started; see getPendingSetValue. */
1337
+ const outboxAppendGeneration = () => appendGeneration;
1352
1338
  /**
1353
1339
  * Appends one op, or several that apply together (they share a new group id unless they carry
1354
1340
  * one), and tells the leader to drain. Returns the op ids in order.
@@ -1373,6 +1359,7 @@ async function appendOutboxOps(inputs) {
1373
1359
  status: 'pending',
1374
1360
  attempts: 0,
1375
1361
  }));
1362
+ appendGeneration += 1;
1376
1363
  await BaseDb.getAppDb().insert(pendingWrites).values(rows);
1377
1364
  startOutbox();
1378
1365
  if (isLeaderTab())
@@ -1858,11 +1845,33 @@ async function getPendingPropertyRows(seedLocalId, propertyNames) {
1858
1845
  }
1859
1846
  return rows;
1860
1847
  }
1848
+ /**
1849
+ * One read of all of a seed's pending rows while it's in flight: an item's properties load together
1850
+ * and would otherwise each send the same query. A caller joins a read only if this tab hasn't
1851
+ * appended an op since it began, so none misses a value assigned before it asked. Each caller still
1852
+ * has the pending rows before it reads the stored row. The test hook sees these reads as reads of
1853
+ * all properties (undefined names).
1854
+ */
1855
+ const sharedReads = new Map();
1856
+ function sharedPendingPropertyRows(seedLocalId) {
1857
+ const generation = outboxAppendGeneration();
1858
+ const existing = sharedReads.get(seedLocalId);
1859
+ if (existing && existing.generation === generation)
1860
+ return existing.read;
1861
+ const created = { generation, read: getPendingPropertyRows(seedLocalId) };
1862
+ sharedReads.set(seedLocalId, created);
1863
+ const forget = () => {
1864
+ if (sharedReads.get(seedLocalId) === created)
1865
+ sharedReads.delete(seedLocalId);
1866
+ };
1867
+ created.read.then(forget, forget);
1868
+ return created.read;
1869
+ }
1861
1870
  /** One property's pending row (see getPendingPropertyRows); undefined when it has none. */
1862
1871
  async function getPendingPropertyRow(seedLocalId, propertyName) {
1863
- if (!propertyName)
1872
+ if (!propertyName || !seedLocalId)
1864
1873
  return undefined;
1865
- const rows = await getPendingPropertyRows(seedLocalId, [propertyName]);
1874
+ const rows = await sharedPendingPropertyRows(seedLocalId);
1866
1875
  for (const name of propertyNameVariants(propertyName)) {
1867
1876
  const row = rows.get(name);
1868
1877
  if (row)
@@ -2458,8 +2467,8 @@ const getItemsData = async ({ modelName, modelFileId, schemaName, deleted, inclu
2458
2467
  conditions.push(eq(seeds.type, easName(modelName)));
2459
2468
  }
2460
2469
  if (!modelFileId && schemaName && modelName) {
2461
- const _mod_5 = await import('./index-s73wD_LC.js');
2462
- const _ns_5 = _mod_5.bl;
2470
+ const _mod_5 = await import('./index-C0SetTd1.js');
2471
+ const _ns_5 = _mod_5.bn;
2463
2472
  const { resolveModelRecord } = _ns_5;
2464
2473
  modelFileId = (await resolveModelRecord(modelName, { schemaName }))?.schemaFileId ?? undefined;
2465
2474
  if (!modelFileId)
@@ -2686,7 +2695,7 @@ const resolveRelatedValue = fromCallback(({ sendBack, input: { context } }) => {
2686
2695
  const { isRelation, propertyValue, propertyName, propertyRecordSchema, populatedFromDb, } = context;
2687
2696
  const _resolveRelatedValue = async () => {
2688
2697
  // Use dynamic import to break circular dependency
2689
- const schemaMod = await import('./index-bOwhhJJL.js');
2698
+ const schemaMod = await import('./index-Dp4uyZYx.js');
2690
2699
  const { ModelPropertyDataTypes } = schemaMod;
2691
2700
  if (!propertyValue || !isRelation || populatedFromDb) {
2692
2701
  return;
@@ -3100,7 +3109,7 @@ const createMetadata = async (metadataValues, propertyRecordSchema, options) =>
3100
3109
  propertyRecordSchema?.validation &&
3101
3110
  metadataValues.propertyValue != null &&
3102
3111
  metadataValues.propertyValue !== '') {
3103
- const { SchemaValidationService } = await import('./SchemaValidationService-BR2ABK2r.js');
3112
+ const { SchemaValidationService } = await import('./SchemaValidationService-T5mqnY8q.js');
3104
3113
  const validationService = new SchemaValidationService();
3105
3114
  const validationResult = validationService.validatePropertyValue(metadataValues.propertyValue, normalizeDataType(propertyRecordSchema.dataType), propertyRecordSchema.validation, propertyRecordSchema.refValueType
3106
3115
  ? normalizeDataType(String(propertyRecordSchema.refValueType))
@@ -3155,6 +3164,7 @@ const createMetadata = async (metadataValues, propertyRecordSchema, options) =>
3155
3164
  .insert(metadata)
3156
3165
  .values({
3157
3166
  ...metadataValues,
3167
+ // Stamped here: a value carried in metadataValues would otherwise win over the column default.
3158
3168
  createdAt: Date.now(),
3159
3169
  updatedAt: Date.now(),
3160
3170
  })
@@ -3307,8 +3317,8 @@ async function readHtmlBodyFromChildStorageArweave(seedLocalId) {
3307
3317
  /* offline / bad tx id */
3308
3318
  }
3309
3319
  try {
3310
- const _mod_6 = await import('./index-s73wD_LC.js');
3311
- const _ns_6 = _mod_6.bn;
3320
+ const _mod_6 = await import('./index-C0SetTd1.js');
3321
+ const _ns_6 = _mod_6.bp;
3312
3322
  const { downloadTransactionIdWithDedupe } = _ns_6;
3313
3323
  await downloadTransactionIdWithDedupe(txId);
3314
3324
  const retryFp = BaseFileManager.getFilesPath('html', `${seedLocalId}.html`);
@@ -3368,7 +3378,7 @@ const hydrateFromDb = fromCallback(({ sendBack, input: { context } }) => {
3368
3378
  // to use dynamically imported ModelPropertyDataTypes
3369
3379
  const _hydrateFromDb = async () => {
3370
3380
  // Use dynamic import to break circular dependency
3371
- const schemaMod = await import('./index-bOwhhJJL.js');
3381
+ const schemaMod = await import('./index-Dp4uyZYx.js');
3372
3382
  const { ModelPropertyDataTypes } = schemaMod;
3373
3383
  const appDb = BaseDb.getAppDb();
3374
3384
  const whereClauses = [];
@@ -3416,7 +3426,7 @@ const hydrateFromDb = fromCallback(({ sendBack, input: { context } }) => {
3416
3426
  }
3417
3427
  const stored = rows?.[0] ?? { seedLocalId, seedUid, propertyName };
3418
3428
  const firstRow = pending ? applyPendingRow({ ...stored }, pending) : { ...stored };
3419
- const _mod_7 = await import('./ClientManager-Bv15o3Oz.js');
3429
+ const _mod_7 = await import('./ClientManager-B1r_8P5Z.js');
3420
3430
  const _ns_7 = _mod_7.Z;
3421
3431
  const { getPropertyConflict } = _ns_7;
3422
3432
  const conflict = await getPropertyConflict(firstRow.seedLocalId ?? seedLocalId, propertyName);
@@ -3643,6 +3653,8 @@ const loadOrCreateProperty = fromCallback(({ sendBack, input: { context } }) =>
3643
3653
  if (!db) {
3644
3654
  throw new Error('Database not available');
3645
3655
  }
3656
+ const timing = timingMarks();
3657
+ const timingLabel = `property ${seedLocalId ?? seedUid} ${propertyName} loadOrCreateProperty`;
3646
3658
  // Use getMetadataLatest subquery pattern to get the latest metadata record for the property
3647
3659
  const metadataLatest = getMetadataLatest({
3648
3660
  seedLocalId: seedLocalId ?? undefined,
@@ -3657,12 +3669,14 @@ const loadOrCreateProperty = fromCallback(({ sendBack, input: { context } }) =>
3657
3669
  // applies between the two reads is then in one of them
3658
3670
  const { applyPendingRow, getPendingPropertyRow, pendingSetValueOf } = await Promise.resolve().then(function () { return pendingValues; });
3659
3671
  const pendingFirst = seedLocalId ? await getPendingPropertyRow(seedLocalId, propertyName) : undefined;
3672
+ timing.mark('pending value');
3660
3673
  const metadataRecords = await db
3661
3674
  .with(metadataLatest)
3662
3675
  .select()
3663
3676
  .from(metadataLatest)
3664
3677
  .where(and(propertyNameWhere, eq(metadataLatest.rowNum, 1)))
3665
3678
  .limit(5);
3679
+ timing.mark('metadata');
3666
3680
  if (metadataRecords.length === 0) {
3667
3681
  // Metadata not found - this is a new property, will be created elsewhere.
3668
3682
  // Still resolve propertyRecordSchema from Model so getSegmentedItemProperties and
@@ -3671,12 +3685,12 @@ const loadOrCreateProperty = fromCallback(({ sendBack, input: { context } }) =>
3671
3685
  const modelNameForNew = context.modelName;
3672
3686
  if (modelNameForNew) {
3673
3687
  try {
3674
- const _mod_8 = await import('./errors-a4Tj6hly.js');
3688
+ const _mod_8 = await import('./errors-rIWK7gwJ.js');
3675
3689
  const _ns_8 = _mod_8.i;
3676
3690
  const { Model } = _ns_8;
3677
3691
  const { modelPropertiesToObject } = await import('./model-oHA3YhOd.js');
3678
- const _mod_9 = await import('./index-s73wD_LC.js');
3679
- const _ns_9 = _mod_9.bl;
3692
+ const _mod_9 = await import('./index-C0SetTd1.js');
3693
+ const _ns_9 = _mod_9.bn;
3680
3694
  const { resolveItemModelFileId } = _ns_9;
3681
3695
  const normalizedModelName = upperFirst(camelCase(modelNameForNew));
3682
3696
  const itemModelFileId = await resolveItemModelFileId({
@@ -3737,60 +3751,25 @@ const loadOrCreateProperty = fromCallback(({ sendBack, input: { context } }) =>
3737
3751
  // It ends up in the context below, and later lookups by name (Model.getByName) can't match it.
3738
3752
  const modelName = context.modelName || (metadataRecord.modelType ? upperFirst(camelCase(metadataRecord.modelType)) : undefined);
3739
3753
  // Model names are only unique per schema: pin lookups to the item's own model row.
3740
- const _mod_10 = await import('./index-s73wD_LC.js');
3741
- const _ns_10 = _mod_10.bl;
3742
- const { resolveItemModelFileId, resolveModelRecord } = _ns_10;
3754
+ const _mod_10 = await import('./index-C0SetTd1.js');
3755
+ const _ns_10 = _mod_10.bn;
3756
+ const { resolveItemModelFileId } = _ns_10;
3743
3757
  const modelFileId = await resolveItemModelFileId({
3744
3758
  modelFileId: context.modelFileId,
3745
3759
  seedLocalId: seedLocalId ?? metadataRecord.seedLocalId,
3746
3760
  seedUid: seedUid ?? metadataRecord.seedUid,
3747
3761
  propertyId: metadataRecord.propertyId,
3748
3762
  });
3763
+ timing.mark('model file id');
3749
3764
  if (modelName) {
3750
3765
  try {
3751
3766
  // Normalize snake_case to PascalCase: "test_post" -> "TestPost" (startCase gives "Test Post" which fails)
3752
3767
  const normalizedModelName = upperFirst(camelCase(modelName));
3753
- // Query properties table to get property schema
3754
- const modelRecord = await resolveModelRecord(normalizedModelName, { modelFileId }, db);
3755
- const modelRecords = modelRecord ? [modelRecord] : [];
3756
- if (modelRecords.length > 0 && modelRecords[0].id) {
3757
- const propertyRecords = await db
3758
- .select()
3759
- .from(properties)
3760
- .where(and(eq(properties.modelId, modelRecords[0].id), eq(properties.name, propertyName)))
3761
- .limit(1);
3762
- if (propertyRecords.length > 0) {
3763
- const propRecord = propertyRecords[0];
3764
- // properties table has refModelId but not refModelName; resolve ref model name when refModelId is set
3765
- let refModelName;
3766
- if (propRecord.refModelId != null) {
3767
- const refModelRows = await db
3768
- .select({ name: models.name })
3769
- .from(models)
3770
- .where(eq(models.id, propRecord.refModelId))
3771
- .limit(1);
3772
- refModelName = refModelRows[0]?.name ?? undefined;
3773
- }
3774
- propertyRecordSchema = {
3775
- id: propRecord.id,
3776
- dataType: propRecord.dataType,
3777
- ref: refModelName ?? undefined,
3778
- refValueType: propRecord.refValueType || undefined,
3779
- storageType: propRecord.storageType || undefined,
3780
- localStorageDir: propRecord.localStorageDir || undefined,
3781
- filenameSuffix: propRecord.filenameSuffix || undefined,
3782
- required: propRecord.required ?? undefined,
3783
- };
3784
- // Validation rules (enum, pattern, ...) aren't in the properties table
3785
- const { resolvePropertyValidationRules } = await import('./propertyValidationRules-DwzrYA7c.js');
3786
- const validation = await resolvePropertyValidationRules(normalizedModelName, propertyName, {
3787
- modelFileId: modelRecord?.schemaFileId ?? modelFileId,
3788
- });
3789
- if (validation) {
3790
- propertyRecordSchema = { ...propertyRecordSchema, validation };
3791
- }
3792
- }
3793
- }
3768
+ // One read for the whole model, shared by the item's other properties loading now
3769
+ const { loadModelPropertyRecordSchemas } = await import('./modelPropertyRecordSchemas-C_lYTzMr.js');
3770
+ const schemas = await loadModelPropertyRecordSchemas(normalizedModelName, modelFileId, db);
3771
+ propertyRecordSchema = schemas.get(propertyName);
3772
+ timing.mark('model schema');
3794
3773
  }
3795
3774
  catch (error) {
3796
3775
  logger$3(`Error loading propertyRecordSchema from database: ${error}`);
@@ -3800,7 +3779,7 @@ const loadOrCreateProperty = fromCallback(({ sendBack, input: { context } }) =>
3800
3779
  // Fix 1: Fallback to in-memory Model when DB doesn't have model/properties yet (e.g. runtime-created model)
3801
3780
  if (!propertyRecordSchema && modelName) {
3802
3781
  try {
3803
- const _mod_11 = await import('./errors-a4Tj6hly.js');
3782
+ const _mod_11 = await import('./errors-rIWK7gwJ.js');
3804
3783
  const _ns_11 = _mod_11.i;
3805
3784
  const { Model } = _ns_11;
3806
3785
  const { modelPropertiesToObject } = await import('./model-oHA3YhOd.js');
@@ -3971,6 +3950,8 @@ const loadOrCreateProperty = fromCallback(({ sendBack, input: { context } }) =>
3971
3950
  propertyValueOut = parseListPropertyValueFromStorage(propertyValueOut);
3972
3951
  renderValue = propertyValueOut;
3973
3952
  }
3953
+ timing.mark('value');
3954
+ timing.log(timingLabel);
3974
3955
  // Return loaded property data (use propertyName from context to match schema key, e.g. "html" not "htmlId")
3975
3956
  sendBack({
3976
3957
  type: 'loadOrCreatePropertySuccess',
@@ -4115,7 +4096,6 @@ const updateItemPropertyValue = async ({ localId: localIdParam, propertyName, ne
4115
4096
  // Readers take the newest row by COALESCE(attestation_created_at, created_at), so a draft's
4116
4097
  // time is when its value was last set: a synced value older than this edit mustn't win.
4117
4098
  createdAt: now,
4118
- updatedAt: now,
4119
4099
  };
4120
4100
  if (localStorageDir !== undefined) {
4121
4101
  updatePayload.localStorageDir = localStorageDir ?? null;
@@ -4148,7 +4128,6 @@ const updateItemPropertyValue = async ({ localId: localIdParam, propertyName, ne
4148
4128
  refResolvedValue: refResolvedValue || null,
4149
4129
  refResolvedDisplayValue: refResolvedDisplayValue || null,
4150
4130
  localStorageDir: localStorageDir || null,
4151
- createdAt: Date.now(),
4152
4131
  });
4153
4132
  return {
4154
4133
  localId: newLocalId,
@@ -4186,7 +4165,6 @@ const updateItemPropertyValue = async ({ localId: localIdParam, propertyName, ne
4186
4165
  refResolvedValue: refResolvedValue || null,
4187
4166
  refResolvedDisplayValue: refResolvedDisplayValue || null,
4188
4167
  localStorageDir: localStorageDir || null,
4189
- createdAt: Date.now(),
4190
4168
  });
4191
4169
  return {
4192
4170
  localId: newLocalId,
@@ -4261,7 +4239,7 @@ const analyzeInput = fromCallback(({ sendBack, input: { context, event } }) => {
4261
4239
  const result = await updateItemPropertyValue({ ...props, seedLocalId, propertyName: propertyNameRaw });
4262
4240
  return { skipped: false, result, conflict: null };
4263
4241
  }
4264
- const { appendOutboxOp, getOutboxOps, outboxOpResult, startItemOutbox, throwItemWriteError, waitForOutboxOp } = await import('./index-BgEwcREa.js');
4242
+ const { appendOutboxOp, getOutboxOps, outboxOpResult, startItemOutbox, throwItemWriteError, waitForOutboxOp } = await import('./index-CJK3F_MK.js');
4265
4243
  startItemOutbox();
4266
4244
  // Checked right before appending (no await in between): ops apply in append order
4267
4245
  if (writeTicket && !writeTicket.isLatest())
@@ -4292,9 +4270,9 @@ const analyzeInput = fromCallback(({ sendBack, input: { context, event } }) => {
4292
4270
  return false;
4293
4271
  }
4294
4272
  // Use dynamic import to break circular dependency
4295
- const schemaMod = await import('./index-bOwhhJJL.js');
4273
+ const schemaMod = await import('./index-Dp4uyZYx.js');
4296
4274
  const { ModelPropertyDataTypes } = schemaMod;
4297
- const { SchemaValidationService } = await import('./SchemaValidationService-BR2ABK2r.js');
4275
+ const { SchemaValidationService } = await import('./SchemaValidationService-T5mqnY8q.js');
4298
4276
  const propertyName = propertyNameRaw;
4299
4277
  if (!propertyName) {
4300
4278
  throw new Error('propertyName is required');
@@ -4524,7 +4502,6 @@ const createSeed = async ({ type, seedUid, modelFileId }, options = {}) => {
4524
4502
  type,
4525
4503
  modelFileId: modelFileId ?? null,
4526
4504
  uid: seedUid,
4527
- createdAt: Date.now(),
4528
4505
  schemaUid: schemaUid || null,
4529
4506
  ...(publisher && { publisher }),
4530
4507
  });
@@ -4554,7 +4531,7 @@ async function writeStorageValue(item, value, ticket) {
4554
4531
  if (!seedLocalId) {
4555
4532
  throw new Error(`No local seed for the item to save ${item.propertyName} to`);
4556
4533
  }
4557
- const { appendOutboxOp, getOutboxOps, outboxOpResult, startItemOutbox, throwItemWriteError, waitForOutboxOp } = await import('./index-BgEwcREa.js');
4534
+ const { appendOutboxOp, getOutboxOps, outboxOpResult, startItemOutbox, throwItemWriteError, waitForOutboxOp } = await import('./index-CJK3F_MK.js');
4558
4535
  startItemOutbox();
4559
4536
  // Checked right before appending (no await in between): ops apply in append order
4560
4537
  if (ticket && !ticket.isLatest()) {
@@ -5546,11 +5523,11 @@ const getPropertyData = async ({ propertyName, seedLocalId, seedUid, modelName,
5546
5523
  let names = [...getMetadataPropertyNamesForQuery(propertyName)];
5547
5524
  if (modelName) {
5548
5525
  try {
5549
- const _mod_12 = await import('./errors-a4Tj6hly.js');
5526
+ const _mod_12 = await import('./errors-rIWK7gwJ.js');
5550
5527
  const _ns_12 = _mod_12.i;
5551
5528
  const { Model } = _ns_12;
5552
- const _mod_13 = await import('./index-s73wD_LC.js');
5553
- const _ns_13 = _mod_13.bl;
5529
+ const _mod_13 = await import('./index-C0SetTd1.js');
5530
+ const _ns_13 = _mod_13.bn;
5554
5531
  const { resolveItemModelFileId } = _ns_13;
5555
5532
  // Model names are only unique per schema: use the seed's own model when it is recorded.
5556
5533
  const modelFileId = await resolveItemModelFileId({ seedLocalId, seedUid });
@@ -5786,7 +5763,7 @@ const HTML_PROP_SEED_UID_RE = /^0x[a-fA-F0-9]{64}$/;
5786
5763
  */
5787
5764
  const resolvePropertyRecordSchemaFromSchemaData = async (modelName, propertyName, modelType, schemaName) => {
5788
5765
  try {
5789
- const _mod_14 = await import('./ClientManager-Bv15o3Oz.js');
5766
+ const _mod_14 = await import('./ClientManager-B1r_8P5Z.js');
5790
5767
  const _ns_14 = _mod_14.X;
5791
5768
  const { loadAllSchemasFromDb } = _ns_14;
5792
5769
  const allSchemas = await loadAllSchemasFromDb();
@@ -5840,12 +5817,12 @@ hints = {}) => {
5840
5817
  return undefined;
5841
5818
  }
5842
5819
  try {
5843
- const _mod_15 = await import('./errors-a4Tj6hly.js');
5820
+ const _mod_15 = await import('./errors-rIWK7gwJ.js');
5844
5821
  const _ns_15 = _mod_15.i;
5845
5822
  const { Model } = _ns_15;
5846
5823
  const { modelPropertiesToObject } = await import('./model-oHA3YhOd.js');
5847
- const _mod_16 = await import('./index-s73wD_LC.js');
5848
- const _ns_16 = _mod_16.bl;
5824
+ const _mod_16 = await import('./index-C0SetTd1.js');
5825
+ const _ns_16 = _mod_16.bn;
5849
5826
  const { resolveItemModelFileId } = _ns_16;
5850
5827
  const modelFileId = await resolveItemModelFileId(hints);
5851
5828
  let model = modelFileId
@@ -6042,7 +6019,7 @@ class ItemProperty {
6042
6019
  return;
6043
6020
  }
6044
6021
  // Use dynamic import to break circular dependency
6045
- const schemaMod = await import('./index-bOwhhJJL.js');
6022
+ const schemaMod = await import('./index-Dp4uyZYx.js');
6046
6023
  const { ModelPropertyDataTypes } = schemaMod;
6047
6024
  const { context } = snapshot;
6048
6025
  const { propertyRecordSchema } = context;
@@ -6274,12 +6251,16 @@ class ItemProperty {
6274
6251
  const propertyNameWhere = propertyNames.length > 1
6275
6252
  ? or(...propertyNames.map((n) => eq(metadataLatest$1.propertyName, n)))
6276
6253
  : eq(metadataLatest$1.propertyName, propertyNames[0]);
6277
- const initialMetadata = await db
6278
- .with(metadataLatest$1)
6279
- .select()
6280
- .from(metadataLatest$1)
6281
- .where(and(propertyNameWhere, eq(metadataLatest$1.rowNum, 1)))
6282
- .limit(15);
6254
+ // In the browser the feed watch below reads the same row at once, so only Node (no change
6255
+ // feed) reads it here.
6256
+ const initialMetadata = isBrowser
6257
+ ? []
6258
+ : await db
6259
+ .with(metadataLatest$1)
6260
+ .select()
6261
+ .from(metadataLatest$1)
6262
+ .where(and(propertyNameWhere, eq(metadataLatest$1.rowNum, 1)))
6263
+ .limit(15);
6283
6264
  if (initialMetadata.length > 0) {
6284
6265
  const normalizedDataType = normalizeDataType(propertyRecordSchema?.dataType);
6285
6266
  const normalizedRefValueType = normalizeDataType(propertyRecordSchema?.refValueType);
@@ -6300,9 +6281,8 @@ class ItemProperty {
6300
6281
  localStorageDir: metaRow.localStorageDir || undefined,
6301
6282
  });
6302
6283
  }
6303
- // Only set up liveQuery subscription in browser environment
6284
+ // Only watch for changes in the browser (the change feed is browser-only)
6304
6285
  if (isBrowser) {
6305
- // Set up liveQuery to watch metadata table for this property
6306
6286
  // Use proper SQL parameter binding - ensure values are strings, not objects
6307
6287
  const resolvedSeedUid = seedUid || null;
6308
6288
  const resolvedSeedLocalId = seedLocalId || null;
@@ -6310,114 +6290,117 @@ class ItemProperty {
6310
6290
  // Build query with primitive params only (SQLocal bind rejects SQL fragment objects)
6311
6291
  // ORDER BY spells out METADATA_LATEST_FIRST_ORDER_SQL (compareMetadataRowsLatestFirst) for the same reason
6312
6292
  const [p0, p1, p2] = propertyNames;
6313
- const metadata$ = BaseDb.liveQuery((sql) => {
6293
+ const metadataQuery = (sql) => {
6314
6294
  if (resolvedSeedUid) {
6315
6295
  if (propertyNames.length === 1) {
6316
6296
  return sql `
6317
- SELECT local_id as localId, uid, property_name as propertyName, property_value as propertyValue,
6318
- version_local_id as versionLocalId, version_uid as versionUid, schema_uid as schemaUid,
6319
- ref_resolved_value as refResolvedValue, ref_resolved_display_value as refResolvedDisplayValue, local_storage_dir as localStorageDir
6320
- FROM metadata
6321
- WHERE seed_uid = ${resolvedSeedUid} AND property_name = ${p0} AND property_name IS NOT NULL
6322
- ORDER BY (revoked_at IS NOT NULL), COALESCE(attestation_created_at, created_at) DESC, local_id DESC LIMIT 1
6323
- `;
6297
+ SELECT local_id as localId, uid, property_name as propertyName, property_value as propertyValue,
6298
+ version_local_id as versionLocalId, version_uid as versionUid, schema_uid as schemaUid,
6299
+ ref_resolved_value as refResolvedValue, ref_resolved_display_value as refResolvedDisplayValue, local_storage_dir as localStorageDir
6300
+ FROM metadata
6301
+ WHERE seed_uid = ${resolvedSeedUid} AND property_name = ${p0} AND property_name IS NOT NULL
6302
+ ORDER BY (revoked_at IS NOT NULL), COALESCE(attestation_created_at, created_at) DESC, local_id DESC LIMIT 1
6303
+ `;
6324
6304
  }
6325
6305
  if (propertyNames.length === 2) {
6326
6306
  return sql `
6327
- SELECT local_id as localId, uid, property_name as propertyName, property_value as propertyValue,
6328
- version_local_id as versionLocalId, version_uid as versionUid, schema_uid as schemaUid,
6329
- ref_resolved_value as refResolvedValue, ref_resolved_display_value as refResolvedDisplayValue, local_storage_dir as localStorageDir
6330
- FROM metadata
6331
- WHERE seed_uid = ${resolvedSeedUid} AND (property_name = ${p0} OR property_name = ${p1}) AND property_name IS NOT NULL
6332
- ORDER BY (revoked_at IS NOT NULL), COALESCE(attestation_created_at, created_at) DESC, local_id DESC LIMIT 1
6333
- `;
6307
+ SELECT local_id as localId, uid, property_name as propertyName, property_value as propertyValue,
6308
+ version_local_id as versionLocalId, version_uid as versionUid, schema_uid as schemaUid,
6309
+ ref_resolved_value as refResolvedValue, ref_resolved_display_value as refResolvedDisplayValue, local_storage_dir as localStorageDir
6310
+ FROM metadata
6311
+ WHERE seed_uid = ${resolvedSeedUid} AND (property_name = ${p0} OR property_name = ${p1}) AND property_name IS NOT NULL
6312
+ ORDER BY (revoked_at IS NOT NULL), COALESCE(attestation_created_at, created_at) DESC, local_id DESC LIMIT 1
6313
+ `;
6334
6314
  }
6335
6315
  if (propertyNames.length >= 3) {
6336
6316
  return sql `
6337
- SELECT local_id as localId, uid, property_name as propertyName, property_value as propertyValue,
6338
- version_local_id as versionLocalId, version_uid as versionUid, schema_uid as schemaUid,
6339
- ref_resolved_value as refResolvedValue, ref_resolved_display_value as refResolvedDisplayValue, local_storage_dir as localStorageDir
6340
- FROM metadata
6341
- WHERE seed_uid = ${resolvedSeedUid} AND (property_name = ${p0} OR property_name = ${p1} OR property_name = ${p2}) AND property_name IS NOT NULL
6342
- ORDER BY (revoked_at IS NOT NULL), COALESCE(attestation_created_at, created_at) DESC, local_id DESC LIMIT 1
6343
- `;
6317
+ SELECT local_id as localId, uid, property_name as propertyName, property_value as propertyValue,
6318
+ version_local_id as versionLocalId, version_uid as versionUid, schema_uid as schemaUid,
6319
+ ref_resolved_value as refResolvedValue, ref_resolved_display_value as refResolvedDisplayValue, local_storage_dir as localStorageDir
6320
+ FROM metadata
6321
+ WHERE seed_uid = ${resolvedSeedUid} AND (property_name = ${p0} OR property_name = ${p1} OR property_name = ${p2}) AND property_name IS NOT NULL
6322
+ ORDER BY (revoked_at IS NOT NULL), COALESCE(attestation_created_at, created_at) DESC, local_id DESC LIMIT 1
6323
+ `;
6344
6324
  }
6345
6325
  }
6346
6326
  else if (resolvedSeedLocalId) {
6347
6327
  if (propertyNames.length === 1) {
6348
6328
  return sql `
6349
- SELECT local_id as localId, uid, property_name as propertyName, property_value as propertyValue,
6350
- version_local_id as versionLocalId, version_uid as versionUid, schema_uid as schemaUid,
6351
- ref_resolved_value as refResolvedValue, ref_resolved_display_value as refResolvedDisplayValue, local_storage_dir as localStorageDir
6352
- FROM metadata
6353
- WHERE seed_local_id = ${resolvedSeedLocalId} AND property_name = ${p0} AND property_name IS NOT NULL
6354
- ORDER BY (revoked_at IS NOT NULL), COALESCE(attestation_created_at, created_at) DESC, local_id DESC LIMIT 1
6355
- `;
6329
+ SELECT local_id as localId, uid, property_name as propertyName, property_value as propertyValue,
6330
+ version_local_id as versionLocalId, version_uid as versionUid, schema_uid as schemaUid,
6331
+ ref_resolved_value as refResolvedValue, ref_resolved_display_value as refResolvedDisplayValue, local_storage_dir as localStorageDir
6332
+ FROM metadata
6333
+ WHERE seed_local_id = ${resolvedSeedLocalId} AND property_name = ${p0} AND property_name IS NOT NULL
6334
+ ORDER BY (revoked_at IS NOT NULL), COALESCE(attestation_created_at, created_at) DESC, local_id DESC LIMIT 1
6335
+ `;
6356
6336
  }
6357
6337
  if (propertyNames.length === 2) {
6358
6338
  return sql `
6359
- SELECT local_id as localId, uid, property_name as propertyName, property_value as propertyValue,
6360
- version_local_id as versionLocalId, version_uid as versionUid, schema_uid as schemaUid,
6361
- ref_resolved_value as refResolvedValue, ref_resolved_display_value as refResolvedDisplayValue, local_storage_dir as localStorageDir
6362
- FROM metadata
6363
- WHERE seed_local_id = ${resolvedSeedLocalId} AND (property_name = ${p0} OR property_name = ${p1}) AND property_name IS NOT NULL
6364
- ORDER BY (revoked_at IS NOT NULL), COALESCE(attestation_created_at, created_at) DESC, local_id DESC LIMIT 1
6365
- `;
6339
+ SELECT local_id as localId, uid, property_name as propertyName, property_value as propertyValue,
6340
+ version_local_id as versionLocalId, version_uid as versionUid, schema_uid as schemaUid,
6341
+ ref_resolved_value as refResolvedValue, ref_resolved_display_value as refResolvedDisplayValue, local_storage_dir as localStorageDir
6342
+ FROM metadata
6343
+ WHERE seed_local_id = ${resolvedSeedLocalId} AND (property_name = ${p0} OR property_name = ${p1}) AND property_name IS NOT NULL
6344
+ ORDER BY (revoked_at IS NOT NULL), COALESCE(attestation_created_at, created_at) DESC, local_id DESC LIMIT 1
6345
+ `;
6366
6346
  }
6367
6347
  if (propertyNames.length >= 3) {
6368
6348
  return sql `
6369
- SELECT local_id as localId, uid, property_name as propertyName, property_value as propertyValue,
6370
- version_local_id as versionLocalId, version_uid as versionUid, schema_uid as schemaUid,
6371
- ref_resolved_value as refResolvedValue, ref_resolved_display_value as refResolvedDisplayValue, local_storage_dir as localStorageDir
6372
- FROM metadata
6373
- WHERE seed_local_id = ${resolvedSeedLocalId} AND (property_name = ${p0} OR property_name = ${p1} OR property_name = ${p2}) AND property_name IS NOT NULL
6374
- ORDER BY (revoked_at IS NOT NULL), COALESCE(attestation_created_at, created_at) DESC, local_id DESC LIMIT 1
6375
- `;
6349
+ SELECT local_id as localId, uid, property_name as propertyName, property_value as propertyValue,
6350
+ version_local_id as versionLocalId, version_uid as versionUid, schema_uid as schemaUid,
6351
+ ref_resolved_value as refResolvedValue, ref_resolved_display_value as refResolvedDisplayValue, local_storage_dir as localStorageDir
6352
+ FROM metadata
6353
+ WHERE seed_local_id = ${resolvedSeedLocalId} AND (property_name = ${p0} OR property_name = ${p1} OR property_name = ${p2}) AND property_name IS NOT NULL
6354
+ ORDER BY (revoked_at IS NOT NULL), COALESCE(attestation_created_at, created_at) DESC, local_id DESC LIMIT 1
6355
+ `;
6376
6356
  }
6377
6357
  }
6378
6358
  return sql `SELECT 1 WHERE 1 = 0`;
6379
- });
6359
+ };
6380
6360
  const instanceState = itemPropertyInstanceState.get(this);
6381
6361
  if (!instanceState) {
6382
6362
  logger('[ItemProperty._setupLiveQuerySubscription] Instance state not found');
6383
6363
  return;
6384
6364
  }
6385
- // Unloaded or destroyed while setup awaited: subscribing now would leak the query.
6365
+ // Unloaded or destroyed while setup awaited: watching now would leak the watch.
6386
6366
  if (isActorStopped(this._service))
6387
6367
  return;
6388
- // Subscribe to liveQuery updates
6389
- const subscription = metadata$.subscribe({
6390
- next: async (metadataRows) => {
6391
- if (metadataRows.length === 0)
6392
- return;
6393
- const metaRow = metadataRows[0];
6394
- logger(`[ItemProperty._setupLiveQuerySubscription] Metadata updated in database for propertyName: ${propertyName}`);
6395
- // While this property has a save pending, the row is older than the value in memory
6396
- // (the user may still be typing): showing it would drop keystrokes, and another tab's
6397
- // write would replace the value being typed. The save sets the context itself.
6398
- const { context } = this._service.getSnapshot();
6399
- if (context.isSaving ||
6400
- hasPendingPropertyWrite(propertyWriteKey(context.seedLocalId ?? context.seedUid, context.propertyName))) {
6401
- return;
6402
- }
6403
- // Update context with metadata changes
6404
- this._service.send({
6405
- type: 'updateContext',
6406
- propertyValue: metaRow.propertyValue,
6407
- renderValue: metaRow.propertyValue,
6408
- localId: metaRow.localId || undefined,
6409
- uid: metaRow.uid || undefined,
6410
- versionLocalId: metaRow.versionLocalId || undefined,
6411
- versionUid: metaRow.versionUid || undefined,
6412
- schemaUid: metaRow.schemaUid || undefined,
6413
- refResolvedValue: metaRow.refResolvedValue || undefined,
6414
- ...displayValueFromRow(metaRow),
6415
- localStorageDir: metaRow.localStorageDir || undefined,
6416
- });
6417
- },
6418
- error: (error) => {
6419
- logger(`[ItemProperty._setupLiveQuerySubscription] LiveQuery error: ${error}`);
6420
- },
6368
+ // Re-read on each change to this property's metadata rows (ADR 0020)
6369
+ const subscription = watchEntityRows({
6370
+ seedLocalId: resolvedSeedLocalId,
6371
+ seedUid: resolvedSeedUid,
6372
+ tables: ['metadata'],
6373
+ propertyNames,
6374
+ }, () => queryEntityRows(metadataQuery), (metadataRows) => {
6375
+ if (metadataRows.length === 0)
6376
+ return;
6377
+ const metaRow = metadataRows[0];
6378
+ logger(`[ItemProperty._setupLiveQuerySubscription] Metadata updated in database for propertyName: ${propertyName}`);
6379
+ // While this property has a save pending, the row is older than the value in memory
6380
+ // (the user may still be typing): showing it would drop keystrokes, and another tab's
6381
+ // write would replace the value being typed. The save sets the context itself.
6382
+ const { context } = this._service.getSnapshot();
6383
+ if (context.isSaving ||
6384
+ hasPendingPropertyWrite(propertyWriteKey(context.seedLocalId ?? context.seedUid, context.propertyName))) {
6385
+ return;
6386
+ }
6387
+ // Update context with metadata changes
6388
+ this._service.send({
6389
+ type: 'updateContext',
6390
+ propertyValue: metaRow.propertyValue,
6391
+ renderValue: metaRow.propertyValue,
6392
+ localId: metaRow.localId || undefined,
6393
+ uid: metaRow.uid || undefined,
6394
+ versionLocalId: metaRow.versionLocalId || undefined,
6395
+ versionUid: metaRow.versionUid || undefined,
6396
+ schemaUid: metaRow.schemaUid || undefined,
6397
+ refResolvedValue: metaRow.refResolvedValue || undefined,
6398
+ ...displayValueFromRow(metaRow),
6399
+ localStorageDir: metaRow.localStorageDir || undefined,
6400
+ });
6401
+ }, {
6402
+ immediate: true,
6403
+ onError: (error) => logger(`[ItemProperty._setupLiveQuerySubscription] Metadata read error: ${error}`),
6421
6404
  });
6422
6405
  instanceState.liveQuerySubscription = subscription;
6423
6406
  logger(`[ItemProperty._setupLiveQuerySubscription] LiveQuery subscription set up for propertyName: ${propertyName}`);
@@ -6482,8 +6465,8 @@ class ItemProperty {
6482
6465
  const ctx = this._service.getSnapshot().context;
6483
6466
  let modelFileId;
6484
6467
  try {
6485
- const _mod_17 = await import('./index-s73wD_LC.js');
6486
- const _ns_17 = _mod_17.bl;
6468
+ const _mod_17 = await import('./index-C0SetTd1.js');
6469
+ const _ns_17 = _mod_17.bn;
6487
6470
  const { resolveItemModelFileId } = _ns_17;
6488
6471
  modelFileId = await resolveItemModelFileId({
6489
6472
  modelFileId: ctx.modelFileId,
@@ -6833,8 +6816,8 @@ class ItemProperty {
6833
6816
  const propertiesData = await getItemProperties({ seedLocalId, seedUid });
6834
6817
  const instances = [];
6835
6818
  const seenNormalized = new Set();
6836
- const _mod_18 = await import('./index-s73wD_LC.js');
6837
- const _ns_18 = _mod_18.bl;
6819
+ const _mod_18 = await import('./index-C0SetTd1.js');
6820
+ const _ns_18 = _mod_18.bn;
6838
6821
  const { resolveItemModelFileId } = _ns_18;
6839
6822
  const itemModelFileId = await resolveItemModelFileId({ seedLocalId, seedUid });
6840
6823
  for (const data of propertiesData) {
@@ -6851,7 +6834,7 @@ class ItemProperty {
6851
6834
  }
6852
6835
  else if (baseName) {
6853
6836
  try {
6854
- const _mod_19 = await import('./errors-a4Tj6hly.js');
6837
+ const _mod_19 = await import('./errors-rIWK7gwJ.js');
6855
6838
  const _ns_19 = _mod_19.i;
6856
6839
  const { Model } = _ns_19;
6857
6840
  const { modelPropertiesToObject } = await import('./model-oHA3YhOd.js');
@@ -6868,7 +6851,7 @@ class ItemProperty {
6868
6851
  }
6869
6852
  if (modelName && propertyName) {
6870
6853
  try {
6871
- const _mod_20 = await import('./errors-a4Tj6hly.js');
6854
+ const _mod_20 = await import('./errors-rIWK7gwJ.js');
6872
6855
  const _ns_20 = _mod_20.i;
6873
6856
  const { Model } = _ns_20;
6874
6857
  const { modelPropertiesToObject } = await import('./model-oHA3YhOd.js');
@@ -7071,7 +7054,7 @@ class ItemProperty {
7071
7054
  const { seedLocalId, propertyName } = this._getSnapshotContext();
7072
7055
  if (!seedLocalId || !propertyName)
7073
7056
  return;
7074
- const { appendOutboxOpAndWait, markPropertyConflictsResolved, startItemOutbox, throwItemWriteError } = await import('./index-BgEwcREa.js');
7057
+ const { appendOutboxOpAndWait, markPropertyConflictsResolved, startItemOutbox, throwItemWriteError } = await import('./index-CJK3F_MK.js');
7075
7058
  if (choice === 'remote') {
7076
7059
  startItemOutbox();
7077
7060
  await appendOutboxOpAndWait({
@@ -7318,7 +7301,7 @@ class ItemProperty {
7318
7301
  if (db && seedLocalId) {
7319
7302
  // Through the outbox (ADR 0019): after the property's pending edits, which would
7320
7303
  // otherwise write its rows back
7321
- const { appendOutboxOpAndWait, startItemOutbox, throwItemWriteError } = await import('./index-BgEwcREa.js');
7304
+ const { appendOutboxOpAndWait, startItemOutbox, throwItemWriteError } = await import('./index-CJK3F_MK.js');
7322
7305
  startItemOutbox();
7323
7306
  await appendOutboxOpAndWait({
7324
7307
  seedLocalId,
@@ -7328,7 +7311,7 @@ class ItemProperty {
7328
7311
  }).catch(throwItemWriteError);
7329
7312
  }
7330
7313
  else if (db) {
7331
- const _mod_21 = await import('./index-B6hPWSM4.js');
7314
+ const _mod_21 = await import('./index-CZQrNqvq.js');
7332
7315
  const _ns_21 = _mod_21.s;
7333
7316
  const seedSchemaMod = _ns_21;
7334
7317
  const { metadata } = seedSchemaMod;
@@ -7378,7 +7361,7 @@ const createNewItem = async ({ modelName, modelFileId, ...propertyData }) => {
7378
7361
  }
7379
7362
  const seedType = easName(modelName);
7380
7363
  // Dynamic import to break circular dependency
7381
- const _mod_22 = await import('./errors-a4Tj6hly.js');
7364
+ const _mod_22 = await import('./errors-rIWK7gwJ.js');
7382
7365
  const _ns_22 = _mod_22.i;
7383
7366
  const modelMod = _ns_22;
7384
7367
  const { Model } = modelMod;
@@ -7434,7 +7417,7 @@ const createNewItem = async ({ modelName, modelFileId, ...propertyData }) => {
7434
7417
  }
7435
7418
  rows.push({ propertyName, propertyValue, propertyRecordSchema, schemaUid: schemaUids.get(propertyName) });
7436
7419
  }
7437
- const { appendOutboxOpAndWait, startItemOutbox } = await import('./index-BgEwcREa.js');
7420
+ const { appendOutboxOpAndWait, startItemOutbox } = await import('./index-CJK3F_MK.js');
7438
7421
  startItemOutbox();
7439
7422
  const fields = await timed(`${label} seed fields`, () => resolveNewSeedFields(seedType));
7440
7423
  const applied = await timed(`${label} outbox apply`, () => appendOutboxOpAndWait({
@@ -7453,7 +7436,7 @@ const createNewItem = async ({ modelName, modelFileId, ...propertyData }) => {
7453
7436
  }
7454
7437
  catch (error) {
7455
7438
  // Staged values of a create that never got appended (once appended, the op's discard does it)
7456
- const _mod_23 = await import('./ClientManager-Bv15o3Oz.js');
7439
+ const _mod_23 = await import('./ClientManager-B1r_8P5Z.js');
7457
7440
  const _ns_23 = _mod_23._;
7458
7441
  const { deleteFiles } = _ns_23;
7459
7442
  await deleteFiles(stagedPaths);
@@ -7552,7 +7535,6 @@ const updateSeedUid = async ({ seedLocalId, seedUid, publisher, attestationCreat
7552
7535
  ...(replacesSeedAttestation && { revokedAt: null, attestationRaw: null }),
7553
7536
  ...(shouldSetPublisher && { publisher: normalizedPublisher }),
7554
7537
  ...(attestationCreatedAt != null && { attestationCreatedAt }),
7555
- updatedAt: Date.now(),
7556
7538
  })
7557
7539
  .where(eq(seeds.localId, seedLocalId));
7558
7540
  // Attested version and property rows recorded before the seed uid was known (a republish records
@@ -7584,7 +7566,7 @@ const getModel = () => {
7584
7566
  // the fragile `import(...).then(n => n.X)` chunk-namespace pattern.
7585
7567
  if (!modelImportPromise) {
7586
7568
  modelImportPromise = (async () => {
7587
- const _mod_24 = await import('./errors-a4Tj6hly.js');
7569
+ const _mod_24 = await import('./errors-rIWK7gwJ.js');
7588
7570
  const _ns_24 = _mod_24.i;
7589
7571
  const mod = _ns_24;
7590
7572
  ModelClass = mod.Model;
@@ -7723,7 +7705,7 @@ class Item {
7723
7705
  * sync wrote while they were pending (ADR 0019). Each property's is also on `property.conflict`.
7724
7706
  */
7725
7707
  this.conflicts = async () => {
7726
- const _mod_25 = await import('./ClientManager-Bv15o3Oz.js');
7708
+ const _mod_25 = await import('./ClientManager-B1r_8P5Z.js');
7727
7709
  const _ns_25 = _mod_25.Z;
7728
7710
  const { getItemConflicts } = _ns_25;
7729
7711
  return getItemConflicts(this.seedLocalId);
@@ -7818,14 +7800,14 @@ class Item {
7818
7800
  };
7819
7801
  this.getPublishUploads = async (options) => {
7820
7802
  // Use dynamic import to break circular dependency
7821
- const _mod_26 = await import('./getPublishUploads-CaJHy3SL.js');
7803
+ const _mod_26 = await import('./getPublishUploads-DVsDx6Xf.js');
7822
7804
  const _ns_26 = _mod_26.o;
7823
7805
  const getPublishUploadsMod = _ns_26;
7824
7806
  const { getPublishUploads } = getPublishUploadsMod;
7825
7807
  return await getPublishUploads(this, [], undefined, options);
7826
7808
  };
7827
7809
  this.getPublishPayload = async (uploadedTransactions, options) => {
7828
- const _mod_27 = await import('./getPublishPayload-C2g5pPD2.js');
7810
+ const _mod_27 = await import('./getPublishPayload-BGl2SaGK.js');
7829
7811
  const _ns_27 = _mod_27.g;
7830
7812
  const getPublishPayloadMod = _ns_27;
7831
7813
  const { getPublishPayload } = getPublishPayloadMod;
@@ -8205,15 +8187,16 @@ class Item {
8205
8187
  * child ItemProperty actors are still hydrating. useItems / Item.all must not return that shell.
8206
8188
  */
8207
8189
  static async waitForItemInstanceReadyForRead(item, readyTimeout) {
8208
- await waitForEntityIdle(item, { timeout: readyTimeout });
8190
+ const label = `item ${item.seedLocalId ?? item.seedUid}`;
8191
+ await timedDb(`${label} ready: item idle`, () => waitForEntityIdle(item, { timeout: readyTimeout }));
8209
8192
  const svc = item.getService();
8210
8193
  try {
8211
- await waitFor(svc, (snap) => {
8194
+ await timed(`${label} ready: property instances`, () => waitFor(svc, (snap) => {
8212
8195
  if ('value' in snap && snap.value === 'error') {
8213
8196
  throw new Error('Entity failed to load');
8214
8197
  }
8215
8198
  return Item.isItemSnapshotReadyForRead(snap);
8216
- }, { timeout: readyTimeout });
8199
+ }, { timeout: readyTimeout }));
8217
8200
  }
8218
8201
  catch (e) {
8219
8202
  if (e?.message === 'Entity failed to load') {
@@ -8231,10 +8214,10 @@ class Item {
8231
8214
  if (!pis || pis.size === 0) {
8232
8215
  return;
8233
8216
  }
8234
- await Promise.all([...pis.values()].map((prop) => waitForEntityIdle(prop, {
8217
+ await timedDb(`${label} ready: ${pis.size} properties idle`, () => Promise.all([...pis.values()].map((prop) => waitForEntityIdle(prop, {
8235
8218
  timeout: readyTimeout,
8236
8219
  throwOnError: false,
8237
- })));
8220
+ }))));
8238
8221
  if (timingLogger.enabled) {
8239
8222
  const notIdle = [...pis.entries()]
8240
8223
  .filter(([, prop]) => {
@@ -8368,8 +8351,8 @@ class Item {
8368
8351
  const db = BaseDb.getAppDb();
8369
8352
  if (db && props.modelName) {
8370
8353
  // Model names are only unique per schema: resolve the exact models row from the most specific scope.
8371
- const _mod_28 = await import('./index-s73wD_LC.js');
8372
- const _ns_28 = _mod_28.bl;
8354
+ const _mod_28 = await import('./index-C0SetTd1.js');
8355
+ const _ns_28 = _mod_28.bn;
8373
8356
  const { resolveModelRecord } = _ns_28;
8374
8357
  const modelRecord = await resolveModelRecord(props.modelName, {
8375
8358
  modelFileId: props.modelFileId ?? modelInstance?.id,
@@ -8377,7 +8360,7 @@ class Item {
8377
8360
  });
8378
8361
  const modelRecords = modelRecord ? [modelRecord] : [];
8379
8362
  if (!modelRecord) {
8380
- const _mod_29 = await import('./errors-a4Tj6hly.js');
8363
+ const _mod_29 = await import('./errors-rIWK7gwJ.js');
8381
8364
  const _ns_29 = _mod_29.j;
8382
8365
  const { UnknownModelError } = _ns_29;
8383
8366
  throw new UnknownModelError(props.modelName, schemaName ?? modelInstance?.schemaName);
@@ -8388,11 +8371,11 @@ class Item {
8388
8371
  // Scope the constructor's Model lookup to this model's schema (as getItemData does on reload),
8389
8372
  // so a same-named model cached from another schema can't supply the property set.
8390
8373
  if (modelRecord && !props.schemaName) {
8391
- const _mod_30 = await import('./index-s73wD_LC.js');
8392
- const _ns_30 = _mod_30.bk;
8374
+ const _mod_30 = await import('./index-C0SetTd1.js');
8375
+ const _ns_30 = _mod_30.bm;
8393
8376
  const { modelSchemas } = _ns_30;
8394
- const _mod_31 = await import('./index-s73wD_LC.js');
8395
- const _ns_31 = _mod_31.bj;
8377
+ const _mod_31 = await import('./index-C0SetTd1.js');
8378
+ const _ns_31 = _mod_31.bl;
8396
8379
  const { schemas: schemasTable } = _ns_31;
8397
8380
  const schemaRows = await db
8398
8381
  .select({ schemaName: schemasTable.name })
@@ -8495,7 +8478,7 @@ class Item {
8495
8478
  /* best-effort cache cleanup */
8496
8479
  }
8497
8480
  try {
8498
- const { appendOutboxOpAndWait, deleteFiles, startItemOutbox } = await import('./index-BgEwcREa.js');
8481
+ const { appendOutboxOpAndWait, deleteFiles, startItemOutbox } = await import('./index-CJK3F_MK.js');
8499
8482
  startItemOutbox();
8500
8483
  const applied = await appendOutboxOpAndWait({
8501
8484
  seedLocalId,
@@ -8518,7 +8501,7 @@ class Item {
8518
8501
  for (const [propertyName, value] of pipelineValues) {
8519
8502
  const property = await this.waitForPropertyInstance(item, propertyName, timeout);
8520
8503
  if (!property) {
8521
- const _mod_32 = await import('./errors-a4Tj6hly.js');
8504
+ const _mod_32 = await import('./errors-rIWK7gwJ.js');
8522
8505
  const _ns_32 = _mod_32.j;
8523
8506
  const { ItemCreateError } = _ns_32;
8524
8507
  throw new ItemCreateError(`Item.create: property ${item.modelName}.${propertyName} did not load for item ${item.seedLocalId}; value was not saved`, { code: 'property_not_loaded', modelName: item.modelName, property: propertyName, seedLocalId: item.seedLocalId });
@@ -8530,14 +8513,14 @@ class Item {
8530
8513
  }
8531
8514
  catch (error) {
8532
8515
  if (error instanceof ItemPropertySaveValidationError) {
8533
- const _mod_33 = await import('./errors-a4Tj6hly.js');
8516
+ const _mod_33 = await import('./errors-rIWK7gwJ.js');
8534
8517
  const _ns_33 = _mod_33.j;
8535
8518
  const { ItemCreateValidationError } = _ns_33;
8536
8519
  const created = new ItemCreateValidationError(item.modelName, error.validationErrors.map((e) => ({ property: propertyName, code: e.code, message: e.message })));
8537
8520
  created.cause = error;
8538
8521
  throw created;
8539
8522
  }
8540
- const _mod_34 = await import('./errors-a4Tj6hly.js');
8523
+ const _mod_34 = await import('./errors-rIWK7gwJ.js');
8541
8524
  const _ns_34 = _mod_34.j;
8542
8525
  const { ItemCreateError } = _ns_34;
8543
8526
  throw new ItemCreateError(`Item.create: failed to save ${item.modelName}.${propertyName} for item ${item.seedLocalId}: ` +
@@ -8617,9 +8600,10 @@ class Item {
8617
8600
  * The ID can be either seedUid or seedLocalId
8618
8601
  * @param id - seedUid or seedLocalId
8619
8602
  * @param modelName - Optional model name for querying
8603
+ * @param idKind - 'localId' when the id was given as a seedLocalId: looked up as one first
8620
8604
  * @returns Item instance or undefined if not found
8621
8605
  */
8622
- static async createById(id, modelName) {
8606
+ static async createById(id, modelName, idKind) {
8623
8607
  if (!id) {
8624
8608
  return undefined;
8625
8609
  }
@@ -8628,27 +8612,21 @@ class Item {
8628
8612
  if (cached) {
8629
8613
  return cached;
8630
8614
  }
8631
- // Determine if id is seedUid or seedLocalId by querying database
8632
- // Try seedUid first, then seedLocalId
8633
- let itemData = await getItemData({
8634
- modelName,
8635
- seedUid: id,
8636
- });
8637
- if (!itemData) {
8638
- // Try as seedLocalId
8639
- itemData = await getItemData({
8640
- modelName,
8641
- seedLocalId: id,
8642
- });
8643
- }
8615
+ // Try seedUid first, then seedLocalId; local id first when the caller says it's one (a find by
8616
+ // seedLocalId), which saves the uid lookup. Either way the other is tried if the first misses.
8617
+ const byUid = () => timedDb(`load ${id} item data by uid`, () => getItemData({ modelName, seedUid: id }));
8618
+ const byLocalId = () => timedDb(`load ${id} item data by local id`, () => getItemData({ modelName, seedLocalId: id }));
8619
+ const itemData = idKind === 'localId'
8620
+ ? (await byLocalId()) ?? (await byUid())
8621
+ : (await byUid()) ?? (await byLocalId());
8644
8622
  if (!itemData) {
8645
8623
  return undefined;
8646
8624
  }
8647
8625
  // Item.create() will handle caching the new instance
8648
- return await Item.create({
8626
+ return await timedDb(`load ${id} Item.create`, () => Item.create({
8649
8627
  ...itemData,
8650
8628
  modelName,
8651
- });
8629
+ }));
8652
8630
  }
8653
8631
  static async find({ modelName, seedLocalId, seedUid, waitForReady = true, readyTimeout = DEFAULT_READY_TIMEOUT_MS, }) {
8654
8632
  if (!seedLocalId && !seedUid) {
@@ -8661,7 +8639,7 @@ class Item {
8661
8639
  }
8662
8640
  let cached = false;
8663
8641
  try {
8664
- return await timed(`find ${modelName ?? '?'} ${id}`, () => findEntity({
8642
+ return await timedDb(`find ${modelName ?? '?'} ${id}`, () => findEntity({
8665
8643
  getById: (id) => {
8666
8644
  const instance = Item.getById(id) || undefined;
8667
8645
  cached = instance !== undefined;
@@ -8669,7 +8647,7 @@ class Item {
8669
8647
  },
8670
8648
  createById: async (id) => {
8671
8649
  // Pass modelName to createById if available
8672
- return await Item.createById(id, modelName);
8650
+ return await Item.createById(id, modelName, seedLocalId ? 'localId' : undefined);
8673
8651
  },
8674
8652
  }, { id }, {
8675
8653
  waitForReady,
@@ -8710,7 +8688,7 @@ class Item {
8710
8688
  if (!appDb || Item.instanceCache.size === 0) {
8711
8689
  return;
8712
8690
  }
8713
- const _mod_35 = await import('./index-B6hPWSM4.js');
8691
+ const _mod_35 = await import('./index-CZQrNqvq.js');
8714
8692
  const _ns_35 = _mod_35.s;
8715
8693
  const { metadata } = _ns_35;
8716
8694
  const { eq, and } = await import('drizzle-orm');
@@ -8844,11 +8822,11 @@ class Item {
8844
8822
  }
8845
8823
  /** Throws ItemCreateValidationError for unknown keys and values that break their property's rules. */
8846
8824
  static async assertValidCreateValues(props, propertyNames, dataTypeByPropertyName, skipKeys) {
8847
- const _mod_36 = await import('./errors-a4Tj6hly.js');
8825
+ const _mod_36 = await import('./errors-rIWK7gwJ.js');
8848
8826
  const _ns_36 = _mod_36.j;
8849
8827
  const { ItemCreateValidationError } = _ns_36;
8850
- const { getPropertySchema } = await import('./property-mP9mOZ2L.js');
8851
- const { SchemaValidationService } = await import('./SchemaValidationService-BR2ABK2r.js');
8828
+ const { getPropertySchema } = await import('./property-pcDxNEpy.js');
8829
+ const { SchemaValidationService } = await import('./SchemaValidationService-T5mqnY8q.js');
8852
8830
  const validationService = new SchemaValidationService();
8853
8831
  const modelName = props.modelName;
8854
8832
  const known = new Set(propertyNames);
@@ -8885,7 +8863,7 @@ class Item {
8885
8863
  // Not JSON: validated as given, and rejected as a non-array
8886
8864
  }
8887
8865
  }
8888
- const { resolvePropertyValidationRules } = await import('./propertyValidationRules-DwzrYA7c.js');
8866
+ const { resolvePropertyValidationRules } = await import('./propertyValidationRules-BEjN0f3-.js');
8889
8867
  const rules = propertySchema?.validation ??
8890
8868
  (await resolvePropertyValidationRules(modelName, key, {
8891
8869
  modelFileId: props.modelFileId,
@@ -9187,6 +9165,7 @@ class Item {
9187
9165
  }
9188
9166
  setupState.subscriptionSetUp = true;
9189
9167
  logger(`[Item._setupLiveQuerySubscription] Setting up liveQuery for seedLocalId: ${seedLocalId}`);
9168
+ const timingStart = timingNow();
9190
9169
  const itemActor = this._service;
9191
9170
  const sendToItemMachine = (event) => {
9192
9171
  const status = itemActor.getSnapshot().status;
@@ -9196,7 +9175,7 @@ class Item {
9196
9175
  itemActor.send(event);
9197
9176
  };
9198
9177
  try {
9199
- const _mod_37 = await import('./index-B6hPWSM4.js');
9178
+ const _mod_37 = await import('./index-CZQrNqvq.js');
9200
9179
  const _ns_37 = _mod_37.s;
9201
9180
  const seedSchemaMod = _ns_37;
9202
9181
  const { seeds, metadata } = seedSchemaMod;
@@ -9239,7 +9218,9 @@ class Item {
9239
9218
  logger(`[Item._setupLiveQuerySubscription] No version found for seedLocalId: ${seedLocalId}`);
9240
9219
  return;
9241
9220
  }
9242
- if (currentVersionLocalId) {
9221
+ // In the browser the versions liveQuery below emits at once and its handler runs this same
9222
+ // metadata read and property setup, so only Node (no liveQuery) does it here.
9223
+ if (currentVersionLocalId && !isBrowser) {
9243
9224
  // Query initial metadata records for the latest version
9244
9225
  const initialMetadata = await db
9245
9226
  .select()
@@ -9288,174 +9269,178 @@ class Item {
9288
9269
  latestVersionUid: seedRecord.latestVersionUid,
9289
9270
  });
9290
9271
  }
9291
- // Only set up liveQuery subscription in browser environment
9272
+ // Only watch for changes in the browser (the change feed is browser-only)
9292
9273
  if (isBrowser) {
9293
- // Watch the seed row by local id: its uid changes when an unpublished item is published
9294
- // again (a new seed attestation), and a watch on the uid would stop seeing the row.
9295
- const seeds$ = BaseDb.liveQuery((sql) => sql `
9274
+ const seedsQuery = (sql) => sql `
9296
9275
  SELECT local_id as localId, uid, schema_uid as schemaUid, revoked_at as revokedAt, publisher
9297
9276
  FROM seeds
9298
9277
  WHERE local_id = ${watchedSeedLocalId}
9299
- `);
9300
- // Set up liveQuery to watch versions table for this seed
9301
- const versions$ = BaseDb.liveQuery((sql) => sql `
9278
+ `;
9279
+ const versionsQuery = (sql) => sql `
9302
9280
  SELECT local_id as localId, uid, seed_local_id as seedLocalId, revoked_at as revokedAt
9303
9281
  FROM versions
9304
9282
  WHERE seed_local_id = ${watchedSeedLocalId}
9305
9283
  ORDER BY COALESCE(attestation_created_at, created_at) DESC
9306
- `);
9284
+ `;
9307
9285
  const instanceState = itemInstanceState.get(this);
9308
9286
  if (!instanceState) {
9309
9287
  logger('[Item._setupLiveQuerySubscription] Instance state not found');
9310
9288
  return;
9311
9289
  }
9312
- // Unloaded or destroyed while setup awaited: subscribing now would leak the query.
9290
+ // Unloaded or destroyed while setup awaited: watching now would leak the watches.
9313
9291
  if (isActorStopped(this._service))
9314
9292
  return;
9315
- // Subscribe to seeds updates
9316
- const seedsSubscription = seeds$.subscribe({
9317
- next: async (seedRows) => {
9318
- if (seedRows.length === 0)
9319
- return;
9320
- const seedRow = seedRows[0];
9321
- logger(`[Item._setupLiveQuerySubscription] Seed updated in database`);
9322
- // Update context with seed data
9323
- const status = itemActor.getSnapshot().status;
9324
- if (status === 'stopped' || status === 'done')
9325
- return;
9326
- // The row still has a uid this item moved away from (a republish set the new seed uid
9327
- // on the item; its DB write has not landed): stale, so neither its uid nor its
9328
- // revocation applies. Once the row has the item's uid, the DB has caught up.
9329
- const rowUid = seedRow.uid?.toLowerCase();
9330
- const superseded = supersededSeedUids.get(this._service);
9331
- if (rowUid && superseded?.has(rowUid)) {
9332
- logger('[Item._setupLiveQuerySubscription] Ignoring seed row with a superseded uid');
9333
- return;
9334
- }
9335
- if (rowUid && rowUid === this._getSnapshotContext().seedUid?.toLowerCase()) {
9336
- superseded?.clear();
9337
- }
9338
- // A new uid written elsewhere (sync, another tab's republish) goes through the tracked
9339
- // setter so the instance cache's uid alias follows it. A row without a uid (not yet
9340
- // persisted) never clears the item's uid.
9341
- if (seedRow.uid && seedRow.uid !== this._getSnapshotContext().seedUid) {
9342
- Item.sendTrackedPropertyUpdate(this, 'seedUid', seedRow.uid);
9343
- }
9293
+ // Re-read the seed row and the versions on each change to them (ADR 0020). Both run once
9294
+ // now too, as the liveQueries' first emissions did: the versions handler adds the
9295
+ // property instances to the item's context.
9296
+ const seedsSubscription = watchEntityRows({ seedLocalId: watchedSeedLocalId, tables: ['seeds'] }, () => queryEntityRows(seedsQuery), async (seedRows) => {
9297
+ if (seedRows.length === 0)
9298
+ return;
9299
+ const seedRow = seedRows[0];
9300
+ logger(`[Item._setupLiveQuerySubscription] Seed updated in database`);
9301
+ // Update context with seed data
9302
+ const status = itemActor.getSnapshot().status;
9303
+ if (status === 'stopped' || status === 'done')
9304
+ return;
9305
+ // The row still has a uid this item moved away from (a republish set the new seed uid
9306
+ // on the item; its DB write has not landed): stale, so neither its uid nor its
9307
+ // revocation applies. Once the row has the item's uid, the DB has caught up.
9308
+ const rowUid = seedRow.uid?.toLowerCase();
9309
+ const superseded = supersededSeedUids.get(this._service);
9310
+ if (rowUid && superseded?.has(rowUid)) {
9311
+ logger('[Item._setupLiveQuerySubscription] Ignoring seed row with a superseded uid');
9312
+ return;
9313
+ }
9314
+ if (rowUid && rowUid === this._getSnapshotContext().seedUid?.toLowerCase()) {
9315
+ superseded?.clear();
9316
+ }
9317
+ // A new uid written elsewhere (sync, another tab's republish) goes through the tracked
9318
+ // setter so the instance cache's uid alias follows it. A row without a uid (not yet
9319
+ // persisted) never clears the item's uid.
9320
+ if (seedRow.uid && seedRow.uid !== this._getSnapshotContext().seedUid) {
9321
+ Item.sendTrackedPropertyUpdate(this, 'seedUid', seedRow.uid);
9322
+ }
9323
+ sendToItemMachine({
9324
+ type: 'updateContext',
9325
+ seedLocalId: seedRow.localId,
9326
+ schemaUid: seedRow.schemaUid || undefined,
9327
+ revokedAt: seedRow.revokedAt ?? undefined,
9328
+ // claimUnpublishedDrafts (here or in another tab) stamps drafts' publisher.
9329
+ ...(seedRow.publisher ? { publisher: seedRow.publisher } : {}),
9330
+ });
9331
+ }, {
9332
+ immediate: true,
9333
+ onError: (error) => logger(`[Item._setupLiveQuerySubscription] Seeds read error: ${error}`),
9334
+ });
9335
+ let versionsRuns = 0;
9336
+ const versionsSubscribedAt = timingNow();
9337
+ const versionsSubscription = watchEntityRows({ seedLocalId: watchedSeedLocalId, tables: ['versions'] }, () => queryEntityRows(versionsQuery), async (versionRows) => {
9338
+ const versionsRun = ++versionsRuns;
9339
+ const runStart = timingNow();
9340
+ if (versionsRun === 1 && timingLogger.enabled) {
9341
+ timingLogger(`item ${watchedSeedLocalId} versions read first result ${timingSince(versionsSubscribedAt)}ms after watching, ${timingSince(timingStart)}ms after watch setup began`);
9342
+ }
9343
+ if (versionRows.length === 0)
9344
+ return;
9345
+ // Get the most recent version that isn't revoked. When every version is revoked (the
9346
+ // item was unpublished) there is no latest version any more.
9347
+ const latestVersion = versionRows.find((v) => !isVersionRevoked(v.revokedAt));
9348
+ if (!latestVersion) {
9344
9349
  sendToItemMachine({
9345
9350
  type: 'updateContext',
9346
- seedLocalId: seedRow.localId,
9347
- schemaUid: seedRow.schemaUid || undefined,
9348
- revokedAt: seedRow.revokedAt ?? undefined,
9349
- // claimUnpublishedDrafts (here or in another tab) stamps drafts' publisher.
9350
- ...(seedRow.publisher ? { publisher: seedRow.publisher } : {}),
9351
+ latestVersionLocalId: undefined,
9352
+ latestVersionUid: undefined,
9351
9353
  });
9352
- },
9353
- error: (error) => {
9354
- logger(`[Item._setupLiveQuerySubscription] Seeds liveQuery error: ${error}`);
9355
- },
9356
- });
9357
- // Subscribe to versions updates
9358
- const versionsSubscription = versions$.subscribe({
9359
- next: async (versionRows) => {
9360
- if (versionRows.length === 0)
9361
- return;
9362
- // Get the most recent version that isn't revoked. When every version is revoked (the
9363
- // item was unpublished) there is no latest version any more.
9364
- const latestVersion = versionRows.find((v) => !isVersionRevoked(v.revokedAt));
9365
- if (!latestVersion) {
9366
- sendToItemMachine({
9367
- type: 'updateContext',
9368
- latestVersionLocalId: undefined,
9369
- latestVersionUid: undefined,
9370
- });
9371
- return;
9372
- }
9373
- const latestVersionLocalId = latestVersion.localId;
9374
- logger(`[Item._setupLiveQuerySubscription] Versions updated, latest version: ${latestVersionLocalId}`);
9375
- // Query metadata for the latest version
9376
- const metadataRows = await db
9377
- .select()
9378
- .from(metadata)
9379
- .where(and(eq(metadata.seedLocalId, watchedSeedLocalId), eq(metadata.versionLocalId, latestVersionLocalId)));
9380
- // CRITICAL: Create ItemProperty instances BEFORE updating context
9381
- if (metadataRows.length > 0) {
9354
+ return;
9355
+ }
9356
+ const latestVersionLocalId = latestVersion.localId;
9357
+ logger(`[Item._setupLiveQuerySubscription] Versions updated, latest version: ${latestVersionLocalId}`);
9358
+ // Query metadata for the latest version
9359
+ const metadataRows = await db
9360
+ .select()
9361
+ .from(metadata)
9362
+ .where(and(eq(metadata.seedLocalId, watchedSeedLocalId), eq(metadata.versionLocalId, latestVersionLocalId)));
9363
+ // CRITICAL: Create ItemProperty instances BEFORE updating context
9364
+ if (metadataRows.length > 0) {
9365
+ try {
9366
+ const itemPropertyMod = await Promise.resolve().then(function () { return ItemProperty$1; });
9367
+ const { ItemProperty } = itemPropertyMod;
9368
+ const itemModelName = this._service.getSnapshot().context.modelName;
9369
+ const schemaNameForModel = this._service.getSnapshot().context.schemaName;
9370
+ let propertySchemas = {};
9382
9371
  try {
9383
- const itemPropertyMod = await Promise.resolve().then(function () { return ItemProperty$1; });
9384
- const { ItemProperty } = itemPropertyMod;
9385
- const itemModelName = this._service.getSnapshot().context.modelName;
9386
- const schemaNameForModel = this._service.getSnapshot().context.schemaName;
9387
- let propertySchemas = {};
9388
- try {
9389
- if (itemModelName) {
9390
- const M = getModel();
9391
- const model = M?.resolve(itemModelName, {
9392
- modelFileId: this._service.getSnapshot().context.modelFileId,
9393
- schemaName: schemaNameForModel,
9394
- });
9395
- if (model?.properties?.length) {
9396
- propertySchemas = modelPropertiesToObject(model.properties);
9397
- }
9372
+ if (itemModelName) {
9373
+ const M = getModel();
9374
+ const model = M?.resolve(itemModelName, {
9375
+ modelFileId: this._service.getSnapshot().context.modelFileId,
9376
+ schemaName: schemaNameForModel,
9377
+ });
9378
+ if (model?.properties?.length) {
9379
+ propertySchemas = modelPropertiesToObject(model.properties);
9398
9380
  }
9399
9381
  }
9400
- catch {
9401
- // Model not loaded
9402
- }
9403
- const createPromises = metadataRows.map(async (metaRow) => {
9404
- try {
9405
- let propertyName = metaRow.propertyName;
9406
- const listSchemaKey = propertyName &&
9407
- Object.keys(propertySchemas).length > 0 &&
9408
- resolveStorageNameToSchemaName(propertySchemas, propertyName);
9409
- if (listSchemaKey) {
9410
- propertyName = listSchemaKey;
9411
- }
9412
- else {
9413
- const baseName = propertyName?.endsWith('Id') ? propertyName.slice(0, -2) : undefined;
9414
- const refSeedType = metaRow.refSeedType;
9415
- const isRefTypeFromMeta = refSeedType === 'file' || refSeedType === 'image' || refSeedType === 'relation' || refSeedType === 'html';
9416
- if (baseName && (propertySchemas[baseName] || isRefTypeFromMeta)) {
9417
- propertyName = baseName;
9418
- }
9382
+ }
9383
+ catch {
9384
+ // Model not loaded
9385
+ }
9386
+ const createPromises = metadataRows.map(async (metaRow) => {
9387
+ try {
9388
+ let propertyName = metaRow.propertyName;
9389
+ const listSchemaKey = propertyName &&
9390
+ Object.keys(propertySchemas).length > 0 &&
9391
+ resolveStorageNameToSchemaName(propertySchemas, propertyName);
9392
+ if (listSchemaKey) {
9393
+ propertyName = listSchemaKey;
9394
+ }
9395
+ else {
9396
+ const baseName = propertyName?.endsWith('Id') ? propertyName.slice(0, -2) : undefined;
9397
+ const refSeedType = metaRow.refSeedType;
9398
+ const isRefTypeFromMeta = refSeedType === 'file' || refSeedType === 'image' || refSeedType === 'relation' || refSeedType === 'html';
9399
+ if (baseName && (propertySchemas[baseName] || isRefTypeFromMeta)) {
9400
+ propertyName = baseName;
9419
9401
  }
9420
- const property = await ItemProperty.find({
9402
+ }
9403
+ const property = await ItemProperty.find({
9404
+ propertyName,
9405
+ seedLocalId: watchedSeedLocalId,
9406
+ seedUid: this._getSnapshotContext().seedUid ?? seedUid,
9407
+ modelName: itemModelName,
9408
+ hold: false,
9409
+ });
9410
+ // The item stopped while the lookup ran: it can't take its hold, so nothing would
9411
+ if (property && isActorStopped(this._service))
9412
+ ItemProperty.unloadUnheldForItem([property.seedLocalId, property.seedUid]);
9413
+ if (property) {
9414
+ sendToItemMachine({
9415
+ type: 'addPropertyInstance',
9421
9416
  propertyName,
9422
- seedLocalId: watchedSeedLocalId,
9423
- seedUid: this._getSnapshotContext().seedUid ?? seedUid,
9424
- modelName: itemModelName,
9425
- hold: false,
9417
+ propertyInstance: property,
9426
9418
  });
9427
- // The item stopped while the lookup ran: it can't take its hold, so nothing would
9428
- if (property && isActorStopped(this._service))
9429
- ItemProperty.unloadUnheldForItem([property.seedLocalId, property.seedUid]);
9430
- if (property) {
9431
- sendToItemMachine({
9432
- type: 'addPropertyInstance',
9433
- propertyName,
9434
- propertyInstance: property,
9435
- });
9436
- logger(`[Item._setupLiveQuerySubscription] Created/cached ItemProperty instance for propertyName "${propertyName}" from liveQuery`);
9437
- }
9438
- }
9439
- catch (error) {
9440
- logger(`[Item._setupLiveQuerySubscription] Error creating ItemProperty instance: ${error}`);
9419
+ logger(`[Item._setupLiveQuerySubscription] Created/cached ItemProperty instance for propertyName "${propertyName}" from liveQuery`);
9441
9420
  }
9442
- });
9443
- await Promise.all(createPromises);
9444
- }
9445
- catch (error) {
9446
- logger(`[Item._setupLiveQuerySubscription] Error importing ItemProperty or creating instances from liveQuery: ${error}`);
9421
+ }
9422
+ catch (error) {
9423
+ logger(`[Item._setupLiveQuerySubscription] Error creating ItemProperty instance: ${error}`);
9424
+ }
9425
+ });
9426
+ await Promise.all(createPromises);
9427
+ if (timingLogger.enabled) {
9428
+ timingLogger(`item ${watchedSeedLocalId} versions run ${versionsRun}: metadata read + ${metadataRows.length} ItemProperty.find ${timingSince(runStart)}ms`);
9447
9429
  }
9448
9430
  }
9449
- // Update context with latest version info
9450
- sendToItemMachine({
9451
- type: 'updateContext',
9452
- latestVersionLocalId,
9453
- latestVersionUid: latestVersion.uid || undefined,
9454
- });
9455
- },
9456
- error: (error) => {
9457
- logger(`[Item._setupLiveQuerySubscription] Versions liveQuery error: ${error}`);
9458
- },
9431
+ catch (error) {
9432
+ logger(`[Item._setupLiveQuerySubscription] Error importing ItemProperty or creating instances from liveQuery: ${error}`);
9433
+ }
9434
+ }
9435
+ // Update context with latest version info
9436
+ sendToItemMachine({
9437
+ type: 'updateContext',
9438
+ latestVersionLocalId,
9439
+ latestVersionUid: latestVersion.uid || undefined,
9440
+ });
9441
+ }, {
9442
+ immediate: true,
9443
+ onError: (error) => logger(`[Item._setupLiveQuerySubscription] Versions read error: ${error}`),
9459
9444
  });
9460
9445
  // Store combined subscription
9461
9446
  instanceState.liveQuerySubscription = {
@@ -9558,7 +9543,7 @@ class Item {
9558
9543
  return;
9559
9544
  }
9560
9545
  // Through the outbox (ADR 0019): after the item's pending edits, not before them
9561
- const { appendOutboxOpAndWait, startItemOutbox, throwItemWriteError } = await import('./index-BgEwcREa.js');
9546
+ const { appendOutboxOpAndWait, startItemOutbox, throwItemWriteError } = await import('./index-CJK3F_MK.js');
9562
9547
  startItemOutbox();
9563
9548
  await appendOutboxOpAndWait({
9564
9549
  seedLocalId: context.seedLocalId,
@@ -9586,4 +9571,4 @@ var Item$1 = /*#__PURE__*/Object.freeze({
9586
9571
  });
9587
9572
 
9588
9573
  export { getGetPublisherForNewSeeds as $, assertItemOwned as A, isItemOwned as B, waitForEntityIdle as C, compareMetadataRowsLatestFirst as D, getEasSchemaUidForModel as E, getLatestPublishedVersionRow as F, parseListPropertyValueFromStorage as G, chunkValues as H, Item as I, rowsPerInsert as J, getGetAdditionalSyncAddresses as K, selectInBatches as L, METADATA_LATEST_FIRST_ORDER_SQL as M, isVersionRevoked as N, OUTBOX_DEFER_MS as O, isActorStopped as P, DEFAULT_READY_TIMEOUT_MS as Q, createReactiveProxy as R, sameEntity as S, findEntity as T, forceRemoveFromCaches as U, runDestroyLifecycle as V, isPublishedMetadataRow as W, ClientManagerState as X, MachineIds as Y, PUBLISH_NOT_CONFIGURED_MESSAGE as Z, createNewItem as _, appendOutboxOpAndWait as a, getMetadataLatest as a0, getPublishExecutor as a1, getRevokeExecutor as a2, getUploadExecutor as a3, getVersionData$1 as a4, isLocalUnsealedDraft as a5, isSeedRowOwned as a6, localUnsealedDraftSql as a7, ownedPublisherSql as a8, ownedSeedsSql as a9, pickLatestMetadataRowPerProperty as aa, placeholderUidSql as ab, propertyMachine as ac, publisherInAddressListSql as ad, publisherIsInOwnedSet as ae, setAdditionalSyncAddresses as af, setGetPublisherForNewSeeds as ag, setPublishExecutor as ah, setRevokeExecutor as ai, setUploadExecutor as aj, ActorKeyedState as ak, clearDestroySubscriptions as al, unloadEntity as am, ClientManagerEvents as an, resolvePublisherFromSeedRow as ao, getSeedPublisher as ap, propertyNameVariants as aq, createSeed as ar, createMetadata as as, updateItemPropertyValue as at, getPropertyData$1 as au, Item$1 as av, waitForOutboxOp as b, appendOutboxOp as c, OUTBOX_MAX_ATTEMPTS as d, OUTBOX_PRUNE_AFTER_MS as e, OUTBOX_PRUNE_FAILED_AFTER_MS as f, getOutboxOps as g, OUTBOX_RETRY_DELAYS_MS as h, OutboxOpDeferredError as i, OutboxOpFailedError as j, OutboxOpRejectedError as k, OutboxOpRetryableError as l, appendOutboxOps as m, drainOutbox as n, outboxOpResult as o, getPendingSetValue as p, outboxOpValue as q, pruneOutbox as r, registerOutboxApplier as s, startOutbox as t, writeInBatches as u, getItemData as v, waitForPendingOutboxOps as w, ItemProperty as x, ItemPropertySaveValidationError as y, OwnershipError as z };
9589
- //# sourceMappingURL=Item-tX3kpbj4.js.map
9574
+ //# sourceMappingURL=Item-CjTEShfk.js.map