@seedprotocol/sdk 0.6.10 → 0.7.1

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 (399) hide show
  1. package/dist/{BasePathResolver-B6CKqoKw.js → BasePathResolver-DRT09oVv.js} +36 -2
  2. package/dist/BasePathResolver-DRT09oVv.js.map +1 -0
  3. package/dist/ClientManager-DngaZdw6.js +4763 -0
  4. package/dist/ClientManager-DngaZdw6.js.map +1 -0
  5. package/dist/{ClientManager-ChcmUL47.js → Item-ZUAmf943.js} +1175 -5903
  6. package/dist/Item-ZUAmf943.js.map +1 -0
  7. package/dist/{ModelProperty-D79uV42p.js → ModelProperty-6llK4MTH.js} +326 -109
  8. package/dist/ModelProperty-6llK4MTH.js.map +1 -0
  9. package/dist/{Schema-a8uO-hIZ.js → Schema-D-Ud-XYw.js} +164 -885
  10. package/dist/Schema-D-Ud-XYw.js.map +1 -0
  11. package/dist/{SchemaValidationService-Y49vqast.js → SchemaValidationService-IoS7JquP.js} +26 -18
  12. package/dist/SchemaValidationService-IoS7JquP.js.map +1 -0
  13. package/dist/{backfillMetadataPropertyIds-CBsf7LnU.js → backfillMetadataPropertyIds-BlVeE7w7.js} +11 -6
  14. package/dist/backfillMetadataPropertyIds-BlVeE7w7.js.map +1 -0
  15. package/dist/cjs/{ModelProperty-D9FGaGuE.js → ModelProperty-Dv7AQfmQ.js} +297 -89
  16. package/dist/cjs/ModelProperty-Dv7AQfmQ.js.map +1 -0
  17. package/dist/cjs/{Schema-BiJIPLEL.js → Schema-BHVp1g-M.js} +136 -868
  18. package/dist/cjs/Schema-BHVp1g-M.js.map +1 -0
  19. package/dist/cjs/{SchemaValidationService-DtYs_CNY.js → SchemaValidationService-BSU9knjf.js} +18 -11
  20. package/dist/cjs/SchemaValidationService-BSU9knjf.js.map +1 -0
  21. package/dist/cjs/{backfillMetadataPropertyIds-2XaN3b9S.js → backfillMetadataPropertyIds-WIovQ_d8.js} +8 -3
  22. package/dist/cjs/backfillMetadataPropertyIds-WIovQ_d8.js.map +1 -0
  23. package/dist/cjs/{eas-CMNppmGE.js → eas-CUYXdr2t.js} +4 -4
  24. package/dist/cjs/{eas-CMNppmGE.js.map → eas-CUYXdr2t.js.map} +1 -1
  25. package/dist/cjs/{getItem-B6jEINjW.js → getItem-z1tHu0hu.js} +2 -2
  26. package/dist/cjs/{getItem-B6jEINjW.js.map → getItem-z1tHu0hu.js.map} +1 -1
  27. package/dist/cjs/getLatestVersionRow-CcaabxIW.js +59 -0
  28. package/dist/cjs/getLatestVersionRow-CcaabxIW.js.map +1 -0
  29. package/dist/cjs/{getPublishPayload-D5DhLGvN.js → getPublishPayload-CEP_e-Kv.js} +283 -138
  30. package/dist/cjs/getPublishPayload-CEP_e-Kv.js.map +1 -0
  31. package/dist/cjs/{getPublishUploads-DMhCCKYF.js → getPublishUploads-Ctn5k1k6.js} +65 -19
  32. package/dist/cjs/getPublishUploads-Ctn5k1k6.js.map +1 -0
  33. package/dist/cjs/{index-CSNtEnbF.js → index-Cvvt0-5B.js} +2698 -1725
  34. package/dist/cjs/index-Cvvt0-5B.js.map +1 -0
  35. package/dist/cjs/{index-DPp9rdRL.js → index-DfGhF1dc.js} +3 -3
  36. package/dist/cjs/index-DfGhF1dc.js.map +1 -0
  37. package/dist/cjs/{property-DlKiAWt4.js → property-DbEPQ1m9.js} +40 -35
  38. package/dist/cjs/property-DbEPQ1m9.js.map +1 -0
  39. package/dist/cjs/publishDraftGraph-C38gf302.js +403 -0
  40. package/dist/cjs/publishDraftGraph-C38gf302.js.map +1 -0
  41. package/dist/cjs/resetAmbiguousLegacyItemData-CfMhRHwK.js +116 -0
  42. package/dist/cjs/resetAmbiguousLegacyItemData-CfMhRHwK.js.map +1 -0
  43. package/dist/cjs/resolveModelForSyncedSeed-CNYaLOir.js +49 -0
  44. package/dist/cjs/resolveModelForSyncedSeed-CNYaLOir.js.map +1 -0
  45. package/dist/cjs/syncDbWithEas-d1iOdTTI.js +886 -0
  46. package/dist/cjs/syncDbWithEas-d1iOdTTI.js.map +1 -0
  47. package/dist/{configurePlatform-CE0Vew17.js → configurePlatform-CZpjyuCo.js} +4 -4
  48. package/dist/{configurePlatform-CE0Vew17.js.map → configurePlatform-CZpjyuCo.js.map} +1 -1
  49. package/dist/db/drizzle/0015_add_model_file_id_to_seeds.sql +11 -0
  50. package/dist/db/drizzle/0016_add_revoked_at_to_metadata.sql +1 -0
  51. package/dist/db/drizzle/0017_add_revoked_at_to_versions.sql +1 -0
  52. package/dist/db/drizzle/0018_add_storage_settings_to_properties.sql +53 -0
  53. package/dist/db/drizzle/0019_add_derived_from_uid_to_metadata.sql +35 -0
  54. package/dist/db/drizzle/meta/0011_snapshot.json +1182 -0
  55. package/dist/db/drizzle/meta/0012_snapshot.json +1244 -0
  56. package/dist/db/drizzle/meta/0013_snapshot.json +63 -1
  57. package/dist/db/drizzle/meta/0014_snapshot.json +62 -0
  58. package/dist/db/drizzle/meta/0015_snapshot.json +1338 -0
  59. package/dist/db/drizzle/meta/0016_snapshot.json +1345 -0
  60. package/dist/db/drizzle/meta/0017_snapshot.json +1352 -0
  61. package/dist/db/drizzle/meta/0018_snapshot.json +1373 -0
  62. package/dist/db/drizzle/meta/0019_snapshot.json +1380 -0
  63. package/dist/db/drizzle/meta/_journal.json +35 -0
  64. package/dist/{db-WbrzEf7c.js → db-Lw0KVZmc.js} +546 -106
  65. package/dist/db-Lw0KVZmc.js.map +1 -0
  66. package/dist/{eas-CfYCu4IX.js → eas-CQ-Smzk2.js} +7 -7
  67. package/dist/eas-CQ-Smzk2.js.map +1 -0
  68. package/dist/errors-CrBxGWah.js +17 -0
  69. package/dist/errors-CrBxGWah.js.map +1 -0
  70. package/dist/{getItem-Br-bGNFO.js → getItem-CSfSok9f.js} +8 -10
  71. package/dist/{getItem-Br-bGNFO.js.map → getItem-CSfSok9f.js.map} +1 -1
  72. package/dist/getLatestVersionRow-72Atl9vB.js +46 -0
  73. package/dist/getLatestVersionRow-72Atl9vB.js.map +1 -0
  74. package/dist/{getPublishPayload-BIrTVUxb.js → getPublishPayload-76_KfB5Y.js} +297 -154
  75. package/dist/getPublishPayload-76_KfB5Y.js.map +1 -0
  76. package/dist/{getPublishUploads-C6cDeZdz.js → getPublishUploads-CqgMBD8f.js} +68 -21
  77. package/dist/getPublishUploads-CqgMBD8f.js.map +1 -0
  78. package/dist/{index-Djd3667v.js → index-5b3JsS55.js} +2 -2
  79. package/dist/index-5b3JsS55.js.map +1 -0
  80. package/dist/{index-ClSv5pTA.js → index-BpgD305l.js} +12 -11
  81. package/dist/index-BpgD305l.js.map +1 -0
  82. package/dist/{index-HRHkbVQd.js → index-Y-yYyRBf.js} +530 -196
  83. package/dist/index-Y-yYyRBf.js.map +1 -0
  84. package/dist/index.browser-DaTzn79x.js +4139 -0
  85. package/dist/index.browser-DaTzn79x.js.map +1 -0
  86. package/dist/{index.node-DBtQkEfz.js → index.node-NYKqFOoe.js} +9 -4
  87. package/dist/index.node-NYKqFOoe.js.map +1 -0
  88. package/dist/main.cjs +1 -1
  89. package/dist/main.js +886 -560
  90. package/dist/main.js.map +1 -1
  91. package/dist/node.js +19 -15
  92. package/dist/node.js.map +1 -1
  93. package/dist/platform.browser.js +18 -3719
  94. package/dist/platform.browser.js.map +1 -1
  95. package/dist/platform.node.js +3 -3
  96. package/dist/{property-CQjuZ4JW.js → property-ByaiSyUK.js} +53 -48
  97. package/dist/property-ByaiSyUK.js.map +1 -0
  98. package/dist/publishDraftGraph-BRm6Pq3Q.js +405 -0
  99. package/dist/publishDraftGraph-BRm6Pq3Q.js.map +1 -0
  100. package/dist/resetAmbiguousLegacyItemData-B4dX6ZA1.js +88 -0
  101. package/dist/resetAmbiguousLegacyItemData-B4dX6ZA1.js.map +1 -0
  102. package/dist/resolveModelForSyncedSeed-B0tco3zG.js +46 -0
  103. package/dist/resolveModelForSyncedSeed-B0tco3zG.js.map +1 -0
  104. package/dist/seedSchema/MetadataSchema.ts +9 -0
  105. package/dist/seedSchema/ModelSchema.ts +5 -0
  106. package/dist/seedSchema/SeedSchema.ts +3 -0
  107. package/dist/seedSchema/VersionSchema.ts +5 -0
  108. package/dist/src/Item/Item.d.ts +21 -0
  109. package/dist/src/Item/Item.d.ts.map +1 -1
  110. package/dist/src/Item/service/actors/loadOrCreateItem.d.ts.map +1 -1
  111. package/dist/src/Item/service/actors/waitForDb.d.ts.map +1 -1
  112. package/dist/src/Item/service/itemMachineSingle.d.ts +3 -29
  113. package/dist/src/Item/service/itemMachineSingle.d.ts.map +1 -1
  114. package/dist/src/ItemProperty/ItemProperty.d.ts +13 -4
  115. package/dist/src/ItemProperty/ItemProperty.d.ts.map +1 -1
  116. package/dist/src/ItemProperty/service/actors/hydrateFromDb.d.ts.map +1 -1
  117. package/dist/src/ItemProperty/service/actors/loadOrCreateProperty.d.ts.map +1 -1
  118. package/dist/src/ItemProperty/service/actors/saveValueToDb/saveFile.d.ts.map +1 -1
  119. package/dist/src/ItemProperty/service/actors/saveValueToDb/saveHtml.d.ts.map +1 -1
  120. package/dist/src/ItemProperty/service/actors/saveValueToDb/saveImage.d.ts.map +1 -1
  121. package/dist/src/ItemProperty/service/actors/saveValueToDb/saveItemStorage.d.ts.map +1 -1
  122. package/dist/src/ItemProperty/service/propertyMachine.d.ts +4 -9
  123. package/dist/src/ItemProperty/service/propertyMachine.d.ts.map +1 -1
  124. package/dist/src/Model/Model.d.ts +52 -2
  125. package/dist/src/Model/Model.d.ts.map +1 -1
  126. package/dist/src/Model/errors.d.ts +10 -0
  127. package/dist/src/Model/errors.d.ts.map +1 -0
  128. package/dist/src/Model/service/actors/createModelProperties.d.ts.map +1 -1
  129. package/dist/src/Model/service/actors/loadOrCreateModel.d.ts.map +1 -1
  130. package/dist/src/Model/service/actors/validateModel.d.ts.map +1 -1
  131. package/dist/src/Model/service/modelMachine.d.ts +0 -8
  132. package/dist/src/Model/service/modelMachine.d.ts.map +1 -1
  133. package/dist/src/ModelProperty/ModelProperty.d.ts +42 -2
  134. package/dist/src/ModelProperty/ModelProperty.d.ts.map +1 -1
  135. package/dist/src/ModelProperty/service/actors/compareAndMarkDraft.d.ts.map +1 -1
  136. package/dist/src/ModelProperty/service/actors/saveToSchema.d.ts.map +1 -1
  137. package/dist/src/ModelProperty/service/actors/validateProperty.d.ts.map +1 -1
  138. package/dist/src/ModelProperty/service/modelPropertyMachine.d.ts +2 -9
  139. package/dist/src/ModelProperty/service/modelPropertyMachine.d.ts.map +1 -1
  140. package/dist/src/Schema/Schema.d.ts +8 -2
  141. package/dist/src/Schema/Schema.d.ts.map +1 -1
  142. package/dist/src/Schema/service/actors/checkExistingSchema.d.ts.map +1 -1
  143. package/dist/src/Schema/service/actors/createModelInstances.d.ts.map +1 -1
  144. package/dist/src/Schema/service/actors/loadOrCreateSchema.d.ts.map +1 -1
  145. package/dist/src/Schema/service/schemaMachine.d.ts +1 -217
  146. package/dist/src/Schema/service/schemaMachine.d.ts.map +1 -1
  147. package/dist/src/Schema/service/validation/SchemaValidationService.d.ts.map +1 -1
  148. package/dist/src/browser/db/Db.d.ts +3 -0
  149. package/dist/src/browser/db/Db.d.ts.map +1 -1
  150. package/dist/src/browser/db/drizzleFiles.d.ts +7 -2
  151. package/dist/src/browser/db/drizzleFiles.d.ts.map +1 -1
  152. package/dist/src/browser/db/embeddedMigrations.d.ts +11 -2
  153. package/dist/src/browser/db/embeddedMigrations.d.ts.map +1 -1
  154. package/dist/src/browser/db/sqliteBusyRetry.d.ts +14 -0
  155. package/dist/src/browser/db/sqliteBusyRetry.d.ts.map +1 -0
  156. package/dist/src/browser/helpers/FileManager.d.ts +1 -0
  157. package/dist/src/browser/helpers/FileManager.d.ts.map +1 -1
  158. package/dist/src/browser/helpers/QueryClient.d.ts +1 -0
  159. package/dist/src/browser/helpers/QueryClient.d.ts.map +1 -1
  160. package/dist/src/browser/helpers/opfsErrors.d.ts +2 -0
  161. package/dist/src/browser/helpers/opfsErrors.d.ts.map +1 -0
  162. package/dist/src/browser/helpers/tolerantWebAccess.d.ts +47 -0
  163. package/dist/src/browser/helpers/tolerantWebAccess.d.ts.map +1 -0
  164. package/dist/src/browser/workers/FileDownloader.d.ts.map +1 -1
  165. package/dist/src/browser/workers/ImageResizer.d.ts.map +1 -1
  166. package/dist/src/browser/workers/filesDownload.d.ts.map +1 -1
  167. package/dist/src/browser/workers/imageResize.d.ts.map +1 -1
  168. package/dist/src/client/ClientManager.d.ts.map +1 -1
  169. package/dist/src/client/actors/addModelsToDb.d.ts +14 -0
  170. package/dist/src/client/actors/addModelsToDb.d.ts.map +1 -1
  171. package/dist/src/client/actors/platformClassesInit.d.ts.map +1 -1
  172. package/dist/src/client/actors/processSchemaFiles.d.ts.map +1 -1
  173. package/dist/src/client/actors/saveConfig.d.ts +11 -0
  174. package/dist/src/client/actors/saveConfig.d.ts.map +1 -1
  175. package/dist/src/client/constants.d.ts +0 -8
  176. package/dist/src/client/constants.d.ts.map +1 -1
  177. package/dist/src/db/backfillMetadataPropertyIds.d.ts.map +1 -1
  178. package/dist/src/db/configs/{dev.schema.config.d.ts → migrations.config.d.ts} +1 -1
  179. package/dist/src/db/configs/migrations.config.d.ts.map +1 -0
  180. package/dist/src/db/read/batchLatestPublishedVersionBySeedLocalIds.d.ts +1 -1
  181. package/dist/src/db/read/batchLatestPublishedVersionBySeedLocalIds.d.ts.map +1 -1
  182. package/dist/src/db/read/getItemData.d.ts.map +1 -1
  183. package/dist/src/db/read/getItemProperties.d.ts.map +1 -1
  184. package/dist/src/db/read/getItems.d.ts +7 -2
  185. package/dist/src/db/read/getItems.d.ts.map +1 -1
  186. package/dist/src/db/read/getLatestPublishedVersionRow.d.ts +2 -1
  187. package/dist/src/db/read/getLatestPublishedVersionRow.d.ts.map +1 -1
  188. package/dist/src/db/read/getLatestVersionRow.d.ts +13 -0
  189. package/dist/src/db/read/getLatestVersionRow.d.ts.map +1 -0
  190. package/dist/src/db/read/getModelSchemas.d.ts.map +1 -1
  191. package/dist/src/db/read/getPropertyData.d.ts.map +1 -1
  192. package/dist/src/db/read/getPublishPayload.d.ts +18 -11
  193. package/dist/src/db/read/getPublishPayload.d.ts.map +1 -1
  194. package/dist/src/db/read/getPublishPendingDiff.d.ts +2 -1
  195. package/dist/src/db/read/getPublishPendingDiff.d.ts.map +1 -1
  196. package/dist/src/db/read/getPublishUploads.d.ts +5 -0
  197. package/dist/src/db/read/getPublishUploads.d.ts.map +1 -1
  198. package/dist/src/db/read/getSchemaUidForModel.d.ts.map +1 -1
  199. package/dist/src/db/read/getSeedPublishState.d.ts +8 -2
  200. package/dist/src/db/read/getSeedPublishState.d.ts.map +1 -1
  201. package/dist/src/db/read/isSeedRevoked.d.ts +7 -0
  202. package/dist/src/db/read/isSeedRevoked.d.ts.map +1 -0
  203. package/dist/src/db/read/publishDraftGraph.d.ts +57 -0
  204. package/dist/src/db/read/publishDraftGraph.d.ts.map +1 -0
  205. package/dist/src/db/read/publishErrors.d.ts +37 -0
  206. package/dist/src/db/read/publishErrors.d.ts.map +1 -0
  207. package/dist/src/db/read/resolveModelForSyncedSeed.d.ts +39 -0
  208. package/dist/src/db/read/resolveModelForSyncedSeed.d.ts.map +1 -0
  209. package/dist/src/db/read/resolveModelRecord.d.ts +69 -0
  210. package/dist/src/db/read/resolveModelRecord.d.ts.map +1 -0
  211. package/dist/src/db/read/resolveRelatedSeedRef.d.ts +34 -0
  212. package/dist/src/db/read/resolveRelatedSeedRef.d.ts.map +1 -0
  213. package/dist/src/db/read/subqueries/liveVersion.d.ts +12 -0
  214. package/dist/src/db/read/subqueries/liveVersion.d.ts.map +1 -0
  215. package/dist/src/db/read/subqueries/metadataLatest.d.ts +4 -0
  216. package/dist/src/db/read/subqueries/metadataLatest.d.ts.map +1 -1
  217. package/dist/src/db/read/subqueries/versionData.d.ts +7 -2
  218. package/dist/src/db/read/subqueries/versionData.d.ts.map +1 -1
  219. package/dist/src/db/read/summarizePublishWork.d.ts +10 -2
  220. package/dist/src/db/read/summarizePublishWork.d.ts.map +1 -1
  221. package/dist/src/db/resetAmbiguousLegacyItemData.d.ts +17 -0
  222. package/dist/src/db/resetAmbiguousLegacyItemData.d.ts.map +1 -0
  223. package/dist/src/db/sqlParamBatches.d.ts +27 -0
  224. package/dist/src/db/sqlParamBatches.d.ts.map +1 -0
  225. package/dist/src/db/write/addExcludedTransactions.d.ts +7 -0
  226. package/dist/src/db/write/addExcludedTransactions.d.ts.map +1 -0
  227. package/dist/src/db/write/applyPropertyAttestationUidsFromPublish.d.ts +6 -0
  228. package/dist/src/db/write/applyPropertyAttestationUidsFromPublish.d.ts.map +1 -1
  229. package/dist/src/db/write/createMetadata.d.ts +2 -0
  230. package/dist/src/db/write/createMetadata.d.ts.map +1 -1
  231. package/dist/src/db/write/createNewItem.d.ts +3 -1
  232. package/dist/src/db/write/createNewItem.d.ts.map +1 -1
  233. package/dist/src/db/write/createSeed.d.ts +2 -1
  234. package/dist/src/db/write/createSeed.d.ts.map +1 -1
  235. package/dist/src/db/write/createSeeds.d.ts +1 -1
  236. package/dist/src/db/write/createSeeds.d.ts.map +1 -1
  237. package/dist/src/db/write/linkModelToSchema.d.ts +12 -0
  238. package/dist/src/db/write/linkModelToSchema.d.ts.map +1 -0
  239. package/dist/src/db/write/updateItemPropertyValue.d.ts.map +1 -1
  240. package/dist/src/db/write/updateMetadata.d.ts.map +1 -1
  241. package/dist/src/db/write/updateSeedRevokedAt.d.ts +11 -1
  242. package/dist/src/db/write/updateSeedRevokedAt.d.ts.map +1 -1
  243. package/dist/src/db/write/updateSeedUid.d.ts.map +1 -1
  244. package/dist/src/db/write/updateVersionUid.d.ts +2 -1
  245. package/dist/src/db/write/updateVersionUid.d.ts.map +1 -1
  246. package/dist/src/events/files/download.d.ts.map +1 -1
  247. package/dist/src/events/item/easSyncManager.d.ts +2 -0
  248. package/dist/src/events/item/easSyncManager.d.ts.map +1 -1
  249. package/dist/src/events/item/index.d.ts.map +1 -1
  250. package/dist/src/events/item/syncDbWithEas.d.ts +16 -0
  251. package/dist/src/events/item/syncDbWithEas.d.ts.map +1 -1
  252. package/dist/src/helpers/FileManager/BaseFileManager.d.ts +1 -0
  253. package/dist/src/helpers/FileManager/BaseFileManager.d.ts.map +1 -1
  254. package/dist/src/helpers/FileManager/IFileManager.d.ts +5 -0
  255. package/dist/src/helpers/FileManager/IFileManager.d.ts.map +1 -1
  256. package/dist/src/helpers/FileManager/errors.d.ts +10 -0
  257. package/dist/src/helpers/FileManager/errors.d.ts.map +1 -0
  258. package/dist/src/helpers/compareMetadataRowsLatestFirst.d.ts +21 -3
  259. package/dist/src/helpers/compareMetadataRowsLatestFirst.d.ts.map +1 -1
  260. package/dist/src/helpers/constants.d.ts +9 -0
  261. package/dist/src/helpers/constants.d.ts.map +1 -1
  262. package/dist/src/helpers/crypto.d.ts +5 -0
  263. package/dist/src/helpers/crypto.d.ts.map +1 -1
  264. package/dist/src/helpers/db.d.ts +25 -5
  265. package/dist/src/helpers/db.d.ts.map +1 -1
  266. package/dist/src/helpers/easPropertyCanonical.d.ts +1 -1
  267. package/dist/src/helpers/easPropertyCanonical.d.ts.map +1 -1
  268. package/dist/src/helpers/entity/entityCommon.d.ts +10 -0
  269. package/dist/src/helpers/entity/entityCommon.d.ts.map +1 -1
  270. package/dist/src/helpers/entity/entityDestroy.d.ts +1 -1
  271. package/dist/src/helpers/entity/entityDestroy.d.ts.map +1 -1
  272. package/dist/src/helpers/entity/entityLiveQuery.d.ts +5 -0
  273. package/dist/src/helpers/entity/entityLiveQuery.d.ts.map +1 -1
  274. package/dist/src/helpers/entity/evictionEpoch.d.ts +18 -0
  275. package/dist/src/helpers/entity/evictionEpoch.d.ts.map +1 -0
  276. package/dist/src/helpers/file/fetchAll/actors.d.ts.map +1 -1
  277. package/dist/src/helpers/getSegmentedItemProperties.d.ts.map +1 -1
  278. package/dist/src/helpers/htmlEmbeddedDataUriPublish.d.ts +31 -3
  279. package/dist/src/helpers/htmlEmbeddedDataUriPublish.d.ts.map +1 -1
  280. package/dist/src/helpers/isPublishedMetadataRow.d.ts +10 -0
  281. package/dist/src/helpers/isPublishedMetadataRow.d.ts.map +1 -0
  282. package/dist/src/helpers/ownership.d.ts.map +1 -1
  283. package/dist/src/helpers/property.d.ts +6 -1
  284. package/dist/src/helpers/property.d.ts.map +1 -1
  285. package/dist/src/helpers/schema.d.ts +14 -4
  286. package/dist/src/helpers/schema.d.ts.map +1 -1
  287. package/dist/src/helpers/tabCoordinator.d.ts +45 -0
  288. package/dist/src/helpers/tabCoordinator.d.ts.map +1 -0
  289. package/dist/src/helpers/tabEvents.d.ts +27 -0
  290. package/dist/src/helpers/tabEvents.d.ts.map +1 -0
  291. package/dist/src/helpers/tabLocks.d.ts +28 -0
  292. package/dist/src/helpers/tabLocks.d.ts.map +1 -0
  293. package/dist/src/helpers/updateSchema.d.ts.map +1 -1
  294. package/dist/src/imports/json.d.ts.map +1 -1
  295. package/dist/src/imports/markdown.d.ts.map +1 -1
  296. package/dist/src/index.d.ts +13 -3
  297. package/dist/src/index.d.ts.map +1 -1
  298. package/dist/src/node/db/Db.d.ts.map +1 -1
  299. package/dist/src/node/helpers/FileManager.d.ts +2 -0
  300. package/dist/src/node/helpers/FileManager.d.ts.map +1 -1
  301. package/dist/src/query/createLocalQueryDataSource.d.ts +4 -0
  302. package/dist/src/query/createLocalQueryDataSource.d.ts.map +1 -1
  303. package/dist/src/seedSchema/MetadataSchema.d.ts +36 -0
  304. package/dist/src/seedSchema/MetadataSchema.d.ts.map +1 -1
  305. package/dist/src/seedSchema/ModelSchema.d.ts +57 -0
  306. package/dist/src/seedSchema/ModelSchema.d.ts.map +1 -1
  307. package/dist/src/seedSchema/SeedSchema.d.ts +19 -0
  308. package/dist/src/seedSchema/SeedSchema.d.ts.map +1 -1
  309. package/dist/src/seedSchema/VersionSchema.d.ts +17 -0
  310. package/dist/src/seedSchema/VersionSchema.d.ts.map +1 -1
  311. package/dist/src/services/write/actors/validateEntity.d.ts.map +1 -1
  312. package/dist/src/services/write/actors/writeToDatabase.d.ts +5 -0
  313. package/dist/src/services/write/actors/writeToDatabase.d.ts.map +1 -1
  314. package/dist/src/services/write/writeProcessMachine.d.ts.map +1 -1
  315. package/dist/src/stores/eas.d.ts +1 -1
  316. package/dist/src/stores/eas.d.ts.map +1 -1
  317. package/dist/src/types/index.d.ts +7 -0
  318. package/dist/src/types/index.d.ts.map +1 -1
  319. package/dist/src/types/item.d.ts +19 -11
  320. package/dist/src/types/item.d.ts.map +1 -1
  321. package/dist/src/types/property.d.ts +3 -2
  322. package/dist/src/types/property.d.ts.map +1 -1
  323. package/dist/syncDbWithEas-BPap9Sru.js +855 -0
  324. package/dist/syncDbWithEas-BPap9Sru.js.map +1 -0
  325. package/dist/{index-280bL-n4.js → tabEvents-C6NXS6Jl.js} +231 -68
  326. package/dist/tabEvents-C6NXS6Jl.js.map +1 -0
  327. package/dist/tolerantWebAccess-NBQ1NB4i.js +160 -0
  328. package/dist/tolerantWebAccess-NBQ1NB4i.js.map +1 -0
  329. package/dist/updateSeedRevokedAt-CYwgVNlM.js +32 -0
  330. package/dist/updateSeedRevokedAt-CYwgVNlM.js.map +1 -0
  331. package/package.json +8 -10
  332. package/dist/BasePathResolver-B6CKqoKw.js.map +0 -1
  333. package/dist/ClientManager-ChcmUL47.js.map +0 -1
  334. package/dist/ModelProperty-D79uV42p.js.map +0 -1
  335. package/dist/Schema-a8uO-hIZ.js.map +0 -1
  336. package/dist/SchemaValidationService-Y49vqast.js.map +0 -1
  337. package/dist/backfillMetadataPropertyIds-CBsf7LnU.js.map +0 -1
  338. package/dist/cjs/ModelProperty-D9FGaGuE.js.map +0 -1
  339. package/dist/cjs/Schema-BiJIPLEL.js.map +0 -1
  340. package/dist/cjs/SchemaValidationService-DtYs_CNY.js.map +0 -1
  341. package/dist/cjs/backfillMetadataPropertyIds-2XaN3b9S.js.map +0 -1
  342. package/dist/cjs/getPublishPayload-D5DhLGvN.js.map +0 -1
  343. package/dist/cjs/getPublishUploads-DMhCCKYF.js.map +0 -1
  344. package/dist/cjs/getSegmentedItemProperties-CU8rtBAo.js +0 -148
  345. package/dist/cjs/getSegmentedItemProperties-CU8rtBAo.js.map +0 -1
  346. package/dist/cjs/index-CSNtEnbF.js.map +0 -1
  347. package/dist/cjs/index-DPp9rdRL.js.map +0 -1
  348. package/dist/cjs/property-DlKiAWt4.js.map +0 -1
  349. package/dist/cjs/syncDbWithEas-C6n34o_Q.js +0 -606
  350. package/dist/cjs/syncDbWithEas-C6n34o_Q.js.map +0 -1
  351. package/dist/db-WbrzEf7c.js.map +0 -1
  352. package/dist/eas-CfYCu4IX.js.map +0 -1
  353. package/dist/getPublishPayload-BIrTVUxb.js.map +0 -1
  354. package/dist/getPublishUploads-C6cDeZdz.js.map +0 -1
  355. package/dist/getSegmentedItemProperties-BmKE71vU.js +0 -148
  356. package/dist/getSegmentedItemProperties-BmKE71vU.js.map +0 -1
  357. package/dist/index-280bL-n4.js.map +0 -1
  358. package/dist/index-ClSv5pTA.js.map +0 -1
  359. package/dist/index-Djd3667v.js.map +0 -1
  360. package/dist/index-HRHkbVQd.js.map +0 -1
  361. package/dist/index.node-DBtQkEfz.js.map +0 -1
  362. package/dist/property-CQjuZ4JW.js.map +0 -1
  363. package/dist/src/Item/service/actors/fetchDataFromEas.d.ts +0 -4
  364. package/dist/src/Item/service/actors/fetchDataFromEas.d.ts.map +0 -1
  365. package/dist/src/Item/service/actors/hydrateExistingItem.d.ts +0 -4
  366. package/dist/src/Item/service/actors/hydrateExistingItem.d.ts.map +0 -1
  367. package/dist/src/Item/service/actors/hydrateNewItem.d.ts +0 -4
  368. package/dist/src/Item/service/actors/hydrateNewItem.d.ts.map +0 -1
  369. package/dist/src/Item/service/actors/initialize.d.ts +0 -4
  370. package/dist/src/Item/service/actors/initialize.d.ts.map +0 -1
  371. package/dist/src/Item/service/actors/reload.d.ts +0 -5
  372. package/dist/src/Item/service/actors/reload.d.ts.map +0 -1
  373. package/dist/src/Item/service/actors/saveDataToDb.d.ts +0 -4
  374. package/dist/src/Item/service/actors/saveDataToDb.d.ts.map +0 -1
  375. package/dist/src/ItemProperty/service/actors/resolveRemoteStorage.d.ts +0 -5
  376. package/dist/src/ItemProperty/service/actors/resolveRemoteStorage.d.ts.map +0 -1
  377. package/dist/src/Schema/service/addModelsMachine.d.ts +0 -123
  378. package/dist/src/Schema/service/addModelsMachine.d.ts.map +0 -1
  379. package/dist/src/browser/helpers/index.d.ts +0 -4
  380. package/dist/src/browser/helpers/index.d.ts.map +0 -1
  381. package/dist/src/db/configs/dev.schema.config.d.ts.map +0 -1
  382. package/dist/src/helpers/file/download/actors.d.ts +0 -17
  383. package/dist/src/helpers/file/download/actors.d.ts.map +0 -1
  384. package/dist/src/helpers/file/download/index.d.ts +0 -70
  385. package/dist/src/helpers/file/download/index.d.ts.map +0 -1
  386. package/dist/src/services/publish/actors/createPublishAttempt.d.ts +0 -4
  387. package/dist/src/services/publish/actors/createPublishAttempt.d.ts.map +0 -1
  388. package/dist/src/services/publish/actors/preparePublishRequestData.d.ts +0 -4
  389. package/dist/src/services/publish/actors/preparePublishRequestData.d.ts.map +0 -1
  390. package/dist/src/services/publish/actors/upload.d.ts +0 -4
  391. package/dist/src/services/publish/actors/upload.d.ts.map +0 -1
  392. package/dist/src/services/publish/actors/validateItemData.d.ts +0 -4
  393. package/dist/src/services/publish/actors/validateItemData.d.ts.map +0 -1
  394. package/dist/src/services/publish/publishMachine.d.ts +0 -32
  395. package/dist/src/services/publish/publishMachine.d.ts.map +0 -1
  396. package/dist/syncDbWithEas-CuARXfyN.js +0 -598
  397. package/dist/syncDbWithEas-CuARXfyN.js.map +0 -1
  398. package/dist/updateSeedRevokedAt-CBcLfHWs.js +0 -22
  399. package/dist/updateSeedRevokedAt-CBcLfHWs.js.map +0 -1
