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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (239) hide show
  1. package/dist/{db-CQt-gcAl.js → BasePathResolver-Cm4apKRb.js} +2041 -127
  2. package/dist/BasePathResolver-Cm4apKRb.js.map +1 -0
  3. package/dist/{ClientManager-DDA9956Y.js → ClientManager-i3nJASkg.js} +664 -277
  4. package/dist/ClientManager-i3nJASkg.js.map +1 -0
  5. package/dist/{Item-D4FigtYS.js → Item-DBFchXpC.js} +495 -219
  6. package/dist/Item-DBFchXpC.js.map +1 -0
  7. package/dist/{ModelProperty-BDt6AU2h.js → ModelProperty-BS49g01Y.js} +167 -47
  8. package/dist/ModelProperty-BS49g01Y.js.map +1 -0
  9. package/dist/{Schema-B8xqLWkL.js → Schema-CpMNEnUO.js} +53 -42
  10. package/dist/Schema-CpMNEnUO.js.map +1 -0
  11. package/dist/{SchemaValidationService-BPxkfDLU.js → SchemaValidationService-DieV4KL-.js} +13 -14
  12. package/dist/{SchemaValidationService-BPxkfDLU.js.map → SchemaValidationService-DieV4KL-.js.map} +1 -1
  13. package/dist/{backfillMetadataPropertyIds-DuTPcv8t.js → backfillMetadataPropertyIds-DSoOoTnX.js} +14 -7
  14. package/dist/{backfillMetadataPropertyIds-DuTPcv8t.js.map → backfillMetadataPropertyIds-DSoOoTnX.js.map} +1 -1
  15. package/dist/{configurePlatform-YcOiDQBZ.js → configurePlatform-D0lQGAMQ.js} +8 -7
  16. package/dist/{configurePlatform-YcOiDQBZ.js.map → configurePlatform-D0lQGAMQ.js.map} +1 -1
  17. package/dist/detachRowsBeforeDelete-S0q-DJPT.js +50 -0
  18. package/dist/detachRowsBeforeDelete-S0q-DJPT.js.map +1 -0
  19. package/dist/{eas-CpOD74Ke.js → eas-6pjU-OuX.js} +9 -8
  20. package/dist/eas-6pjU-OuX.js.map +1 -0
  21. package/dist/{getItem-B_OoFkd7.js → getItem-CxBNZ-WL.js} +13 -11
  22. package/dist/{getItem-B_OoFkd7.js.map → getItem-CxBNZ-WL.js.map} +1 -1
  23. package/dist/{getPublishPayload-Xl3sRkR-.js → getPublishPayload-CTCvRUoU.js} +50 -18
  24. package/dist/getPublishPayload-CTCvRUoU.js.map +1 -0
  25. package/dist/getPublishUploads-SFHCbf_y.js +648 -0
  26. package/dist/getPublishUploads-SFHCbf_y.js.map +1 -0
  27. package/dist/{index-Xl1_4Lmb.js → index-8O3Uow-Y.js} +125 -57
  28. package/dist/index-8O3Uow-Y.js.map +1 -0
  29. package/dist/{index-CSOQFAOn.js → index-AVFTVp1m.js} +2 -2
  30. package/dist/index-AVFTVp1m.js.map +1 -0
  31. package/dist/index-Cvt5UBz4.js +30 -0
  32. package/dist/index-Cvt5UBz4.js.map +1 -0
  33. package/dist/{index.browser-CjTe0vt1.js → index.browser-DBhxRoe8.js} +554 -165
  34. package/dist/index.browser-DBhxRoe8.js.map +1 -0
  35. package/dist/{index.node-Cfa7npS6.js → index.node-CJhlcNHM.js} +25 -13
  36. package/dist/index.node-CJhlcNHM.js.map +1 -0
  37. package/dist/main.js +30 -47
  38. package/dist/main.js.map +1 -1
  39. package/dist/mimeTypes-DHAHC4eZ.js +204 -0
  40. package/dist/mimeTypes-DHAHC4eZ.js.map +1 -0
  41. package/dist/node.js +19 -21
  42. package/dist/node.js.map +1 -1
  43. package/dist/platform.browser.js +13 -11
  44. package/dist/platform.browser.js.map +1 -1
  45. package/dist/platform.node.js +18 -5
  46. package/dist/platform.node.js.map +1 -1
  47. package/dist/{property-BrXkY1Rg.js → property-DwPD283A.js} +14 -12
  48. package/dist/property-DwPD283A.js.map +1 -0
  49. package/dist/{publishDraftGraph-X0Wr9txE.js → publishDraftGraph-BOn3_Occ.js} +6 -9
  50. package/dist/{publishDraftGraph-X0Wr9txE.js.map → publishDraftGraph-BOn3_Occ.js.map} +1 -1
  51. package/dist/{resetAmbiguousLegacyItemData-Ci6PM_vC.js → resetAmbiguousLegacyItemData-BkYmBeJc.js} +14 -3
  52. package/dist/{resetAmbiguousLegacyItemData-Ci6PM_vC.js.map → resetAmbiguousLegacyItemData-BkYmBeJc.js.map} +1 -1
  53. package/dist/{resolveModelForSyncedSeed-DFVdnYq8.js → resolveModelForSyncedSeed-BL24nLa7.js} +2 -2
  54. package/dist/{resolveModelForSyncedSeed-DFVdnYq8.js.map → resolveModelForSyncedSeed-BL24nLa7.js.map} +1 -1
  55. package/dist/src/Item/Item.d.ts +21 -3
  56. package/dist/src/Item/Item.d.ts.map +1 -1
  57. package/dist/src/Item/service/actors/runPublish.d.ts +11 -2
  58. package/dist/src/Item/service/actors/runPublish.d.ts.map +1 -1
  59. package/dist/src/Item/service/itemMachineSingle.d.ts +12 -2
  60. package/dist/src/Item/service/itemMachineSingle.d.ts.map +1 -1
  61. package/dist/src/ItemProperty/ItemProperty.d.ts +5 -3
  62. package/dist/src/ItemProperty/ItemProperty.d.ts.map +1 -1
  63. package/dist/src/ItemProperty/service/actors/saveValueToDb/analyzeInput.d.ts.map +1 -1
  64. package/dist/src/ItemProperty/service/actors/saveValueToDb/saveItemStorage.d.ts.map +1 -1
  65. package/dist/src/ItemProperty/service/propertyMachine.d.ts.map +1 -1
  66. package/dist/src/Model/Model.d.ts +10 -4
  67. package/dist/src/Model/Model.d.ts.map +1 -1
  68. package/dist/src/Model/index.d.ts +2 -2
  69. package/dist/src/ModelProperty/ModelProperty.d.ts +10 -2
  70. package/dist/src/ModelProperty/ModelProperty.d.ts.map +1 -1
  71. package/dist/src/ModelProperty/service/modelPropertyMachine.d.ts +3 -0
  72. package/dist/src/ModelProperty/service/modelPropertyMachine.d.ts.map +1 -1
  73. package/dist/src/Schema/Schema.d.ts +2 -2
  74. package/dist/src/Schema/Schema.d.ts.map +1 -1
  75. package/dist/src/Schema/index.d.ts +0 -1
  76. package/dist/src/Schema/index.d.ts.map +1 -1
  77. package/dist/src/browser/helpers/FileManager.d.ts +4 -1
  78. package/dist/src/browser/helpers/FileManager.d.ts.map +1 -1
  79. package/dist/src/browser/helpers/tolerantWebAccess.d.ts +79 -4
  80. package/dist/src/browser/helpers/tolerantWebAccess.d.ts.map +1 -1
  81. package/dist/src/browser/workers/FileDownloader.d.ts +19 -4
  82. package/dist/src/browser/workers/FileDownloader.d.ts.map +1 -1
  83. package/dist/src/browser/workers/filesDownload.d.ts.map +1 -1
  84. package/dist/src/client/ClientManager.d.ts +30 -11
  85. package/dist/src/client/ClientManager.d.ts.map +1 -1
  86. package/dist/src/client/actors/platformClassesInit.d.ts +6 -0
  87. package/dist/src/client/actors/platformClassesInit.d.ts.map +1 -1
  88. package/dist/src/client/actors/processSchemaFiles.d.ts.map +1 -1
  89. package/dist/src/client/actors/saveConfig.d.ts +13 -6
  90. package/dist/src/client/actors/saveConfig.d.ts.map +1 -1
  91. package/dist/src/client/clientManagerMachine.d.ts.map +1 -1
  92. package/dist/src/db/migrateLegacyItemStorageRows.d.ts +57 -0
  93. package/dist/src/db/migrateLegacyItemStorageRows.d.ts.map +1 -0
  94. package/dist/src/db/read/getCompositeChildPaths.d.ts +13 -0
  95. package/dist/src/db/read/getCompositeChildPaths.d.ts.map +1 -0
  96. package/dist/src/db/read/getItems.d.ts.map +1 -1
  97. package/dist/src/db/read/getPublishPayload.d.ts +1 -1
  98. package/dist/src/db/read/getPublishPayload.d.ts.map +1 -1
  99. package/dist/src/db/read/getPublishUploads.d.ts +32 -3
  100. package/dist/src/db/read/getPublishUploads.d.ts.map +1 -1
  101. package/dist/src/db/read/summarizePublishWork.d.ts.map +1 -1
  102. package/dist/src/db/write/claimUnpublishedDrafts.d.ts +2 -0
  103. package/dist/src/db/write/claimUnpublishedDrafts.d.ts.map +1 -1
  104. package/dist/src/db/write/convertVerbatimItemStorageRow.d.ts +44 -0
  105. package/dist/src/db/write/convertVerbatimItemStorageRow.d.ts.map +1 -0
  106. package/dist/src/db/write/createNewItem.d.ts.map +1 -1
  107. package/dist/src/eventBus.d.ts +5 -0
  108. package/dist/src/eventBus.d.ts.map +1 -1
  109. package/dist/src/events/files/download.d.ts.map +1 -1
  110. package/dist/src/helpers/FileManager/BaseFileManager.d.ts +3 -3
  111. package/dist/src/helpers/FileManager/BaseFileManager.d.ts.map +1 -1
  112. package/dist/src/helpers/FileManager/IFileManager.d.ts +25 -1
  113. package/dist/src/helpers/FileManager/IFileManager.d.ts.map +1 -1
  114. package/dist/src/helpers/arweaveContentTags.d.ts +33 -0
  115. package/dist/src/helpers/arweaveContentTags.d.ts.map +1 -0
  116. package/dist/src/helpers/cachedPropertyRefresh.d.ts +12 -0
  117. package/dist/src/helpers/cachedPropertyRefresh.d.ts.map +1 -0
  118. package/dist/src/helpers/compositeUpload.d.ts +28 -0
  119. package/dist/src/helpers/compositeUpload.d.ts.map +1 -0
  120. package/dist/src/helpers/db.d.ts +3 -0
  121. package/dist/src/helpers/db.d.ts.map +1 -1
  122. package/dist/src/helpers/easSdk.d.ts +16 -0
  123. package/dist/src/helpers/easSdk.d.ts.map +1 -0
  124. package/dist/src/helpers/entity/detachRowsBeforeDelete.d.ts +16 -0
  125. package/dist/src/helpers/entity/detachRowsBeforeDelete.d.ts.map +1 -0
  126. package/dist/src/helpers/entity/entityDestroy.d.ts +2 -0
  127. package/dist/src/helpers/entity/entityDestroy.d.ts.map +1 -1
  128. package/dist/src/helpers/itemStorageFile.d.ts +57 -0
  129. package/dist/src/helpers/itemStorageFile.d.ts.map +1 -0
  130. package/dist/src/helpers/mapWithConcurrency.d.ts +7 -0
  131. package/dist/src/helpers/mapWithConcurrency.d.ts.map +1 -0
  132. package/dist/src/helpers/mimeTypes.d.ts +43 -0
  133. package/dist/src/helpers/mimeTypes.d.ts.map +1 -0
  134. package/dist/src/helpers/ownership.d.ts +28 -4
  135. package/dist/src/helpers/ownership.d.ts.map +1 -1
  136. package/dist/src/helpers/property/index.d.ts +37 -51
  137. package/dist/src/helpers/property/index.d.ts.map +1 -1
  138. package/dist/src/helpers/publishConfig.d.ts +27 -8
  139. package/dist/src/helpers/publishConfig.d.ts.map +1 -1
  140. package/dist/src/helpers/storageDir.d.ts +16 -0
  141. package/dist/src/helpers/storageDir.d.ts.map +1 -0
  142. package/dist/src/helpers/tabCoordinator.d.ts +5 -1
  143. package/dist/src/helpers/tabCoordinator.d.ts.map +1 -1
  144. package/dist/src/helpers/tabEvents.d.ts +23 -2
  145. package/dist/src/helpers/tabEvents.d.ts.map +1 -1
  146. package/dist/src/helpers/updateSchema.d.ts +5 -0
  147. package/dist/src/helpers/updateSchema.d.ts.map +1 -1
  148. package/dist/src/helpers/waitForEntityIdle.d.ts +5 -0
  149. package/dist/src/helpers/waitForEntityIdle.d.ts.map +1 -1
  150. package/dist/src/imports/json.d.ts +9 -0
  151. package/dist/src/imports/json.d.ts.map +1 -1
  152. package/dist/src/index.d.ts +11 -7
  153. package/dist/src/index.d.ts.map +1 -1
  154. package/dist/src/interfaces/IItem.d.ts +7 -1
  155. package/dist/src/interfaces/IItem.d.ts.map +1 -1
  156. package/dist/src/node/db/Db.d.ts.map +1 -1
  157. package/dist/src/node/helpers/PathResolver.d.ts.map +1 -1
  158. package/dist/src/node/index.d.ts +8 -1
  159. package/dist/src/node/index.d.ts.map +1 -1
  160. package/dist/src/platform/index.browser.d.ts +2 -0
  161. package/dist/src/platform/index.browser.d.ts.map +1 -1
  162. package/dist/src/platform/index.node.d.ts +2 -0
  163. package/dist/src/platform/index.node.d.ts.map +1 -1
  164. package/dist/src/types/fileManager.d.ts +3 -14
  165. package/dist/src/types/fileManager.d.ts.map +1 -1
  166. package/dist/src/types/index.d.ts +12 -1
  167. package/dist/src/types/index.d.ts.map +1 -1
  168. package/dist/src/types/machines.d.ts +2 -0
  169. package/dist/src/types/machines.d.ts.map +1 -1
  170. package/dist/src/types/property.d.ts +8 -0
  171. package/dist/src/types/property.d.ts.map +1 -1
  172. package/dist/src/types/publish.d.ts +14 -0
  173. package/dist/src/types/publish.d.ts.map +1 -1
  174. package/dist/{syncDbWithEas-BU-jZ5bJ.js → syncDbWithEas-Bv2Fe38J.js} +17 -17
  175. package/dist/{syncDbWithEas-BU-jZ5bJ.js.map → syncDbWithEas-Bv2Fe38J.js.map} +1 -1
  176. package/dist/tabEvents-9s2WCYw-.js +335 -0
  177. package/dist/tabEvents-9s2WCYw-.js.map +1 -0
  178. package/dist/tolerantWebAccess-iUu80pAP.js +551 -0
  179. package/dist/tolerantWebAccess-iUu80pAP.js.map +1 -0
  180. package/dist/{updateSeedRevokedAt-iLpzae1i.js → updateSeedRevokedAt-zBfi931j.js} +3 -3
  181. package/dist/{updateSeedRevokedAt-iLpzae1i.js.map → updateSeedRevokedAt-zBfi931j.js.map} +1 -1
  182. package/package.json +11 -12
  183. package/src/node/easLodashRegister.js +4 -0
  184. package/dist/BasePathResolver-BdxCSIzn.js +0 -679
  185. package/dist/BasePathResolver-BdxCSIzn.js.map +0 -1
  186. package/dist/ClientManager-DDA9956Y.js.map +0 -1
  187. package/dist/Item-D4FigtYS.js.map +0 -1
  188. package/dist/ModelProperty-BDt6AU2h.js.map +0 -1
  189. package/dist/Schema-B8xqLWkL.js.map +0 -1
  190. package/dist/cjs/ModelProperty-B-cZm1yU.js +0 -1977
  191. package/dist/cjs/ModelProperty-B-cZm1yU.js.map +0 -1
  192. package/dist/cjs/Schema-STP972Xw.js +0 -5256
  193. package/dist/cjs/Schema-STP972Xw.js.map +0 -1
  194. package/dist/cjs/SchemaValidationService-CKNW1bKg.js +0 -778
  195. package/dist/cjs/SchemaValidationService-CKNW1bKg.js.map +0 -1
  196. package/dist/cjs/backfillMetadataPropertyIds-CP3y1skt.js +0 -89
  197. package/dist/cjs/backfillMetadataPropertyIds-CP3y1skt.js.map +0 -1
  198. package/dist/cjs/eas-CAnUC4wd.js +0 -138
  199. package/dist/cjs/eas-CAnUC4wd.js.map +0 -1
  200. package/dist/cjs/getItem-CWgb3e9G.js +0 -58
  201. package/dist/cjs/getItem-CWgb3e9G.js.map +0 -1
  202. package/dist/cjs/getPublishPayload-BsZWiJ03.js +0 -1603
  203. package/dist/cjs/getPublishPayload-BsZWiJ03.js.map +0 -1
  204. package/dist/cjs/getPublishUploads-BQr8aMVP.js +0 -495
  205. package/dist/cjs/getPublishUploads-BQr8aMVP.js.map +0 -1
  206. package/dist/cjs/index-nA5PxBSs.js +0 -70
  207. package/dist/cjs/index-nA5PxBSs.js.map +0 -1
  208. package/dist/cjs/index-usKaANAq.js +0 -22171
  209. package/dist/cjs/index-usKaANAq.js.map +0 -1
  210. package/dist/cjs/index.browser-BSf8HpnU.js +0 -22
  211. package/dist/cjs/index.browser-BSf8HpnU.js.map +0 -1
  212. package/dist/cjs/property-xMwPhQ5N.js +0 -327
  213. package/dist/cjs/property-xMwPhQ5N.js.map +0 -1
  214. package/dist/cjs/publishDraftGraph-BRWlR1KO.js +0 -403
  215. package/dist/cjs/publishDraftGraph-BRWlR1KO.js.map +0 -1
  216. package/dist/cjs/resetAmbiguousLegacyItemData-8nfkj9rz.js +0 -116
  217. package/dist/cjs/resetAmbiguousLegacyItemData-8nfkj9rz.js.map +0 -1
  218. package/dist/cjs/resolveModelForSyncedSeed-kYRuDWYw.js +0 -49
  219. package/dist/cjs/resolveModelForSyncedSeed-kYRuDWYw.js.map +0 -1
  220. package/dist/cjs/syncDbWithEas-DqRhV8o2.js +0 -886
  221. package/dist/cjs/syncDbWithEas-DqRhV8o2.js.map +0 -1
  222. package/dist/db-CQt-gcAl.js.map +0 -1
  223. package/dist/eas-CpOD74Ke.js.map +0 -1
  224. package/dist/getPublishPayload-Xl3sRkR-.js.map +0 -1
  225. package/dist/getPublishUploads-DHP01KgU.js +0 -484
  226. package/dist/getPublishUploads-DHP01KgU.js.map +0 -1
  227. package/dist/index-BGt4_oPO.js +0 -31
  228. package/dist/index-BGt4_oPO.js.map +0 -1
  229. package/dist/index-CSOQFAOn.js.map +0 -1
  230. package/dist/index-Xl1_4Lmb.js.map +0 -1
  231. package/dist/index.browser-CjTe0vt1.js.map +0 -1
  232. package/dist/index.node-Cfa7npS6.js.map +0 -1
  233. package/dist/main.cjs +0 -84
  234. package/dist/main.cjs.map +0 -1
  235. package/dist/property-BrXkY1Rg.js.map +0 -1
  236. package/dist/tabEvents-BZJMY5uK.js +0 -1344
  237. package/dist/tabEvents-BZJMY5uK.js.map +0 -1
  238. package/dist/tolerantWebAccess-BZ2RA_mb.js +0 -160
  239. package/dist/tolerantWebAccess-BZ2RA_mb.js.map +0 -1
@@ -1,17 +1,16 @@
1
+ import { startCase, isEqual } from 'lodash-es';
2
+ import { E as BaseDb, l as easSyncProcesses, G as eventEmitter, a8 as isNode, ah as isBrowser, I as BasePathResolver, aA as normalizeAddressConfig, h as appState, aL as downloadAllFilesRequestHandler, aM as downloadAllFilesBinaryRequestHandler, J as BaseFileManager, H as toSnakeCase, s as models$1, r as modelUids, A as seeds, aB as normalizeAddressList, z as schemas, aK as loadModelsFromDbForSchema, aI as addSchemaToDb, aF as isInternalSchema, aN as INTERNAL_SCHEMA_IDS, $ as generateId, aO as linkModelToSchema, n as normalizeDataType, aq as SEED_PROTOCOL_SCHEMA_NAME, q as modelSchemas, m as metadata$1, u as properties, L as resolveItemModelFileId, C as versions, o as htmlEmbeddedImageCoPublish, j as arweaveL1FinalizeJobs, y as publishProcesses, X as normalizePublisher, aP as getWatchedAddressesFromDb, aQ as getOwnedAddressesFromDb, aR as CLIENT_NOT_INITIALIZED } from './BasePathResolver-Cm4apKRb.js';
1
3
  import debug from 'debug';
2
4
  import { createActor, setup, assign, fromPromise, fromCallback, waitFor } from 'xstate';
3
- import { m as eventEmitter, C as normalizeAddressConfig, E as normalizeAddressList, S as loadModelsFromDbForSchema, O as addSchemaToDb, n as normalizeDataType, U as linkModelToSchema, s as normalizePublisher, V as getWatchedAddressesFromDb, W as getOwnedAddressesFromDb } from './db-CQt-gcAl.js';
4
- import { u as MachineIds, V as ClientManagerEvents, C as ClientManagerState, W as resolvePublisherFromSeedRow, F as isLocalUnsealedDraft, I as Item } from './Item-D4FigtYS.js';
5
- import { a as BaseDb, e as easSyncProcesses, t as BasePathResolver, b as appState, B as BaseFileManager, j as models$1, i as modelUids, r as seeds, s as schemas, K as isInternalSchema, L as INTERNAL_SCHEMA_IDS, F as SEED_PROTOCOL_SCHEMA_NAME, g as modelSchemas, m as metadata$1, v as versions, h as htmlEmbeddedImageCoPublish, c as arweaveL1FinalizeJobs, q as publishProcesses, M as CLIENT_NOT_INITIALIZED } from './BasePathResolver-BdxCSIzn.js';
6
- import { eq, inArray, and, isNotNull, ne, desc, countDistinct, like, or, isNull } from 'drizzle-orm';
7
- import { q as withDbTabLock, k as isLeaderTab, x as postTabMessage, y as onTabMessage, w as whenLeaderTab, z as listenForOtherTabsEvents, B as isNode, C as isBrowser, D as startTabCoordination, E as downloadAllFilesRequestHandler, G as downloadAllFilesBinaryRequestHandler, t as toSnakeCase, v as withSeedDbLock, b as generateId, p as parseAddressesPersistedPayload, e as emitAcrossTabs, A as ADDRESSES_PERSISTED_EVENT, L as LOCAL_COPIES_REMOVED_EVENT } from './tabEvents-BZJMY5uK.js';
5
+ import { x as MachineIds, a2 as ClientManagerEvents, a3 as withLockedItemStorageRow, a4 as getItemStorageFilePath, a5 as writeItemStorageFile, c as compareMetadataRowsLatestFirst, C as ClientManagerState, a6 as resolvePublisherFromSeedRow, J as isLocalUnsealedDraft, I as Item } from './Item-DBFchXpC.js';
6
+ import { eq, inArray, and, isNotNull, ne, desc, countDistinct, isNull, or, like } from 'drizzle-orm';
7
+ import { a as withDbTabLock, i as isLeaderTab, c as postTabMessage, o as onTabMessage, w as whenLeaderTab, l as listenForOtherTabsEvents, s as startTabCoordination, b as withSeedDbLock, p as parseAddressesPersistedPayload, e as emitAcrossTabs, A as ADDRESSES_PERSISTED_EVENT, L as LOCAL_COPIES_REMOVED_EVENT } from './tabEvents-9s2WCYw-.js';
8
8
  import { seedGatewayConfigFromSeedConfig, setPreferredArweaveReadBaseUrls, resolveSeedGatewayEndpoints, setResolvedSeedGatewayEndpoints, BaseArweaveClient, ensureReadGatewaySelected, DEFAULT_ARWEAVE_HOST } from '@seedprotocol/arweave';
9
9
  import { configureEasReadChain, BaseQueryClient, BaseEasClient, GET_SCHEMAS, whenEasReadChainSettled, getEasReadChainId, DEFAULT_EAS_CHAIN_ID, isEasReadChainConfigured, isValidEasAttestationUid } from '@seedprotocol/eas';
10
10
  import 'pluralize';
11
11
  import { sha3_256 } from '@noble/hashes/sha3';
12
- import { bytesToHex, utf8ToBytes } from '@noble/hashes/utils';
12
+ import { utf8ToBytes, bytesToHex } from '@noble/hashes/utils';
13
13
  import { clearLocalQuerySource, registerLocalQuerySource, getSeed } from '@seedprotocol/query';
14
- import { startCase } from 'lodash-es';
15
14
 
16
15
  let writeTail = Promise.resolve();