@@ -1,8 +1,8 @@
1
- import { a as BaseDb, c as appState, m as models, i as modelSchemas, p as properties, s as schemas, b as metadata } from './BasePathResolver-B6CKqoKw.js';
1
+ import { j as models, g as modelSchemas, s as schemas, B as BaseDb, r as seeds, p as properties, b as appState, m as metadata } from './BasePathResolver-DRT09oVv.js';
2
2
  import { toSnakeCase } from 'drizzle-orm/casing';
3
- import { eq, and, isNull } from 'drizzle-orm';
4
- import { upperFirst, camelCase } from 'lodash-es';
3
+ import { eq, and, inArray, desc, isNull } from 'drizzle-orm';
5
4
  import debug from 'debug';
5
+ import { upperFirst, camelCase } from 'lodash-es';
6
6
  import 'pluralize';
7
7
  import { Type } from '@sinclair/typebox';
8
8
 
@@ -214,6 +214,58 @@ const Boolean = () => PropertyConstructor(Property.Boolean());
214
214
  const Date$1 = () => PropertyConstructor(Property.Date());
215
215
  const Html = (opts) => PropertyConstructor(htmlPropertyFactory(opts));
216
216
 
217
+ class SeedEventEmitter {
218
+ constructor() {
219
+ this.listeners = new Map();
220
+ }
221
+ on(event, listener) {
222
+ const set = this.listeners.get(event) ?? new Set();
223
+ set.add(listener);
224
+ this.listeners.set(event, set);
225
+ return this;
226
+ }
227
+ addListener(event, listener) {
228
+ return this.on(event, listener);
229
+ }
230
+ once(event, listener) {
231
+ const wrapped = (...args) => {
232
+ this.off(event, wrapped);
233
+ listener(...args);
234
+ };
235
+ return this.on(event, wrapped);
236
+ }
237
+ off(event, listener) {
238
+ const set = this.listeners.get(event);
239
+ if (!set)
240
+ return this;
241
+ set.delete(listener);
242
+ if (set.size === 0)
243
+ this.listeners.delete(event);
244
+ return this;
245
+ }
246
+ removeListener(event, listener) {
247
+ return this.off(event, listener);
248
+ }
249
+ removeAllListeners(event) {
250
+ if (typeof event === 'undefined') {
251
+ this.listeners.clear();
252
+ return this;
253
+ }
254
+ this.listeners.delete(event);
255
+ return this;
256
+ }
257
+ emit(event, ...args) {
258
+ const set = this.listeners.get(event);
259
+ if (!set || set.size === 0)
260
+ return false;
261
+ for (const listener of [...set]) {
262
+ listener(...args);
263
+ }
264
+ return true;
265
+ }
266
+ }
267
+ const eventEmitter = new SeedEventEmitter();
268
+
217
269
  /**
218
270
  * Detect SQLite UNIQUE constraint failures across better-sqlite3 and drizzle/wasm wrappers.
219
271
  * Drizzle often surfaces `Failed query: insert into...` without "UNIQUE constraint" on message,
@@ -264,6 +316,219 @@ function matchesUniqueConstraintText(text) {
264
316
  (text.includes('2067') && lower.includes('constraint')));
265
317
  }
266
318
 
319
+ /**
320
+ * Thrown when a model name exists in more than one schema and nothing says which one is meant.
321
+ * Model names are only unique within a schema; pass `schemaName` (or `modelFileId`) to choose.
322
+ */
323
+ class AmbiguousModelError extends Error {
324
+ constructor(modelName, schemaNames) {
325
+ const names = [...new Set(schemaNames)].sort();
326
+ super(`Model "${modelName}" exists in schemas ${names.map((n) => `"${n}"`).join(', ')}; ` +
327
+ `pass schemaName (or modelFileId) to choose one.`);
328
+ this.name = 'AmbiguousModelError';
329
+ this.modelName = modelName;
330
+ this.schemaNames = names;
331
+ }
332
+ }
333
+
334
+ const columns = {
335
+ id: models.id,
336
+ name: models.name,
337
+ schemaFileId: models.schemaFileId,
338
+ };
339
+ /**
340
+ * Resolve a models row from a model name plus whatever scope is known, most specific first:
341
+ * modelFileId, modelId, then schemaId/schemaName + name, then the name alone. The name alone is
342
+ * only accepted when it is unambiguous; otherwise this throws AmbiguousModelError.
343
+ */
344
+ const resolveModelRecord = async (modelName, scope = {}, db = BaseDb.getAppDb()) => {
345
+ if (!db)
346
+ return undefined;
347
+ if (scope.modelFileId) {
348
+ const rows = await db
349
+ .select(columns)
350
+ .from(models)
351
+ .where(eq(models.schemaFileId, scope.modelFileId))
352
+ .limit(1);
353
+ if (rows.length > 0)
354
+ return rows[0];
355
+ }
356
+ if (scope.modelId) {
357
+ const rows = await db.select(columns).from(models).where(eq(models.id, scope.modelId)).limit(1);
358
+ if (rows.length > 0)
359
+ return rows[0];
360
+ }
361
+ if (!modelName)
362
+ return undefined;
363
+ if (scope.schemaId || scope.schemaName) {
364
+ const rows = await db
365
+ .select(columns)
366
+ .from(models)
367
+ .innerJoin(modelSchemas, eq(models.id, modelSchemas.modelId))
368
+ .innerJoin(schemas, eq(modelSchemas.schemaId, schemas.id))
369
+ .where(and(eq(models.name, modelName), scope.schemaId ? eq(schemas.id, scope.schemaId) : eq(schemas.name, scope.schemaName)))
370
+ .limit(1);
371
+ if (rows.length > 0)
372
+ return rows[0];
373
+ }
374
+ return resolveModelRecordByNameOnly(modelName, db);
375
+ };
376
+ /**
377
+ * Name-only resolution. Rows linked to a schema win over unlinked stubs (null-schemaFileId rows
378
+ * from ref resolution); if more than one linked row has the name it is ambiguous and this throws.
379
+ * `label` names the lookup in the error (defaults to the model name).
380
+ */
381
+ const resolveModelRecordByNameOnly = async (modelName, db, label = Array.isArray(modelName) ? modelName.join(', ') : modelName) => {
382
+ const rows = (await db
383
+ .select({ ...columns, schemaName: schemas.name })
384
+ .from(models)
385
+ .leftJoin(modelSchemas, eq(models.id, modelSchemas.modelId))
386
+ .leftJoin(schemas, eq(modelSchemas.schemaId, schemas.id))
387
+ .where(Array.isArray(modelName) ? inArray(models.name, modelName) : eq(models.name, modelName))
388
+ .orderBy(desc(models.id)));
389
+ if (rows.length === 0)
390
+ return undefined;
391
+ const linked = rows.filter((r) => r.schemaName);
392
+ const linkedIds = new Set(linked.map((r) => r.id));
393
+ if (linkedIds.size > 1) {
394
+ throw new AmbiguousModelError(label, linked.map((r) => r.schemaName));
395
+ }
396
+ const chosen = linked[0] ?? rows[0];
397
+ return { id: chosen.id, name: chosen.name, schemaFileId: chosen.schemaFileId };
398
+ };
399
+ /**
400
+ * The model names a model name or EAS model type can refer to: the name itself, names whose
401
+ * snake_case form is the type (`new_model` → "New model", as Model.findByModelType matches), and
402
+ * the PascalCase form older callers relied on (`sync_storage_post` → "SyncStoragePost").
403
+ */
404
+ const modelNamesForNameOrType = async (nameOrType, db) => {
405
+ const pascal = upperFirst(camelCase(nameOrType));
406
+ const rows = (await db.selectDistinct({ name: models.name }).from(models));
407
+ return rows
408
+ .map((r) => r.name)
409
+ .filter((name) => name === nameOrType || name === pascal || toSnakeCase(name) === nameOrType);
410
+ };
411
+ /**
412
+ * resolveModelRecord for a model name **or** an EAS model type (snake_case model name, what sync
413
+ * stores in seeds.type): "New model" resolves from `new_model`. Scope and ambiguity behave as in
414
+ * resolveModelRecord: modelFileId/modelId first, then the schema, then the name(s) alone, which throws
415
+ * AmbiguousModelError when models in several schemas match.
416
+ */
417
+ const resolveModelRecordByNameOrType = async (nameOrType, scope = {}, db = BaseDb.getAppDb()) => {
418
+ if (!db)
419
+ return undefined;
420
+ if (scope.modelFileId || scope.modelId) {
421
+ const byId = await resolveModelRecord(undefined, scope, db);
422
+ if (byId)
423
+ return byId;
424
+ }
425
+ if (!nameOrType)
426
+ return undefined;
427
+ const names = await modelNamesForNameOrType(nameOrType, db);
428
+ if (names.length === 0)
429
+ return undefined;
430
+ if (names.length === 1)
431
+ return resolveModelRecord(names[0], { ...scope, modelFileId: undefined, modelId: undefined }, db);
432
+ // Several model names map to this type (e.g. "New model" and "NewModel" in different schemas).
433
+ if (scope.schemaId || scope.schemaName) {
434
+ const rows = (await db
435
+ .select(columns)
436
+ .from(models)
437
+ .innerJoin(modelSchemas, eq(models.id, modelSchemas.modelId))
438
+ .innerJoin(schemas, eq(modelSchemas.schemaId, schemas.id))
439
+ .where(and(inArray(models.name, names), scope.schemaId ? eq(schemas.id, scope.schemaId) : eq(schemas.name, scope.schemaName))));
440
+ if (new Set(rows.map((r) => r.id)).size === 1)
441
+ return rows[0];
442
+ }
443
+ return resolveModelRecordByNameOnly(names, db, nameOrType);
444
+ };
445
+ /**
446
+ * Work out which model (schemaFileId) an item belongs to from whatever is at hand: an explicit
447
+ * modelFileId, the seed's model_file_id, or a metadata row's property_id → properties.model_id.
448
+ */
449
+ const resolveItemModelFileId = async (hints, db = BaseDb.getAppDb()) => {
450
+ if (hints.modelFileId)
451
+ return hints.modelFileId;
452
+ if (!db)
453
+ return undefined;
454
+ if (hints.seedLocalId || hints.seedUid) {
455
+ const rows = await db
456
+ .select({ modelFileId: seeds.modelFileId })
457
+ .from(seeds)
458
+ .where(hints.seedLocalId ? eq(seeds.localId, hints.seedLocalId) : eq(seeds.uid, hints.seedUid))
459
+ .limit(1);
460
+ if (rows[0]?.modelFileId)
461
+ return rows[0].modelFileId;
462
+ }
463
+ if (hints.propertyId) {
464
+ const rows = await db
465
+ .select({ modelFileId: models.schemaFileId })
466
+ .from(properties)
467
+ .innerJoin(models, eq(properties.modelId, models.id))
468
+ .where(eq(properties.id, hints.propertyId))
469
+ .limit(1);
470
+ if (rows[0]?.modelFileId)
471
+ return rows[0].modelFileId;
472
+ }
473
+ return undefined;
474
+ };
475
+ /** ModelScope for an Item (or ItemProperty) instance: its recorded modelFileId (context or seed row) and schemaName. */
476
+ const getItemModelScope = async (item) => {
477
+ let context;
478
+ try {
479
+ context = item.getService?.().getSnapshot().context;
480
+ }
481
+ catch {
482
+ context = undefined;
483
+ }
484
+ const modelFileId = await resolveItemModelFileId({
485
+ modelFileId: context?.modelFileId,
486
+ seedLocalId: item.seedLocalId ?? context?.seedLocalId,
487
+ seedUid: item.seedUid ?? context?.seedUid,
488
+ propertyId: context?.propertyId,
489
+ });
490
+ return { modelFileId, schemaName: context?.schemaName };
491
+ };
492
+ /**
493
+ * Resolve a ref (e.g. a Relation's target model) by name from the schema(s) its owning model belongs
494
+ * to, so "Tag" means the owner schema's Tag rather than any Tag. Falls back to resolveModelRecord.
495
+ */
496
+ const resolveRefModelRecord = async (refModelName, owner, db = BaseDb.getAppDb()) => {
497
+ if (!db || !refModelName)
498
+ return undefined;
499
+ const ownerRow = owner.modelFileId || owner.modelId ? await resolveModelRecord(undefined, owner, db) : undefined;
500
+ const schemaFilter = ownerRow
501
+ ? inArray(modelSchemas.schemaId,
502
+ // any schema the owner is linked to
503
+ db.select({ schemaId: modelSchemas.schemaId }).from(modelSchemas).where(eq(modelSchemas.modelId, ownerRow.id)))
504
+ : owner.schemaId
505
+ ? eq(modelSchemas.schemaId, owner.schemaId)
506
+ : owner.schemaName
507
+ ? eq(schemas.name, owner.schemaName)
508
+ : undefined;
509
+ if (schemaFilter) {
510
+ const rows = await db
511
+ .select(columns)
512
+ .from(models)
513
+ .innerJoin(modelSchemas, eq(models.id, modelSchemas.modelId))
514
+ .innerJoin(schemas, eq(modelSchemas.schemaId, schemas.id))
515
+ .where(and(eq(models.name, refModelName), schemaFilter))
516
+ .limit(1);
517
+ if (rows.length > 0)
518
+ return rows[0];
519
+ }
520
+ return resolveModelRecord(refModelName, {}, db);
521
+ };
522
+
523
+ var resolveModelRecord$1 = /*#__PURE__*/Object.freeze({
524
+ __proto__: null,
525
+ getItemModelScope: getItemModelScope,
526
+ resolveItemModelFileId: resolveItemModelFileId,
527
+ resolveModelRecord: resolveModelRecord,
528
+ resolveModelRecordByNameOrType: resolveModelRecordByNameOrType,
529
+ resolveRefModelRecord: resolveRefModelRecord
530
+ });
531
+
267
532
  /**
268
533
  * Lowercase + trim an address for persist and compare.
269
534
  * Does not checksum or validate — test and placeholder addresses must keep working.
@@ -318,21 +583,74 @@ function normalizeAddressConfig(addresses) {
318
583
  };
319
584
  }
320
585
 
586
+ const pendingLinks = new Map();
587
+ /**
588
+ * Insert the `model_schemas` row linking a model to a schema, unless it already exists.
589
+ *
590
+ * `model_schemas` has no unique constraint, and several writers link the same model during one
591
+ * import (importJsonSchema's addModelsToDb and the write service's writeModelToDb). Each used to
592
+ * check-then-insert on its own, so concurrent writers inserted the link twice. The check and insert
593
+ * run serialized per (model, schema) here.
594
+ *
595
+ * @returns true when this call inserted the link
596
+ */
597
+ function linkModelToSchema(db, modelId, schemaId) {
598
+ const key = `${modelId}:${schemaId}`;
599
+ const previous = pendingLinks.get(key) ?? Promise.resolve(false);
600
+ const current = previous
601
+ .catch(() => false)
602
+ .then(async () => {
603
+ const existing = await db
604
+ .select({ id: modelSchemas.id })
605
+ .from(modelSchemas)
606
+ .where(and(eq(modelSchemas.modelId, modelId), eq(modelSchemas.schemaId, schemaId)))
607
+ .limit(1);
608
+ if (existing.length > 0)
609
+ return false;
610
+ await db.insert(modelSchemas).values({ modelId, schemaId });
611
+ return true;
612
+ });
613
+ pendingLinks.set(key, current);
614
+ const cleanup = () => {
615
+ if (pendingLinks.get(key) === current)
616
+ pendingLinks.delete(key);
617
+ };
618
+ current.then(cleanup, cleanup);
619
+ return current;
620
+ }
621
+
321
622
  const logger = debug('seedSdk:helpers:db');