17
16
  function enqueueEasSyncDbWrite(fn) {
@@ -109,7 +108,7 @@ const runEasSync = fromPromise(async ({ input, }) => {
109
108
  requestPayload: input.requestPayload,
110
109
  persistedSnapshot: input.runningSnapshot,
111
110
  });
112
- const { runSyncFromEas } = await import('./syncDbWithEas-BU-jZ5bJ.js');
111
+ const { runSyncFromEas } = await import('./syncDbWithEas-Bv2Fe38J.js');
113
112
  try {
114
113
  // Sync checks for rows and then inserts the rest (no unique index on uids), so syncs in
115
114
  // different tabs take turns. A sync can run for minutes, so wait without a timeout.
@@ -285,7 +284,7 @@ function newCorrelationId() {
285
284
  return `${Date.now()}-${Math.random().toString(36).slice(2)}`;
286
285
  }
287
286
  /** Requests deferred in this tab until it leads, by source; each runs once on takeover. */
288
- const deferredUntilLeader = new Set();
287
+ const deferredUntilLeader$1 = new Set();
289
288
  /**
290
289
  * Automatic syncs run in the leader tab only (docs/MULTI_TAB.md). A tab that skips one runs it if
291
290
  * it later becomes leader, so closing the leader doesn't lose the catch-up sync.
@@ -296,11 +295,11 @@ function runInLeaderTab(source, request) {
296
295
  return;
297
296
  }
298
297
  log(`${source} sync skipped: another tab leads`);
299
- if (deferredUntilLeader.has(source))
298
+ if (deferredUntilLeader$1.has(source))
300
299
  return;
301
- deferredUntilLeader.add(source);
300
+ deferredUntilLeader$1.add(source);
302
301
  void whenLeaderTab().then(() => {
303
- deferredUntilLeader.delete(source);
302
+ deferredUntilLeader$1.delete(source);
304
303
  request();
305
304
  });
306
305
  }
@@ -374,10 +373,10 @@ var easSyncManager = /*#__PURE__*/Object.freeze({
374
373
  startEasSyncActor: startEasSyncActor
375
374
  });
376
375
 
377
- const logger$b = debug('seedSdk:services:events');
376
+ const logger$c = debug('seedSdk:services:events');
378
377
  const handleServiceSaveState = (event) => {
379
378
  const { state, serviceId } = event;
380
- logger$b(`[browser] [service.saveState.request] serviceId: ${serviceId}`);
379
+ logger$c(`[browser] [service.saveState.request] serviceId: ${serviceId}`);
381
380
  // TODO: This is called from Node as well. Do we need it? If so, need to generalize this to all platforms.
382
381
  // localStorage.setItem(`seed_sdk_service_${serviceId}`, JSON.stringify(state))
383
382
  };
@@ -428,9 +427,18 @@ function normalizeSeedConfigEndpoints(config) {
428
427
  return { ...config, endpoints: next };
429
428
  }
430
429
 
431
- const logger$a = debug('seedSdk:ClientManager:initialize');
430
+ const logger$b = debug('seedSdk:ClientManager:initialize');
431
+ /**
432
+ * Whether a relative filesDir already names the .seed directory or a path inside
433
+ * it ('.seed', '.seed/files', './.seed/files'). '.seed-alt/x' is not: it is
434
+ * resolved under .seed like any other relative path.
435
+ */
436
+ function isUnderDotSeed(relativePath) {
437
+ const firstSegment = relativePath.split(/[\\/]+/).find((segment) => segment !== '' && segment !== '.');
438
+ return firstSegment === '.seed';
439
+ }
432
440
  const platformClassesInit = fromCallback(({ sendBack, input: { context, event } }) => {
433
- logger$a('initialize from ClientManager');
441
+ logger$b('initialize from ClientManager');
434
442
  const { isInitialized } = context;
435
443
  if (!event || !('options' in event)) {
436
444
  throw new Error('Initialize event must include options');
@@ -463,7 +471,7 @@ const platformClassesInit = fromCallback(({ sendBack, input: { context, event }
463
471
  }
464
472
  // Prefer the condition-resolved factory when available; fall back to explicit
465
473
  // platform imports so source/vitest resolution stays reliable.
466
- const { configurePlatform } = await import('./configurePlatform-YcOiDQBZ.js');
474
+ const { configurePlatform } = await import('./configurePlatform-D0lQGAMQ.js');
467
475
  if (isBrowser()) {
468
476
  const { createPlatformServices } = await import('./platform.browser.js');
469
477
  configurePlatform(createPlatformServices());
@@ -526,8 +534,8 @@ const platformClassesInit = fromCallback(({ sendBack, input: { context, event }
526
534
  normalizedFilesDir = path.join(dotSeedDir, dirName);
527
535
  }
528
536
  else if (!path.isAbsolute(normalizedFilesDir)) {
529
- // If it's a relative path, check if it already starts with .seed
530
- if (normalizedFilesDir.startsWith('.seed') || normalizedFilesDir.startsWith('.seed/')) {
537
+ // If it's a relative path, check if it is already under .seed
538
+ if (isUnderDotSeed(normalizedFilesDir)) {
531
539
  // Already relative to project root, resolve it
532
540
  normalizedFilesDir = path.resolve(normalizedFilesDir);
533
541
  }
@@ -550,6 +558,7 @@ const platformClassesInit = fromCallback(({ sendBack, input: { context, event }
550
558
  gatewaySidecarPort: gatewayConfig.hyper?.localSidecarPort,
551
559
  gatewayProxyBaseUrl: resolvedGateway.proxyBaseUrl ?? gatewayConfig.proxyBaseUrl,
552
560
  addresses: normalizedAddresses.owned,
561
+ addressesProvided: addresses !== undefined,
553
562
  ownedAddresses: normalizedAddresses.owned,
554
563
  watchedAddresses: normalizedAddresses.watched,
555
564
  filesDir: normalizedFilesDir,
@@ -602,7 +611,7 @@ const platformClassesInit = fromCallback(({ sendBack, input: { context, event }
602
611
  };
603
612
  });
604
613
 
605
- const logger$9 = debug('seedSdk:client:writeToDb');
614
+ const logger$a = debug('seedSdk:client:writeToDb');
606
615
  const saveAppState = fromCallback(({ sendBack, input: { key, value } }) => {
607
616
  const _saveAppState = async () => {
608
617
  try {
@@ -610,7 +619,7 @@ const saveAppState = fromCallback(({ sendBack, input: { key, value } }) => {
610
619
  if (!appDb) {
611
620
  // In test environments, continue anyway
612
621
  if (process.env.NODE_ENV === 'test' || process.env.IS_SEED_DEV) {
613
- logger$9('[client/actors] [saveAppState] App DB not found, but continuing in test environment');
622
+ logger$a('[client/actors] [saveAppState] App DB not found, but continuing in test environment');
614
623
  return;
615
624
  }
616
625
  throw new Error('App DB not found');
@@ -626,13 +635,13 @@ const saveAppState = fromCallback(({ sendBack, input: { key, value } }) => {
626
635
  value: JSON.stringify(value),
627
636
  },
628
637
  });
629
- logger$9('result', result);
638
+ logger$a('result', result);
630
639
  }
631
640
  catch (error) {
632
- logger$9('[client/actors] [saveAppState] Error saving app state:', error);
641
+ logger$a('[client/actors] [saveAppState] Error saving app state:', error);
633
642
  // In test environments, continue anyway
634
643
  if (process.env.NODE_ENV === 'test' || process.env.IS_SEED_DEV) {
635
- logger$9('[client/actors] [saveAppState] Continuing despite error in test environment');
644
+ logger$a('[client/actors] [saveAppState] Continuing despite error in test environment');
636
645
  return;
637
646
  }
638
647
  throw error;
@@ -647,10 +656,10 @@ const saveAppState = fromCallback(({ sendBack, input: { key, value } }) => {
647
656
  });
648
657
  })
649
658
  .catch((error) => {
650
- logger$9('[client/actors] [saveAppState] Error in promise chain:', error);
659
+ logger$a('[client/actors] [saveAppState] Error in promise chain:', error);
651
660
  // In test environments, still send success to allow state machine to progress
652
661
  if (process.env.NODE_ENV === 'test' || process.env.IS_SEED_DEV) {
653
- logger$9('[client/actors] [saveAppState] Sending success despite error in test environment');
662
+ logger$a('[client/actors] [saveAppState] Sending success despite error in test environment');
654
663
  sendBack({
655
664
  type: 'saveAppStateSuccess',
656
665
  key,
@@ -720,7 +729,7 @@ const fileSystemInit = fromCallback(({ sendBack, input: { context }, }) => {
720
729
  };
721
730
  });
722
731
 
723
- const logger$8 = debug('seedSdk:client:actors:dbInit');
732
+ const logger$9 = debug('seedSdk:client:actors:dbInit');
724
733
  const dbInit = fromCallback(({ sendBack, input: { context } }) => {
725
734
  const _dbInit = async () => {
726
735
  const { filesDir } = context;
@@ -734,14 +743,14 @@ const dbInit = fromCallback(({ sendBack, input: { context } }) => {
734
743
  if (!appDb) {
735
744
  throw new Error('Database not available after preparation');
736
745
  }
737
- logger$8('[client/actors] [dbInit] Database prepared and ready');
746
+ logger$9('[client/actors] [dbInit] Database prepared and ready');
738
747
  };
739
748
  _dbInit()
740
749
  .then(() => {
741
750
  sendBack({ type: ClientManagerEvents.DB_READY });
742
751
  })
743
752
  .catch((error) => {
744
- logger$8('Error in dbInit:', error);
753
+ logger$9('Error in dbInit:', error);
745
754
  sendBack({
746
755
  type: 'error',
747
756
  error: error instanceof Error ? error : new Error(String(error))
@@ -749,7 +758,7 @@ const dbInit = fromCallback(({ sendBack, input: { context } }) => {
749
758
  });
750
759
  });
751
760
 
752
- const logger$7 = debug('seedSdk:client:actors:addModelsToStore');
761
+ const logger$8 = debug('seedSdk:client:actors:addModelsToStore');
753
762
  const addModelsToStore = fromCallback(({ sendBack, input: { context } }) => {
754
763
  const _addModelsToStore = async () => {
755
764
  let { models } = context;
@@ -763,7 +772,7 @@ const addModelsToStore = fromCallback(({ sendBack, input: { context } }) => {
763
772
  // Models are now Model instances, no registration needed
764
773
  // They should be created via Model.create() and are accessible via Model static methods
765
774
  for (const [key] of Object.entries(allModels)) {
766
- logger$7('model available:', key);
775
+ logger$8('model available:', key);
767
776
  }
768
777
  };
769
778
  _addModelsToStore()
@@ -771,7 +780,7 @@ const addModelsToStore = fromCallback(({ sendBack, input: { context } }) => {
771
780
  sendBack({ type: ClientManagerEvents.ADD_MODELS_TO_STORE_SUCCESS });
772
781
  })
773
782
  .catch((error) => {
774
- logger$7('[client/actors] [addModelsToStore] Error:', error);
783
+ logger$8('[client/actors] [addModelsToStore] Error:', error);
775
784
  sendBack({
776
785
  type: 'error',
777
786
  error: error instanceof Error ? error : new Error(String(error)),
@@ -779,7 +788,7 @@ const addModelsToStore = fromCallback(({ sendBack, input: { context } }) => {
779
788
  });
780
789
  });
781
790
 
782
- const logger$6 = debug('seedSdk:client:actors:addModelsToDb');
791
+ const logger$7 = debug('seedSdk:client:actors:addModelsToDb');
783
792
  /**
784
793
  * Returns every `models` row named in `modelNames`, inserting a null-schemaFileId stub for each name
785
794
  * with no row yet (the schema import adopts stubs via findOrCreateModelRecord). Check-then-insert:
@@ -802,7 +811,7 @@ async function ensureModelStubs(appDb, modelNames, filesDir) {
802
811
  .returning({ id: models$1.id, name: models$1.name, schemaFileId: models$1.schemaFileId }));
803
812
  rows.push(...newlyInserted);
804
813
  for (const name of modelsToInsert) {
805
- logger$6('[client/actors] [addModelsToDb] inserted model:', name);
814
+ logger$7('[client/actors] [addModelsToDb] inserted model:', name);
806
815
  }
807
816
  }
808
817
  return rows;
@@ -839,7 +848,7 @@ const addModelsToDb = fromCallback(({ sendBack, input: { context } }) => {
839
848
  for (const modelName of modelNames) {
840
849
  const foundModel = rowFor(modelName);
841
850
  if (!foundModel) {
842
- logger$6('[client/actors] [addModelsToDb] Warning: Could not find or create model:', modelName);
851
+ logger$7('[client/actors] [addModelsToDb] Warning: Could not find or create model:', modelName);
843
852
  hasModelsInDb = false;
844
853
  continue;
845
854
  }
@@ -851,7 +860,7 @@ const addModelsToDb = fromCallback(({ sendBack, input: { context } }) => {
851
860
  }
852
861
  // If we have no models to process, still send success (empty models is valid)
853
862
  if (schemaDefsByModelName.size === 0) {
854
- logger$6('[client/actors] [addModelsToDb] No models to process, but continuing');
863
+ logger$7('[client/actors] [addModelsToDb] No models to process, but continuing');
855
864
  sendBack({ type: ClientManagerEvents.ADD_MODELS_TO_DB_SUCCESS });
856
865
  return;
857
866
  }
@@ -894,15 +903,15 @@ const addModelsToDb = fromCallback(({ sendBack, input: { context } }) => {
894
903
  requestEasSyncFromModelsInit();
895
904
  }
896
905
  else {
897
- logger$6('[client/actors] [addModelsToDb] No schemas found from EAS, but continuing');
906
+ logger$7('[client/actors] [addModelsToDb] No schemas found from EAS, but continuing');
898
907
  }
899
908
  }
900
909
  catch (error) {
901
910
  if (process.env.NODE_ENV === 'test' || process.env.IS_SEED_DEV) {
902
- logger$6('[client/actors] [addModelsToDb] Warning: Could not fetch schemas from EAS (background):', error.message);
911
+ logger$7('[client/actors] [addModelsToDb] Warning: Could not fetch schemas from EAS (background):', error.message);
903
912
  }
904
913
  else {
905
- logger$6('[client/actors] [addModelsToDb] Error fetching schemas (background):', error.message);
914
+ logger$7('[client/actors] [addModelsToDb] Error fetching schemas (background):', error.message);
906
915
  }
907
916
  }
908
917
  };
@@ -914,10 +923,10 @@ const addModelsToDb = fromCallback(({ sendBack, input: { context } }) => {
914
923
  sendBack({ type: ClientManagerEvents.ADD_MODELS_TO_DB_SUCCESS });
915
924
  })
916
925
  .catch((error) => {
917
- logger$6('[client/actors] [addModelsToDb] Error:', error);
926
+ logger$7('[client/actors] [addModelsToDb] Error:', error);
918
927
  // In test environments, still send success to allow initialization to complete
919
928
  if (process.env.NODE_ENV === 'test' || process.env.IS_SEED_DEV) {
920
- logger$6('[client/actors] [addModelsToDb] Continuing despite error in test environment');
929
+ logger$7('[client/actors] [addModelsToDb] Continuing despite error in test environment');
921
930
  sendBack({ type: ClientManagerEvents.ADD_MODELS_TO_DB_SUCCESS });
922
931
  }
923
932
  else {
@@ -930,7 +939,7 @@ const addModelsToDb = fromCallback(({ sendBack, input: { context } }) => {
930
939
  return () => { };
931
940
  });
932
941
 
933
- const logger$5 = debug('seedSdk:helpers:localDbChain');
942
+ const logger$6 = debug('seedSdk:helpers:localDbChain');
934
943
  /** appState key recording which EAS chain the local database holds attestations from. */
935
944
  const EAS_CHAIN_ID_APP_STATE_KEY = 'easChainId';
936
945
  /**
@@ -1000,7 +1009,7 @@ async function loadLocalDbChain() {
1000
1009
  const localChainId = await resolveLocalDbChainId(appDb);
1001
1010
  if (localChainId !== undefined) {
1002
1011
  configureEasReadChain('localDb', { chainId: localChainId });
1003
- logger$5('local DB holds chain %d', localChainId);
1012
+ logger$6('local DB holds chain %d', localChainId);
1004
1013
  return;
1005
1014
  }
1006
1015
  if (isEasReadChainConfigured()) {
@@ -1026,15 +1035,33 @@ async function assertLocalDbChain() {
1026
1035
  configureEasReadChain('localDb', { chainId: localChainId ?? chainId });
1027
1036
  }
1028
1037
 
1029
- const logger$4 = debug('seedSdk:client:actors:saveConfig');
1038
+ const logger$5 = debug('seedSdk:client:actors:saveConfig');
1039
+ let warnedKeptStoredAddresses = false;
1030
1040
  /**
1031
- * Saves the addresses passed to init. Hosts pass `addresses: []` before a wallet connects. In the
1032
- * first (leader) tab that clears stored addresses, as it always has, so drafts made before the
1033
- * wallet reconnects stay editable. A tab opened while another is running (`keepStoredWhenEmpty`)
1034
- * keeps them instead: they're the other tab's connected wallet, which EAS sync, downloads and
1035
- * publishing read. See docs/MULTI_TAB.md.
1041
+ * Saves the addresses passed to init.
1042
+ *
1043
+ * - No `addresses` option (`addressesProvided: false`): stored addresses are kept, with a
1044
+ * one-time warning when there are any, since a forgotten option would otherwise act on
1045
+ * an earlier session's wallet.
1046
+ * - `addresses: []`: hosts pass this before a wallet connects. In the first (leader) tab it
1047
+ * clears stored addresses, so drafts made before the wallet reconnects stay editable. A tab
1048
+ * opened while another is running (`keepStoredWhenEmpty`) keeps them instead: they're the
1049
+ * other tab's connected wallet, which EAS sync, downloads and publishing read. See
1050
+ * docs/MULTI_TAB.md.
1036
1051
  */
1037
- async function persistInitAddresses(appDb, { addresses, ownedAddresses, watchedAddresses }, { keepStoredWhenEmpty }) {
1052
+ async function persistInitAddresses(appDb, { addresses, addressesProvided, ownedAddresses, watchedAddresses, }, { keepStoredWhenEmpty }) {
1053
+ if (addressesProvided === false) {
1054
+ if (!warnedKeptStoredAddresses) {
1055
+ const rows = await appDb.select().from(appState).where(eq(appState.key, 'addresses')).limit(1);
1056
+ const stored = rows[0]?.value ? normalizeAddressConfig(JSON.parse(rows[0].value)) : undefined;
1057
+ if (stored && (stored.owned.length > 0 || stored.watched.length > 0)) {
1058
+ warnedKeptStoredAddresses = true;
1059
+ console.warn(`[seed] client.init was called without \`addresses\`, so the stored addresses are kept ` +
1060
+ `(${stored.owned.length} owned, ${stored.watched.length} watched). Pass \`addresses: []\` to clear them.`);
1061
+ }
1062
+ }
1063
+ return;
1064
+ }
1038
1065
  const owned = normalizeAddressList(ownedAddresses ?? addresses ?? []);
1039
1066
  const watched = normalizeAddressList(watchedAddresses ?? []);
1040
1067
  if (owned.length === 0 && watched.length === 0 && keepStoredWhenEmpty)
@@ -1046,13 +1073,13 @@ async function persistInitAddresses(appDb, { addresses, ownedAddresses, watchedA
1046
1073
  .onConflictDoUpdate({ target: appState.key, set: { value } });
1047
1074
  }
1048
1075
  const saveConfig = fromCallback(({ sendBack, input: { context } }) => {
1049
- logger$4('saveConfig starting');
1050
- const { endpoints, addresses, ownedAddresses, watchedAddresses, arweaveDomain, uploadApiBaseUrl, gatewayTransport, gatewayHyperKey, gatewaySidecarHost, gatewaySidecarPort, gatewayProxyBaseUrl, } = context;
1076
+ logger$5('saveConfig starting');
1077
+ const { endpoints, addresses, addressesProvided, ownedAddresses, watchedAddresses, arweaveDomain, uploadApiBaseUrl, gatewayTransport, gatewayHyperKey, gatewaySidecarHost, gatewaySidecarPort, gatewayProxyBaseUrl, } = context;
1051
1078
  // Validate endpoints - required for proper initialization
1052
1079
  // If endpoints are missing or invalid, initialization should fail
1053
1080
  if (!endpoints || !endpoints.filePaths || !endpoints.files) {
1054
1081
  const error = new Error('saveConfig called with invalid endpoints: endpoints must include both filePaths and files');
1055
- logger$4('[internal/actors] [saveConfig] Invalid endpoints:', { endpoints });
1082
+ logger$5('[internal/actors] [saveConfig] Invalid endpoints:', { endpoints });
1056
1083
  throw error;
1057
1084
  }
1058
1085
  const _saveConfig = async () => {
@@ -1061,7 +1088,7 @@ const saveConfig = fromCallback(({ sendBack, input: { context } }) => {
1061
1088
  if (!appDb) {
1062
1089
  // In test environments, continue anyway
1063
1090
  if (process.env.NODE_ENV === 'test' || process.env.IS_SEED_DEV) {
1064
- logger$4('[internal/actors] [saveConfig] App DB not found, but continuing in test environment');
1091
+ logger$5('[internal/actors] [saveConfig] App DB not found, but continuing in test environment');
1065
1092
  return;
1066
1093
  }
1067
1094
  throw new Error('App DB not found');
@@ -1080,7 +1107,7 @@ const saveConfig = fromCallback(({ sendBack, input: { context } }) => {
1080
1107
  value: endpointsValueString,
1081
1108
  },
1082
1109
  });
1083
- await persistInitAddresses(appDb, { addresses, ownedAddresses, watchedAddresses }, { keepStoredWhenEmpty: !isLeaderTab() });
1110
+ await persistInitAddresses(appDb, { addresses, addressesProvided, ownedAddresses, watchedAddresses }, { keepStoredWhenEmpty: !isLeaderTab() });
1084
1111
  await appDb
1085
1112
  .insert(appState)
1086
1113
  .values({
@@ -1116,10 +1143,10 @@ const saveConfig = fromCallback(({ sendBack, input: { context } }) => {
1116
1143
  await loadLocalDbChain();
1117
1144
  }
1118
1145
  catch (error) {
1119
- logger$4('[internal/actors] [saveConfig] Error saving config:', error);
1146
+ logger$5('[internal/actors] [saveConfig] Error saving config:', error);
1120
1147
  // In test environments, continue anyway
1121
1148
  if (process.env.NODE_ENV === 'test' || process.env.IS_SEED_DEV) {
1122
- logger$4('[internal/actors] [saveConfig] Continuing despite error in test environment');
1149
+ logger$5('[internal/actors] [saveConfig] Continuing despite error in test environment');
1123
1150
  return;
1124
1151
  }
1125
1152
  throw error;
@@ -1128,14 +1155,14 @@ const saveConfig = fromCallback(({ sendBack, input: { context } }) => {
1128
1155
  // Init writes run one tab at a time (docs/MULTI_TAB.md).
1129
1156
  withSeedDbLock('init', context.filesDir, _saveConfig)
1130
1157
  .then(() => {
1131
- logger$4('[internal/actors] [saveConfig] saveConfig success');
1158
+ logger$5('[internal/actors] [saveConfig] saveConfig success');
1132
1159
  return sendBack({ type: ClientManagerEvents.SAVE_CONFIG_SUCCESS });
1133
1160
  })
1134
1161
  .catch((error) => {
1135
- logger$4('[internal/actors] [saveConfig] Error in saveConfig promise chain:', error);
1162
+ logger$5('[internal/actors] [saveConfig] Error in saveConfig promise chain:', error);
1136
1163
  // In test environments, still send success to allow state machine to progress
1137
1164
  if (process.env.NODE_ENV === 'test' || process.env.IS_SEED_DEV) {
1138
- logger$4('[internal/actors] [saveConfig] Sending success despite error in test environment');
1165
+ logger$5('[internal/actors] [saveConfig] Sending success despite error in test environment');
1139
1166
  sendBack({ type: ClientManagerEvents.SAVE_CONFIG_SUCCESS });
1140
1167
  }
1141
1168
  else {
@@ -1148,7 +1175,7 @@ const saveConfig = fromCallback(({ sendBack, input: { context } }) => {
1148
1175
  return () => { };
1149
1176
  });
1150
1177
 
1151
- const logger$3 = debug('seedSdk:helpers:schema');
1178
+ const logger$4 = debug('seedSdk:helpers:schema');
1152
1179
  /**
1153
1180
  * Sanitize a schema name to be filesystem-safe
1154
1181
  * Replaces all special characters (except alphanumeric, hyphens, underscores) with underscores
@@ -1344,7 +1371,7 @@ async function listCompleteSchemaFiles() {
1344
1371
  const dirExists = await BaseFileManager.pathExists(workingDir);
1345
1372
  if (!dirExists) {
1346
1373
  // Directory doesn't exist yet - return empty array (not an error condition)
1347
- logger$3(`Working directory does not exist yet: ${workingDir}, returning empty schema list`);
1374
+ logger$4(`Working directory does not exist yet: ${workingDir}, returning empty schema list`);
1348
1375
  return [];
1349
1376
  }
1350
1377
  const files = await fs.promises.readdir(workingDir);
@@ -1480,7 +1507,7 @@ async function loadAllSchemasFromDb() {
1480
1507
  }
1481
1508
  catch (error) {
1482
1509
  // If we can't list schema files (e.g., directory doesn't exist yet), continue without file-based loading
1483
- logger$3(`Error listing complete schema files (continuing with DB data): ${error instanceof Error ? error.message : String(error)}`);
1510
+ logger$4(`Error listing complete schema files (continuing with DB data): ${error instanceof Error ? error.message : String(error)}`);
1484
1511
  completeSchemaFiles = [];
1485
1512
  }
1486
1513
  }
@@ -1533,7 +1560,7 @@ async function loadAllSchemasFromDb() {
1533
1560
  continue;
1534
1561
  }
1535
1562
  catch (error) {
1536
- logger$3(`Error parsing schemaData for ${schemaName}:`, error);
1563
+ logger$4(`Error parsing schemaData for ${schemaName}:`, error);
1537
1564
  // Fall through to file-based loading
1538
1565
  }
1539
1566
  }
@@ -1575,7 +1602,7 @@ async function loadAllSchemasFromDb() {
1575
1602
  continue;
1576
1603
  }
1577
1604
  catch (error) {
1578
- logger$3(`Error loading schema file for ${schemaName}:`, error);
1605
+ logger$4(`Error loading schema file for ${schemaName}:`, error);
1579
1606
  // Fall through to try loading from schemaData if available
1580
1607
  }
1581
1608
  }
@@ -1619,7 +1646,7 @@ async function loadAllSchemasFromDb() {
1619
1646
  continue;
1620
1647
  }
1621
1648
  catch (error) {
1622
- logger$3(`Error parsing schemaData for ${schemaName}:`, error);
1649
+ logger$4(`Error parsing schemaData for ${schemaName}:`, error);
1623
1650
  }
1624
1651
  }
1625
1652
  }
@@ -1630,11 +1657,11 @@ async function loadAllSchemasFromDb() {
1630
1657
  // Only process if not already in result
1631
1658
  if (!processedSchemaNames.has(schemaFileInfo.name)) {
1632
1659
  if (isInternalSchema(schemaFileInfo.name, schemaFileInfo.schemaFileId)) {
1633
- logger$3(`STEP 3: skipping internal schema file: ${schemaFileInfo.filePath}`);
1660
+ logger$4(`STEP 3: skipping internal schema file: ${schemaFileInfo.filePath}`);
1634
1661
  continue;
1635
1662
  }
1636
1663
  try {
1637
- logger$3(`STEP 3: processing schema file: ${schemaFileInfo.name} from ${schemaFileInfo.filePath}`);
1664
+ logger$4(`STEP 3: processing schema file: ${schemaFileInfo.name} from ${schemaFileInfo.filePath}`);
1638
1665
  const content = await BaseFileManager.readFileAsString(schemaFileInfo.filePath);
1639
1666
  const schemaFile = JSON.parse(content);
1640
1667
  // Import this schema to database (mark as non-draft since it's in a file)
@@ -1654,7 +1681,7 @@ async function loadAllSchemasFromDb() {
1654
1681
  processedSchemaNames.add(schemaFileInfo.name);
1655
1682
  }
1656
1683
  catch (error) {
1657
- logger$3(`Error loading schema file ${schemaFileInfo.filePath}:`, error);
1684
+ logger$4(`Error loading schema file ${schemaFileInfo.filePath}:`, error);
1658
1685
  }
1659
1686
  }
1660
1687
  }
@@ -1671,7 +1698,7 @@ async function migrateFileSchemasToDb() {
1671
1698
  if (!db) {
1672
1699
  throw new Error('Database not found');
1673
1700
  }
1674
- logger$3('Starting migration of file-based schemas to database');
1701
+ logger$4('Starting migration of file-based schemas to database');
1675
1702
  // Get all complete schema files
1676
1703
  const completeSchemas = await listCompleteSchemaFiles();
1677
1704
  let migratedCount = 0;
@@ -1681,7 +1708,7 @@ async function migrateFileSchemasToDb() {
1681
1708
  const content = await BaseFileManager.readFileAsString(schemaFileInfo.filePath);
1682
1709
  const schemaFile = JSON.parse(content);
1683
1710
  if (!schemaFile.$schema || !schemaFile.metadata?.name) {
1684
- logger$3(`Skipping invalid schema file: ${schemaFileInfo.filePath}`);
1711
+ logger$4(`Skipping invalid schema file: ${schemaFileInfo.filePath}`);
1685
1712
  continue;
1686
1713
  }
1687
1714
  const schemaName = schemaFile.metadata.name;
@@ -1703,17 +1730,17 @@ async function migrateFileSchemasToDb() {
1703
1730
  JSON.stringify(schemaFile, null, 2), // schemaData
1704
1731
  false);
1705
1732
  migratedCount++;
1706
- logger$3(`Migrated schema: ${schemaName} v${schemaFile.version}`);
1733
+ logger$4(`Migrated schema: ${schemaName} v${schemaFile.version}`);
1707
1734
  }
1708
1735
  else {
1709
- logger$3(`Schema ${schemaName} already exists in database, skipping`);
1736
+ logger$4(`Schema ${schemaName} already exists in database, skipping`);
1710
1737
  }
1711
1738
  }
1712
1739
  catch (error) {
1713
- logger$3(`Error migrating schema file ${schemaFileInfo.filePath}:`, error);
1740
+ logger$4(`Error migrating schema file ${schemaFileInfo.filePath}:`, error);
1714
1741
  }
1715
1742
  }
1716
- logger$3(`Migration complete: ${migratedCount} schemas migrated`);
1743
+ logger$4(`Migration complete: ${migratedCount} schemas migrated`);
1717
1744
  return migratedCount;
1718
1745
  }
1719
1746
  /**
@@ -1768,7 +1795,7 @@ const getDeterministicIdsWithPrefix = (prefix) => {
1768
1795
  return (suffix) => bytesToHex(prefixHash.clone().update(utf8ToBytes(suffix)).digest()).slice(0, 10);
1769
1796
  };
1770
1797
 
1771
- const logger$2 = debug('seedSdk:imports:json');
1798
+ const logger$3 = debug('seedSdk:imports:json');
1772
1799
  /**
1773
1800
  * Get refValueType from a property object with case-insensitive key lookup.
1774
1801
  * Handles refValueType, refvaluetype, ref_value_type, elementType, and legacy items.type / items.Type.
@@ -1846,8 +1873,8 @@ function getRefValueType(prop) {
1846
1873
  * @returns Promise that resolves when properties are found, or rejects if not found after max retries
1847
1874
  */
1848
1875
  const verifyPropertiesPersisted = async (db, modelId, modelName, maxRetries = 10, retryDelay = 100) => {
1849
- const _mod_0 = await import('./BasePathResolver-BdxCSIzn.js');
1850
- const _ns_0 = _mod_0.N;
1876
+ const _mod_0 = await import('./BasePathResolver-Cm4apKRb.js');
1877
+ const _ns_0 = _mod_0.aZ;
1851
1878
  const modelSchemaMod = _ns_0;
1852
1879
  const { properties: propertiesTable } = modelSchemaMod;
1853
1880
  const drizzleMod = await import('drizzle-orm');
@@ -1859,11 +1886,11 @@ const verifyPropertiesPersisted = async (db, modelId, modelName, maxRetries = 10
1859
1886
  .where(eq(propertiesTable.modelId, modelId))
1860
1887
  .limit(1);
1861
1888
  if (props.length > 0) {
1862
- logger$2(`Verified properties exist for model "${modelName}" (modelId: ${modelId}) after ${attempt + 1} attempt(s)`);
1889
+ logger$3(`Verified properties exist for model "${modelName}" (modelId: ${modelId}) after ${attempt + 1} attempt(s)`);
1863
1890
  return;
1864
1891
  }
1865
1892
  if (attempt < maxRetries - 1) {
1866
- logger$2(`Properties not yet visible for model "${modelName}" (modelId: ${modelId}), retrying in ${retryDelay}ms (attempt ${attempt + 1}/${maxRetries})`);
1893
+ logger$3(`Properties not yet visible for model "${modelName}" (modelId: ${modelId}), retrying in ${retryDelay}ms (attempt ${attempt + 1}/${maxRetries})`);
1867
1894
  await new Promise(resolve => setTimeout(resolve, retryDelay));
1868
1895
  }
1869
1896
  }
@@ -2169,7 +2196,7 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
2169
2196
  if (parsed.$schema && parsed.metadata) {
2170
2197
  // It's already a complete schema format - preserve it (id may be missing, will be generated)
2171
2198
  originalSchemaFile = parsed;
2172
- logger$2(`Input is complete schema format (${originalSchemaFile.id ? `preserving ID: ${originalSchemaFile.id}` : 'id will be generated'})`);
2199
+ logger$3(`Input is complete schema format (${originalSchemaFile.id ? `preserving ID: ${originalSchemaFile.id}` : 'id will be generated'})`);
2173
2200
  }
2174
2201
  }
2175
2202
  catch {
@@ -2194,8 +2221,8 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
2194
2221
  // Check DB for existing schema by name+version (same as minimal path)
2195
2222
  const db = BaseDb.getAppDb();
2196
2223
  if (db) {
2197
- const _mod_1 = await import('./BasePathResolver-BdxCSIzn.js');
2198
- const _ns_1 = _mod_1.Q;
2224
+ const _mod_1 = await import('./BasePathResolver-Cm4apKRb.js');
2225
+ const _ns_1 = _mod_1.a$;
2199
2226
  const schemaSchemaMod = _ns_1;
2200
2227
  const { schemas: schemasTable } = schemaSchemaMod;
2201
2228
  const drizzleMod = await import('drizzle-orm');
@@ -2208,16 +2235,16 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
2208
2235
  .limit(1);
2209
2236
  if (existingByName.length > 0 && existingByName[0].schemaData) {
2210
2237
  const existing = existingByName[0];
2211
- logger$2(`Idempotency: found existing schema by name+version: ${schemaFile.metadata.name} v${schemaFile.version ?? version}`);
2238
+ logger$3(`Idempotency: found existing schema by name+version: ${schemaFile.metadata.name} v${schemaFile.version ?? version}`);
2212
2239
  const existingSchema = JSON.parse(existing.schemaData);
2213
2240
  const contentMatches = compareSchemaContent(schemaFile, existingSchema);
2214
- logger$2(`Idempotency: compareSchemaContent=${contentMatches} for ${schemaFile.metadata.name}`);
2241
+ logger$3(`Idempotency: compareSchemaContent=${contentMatches} for ${schemaFile.metadata.name}`);
2215
2242
  if (contentMatches) {
2216
2243
  if (existing.schemaFileId) {
2217
2244
  const workingDir = BaseFileManager.getWorkingDir();
2218
2245
  const existingFilePath = getSchemaFilePath(workingDir, schemaFile.metadata.name, schemaFile.version ?? version, existing.schemaFileId);
2219
2246
  if (await BaseFileManager.pathExists(existingFilePath)) {
2220
- logger$2(`Schema ${schemaFile.metadata.name} v${schemaFile.version} already exists with same content, loading existing file`);
2247
+ logger$3(`Schema ${schemaFile.metadata.name} v${schemaFile.version} already exists with same content, loading existing file`);
2221
2248
  return await loadSchemaFromFile(existingFilePath);
2222
2249
  }
2223
2250
  await BaseFileManager.createDirIfNotExists(workingDir);
@@ -2225,7 +2252,7 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
2225
2252
  await BaseFileManager.waitForFileWithContent(existingFilePath, 100, 5000);
2226
2253
  return await loadSchemaFromFile(existingFilePath);
2227
2254
  }
2228
- logger$2(`Schema ${schemaFile.metadata.name} v${schemaFile.version} already exists with same content (no schemaFileId), using DB`);
2255
+ logger$3(`Schema ${schemaFile.metadata.name} v${schemaFile.version} already exists with same content (no schemaFileId), using DB`);
2229
2256
  return '';
2230
2257
  }
2231
2258
  }
@@ -2241,7 +2268,7 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
2241
2268
  // processSchemaFiles runs multiple times (React StrictMode, app restarts).
2242
2269
  if (!schemaFile.id) {
2243
2270
  schemaFile.id = await getDeterministicSchemaFileId(schemaFile);
2244
- logger$2(`Generated deterministic schema ID for ${schemaFile.metadata.name}:`, schemaFile.id);
2271
+ logger$3(`Generated deterministic schema ID for ${schemaFile.metadata.name}:`, schemaFile.id);
2245
2272
  }
2246
2273
  // Before generating IDs, check if a file already exists with this schemaFileId
2247
2274
  // This handles the case where the schema was already loaded via loadSchemaFromFile
@@ -2251,7 +2278,7 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
2251
2278
  const existingFileExists = await BaseFileManager.pathExists(existingFilePath);
2252
2279
  if (existingFileExists) {
2253
2280
  // File already exists with this schemaFileId - just load it instead of creating a new one
2254
- logger$2(`Schema file already exists with schemaFileId ${schemaFile.id}, loading it instead of creating new file`);
2281
+ logger$3(`Schema file already exists with schemaFileId ${schemaFile.id}, loading it instead of creating new file`);
2255
2282
  return await loadSchemaFromFile(existingFilePath);
2256
2283
  }
2257
2284
  // Generate missing model and property IDs.
@@ -2262,12 +2289,12 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
2262
2289
  for (const [modelName, model] of Object.entries(schemaFile.models || {})) {
2263
2290
  if (!model.id) {
2264
2291
  model.id = getDeterministicId(modelName);
2265
- logger$2(`Generated deterministic model ID for ${modelName}:`, model.id);
2292
+ logger$3(`Generated deterministic model ID for ${modelName}:`, model.id);
2266
2293
  }
2267
2294
  for (const [propName, prop] of Object.entries(model.properties || {})) {
2268
2295
  if (!prop.id) {
2269
2296
  prop.id = getDeterministicId(modelName + propName);
2270
- logger$2(`Generated deterministic property ID for ${modelName}.${propName}:`, prop.id);
2297
+ logger$3(`Generated deterministic property ID for ${modelName}.${propName}:`, prop.id);
2271
2298
  }
2272
2299
  }
2273
2300
  }
@@ -2279,8 +2306,8 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
2279
2306
  // For minimal imports: check DB for existing schema before creating new file
2280
2307
  const db = BaseDb.getAppDb();
2281
2308
  if (db) {
2282
- const _mod_2 = await import('./BasePathResolver-BdxCSIzn.js');
2283
- const _ns_2 = _mod_2.Q;
2309
+ const _mod_2 = await import('./BasePathResolver-Cm4apKRb.js');
2310
+ const _ns_2 = _mod_2.a$;
2284
2311
  const schemaSchemaMod = _ns_2;
2285
2312
  const { schemas: schemasTable } = schemaSchemaMod;
2286
2313
  const drizzleMod = await import('drizzle-orm');
@@ -2303,14 +2330,14 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
2303
2330
  const workingDir = BaseFileManager.getWorkingDir();
2304
2331
  const existingFilePath = getSchemaFilePath(workingDir, importData.name, version, existing.schemaFileId);
2305
2332
  if (await BaseFileManager.pathExists(existingFilePath)) {
2306
- logger$2(`Schema ${importData.name} v${version} already exists with same content, loading existing file`);
2333
+ logger$3(`Schema ${importData.name} v${version} already exists with same content, loading existing file`);
2307
2334
  return await loadSchemaFromFile(existingFilePath);
2308
2335
  }
2309
2336
  // File missing but schemaData exists - restore file from schemaData
2310
2337
  await BaseFileManager.createDirIfNotExists(workingDir);
2311
2338
  await BaseFileManager.saveFile(existingFilePath, existing.schemaData);
2312
2339
  await BaseFileManager.waitForFileWithContent(existingFilePath, 100, 5000);
2313
- logger$2(`Restored schema file from schemaData for ${importData.name} v${version}`);
2340
+ logger$3(`Restored schema file from schemaData for ${importData.name} v${version}`);
2314
2341
  return await loadSchemaFromFile(existingFilePath);
2315
2342
  }
2316
2343
  // No schemaFileId - restore file from schemaData using id from parsed schema
@@ -2321,10 +2348,10 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
2321
2348
  await BaseFileManager.createDirIfNotExists(workingDir);
2322
2349
  await BaseFileManager.saveFile(existingFilePath, existing.schemaData);
2323
2350
  await BaseFileManager.waitForFileWithContent(existingFilePath, 100, 5000);
2324
- logger$2(`Restored schema file from schemaData for ${importData.name} v${version}`);
2351
+ logger$3(`Restored schema file from schemaData for ${importData.name} v${version}`);
2325
2352
  return await loadSchemaFromFile(existingFilePath);
2326
2353
  }
2327
- logger$2(`Schema ${importData.name} v${version} already exists with same content (no id), using DB`);
2354
+ logger$3(`Schema ${importData.name} v${version} already exists with same content (no id), using DB`);
2328
2355
  return '';
2329
2356
  }
2330
2357
  // Content differs - create new version
@@ -2335,7 +2362,7 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
2335
2362
  .orderBy(desc(schemasTable.version))
2336
2363
  .limit(1);
2337
2364
  const newVersion = latestVersionRows.length > 0 ? latestVersionRows[0].version + 1 : version;
2338
- logger$2(`Schema ${importData.name} content changed, creating new version v${newVersion}`);
2365
+ logger$3(`Schema ${importData.name} content changed, creating new version v${newVersion}`);
2339
2366
  schemaFile = transformImportToSchemaFile(importData, newVersion);
2340
2367
  version = newVersion;
2341
2368
  }
@@ -2359,7 +2386,7 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
2359
2386
  // Check if this is an internal SDK schema (should not create files in app directory)
2360
2387
  const isInternal = isInternalSchema(schemaFile.metadata.name, schemaFile.id);
2361
2388
  if (isInternal) {
2362
- logger$2(`Skipping file creation for internal schema: ${schemaFile.metadata.name}`);
2389
+ logger$3(`Skipping file creation for internal schema: ${schemaFile.metadata.name}`);
2363
2390
  // For internal schemas, just load to database and store, don't create file
2364
2391
  // Extract schema name and version
2365
2392
  const schemaName = schemaFile.metadata?.name;
@@ -2416,7 +2443,7 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
2416
2443
  // Use fixed internal schema ID if missing (never generate for internal)
2417
2444
  if (!schemaFile.id) {
2418
2445
  schemaFile.id = INTERNAL_SCHEMA_IDS[0];
2419
- logger$2('Using fixed internal schema ID:', schemaFile.id);
2446
+ logger$3('Using fixed internal schema ID:', schemaFile.id);
2420
2447
  }
2421
2448
  // Extract schemaFileIds from JSON file and generate missing ones BEFORE creating models
2422
2449
  // This ensures Model instances are created with correct IDs
@@ -2426,7 +2453,7 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
2426
2453
  // Generate model ID if missing
2427
2454
  if (!model.id) {
2428
2455
  model.id = generateId();
2429
- logger$2(`Generated model ID for ${modelName}:`, model.id);
2456
+ logger$3(`Generated model ID for ${modelName}:`, model.id);
2430
2457
  // Update the schemaFile object so it's included in schemaData
2431
2458
  schemaFile.models[modelName].id = model.id;
2432
2459
  }
@@ -2436,7 +2463,7 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
2436
2463
  // Generate property ID if missing
2437
2464
  if (!prop.id) {
2438
2465
  prop.id = generateId();
2439
- logger$2(`Generated property ID for ${modelName}.${propName}:`, prop.id);
2466
+ logger$3(`Generated property ID for ${modelName}.${propName}:`, prop.id);
2440
2467
  // Update the schemaFile object so it's included in schemaData
2441
2468
  schemaFile.models[modelName].properties[propName].id = prop.id;
2442
2469
  }
@@ -2448,7 +2475,7 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
2448
2475
  }
2449
2476
  // Convert JSON models to Model classes, passing modelFileIds and propertyFileIds so Model instances use correct IDs
2450
2477
  const modelDefinitions = await createModelsFromJson(importDataForInternal, modelFileIds, propertyFileIds);
2451
- logger$2('loadSchemaFromFile (internal) - modelDefinitions length:', Object.keys(modelDefinitions).length);
2478
+ logger$3('loadSchemaFromFile (internal) - modelDefinitions length:', Object.keys(modelDefinitions).length);
2452
2479
  // Convert schema file metadata to schema input for database
2453
2480
  const schemaInput = {
2454
2481
  name: schemaName,
@@ -2458,8 +2485,8 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
2458
2485
  updatedAt: new Date(schemaFile.metadata.updatedAt).getTime(),
2459
2486
  };
2460
2487
  // Use dynamic import to break circular dependency
2461
- const _mod_3 = await import('./db-CQt-gcAl.js');
2462
- const _ns_3 = _mod_3.Z;
2488
+ const _mod_3 = await import('./BasePathResolver-Cm4apKRb.js');
2489
+ const _ns_3 = _mod_3.b2;
2463
2490
  const dbMod = _ns_3;
2464
2491
  const { addSchemaToDb, addModelsToDb } = dbMod;
2465
2492
  // Try to add schema and models to database if database is available
@@ -2480,12 +2507,12 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
2480
2507
  });
2481
2508
  // Verify expected models are linked (single attempt - addModelsToDb already confirmed)
2482
2509
  const expectedModelNames = Object.keys(schemaFile.models || {});
2483
- const _mod_4 = await import('./BasePathResolver-BdxCSIzn.js');
2484
- const _ns_4 = _mod_4.R;
2510
+ const _mod_4 = await import('./BasePathResolver-Cm4apKRb.js');
2511
+ const _ns_4 = _mod_4.b0;
2485
2512
  const modelSchemaSchemaMod = _ns_4;
2486
2513
  const { modelSchemas } = modelSchemaSchemaMod;
2487
- const _mod_5 = await import('./BasePathResolver-BdxCSIzn.js');
2488
- const _ns_5 = _mod_5.N;
2514
+ const _mod_5 = await import('./BasePathResolver-Cm4apKRb.js');
2515
+ const _ns_5 = _mod_5.aZ;
2489
2516
  const modelSchemaMod = _ns_5;
2490
2517
  const { models: modelsTable } = modelSchemaMod;
2491
2518
  const drizzleMod = await import('drizzle-orm');
@@ -2574,12 +2601,12 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
2574
2601
  }
2575
2602
  catch (dbError) {
2576
2603
  // Database not available - log warning but continue
2577
- logger$2('Database not available, skipping database operations:', dbError instanceof Error ? dbError.message : String(dbError));
2604
+ logger$3('Database not available, skipping database operations:', dbError instanceof Error ? dbError.message : String(dbError));
2578
2605
  }
2579
2606
  // Models are now Model instances, no registration needed
2580
2607
  // They should be created via Model.create() and are accessible via Model static methods
2581
2608
  for (const [modelName] of Object.entries(modelDefinitions)) {
2582
- logger$2('loadSchemaFromFile (internal) - model available:', modelName);
2609
+ logger$3('loadSchemaFromFile (internal) - model available:', modelName);
2583
2610
  }
2584
2611
  // Schema is now saved to database
2585
2612
  // useSchemas hook will pick it up via database queries
@@ -2590,7 +2617,7 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
2590
2617
  // Ensure schema ID is defined (should always be set by this point, but check for safety)
2591
2618
  if (!schemaFile.id) {
2592
2619
  schemaFile.id = generateId();
2593
- logger$2('Generated schema ID before file path creation:', schemaFile.id);
2620
+ logger$3('Generated schema ID before file path creation:', schemaFile.id);
2594
2621
  }
2595
2622
  // Get the target file path using ID-based naming (preferred)
2596
2623
  const filePath = getSchemaFilePath(workingDir, schemaFile.metadata.name, version, schemaFile.id);
@@ -2609,7 +2636,7 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
2609
2636
  const data = JSON.parse(content);
2610
2637
  if (data.$schema) {
2611
2638
  // File is already a complete schema, just load it
2612
- logger$2(`Schema file ${filePath} already exists and is complete, loading it`);
2639
+ logger$3(`Schema file ${filePath} already exists and is complete, loading it`);
2613
2640
  return await loadSchemaFromFile(filePath);
2614
2641
  }
2615
2642
  }
@@ -2627,7 +2654,7 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
2627
2654
  // Compare schemas structurally
2628
2655
  if (compareSchemasStructurally(schemaFile, existingSchema)) {
2629
2656
  // Schemas match - just load the existing file
2630
- logger$2(`Schema ${schemaFile.metadata.name} v${version} already exists with matching content, loading it`);
2657
+ logger$3(`Schema ${schemaFile.metadata.name} v${version} already exists with matching content, loading it`);
2631
2658
  return await loadSchemaFromFile(filePath);
2632
2659
  }
2633
2660
  else {
@@ -2670,7 +2697,7 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
2670
2697
  * Apply schema and models to the database. Shared by loadSchemaFromFile and syncSchemaFromSource.
2671
2698
  * @internal
2672
2699
  */
2673
- async function applySchemaToDb(schemaFile, modelDefinitions, modelFileIds, propertyFileIds) {
2700
+ async function applySchemaToDb(schemaFile, modelDefinitions, modelFileIds, propertyFileIds, propertyDefinitions) {
2674
2701
  const schemaName = schemaFile.metadata?.name;
2675
2702
  const version = schemaFile.version;
2676
2703
  if (!schemaName) {
@@ -2683,8 +2710,8 @@ async function applySchemaToDb(schemaFile, modelDefinitions, modelFileIds, prope
2683
2710
  createdAt: new Date(schemaFile.metadata.createdAt).getTime(),
2684
2711
  updatedAt: new Date(schemaFile.metadata.updatedAt).getTime(),
2685
2712
  };
2686
- const _mod_6 = await import('./db-CQt-gcAl.js');
2687
- const _ns_6 = _mod_6.Z;
2713
+ const _mod_6 = await import('./BasePathResolver-Cm4apKRb.js');
2714
+ const _ns_6 = _mod_6.b2;
2688
2715
  const dbMod = _ns_6;
2689
2716
  const { addSchemaToDb, addModelsToDb } = dbMod;
2690
2717
  const db = BaseDb.getAppDb();
@@ -2698,6 +2725,7 @@ async function applySchemaToDb(schemaFile, modelDefinitions, modelFileIds, prope
2698
2725
  schemaFileId: schemaFile.id,
2699
2726
  modelFileIds,
2700
2727
  propertyFileIds,
2728
+ propertyDefinitions,
2701
2729
  });
2702
2730
  await new Promise(resolve => setTimeout(resolve, 200));
2703
2731
  }
@@ -2804,7 +2832,7 @@ const loadSchemaFromFile = async (schemaFilePath) => {
2804
2832
  // Generate schema ID if missing (before creating schemaInput)
2805
2833
  if (!schemaFile.id) {
2806
2834
  schemaFile.id = generateId();
2807
- logger$2('Generated schema ID for schema file:', schemaFile.id);
2835
+ logger$3('Generated schema ID for schema file:', schemaFile.id);
2808
2836
  }
2809
2837
  // Extract schemaFileIds from JSON file and generate missing ones BEFORE creating models
2810
2838
  // This ensures Model instances are created with correct IDs
@@ -2814,7 +2842,7 @@ const loadSchemaFromFile = async (schemaFilePath) => {
2814
2842
  // Generate model ID if missing
2815
2843
  if (!model.id) {
2816
2844
  model.id = generateId();
2817
- logger$2(`Generated model ID for ${modelName}:`, model.id);
2845
+ logger$3(`Generated model ID for ${modelName}:`, model.id);
2818
2846
  // Update the schemaFile object so it's included in schemaData
2819
2847
  schemaFile.models[modelName].id = model.id;
2820
2848
  }
@@ -2824,7 +2852,7 @@ const loadSchemaFromFile = async (schemaFilePath) => {
2824
2852
  // Generate property ID if missing
2825
2853
  if (!prop.id) {
2826
2854
  prop.id = generateId();
2827
- logger$2(`Generated property ID for ${modelName}.${propName}:`, prop.id);
2855
+ logger$3(`Generated property ID for ${modelName}.${propName}:`, prop.id);
2828
2856
  // Update the schemaFile object so it's included in schemaData
2829
2857
  schemaFile.models[modelName].properties[propName].id = prop.id;
2830
2858
  }
@@ -2836,19 +2864,26 @@ const loadSchemaFromFile = async (schemaFilePath) => {
2836
2864
  }
2837
2865
  // Convert JSON models to Model classes, passing modelFileIds and propertyFileIds so Model instances use correct IDs
2838
2866
  const modelDefinitions = await createModelsFromJson(importData, modelFileIds, propertyFileIds);
2839
- logger$2('loadSchemaFromFile - modelDefinitions length:', Object.keys(modelDefinitions).length);
2867
+ logger$3('loadSchemaFromFile - modelDefinitions length:', Object.keys(modelDefinitions).length);
2840
2868
  // Try to add schema and models to database if database is available
2841
2869
  try {
2842
2870
  const db = BaseDb.getAppDb();
2843
2871
  if (db) {
2844
- const { schemaRecord } = await applySchemaToDb(schemaFile, modelDefinitions, modelFileIds, propertyFileIds);
2872
+ // A model already in the instance cache keeps its old properties (Model.create ignores the
2873
+ // ones passed), so give addModelsToDb this file's definitions: a renamed or changed property
2874
+ // must come from the file, not from the cached model.
2875
+ const propertyDefinitions = new Map(Object.entries(importData.models).map(([modelName, modelDef]) => [
2876
+ modelName,
2877
+ jsonPropertiesToSchemaProperties(modelName, modelDef, propertyFileIds.get(modelName)),
2878
+ ]));
2879
+ const { schemaRecord } = await applySchemaToDb(schemaFile, modelDefinitions, modelFileIds, propertyFileIds, propertyDefinitions);
2845
2880
  // Query the database to get model IDs that were just created
2846
- const _mod_7 = await import('./BasePathResolver-BdxCSIzn.js');
2847
- const _ns_7 = _mod_7.R;
2881
+ const _mod_7 = await import('./BasePathResolver-Cm4apKRb.js');
2882
+ const _ns_7 = _mod_7.b0;
2848
2883
  const modelSchemaSchemaMod = _ns_7;
2849
2884
  const { modelSchemas } = modelSchemaSchemaMod;
2850
- const _mod_8 = await import('./BasePathResolver-BdxCSIzn.js');
2851
- const _ns_8 = _mod_8.N;
2885
+ const _mod_8 = await import('./BasePathResolver-Cm4apKRb.js');
2886
+ const _ns_8 = _mod_8.aZ;
2852
2887
  const modelSchemaMod = _ns_8;
2853
2888
  const { models: modelsTable } = modelSchemaMod;
2854
2889
  const drizzleMod = await import('drizzle-orm');
@@ -2895,17 +2930,17 @@ const loadSchemaFromFile = async (schemaFilePath) => {
2895
2930
  await new Promise(resolve => setTimeout(resolve, 100));
2896
2931
  }
2897
2932
  }
2898
- logger$2(`Verifying properties: found ${modelLinks.length} model links for schema ${schemaName} (id: ${schemaRecord.id})`);
2933
+ logger$3(`Verifying properties: found ${modelLinks.length} model links for schema ${schemaName} (id: ${schemaRecord.id})`);
2899
2934
  // If we didn't verify via direct lookup, verify via join table
2900
2935
  if (!seedModelId || (seedModel.length === 0 || !seedModel[0].id)) {
2901
2936
  const seedModelLink = modelLinks.find((link) => link.modelName === 'Seed');
2902
2937
  if (seedModelLink && seedModelLink.modelId) {
2903
- logger$2(`Verifying properties for Seed model via join table (modelId: ${seedModelLink.modelId})`);
2938
+ logger$3(`Verifying properties for Seed model via join table (modelId: ${seedModelLink.modelId})`);
2904
2939
  await verifyPropertiesPersisted(db, seedModelLink.modelId, 'Seed', 10, 100);
2905
2940
  }
2906
2941
  else if (modelLinks.length > 0 && modelLinks[0].modelId) {
2907
2942
  // Fallback to first model if Seed not found
2908
- logger$2(`Verifying properties for ${modelLinks[0].modelName} model via join table (modelId: ${modelLinks[0].modelId})`);
2943
+ logger$3(`Verifying properties for ${modelLinks[0].modelName} model via join table (modelId: ${modelLinks[0].modelId})`);
2909
2944
  await verifyPropertiesPersisted(db, modelLinks[0].modelId, modelLinks[0].modelName || 'unknown', 10, 100);
2910
2945
  }
2911
2946
  }
@@ -2913,8 +2948,8 @@ const loadSchemaFromFile = async (schemaFilePath) => {
2913
2948
  // After properties are created (file path), ensure schemaFile has the correct IDs from database
2914
2949
  // Query the database to get the actual schemaFileId values that were used
2915
2950
  // This ensures schemaData matches what's actually in the database
2916
- const _mod_9 = await import('./BasePathResolver-BdxCSIzn.js');
2917
- const _ns_9 = _mod_9.N;
2951
+ const _mod_9 = await import('./BasePathResolver-Cm4apKRb.js');
2952
+ const _ns_9 = _mod_9.aZ;
2918
2953
  const modelSchemaMod2 = _ns_9;
2919
2954
  const { properties: propertiesTable } = modelSchemaMod2;
2920
2955
  let schemaFileUpdated = false;
@@ -2938,7 +2973,7 @@ const loadSchemaFromFile = async (schemaFilePath) => {
2938
2973
  const currentId = schemaFile.models[modelName].properties[propRecord.name].id;
2939
2974
  if (currentId !== propRecord.schemaFileId) {
2940
2975
  schemaFile.models[modelName].properties[propRecord.name].id = propRecord.schemaFileId;
2941
- logger$2(`Updated schemaFile property ID for ${modelName}.${propRecord.name} from ${currentId} to ${propRecord.schemaFileId}`);
2976
+ logger$3(`Updated schemaFile property ID for ${modelName}.${propRecord.name} from ${currentId} to ${propRecord.schemaFileId}`);
2942
2977
  schemaFileUpdated = true;
2943
2978
  }
2944
2979
  }
@@ -2949,8 +2984,8 @@ const loadSchemaFromFile = async (schemaFilePath) => {
2949
2984
  // This is important even if nothing changed, to ensure consistency
2950
2985
  const updatedSchemaData = JSON.stringify(schemaFile, null, 2);
2951
2986
  // Update the schema record in the database with current schemaData
2952
- const _mod_10 = await import('./BasePathResolver-BdxCSIzn.js');
2953
- const _ns_10 = _mod_10.Q;
2987
+ const _mod_10 = await import('./BasePathResolver-Cm4apKRb.js');
2988
+ const _ns_10 = _mod_10.a$;
2954
2989
  const schemaSchemaMod = _ns_10;
2955
2990
  const { schemas: schemasTable } = schemaSchemaMod;
2956
2991
  await db
@@ -2958,21 +2993,21 @@ const loadSchemaFromFile = async (schemaFilePath) => {
2958
2993
  .set({ schemaData: updatedSchemaData })
2959
2994
  .where(eq(schemasTable.id, schemaRecord.id));
2960
2995
  if (schemaFileUpdated) {
2961
- logger$2(`Updated schemaData in database with actual property IDs for schema "${schemaName}"`);
2996
+ logger$3(`Updated schemaData in database with actual property IDs for schema "${schemaName}"`);
2962
2997
  }
2963
2998
  else {
2964
- logger$2(`Verified schemaData in database matches schemaFile for schema "${schemaName}"`);
2999
+ logger$3(`Verified schemaData in database matches schemaFile for schema "${schemaName}"`);
2965
3000
  }
2966
3001
  }
2967
3002
  }
2968
3003
  catch (dbError) {
2969
3004
  // Database not available - log warning but continue
2970
- logger$2('Database not available, skipping database operations:', dbError instanceof Error ? dbError.message : String(dbError));
3005
+ logger$3('Database not available, skipping database operations:', dbError instanceof Error ? dbError.message : String(dbError));
2971
3006
  }
2972
3007
  // Models are now Model instances, no registration needed
2973
3008
  // They should be created via Model.create() and are accessible via Model static methods
2974
3009
  for (const [modelName] of Object.entries(modelDefinitions)) {
2975
- logger$2('loadSchemaFromFile - model available:', modelName);
3010
+ logger$3('loadSchemaFromFile - model available:', modelName);
2976
3011
  }
2977
3012
  return schemaFilePath;
2978
3013
  }
@@ -2984,19 +3019,12 @@ const loadSchemaFromFile = async (schemaFilePath) => {
2984
3019
  }
2985
3020
  };
2986
3021
  /**
2987
- * Create a Model class from a JSON model definition
2988
- * @param modelName - The name of the model
3022
+ * Convert a JSON model's properties to the schema property format Model.create and addModelsToDb take
3023
+ * @param modelName - The name of the model (for error messages)
2989
3024
  * @param modelDef - The JSON model definition
2990
- * @param schemaName - The name of the schema this model belongs to
2991
- * @returns A Model class that can be used with the SDK
3025
+ * @param propertyFileIds - Optional map of property names to their file IDs from the JSON file
2992
3026
  */
2993
- const createModelFromJson = async (modelName, modelDef, schemaName, modelFileId, // Optional modelFileId from JSON file
2994
- propertyFileIds) => {
2995
- const _mod_11 = await import('./index-Xl1_4Lmb.js');
2996
- const _ns_11 = _mod_11.f;
2997
- const modelMod = _ns_11;
2998
- const { Model } = modelMod;
2999
- // Convert JSON properties to schema format
3027
+ const jsonPropertiesToSchemaProperties = (modelName, modelDef, propertyFileIds) => {
3000
3028
  const convertedProperties = {};
3001
3029
  if (modelDef.properties) {
3002
3030
  for (const [propName, propDef] of Object.entries(modelDef.properties)) {
@@ -3055,14 +3083,30 @@ propertyFileIds) => {
3055
3083
  convertedProperties[propName] = schemaProp;
3056
3084
  }
3057
3085
  }
3086
+ return convertedProperties;
3087
+ };
3088
+ /**
3089
+ * Create a Model class from a JSON model definition
3090
+ * @param modelName - The name of the model
3091
+ * @param modelDef - The JSON model definition
3092
+ * @param schemaName - The name of the schema this model belongs to
3093
+ * @returns A Model class that can be used with the SDK
3094
+ */
3095
+ const createModelFromJson = async (modelName, modelDef, schemaName, modelFileId, // Optional modelFileId from JSON file
3096
+ propertyFileIds) => {
3097
+ const _mod_11 = await import('./index-8O3Uow-Y.js');
3098
+ const _ns_11 = _mod_11.f;
3099
+ const modelMod = _ns_11;
3100
+ const { Model } = modelMod;
3101
+ const convertedProperties = jsonPropertiesToSchemaProperties(modelName, modelDef, propertyFileIds);
3058
3102
  // Create Model instance with the definition
3059
3103
  // Pass id (schemaFileId) if provided to ensure Model instance uses correct ID
3060
3104
  // Note: indexes and description are ignored - they remain in JSON for schema file format compliance but are not used by Model instances
3061
3105
  if (modelFileId) {
3062
- logger$2(`Creating schema model "${modelName}" with modelFileId: ${modelFileId}`);
3106
+ logger$3(`Creating schema model "${modelName}" with modelFileId: ${modelFileId}`);
3063
3107
  }
3064
3108
  else {
3065
- logger$2(`Warning: Creating schema model "${modelName}" without modelFileId - it will be renamed if duplicates exist`);
3109
+ logger$3(`Warning: Creating schema model "${modelName}" without modelFileId - it will be renamed if duplicates exist`);
3066
3110
  }
3067
3111
  const modelInstance = Model.create(modelName, schemaName, {
3068
3112
  modelFileId: modelFileId, // Pass modelFileId (preferred) as id (schemaFileId) from JSON file
@@ -3088,7 +3132,7 @@ const createModelsFromJson = async (importData, modelFileIds, propertyFileIds) =
3088
3132
  // Use modelFileId from map (no fallback to modelDef.id as JsonImportSchema doesn't have id property)
3089
3133
  const finalModelFileId = modelFileId;
3090
3134
  if (!finalModelFileId) {
3091
- logger$2(`Warning: No modelFileId found for model "${modelName}" - model will be created without ID`);
3135
+ logger$3(`Warning: No modelFileId found for model "${modelName}" - model will be created without ID`);
3092
3136
  }
3093
3137
  // Get propertyFileIds for this model if available
3094
3138
  const modelPropertyFileIds = propertyFileIds?.get(modelName);
@@ -3278,7 +3322,7 @@ var SEEDPROTOCOL_Seed_Protocol_v1 = /*#__PURE__*/Object.freeze({
3278
3322
  version: version
3279
3323
  });
3280
3324
 
3281
- const logger$1 = debug('seedSdk:client:actors:processSchemaFiles');
3325
+ const logger$2 = debug('seedSdk:client:actors:processSchemaFiles');
3282
3326
  let processSchemaFilesChain = Promise.resolve();
3283
3327
  function resolveSchemaFilePath(schemaFile) {
3284
3328
  const path = BaseFileManager.getPathModule();
@@ -3306,16 +3350,22 @@ async function resolveSchemaNameFromSource(source) {
3306
3350
  }
3307
3351
  }
3308
3352
  catch (error) {
3309
- logger$1('Could not resolve schema name from path:', source, error);
3353
+ logger$2('Could not resolve schema name from path:', source, error);
3310
3354
  }
3311
3355
  }
3312
3356
  return null;
3313
3357
  }
3358
+ /** Error for a schema the app passed in config, so init fails with what went wrong and where. */
3359
+ function userSchemaLoadError(option, source, error) {
3360
+ const where = typeof source === 'string' ? ` from "${source}"` : '';
3361
+ const reason = error instanceof Error ? error.message : String(error);
3362
+ return new Error(`Could not load config.${option}${where}: ${reason}`, { cause: error });
3363
+ }
3314
3364
  // Timeout for the entire schema processing operation (120 seconds)
3315
3365
  // Schema processing can be slow with syncSchemaFromSource, loadAllSchemasFromDb, and OPFS file I/O
3316
3366
  const PROCESS_SCHEMA_FILES_TIMEOUT_MS = 120000;
3317
3367
  const processSchemaFiles = fromCallback(({ sendBack, input: { context } }) => {
3318
- logger$1('processSchemaFiles started');
3368
+ logger$2('processSchemaFiles started');
3319
3369
  let hasResponded = false;
3320
3370
  let timeoutId = null;
3321
3371
  const reportError = (error) => {
@@ -3325,7 +3375,7 @@ const processSchemaFiles = fromCallback(({ sendBack, input: { context } }) => {
3325
3375
  clearTimeout(timeoutId);
3326
3376
  timeoutId = null;
3327
3377
  }
3328
- logger$1('processSchemaFiles error:', error);
3378
+ logger$2('processSchemaFiles error:', error);
3329
3379
  sendBack({
3330
3380
  type: 'error',
3331
3381
  error: error instanceof Error ? error : new Error(String(error))
@@ -3339,7 +3389,7 @@ const processSchemaFiles = fromCallback(({ sendBack, input: { context } }) => {
3339
3389
  clearTimeout(timeoutId);
3340
3390
  timeoutId = null;
3341
3391
  }
3342
- logger$1('processSchemaFiles completed');
3392
+ logger$2('processSchemaFiles completed');
3343
3393
  sendBack({ type: ClientManagerEvents.PROCESS_SCHEMA_FILES_SUCCESS });
3344
3394
  }
3345
3395
  };
@@ -3351,7 +3401,7 @@ const processSchemaFiles = fromCallback(({ sendBack, input: { context } }) => {
3351
3401
  // Schemas written (or confirmed present) this run — skip redundant loadSchemaFromFile later
3352
3402
  const schemasWrittenThisRun = new Set();
3353
3403
  // First, load the internal seed-protocol schema
3354
- logger$1('Loading internal seed-protocol schema');
3404
+ logger$2('Loading internal seed-protocol schema');
3355
3405
  const internalSchemaData = internalSchema;
3356
3406
  const db = BaseDb.getAppDb();
3357
3407
  const internalSchemaExists = db
@@ -3360,21 +3410,21 @@ const processSchemaFiles = fromCallback(({ sendBack, input: { context } }) => {
3360
3410
  // Always mark internal schema as written so the DB/file loop does not re-apply it
3361
3411
  schemasWrittenThisRun.add(SEED_PROTOCOL_SCHEMA_NAME);
3362
3412
  if (internalSchemaExists) {
3363
- logger$1('Internal seed-protocol schema already in DB, skipping import');
3413
+ logger$2('Internal seed-protocol schema already in DB, skipping import');
3364
3414
  }
3365
3415
  else {
3366
3416
  try {
3367
3417
  // Import the internal schema to database (will create models and add to store)
3368
3418
  await importJsonSchema({ contents: JSON.stringify(internalSchemaData) }, internalSchemaData.version);
3369
- logger$1(`Loaded internal seed-protocol schema v${internalSchemaData.version}`);
3419
+ logger$2(`Loaded internal seed-protocol schema v${internalSchemaData.version}`);
3370
3420
  }
3371
3421
  catch (error) {
3372
3422
  // If schema already exists, that's fine - it means it was already loaded
3373
3423
  if (error?.message?.includes('already exists')) {
3374
- logger$1('Internal seed-protocol schema already loaded');
3424
+ logger$2('Internal seed-protocol schema already loaded');
3375
3425
  }
3376
3426
  else {
3377
- logger$1('Error loading internal seed-protocol schema:', error);
3427
+ logger$2('Error loading internal seed-protocol schema:', error);
3378
3428
  // Don't fail if internal schema can't be loaded - it might already be in DB
3379
3429
  }
3380
3430
  }
@@ -3387,7 +3437,7 @@ const processSchemaFiles = fromCallback(({ sendBack, input: { context } }) => {
3387
3437
  : '';
3388
3438
  const schemaId = typeof context.schema === 'object' && context.schema?.id ? String(context.schema.id) : undefined;
3389
3439
  if (isInternalSchema(schemaName, schemaId)) {
3390
- logger$1('Schema is internal (Seed Protocol), already loaded - skipping syncSchemaFromSource');
3440
+ logger$2('Schema is internal (Seed Protocol), already loaded - skipping syncSchemaFromSource');
3391
3441
  }
3392
3442
  else {
3393
3443
  try {
@@ -3396,11 +3446,12 @@ const processSchemaFiles = fromCallback(({ sendBack, input: { context } }) => {
3396
3446
  if (syncedName) {
3397
3447
  schemasWrittenThisRun.add(syncedName);
3398
3448
  }
3399
- logger$1(`Synced canonical schema from ${typeof context.schema === 'string' ? context.schema : 'object'}`);
3449
+ logger$2(`Synced canonical schema from ${typeof context.schema === 'string' ? context.schema : 'object'}`);
3400
3450
  }
3401
3451
  catch (error) {
3402
- logger$1(`Error syncing canonical schema:`, error);
3403
- // Don't fail init - schema might already be in DB
3452
+ // A schema the app passed in failed (missing file, bad JSON, DB write). Re-running an
3453
+ // unchanged schema does not throw, so this is not the already-loaded case: fail init.
3454
+ throw userSchemaLoadError('schema', context.schema, error);
3404
3455
  }
3405
3456
  }
3406
3457
  }
@@ -3414,23 +3465,22 @@ const processSchemaFiles = fromCallback(({ sendBack, input: { context } }) => {
3414
3465
  if (parsed?.metadata?.name) {
3415
3466
  schemasWrittenThisRun.add(String(parsed.metadata.name));
3416
3467
  }
3417
- logger$1(`Loaded schema from ${resolvedPath}`);
3468
+ logger$2(`Loaded schema from ${resolvedPath}`);
3418
3469
  }
3419
3470
  catch (error) {
3420
- logger$1(`Error loading schema file ${context.schemaFile}:`, error);
3421
- // Don't fail init - schema might already be in DB
3471
+ throw userSchemaLoadError('schemaFile', context.schemaFile, error);
3422
3472
  }
3423
3473
  }
3424
3474
  // Process minimal import files (files without $schema) - skip when canonical schema is set
3425
3475
  if (!context.schema) {
3426
- logger$1('Listing schema files');
3476
+ logger$2('Listing schema files');
3427
3477
  let schemaFiles = [];
3428
3478
  try {
3429
3479
  schemaFiles = await listSchemaFiles();
3430
- logger$1(`Found ${schemaFiles.length} schema files to process`);
3480
+ logger$2(`Found ${schemaFiles.length} schema files to process`);
3431
3481
  }
3432
3482
  catch (error) {
3433
- logger$1('Error listing schema files (continuing anyway):', error);
3483
+ logger$2('Error listing schema files (continuing anyway):', error);
3434
3484
  schemaFiles = [];
3435
3485
  }
3436
3486
  for (const schemaFile of schemaFiles) {
@@ -3441,19 +3491,19 @@ const processSchemaFiles = fromCallback(({ sendBack, input: { context } }) => {
3441
3491
  }
3442
3492
  }
3443
3493
  catch (error) {
3444
- logger$1(`Error importing schema file ${schemaFile.filePath}:`, error);
3494
+ logger$2(`Error importing schema file ${schemaFile.filePath}:`, error);
3445
3495
  }
3446
3496
  }
3447
3497
  }
3448
3498
  // Then, load all schemas using the unified database-first approach
3449
- logger$1('Loading schemas from database and files');
3499
+ logger$2('Loading schemas from database and files');
3450
3500
  let allSchemasData = [];
3451
3501
  try {
3452
3502
  allSchemasData = await loadAllSchemasFromDb();
3453
- logger$1(`Loaded ${allSchemasData.length} schemas (${allSchemasData.filter(s => s.isDraft).length} drafts, ${allSchemasData.filter(s => !s.isDraft).length} published)`);
3503
+ logger$2(`Loaded ${allSchemasData.length} schemas (${allSchemasData.filter(s => s.isDraft).length} drafts, ${allSchemasData.filter(s => !s.isDraft).length} published)`);
3454
3504
  }
3455
3505
  catch (error) {
3456
- logger$1('Error loading schemas from database (continuing anyway):', error);
3506
+ logger$2('Error loading schemas from database (continuing anyway):', error);
3457
3507
  // Continue with empty array - this is not critical for initialization
3458
3508
  // Schemas can be loaded on-demand later
3459
3509
  allSchemasData = [];
@@ -3474,13 +3524,13 @@ const processSchemaFiles = fromCallback(({ sendBack, input: { context } }) => {
3474
3524
  }
3475
3525
  }
3476
3526
  catch (error) {
3477
- logger$1('Error counting linked models (re-applying all schema files):', error);
3527
+ logger$2('Error counting linked models (re-applying all schema files):', error);
3478
3528
  }
3479
3529
  }
3480
3530
  for (const schemaData of allSchemasData) {
3481
3531
  const schema = schemaData.schema;
3482
3532
  const schemaName = schema.metadata?.name || 'unknown';
3483
- logger$1(`Processing schema: ${schemaName} v${schema.version} (${schemaData.isDraft ? 'draft' : 'published'}, source: ${schemaData.source})`);
3533
+ logger$2(`Processing schema: ${schemaName} v${schema.version} (${schemaData.isDraft ? 'draft' : 'published'}, source: ${schemaData.source})`);
3484
3534
  // For published schemas (not drafts), load models from file if available
3485
3535
  if (!schemaData.isDraft && schema.id) {
3486
3536
  // loadAllSchemasFromDb already picked the latest file for this schema (and read it)
@@ -3510,7 +3560,7 @@ const processSchemaFiles = fromCallback(({ sendBack, input: { context } }) => {
3510
3560
  }
3511
3561
  }
3512
3562
  catch (error) {
3513
- logger$1(`Error loading schema file for ${schemaName}:`, error);
3563
+ logger$2(`Error loading schema file for ${schemaName}:`, error);
3514
3564
  }
3515
3565
  }
3516
3566
  else {
@@ -3559,11 +3609,11 @@ const processSchemaFiles = fromCallback(({ sendBack, input: { context } }) => {
3559
3609
  };
3560
3610
  const modelDefinitions = await createModelsFromJson(importData, modelFileIds, propertyFileIds);
3561
3611
  Object.assign(allModels, modelDefinitions);
3562
- logger$1(`Loaded ${Object.keys(modelDefinitions).length} models from schema data for ${schemaName}`);
3612
+ logger$2(`Loaded ${Object.keys(modelDefinitions).length} models from schema data for ${schemaName}`);
3563
3613
  }
3564
3614
  }
3565
3615
  catch (error) {
3566
- logger$1(`Error creating models from schema data for ${schemaName}:`, error);
3616
+ logger$2(`Error creating models from schema data for ${schemaName}:`, error);
3567
3617
  }
3568
3618
  }
3569
3619
  }
@@ -3613,11 +3663,11 @@ const processSchemaFiles = fromCallback(({ sendBack, input: { context } }) => {
3613
3663
  };
3614
3664
  const modelDefinitions = await createModelsFromJson(importData, modelFileIds, propertyFileIds);
3615
3665
  Object.assign(allModels, modelDefinitions);
3616
- logger$1(`Loaded ${Object.keys(modelDefinitions).length} models from draft schema ${schemaName}`);
3666
+ logger$2(`Loaded ${Object.keys(modelDefinitions).length} models from draft schema ${schemaName}`);
3617
3667
  }
3618
3668
  }
3619
3669
  catch (error) {
3620
- logger$1(`Error creating models from draft schema ${schemaName}:`, error);
3670
+ logger$2(`Error creating models from draft schema ${schemaName}:`, error);
3621
3671
  }
3622
3672
  }
3623
3673
  // Schemas are now loaded on-demand via database queries (useSchemas hook uses loadAllSchemasFromDb)
@@ -3631,14 +3681,12 @@ const processSchemaFiles = fromCallback(({ sendBack, input: { context } }) => {
3631
3681
  }
3632
3682
  });
3633
3683
  };
3634
- processSchemaFilesChain = processSchemaFilesChain
3684
+ const run = processSchemaFilesChain
3635
3685
  // Its schema and model inserts check for rows first, so tabs take turns (docs/MULTI_TAB.md).
3636
- .then(() => withSeedDbLock('init', context.filesDir, _processSchemaFiles))
3637
- .catch((err) => {
3638
- logger$1('processSchemaFiles chain error:', err);
3639
- throw err;
3640
- });
3641
- processSchemaFilesChain.then(reportSuccess).catch((error) => {
3686
+ .then(() => withSeedDbLock('init', context.filesDir, _processSchemaFiles));
3687
+ // The chain only orders runs; a failed run must not fail the next init too.
3688
+ processSchemaFilesChain = run.catch(() => { });
3689
+ run.then(reportSuccess).catch((error) => {
3642
3690
  reportError(error instanceof Error ? error : new Error(String(error)));
3643
3691
  });
3644
3692
  // Cleanup function to clear timeout if actor is stopped
@@ -3650,6 +3698,285 @@ const processSchemaFiles = fromCallback(({ sendBack, input: { context } }) => {
3650
3698
  };
3651
3699
  });
3652
3700
 
3701
+ /**
3702
+ * A legacy ItemStorage draft row: a local edit (no attestation uid, not derived from one) that holds
3703
+ * the content itself in property_value, with no file reference. Item.create / createNewItem stored
3704
+ * ItemStorage values like this before they went through the save pipeline.
3705
+ */
3706
+ const isVerbatimItemStorageDraftRow = (row) => !row.uid &&
3707
+ row.derivedFromUid == null &&
3708
+ !row.refResolvedValue &&
3709
+ typeof row.propertyValue === 'string' &&
3710
+ row.propertyValue !== '';
3711
+ /**
3712
+ * Convert one legacy ItemStorage draft row (see {@link isVerbatimItemStorageDraftRow}) into the
3713
+ * shape saveItemStorage gives a row: the content goes to the file a save would write
3714
+ * (`<seedUid or seedLocalId><extension>` in the property's storage directory), and the row records
3715
+ * `refResolvedValue`, `localStorageDir` and `refValueType: 'file'` with property_value cleared.
3716
+ * Used by publish (resolveItemStorageChildFile) and the one-time migration (migrateLegacyItemStorageRows).
3717
+ *
3718
+ * Reading the row, writing the file and updating the row happen under the file's lock
3719
+ * ({@link withItemStorageFileLock}), which saveItemStorage holds too: a save in this or another tab
3720
+ * either finishes before (the row, read again once the lock is held, is no longer legacy and is
3721
+ * left alone) or starts after (and overwrites the file and row with its content). Without the lock
3722
+ * a save landing between the read and the file write would have its file overwritten with the old
3723
+ * content. The row update also stays conditional on the row being unchanged, for writers that
3724
+ * don't take the lock (a tab still running an older SDK).
3725
+ *
3726
+ * Returns undefined when there was nothing to convert. Throws when the file can't be written; the
3727
+ * row is then unchanged.
3728
+ */
3729
+ const convertVerbatimItemStorageRow = async (localId, storage = {}) => {
3730
+ const appDb = BaseDb.getAppDb();
3731
+ if (!appDb || !localId)
3732
+ return undefined;
3733
+ const targetOf = (row) => {
3734
+ if (!isVerbatimItemStorageDraftRow(row))
3735
+ return undefined;
3736
+ const seedId = storage.seedId || row.seedUid || row.seedLocalId;
3737
+ if (!seedId)
3738
+ return undefined;
3739
+ return {
3740
+ seedId,
3741
+ localStorageDir: storage.localStorageDir || row.localStorageDir,
3742
+ filenameSuffix: storage.filenameSuffix,
3743
+ };
3744
+ };
3745
+ return withLockedItemStorageRow(localId, (row) => {
3746
+ const target = targetOf(row);
3747
+ return target && getItemStorageFilePath(target);
3748
+ }, async (row) => {
3749
+ const content = row.propertyValue;
3750
+ const { fileName, filePath, localStorageDir } = await writeItemStorageFile(targetOf(row), content);
3751
+ await appDb
3752
+ .update(metadata$1)
3753
+ .set({ refResolvedValue: fileName, localStorageDir, refValueType: 'file', propertyValue: null })
3754
+ .where(and(eq(metadata$1.localId, localId), isNull(metadata$1.refResolvedValue), eq(metadata$1.propertyValue, content)));
3755
+ // Changed between the read and the update by a writer outside the lock: that change stands.
3756
+ const after = await appDb
3757
+ .select({ refResolvedValue: metadata$1.refResolvedValue, propertyValue: metadata$1.propertyValue })
3758
+ .from(metadata$1)
3759
+ .where(eq(metadata$1.localId, localId))
3760
+ .limit(1);
3761
+ if (after[0]?.refResolvedValue !== fileName || after[0]?.propertyValue != null)
3762
+ return undefined;
3763
+ return { fileName, filePath, localStorageDir, content };
3764
+ });
3765
+ };
3766
+
3767
+ const logger$1 = debug('seedSdk:db:migrateLegacyItemStorageRows');
3768
+ /** appState key recording that legacy ItemStorage rows have been written to their files. */
3769
+ const LEGACY_ITEM_STORAGE_MIGRATION_KEY = 'legacyItemStorageFiles:v1';
3770
+ /** Runs in a row that left rows unconverted because a file write failed, before giving up. */
3771
+ const LEGACY_ITEM_STORAGE_MIGRATION_MAX_ATTEMPTS = 3;
3772
+ const readMarker = async () => {
3773
+ const db = BaseDb.getAppDb();
3774
+ const rows = await db
3775
+ .select({ value: appState.value })
3776
+ .from(appState)
3777
+ .where(eq(appState.key, LEGACY_ITEM_STORAGE_MIGRATION_KEY))
3778
+ .limit(1);
3779
+ if (!rows.length)
3780
+ return undefined;
3781
+ try {
3782
+ return JSON.parse(rows[0].value ?? '');
3783
+ }
3784
+ catch {
3785
+ return null;
3786
+ }
3787
+ };
3788
+ const writeMarker = async (marker) => {
3789
+ const db = BaseDb.getAppDb();
3790
+ const now = Date.now();
3791
+ const value = JSON.stringify(marker);
3792
+ await db
3793
+ .insert(appState)
3794
+ .values({ key: LEGACY_ITEM_STORAGE_MIGRATION_KEY, value, createdAt: now, updatedAt: now })
3795
+ .onConflictDoUpdate({ target: appState.key, set: { value, updatedAt: now } });
3796
+ };
3797
+ /**
3798
+ * The storage settings of a metadata row's property: by its property_id, else by name in the
3799
+ * seed's own model (model names are only unique per schema). Undefined when it can't be told.
3800
+ */
3801
+ const createStorageResolver = () => {
3802
+ const db = BaseDb.getAppDb();
3803
+ const byPropertyId = new Map();
3804
+ const byModelAndName = new Map();
3805
+ return async (row) => {
3806
+ if (row.propertyId != null) {
3807
+ if (!byPropertyId.has(row.propertyId)) {
3808
+ const found = await db
3809
+ .select({
3810
+ storageType: properties.storageType,
3811
+ localStorageDir: properties.localStorageDir,
3812
+ filenameSuffix: properties.filenameSuffix,
3813
+ })
3814
+ .from(properties)
3815
+ .where(eq(properties.id, row.propertyId))
3816
+ .limit(1);
3817
+ byPropertyId.set(row.propertyId, found[0]);
3818
+ }
3819
+ const fromId = byPropertyId.get(row.propertyId);
3820
+ if (fromId)
3821
+ return fromId;
3822
+ }
3823
+ const modelFileId = await resolveItemModelFileId({ seedLocalId: row.seedLocalId, seedUid: row.seedUid });
3824
+ if (!modelFileId || !row.propertyName)
3825
+ return undefined;
3826
+ const key = `${modelFileId}\u0000${row.propertyName}`;
3827
+ if (!byModelAndName.has(key)) {
3828
+ const found = await db
3829
+ .select({
3830
+ storageType: properties.storageType,
3831
+ localStorageDir: properties.localStorageDir,
3832
+ filenameSuffix: properties.filenameSuffix,
3833
+ })
3834
+ .from(properties)
3835
+ .innerJoin(models$1, eq(properties.modelId, models$1.id))
3836
+ .where(and(eq(models$1.schemaFileId, modelFileId), eq(properties.name, row.propertyName)))
3837
+ .limit(1);
3838
+ byModelAndName.set(key, found[0]);
3839
+ }
3840
+ return byModelAndName.get(key);
3841
+ };
3842
+ };
3843
+ /** True if `row` is the row readers show for its property: the newest of its seed's rows by that name. */
3844
+ const isNewestRowOfProperty = async (row) => {
3845
+ if (!row.seedLocalId || !row.propertyName)
3846
+ return false;
3847
+ const db = BaseDb.getAppDb();
3848
+ const siblings = await db
3849
+ .select()
3850
+ .from(metadata$1)
3851
+ .where(and(eq(metadata$1.seedLocalId, row.seedLocalId), eq(metadata$1.propertyName, row.propertyName)));
3852
+ return [...siblings].sort(compareMetadataRowsLatestFirst)[0]?.localId === row.localId;
3853
+ };
3854
+ /**
3855
+ * One-time data migration: writes the content of legacy ItemStorage draft rows to their files.
3856
+ *
3857
+ * Before Item.create / createNewItem saved ItemStorage values through the save pipeline, a value
3858
+ * given at creation was stored verbatim in metadata.property_value with no file. Publish converts
3859
+ * such a row lazily (resolveItemStorageChildFile); this converts them all up front, with the same
3860
+ * code ({@link convertVerbatimItemStorageRow}), so every ItemStorage draft has the shape a save
3861
+ * gives it: the content in `<seedUid or seedLocalId><extension>`, the row holding
3862
+ * refResolvedValue / localStorageDir / refValueType 'file' and no property_value.
3863
+ *
3864
+ * Only local drafts (no uid, not derived from an attestation) of properties whose properties row
3865
+ * says `storage_type = 'ItemStorage'` are touched, and of those only the newest row of each
3866
+ * seed's property: that is the row reads show and saves write to, and older rows sharing the one
3867
+ * file name would overwrite it with older content. Published and synced rows are never changed.
3868
+ *
3869
+ * A row that fails is logged and left as it was (publish still converts it). The run is recorded
3870
+ * in appState under {@link LEGACY_ITEM_STORAGE_MIGRATION_KEY}; a run with failed rows is retried
3871
+ * on the next start, up to {@link LEGACY_ITEM_STORAGE_MIGRATION_MAX_ATTEMPTS} runs. Safe to run
3872
+ * again regardless: a converted row no longer matches.
3873
+ *
3874
+ * @param options.force run even when the marker says it is done
3875
+ */
3876
+ async function migrateLegacyItemStorageRows(options = {}) {
3877
+ const result = {
3878
+ alreadyDone: false,
3879
+ candidates: 0,
3880
+ converted: 0,
3881
+ failed: 0,
3882
+ skipped: 0,
3883
+ };
3884
+ const db = BaseDb.getAppDb();
3885
+ if (!db)
3886
+ return { ...result, alreadyDone: true };
3887
+ const marker = await readMarker();
3888
+ const previousAttempts = marker?.status === 'retry' ? marker.attempts : 0;
3889
+ if (!options.force && marker && marker.status === 'done') {
3890
+ return { ...result, alreadyDone: true };
3891
+ }
3892
+ const itemStorageNames = (await db
3893
+ .selectDistinct({ name: properties.name })
3894
+ .from(properties)
3895
+ .where(eq(properties.storageType, 'ItemStorage'))).map((r) => r.name);
3896
+ const candidates = itemStorageNames.length
3897
+ ? await db
3898
+ .select()
3899
+ .from(metadata$1)
3900
+ .where(and(inArray(metadata$1.propertyName, itemStorageNames), or(isNull(metadata$1.uid), eq(metadata$1.uid, '')), isNull(metadata$1.derivedFromUid), isNull(metadata$1.refResolvedValue), isNotNull(metadata$1.propertyValue), ne(metadata$1.propertyValue, '')))
3901
+ : [];
3902
+ const resolveStorage = createStorageResolver();
3903
+ for (const row of candidates) {
3904
+ if (!row.localId || !isVerbatimItemStorageDraftRow(row))
3905
+ continue;
3906
+ try {
3907
+ const storage = await resolveStorage(row);
3908
+ if (storage?.storageType !== 'ItemStorage')
3909
+ continue;
3910
+ result.candidates++;
3911
+ if (!(await isNewestRowOfProperty(row))) {
3912
+ result.skipped++;
3913
+ continue;
3914
+ }
3915
+ const converted = await convertVerbatimItemStorageRow(row.localId, {
3916
+ localStorageDir: storage.localStorageDir,
3917
+ filenameSuffix: storage.filenameSuffix,
3918
+ });
3919
+ if (converted) {
3920
+ result.converted++;
3921
+ logger$1(`wrote ${row.propertyName} of ${row.seedLocalId} to ${converted.filePath}`);
3922
+ }
3923
+ else {
3924
+ result.skipped++;
3925
+ }
3926
+ }
3927
+ catch (error) {
3928
+ result.failed++;
3929
+ logger$1(`converting ${row.propertyName} of ${row.seedLocalId} (${row.localId}) failed; left as is`, error);
3930
+ }
3931
+ }
3932
+ const attempts = previousAttempts + 1;
3933
+ await writeMarker({
3934
+ status: result.failed > 0 && attempts < LEGACY_ITEM_STORAGE_MIGRATION_MAX_ATTEMPTS ? 'retry' : 'done',
3935
+ attempts,
3936
+ converted: result.converted,
3937
+ failed: result.failed,
3938
+ at: Date.now(),
3939
+ });
3940
+ if (result.candidates > 0) {
3941
+ logger$1(`legacy ItemStorage rows: ${result.converted} converted, ${result.failed} failed, ` +
3942
+ `${result.skipped} skipped of ${result.candidates}`);
3943
+ }
3944
+ return result;
3945
+ }
3946
+ let running;
3947
+ let deferredUntilLeader = false;
3948
+ const runInBackground = () => {
3949
+ running ?? (running = withDbTabLock('item-storage-migration', () => migrateLegacyItemStorageRows())
3950
+ .then(() => undefined)
3951
+ .catch((error) => {
3952
+ // Never fails init: rows stay as they were and publish converts them lazily.
3953
+ logger$1('legacy ItemStorage migration failed', error);
3954
+ })
3955
+ .finally(() => {
3956
+ running = undefined;
3957
+ }));
3958
+ return running;
3959
+ };
3960
+ /**
3961
+ * Starts {@link migrateLegacyItemStorageRows} in the background once client init has finished
3962
+ * (the properties table then holds the current storage settings). It runs in the leader tab only
3963
+ * (docs/MULTI_TAB.md), under a `seed:item-storage-migration:<db>` lock in case several tabs lead
3964
+ * (`multiTab: 'off'`); a tab that isn't leader runs it if it takes over. Never throws.
3965
+ */
3966
+ function startLegacyItemStorageMigration() {
3967
+ if (isLeaderTab()) {
3968
+ void runInBackground();
3969
+ return;
3970
+ }
3971
+ if (deferredUntilLeader)
3972
+ return;
3973
+ deferredUntilLeader = true;
3974
+ void whenLeaderTab().then(() => {
3975
+ deferredUntilLeader = false;
3976
+ void runInBackground();
3977
+ });
3978
+ }
3979
+
3653
3980
  const { UNINITIALIZED, PLATFORM_CLASSES_INIT, FILE_SYSTEM_INIT, DB_INIT, SAVE_CONFIG, PROCESS_SCHEMA_FILES, ADD_MODELS_TO_STORE, ADD_MODELS_TO_DB, IDLE, INIT_FAILED, } = ClientManagerState;
3654
3981
  const { UPDATE_CONTEXT, PLATFORM_CLASSES_READY, FILE_SYSTEM_READY, DB_READY, SAVE_CONFIG_SUCCESS, SAVE_APP_STATE_SUCCESS, SAVE_APP_STATE_ERROR, SET_ADDRESSES, ADD_MODELS_TO_STORE_SUCCESS, ADD_MODELS_TO_DB_SUCCESS, PROCESS_SCHEMA_FILES_SUCCESS, } = ClientManagerEvents;
3655
3982
  const logSyncAfterAddressSave = debug("seedSdk:client:clientManagerMachine:syncAfterAddressSave");
@@ -3870,9 +4197,15 @@ const clientManagerMachine = setup({
3870
4197
  },
3871
4198
  },
3872
4199
  [IDLE]: {
3873
- entry: assign({
3874
- isInitialized: true,
3875
- }),
4200
+ entry: [
4201
+ assign({
4202
+ isInitialized: true,
4203
+ }),
4204
+ // One-time data migration that writes files, so it can't be a SQL migration in prepareDb.
4205
+ // In the background after init: the app is usable at once, the properties table holds the
4206
+ // current storage settings by now, and a failure never fails init.
4207
+ () => startLegacyItemStorageMigration(),
4208
+ ],
3876
4209
  on: {
3877
4210
  [SAVE_APP_STATE_SUCCESS]: {
3878
4211
  actions: [
@@ -4486,6 +4819,7 @@ const emptyResult = () => ({
4486
4819
  seeds: 0,
4487
4820
  versions: 0,
4488
4821
  metadata: 0,
4822
+ seedLocalIds: [],
4489
4823
  });
4490
4824
  /**
4491
4825
  * Stamp local seeds/versions/metadata that have no publisher and no real uid.
@@ -4514,22 +4848,23 @@ async function claimUnpublishedDrafts(publisher) {
4514
4848
  isLocalUnsealedDraft(row))
4515
4849
  .map((row) => row.localId);
4516
4850
  if (ids.length === 0)
4517
- return 0;
4851
+ return [];
4518
4852
  await appDb
4519
4853
  .update(table)
4520
4854
  .set({ publisher: normalized, updatedAt: now })
4521
4855
  .where(inArray(table.localId, ids));
4522
- return ids.length;
4856
+ return ids;
4523
4857
  };
4524
- const [seedCount, versionCount, metadataCount] = await Promise.all([
4858
+ const [seedIds, versionIds, metadataIds] = await Promise.all([
4525
4859
  claimTable(seeds),
4526
4860
  claimTable(versions),
4527
4861
  claimTable(metadata$1),
4528
4862
  ]);
4529
4863
  return {
4530
- seeds: seedCount,
4531
- versions: versionCount,
4532
- metadata: metadataCount,
4864
+ seeds: seedIds.length,
4865
+ versions: versionIds.length,
4866
+ metadata: metadataIds.length,
4867
+ seedLocalIds: seedIds,
4533
4868
  };
4534
4869
  }
4535
4870
 
@@ -4547,11 +4882,97 @@ const subscription = clientManager.subscribe((snapshot) => {
4547
4882
  logger('ClientManager snapshot.context.isInitialized:', snapshot.context.isInitialized);
4548
4883
  });
4549
4884
  clientManager.start();
4885
+ /** Config of the init that is running or has succeeded; cleared when init fails or the client stops. */
4886
+ let activeInitConfig;
4887
+ const INIT_CONFIG_CONFLICT_MESSAGE = 'client.init was already called with a different config. The SDK keeps the config it was ' +
4888
+ 'initialised with: pass the same config, or call client.stop() before initialising with a new one. ' +
4889
+ 'To change addresses, use client.setAddresses() (or call init again with the same config and new addresses).';
4550
4890
  const ensureInitialized = () => {
4551
4891
  if (!clientManager.getSnapshot().context.isInitialized) {
4552
4892
  throw new Error(CLIENT_NOT_INITIALIZED);
4553
4893
  }
4554
4894
  };
4895
+ const coalescedInit = createCoalescedAsync(async (options) => {
4896
+ // If the actor is stopped (e.g., from a previous failed test), restart it
4897
+ const snapshot = clientManager.getSnapshot();
4898
+ const currentState = snapshot.value;
4899
+ const isStopped = snapshot.status === 'stopped';
4900
+ if (isStopped) {
4901
+ logger('Client manager was stopped, restarting...');
4902
+ clientManager.start();
4903
+ // Wait for the actor to be ready
4904
+ try {
4905
+ await waitFor(clientManager, (snapshot) => snapshot.status !== 'stopped', { timeout: 1000 });
4906
+ }
4907
+ catch (e) {
4908
+ logger('Timeout waiting for actor to restart, continuing anyway...');
4909
+ }
4910
+ }
4911
+ // Clear any stale context from previous failed initializations
4912
+ // This ensures we start with a clean slate before the new init updates it
4913
+ if (currentState !== 'uninitialized') {
4914
+ logger(`Client manager is in state ${currentState}, clearing stale context before re-init...`);
4915
+ clientManager.send({
4916
+ type: 'updateContext',
4917
+ context: {
4918
+ isInitialized: false,
4919
+ addressesSet: false,
4920
+ isSaving: false,
4921
+ syncFromEasOnAddressChange: false,
4922
+ endpoints: undefined,
4923
+ addresses: undefined,
4924
+ ownedAddresses: undefined,
4925
+ watchedAddresses: undefined,
4926
+ models: undefined,
4927
+ arweaveDomain: undefined,
4928
+ filesDir: undefined,
4929
+ dbConfig: undefined,
4930
+ initError: undefined,
4931
+ saveError: undefined,
4932
+ }
4933
+ });
4934
+ // Wait a moment for the context update to be processed
4935
+ await new Promise(resolve => setTimeout(resolve, 10));
4936
+ }
4937
+ // Send init event - the root-level handler will transition to PLATFORM_CLASSES_INIT
4938
+ // which will stop any running actors and start fresh with the new options
4939
+ // The platformClassesInit actor will update the context with the correct endpoints from options
4940
+ clientManager.send({ type: 'init', options });
4941
+ // Wait for the state machine to transition to PLATFORM_CLASSES_INIT to ensure
4942
+ // any old actors are stopped and the new initialization flow begins
4943
+ try {
4944
+ await waitFor(clientManager, (snapshot) => {
4945
+ return snapshot.value === 'platformClassesInit' || snapshot.context.isInitialized;
4946
+ }, { timeout: 1000 });
4947
+ }
4948
+ catch (e) {
4949
+ // If we can't transition, continue anyway - the waitFor below will catch any errors
4950
+ logger('Timeout waiting for state transition, continuing...');
4951
+ }
4952
+ try {
4953
+ await waitFor(clientManager, (snapshot) => {
4954
+ return snapshot.context.isInitialized || snapshot.context.initError != null;
4955
+ }, { timeout: 120000 });
4956
+ const initError = clientManager.getSnapshot().context.initError;
4957
+ if (initError) {
4958
+ throw initError instanceof Error ? initError : new Error(String(initError));
4959
+ }
4960
+ }
4961
+ catch (error) {
4962
+ // Ensure we never throw undefined
4963
+ if (error === undefined || error === null) {
4964
+ throw new Error('Initialization failed with undefined error');
4965
+ }
4966
+ throw error;
4967
+ }
4968
+ // Wire `@seedprotocol/query` local source once DB is ready
4969
+ registerSeedQueryLocalSource({ force: true });
4970
+ }, () => {
4971
+ const snapshot = clientManager.getSnapshot();
4972
+ return (snapshot.value === ClientManagerState.IDLE &&
4973
+ snapshot.context.isInitialized === true &&
4974
+ !snapshot.context.initError);
4975
+ });
4555
4976
  // Singleton instance - created once at module load time
4556
4977
  // ES modules cache exports, ensuring all imports get the same instance
4557
4978
  const clientInstance = {
@@ -4562,87 +4983,32 @@ const clientInstance = {
4562
4983
  // ensureInitialized();
4563
4984
  return clientManager;
4564
4985
  },
4565
- init: createCoalescedAsync(async (options) => {
4566
- // If the actor is stopped (e.g., from a previous failed test), restart it
4567
- const snapshot = clientManager.getSnapshot();
4568
- const currentState = snapshot.value;
4569
- const isStopped = snapshot.status === 'stopped';
4570
- if (isStopped) {
4571
- logger('Client manager was stopped, restarting...');
4572
- clientManager.start();
4573
- // Wait for the actor to be ready
4574
- try {
4575
- await waitFor(clientManager, (snapshot) => snapshot.status !== 'stopped', { timeout: 1000 });
4576
- }
4577
- catch (e) {
4578
- logger('Timeout waiting for actor to restart, continuing anyway...');
4579
- }
4580
- }
4581
- // Clear any stale context from previous failed initializations
4582
- // This ensures we start with a clean slate before the new init updates it
4583
- if (currentState !== 'uninitialized') {
4584
- logger(`Client manager is in state ${currentState}, clearing stale context before re-init...`);
4585
- clientManager.send({
4586
- type: 'updateContext',
4587
- context: {
4588
- isInitialized: false,
4589
- addressesSet: false,
4590
- isSaving: false,
4591
- syncFromEasOnAddressChange: false,
4592
- endpoints: undefined,
4593
- addresses: undefined,
4594
- ownedAddresses: undefined,
4595
- watchedAddresses: undefined,
4596
- models: undefined,
4597
- arweaveDomain: undefined,
4598
- filesDir: undefined,
4599
- dbConfig: undefined,
4600
- initError: undefined,
4601
- saveError: undefined,
4602
- }
4603
- });
4604
- // Wait a moment for the context update to be processed
4605
- await new Promise(resolve => setTimeout(resolve, 10));
4606
- }
4607
- // Send init event - the root-level handler will transition to PLATFORM_CLASSES_INIT
4608
- // which will stop any running actors and start fresh with the new options
4609
- // The platformClassesInit actor will update the context with the correct endpoints from options
4610
- clientManager.send({ type: 'init', options });
4611
- // Wait for the state machine to transition to PLATFORM_CLASSES_INIT to ensure
4612
- // any old actors are stopped and the new initialization flow begins
4613
- try {
4614
- await waitFor(clientManager, (snapshot) => {
4615
- return snapshot.value === 'platformClassesInit' || snapshot.context.isInitialized;
4616
- }, { timeout: 1000 });
4617
- }
4618
- catch (e) {
4619
- // If we can't transition, continue anyway - the waitFor below will catch any errors
4620
- logger('Timeout waiting for state transition, continuing...');
4986
+ /**
4987
+ * Initialise the SDK. Calls made while an init is running share it. Once initialised, a
4988
+ * call with the same config resolves at once and applies any change in `addresses`; a
4989
+ * call with a different config throws INIT_CONFIG_CONFLICT_MESSAGE (call stop() first).
4990
+ */
4991
+ init: async (options) => {
4992
+ if (activeInitConfig !== undefined && !isEqual(activeInitConfig, options?.config)) {
4993
+ throw new Error(INIT_CONFIG_CONFLICT_MESSAGE);
4621
4994
  }
4995
+ const isRepeat = activeInitConfig !== undefined;
4996
+ activeInitConfig = options?.config;
4622
4997
  try {
4623
- await waitFor(clientManager, (snapshot) => {
4624
- return snapshot.context.isInitialized || snapshot.context.initError != null;
4625
- }, { timeout: 120000 });
4626
- const initError = clientManager.getSnapshot().context.initError;
4627
- if (initError) {
4628
- throw initError instanceof Error ? initError : new Error(String(initError));
4629
- }
4998
+ await coalescedInit(options);
4630
4999
  }
4631
5000
  catch (error) {
4632
- // Ensure we never throw undefined
4633
- if (error === undefined || error === null) {
4634
- throw new Error('Initialization failed with undefined error');
4635
- }
5001
+ activeInitConfig = undefined;
4636
5002
  throw error;
4637
5003
  }
4638
- // Wire `@seedprotocol/query` local source once DB is ready
4639
- registerSeedQueryLocalSource({ force: true });
4640
- }, () => {
4641
- const snapshot = clientManager.getSnapshot();
4642
- return (snapshot.value === ClientManagerState.IDLE &&
4643
- snapshot.context.isInitialized === true &&
4644
- !snapshot.context.initError);
4645
- }),
5004
+ if (isRepeat && options?.addresses !== undefined) {
5005
+ const wanted = normalizeAddressConfig(options.addresses);
5006
+ const current = { owned: await getOwnedAddressesFromDb(), watched: await getWatchedAddressesFromDb() };
5007
+ if (!isEqual(wanted, current)) {
5008
+ await clientInstance.setAddresses(wanted);
5009
+ }
5010
+ }
5011
+ },
4646
5012
  setAddresses: async (addresses) => {
4647
5013
  ensureInitialized();
4648
5014
  logger('setAddresses', addresses);
@@ -4675,7 +5041,10 @@ const clientInstance = {
4675
5041
  */
4676
5042
  claimUnpublishedDrafts: async (publisher) => {
4677
5043
  ensureInitialized();
4678
- return claimUnpublishedDrafts(publisher);
5044
+ const result = await claimUnpublishedDrafts(publisher);
5045
+ // Loaded Items read publisher from their context; give the claimed ones the new value.
5046
+ Item.setPublisherForCachedSeeds(result.seedLocalIds, publisher);
5047
+ return result;
4679
5048
  },
4680
5049
  /**
4681
5050
  * Hard-delete local on-chain seed copies for the given publisher addresses.
@@ -4730,21 +5099,38 @@ const clientInstance = {
4730
5099
  // Global service removed - model registration is now handled by ClientManager
4731
5100
  // Models are added to DB during the ADD_MODELS_TO_DB state
4732
5101
  },
5102
+ /**
5103
+ * Calls `callback` once the client is initialised, or on the next microtask if it already
5104
+ * is. Returns a function that cancels the callback.
5105
+ */
4733
5106
  onReady: (callback) => {
5107
+ if (clientManager.getSnapshot().context.isInitialized) {
5108
+ let cancelled = false;
5109
+ queueMicrotask(() => {
5110
+ if (!cancelled)
5111
+ callback();
5112
+ });
5113
+ return () => {
5114
+ cancelled = true;
5115
+ };
5116
+ }
4734
5117
  const subscription = clientManager.subscribe((snapshot) => {
4735
5118
  if (snapshot.context.isInitialized) {
4736
5119
  subscription.unsubscribe();
4737
5120
  callback();
4738
5121
  }
4739
5122
  });
5123
+ return () => subscription.unsubscribe();
4740
5124
  },
4741
5125
  stop: () => {
4742
5126
  ensureInitialized();
5127
+ activeInitConfig = undefined;
4743
5128
  unregisterSeedQueryLocalSource();
4744
5129
  clientManager.stop();
4745
5130
  },
4746
5131
  unload: () => {
4747
5132
  ensureInitialized();
5133
+ activeInitConfig = undefined;
4748
5134
  unregisterSeedQueryLocalSource();
4749
5135
  clientManager.stop();
4750
5136
  subscription.unsubscribe();
@@ -4760,9 +5146,10 @@ const getClient = () => {
4760
5146
  var ClientManager$1 = /*#__PURE__*/Object.freeze({
4761
5147
  __proto__: null,
4762
5148
  ClientManager: ClientManager,
5149
+ INIT_CONFIG_CONFLICT_MESSAGE: INIT_CONFIG_CONFLICT_MESSAGE,
4763
5150
  clientManager: clientManager,
4764
5151
  getClient: getClient
4765
5152
  });
4766
5153
 
4767
- export { startEasSyncActor as A, unregisterSeedQueryLocalSource as B, ClientManager as C, createModelsFromJson as D, EAS_CHAIN_ID_APP_STATE_KEY as E, getLatestSchemaVersion as F, schema as G, ClientManager$1 as H, SEEDPROTOCOL_Seed_Protocol_v1 as S, assertLocalDbChain as a, getRefValueType as b, claimUnpublishedDrafts as c, createLocalQueryDataSource as d, createSchema as e, easSyncActor as f, getContentHash as g, getClient as h, importJsonSchema as i, getPublishedSeedRecord as j, getSchemaNameFromId as k, loadSchemaFromFile as l, isSeedQueryLocalSourceRegistered as m, listCompleteSchemaFiles as n, loadAllSchemasFromDb as o, mergeEasSyncRequestIntents as p, readSchema as q, readJsonImportFile as r, syncSchemaFromSource as s, transformImportToSchemaFile as t, registerSeedQueryLocalSource as u, requestEasSyncFromAddressChange as v, waitForEasReadChain as w, requestEasSyncFromEventBus as x, requestEasSyncFromModelsInit as y, sendEasSyncClientRequest as z };
4768
- //# sourceMappingURL=ClientManager-DDA9956Y.js.map
5154
+ export { requestEasSyncFromModelsInit as A, sendEasSyncClientRequest as B, ClientManager as C, startEasSyncActor as D, EAS_CHAIN_ID_APP_STATE_KEY as E, unregisterSeedQueryLocalSource as F, createModelsFromJson as G, getLatestSchemaVersion as H, INIT_CONFIG_CONFLICT_MESSAGE as I, jsonPropertiesToSchemaProperties as J, schema as K, ClientManager$1 as L, SEEDPROTOCOL_Seed_Protocol_v1 as S, assertLocalDbChain as a, importJsonSchema as b, convertVerbatimItemStorageRow as c, getContentHash as d, claimUnpublishedDrafts as e, createLocalQueryDataSource as f, getRefValueType as g, createSchema as h, isVerbatimItemStorageDraftRow as i, easSyncActor as j, getClient as k, loadSchemaFromFile as l, getPublishedSeedRecord as m, getSchemaNameFromId as n, isSeedQueryLocalSourceRegistered as o, listCompleteSchemaFiles as p, loadAllSchemasFromDb as q, readJsonImportFile as r, syncSchemaFromSource as s, transformImportToSchemaFile as t, mergeEasSyncRequestIntents as u, readSchema as v, waitForEasReadChain as w, registerSeedQueryLocalSource as x, requestEasSyncFromAddressChange as y, requestEasSyncFromEventBus as z };
5155
+ //# sourceMappingURL=ClientManager-i3nJASkg.js.map