623
+ /**
624
+ * The `properties` storage columns for a property definition, in either the internal shape
625
+ * (`storageType`, `localStorageDir`, `filenameSuffix`) or the schema-file shape
626
+ * (`storage: { type, path, extension }`). All null when the definition has no storage config.
627
+ */
628
+ function propertyStorageColumns(def) {
629
+ const normalized = normalizePropertyRecordSchema((def ?? {}));
630
+ return {
631
+ storageType: normalized.storageType ?? null,
632
+ localStorageDir: normalized.localStorageDir ?? null,
633
+ filenameSuffix: normalized.filenameSuffix ?? null,
634
+ };
635
+ }
636
+ /** True when the definition carries any storage setting (so writing its columns can't wipe them by omission). */
637
+ const hasStorageSettings = (columns) => columns.storageType != null || columns.localStorageDir != null || columns.filenameSuffix != null;
322
638
  /**
323
639
  * Resolve property_id (integer properties.id) from a property's schemaFileId (the string `id` in
324
640
  * schema files and propertyRecordSchema). Scoped to the model since schemaFileIds are per schema file.
325
641
  * @returns properties.id or null if not found
326
642
  */
327
- async function getPropertyIdForSchemaFileId(modelNameOrType, schemaFileId) {
643
+ async function getPropertyIdForSchemaFileId(modelNameOrType, schemaFileId, scope = {}) {
328
644
  const db = BaseDb.getAppDb();
329
645
  if (!db || !modelNameOrType || !schemaFileId)
330
646
  return null;
647
+ const modelRecord = await resolveModelRecordByNameOrType(modelNameOrType, scope, db);
648
+ if (!modelRecord)
649
+ return null;
331
650
  const rows = await db
332
651
  .select({ id: properties.id })
333
652
  .from(properties)
334
- .innerJoin(models, eq(properties.modelId, models.id))
335
- .where(and(eq(models.name, upperFirst(camelCase(modelNameOrType))), eq(properties.schemaFileId, schemaFileId)))
653
+ .where(and(eq(properties.modelId, modelRecord.id), eq(properties.schemaFileId, schemaFileId)))
336
654
  .limit(1);
337
655
  return rows[0]?.id ?? null;
338
656
  }
@@ -341,15 +659,18 @@ async function getPropertyIdForSchemaFileId(modelNameOrType, schemaFileId) {
341
659
  * Handles property name variants (e.g. htmlId -> html, avatarImageIds -> avatarImages).
342
660
  * @param modelNameOrType - Model name (PascalCase) or model type (snake_case)
343
661
  * @param propertyName - Property name as stored in metadata (may have Id/Ids suffix)
662
+ * @param scope - Which model is meant when several schemas define one with this name
344
663
  * @returns properties.id or null if not found
345
664
  */
346
- async function getPropertyIdForModelAndName(modelNameOrType, propertyName) {
665
+ async function getPropertyIdForModelAndName(modelNameOrType, propertyName, scope = {}) {
347
666
  const db = BaseDb.getAppDb();
348
667
  if (!db)
349
668
  return null;
350
669
  if (!modelNameOrType || !propertyName)
351
670
  return null;
352
- const normalizedModelName = upperFirst(camelCase(modelNameOrType));
671
+ const modelRecord = await resolveModelRecordByNameOrType(modelNameOrType, scope, db);
672
+ if (!modelRecord)
673
+ return null;
353
674
  const propertyNamesToTry = [propertyName];
354
675
  if (propertyName.endsWith('Ids')) {
355
676
  propertyNamesToTry.push(propertyName.slice(0, -3));
@@ -361,8 +682,7 @@ async function getPropertyIdForModelAndName(modelNameOrType, propertyName) {
361
682
  const rows = await db
362
683
  .select({ id: properties.id })
363
684
  .from(properties)
364
- .innerJoin(models, eq(properties.modelId, models.id))
365
- .where(and(eq(models.name, normalizedModelName), eq(properties.name, pName)))
685
+ .where(and(eq(properties.modelId, modelRecord.id), eq(properties.name, pName)))
366
686
  .limit(1);
367
687
  if (rows.length > 0 && rows[0].id != null) {
368
688
  return rows[0].id;
@@ -370,6 +690,28 @@ async function getPropertyIdForModelAndName(modelNameOrType, propertyName) {
370
690
  }
371
691
  return null;
372
692
  }
693
+ /**
694
+ * A model's ItemStorage properties as stored in `properties` (storage_type 'ItemStorage'), with
695
+ * their storage path and extension. Reads the table, not ModelProperty instances, so it doesn't
696
+ * depend on whether (or from where) the model's property instances have loaded.
697
+ */
698
+ async function getItemStoragePropertiesForModel(modelNameOrType, scope = {}) {
699
+ const db = BaseDb.getAppDb();
700
+ if (!db || !modelNameOrType)
701
+ return [];
702
+ const modelRecord = await resolveModelRecordByNameOrType(modelNameOrType, scope, db);
703
+ if (!modelRecord)
704
+ return [];
705
+ return db
706
+ .select({
707
+ id: properties.id,
708
+ name: properties.name,
709
+ localStorageDir: properties.localStorageDir,
710
+ filenameSuffix: properties.filenameSuffix,
711
+ })
712
+ .from(properties)
713
+ .where(and(eq(properties.modelId, modelRecord.id), eq(properties.storageType, 'ItemStorage')));
714
+ }
373
715
  /**
374
716
  * Migrate metadata rows when a property is renamed.
375
717
  * Updates metadata.propertyName from old to new for all rows that reference the renamed property.
@@ -380,7 +722,7 @@ async function getPropertyIdForModelAndName(modelNameOrType, propertyName) {
380
722
  * @param propertySchemaFileId - Optional schema file ID for the property (most reliable lookup)
381
723
  * @returns Count of metadata rows updated
382
724
  */
383
- async function migrateMetadataForPropertyRename(modelName, oldPropertyName, newPropertyName, propertySchemaFileId) {
725
+ async function migrateMetadataForPropertyRename(modelName, oldPropertyName, newPropertyName, propertySchemaFileId, scope = {}) {
384
726
  const db = BaseDb.getAppDb();
385
727
  if (!db) {
386
728
  logger('[migrateMetadataForPropertyRename] Database not available, skipping');
@@ -389,10 +731,10 @@ async function migrateMetadataForPropertyRename(modelName, oldPropertyName, newP
389
731
  // Find the property row by schemaFileId (preferred) or by name
390
732
  let propertyId = null;
391
733
  if (propertySchemaFileId) {
392
- propertyId = await getPropertyIdForSchemaFileId(modelName, propertySchemaFileId);
734
+ propertyId = await getPropertyIdForSchemaFileId(modelName, propertySchemaFileId, scope);
393
735
  }
394
736
  if (propertyId == null) {
395
- propertyId = await getPropertyIdForModelAndName(modelName, oldPropertyName);
737
+ propertyId = await getPropertyIdForModelAndName(modelName, oldPropertyName, scope);
396
738
  }
397
739
  if (propertyId == null) {
398
740
  logger(`[migrateMetadataForPropertyRename] Property not found: ${modelName}.${oldPropertyName}, skipping`);
@@ -432,12 +774,6 @@ async function migrateMetadataForPropertyRename(modelName, oldPropertyName, newP
432
774
  }
433
775
  return total;
434
776
  }
435
- const escapeSqliteString = (value) => {
436
- if (typeof value !== 'string') {
437
- throw new Error(`Value must be a string, instead got: ${JSON.stringify(value)}`);
438
- }
439
- return value.replace(/'/g, "''");
440
- };
441
777
  const getObjectForRow = (row) => {
442
778
  const obj = {};
443
779
  row.columnNames.forEach((colName, index) => {
@@ -474,13 +810,37 @@ const getSqlResultObject = (queryResult) => {
474
810
  }
475
811
  return obj;
476
812
  };
813
+ /**
814
+ * True when the models row is linked (model_schemas) to any schema other than schemaId.
815
+ */
816
+ const isModelLinkedToOtherSchema = async (db, modelId, schemaId) => {
817
+ const links = await db
818
+ .select({ schemaId: modelSchemas.schemaId })
819
+ .from(modelSchemas)
820
+ .where(eq(modelSchemas.modelId, modelId));
821
+ return links.some((l) => l.schemaId !== schemaId);
822
+ };
823
+ const isModelLinkedToAnySchema = async (db, modelId) => {
824
+ const links = await db
825
+ .select({ id: modelSchemas.id })
826
+ .from(modelSchemas)
827
+ .where(eq(modelSchemas.modelId, modelId))
828
+ .limit(1);
829
+ return links.length > 0;
830
+ };
477
831
  /**
478
832
  * Find or create a models row by schemaFileId (preferred) or name.
479
833
  * Reuses an existing same-name row (especially schemaFileId=null stubs created via
480
834
  * ref resolution) instead of inserting a second row — models.name is not unique,
481
835
  * and duplicate names break createOrUpdate lookups (e.g. Resource.tags → Tag).
836
+ *
837
+ * When modelFileId is given, a same-name row that already carries a *different*
838
+ * non-null schemaFileId is only adopted if no other schema is linked to it via
839
+ * model_schemas. Otherwise it belongs to another schema (e.g. two schemas that each
840
+ * define "Post"), and re-id'ing it would strand that schema's cached Model instance,
841
+ * so a new row is inserted instead.
482
842
  */
483
- const findOrCreateModelRecord = async (db, modelName, modelFileId) => {
843
+ const findOrCreateModelRecord = async (db, modelName, modelFileId, schemaId) => {
484
844
  if (modelFileId) {
485
845
  const byFileId = await db
486
846
  .select()
@@ -504,15 +864,47 @@ const findOrCreateModelRecord = async (db, modelName, modelFileId) => {
504
864
  .from(models)
505
865
  .where(eq(models.name, modelName)));
506
866
  if (byName.length > 0) {
507
- // Prefer exact file-id match, then adoptable null schemaFileId stub, then any single row.
508
- let chosen = (modelFileId
867
+ // Prefer exact file-id match, then (for refs without a file id) this schema's row, then an
868
+ // adoptable null schemaFileId stub, then any single row.
869
+ let chosen = modelFileId
509
870
  ? byName.find((r) => r.schemaFileId === modelFileId)
510
- : undefined) ||
511
- byName.find((r) => !r.schemaFileId) ||
512
- (byName.length === 1 ? byName[0] : undefined) ||
513
- byName.find((r) => !!r.schemaFileId) ||
514
- byName[0];
515
- if (modelFileId && chosen.schemaFileId !== modelFileId) {
871
+ : undefined;
872
+ if (!chosen && !modelFileId && schemaId && byName.length > 1) {
873
+ for (const candidate of byName) {
874
+ if (!(await isModelLinkedToOtherSchema(db, candidate.id, schemaId))) {
875
+ const links = await db
876
+ .select({ schemaId: modelSchemas.schemaId })
877
+ .from(modelSchemas)
878
+ .where(eq(modelSchemas.modelId, candidate.id));
879
+ if (links.length > 0) {
880
+ chosen = candidate;
881
+ break;
882
+ }
883
+ }
884
+ }
885
+ }
886
+ chosen ?? (chosen = byName.find((r) => !r.schemaFileId));
887
+ if (!chosen && modelFileId) {
888
+ // Every same-name row has a different file id. Only adopt one that no other
889
+ // schema claims; otherwise fall through and insert a row for this file id.
890
+ // A row with a file id that no schema links is a deleted schema's leftover (its old
891
+ // properties are still attached), not an unclaimed row: don't adopt it either.
892
+ for (const candidate of byName) {
893
+ if (candidate.schemaFileId && !(await isModelLinkedToAnySchema(db, candidate.id)))
894
+ continue;
895
+ if (!(await isModelLinkedToOtherSchema(db, candidate.id, schemaId))) {
896
+ chosen = candidate;
897
+ break;
898
+ }
899
+ }
900
+ }
901
+ else if (!chosen) {
902
+ chosen =
903
+ (byName.length === 1 ? byName[0] : undefined) ||
904
+ byName.find((r) => !!r.schemaFileId) ||
905
+ byName[0];
906
+ }
907
+ if (chosen && modelFileId && chosen.schemaFileId !== modelFileId) {
516
908
  const conflict = await db
517
909
  .select()
518
910
  .from(models)
@@ -521,17 +913,17 @@ const findOrCreateModelRecord = async (db, modelName, modelFileId) => {
521
913
  if (conflict.length > 0) {
522
914
  return conflict[0];
523
915
  }
524
- // Adopt stub (null schemaFileId) or sole same-name row by attaching this file id.
525
- if (!chosen.schemaFileId || byName.length === 1) {
526
- await db
527
- .update(models)
528
- .set({ schemaFileId: modelFileId, isEdited: false })
529
- .where(eq(models.id, chosen.id));
530
- chosen = { ...chosen, schemaFileId: modelFileId, isEdited: false };
531
- logger(`Adopted existing model "${modelName}" (id: ${chosen.id}) with schemaFileId "${modelFileId}"`);
532
- }
916
+ // Adopt stub (null schemaFileId) or an unclaimed same-name row by attaching this file id.
917
+ await db
918
+ .update(models)
919
+ .set({ schemaFileId: modelFileId, isEdited: false })
920
+ .where(eq(models.id, chosen.id));
921
+ chosen = { ...chosen, schemaFileId: modelFileId, isEdited: false };
922
+ logger(`Adopted existing model "${modelName}" (id: ${chosen.id}) with schemaFileId "${modelFileId}"`);
923
+ }
924
+ if (chosen) {
925
+ return chosen;
533
926
  }
534
- return chosen;
535
927
  }
536
928
  try {
537
929
  const inserted = await db
@@ -570,6 +962,29 @@ const findOrCreateModelRecord = async (db, modelName, modelFileId) => {
570
962
  throw error;
571
963
  }
572
964
  };
965
+ /**
966
+ * Find or create the models row a Relation property on ownerModelId points to. Model names are only
967
+ * unique per schema, so the ref is looked up in the owner's schema(s) first; a global name lookup
968
+ * (createOrUpdate by name) threw "Multiple records found" once two schemas defined the ref model.
969
+ */
970
+ const findOrCreateRefModelRecord = async (db, refModelName, ownerModelId) => {
971
+ try {
972
+ const ref = await resolveRefModelRecord(refModelName, { modelId: ownerModelId }, db);
973
+ if (ref)
974
+ return ref;
975
+ }
976
+ catch (error) {
977
+ // Not in the owner's schema and defined by several others: pick/create like an import does
978
+ if (!(error instanceof AmbiguousModelError))
979
+ throw error;
980
+ }
981
+ const [ownerLink] = await db
982
+ .select({ schemaId: modelSchemas.schemaId })
983
+ .from(modelSchemas)
984
+ .where(eq(modelSchemas.modelId, ownerModelId))
985
+ .limit(1);
986
+ return findOrCreateModelRecord(db, refModelName, undefined, ownerLink?.schemaId ?? undefined);
987
+ };
573
988
  const createOrUpdate = async (db, table, values) => {
574
989
  const valueFilters = [];
575
990
  const propertiesToExcludeFromDb = ['ref'];
@@ -871,8 +1286,8 @@ const renameModelInDb = async (oldName, newName, schemaNameOrId) => {
871
1286
  if (!db) {
872
1287
  throw new Error('Database not found');
873
1288
  }
874
- const _mod_0 = await import('./BasePathResolver-B6CKqoKw.js');
875
- const _ns_0 = _mod_0.O;
1289
+ const _mod_0 = await import('./BasePathResolver-DRT09oVv.js');
1290
+ const _ns_0 = _mod_0.Q;
876
1291
  const { schemas: schemasTable } = _ns_0;
877
1292
  // Find the model by old name, optionally scoped by schema
878
1293
  let existingModels;
@@ -916,8 +1331,11 @@ const renameModelInDb = async (oldName, newName, schemaNameOrId) => {
916
1331
  isEdited: models.isEdited,
917
1332
  })
918
1333
  .from(models)
919
- .where(eq(models.name, oldName))
920
- .limit(1);
1334
+ .where(eq(models.name, oldName));
1335
+ // Model names are only unique per schema: an unscoped rename must not pick one arbitrarily.
1336
+ if (existingModels.length > 1) {
1337
+ throw new Error(`Model "${oldName}" exists in more than one schema; pass the schema name or id to rename it`);
1338
+ }
921
1339
  }
922
1340
  if (existingModels.length === 0) {
923
1341
  if (schemaNameOrId !== undefined) {
@@ -991,7 +1409,9 @@ const renameModelInDb = async (oldName, newName, schemaNameOrId) => {
991
1409
  * @param schemaFileValue - Optional schema file value to compare against database
992
1410
  * @returns true if the property is marked as edited, false otherwise
993
1411
  */
994
- async function checkIfPropertyIsEdited(modelName, propertyName, schemaFileValue) {
1412
+ async function checkIfPropertyIsEdited(modelName, propertyName, schemaFileValue,
1413
+ /** The property's models row (model names are only unique per schema). */
1414
+ modelId) {
995
1415
  try {
996
1416
  // When schemaFileValue is provided (schema sync path), do database check FIRST.
997
1417
  // This avoids the ModelProperty dynamic import which can hang due to circular
@@ -1000,11 +1420,8 @@ async function checkIfPropertyIsEdited(modelName, propertyName, schemaFileValue)
1000
1420
  const db = BaseDb.getAppDb();
1001
1421
  if (db) {
1002
1422
  // Find the model
1003
- const modelRecords = await db
1004
- .select()
1005
- .from(models)
1006
- .where(eq(models.name, modelName))
1007
- .limit(1);
1423
+ const resolvedModel = await resolveModelRecord(modelName, { modelId }, db);
1424
+ const modelRecords = resolvedModel ? [resolvedModel] : [];
1008
1425
  if (modelRecords.length > 0) {
1009
1426
  const modelRecord = modelRecords[0];
1010
1427
  // Find the property in the database
@@ -1023,13 +1440,9 @@ async function checkIfPropertyIsEdited(modelName, propertyName, schemaFileValue)
1023
1440
  }
1024
1441
  // Check refModelId if it's a relation
1025
1442
  if (schemaFileValue.ref) {
1026
- const refModelRecords = await db
1027
- .select()
1028
- .from(models)
1029
- .where(eq(models.name, schemaFileValue.ref))
1030
- .limit(1);
1031
- if (refModelRecords.length > 0) {
1032
- const expectedRefModelId = refModelRecords[0].id;
1443
+ const refModelRecord = await resolveRefModelRecord(schemaFileValue.ref, { modelId: modelRecord.id }, db);
1444
+ if (refModelRecord) {
1445
+ const expectedRefModelId = refModelRecord.id;
1033
1446
  if (dbProperty.refModelId !== expectedRefModelId) {
1034
1447
  logger(`Property ${modelName}:${propertyName} has been edited (refModelId differs)`);
1035
1448
  return true;
@@ -1055,6 +1468,22 @@ async function checkIfPropertyIsEdited(modelName, propertyName, schemaFileValue)
1055
1468
  return true;
1056
1469
  }
1057
1470
  }
1471
+ // Storage settings. Rows written before they were stored (all null) aren't edits: the
1472
+ // schema file's values fill them in on this load.
1473
+ const dbStorage = {
1474
+ storageType: dbProperty.storageType ?? null,
1475
+ localStorageDir: dbProperty.localStorageDir ?? null,
1476
+ filenameSuffix: dbProperty.filenameSuffix ?? null,
1477
+ };
1478
+ if (hasStorageSettings(dbStorage)) {
1479
+ const fileStorage = propertyStorageColumns(schemaFileValue);
1480
+ if (dbStorage.storageType !== fileStorage.storageType ||
1481
+ dbStorage.localStorageDir !== fileStorage.localStorageDir ||
1482
+ dbStorage.filenameSuffix !== fileStorage.filenameSuffix) {
1483
+ logger(`Property ${modelName}:${propertyName} has been edited (storage settings differ)`);
1484
+ return true;
1485
+ }
1486
+ }
1058
1487
  }
1059
1488
  }
1060
1489
  }
@@ -1108,9 +1537,9 @@ const addModelsToDb = async (models$1, schema, modelRenames, schemaFileData) =>
1108
1537
  for (const [modelName, modelClass] of Object.entries(models$1)) {
1109
1538
  try {
1110
1539
  const modelFileId = schemaFileData?.modelFileIds?.get(modelName);
1111
- let modelRecord = await findOrCreateModelRecord(db, modelName, modelFileId);
1540
+ let modelRecord = await findOrCreateModelRecord(db, modelName, modelFileId, schemaRecord?.id);
1112
1541
  // Keep schemaFileId aligned when findOrCreate returned a row that still needs adoption
1113
- // (e.g. sole same-name row that already had a different non-null id — rare).
1542
+ // (rare: findOrCreate handles stubs and unclaimed same-name rows itself).
1114
1543
  if (modelFileId && modelRecord.schemaFileId !== modelFileId) {
1115
1544
  const existingWithFileId = await db
1116
1545
  .select()
@@ -1194,6 +1623,8 @@ const addModelsToDb = async (models$1, schema, modelRenames, schemaFileData) =>
1194
1623
  dataType: normalizeDataType(propertyValues.dataType),
1195
1624
  schemaFileId: propertyFileId || null,
1196
1625
  required: propertyValues.required ?? false,
1626
+ // The schema file is the source of truth here: no storage config means none.
1627
+ ...propertyStorageColumns(propertyValues),
1197
1628
  };
1198
1629
  // Handle ref property - create ref model if needed
1199
1630
  // Check both ref and refModelName (refModelName is set by createModelFromJson)
@@ -1205,7 +1636,7 @@ const addModelsToDb = async (models$1, schema, modelRenames, schemaFileData) =>
1205
1636
  const refModelFileId = schemaFileData?.modelFileIds?.get(refModelName);
1206
1637
  const refModel = cachedRef
1207
1638
  ? cachedRef
1208
- : await findOrCreateModelRecord(db, refModelName, refModelFileId);
1639
+ : await findOrCreateModelRecord(db, refModelName, refModelFileId, schemaRecord?.id);
1209
1640
  if (!cachedRef) {
1210
1641
  modelRecords.set(refModelName, refModel);
1211
1642
  }
@@ -1258,7 +1689,8 @@ const addModelsToDb = async (models$1, schema, modelRenames, schemaFileData) =>
1258
1689
  ref: propertyValues.ref,
1259
1690
  refValueType: propertyValues.refValueType,
1260
1691
  required: propertyValues.required,
1261
- });
1692
+ ...propertyStorageColumns(propertyValues),
1693
+ }, modelRecord.id);
1262
1694
  if (isPropertyEdited) {
1263
1695
  // Property has been locally edited - skip update to preserve local changes
1264
1696
  logger(`Skipping update for property ${modelName}:${existingProperty.name} -> ${propertyName} - it has been locally edited and will be preserved`);
@@ -1283,6 +1715,9 @@ const addModelsToDb = async (models$1, schema, modelRenames, schemaFileData) =>
1283
1715
  existingProperty.required === (updateData.required ?? false) &&
1284
1716
  existingProperty.refModelId === (updateData.refModelId ?? null) &&
1285
1717
  existingProperty.refValueType === (updateData.refValueType ?? null) &&
1718
+ (existingProperty.storageType ?? null) === (updateData.storageType ?? null) &&
1719
+ (existingProperty.localStorageDir ?? null) === (updateData.localStorageDir ?? null) &&
1720
+ (existingProperty.filenameSuffix ?? null) === (updateData.filenameSuffix ?? null) &&
1286
1721
  existingProperty.isEdited === (updateData.isEdited ?? false);
1287
1722
  if (!unchanged) {
1288
1723
  await db
@@ -1358,10 +1793,8 @@ const addModelsToDb = async (models$1, schema, modelRenames, schemaFileData) =>
1358
1793
  const toInsert = modelIds.filter(({ modelId }) => !existingSet.has(modelId));
1359
1794
  if (toInsert.length > 0) {
1360
1795
  for (const { modelName, modelId } of toInsert) {
1361
- await db.insert(modelSchemas).values({
1362
- modelId,
1363
- schemaId: schemaRecord.id,
1364
- });
1796
+ if (!(await linkModelToSchema(db, modelId, schemaRecord.id)))
1797
+ continue;
1365
1798
  logger(`Created join table entry for model ${modelName} (id: ${modelId}) to schema (id: ${schemaRecord.id})`);
1366
1799
  }
1367
1800
  }
@@ -1432,6 +1865,12 @@ const loadModelsFromDbForSchema = async (schemaId) => {
1432
1865
  if (prop.refValueType) {
1433
1866
  propertyData.refValueType = normalizeDataType(prop.refValueType ?? undefined);
1434
1867
  }
1868
+ if (prop.storageType)
1869
+ propertyData.storageType = prop.storageType;
1870
+ if (prop.localStorageDir)
1871
+ propertyData.localStorageDir = prop.localStorageDir;
1872
+ if (prop.filenameSuffix)
1873
+ propertyData.filenameSuffix = prop.filenameSuffix;
1435
1874
  modelProperties[prop.name] = propertyData;
1436
1875
  }
1437
1876
  // Create model structure. Include id (schemaFileId) so processSchemaFiles can populate
@@ -1531,12 +1970,8 @@ const savePropertyToDb = async (property) => {
1531
1970
  modelRecord = byId[0];
1532
1971
  }
1533
1972
  if (!modelRecord && property.modelName) {
1534
- const byName = await db
1535
- .select()
1536
- .from(models)
1537
- .where(eq(models.name, property.modelName))
1538
- .limit(1);
1539
- modelRecord = byName[0];
1973
+ // Model names are only unique per schema: scope by the property's schema when known
1974
+ modelRecord = await resolveModelRecord(property.modelName, { schemaName: property._schemaName }, db);
1540
1975
  }
1541
1976
  if (!modelRecord && property.modelName) {
1542
1977
  const bySchemaFileId = await db
@@ -1610,9 +2045,7 @@ const savePropertyToDb = async (property) => {
1610
2045
  }
1611
2046
  // Handle ref property - create ref model if needed
1612
2047
  if (property.refModelName) {
1613
- const refModel = await createOrUpdate(db, models, {
1614
- name: property.refModelName,
1615
- });
2048
+ const refModel = await findOrCreateRefModelRecord(db, property.refModelName, modelRecord.id);
1616
2049
  propertyData.refModelId = refModel.id;
1617
2050
  }
1618
2051
  else if (property.refModelId) {
@@ -1630,6 +2063,12 @@ const savePropertyToDb = async (property) => {
1630
2063
  propertyData.refValueType = null;
1631
2064
  }
1632
2065
  propertyData.required = property.required ?? false;
2066
+ // Only when the context has storage settings: a context built without them (e.g. loaded before
2067
+ // they were stored) must not clear the row's.
2068
+ const storage = propertyStorageColumns(property);
2069
+ if (hasStorageSettings(storage)) {
2070
+ Object.assign(propertyData, storage);
2071
+ }
1633
2072
  if (existingProperties.length > 0) {
1634
2073
  // Property exists, update it with new values (including new name)
1635
2074
  // Set isEdited = true when property is edited
@@ -1851,8 +2290,8 @@ async function writeModelToDb(modelFileId, data) {
1851
2290
  throw new Error(`Model with id ${modelId} does not exist in database. Cannot create join record.`);
1852
2291
  }
1853
2292
  // Verify schemaId exists and get name/fileId for invalidation broadcast
1854
- const _mod_1 = await import('./BasePathResolver-B6CKqoKw.js');
1855
- const _ns_1 = _mod_1.O;
2293
+ const _mod_1 = await import('./BasePathResolver-DRT09oVv.js');
2294
+ const _ns_1 = _mod_1.Q;
1856
2295
  const schemaSchemaMod = _ns_1;
1857
2296
  const { schemas: schemasTable } = schemaSchemaMod;
1858
2297
  const schemaCheck = await db
@@ -1868,10 +2307,7 @@ async function writeModelToDb(modelFileId, data) {
1868
2307
  throw new Error(`Schema with id ${data.schemaId} does not exist in database. Cannot create join record.`);
1869
2308
  }
1870
2309
  logger(`Creating join record: modelId=${modelId}, schemaId=${data.schemaId} (both verified to exist)`);
1871
- await db.insert(modelSchemas).values({
1872
- modelId,
1873
- schemaId: data.schemaId,
1874
- });
2310
+ await linkModelToSchema(db, modelId, data.schemaId);
1875
2311
  // Notify React useModels so it can invalidate; live query over join often doesn't re-run when model_schemas is inserted.
1876
2312
  // Yield so the insert is visible to the refetch that will run when the broadcast is received.
1877
2313
  if (typeof BroadcastChannel !== 'undefined') {
@@ -1969,9 +2405,7 @@ async function writePropertyToDb(propertyFileId, data, isEdited = false) {
1969
2405
  // Check refModelName first, then ref (for backwards compatibility with schema files)
1970
2406
  const refModelName = data.refModelName || data.ref;
1971
2407
  if (refModelName) {
1972
- const refModel = await createOrUpdate(db, models, {
1973
- name: refModelName,
1974
- });
2408
+ const refModel = await findOrCreateRefModelRecord(db, refModelName, data.modelId);
1975
2409
  propertyData.refModelId = refModel.id;
1976
2410
  }
1977
2411
  else if (data.refModelId) {
@@ -1988,9 +2422,17 @@ async function writePropertyToDb(propertyFileId, data, isEdited = false) {
1988
2422
  // If refValueType is not set, ensure it's null
1989
2423
  propertyData.refValueType = null;
1990
2424
  }
1991
- propertyData.required = data.required ?? false;
1992
- // Note: Additional property fields like storageType, localStorageDir, filenameSuffix
1993
- // are not stored in the properties table but may be in the schema JSON
2425
+ // Only overwrite `required` when the caller knows it. The creation write's payload can lack it, and
2426
+ // defaulting to false here cleared the flag the schema import set (required relations became optional).
2427
+ if (data.required !== undefined) {
2428
+ propertyData.required = data.required;
2429
+ }
2430
+ // Storage settings, like `required`, only when the caller has them: the creation write's payload
2431
+ // can lack them, and writing nulls would clear what the schema import stored.
2432
+ const storage = propertyStorageColumns(data);
2433
+ if (hasStorageSettings(storage)) {
2434
+ Object.assign(propertyData, storage);
2435
+ }
1994
2436
  if (existingProperties.length > 0) {
1995
2437
  // Property exists, update it with new values.
1996
2438
  // Use existing row id for WHERE (not name+modelId) so renames work: the row
@@ -2020,7 +2462,7 @@ async function writePropertyToDb(propertyFileId, data, isEdited = false) {
2020
2462
  }
2021
2463
  else {
2022
2464
  try {
2023
- await db.insert(properties).values(propertyData);
2465
+ await db.insert(properties).values({ required: false, ...propertyData });
2024
2466
  logger(`Created property ${data.name} (${propertyFileId}) in database`);
2025
2467
  }
2026
2468
  catch (error) {
@@ -2061,8 +2503,8 @@ async function getSchemaId(schemaNameOrFileId) {
2061
2503
  if (!db) {
2062
2504
  throw new Error('Database not available');
2063
2505
  }
2064
- const _mod_2 = await import('./BasePathResolver-B6CKqoKw.js');
2065
- const _ns_2 = _mod_2.O;
2506
+ const _mod_2 = await import('./BasePathResolver-DRT09oVv.js');
2507
+ const _ns_2 = _mod_2.Q;
2066
2508
  const schemaSchemaMod = _ns_2;
2067
2509
  const { schemas: schemasTable } = schemaSchemaMod;
2068
2510
  const drizzleMod = await import('drizzle-orm');
@@ -2099,8 +2541,8 @@ async function getSchemaIdByFileId(schemaFileId) {
2099
2541
  if (!db) {
2100
2542
  throw new Error('Database not available');
2101
2543
  }
2102
- const _mod_3 = await import('./BasePathResolver-B6CKqoKw.js');
2103
- const _ns_3 = _mod_3.O;
2544
+ const _mod_3 = await import('./BasePathResolver-DRT09oVv.js');
2545
+ const _ns_3 = _mod_3.Q;
2104
2546
  const schemaSchemaMod = _ns_3;
2105
2547
  const { schemas: schemasTable } = schemaSchemaMod;
2106
2548
  const drizzleMod = await import('drizzle-orm');
@@ -2128,8 +2570,8 @@ async function getModelId(modelNameOrFileId, schemaNameOrId) {
2128
2570
  if (!db) {
2129
2571
  throw new Error('Database not available');
2130
2572
  }
2131
- const _mod_4 = await import('./BasePathResolver-B6CKqoKw.js');
2132
- const _ns_4 = _mod_4.M;
2573
+ const _mod_4 = await import('./BasePathResolver-DRT09oVv.js');
2574
+ const _ns_4 = _mod_4.N;
2133
2575
  const modelSchemaMod = _ns_4;
2134
2576
  const { models: modelsTable } = modelSchemaMod;
2135
2577
  const drizzleMod = await import('drizzle-orm');
@@ -2145,12 +2587,12 @@ async function getModelId(modelNameOrFileId, schemaNameOrId) {
2145
2587
  [eq(modelsTable.name, modelNameOrFileId)];
2146
2588
  // If schema is provided, narrow the search
2147
2589
  if (schemaNameOrId !== undefined) {
2148
- const _mod_5 = await import('./BasePathResolver-B6CKqoKw.js');
2149
- const _ns_5 = _mod_5.Q;
2590
+ const _mod_5 = await import('./BasePathResolver-DRT09oVv.js');
2591
+ const _ns_5 = _mod_5.R;
2150
2592
  const modelSchemaSchemaMod = _ns_5;
2151
2593
  const { modelSchemas } = modelSchemaSchemaMod;
2152
- const _mod_6 = await import('./BasePathResolver-B6CKqoKw.js');
2153
- const _ns_6 = _mod_6.O;
2594
+ const _mod_6 = await import('./BasePathResolver-DRT09oVv.js');
2595
+ const _ns_6 = _mod_6.Q;
2154
2596
  const schemaSchemaMod = _ns_6;
2155
2597
  const { schemas: schemasTable } = schemaSchemaMod;
2156
2598
  if (typeof schemaNameOrId === 'number') {
@@ -2174,12 +2616,9 @@ async function getModelId(modelNameOrFileId, schemaNameOrId) {
2174
2616
  }
2175
2617
  }
2176
2618
  else {
2177
- // No schema filter, just search by name
2178
- records = await db
2179
- .select()
2180
- .from(modelsTable)
2181
- .where(eq(modelsTable.name, modelNameOrFileId))
2182
- .limit(1);
2619
+ // No schema filter: name-only (newest row, warns when the name is ambiguous)
2620
+ const byName = await resolveModelRecord(modelNameOrFileId, {}, db);
2621
+ records = byName ? [byName] : [];
2183
2622
  }
2184
2623
  }
2185
2624
  if (records.length === 0) {
@@ -2199,8 +2638,8 @@ async function getModelIdByFileId(modelFileId) {
2199
2638
  if (!db) {
2200
2639
  throw new Error('Database not available');
2201
2640
  }
2202
- const _mod_7 = await import('./BasePathResolver-B6CKqoKw.js');
2203
- const _ns_7 = _mod_7.M;
2641
+ const _mod_7 = await import('./BasePathResolver-DRT09oVv.js');
2642
+ const _ns_7 = _mod_7.N;
2204
2643
  const modelSchemaMod = _ns_7;
2205
2644
  const { models: modelsTable } = modelSchemaMod;
2206
2645
  const drizzleMod = await import('drizzle-orm');
@@ -2221,11 +2660,11 @@ var db = /*#__PURE__*/Object.freeze({
2221
2660
  addModelsToDb: addModelsToDb,
2222
2661
  addSchemaToDb: addSchemaToDb,
2223
2662
  createOrUpdate: createOrUpdate,
2224
- escapeSqliteString: escapeSqliteString,
2225
2663
  getAddressesForItemsFilter: getAddressesForItemsFilter,
2226
2664
  getAddressesFromDb: getAddressesFromDb,
2227
2665
  getAddressesFromDbOptional: getAddressesFromDbOptional,
2228
2666
  getAllAddressesFromDb: getAllAddressesFromDb,
2667
+ getItemStoragePropertiesForModel: getItemStoragePropertiesForModel,
2229
2668
  getModelId: getModelId,
2230
2669
  getModelIdByFileId: getModelIdByFileId,
2231
2670
  getModelNameByModelId: getModelNameByModelId,
@@ -2240,11 +2679,12 @@ var db = /*#__PURE__*/Object.freeze({
2240
2679
  getWatchedAddressesFromDb: getWatchedAddressesFromDb,
2241
2680
  loadModelsFromDbForSchema: loadModelsFromDbForSchema,
2242
2681
  migrateMetadataForPropertyRename: migrateMetadataForPropertyRename,
2682
+ propertyStorageColumns: propertyStorageColumns,
2243
2683
  renameModelInDb: renameModelInDb,
2244
2684
  savePropertyToDb: savePropertyToDb,
2245
2685
  writeModelToDb: writeModelToDb,
2246
2686
  writePropertyToDb: writePropertyToDb
2247
2687
  });
2248
2688
 
2249
- export { addSchemaToDb as A, Boolean as B, renameModelInDb as C, DEFAULT_TEXT_MAX_LENGTH as D, loadModelsFromDbForSchema as E, File as F, getOwnedAddressesFromDb as G, Html as H, Image as I, Json as J, getPropertyIdForSchemaFileId as K, List as L, ModelPropertyDataTypes as M, Number$1 as N, getWatchedAddressesFromDb as O, Property as P, db as Q, Relation as R, THtmlEmbeddedDataUriPolicy as T, Date$1 as a, PropertyConstructor as b, PropertyMetadataKey as c, TProperty as d, TPropertyConstructor as e, TPropertyDataType as f, TPropertyDefs as g, TStorageType as h, TValidationRules as i, Text as j, isDataType as k, normalizePropertyRecordSchema as l, getPropertyIdForModelAndName as m, normalizeDataType as n, normalizePublisher as o, getAllAddressesFromDb as p, escapeSqliteString as q, normalizeHexAddress as r, addModelsToDb as s, getModelIdByFileId as t, getModelId as u, getAddressesForItemsFilter as v, normalizeAddressConfig as w, normalizeAddressList as x, writeModelToDb as y, writePropertyToDb as z };
2250
- //# sourceMappingURL=db-WbrzEf7c.js.map
2689
+ export { AmbiguousModelError as A, Boolean as B, normalizeAddressConfig as C, DEFAULT_TEXT_MAX_LENGTH as D, normalizeAddressList as E, File as F, writeModelToDb as G, Html as H, Image as I, Json as J, writePropertyToDb as K, List as L, ModelPropertyDataTypes as M, Number$1 as N, addSchemaToDb as O, Property as P, renameModelInDb as Q, Relation as R, loadModelsFromDbForSchema as S, THtmlEmbeddedDataUriPolicy as T, linkModelToSchema as U, getWatchedAddressesFromDb as V, getOwnedAddressesFromDb as W, getPropertyIdForSchemaFileId as X, resolveModelRecord$1 as Y, db as Z, Date$1 as a, PropertyConstructor as b, PropertyMetadataKey as c, TProperty as d, TPropertyConstructor as e, TPropertyDataType as f, TPropertyDefs as g, TStorageType as h, TValidationRules as i, Text as j, isDataType as k, normalizePropertyRecordSchema as l, eventEmitter as m, normalizeDataType as n, getPropertyIdForModelAndName as o, resolveModelRecord as p, getItemModelScope as q, resolveItemModelFileId as r, normalizePublisher as s, getAllAddressesFromDb as t, normalizeHexAddress as u, getItemStoragePropertiesForModel as v, addModelsToDb as w, getModelIdByFileId as x, getModelId as y, getAddressesForItemsFilter as z };
2690
+ //# sourceMappingURL=db-Lw0KVZmc.js.map