@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.
- package/dist/{BasePathResolver-B6CKqoKw.js → BasePathResolver-DRT09oVv.js} +36 -2
- package/dist/BasePathResolver-DRT09oVv.js.map +1 -0
- package/dist/ClientManager-DngaZdw6.js +4763 -0
- package/dist/ClientManager-DngaZdw6.js.map +1 -0
- package/dist/{ClientManager-ChcmUL47.js → Item-ZUAmf943.js} +1175 -5903
- package/dist/Item-ZUAmf943.js.map +1 -0
- package/dist/{ModelProperty-D79uV42p.js → ModelProperty-6llK4MTH.js} +326 -109
- package/dist/ModelProperty-6llK4MTH.js.map +1 -0
- package/dist/{Schema-a8uO-hIZ.js → Schema-D-Ud-XYw.js} +164 -885
- package/dist/Schema-D-Ud-XYw.js.map +1 -0
- package/dist/{SchemaValidationService-Y49vqast.js → SchemaValidationService-IoS7JquP.js} +26 -18
- package/dist/SchemaValidationService-IoS7JquP.js.map +1 -0
- package/dist/{backfillMetadataPropertyIds-CBsf7LnU.js → backfillMetadataPropertyIds-BlVeE7w7.js} +11 -6
- package/dist/backfillMetadataPropertyIds-BlVeE7w7.js.map +1 -0
- package/dist/cjs/{ModelProperty-D9FGaGuE.js → ModelProperty-Dv7AQfmQ.js} +297 -89
- package/dist/cjs/ModelProperty-Dv7AQfmQ.js.map +1 -0
- package/dist/cjs/{Schema-BiJIPLEL.js → Schema-BHVp1g-M.js} +136 -868
- package/dist/cjs/Schema-BHVp1g-M.js.map +1 -0
- package/dist/cjs/{SchemaValidationService-DtYs_CNY.js → SchemaValidationService-BSU9knjf.js} +18 -11
- package/dist/cjs/SchemaValidationService-BSU9knjf.js.map +1 -0
- package/dist/cjs/{backfillMetadataPropertyIds-2XaN3b9S.js → backfillMetadataPropertyIds-WIovQ_d8.js} +8 -3
- package/dist/cjs/backfillMetadataPropertyIds-WIovQ_d8.js.map +1 -0
- package/dist/cjs/{eas-CMNppmGE.js → eas-CUYXdr2t.js} +4 -4
- package/dist/cjs/{eas-CMNppmGE.js.map → eas-CUYXdr2t.js.map} +1 -1
- package/dist/cjs/{getItem-B6jEINjW.js → getItem-z1tHu0hu.js} +2 -2
- package/dist/cjs/{getItem-B6jEINjW.js.map → getItem-z1tHu0hu.js.map} +1 -1
- package/dist/cjs/getLatestVersionRow-CcaabxIW.js +59 -0
- package/dist/cjs/getLatestVersionRow-CcaabxIW.js.map +1 -0
- package/dist/cjs/{getPublishPayload-D5DhLGvN.js → getPublishPayload-CEP_e-Kv.js} +283 -138
- package/dist/cjs/getPublishPayload-CEP_e-Kv.js.map +1 -0
- package/dist/cjs/{getPublishUploads-DMhCCKYF.js → getPublishUploads-Ctn5k1k6.js} +65 -19
- package/dist/cjs/getPublishUploads-Ctn5k1k6.js.map +1 -0
- package/dist/cjs/{index-CSNtEnbF.js → index-Cvvt0-5B.js} +2698 -1725
- package/dist/cjs/index-Cvvt0-5B.js.map +1 -0
- package/dist/cjs/{index-DPp9rdRL.js → index-DfGhF1dc.js} +3 -3
- package/dist/cjs/index-DfGhF1dc.js.map +1 -0
- package/dist/cjs/{property-DlKiAWt4.js → property-DbEPQ1m9.js} +40 -35
- package/dist/cjs/property-DbEPQ1m9.js.map +1 -0
- package/dist/cjs/publishDraftGraph-C38gf302.js +403 -0
- package/dist/cjs/publishDraftGraph-C38gf302.js.map +1 -0
- package/dist/cjs/resetAmbiguousLegacyItemData-CfMhRHwK.js +116 -0
- package/dist/cjs/resetAmbiguousLegacyItemData-CfMhRHwK.js.map +1 -0
- package/dist/cjs/resolveModelForSyncedSeed-CNYaLOir.js +49 -0
- package/dist/cjs/resolveModelForSyncedSeed-CNYaLOir.js.map +1 -0
- package/dist/cjs/syncDbWithEas-d1iOdTTI.js +886 -0
- package/dist/cjs/syncDbWithEas-d1iOdTTI.js.map +1 -0
- package/dist/{configurePlatform-CE0Vew17.js → configurePlatform-CZpjyuCo.js} +4 -4
- package/dist/{configurePlatform-CE0Vew17.js.map → configurePlatform-CZpjyuCo.js.map} +1 -1
- package/dist/db/drizzle/0015_add_model_file_id_to_seeds.sql +11 -0
- package/dist/db/drizzle/0016_add_revoked_at_to_metadata.sql +1 -0
- package/dist/db/drizzle/0017_add_revoked_at_to_versions.sql +1 -0
- package/dist/db/drizzle/0018_add_storage_settings_to_properties.sql +53 -0
- package/dist/db/drizzle/0019_add_derived_from_uid_to_metadata.sql +35 -0
- package/dist/db/drizzle/meta/0011_snapshot.json +1182 -0
- package/dist/db/drizzle/meta/0012_snapshot.json +1244 -0
- package/dist/db/drizzle/meta/0013_snapshot.json +63 -1
- package/dist/db/drizzle/meta/0014_snapshot.json +62 -0
- package/dist/db/drizzle/meta/0015_snapshot.json +1338 -0
- package/dist/db/drizzle/meta/0016_snapshot.json +1345 -0
- package/dist/db/drizzle/meta/0017_snapshot.json +1352 -0
- package/dist/db/drizzle/meta/0018_snapshot.json +1373 -0
- package/dist/db/drizzle/meta/0019_snapshot.json +1380 -0
- package/dist/db/drizzle/meta/_journal.json +35 -0
- package/dist/{db-WbrzEf7c.js → db-Lw0KVZmc.js} +546 -106
- package/dist/db-Lw0KVZmc.js.map +1 -0
- package/dist/{eas-CfYCu4IX.js → eas-CQ-Smzk2.js} +7 -7
- package/dist/eas-CQ-Smzk2.js.map +1 -0
- package/dist/errors-CrBxGWah.js +17 -0
- package/dist/errors-CrBxGWah.js.map +1 -0
- package/dist/{getItem-Br-bGNFO.js → getItem-CSfSok9f.js} +8 -10
- package/dist/{getItem-Br-bGNFO.js.map → getItem-CSfSok9f.js.map} +1 -1
- package/dist/getLatestVersionRow-72Atl9vB.js +46 -0
- package/dist/getLatestVersionRow-72Atl9vB.js.map +1 -0
- package/dist/{getPublishPayload-BIrTVUxb.js → getPublishPayload-76_KfB5Y.js} +297 -154
- package/dist/getPublishPayload-76_KfB5Y.js.map +1 -0
- package/dist/{getPublishUploads-C6cDeZdz.js → getPublishUploads-CqgMBD8f.js} +68 -21
- package/dist/getPublishUploads-CqgMBD8f.js.map +1 -0
- package/dist/{index-Djd3667v.js → index-5b3JsS55.js} +2 -2
- package/dist/index-5b3JsS55.js.map +1 -0
- package/dist/{index-ClSv5pTA.js → index-BpgD305l.js} +12 -11
- package/dist/index-BpgD305l.js.map +1 -0
- package/dist/{index-HRHkbVQd.js → index-Y-yYyRBf.js} +530 -196
- package/dist/index-Y-yYyRBf.js.map +1 -0
- package/dist/index.browser-DaTzn79x.js +4139 -0
- package/dist/index.browser-DaTzn79x.js.map +1 -0
- package/dist/{index.node-DBtQkEfz.js → index.node-NYKqFOoe.js} +9 -4
- package/dist/index.node-NYKqFOoe.js.map +1 -0
- package/dist/main.cjs +1 -1
- package/dist/main.js +886 -560
- package/dist/main.js.map +1 -1
- package/dist/node.js +19 -15
- package/dist/node.js.map +1 -1
- package/dist/platform.browser.js +18 -3719
- package/dist/platform.browser.js.map +1 -1
- package/dist/platform.node.js +3 -3
- package/dist/{property-CQjuZ4JW.js → property-ByaiSyUK.js} +53 -48
- package/dist/property-ByaiSyUK.js.map +1 -0
- package/dist/publishDraftGraph-BRm6Pq3Q.js +405 -0
- package/dist/publishDraftGraph-BRm6Pq3Q.js.map +1 -0
- package/dist/resetAmbiguousLegacyItemData-B4dX6ZA1.js +88 -0
- package/dist/resetAmbiguousLegacyItemData-B4dX6ZA1.js.map +1 -0
- package/dist/resolveModelForSyncedSeed-B0tco3zG.js +46 -0
- package/dist/resolveModelForSyncedSeed-B0tco3zG.js.map +1 -0
- package/dist/seedSchema/MetadataSchema.ts +9 -0
- package/dist/seedSchema/ModelSchema.ts +5 -0
- package/dist/seedSchema/SeedSchema.ts +3 -0
- package/dist/seedSchema/VersionSchema.ts +5 -0
- package/dist/src/Item/Item.d.ts +21 -0
- package/dist/src/Item/Item.d.ts.map +1 -1
- package/dist/src/Item/service/actors/loadOrCreateItem.d.ts.map +1 -1
- package/dist/src/Item/service/actors/waitForDb.d.ts.map +1 -1
- package/dist/src/Item/service/itemMachineSingle.d.ts +3 -29
- package/dist/src/Item/service/itemMachineSingle.d.ts.map +1 -1
- package/dist/src/ItemProperty/ItemProperty.d.ts +13 -4
- package/dist/src/ItemProperty/ItemProperty.d.ts.map +1 -1
- package/dist/src/ItemProperty/service/actors/hydrateFromDb.d.ts.map +1 -1
- package/dist/src/ItemProperty/service/actors/loadOrCreateProperty.d.ts.map +1 -1
- package/dist/src/ItemProperty/service/actors/saveValueToDb/saveFile.d.ts.map +1 -1
- package/dist/src/ItemProperty/service/actors/saveValueToDb/saveHtml.d.ts.map +1 -1
- package/dist/src/ItemProperty/service/actors/saveValueToDb/saveImage.d.ts.map +1 -1
- package/dist/src/ItemProperty/service/actors/saveValueToDb/saveItemStorage.d.ts.map +1 -1
- package/dist/src/ItemProperty/service/propertyMachine.d.ts +4 -9
- package/dist/src/ItemProperty/service/propertyMachine.d.ts.map +1 -1
- package/dist/src/Model/Model.d.ts +52 -2
- package/dist/src/Model/Model.d.ts.map +1 -1
- package/dist/src/Model/errors.d.ts +10 -0
- package/dist/src/Model/errors.d.ts.map +1 -0
- package/dist/src/Model/service/actors/createModelProperties.d.ts.map +1 -1
- package/dist/src/Model/service/actors/loadOrCreateModel.d.ts.map +1 -1
- package/dist/src/Model/service/actors/validateModel.d.ts.map +1 -1
- package/dist/src/Model/service/modelMachine.d.ts +0 -8
- package/dist/src/Model/service/modelMachine.d.ts.map +1 -1
- package/dist/src/ModelProperty/ModelProperty.d.ts +42 -2
- package/dist/src/ModelProperty/ModelProperty.d.ts.map +1 -1
- package/dist/src/ModelProperty/service/actors/compareAndMarkDraft.d.ts.map +1 -1
- package/dist/src/ModelProperty/service/actors/saveToSchema.d.ts.map +1 -1
- package/dist/src/ModelProperty/service/actors/validateProperty.d.ts.map +1 -1
- package/dist/src/ModelProperty/service/modelPropertyMachine.d.ts +2 -9
- package/dist/src/ModelProperty/service/modelPropertyMachine.d.ts.map +1 -1
- package/dist/src/Schema/Schema.d.ts +8 -2
- package/dist/src/Schema/Schema.d.ts.map +1 -1
- package/dist/src/Schema/service/actors/checkExistingSchema.d.ts.map +1 -1
- package/dist/src/Schema/service/actors/createModelInstances.d.ts.map +1 -1
- package/dist/src/Schema/service/actors/loadOrCreateSchema.d.ts.map +1 -1
- package/dist/src/Schema/service/schemaMachine.d.ts +1 -217
- package/dist/src/Schema/service/schemaMachine.d.ts.map +1 -1
- package/dist/src/Schema/service/validation/SchemaValidationService.d.ts.map +1 -1
- package/dist/src/browser/db/Db.d.ts +3 -0
- package/dist/src/browser/db/Db.d.ts.map +1 -1
- package/dist/src/browser/db/drizzleFiles.d.ts +7 -2
- package/dist/src/browser/db/drizzleFiles.d.ts.map +1 -1
- package/dist/src/browser/db/embeddedMigrations.d.ts +11 -2
- package/dist/src/browser/db/embeddedMigrations.d.ts.map +1 -1
- package/dist/src/browser/db/sqliteBusyRetry.d.ts +14 -0
- package/dist/src/browser/db/sqliteBusyRetry.d.ts.map +1 -0
- package/dist/src/browser/helpers/FileManager.d.ts +1 -0
- package/dist/src/browser/helpers/FileManager.d.ts.map +1 -1
- package/dist/src/browser/helpers/QueryClient.d.ts +1 -0
- package/dist/src/browser/helpers/QueryClient.d.ts.map +1 -1
- package/dist/src/browser/helpers/opfsErrors.d.ts +2 -0
- package/dist/src/browser/helpers/opfsErrors.d.ts.map +1 -0
- package/dist/src/browser/helpers/tolerantWebAccess.d.ts +47 -0
- package/dist/src/browser/helpers/tolerantWebAccess.d.ts.map +1 -0
- package/dist/src/browser/workers/FileDownloader.d.ts.map +1 -1
- package/dist/src/browser/workers/ImageResizer.d.ts.map +1 -1
- package/dist/src/browser/workers/filesDownload.d.ts.map +1 -1
- package/dist/src/browser/workers/imageResize.d.ts.map +1 -1
- package/dist/src/client/ClientManager.d.ts.map +1 -1
- package/dist/src/client/actors/addModelsToDb.d.ts +14 -0
- package/dist/src/client/actors/addModelsToDb.d.ts.map +1 -1
- package/dist/src/client/actors/platformClassesInit.d.ts.map +1 -1
- package/dist/src/client/actors/processSchemaFiles.d.ts.map +1 -1
- package/dist/src/client/actors/saveConfig.d.ts +11 -0
- package/dist/src/client/actors/saveConfig.d.ts.map +1 -1
- package/dist/src/client/constants.d.ts +0 -8
- package/dist/src/client/constants.d.ts.map +1 -1
- package/dist/src/db/backfillMetadataPropertyIds.d.ts.map +1 -1
- package/dist/src/db/configs/{dev.schema.config.d.ts → migrations.config.d.ts} +1 -1
- package/dist/src/db/configs/migrations.config.d.ts.map +1 -0
- package/dist/src/db/read/batchLatestPublishedVersionBySeedLocalIds.d.ts +1 -1
- package/dist/src/db/read/batchLatestPublishedVersionBySeedLocalIds.d.ts.map +1 -1
- package/dist/src/db/read/getItemData.d.ts.map +1 -1
- package/dist/src/db/read/getItemProperties.d.ts.map +1 -1
- package/dist/src/db/read/getItems.d.ts +7 -2
- package/dist/src/db/read/getItems.d.ts.map +1 -1
- package/dist/src/db/read/getLatestPublishedVersionRow.d.ts +2 -1
- package/dist/src/db/read/getLatestPublishedVersionRow.d.ts.map +1 -1
- package/dist/src/db/read/getLatestVersionRow.d.ts +13 -0
- package/dist/src/db/read/getLatestVersionRow.d.ts.map +1 -0
- package/dist/src/db/read/getModelSchemas.d.ts.map +1 -1
- package/dist/src/db/read/getPropertyData.d.ts.map +1 -1
- package/dist/src/db/read/getPublishPayload.d.ts +18 -11
- package/dist/src/db/read/getPublishPayload.d.ts.map +1 -1
- package/dist/src/db/read/getPublishPendingDiff.d.ts +2 -1
- package/dist/src/db/read/getPublishPendingDiff.d.ts.map +1 -1
- package/dist/src/db/read/getPublishUploads.d.ts +5 -0
- package/dist/src/db/read/getPublishUploads.d.ts.map +1 -1
- package/dist/src/db/read/getSchemaUidForModel.d.ts.map +1 -1
- package/dist/src/db/read/getSeedPublishState.d.ts +8 -2
- package/dist/src/db/read/getSeedPublishState.d.ts.map +1 -1
- package/dist/src/db/read/isSeedRevoked.d.ts +7 -0
- package/dist/src/db/read/isSeedRevoked.d.ts.map +1 -0
- package/dist/src/db/read/publishDraftGraph.d.ts +57 -0
- package/dist/src/db/read/publishDraftGraph.d.ts.map +1 -0
- package/dist/src/db/read/publishErrors.d.ts +37 -0
- package/dist/src/db/read/publishErrors.d.ts.map +1 -0
- package/dist/src/db/read/resolveModelForSyncedSeed.d.ts +39 -0
- package/dist/src/db/read/resolveModelForSyncedSeed.d.ts.map +1 -0
- package/dist/src/db/read/resolveModelRecord.d.ts +69 -0
- package/dist/src/db/read/resolveModelRecord.d.ts.map +1 -0
- package/dist/src/db/read/resolveRelatedSeedRef.d.ts +34 -0
- package/dist/src/db/read/resolveRelatedSeedRef.d.ts.map +1 -0
- package/dist/src/db/read/subqueries/liveVersion.d.ts +12 -0
- package/dist/src/db/read/subqueries/liveVersion.d.ts.map +1 -0
- package/dist/src/db/read/subqueries/metadataLatest.d.ts +4 -0
- package/dist/src/db/read/subqueries/metadataLatest.d.ts.map +1 -1
- package/dist/src/db/read/subqueries/versionData.d.ts +7 -2
- package/dist/src/db/read/subqueries/versionData.d.ts.map +1 -1
- package/dist/src/db/read/summarizePublishWork.d.ts +10 -2
- package/dist/src/db/read/summarizePublishWork.d.ts.map +1 -1
- package/dist/src/db/resetAmbiguousLegacyItemData.d.ts +17 -0
- package/dist/src/db/resetAmbiguousLegacyItemData.d.ts.map +1 -0
- package/dist/src/db/sqlParamBatches.d.ts +27 -0
- package/dist/src/db/sqlParamBatches.d.ts.map +1 -0
- package/dist/src/db/write/addExcludedTransactions.d.ts +7 -0
- package/dist/src/db/write/addExcludedTransactions.d.ts.map +1 -0
- package/dist/src/db/write/applyPropertyAttestationUidsFromPublish.d.ts +6 -0
- package/dist/src/db/write/applyPropertyAttestationUidsFromPublish.d.ts.map +1 -1
- package/dist/src/db/write/createMetadata.d.ts +2 -0
- package/dist/src/db/write/createMetadata.d.ts.map +1 -1
- package/dist/src/db/write/createNewItem.d.ts +3 -1
- package/dist/src/db/write/createNewItem.d.ts.map +1 -1
- package/dist/src/db/write/createSeed.d.ts +2 -1
- package/dist/src/db/write/createSeed.d.ts.map +1 -1
- package/dist/src/db/write/createSeeds.d.ts +1 -1
- package/dist/src/db/write/createSeeds.d.ts.map +1 -1
- package/dist/src/db/write/linkModelToSchema.d.ts +12 -0
- package/dist/src/db/write/linkModelToSchema.d.ts.map +1 -0
- package/dist/src/db/write/updateItemPropertyValue.d.ts.map +1 -1
- package/dist/src/db/write/updateMetadata.d.ts.map +1 -1
- package/dist/src/db/write/updateSeedRevokedAt.d.ts +11 -1
- package/dist/src/db/write/updateSeedRevokedAt.d.ts.map +1 -1
- package/dist/src/db/write/updateSeedUid.d.ts.map +1 -1
- package/dist/src/db/write/updateVersionUid.d.ts +2 -1
- package/dist/src/db/write/updateVersionUid.d.ts.map +1 -1
- package/dist/src/events/files/download.d.ts.map +1 -1
- package/dist/src/events/item/easSyncManager.d.ts +2 -0
- package/dist/src/events/item/easSyncManager.d.ts.map +1 -1
- package/dist/src/events/item/index.d.ts.map +1 -1
- package/dist/src/events/item/syncDbWithEas.d.ts +16 -0
- package/dist/src/events/item/syncDbWithEas.d.ts.map +1 -1
- package/dist/src/helpers/FileManager/BaseFileManager.d.ts +1 -0
- package/dist/src/helpers/FileManager/BaseFileManager.d.ts.map +1 -1
- package/dist/src/helpers/FileManager/IFileManager.d.ts +5 -0
- package/dist/src/helpers/FileManager/IFileManager.d.ts.map +1 -1
- package/dist/src/helpers/FileManager/errors.d.ts +10 -0
- package/dist/src/helpers/FileManager/errors.d.ts.map +1 -0
- package/dist/src/helpers/compareMetadataRowsLatestFirst.d.ts +21 -3
- package/dist/src/helpers/compareMetadataRowsLatestFirst.d.ts.map +1 -1
- package/dist/src/helpers/constants.d.ts +9 -0
- package/dist/src/helpers/constants.d.ts.map +1 -1
- package/dist/src/helpers/crypto.d.ts +5 -0
- package/dist/src/helpers/crypto.d.ts.map +1 -1
- package/dist/src/helpers/db.d.ts +25 -5
- package/dist/src/helpers/db.d.ts.map +1 -1
- package/dist/src/helpers/easPropertyCanonical.d.ts +1 -1
- package/dist/src/helpers/easPropertyCanonical.d.ts.map +1 -1
- package/dist/src/helpers/entity/entityCommon.d.ts +10 -0
- package/dist/src/helpers/entity/entityCommon.d.ts.map +1 -1
- package/dist/src/helpers/entity/entityDestroy.d.ts +1 -1
- package/dist/src/helpers/entity/entityDestroy.d.ts.map +1 -1
- package/dist/src/helpers/entity/entityLiveQuery.d.ts +5 -0
- package/dist/src/helpers/entity/entityLiveQuery.d.ts.map +1 -1
- package/dist/src/helpers/entity/evictionEpoch.d.ts +18 -0
- package/dist/src/helpers/entity/evictionEpoch.d.ts.map +1 -0
- package/dist/src/helpers/file/fetchAll/actors.d.ts.map +1 -1
- package/dist/src/helpers/getSegmentedItemProperties.d.ts.map +1 -1
- package/dist/src/helpers/htmlEmbeddedDataUriPublish.d.ts +31 -3
- package/dist/src/helpers/htmlEmbeddedDataUriPublish.d.ts.map +1 -1
- package/dist/src/helpers/isPublishedMetadataRow.d.ts +10 -0
- package/dist/src/helpers/isPublishedMetadataRow.d.ts.map +1 -0
- package/dist/src/helpers/ownership.d.ts.map +1 -1
- package/dist/src/helpers/property.d.ts +6 -1
- package/dist/src/helpers/property.d.ts.map +1 -1
- package/dist/src/helpers/schema.d.ts +14 -4
- package/dist/src/helpers/schema.d.ts.map +1 -1
- package/dist/src/helpers/tabCoordinator.d.ts +45 -0
- package/dist/src/helpers/tabCoordinator.d.ts.map +1 -0
- package/dist/src/helpers/tabEvents.d.ts +27 -0
- package/dist/src/helpers/tabEvents.d.ts.map +1 -0
- package/dist/src/helpers/tabLocks.d.ts +28 -0
- package/dist/src/helpers/tabLocks.d.ts.map +1 -0
- package/dist/src/helpers/updateSchema.d.ts.map +1 -1
- package/dist/src/imports/json.d.ts.map +1 -1
- package/dist/src/imports/markdown.d.ts.map +1 -1
- package/dist/src/index.d.ts +13 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/node/db/Db.d.ts.map +1 -1
- package/dist/src/node/helpers/FileManager.d.ts +2 -0
- package/dist/src/node/helpers/FileManager.d.ts.map +1 -1
- package/dist/src/query/createLocalQueryDataSource.d.ts +4 -0
- package/dist/src/query/createLocalQueryDataSource.d.ts.map +1 -1
- package/dist/src/seedSchema/MetadataSchema.d.ts +36 -0
- package/dist/src/seedSchema/MetadataSchema.d.ts.map +1 -1
- package/dist/src/seedSchema/ModelSchema.d.ts +57 -0
- package/dist/src/seedSchema/ModelSchema.d.ts.map +1 -1
- package/dist/src/seedSchema/SeedSchema.d.ts +19 -0
- package/dist/src/seedSchema/SeedSchema.d.ts.map +1 -1
- package/dist/src/seedSchema/VersionSchema.d.ts +17 -0
- package/dist/src/seedSchema/VersionSchema.d.ts.map +1 -1
- package/dist/src/services/write/actors/validateEntity.d.ts.map +1 -1
- package/dist/src/services/write/actors/writeToDatabase.d.ts +5 -0
- package/dist/src/services/write/actors/writeToDatabase.d.ts.map +1 -1
- package/dist/src/services/write/writeProcessMachine.d.ts.map +1 -1
- package/dist/src/stores/eas.d.ts +1 -1
- package/dist/src/stores/eas.d.ts.map +1 -1
- package/dist/src/types/index.d.ts +7 -0
- package/dist/src/types/index.d.ts.map +1 -1
- package/dist/src/types/item.d.ts +19 -11
- package/dist/src/types/item.d.ts.map +1 -1
- package/dist/src/types/property.d.ts +3 -2
- package/dist/src/types/property.d.ts.map +1 -1
- package/dist/syncDbWithEas-BPap9Sru.js +855 -0
- package/dist/syncDbWithEas-BPap9Sru.js.map +1 -0
- package/dist/{index-280bL-n4.js → tabEvents-C6NXS6Jl.js} +231 -68
- package/dist/tabEvents-C6NXS6Jl.js.map +1 -0
- package/dist/tolerantWebAccess-NBQ1NB4i.js +160 -0
- package/dist/tolerantWebAccess-NBQ1NB4i.js.map +1 -0
- package/dist/updateSeedRevokedAt-CYwgVNlM.js +32 -0
- package/dist/updateSeedRevokedAt-CYwgVNlM.js.map +1 -0
- package/package.json +8 -10
- package/dist/BasePathResolver-B6CKqoKw.js.map +0 -1
- package/dist/ClientManager-ChcmUL47.js.map +0 -1
- package/dist/ModelProperty-D79uV42p.js.map +0 -1
- package/dist/Schema-a8uO-hIZ.js.map +0 -1
- package/dist/SchemaValidationService-Y49vqast.js.map +0 -1
- package/dist/backfillMetadataPropertyIds-CBsf7LnU.js.map +0 -1
- package/dist/cjs/ModelProperty-D9FGaGuE.js.map +0 -1
- package/dist/cjs/Schema-BiJIPLEL.js.map +0 -1
- package/dist/cjs/SchemaValidationService-DtYs_CNY.js.map +0 -1
- package/dist/cjs/backfillMetadataPropertyIds-2XaN3b9S.js.map +0 -1
- package/dist/cjs/getPublishPayload-D5DhLGvN.js.map +0 -1
- package/dist/cjs/getPublishUploads-DMhCCKYF.js.map +0 -1
- package/dist/cjs/getSegmentedItemProperties-CU8rtBAo.js +0 -148
- package/dist/cjs/getSegmentedItemProperties-CU8rtBAo.js.map +0 -1
- package/dist/cjs/index-CSNtEnbF.js.map +0 -1
- package/dist/cjs/index-DPp9rdRL.js.map +0 -1
- package/dist/cjs/property-DlKiAWt4.js.map +0 -1
- package/dist/cjs/syncDbWithEas-C6n34o_Q.js +0 -606
- package/dist/cjs/syncDbWithEas-C6n34o_Q.js.map +0 -1
- package/dist/db-WbrzEf7c.js.map +0 -1
- package/dist/eas-CfYCu4IX.js.map +0 -1
- package/dist/getPublishPayload-BIrTVUxb.js.map +0 -1
- package/dist/getPublishUploads-C6cDeZdz.js.map +0 -1
- package/dist/getSegmentedItemProperties-BmKE71vU.js +0 -148
- package/dist/getSegmentedItemProperties-BmKE71vU.js.map +0 -1
- package/dist/index-280bL-n4.js.map +0 -1
- package/dist/index-ClSv5pTA.js.map +0 -1
- package/dist/index-Djd3667v.js.map +0 -1
- package/dist/index-HRHkbVQd.js.map +0 -1
- package/dist/index.node-DBtQkEfz.js.map +0 -1
- package/dist/property-CQjuZ4JW.js.map +0 -1
- package/dist/src/Item/service/actors/fetchDataFromEas.d.ts +0 -4
- package/dist/src/Item/service/actors/fetchDataFromEas.d.ts.map +0 -1
- package/dist/src/Item/service/actors/hydrateExistingItem.d.ts +0 -4
- package/dist/src/Item/service/actors/hydrateExistingItem.d.ts.map +0 -1
- package/dist/src/Item/service/actors/hydrateNewItem.d.ts +0 -4
- package/dist/src/Item/service/actors/hydrateNewItem.d.ts.map +0 -1
- package/dist/src/Item/service/actors/initialize.d.ts +0 -4
- package/dist/src/Item/service/actors/initialize.d.ts.map +0 -1
- package/dist/src/Item/service/actors/reload.d.ts +0 -5
- package/dist/src/Item/service/actors/reload.d.ts.map +0 -1
- package/dist/src/Item/service/actors/saveDataToDb.d.ts +0 -4
- package/dist/src/Item/service/actors/saveDataToDb.d.ts.map +0 -1
- package/dist/src/ItemProperty/service/actors/resolveRemoteStorage.d.ts +0 -5
- package/dist/src/ItemProperty/service/actors/resolveRemoteStorage.d.ts.map +0 -1
- package/dist/src/Schema/service/addModelsMachine.d.ts +0 -123
- package/dist/src/Schema/service/addModelsMachine.d.ts.map +0 -1
- package/dist/src/browser/helpers/index.d.ts +0 -4
- package/dist/src/browser/helpers/index.d.ts.map +0 -1
- package/dist/src/db/configs/dev.schema.config.d.ts.map +0 -1
- package/dist/src/helpers/file/download/actors.d.ts +0 -17
- package/dist/src/helpers/file/download/actors.d.ts.map +0 -1
- package/dist/src/helpers/file/download/index.d.ts +0 -70
- package/dist/src/helpers/file/download/index.d.ts.map +0 -1
- package/dist/src/services/publish/actors/createPublishAttempt.d.ts +0 -4
- package/dist/src/services/publish/actors/createPublishAttempt.d.ts.map +0 -1
- package/dist/src/services/publish/actors/preparePublishRequestData.d.ts +0 -4
- package/dist/src/services/publish/actors/preparePublishRequestData.d.ts.map +0 -1
- package/dist/src/services/publish/actors/upload.d.ts +0 -4
- package/dist/src/services/publish/actors/upload.d.ts.map +0 -1
- package/dist/src/services/publish/actors/validateItemData.d.ts +0 -4
- package/dist/src/services/publish/actors/validateItemData.d.ts.map +0 -1
- package/dist/src/services/publish/publishMachine.d.ts +0 -32
- package/dist/src/services/publish/publishMachine.d.ts.map +0 -1
- package/dist/syncDbWithEas-CuARXfyN.js +0 -598
- package/dist/syncDbWithEas-CuARXfyN.js.map +0 -1
- package/dist/updateSeedRevokedAt-CBcLfHWs.js +0 -22
- package/dist/updateSeedRevokedAt-CBcLfHWs.js.map +0 -1
|
@@ -1,15 +1,32 @@
|
|
|
1
1
|
import { fromCallback, fromPromise, setup, assign, createActor } from 'xstate';
|
|
2
|
-
import {
|
|
3
|
-
import { eq, or } from 'drizzle-orm';
|
|
4
|
-
import './
|
|
2
|
+
import { B as BaseDb, j as models, p as properties, K as isInternalSchema, g as modelSchemas, s as schemas } from './BasePathResolver-DRT09oVv.js';
|
|
3
|
+
import { eq, and, isNull, or } from 'drizzle-orm';
|
|
4
|
+
import './tabEvents-C6NXS6Jl.js';
|
|
5
5
|
import debug from 'debug';
|
|
6
6
|
import { generateId } from './generateId-BopUwD8F.js';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
7
|
+
import { G as writeModelToDb, K as writePropertyToDb, O as addSchemaToDb, A as AmbiguousModelError, Q as renameModelInDb, d as TProperty } from './db-Lw0KVZmc.js';
|
|
8
|
+
import { j as waitForEntityIdle, T as getInvariantSafePropertyDescriptor, m as findEntity, C as ClientManagerState, I as Item, U as clearDestroySubscriptions, n as forceRemoveFromCaches, V as unloadEntity, o as runDestroyLifecycle } from './Item-ZUAmf943.js';
|
|
9
|
+
import { h as getClient } from './ClientManager-DngaZdw6.js';
|
|
9
10
|
import { modelPropertiesToObject } from './model-DGMe-TTm.js';
|
|
10
11
|
import { toSnakeCase } from 'drizzle-orm/casing';
|
|
11
12
|
import { Type } from '@sinclair/typebox';
|
|
12
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Common getters and utilities for entity classes
|
|
16
|
+
* These work with any entity that has a getService() method returning an XState actor
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Get the current state value from an entity's service
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Whether an actor has been stopped (unload, destroy, or Schema eviction). Async work started by an
|
|
23
|
+
* entity (DB lookups, retry timers) must check this before sending, since a stopped actor ignores
|
|
24
|
+
* events and XState warns about every one of them.
|
|
25
|
+
*/
|
|
26
|
+
function isActorStopped(actor) {
|
|
27
|
+
return actor.getSnapshot().status === 'stopped';
|
|
28
|
+
}
|
|
29
|
+
|
|
13
30
|
const logger$7 = debug('seedSdk:model:actors:loadOrCreateModel');
|
|
14
31
|
/**
|
|
15
32
|
* Create ModelProperty instances for all property IDs to ensure they're cached
|
|
@@ -21,7 +38,7 @@ const createPropertyInstances = async (propertyFileIds) => {
|
|
|
21
38
|
return;
|
|
22
39
|
}
|
|
23
40
|
try {
|
|
24
|
-
const mod = await import('./ModelProperty-
|
|
41
|
+
const mod = await import('./ModelProperty-6llK4MTH.js');
|
|
25
42
|
const ModelProperty = mod?.ModelProperty ?? mod?.default;
|
|
26
43
|
if (!ModelProperty) {
|
|
27
44
|
logger$7('createPropertyInstances: ModelProperty not available from dynamic import');
|
|
@@ -52,7 +69,7 @@ const createPropertyInstances = async (propertyFileIds) => {
|
|
|
52
69
|
// Don't throw - this is best-effort to pre-populate cache
|
|
53
70
|
}
|
|
54
71
|
};
|
|
55
|
-
const loadOrCreateModel = fromCallback(({ sendBack, input: { context } }) => {
|
|
72
|
+
const loadOrCreateModel = fromCallback(({ sendBack, input: { context }, self }) => {
|
|
56
73
|
const _loadOrCreateModel = async () => {
|
|
57
74
|
const { modelName, schemaName, id, _idFromSchema } = context; // id is now the schemaFileId (string)
|
|
58
75
|
if (!modelName || !schemaName) {
|
|
@@ -85,11 +102,40 @@ const loadOrCreateModel = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
85
102
|
// But if we have a schemaFileId and the model found by name has a different schemaFileId,
|
|
86
103
|
// don't use it - we're creating a new model from a schema file with a specific ID
|
|
87
104
|
if (!modelRecord) {
|
|
88
|
-
|
|
89
|
-
|
|
105
|
+
// Model names are only unique per schema: prefer this schema's row, and otherwise only
|
|
106
|
+
// consider same-name rows that no schema claims yet (never another schema's model).
|
|
107
|
+
const _mod_0 = await import('./BasePathResolver-DRT09oVv.js');
|
|
108
|
+
const _ns_0 = _mod_0.R;
|
|
109
|
+
const { modelSchemas } = _ns_0;
|
|
110
|
+
const _mod_1 = await import('./BasePathResolver-DRT09oVv.js');
|
|
111
|
+
const _ns_1 = _mod_1.Q;
|
|
112
|
+
const { schemas: schemasTable } = _ns_1;
|
|
113
|
+
let dbModels = await db
|
|
114
|
+
.select({
|
|
115
|
+
id: models.id,
|
|
116
|
+
name: models.name,
|
|
117
|
+
schemaFileId: models.schemaFileId,
|
|
118
|
+
isEdited: models.isEdited,
|
|
119
|
+
})
|
|
90
120
|
.from(models)
|
|
91
|
-
.
|
|
121
|
+
.innerJoin(modelSchemas, eq(models.id, modelSchemas.modelId))
|
|
122
|
+
.innerJoin(schemasTable, eq(modelSchemas.schemaId, schemasTable.id))
|
|
123
|
+
.where(and(eq(models.name, modelName), eq(schemasTable.name, schemaName)))
|
|
92
124
|
.limit(1);
|
|
125
|
+
if (dbModels.length === 0) {
|
|
126
|
+
dbModels = await db
|
|
127
|
+
.select({
|
|
128
|
+
id: models.id,
|
|
129
|
+
name: models.name,
|
|
130
|
+
schemaFileId: models.schemaFileId,
|
|
131
|
+
isEdited: models.isEdited,
|
|
132
|
+
})
|
|
133
|
+
.from(models)
|
|
134
|
+
.leftJoin(modelSchemas, eq(models.id, modelSchemas.modelId))
|
|
135
|
+
// Stubs only: an unlinked row with a schemaFileId is a deleted schema's leftover, not ours
|
|
136
|
+
.where(and(eq(models.name, modelName), isNull(modelSchemas.id), isNull(models.schemaFileId)))
|
|
137
|
+
.limit(1);
|
|
138
|
+
}
|
|
93
139
|
if (dbModels.length > 0) {
|
|
94
140
|
const foundModel = dbModels[0];
|
|
95
141
|
const dbSchemaFileId = foundModel.schemaFileId;
|
|
@@ -98,7 +144,9 @@ const loadOrCreateModel = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
98
144
|
// This handles the case where Model.create was called with a generated ID, but the model
|
|
99
145
|
// already exists in the database with a different ID. By updating the current instance's
|
|
100
146
|
// schemaFileId to match the database, both will point to the same cached instance.
|
|
101
|
-
|
|
147
|
+
// Skip for schema models (_idFromSchema): their id is authoritative, and a same-name row
|
|
148
|
+
// with a different id belongs to another schema (e.g. two schemas that each define "Post").
|
|
149
|
+
if (dbSchemaFileId && !(_idFromSchema && schemaFileId && schemaFileId !== dbSchemaFileId)) {
|
|
102
150
|
try {
|
|
103
151
|
const modelMod = await Promise.resolve().then(function () { return Model$1; });
|
|
104
152
|
const { Model } = modelMod;
|
|
@@ -164,7 +212,9 @@ const loadOrCreateModel = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
164
212
|
.map((record) => record.schemaFileId)
|
|
165
213
|
.filter((id) => id !== null && id !== undefined);
|
|
166
214
|
if (propertyFileIds.length > 0) {
|
|
167
|
-
|
|
215
|
+
// Not for a model stopped meanwhile (unloaded, or evicted with its schema)
|
|
216
|
+
if (!isActorStopped(self))
|
|
217
|
+
await createPropertyInstances(propertyFileIds);
|
|
168
218
|
}
|
|
169
219
|
// Generate schemaFileId if not set
|
|
170
220
|
if (!schemaFileId) {
|
|
@@ -205,10 +255,13 @@ const loadOrCreateModel = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
205
255
|
// Step 2: Fallback to Schema context (only if database doesn't have the model)
|
|
206
256
|
// This handles the case where model exists in schema file but not yet in database
|
|
207
257
|
try {
|
|
208
|
-
const
|
|
209
|
-
const
|
|
210
|
-
const schemaMod =
|
|
258
|
+
const _mod_2 = await import('./Schema-D-Ud-XYw.js');
|
|
259
|
+
const _ns_2 = _mod_2.b;
|
|
260
|
+
const schemaMod = _ns_2;
|
|
211
261
|
const { Schema } = schemaMod;
|
|
262
|
+
// Stopped meanwhile (unloaded, or evicted with its schema): don't load the schema again
|
|
263
|
+
if (isActorStopped(self))
|
|
264
|
+
return;
|
|
212
265
|
const schema = Schema.create(schemaName, { waitForReady: false });
|
|
213
266
|
const schemaSnapshot = schema.getService().getSnapshot();
|
|
214
267
|
// Wait for schema to load if it's still loading
|
|
@@ -353,13 +406,13 @@ const loadOrCreateModel = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
353
406
|
}
|
|
354
407
|
// Also check database for models (in case they're persisted but not in Schema context)
|
|
355
408
|
if (db) {
|
|
356
|
-
const
|
|
357
|
-
const
|
|
358
|
-
const modelSchemaSchemaMod =
|
|
409
|
+
const _mod_3 = await import('./BasePathResolver-DRT09oVv.js');
|
|
410
|
+
const _ns_3 = _mod_3.R;
|
|
411
|
+
const modelSchemaSchemaMod = _ns_3;
|
|
359
412
|
const { modelSchemas } = modelSchemaSchemaMod;
|
|
360
|
-
const
|
|
361
|
-
const
|
|
362
|
-
const schemaSchemaMod =
|
|
413
|
+
const _mod_4 = await import('./BasePathResolver-DRT09oVv.js');
|
|
414
|
+
const _ns_4 = _mod_4.Q;
|
|
415
|
+
const schemaSchemaMod = _ns_4;
|
|
363
416
|
const { schemas: schemasTable } = schemaSchemaMod;
|
|
364
417
|
// Query all models for this schema to check for duplicates (case-insensitive)
|
|
365
418
|
logger$7(`Checking database for duplicate model names in schema "${schemaName}"`);
|
|
@@ -453,12 +506,14 @@ const loadOrCreateModel = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
453
506
|
}
|
|
454
507
|
// Mark schema as draft when a new model is created so saveNewVersion() can persist it
|
|
455
508
|
try {
|
|
456
|
-
const
|
|
457
|
-
const
|
|
458
|
-
const schemaMod =
|
|
509
|
+
const _mod_5 = await import('./Schema-D-Ud-XYw.js');
|
|
510
|
+
const _ns_5 = _mod_5.b;
|
|
511
|
+
const schemaMod = _ns_5;
|
|
459
512
|
const { Schema } = schemaMod;
|
|
460
|
-
|
|
461
|
-
|
|
513
|
+
if (!isActorStopped(self)) {
|
|
514
|
+
const schema = Schema.create(schemaName, { waitForReady: false });
|
|
515
|
+
schema.getService().send({ type: 'markAsDraft', propertyKey: 'schema:models' });
|
|
516
|
+
}
|
|
462
517
|
}
|
|
463
518
|
catch (err) {
|
|
464
519
|
logger$7(`Failed to mark schema as draft after creating model: ${err}`);
|
|
@@ -479,7 +534,7 @@ const loadOrCreateModel = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
479
534
|
const logger$6 = debug('seedSdk:model:actors:validateModel');
|
|
480
535
|
// Validation timeout in milliseconds (10 seconds)
|
|
481
536
|
const VALIDATION_TIMEOUT_MS = 10000;
|
|
482
|
-
const validateModel = fromCallback(({ sendBack, input: { context } }) => {
|
|
537
|
+
const validateModel = fromCallback(({ sendBack, input: { context }, self }) => {
|
|
483
538
|
let hasResponded = false;
|
|
484
539
|
// Timeout handler to ensure we always respond
|
|
485
540
|
const timeoutId = setTimeout(() => {
|
|
@@ -499,12 +554,12 @@ const validateModel = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
499
554
|
const _validateModel = async () => {
|
|
500
555
|
try {
|
|
501
556
|
// Use dynamic imports to break circular dependencies
|
|
502
|
-
const validationServiceMod = await import('./SchemaValidationService-
|
|
557
|
+
const validationServiceMod = await import('./SchemaValidationService-IoS7JquP.js');
|
|
503
558
|
const { SchemaValidationService } = validationServiceMod;
|
|
504
559
|
const validationService = new SchemaValidationService();
|
|
505
|
-
const
|
|
506
|
-
const
|
|
507
|
-
const schemaMod =
|
|
560
|
+
const _mod_6 = await import('./Schema-D-Ud-XYw.js');
|
|
561
|
+
const _ns_6 = _mod_6.b;
|
|
562
|
+
const schemaMod = _ns_6;
|
|
508
563
|
const { Schema } = schemaMod;
|
|
509
564
|
// Validate model structure
|
|
510
565
|
const structureResult = validationService.validateModelStructure(context);
|
|
@@ -519,6 +574,9 @@ const validateModel = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
519
574
|
// If we have schema name, validate against schema
|
|
520
575
|
// CRITICAL: Use validateModelAgainstSchema which doesn't require the model to be in schema context
|
|
521
576
|
// This allows validation BEFORE registration, preventing update loops
|
|
577
|
+
// Stopped meanwhile (unloaded, or evicted with its schema): don't load the schema again
|
|
578
|
+
if (isActorStopped(self))
|
|
579
|
+
return;
|
|
522
580
|
if (context.schemaName) {
|
|
523
581
|
try {
|
|
524
582
|
const schema = Schema.create(context.schemaName, {
|
|
@@ -601,10 +659,14 @@ const validateModel = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
601
659
|
});
|
|
602
660
|
|
|
603
661
|
const logger$5 = debug('seedSdk:model:actors:createModelProperties');
|
|
604
|
-
const createModelProperties = fromCallback(({ sendBack, input }) => {
|
|
662
|
+
const createModelProperties = fromCallback(({ sendBack, input, self }) => {
|
|
663
|
+
// The model was stopped (unloaded, or evicted with its schema by Schema.destroy / test cleanup) while
|
|
664
|
+
// this ran: stopping it stops this actor too, but can't cancel the awaits below. A stopped model
|
|
665
|
+
// creates no properties (they'd be cached for a model that's gone, and write rows under it).
|
|
666
|
+
const stopped = () => isActorStopped(self);
|
|
605
667
|
const _createProperties = async () => {
|
|
606
668
|
const { context, propertyDefinitions } = input;
|
|
607
|
-
const { id, _dbId, modelName } = context;
|
|
669
|
+
const { id, _dbId, modelName, schemaName } = context;
|
|
608
670
|
if (!id || !_dbId || !modelName) {
|
|
609
671
|
throw new Error('Model ID, file ID, and name are required to create properties');
|
|
610
672
|
}
|
|
@@ -614,7 +676,7 @@ const createModelProperties = fromCallback(({ sendBack, input }) => {
|
|
|
614
676
|
return;
|
|
615
677
|
}
|
|
616
678
|
logger$5(`Creating ${Object.keys(propertyDefinitions).length} properties for model "${modelName}" (id: ${_dbId})`);
|
|
617
|
-
const mod = await import('./ModelProperty-
|
|
679
|
+
const mod = await import('./ModelProperty-6llK4MTH.js');
|
|
618
680
|
const ModelProperty = mod?.ModelProperty ?? mod?.default;
|
|
619
681
|
if (!ModelProperty) {
|
|
620
682
|
logger$5('ModelProperty not available from dynamic import');
|
|
@@ -622,13 +684,25 @@ const createModelProperties = fromCallback(({ sendBack, input }) => {
|
|
|
622
684
|
return;
|
|
623
685
|
}
|
|
624
686
|
const drizzleMod = await import('drizzle-orm');
|
|
625
|
-
const { eq } = drizzleMod;
|
|
687
|
+
const { and, eq } = drizzleMod;
|
|
626
688
|
const db = BaseDb.getAppDb();
|
|
627
689
|
for (const [propName, propData] of Object.entries(propertyDefinitions)) {
|
|
628
|
-
//
|
|
690
|
+
// The model's own write (writeModelToDb) normally stored this property already, under
|
|
691
|
+
// propData.id or an id it generated. Reuse that row so the instance gets the same id
|
|
692
|
+
// and doesn't write the property a second time.
|
|
693
|
+
const propertyRecord = db
|
|
694
|
+
? (await db
|
|
695
|
+
.select()
|
|
696
|
+
.from(properties)
|
|
697
|
+
.where(propData.id
|
|
698
|
+
? eq(properties.schemaFileId, propData.id)
|
|
699
|
+
: and(eq(properties.modelId, _dbId), eq(properties.name, propName)))
|
|
700
|
+
.limit(1))[0]
|
|
701
|
+
: undefined;
|
|
702
|
+
// Otherwise use provided ID or generate a random one
|
|
629
703
|
// IDs should be generated in the import process before creating properties
|
|
630
704
|
const { generateId } = await import('./generateId-BopUwD8F.js');
|
|
631
|
-
const propertyFileId = propData.id || generateId();
|
|
705
|
+
const propertyFileId = propData.id || propertyRecord?.schemaFileId || generateId();
|
|
632
706
|
logger$5(`Creating property "${propName}" with fileId "${propertyFileId}"`);
|
|
633
707
|
// Query database to get refModelId if the property has ref/refModelName
|
|
634
708
|
// The property should already be in DB from addModelsToDb
|
|
@@ -637,24 +711,18 @@ const createModelProperties = fromCallback(({ sendBack, input }) => {
|
|
|
637
711
|
try {
|
|
638
712
|
const refModelName = propData.refModelName || propData.ref;
|
|
639
713
|
// First try to get refModelId from the property record in the database
|
|
640
|
-
|
|
641
|
-
.
|
|
642
|
-
.from(properties)
|
|
643
|
-
.where(eq(properties.schemaFileId, propertyFileId))
|
|
644
|
-
.limit(1);
|
|
645
|
-
if (propertyRecords.length > 0 && propertyRecords[0].refModelId) {
|
|
646
|
-
refModelId = propertyRecords[0].refModelId;
|
|
714
|
+
if (propertyRecord?.refModelId) {
|
|
715
|
+
refModelId = propertyRecord.refModelId;
|
|
647
716
|
logger$5(`Found refModelId ${refModelId} from database for property "${propName}"`);
|
|
648
717
|
}
|
|
649
718
|
else if (refModelName) {
|
|
650
|
-
// Fallback:
|
|
651
|
-
const
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
refModelId = refModelRecords[0].id;
|
|
719
|
+
// Fallback: resolve the ref by name within this model's schema
|
|
720
|
+
const _mod_7 = await import('./db-Lw0KVZmc.js');
|
|
721
|
+
const _ns_7 = _mod_7.Y;
|
|
722
|
+
const { resolveModelRecord } = _ns_7;
|
|
723
|
+
const refModelRecord = await resolveModelRecord(refModelName, { schemaName }, db);
|
|
724
|
+
if (refModelRecord?.id) {
|
|
725
|
+
refModelId = refModelRecord.id;
|
|
658
726
|
logger$5(`Resolved refModelId ${refModelId} from model name "${refModelName}" for property "${propName}"`);
|
|
659
727
|
}
|
|
660
728
|
}
|
|
@@ -664,6 +732,10 @@ const createModelProperties = fromCallback(({ sendBack, input }) => {
|
|
|
664
732
|
// Continue without refModelId - it will be resolved later in _initializeOriginalValues
|
|
665
733
|
}
|
|
666
734
|
}
|
|
735
|
+
if (stopped()) {
|
|
736
|
+
logger$5(`Model "${modelName}" was stopped while creating its properties; not creating the rest`);
|
|
737
|
+
return;
|
|
738
|
+
}
|
|
667
739
|
// Create ModelProperty instance
|
|
668
740
|
// This will load from DB if it exists, or create new instance
|
|
669
741
|
// The property should already be in DB from writeModelToDb
|
|
@@ -678,12 +750,14 @@ const createModelProperties = fromCallback(({ sendBack, input }) => {
|
|
|
678
750
|
refModelName: propData.refModelName,
|
|
679
751
|
refModelId,
|
|
680
752
|
refValueType: propData.refValueType,
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
753
|
+
// Definitions built from DB rows may lack storage settings; the row has them.
|
|
754
|
+
storageType: propData.storageType ?? propertyRecord?.storageType ?? undefined,
|
|
755
|
+
localStorageDir: propData.localStorageDir ?? propertyRecord?.localStorageDir ?? undefined,
|
|
756
|
+
filenameSuffix: propData.filenameSuffix ?? propertyRecord?.filenameSuffix ?? undefined,
|
|
684
757
|
required: propData.required,
|
|
685
758
|
_propertyFileId: propertyFileId, // Store schemaFileId for getById() lookups
|
|
686
|
-
|
|
759
|
+
_dbId: propertyRecord?.schemaFileId === propertyFileId ? propertyRecord.id : undefined, // Already persisted: skip the write
|
|
760
|
+
}, { schemaName }); // Use 'as any' because _propertyFileId is not in TProperty type
|
|
687
761
|
}
|
|
688
762
|
logger$5(`Successfully created all properties for model "${modelName}"`);
|
|
689
763
|
sendBack({ type: 'createModelPropertiesSuccess' });
|
|
@@ -700,6 +774,37 @@ const createModelProperties = fromCallback(({ sendBack, input }) => {
|
|
|
700
774
|
};
|
|
701
775
|
});
|
|
702
776
|
|
|
777
|
+
/**
|
|
778
|
+
* Eviction epochs: lets work that was started before a schema's Model/ModelProperty instances were
|
|
779
|
+
* evicted (Schema.destroy, test cleanup) tell, when it finishes, that it must not put instances for
|
|
780
|
+
* that schema back in the caches. Stopping the evicted actors can't cancel such work (a DB lookup
|
|
781
|
+
* that ends in Model.create, a model's property creation), and finishing it after the eviction would
|
|
782
|
+
* rebuild instances from rows that are about to be deleted, which then write themselves again.
|
|
783
|
+
*
|
|
784
|
+
* Capture `currentEvictionEpoch()` when the work starts; before creating or caching an instance, skip
|
|
785
|
+
* it when `schemaEvictedSince(schemaName, epoch)`. Work started after an eviction is unaffected.
|
|
786
|
+
*/
|
|
787
|
+
let epoch = 0;
|
|
788
|
+
const lastEvictionBySchema = new Map();
|
|
789
|
+
function currentEvictionEpoch() {
|
|
790
|
+
return epoch;
|
|
791
|
+
}
|
|
792
|
+
/** Called by Model.evictForSchema. */
|
|
793
|
+
function recordSchemaEviction(schemaName) {
|
|
794
|
+
epoch += 1;
|
|
795
|
+
lastEvictionBySchema.set(schemaName, epoch);
|
|
796
|
+
}
|
|
797
|
+
/** True when the schema's instances were evicted after `since` (an epoch from currentEvictionEpoch). */
|
|
798
|
+
function schemaEvictedSince(schemaName, since) {
|
|
799
|
+
if (epoch === since || !schemaName)
|
|
800
|
+
return false;
|
|
801
|
+
return (lastEvictionBySchema.get(schemaName) ?? 0) > since;
|
|
802
|
+
}
|
|
803
|
+
/** True when any schema was evicted after `since` (cheap check before looking up which schemas apply). */
|
|
804
|
+
function anyEvictionSince(since) {
|
|
805
|
+
return epoch !== since;
|
|
806
|
+
}
|
|
807
|
+
|
|
703
808
|
const logger$4 = debug('seedSdk:write:validateEntity');
|
|
704
809
|
// XState v5 type inference bug: fromPromise types are inverted
|
|
705
810
|
// We use type assertion to work around this
|
|
@@ -707,6 +812,20 @@ const validateEntity = fromPromise(async ({ input }) => {
|
|
|
707
812
|
// Type assertion to fix XState v5 type inference bug
|
|
708
813
|
// Convert through unknown to avoid type overlap error
|
|
709
814
|
const entityInput = input;
|
|
815
|
+
// Validation awaits imports before looking up the schema; the entity can be evicted with its
|
|
816
|
+
// schema meanwhile (Schema.destroy, test cleanup). Schema.create would then load the evicted
|
|
817
|
+
// schema again, and its load re-creates the schema's models from rows being deleted.
|
|
818
|
+
const evictionEpoch = currentEvictionEpoch();
|
|
819
|
+
/** The schema to validate against; throws (validation then skips the schema check) once it was evicted. */
|
|
820
|
+
const schemaForValidation = async (schemaName) => {
|
|
821
|
+
const _mod_8 = await import('./Schema-D-Ud-XYw.js');
|
|
822
|
+
const _ns_8 = _mod_8.b;
|
|
823
|
+
const { Schema } = _ns_8;
|
|
824
|
+
if (schemaEvictedSince(schemaName, evictionEpoch)) {
|
|
825
|
+
throw new Error(`Schema "${schemaName}" was evicted during validation`);
|
|
826
|
+
}
|
|
827
|
+
return Schema.create(schemaName, { waitForReady: false });
|
|
828
|
+
};
|
|
710
829
|
const _validate = async () => {
|
|
711
830
|
try {
|
|
712
831
|
const msg = `[validateEntity] Starting validation for ${entityInput.entityType}`;
|
|
@@ -717,7 +836,7 @@ const validateEntity = fromPromise(async ({ input }) => {
|
|
|
717
836
|
const structureMsg = `[validateEntity] Validating model structure`;
|
|
718
837
|
logger$4(structureMsg);
|
|
719
838
|
// Use existing Model validation
|
|
720
|
-
const validationServiceMod = await import('./SchemaValidationService-
|
|
839
|
+
const validationServiceMod = await import('./SchemaValidationService-IoS7JquP.js');
|
|
721
840
|
const { SchemaValidationService } = validationServiceMod;
|
|
722
841
|
const validationService = new SchemaValidationService();
|
|
723
842
|
// Validate model structure
|
|
@@ -735,13 +854,7 @@ const validateEntity = fromPromise(async ({ input }) => {
|
|
|
735
854
|
if (entityInput.entityData.schemaName) {
|
|
736
855
|
try {
|
|
737
856
|
logger$4(`[validateEntity] Validating model against schema "${entityInput.entityData.schemaName}"`);
|
|
738
|
-
const
|
|
739
|
-
const _ns_5 = _mod_5.b;
|
|
740
|
-
const schemaMod = _ns_5;
|
|
741
|
-
const { Schema } = schemaMod;
|
|
742
|
-
const schema = Schema.create(entityInput.entityData.schemaName, {
|
|
743
|
-
waitForReady: false,
|
|
744
|
-
});
|
|
857
|
+
const schema = await schemaForValidation(entityInput.entityData.schemaName);
|
|
745
858
|
const schemaSnapshot = schema.getService().getSnapshot();
|
|
746
859
|
const schemaStatus = schemaSnapshot.value;
|
|
747
860
|
logger$4(`[validateEntity] Schema status: ${schemaStatus}`);
|
|
@@ -773,7 +886,7 @@ const validateEntity = fromPromise(async ({ input }) => {
|
|
|
773
886
|
}
|
|
774
887
|
else if (entityInput.entityType === 'modelProperty') {
|
|
775
888
|
// Use existing ModelProperty validation
|
|
776
|
-
const validationServiceMod = await import('./SchemaValidationService-
|
|
889
|
+
const validationServiceMod = await import('./SchemaValidationService-IoS7JquP.js');
|
|
777
890
|
const { SchemaValidationService } = validationServiceMod;
|
|
778
891
|
const validationService = new SchemaValidationService();
|
|
779
892
|
// Validate property structure
|
|
@@ -788,13 +901,7 @@ const validateEntity = fromPromise(async ({ input }) => {
|
|
|
788
901
|
// If schema name and model name provided, validate against schema
|
|
789
902
|
if (entityInput.entityData._schemaName && entityInput.entityData.modelName) {
|
|
790
903
|
try {
|
|
791
|
-
const
|
|
792
|
-
const _ns_6 = _mod_6.b;
|
|
793
|
-
const schemaMod = _ns_6;
|
|
794
|
-
const { Schema } = schemaMod;
|
|
795
|
-
const schema = Schema.create(entityInput.entityData._schemaName, {
|
|
796
|
-
waitForReady: false,
|
|
797
|
-
});
|
|
904
|
+
const schema = await schemaForValidation(entityInput.entityData._schemaName);
|
|
798
905
|
const schemaSnapshot = schema.getService().getSnapshot();
|
|
799
906
|
const schemaStatus = schemaSnapshot.value;
|
|
800
907
|
if (schemaStatus === 'idle') {
|
|
@@ -819,7 +926,7 @@ const validateEntity = fromPromise(async ({ input }) => {
|
|
|
819
926
|
}
|
|
820
927
|
else if (entityInput.entityType === 'schema') {
|
|
821
928
|
// Schema validation - use existing validation
|
|
822
|
-
const validationServiceMod = await import('./SchemaValidationService-
|
|
929
|
+
const validationServiceMod = await import('./SchemaValidationService-IoS7JquP.js');
|
|
823
930
|
const { SchemaValidationService } = validationServiceMod;
|
|
824
931
|
const validationService = new SchemaValidationService();
|
|
825
932
|
const schemaResult = validationService.validateSchema(entityInput.entityData);
|
|
@@ -849,6 +956,22 @@ const validateEntity = fromPromise(async ({ input }) => {
|
|
|
849
956
|
});
|
|
850
957
|
|
|
851
958
|
const logger$3 = debug('seedSdk:write:writeToDatabase');
|
|
959
|
+
// Writes that have started. Stopping a write process's actor can't cancel one, so code that deletes rows
|
|
960
|
+
// under live instances (Schema.destroy, test cleanup) waits for these after evicting the instances.
|
|
961
|
+
const inFlightWrites = new Set();
|
|
962
|
+
/**
|
|
963
|
+
* Resolves once every database write started so far has finished (or after timeoutMs). Evict/stop the
|
|
964
|
+
* instances first so no new writes start while waiting.
|
|
965
|
+
*/
|
|
966
|
+
const waitForInFlightWrites = async (timeoutMs = 5000) => {
|
|
967
|
+
const deadline = Date.now() + timeoutMs;
|
|
968
|
+
while (inFlightWrites.size > 0 && Date.now() < deadline) {
|
|
969
|
+
await Promise.race([
|
|
970
|
+
Promise.allSettled([...inFlightWrites]),
|
|
971
|
+
new Promise((resolve) => setTimeout(resolve, deadline - Date.now())),
|
|
972
|
+
]);
|
|
973
|
+
}
|
|
974
|
+
};
|
|
852
975
|
const writeToDatabase = fromCallback(({ sendBack, input }) => {
|
|
853
976
|
const _write = async () => {
|
|
854
977
|
try {
|
|
@@ -892,7 +1015,7 @@ const writeToDatabase = fromCallback(({ sendBack, input }) => {
|
|
|
892
1015
|
// initial write completes is not overwritten by the stale requestWrite payload.
|
|
893
1016
|
let dataToWrite = input.entityData;
|
|
894
1017
|
try {
|
|
895
|
-
const mod = await import('./ModelProperty-
|
|
1018
|
+
const mod = await import('./ModelProperty-6llK4MTH.js');
|
|
896
1019
|
const ModelProperty = mod?.ModelProperty ?? mod?.default;
|
|
897
1020
|
if (ModelProperty && typeof ModelProperty.getById === 'function') {
|
|
898
1021
|
const instance = ModelProperty.getById(input.entityId);
|
|
@@ -909,6 +1032,7 @@ const writeToDatabase = fromCallback(({ sendBack, input }) => {
|
|
|
909
1032
|
storageType: ctx.storageType ?? input.entityData.storageType,
|
|
910
1033
|
localStorageDir: ctx.localStorageDir ?? input.entityData.localStorageDir,
|
|
911
1034
|
filenameSuffix: ctx.filenameSuffix ?? input.entityData.filenameSuffix,
|
|
1035
|
+
required: ctx.required ?? input.entityData.required,
|
|
912
1036
|
};
|
|
913
1037
|
}
|
|
914
1038
|
}
|
|
@@ -941,18 +1065,26 @@ const writeToDatabase = fromCallback(({ sendBack, input }) => {
|
|
|
941
1065
|
});
|
|
942
1066
|
}
|
|
943
1067
|
};
|
|
944
|
-
_write().catch((error) => {
|
|
1068
|
+
const write = _write().catch((error) => {
|
|
945
1069
|
logger$3('Error in writeToDatabase promise:', error);
|
|
946
1070
|
sendBack({
|
|
947
1071
|
type: 'writeError',
|
|
948
1072
|
error: error instanceof Error ? error : new Error(String(error)),
|
|
949
1073
|
});
|
|
950
1074
|
});
|
|
1075
|
+
inFlightWrites.add(write);
|
|
1076
|
+
write.finally(() => inFlightWrites.delete(write));
|
|
951
1077
|
return () => {
|
|
952
1078
|
// Cleanup function (optional)
|
|
953
1079
|
};
|
|
954
1080
|
});
|
|
955
1081
|
|
|
1082
|
+
var writeToDatabase$1 = /*#__PURE__*/Object.freeze({
|
|
1083
|
+
__proto__: null,
|
|
1084
|
+
waitForInFlightWrites: waitForInFlightWrites,
|
|
1085
|
+
writeToDatabase: writeToDatabase
|
|
1086
|
+
});
|
|
1087
|
+
|
|
956
1088
|
const logger$2 = debug('seedSdk:write:writeProcessMachine');
|
|
957
1089
|
const writeProcessMachine = setup({
|
|
958
1090
|
types: {
|
|
@@ -1131,7 +1263,10 @@ const writeProcessMachine = setup({
|
|
|
1131
1263
|
retryCount: ({ context }) => context.retryCount + 1,
|
|
1132
1264
|
}),
|
|
1133
1265
|
({ context, event }) => {
|
|
1134
|
-
|
|
1266
|
+
const errorMsg = `[writing] Write error for ${context.entityType} "${context.entityId}": ${event.error}`;
|
|
1267
|
+
logger$2(errorMsg);
|
|
1268
|
+
// Nothing else reports a failed persist to the caller, so always log to console
|
|
1269
|
+
console.error(errorMsg, event.error);
|
|
1135
1270
|
},
|
|
1136
1271
|
],
|
|
1137
1272
|
},
|
|
@@ -1189,9 +1324,6 @@ const modelMachine = setup({
|
|
|
1189
1324
|
isModelValid: ({ context }) => {
|
|
1190
1325
|
return !context._validationErrors || context._validationErrors.length === 0;
|
|
1191
1326
|
},
|
|
1192
|
-
hasValidationErrors: ({ context }) => {
|
|
1193
|
-
return !!context._validationErrors && context._validationErrors.length > 0;
|
|
1194
|
-
},
|
|
1195
1327
|
},
|
|
1196
1328
|
actions: {
|
|
1197
1329
|
assignValidationErrors: assign(({ context, event }) => {
|
|
@@ -1266,16 +1398,23 @@ const modelMachine = setup({
|
|
|
1266
1398
|
({ context, event, self }) => {
|
|
1267
1399
|
if (event._liveQueryPropertyIds !== undefined) {
|
|
1268
1400
|
const newPropertyIds = event._liveQueryPropertyIds;
|
|
1401
|
+
// The model can be evicted with its schema (Schema.destroy, test cleanup) before the
|
|
1402
|
+
// timer and import below run: then create nothing, and drop lookups an eviction overtakes.
|
|
1403
|
+
const evictionEpoch = currentEvictionEpoch();
|
|
1269
1404
|
// Use setTimeout to check after assign has been applied
|
|
1270
1405
|
setTimeout(() => {
|
|
1271
|
-
self.getSnapshot();
|
|
1406
|
+
const snapshot = self.getSnapshot();
|
|
1407
|
+
if (snapshot.status === 'stopped')
|
|
1408
|
+
return;
|
|
1272
1409
|
// Create ModelProperty instances for any new property IDs
|
|
1273
1410
|
if (Array.isArray(newPropertyIds) && newPropertyIds.length > 0) {
|
|
1274
1411
|
// Import and create instances asynchronously (fire-and-forget)
|
|
1275
|
-
import('./ModelProperty-
|
|
1412
|
+
import('./ModelProperty-6llK4MTH.js').then(({ ModelProperty }) => {
|
|
1413
|
+
if (self.getSnapshot().status === 'stopped')
|
|
1414
|
+
return;
|
|
1276
1415
|
const createPromises = newPropertyIds.map(async (propertyFileId) => {
|
|
1277
1416
|
try {
|
|
1278
|
-
const property = await ModelProperty.createById(propertyFileId);
|
|
1417
|
+
const property = await ModelProperty.createById(propertyFileId, { evictionEpoch });
|
|
1279
1418
|
if (property) {
|
|
1280
1419
|
logger$1(`[modelMachine] Created/cached ModelProperty instance for propertyFileId "${propertyFileId}" after _liveQueryPropertyIds update`);
|
|
1281
1420
|
}
|
|
@@ -1349,22 +1488,15 @@ const modelMachine = setup({
|
|
|
1349
1488
|
})),
|
|
1350
1489
|
},
|
|
1351
1490
|
destroyStarted: {
|
|
1352
|
-
actions: assign({
|
|
1353
|
-
},
|
|
1354
|
-
destroyDone: {
|
|
1355
|
-
actions: assign({ _destroyInProgress: false }),
|
|
1491
|
+
actions: assign({ _destroyError: null }),
|
|
1356
1492
|
},
|
|
1357
1493
|
destroyError: {
|
|
1358
1494
|
actions: assign(({ event }) => ({
|
|
1359
|
-
_destroyInProgress: false,
|
|
1360
1495
|
_destroyError: event.error instanceof Error
|
|
1361
1496
|
? { message: event.error.message, name: event.error.name }
|
|
1362
1497
|
: { message: String(event.error) },
|
|
1363
1498
|
})),
|
|
1364
1499
|
},
|
|
1365
|
-
clearDestroyError: {
|
|
1366
|
-
actions: assign({ _destroyError: null }),
|
|
1367
|
-
},
|
|
1368
1500
|
},
|
|
1369
1501
|
states: {
|
|
1370
1502
|
loading: {
|
|
@@ -1497,10 +1629,9 @@ const modelMachine = setup({
|
|
|
1497
1629
|
},
|
|
1498
1630
|
],
|
|
1499
1631
|
},
|
|
1500
|
-
always:
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
},
|
|
1632
|
+
// No `always: hasValidationErrors -> validating` here: validation is re-run when the context changes
|
|
1633
|
+
// (updateContext) or on request (validateModel). Re-entering while errors exist would loop forever on a
|
|
1634
|
+
// model that is still invalid.
|
|
1504
1635
|
},
|
|
1505
1636
|
validating: {
|
|
1506
1637
|
on: {
|
|
@@ -1550,6 +1681,8 @@ const modelMachine = setup({
|
|
|
1550
1681
|
// Trigger property refresh after properties are created
|
|
1551
1682
|
// This ensures _liveQueryPropertyIds is updated in Node.js where liveQuery isn't available
|
|
1552
1683
|
setTimeout(() => {
|
|
1684
|
+
if (self.getSnapshot().status === 'stopped')
|
|
1685
|
+
return;
|
|
1553
1686
|
self.send({ type: 'refreshProperties' });
|
|
1554
1687
|
}, 100); // Small delay to ensure properties are written to DB
|
|
1555
1688
|
},
|
|
@@ -1604,11 +1737,16 @@ function setupEntityLiveQuery(instance, config) {
|
|
|
1604
1737
|
const initialIds = config.extractEntityIds(initialRows);
|
|
1605
1738
|
if (initialIds.length > 0) {
|
|
1606
1739
|
logger(`Initial query returned ${initialIds.length} entities`);
|
|
1607
|
-
// Create child instances if provided
|
|
1740
|
+
// Create child instances if provided (not for a stopped entity: an unloaded or evicted
|
|
1741
|
+
// parent must not re-cache its children)
|
|
1742
|
+
if (isActorStopped(instance.getService()))
|
|
1743
|
+
return;
|
|
1608
1744
|
if (config.createChildInstances) {
|
|
1609
1745
|
await config.createChildInstances(initialIds);
|
|
1610
1746
|
}
|
|
1611
|
-
// Update context with initial IDs
|
|
1747
|
+
// Update context with initial IDs (the queries above can outlive the instance)
|
|
1748
|
+
if (isActorStopped(instance.getService()))
|
|
1749
|
+
return;
|
|
1612
1750
|
config.updateContext(instance, initialIds);
|
|
1613
1751
|
}
|
|
1614
1752
|
}
|
|
@@ -1633,11 +1771,15 @@ function setupEntityLiveQuery(instance, config) {
|
|
|
1633
1771
|
}
|
|
1634
1772
|
logger(`Query returned ${rows.length} rows`);
|
|
1635
1773
|
const ids = config.extractEntityIds(rows);
|
|
1636
|
-
// Create child instances if provided (before updating context)
|
|
1774
|
+
// Create child instances if provided (before updating context; not for a stopped entity)
|
|
1775
|
+
if (isActorStopped(instance.getService()))
|
|
1776
|
+
return;
|
|
1637
1777
|
if (config.createChildInstances && ids.length > 0) {
|
|
1638
1778
|
await config.createChildInstances(ids);
|
|
1639
1779
|
}
|
|
1640
1780
|
// Update context with new IDs
|
|
1781
|
+
if (isActorStopped(instance.getService()))
|
|
1782
|
+
return;
|
|
1641
1783
|
config.updateContext(instance, ids);
|
|
1642
1784
|
},
|
|
1643
1785
|
error: (error) => {
|
|
@@ -1656,9 +1798,31 @@ function setupEntityLiveQuery(instance, config) {
|
|
|
1656
1798
|
setupState.subscriptionSetUp = false; // Reset on error so we can retry
|
|
1657
1799
|
}
|
|
1658
1800
|
};
|
|
1659
|
-
//
|
|
1660
|
-
|
|
1661
|
-
|
|
1801
|
+
// The entity's DB row can be written after the entity goes idle (e.g. a schema import writes its
|
|
1802
|
+
// models' rows after the Model instances loaded from the schema file). Nothing changes the
|
|
1803
|
+
// entity's snapshot then, so an idle entity's id is also retried on a timer until found or the
|
|
1804
|
+
// actor stops. Only while idle and not writing (canRetryEntityId): a busy entity's own snapshots
|
|
1805
|
+
// drive the lookup, and finding its row mid-write handed a Model its _dbId before its write (and
|
|
1806
|
+
// its properties' rows) had finished.
|
|
1807
|
+
let retryIndex = 0;
|
|
1808
|
+
let retryTimer;
|
|
1809
|
+
const scheduleRetry = () => {
|
|
1810
|
+
if (retryTimer !== undefined || retryIndex >= ENTITY_ID_RETRY_DELAYS_MS.length)
|
|
1811
|
+
return;
|
|
1812
|
+
retryTimer = setTimeout(() => {
|
|
1813
|
+
retryTimer = undefined;
|
|
1814
|
+
// Busy: its next snapshot retries
|
|
1815
|
+
if (instance.getService().getSnapshot().value !== 'idle')
|
|
1816
|
+
return;
|
|
1817
|
+
if (config.canRetryEntityId && !config.canRetryEntityId(instance))
|
|
1818
|
+
return;
|
|
1819
|
+
retryIndex++;
|
|
1820
|
+
void trySetup();
|
|
1821
|
+
}, ENTITY_ID_RETRY_DELAYS_MS[retryIndex]);
|
|
1822
|
+
};
|
|
1823
|
+
const trySetup = async () => {
|
|
1824
|
+
if (setupState.subscriptionSetUp || isActorStopped(instance.getService()))
|
|
1825
|
+
return;
|
|
1662
1826
|
if (config.isReady && !config.isReady(instance)) {
|
|
1663
1827
|
if (config.waitForReady) {
|
|
1664
1828
|
await config.waitForReady(instance);
|
|
@@ -1667,35 +1831,42 @@ function setupEntityLiveQuery(instance, config) {
|
|
|
1667
1831
|
return; // Not ready yet, will retry on next snapshot
|
|
1668
1832
|
}
|
|
1669
1833
|
}
|
|
1670
|
-
|
|
1671
|
-
|
|
1834
|
+
let entityId;
|
|
1835
|
+
try {
|
|
1836
|
+
entityId = await config.getEntityId(instance);
|
|
1837
|
+
}
|
|
1838
|
+
catch (error) {
|
|
1839
|
+
logger(`Error getting entity ID: ${error}`);
|
|
1840
|
+
}
|
|
1672
1841
|
if (!entityId) {
|
|
1673
|
-
|
|
1842
|
+
scheduleRetry();
|
|
1843
|
+
return;
|
|
1674
1844
|
}
|
|
1675
1845
|
// Once we have entity ID, set up the liveQuery subscription (only once)
|
|
1676
1846
|
if (!setupState.subscriptionSetUp) {
|
|
1677
1847
|
await setupLiveQuery(entityId);
|
|
1678
|
-
if (setupState.subscriptionSetUp) {
|
|
1679
|
-
setupSubscription.unsubscribe();
|
|
1680
|
-
}
|
|
1681
1848
|
}
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
// Not ready yet, will be handled by subscription
|
|
1687
|
-
return;
|
|
1688
|
-
}
|
|
1689
|
-
config.getEntityId(instance).then((entityId) => {
|
|
1690
|
-
if (entityId && !setupState.subscriptionSetUp) {
|
|
1691
|
-
setupLiveQuery(entityId).catch((error) => {
|
|
1692
|
-
logger(`Error in immediate setup: ${error}`);
|
|
1693
|
-
});
|
|
1849
|
+
if (setupState.subscriptionSetUp) {
|
|
1850
|
+
setupSubscription.unsubscribe();
|
|
1851
|
+
if (retryTimer !== undefined)
|
|
1852
|
+
clearTimeout(retryTimer);
|
|
1694
1853
|
}
|
|
1695
|
-
}
|
|
1696
|
-
|
|
1854
|
+
};
|
|
1855
|
+
// Set up liveQuery subscription as soon as we have entity ID
|
|
1856
|
+
const setupSubscription = instance.getService().subscribe({
|
|
1857
|
+
next: () => {
|
|
1858
|
+
void trySetup();
|
|
1859
|
+
},
|
|
1860
|
+
complete: () => {
|
|
1861
|
+
if (retryTimer !== undefined)
|
|
1862
|
+
clearTimeout(retryTimer);
|
|
1863
|
+
},
|
|
1697
1864
|
});
|
|
1865
|
+
// Also check current state immediately in case entity ID is already available
|
|
1866
|
+
void trySetup();
|
|
1698
1867
|
}
|
|
1868
|
+
/** Backoff for retrying an entity's id when its DB row isn't there yet (~60s in total). */
|
|
1869
|
+
const ENTITY_ID_RETRY_DELAYS_MS = [50, 100, 200, 400, 800, 1600, ...Array(28).fill(2000)];
|
|
1699
1870
|
|
|
1700
1871
|
/**
|
|
1701
1872
|
* Returns model rows (id, name, schemaFileId, isEdited) for building Model instances.
|
|
@@ -1743,7 +1914,7 @@ const saveDraftLogger = debug('seedSdk:model:saveDraftToDb');
|
|
|
1743
1914
|
// Lazy import cache for ModelProperty to avoid circular dependency
|
|
1744
1915
|
// Eagerly start loading to minimize delay on first access
|
|
1745
1916
|
let ModelPropertyClass = null;
|
|
1746
|
-
const modelPropertyImportPromise = import('./ModelProperty-
|
|
1917
|
+
const modelPropertyImportPromise = import('./ModelProperty-6llK4MTH.js')
|
|
1747
1918
|
.then(module => {
|
|
1748
1919
|
ModelPropertyClass = module.ModelProperty;
|
|
1749
1920
|
return ModelPropertyClass;
|
|
@@ -1758,17 +1929,10 @@ function getModelProperty() {
|
|
|
1758
1929
|
// and the getter will return empty array, which matches the original behavior
|
|
1759
1930
|
return ModelPropertyClass;
|
|
1760
1931
|
}
|
|
1761
|
-
// Lazy import
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
.
|
|
1765
|
-
SchemaClass = module.Schema;
|
|
1766
|
-
return SchemaClass;
|
|
1767
|
-
})
|
|
1768
|
-
.catch(() => {
|
|
1769
|
-
// If import fails, SchemaClass remains null
|
|
1770
|
-
return null;
|
|
1771
|
-
});
|
|
1932
|
+
// Lazy import for Schema to avoid circular dependency
|
|
1933
|
+
const schemaImportPromise = (async () => { const _mod_11 = await import('./Schema-D-Ud-XYw.js'); return _mod_11.b; })()
|
|
1934
|
+
.then(module => module.Schema)
|
|
1935
|
+
.catch(() => null);
|
|
1772
1936
|
// WeakMap to store mutable state per Model instance
|
|
1773
1937
|
// This avoids issues with read-only properties when instances are frozen by Immer
|
|
1774
1938
|
const modelInstanceState = new WeakMap();
|
|
@@ -1830,6 +1994,14 @@ class Model {
|
|
|
1830
1994
|
});
|
|
1831
1995
|
// Note: Property getters/setters are now handled by the Proxy in create()
|
|
1832
1996
|
}
|
|
1997
|
+
/**
|
|
1998
|
+
* True when a name-cached instance belongs to a different model than the requested modelFileId.
|
|
1999
|
+
* A schema re-imported under the same name can give its models new ids while the previous
|
|
2000
|
+
* instances are still cached by name; Model.create must not hand those back for the new id.
|
|
2001
|
+
*/
|
|
2002
|
+
static isOtherModelId(cachedId, requestedId) {
|
|
2003
|
+
return !!requestedId && !!cachedId && cachedId !== requestedId;
|
|
2004
|
+
}
|
|
1833
2005
|
/**
|
|
1834
2006
|
* Find a unique model name by checking for duplicates (case-insensitive) in the cache
|
|
1835
2007
|
* If duplicates are found, appends an incrementing number to make it unique
|
|
@@ -1888,36 +2060,6 @@ class Model {
|
|
|
1888
2060
|
}
|
|
1889
2061
|
}
|
|
1890
2062
|
}
|
|
1891
|
-
// Also check schema context models (case-insensitive)
|
|
1892
|
-
// This ensures runtime-created models are renamed if they conflict with schema-defined models
|
|
1893
|
-
try {
|
|
1894
|
-
// Use lazy-loaded Schema class to avoid circular dependency
|
|
1895
|
-
if (SchemaClass) {
|
|
1896
|
-
const schema = SchemaClass.create(schemaName);
|
|
1897
|
-
const schemaContext = schema.getService().getSnapshot().context;
|
|
1898
|
-
if (schemaContext.models) {
|
|
1899
|
-
for (const schemaModelName of Object.keys(schemaContext.models)) {
|
|
1900
|
-
const lowerSchemaModelName = schemaModelName.toLowerCase();
|
|
1901
|
-
// If it matches the base name (case-insensitive), check if it has a number suffix
|
|
1902
|
-
if (lowerSchemaModelName === lowerModelName) {
|
|
1903
|
-
existingNumbers.add(0); // Base name exists in schema
|
|
1904
|
-
}
|
|
1905
|
-
else if (lowerSchemaModelName.startsWith(lowerModelName + ' ')) {
|
|
1906
|
-
// Check if it's the base name followed by a space and a number
|
|
1907
|
-
const suffix = lowerSchemaModelName.slice(lowerModelName.length + 1);
|
|
1908
|
-
const number = parseInt(suffix, 10);
|
|
1909
|
-
if (!isNaN(number) && suffix === number.toString()) {
|
|
1910
|
-
existingNumbers.add(number);
|
|
1911
|
-
}
|
|
1912
|
-
}
|
|
1913
|
-
}
|
|
1914
|
-
}
|
|
1915
|
-
}
|
|
1916
|
-
}
|
|
1917
|
-
catch (error) {
|
|
1918
|
-
// If schema check fails, continue with cache-only check
|
|
1919
|
-
// This is a best-effort check and shouldn't block model creation
|
|
1920
|
-
}
|
|
1921
2063
|
// If no duplicates found (no base name match and no numbered variants), return original name
|
|
1922
2064
|
if (existingNumbers.size === 0) {
|
|
1923
2065
|
return modelName;
|
|
@@ -1997,7 +2139,7 @@ class Model {
|
|
|
1997
2139
|
if (this.instanceCache.has(legacyKey)) {
|
|
1998
2140
|
const { instance, refCount } = this.instanceCache.get(legacyKey);
|
|
1999
2141
|
const ctx = instance._getSnapshotContext();
|
|
2000
|
-
if (!ctx._idFromSchema) {
|
|
2142
|
+
if (!ctx._idFromSchema && !this.isOtherModelId(ctx.id, id)) {
|
|
2001
2143
|
this.instanceCache.set(legacyKey, {
|
|
2002
2144
|
instance,
|
|
2003
2145
|
refCount: refCount + 1,
|
|
@@ -2033,7 +2175,8 @@ class Model {
|
|
|
2033
2175
|
: `${schemaName}:__pending__${resolvedId}`;
|
|
2034
2176
|
// Step 6: Check legacy cache with unique name (backward compatibility during migration)
|
|
2035
2177
|
// This is a fallback in case an instance was cached with a unique name
|
|
2036
|
-
if (this.instanceCache.has(nameKey)
|
|
2178
|
+
if (this.instanceCache.has(nameKey) &&
|
|
2179
|
+
!this.isOtherModelId(this.instanceCache.get(nameKey).instance._getSnapshotContext().id, id)) {
|
|
2037
2180
|
const { instance, refCount } = this.instanceCache.get(nameKey);
|
|
2038
2181
|
this.instanceCache.set(nameKey, {
|
|
2039
2182
|
instance,
|
|
@@ -2285,6 +2428,9 @@ class Model {
|
|
|
2285
2428
|
resolve();
|
|
2286
2429
|
}, 10000);
|
|
2287
2430
|
});
|
|
2431
|
+
// Unloaded or evicted (e.g. Schema.destroy) while it loaded: a stopped model never writes
|
|
2432
|
+
if (isActorStopped(proxiedInstance._service))
|
|
2433
|
+
return;
|
|
2288
2434
|
// Only write if validation passed (model is in idle state, not error)
|
|
2289
2435
|
const finalSnapshot = proxiedInstance._service.getSnapshot();
|
|
2290
2436
|
if (finalSnapshot.value === 'idle' && (!finalSnapshot.context._validationErrors || finalSnapshot.context._validationErrors.length === 0)) {
|
|
@@ -2408,15 +2554,20 @@ class Model {
|
|
|
2408
2554
|
}
|
|
2409
2555
|
logger(`WARNING: Could not verify schema exists in database: ${error}. Proceeding anyway.`);
|
|
2410
2556
|
}
|
|
2411
|
-
|
|
2412
|
-
|
|
2557
|
+
const pendingModelFileId = finalSnapshot.context.id;
|
|
2558
|
+
const pendingSchemaId = schemaId;
|
|
2413
2559
|
// Wait for writeProcess to be spawned (it's spawned in idle state entry action)
|
|
2414
2560
|
// Retry a few times if writeProcess isn't available yet
|
|
2415
2561
|
let retries = 0;
|
|
2416
2562
|
const maxRetries = 10;
|
|
2417
2563
|
const checkAndSend = async () => {
|
|
2564
|
+
// Unloaded or evicted (e.g. Schema.destroy) before the write started: nothing to write to
|
|
2565
|
+
if (isActorStopped(proxiedInstance._service))
|
|
2566
|
+
return;
|
|
2418
2567
|
const currentSnapshot = proxiedInstance._service.getSnapshot();
|
|
2419
2568
|
if (currentSnapshot.context.writeProcess) {
|
|
2569
|
+
// Track pending write (only once it really starts: a stopped model leaves none behind)
|
|
2570
|
+
Model.trackPendingWrite(pendingModelFileId, pendingSchemaId); // id is now the schemaFileId (string)
|
|
2420
2571
|
logger(`Triggering write process for model "${finalSnapshot.context.modelName}" (schemaId: ${schemaId})`);
|
|
2421
2572
|
// Use pending property definitions if available, otherwise convert from ModelProperty instances
|
|
2422
2573
|
let propertiesObject = {};
|
|
@@ -2540,14 +2691,45 @@ class Model {
|
|
|
2540
2691
|
}
|
|
2541
2692
|
return this.getById(id);
|
|
2542
2693
|
}
|
|
2543
|
-
// If schemaName not provided,
|
|
2694
|
+
// If schemaName not provided, search all name keys. Model names are only unique per schema, so
|
|
2695
|
+
// this throws AmbiguousModelError when cached models from several schemas share the name.
|
|
2696
|
+
// Callers that know the schema or model id should use Model.resolve() instead.
|
|
2697
|
+
return this._getUniqueCachedModel(modelName, (cachedModelName) => cachedModelName === modelName);
|
|
2698
|
+
}
|
|
2699
|
+
/** The one cached Model whose name matches, or AmbiguousModelError if models from several schemas do. */
|
|
2700
|
+
static _getUniqueCachedModel(label, matches) {
|
|
2701
|
+
const matchesById = new Map(); // modelFileId -> schemaName
|
|
2544
2702
|
for (const [nameKey, id] of this.instanceCacheByName.entries()) {
|
|
2545
|
-
const
|
|
2546
|
-
|
|
2547
|
-
|
|
2703
|
+
const separator = nameKey.lastIndexOf(':');
|
|
2704
|
+
const cachedModelName = nameKey.slice(separator + 1);
|
|
2705
|
+
if (id && cachedModelName && matches(cachedModelName) && this.instanceCacheById.has(id)) {
|
|
2706
|
+
matchesById.set(id, nameKey.slice(0, separator));
|
|
2548
2707
|
}
|
|
2549
2708
|
}
|
|
2550
|
-
|
|
2709
|
+
if (matchesById.size > 1) {
|
|
2710
|
+
throw new AmbiguousModelError(label, [...matchesById.values()]);
|
|
2711
|
+
}
|
|
2712
|
+
const [matchId] = matchesById.keys();
|
|
2713
|
+
return matchId ? this.getById(matchId) : undefined;
|
|
2714
|
+
}
|
|
2715
|
+
/**
|
|
2716
|
+
* Resolve a cached Model from the most specific scope available: modelFileId (Model.id), then
|
|
2717
|
+
* schemaName + modelName, then modelName alone.
|
|
2718
|
+
*/
|
|
2719
|
+
static resolve(modelName, scope = {}) {
|
|
2720
|
+
if (scope.modelFileId) {
|
|
2721
|
+
const byId = this.getById(scope.modelFileId);
|
|
2722
|
+
if (byId)
|
|
2723
|
+
return byId;
|
|
2724
|
+
}
|
|
2725
|
+
if (!modelName)
|
|
2726
|
+
return undefined;
|
|
2727
|
+
if (scope.schemaName) {
|
|
2728
|
+
const bySchema = this.getByName(modelName, scope.schemaName);
|
|
2729
|
+
if (bySchema)
|
|
2730
|
+
return bySchema;
|
|
2731
|
+
}
|
|
2732
|
+
return this.getByName(modelName);
|
|
2551
2733
|
}
|
|
2552
2734
|
/**
|
|
2553
2735
|
* Find Model by modelType (snake_case from DB/metadata).
|
|
@@ -2556,14 +2738,7 @@ class Model {
|
|
|
2556
2738
|
static findByModelType(modelType) {
|
|
2557
2739
|
if (!modelType)
|
|
2558
2740
|
return undefined;
|
|
2559
|
-
|
|
2560
|
-
const parts = nameKey.split(':', 2);
|
|
2561
|
-
const cachedModelName = parts[1];
|
|
2562
|
-
if (cachedModelName && toSnakeCase(cachedModelName) === modelType) {
|
|
2563
|
-
return this.getById(id);
|
|
2564
|
-
}
|
|
2565
|
-
}
|
|
2566
|
-
return undefined;
|
|
2741
|
+
return this._getUniqueCachedModel(modelType, (cachedModelName) => toSnakeCase(cachedModelName) === modelType);
|
|
2567
2742
|
}
|
|
2568
2743
|
/**
|
|
2569
2744
|
* Get all Model instances for a schema from cache only (synchronous).
|
|
@@ -2595,6 +2770,54 @@ class Model {
|
|
|
2595
2770
|
}
|
|
2596
2771
|
return instances;
|
|
2597
2772
|
}
|
|
2773
|
+
/**
|
|
2774
|
+
* Async Model.resolve(): exact cache hit by modelFileId or schemaName+modelName, else the DB row for
|
|
2775
|
+
* that scope (instantiating the Model), and only then the name-only fallback.
|
|
2776
|
+
*/
|
|
2777
|
+
static async resolveAsync(modelName, scope = {}) {
|
|
2778
|
+
if (scope.modelFileId) {
|
|
2779
|
+
const byId = this.getById(scope.modelFileId);
|
|
2780
|
+
if (byId)
|
|
2781
|
+
return byId;
|
|
2782
|
+
}
|
|
2783
|
+
if (modelName && scope.schemaName) {
|
|
2784
|
+
const bySchema = this.getByName(modelName, scope.schemaName);
|
|
2785
|
+
if (bySchema)
|
|
2786
|
+
return bySchema;
|
|
2787
|
+
}
|
|
2788
|
+
if (scope.modelFileId || scope.schemaName) {
|
|
2789
|
+
const db = BaseDb.getAppDb();
|
|
2790
|
+
if (db) {
|
|
2791
|
+
const evictionEpoch = currentEvictionEpoch();
|
|
2792
|
+
try {
|
|
2793
|
+
const rows = await db
|
|
2794
|
+
.select({
|
|
2795
|
+
modelFileId: models.schemaFileId,
|
|
2796
|
+
modelName: models.name,
|
|
2797
|
+
schemaName: schemas.name,
|
|
2798
|
+
})
|
|
2799
|
+
.from(models)
|
|
2800
|
+
.innerJoin(modelSchemas, eq(models.id, modelSchemas.modelId))
|
|
2801
|
+
.innerJoin(schemas, eq(modelSchemas.schemaId, schemas.id))
|
|
2802
|
+
.where(scope.modelFileId
|
|
2803
|
+
? eq(models.schemaFileId, scope.modelFileId)
|
|
2804
|
+
: and(eq(models.name, modelName ?? ''), eq(schemas.name, scope.schemaName)))
|
|
2805
|
+
.limit(1);
|
|
2806
|
+
const record = rows[0];
|
|
2807
|
+
if (record?.modelName && record.schemaName && record.modelFileId) {
|
|
2808
|
+
// Its schema was evicted while we read the row: don't bring the model back.
|
|
2809
|
+
if (schemaEvictedSince(record.schemaName, evictionEpoch))
|
|
2810
|
+
return undefined;
|
|
2811
|
+
return this.create(record.modelName, record.schemaName, { id: record.modelFileId });
|
|
2812
|
+
}
|
|
2813
|
+
}
|
|
2814
|
+
catch (error) {
|
|
2815
|
+
logger(`Model.resolveAsync: scoped lookup failed for "${modelName}": ${error instanceof Error ? error.message : String(error)}`);
|
|
2816
|
+
}
|
|
2817
|
+
}
|
|
2818
|
+
}
|
|
2819
|
+
return modelName ? this.getByNameAsync(modelName) : undefined;
|
|
2820
|
+
}
|
|
2598
2821
|
/**
|
|
2599
2822
|
* Get Model instance by name, querying database if not in cache
|
|
2600
2823
|
* This is an async version that can query the database when schemaName is not provided
|
|
@@ -2603,7 +2826,7 @@ class Model {
|
|
|
2603
2826
|
* @param schemaName - Optional schema name (will query DB if not provided)
|
|
2604
2827
|
* @returns The Model instance if found, undefined otherwise
|
|
2605
2828
|
*/
|
|
2606
|
-
static async getByNameAsync(modelName, schemaName) {
|
|
2829
|
+
static async getByNameAsync(modelName, schemaName, options) {
|
|
2607
2830
|
// First try cache
|
|
2608
2831
|
const cached = this.getByName(modelName, schemaName);
|
|
2609
2832
|
if (cached) {
|
|
@@ -2615,8 +2838,16 @@ class Model {
|
|
|
2615
2838
|
if (!db) {
|
|
2616
2839
|
return undefined;
|
|
2617
2840
|
}
|
|
2841
|
+
const evictionEpoch = options?.evictionEpoch ?? currentEvictionEpoch();
|
|
2618
2842
|
try {
|
|
2619
|
-
// Query model by name
|
|
2843
|
+
// Query model by name (throws AmbiguousModelError when several schemas define it)
|
|
2844
|
+
const _mod_9 = await import('./db-Lw0KVZmc.js');
|
|
2845
|
+
const _ns_9 = _mod_9.Y;
|
|
2846
|
+
const { resolveModelRecord } = _ns_9;
|
|
2847
|
+
const resolved = await resolveModelRecord(modelName, {}, db);
|
|
2848
|
+
if (!resolved?.schemaFileId) {
|
|
2849
|
+
return undefined;
|
|
2850
|
+
}
|
|
2620
2851
|
const modelRecords = await db
|
|
2621
2852
|
.select({
|
|
2622
2853
|
modelFileId: models.schemaFileId,
|
|
@@ -2626,7 +2857,7 @@ class Model {
|
|
|
2626
2857
|
.from(models)
|
|
2627
2858
|
.innerJoin(modelSchemas, eq(models.id, modelSchemas.modelId))
|
|
2628
2859
|
.innerJoin(schemas, eq(modelSchemas.schemaId, schemas.id))
|
|
2629
|
-
.where(eq(models.
|
|
2860
|
+
.where(eq(models.id, resolved.id))
|
|
2630
2861
|
.limit(1);
|
|
2631
2862
|
if (modelRecords.length === 0) {
|
|
2632
2863
|
return undefined;
|
|
@@ -2635,12 +2866,18 @@ class Model {
|
|
|
2635
2866
|
if (!record.modelName || !record.schemaName || !record.modelFileId) {
|
|
2636
2867
|
return undefined;
|
|
2637
2868
|
}
|
|
2869
|
+
// Its schema was evicted while we read the row: don't bring the model back.
|
|
2870
|
+
if (schemaEvictedSince(record.schemaName, evictionEpoch)) {
|
|
2871
|
+
return undefined;
|
|
2872
|
+
}
|
|
2638
2873
|
// Create model instance (will be cached)
|
|
2639
2874
|
return this.create(record.modelName, record.schemaName, {
|
|
2640
2875
|
id: record.modelFileId, // id is now the schemaFileId (string)
|
|
2641
2876
|
});
|
|
2642
2877
|
}
|
|
2643
2878
|
catch (error) {
|
|
2879
|
+
if (error instanceof AmbiguousModelError)
|
|
2880
|
+
throw error;
|
|
2644
2881
|
logger(`Model.getByNameAsync: Error looking up model by name "${modelName}": ${error instanceof Error ? error.message : String(error)}`);
|
|
2645
2882
|
return undefined;
|
|
2646
2883
|
}
|
|
@@ -2654,7 +2891,7 @@ class Model {
|
|
|
2654
2891
|
* @param modelFileId - The model file ID to look up
|
|
2655
2892
|
* @returns The Model instance if found, undefined otherwise
|
|
2656
2893
|
*/
|
|
2657
|
-
static async createById(modelFileId) {
|
|
2894
|
+
static async createById(modelFileId, options) {
|
|
2658
2895
|
if (!modelFileId) {
|
|
2659
2896
|
return undefined;
|
|
2660
2897
|
}
|
|
@@ -2670,6 +2907,7 @@ class Model {
|
|
|
2670
2907
|
logger(`Model.createById: Database not available for ID "${modelFileId}"`);
|
|
2671
2908
|
return undefined;
|
|
2672
2909
|
}
|
|
2910
|
+
const evictionEpoch = options?.evictionEpoch ?? currentEvictionEpoch();
|
|
2673
2911
|
try {
|
|
2674
2912
|
// Query model by schemaFileId and join to get schema name
|
|
2675
2913
|
const modelRecords = await db
|
|
@@ -2692,6 +2930,12 @@ class Model {
|
|
|
2692
2930
|
logger(`Model.createById: Missing modelName or schemaName for ID "${modelFileId}"`);
|
|
2693
2931
|
return undefined;
|
|
2694
2932
|
}
|
|
2933
|
+
// Its schema was evicted while we read the row (e.g. a Schema live query in flight during
|
|
2934
|
+
// Schema.destroy or test cleanup): don't bring the model back.
|
|
2935
|
+
if (schemaEvictedSince(schemaName, evictionEpoch)) {
|
|
2936
|
+
logger(`Model.createById: schema "${schemaName}" was evicted during the lookup of "${modelFileId}"`);
|
|
2937
|
+
return undefined;
|
|
2938
|
+
}
|
|
2695
2939
|
// Step 3: Create model using existing create method (which will handle caching)
|
|
2696
2940
|
logger(`Model.createById: Creating model "${modelName}" in schema "${schemaName}" from ID "${modelFileId}"`);
|
|
2697
2941
|
return this.create(modelName, schemaName, {
|
|
@@ -2746,6 +2990,7 @@ class Model {
|
|
|
2746
2990
|
logger(`Model.createBySchemaId: Database not available for schema "${schemaIdentifier}"`);
|
|
2747
2991
|
return [];
|
|
2748
2992
|
}
|
|
2993
|
+
const evictionEpoch = currentEvictionEpoch();
|
|
2749
2994
|
try {
|
|
2750
2995
|
// Query all models for this schema - support both schemaFileId and schema name
|
|
2751
2996
|
const modelRecords = await db
|
|
@@ -2768,6 +3013,10 @@ class Model {
|
|
|
2768
3013
|
if (!record.modelName || !record.schemaName || !record.modelFileId) {
|
|
2769
3014
|
continue;
|
|
2770
3015
|
}
|
|
3016
|
+
// Its schema was evicted while we read the rows: don't bring its models back.
|
|
3017
|
+
if (schemaEvictedSince(record.schemaName, evictionEpoch)) {
|
|
3018
|
+
continue;
|
|
3019
|
+
}
|
|
2771
3020
|
// Check cache first
|
|
2772
3021
|
const cached = this.getById(record.modelFileId);
|
|
2773
3022
|
if (cached) {
|
|
@@ -2846,9 +3095,10 @@ class Model {
|
|
|
2846
3095
|
const instances = [];
|
|
2847
3096
|
const seen = new Set();
|
|
2848
3097
|
for (const row of rows) {
|
|
2849
|
-
|
|
3098
|
+
// A model can appear more than once (e.g. duplicate model_schemas links); return it once.
|
|
3099
|
+
if (row.schemaFileId && !seen.has(row.schemaFileId)) {
|
|
2850
3100
|
const instance = await this.createById(row.schemaFileId);
|
|
2851
|
-
if (instance) {
|
|
3101
|
+
if (instance && !seen.has(instance.id ?? row.schemaFileId)) {
|
|
2852
3102
|
instances.push(instance);
|
|
2853
3103
|
seen.add(instance.id ?? row.schemaFileId);
|
|
2854
3104
|
}
|
|
@@ -3206,6 +3456,52 @@ class Model {
|
|
|
3206
3456
|
}, 10000);
|
|
3207
3457
|
});
|
|
3208
3458
|
}
|
|
3459
|
+
/**
|
|
3460
|
+
* Force-evict every cached Model belonging to a schema, ignoring refCounts, and stop their services.
|
|
3461
|
+
* Used by Schema.destroy(): once the DB rows are gone, cached instances would keep a dangling _dbId
|
|
3462
|
+
* and be handed back by Model.create/Model.all after the schema is re-imported.
|
|
3463
|
+
* @returns names of the evicted models (so callers can evict their ModelProperty instances)
|
|
3464
|
+
*/
|
|
3465
|
+
static evictForSchema(schemaName) {
|
|
3466
|
+
// Work already running for this schema's models must not re-cache them when it finishes.
|
|
3467
|
+
recordSchemaEviction(schemaName);
|
|
3468
|
+
const instances = new Set();
|
|
3469
|
+
for (const { instance } of this.instanceCacheById.values())
|
|
3470
|
+
instances.add(instance);
|
|
3471
|
+
for (const { instance } of this.instanceCache.values())
|
|
3472
|
+
instances.add(instance);
|
|
3473
|
+
const evictedNames = [];
|
|
3474
|
+
for (const instance of instances) {
|
|
3475
|
+
let context;
|
|
3476
|
+
try {
|
|
3477
|
+
context = instance._getSnapshotContext();
|
|
3478
|
+
}
|
|
3479
|
+
catch {
|
|
3480
|
+
continue;
|
|
3481
|
+
}
|
|
3482
|
+
if (context.schemaName !== schemaName)
|
|
3483
|
+
continue;
|
|
3484
|
+
const nameKey = `${context.schemaName}:${context.modelName}`;
|
|
3485
|
+
clearDestroySubscriptions(instance, { instanceState: modelInstanceState });
|
|
3486
|
+
forceRemoveFromCaches(instance, {
|
|
3487
|
+
getCacheKeys: () => (context.id ? [context.id, nameKey] : [nameKey]),
|
|
3488
|
+
caches: [
|
|
3489
|
+
Model.instanceCacheById,
|
|
3490
|
+
Model.instanceCacheByName,
|
|
3491
|
+
Model.instanceCache,
|
|
3492
|
+
],
|
|
3493
|
+
});
|
|
3494
|
+
try {
|
|
3495
|
+
instance._service.stop();
|
|
3496
|
+
}
|
|
3497
|
+
catch {
|
|
3498
|
+
// Service might already be stopped
|
|
3499
|
+
}
|
|
3500
|
+
if (context.modelName)
|
|
3501
|
+
evictedNames.push(context.modelName);
|
|
3502
|
+
}
|
|
3503
|
+
return evictedNames;
|
|
3504
|
+
}
|
|
3209
3505
|
/**
|
|
3210
3506
|
* Unload the model instance and clean up resources
|
|
3211
3507
|
*/
|
|
@@ -3320,16 +3616,18 @@ class Model {
|
|
|
3320
3616
|
if (!db) {
|
|
3321
3617
|
return undefined;
|
|
3322
3618
|
}
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
if (
|
|
3619
|
+
// Model names are only unique per schema: find this model's row by its id (schemaFileId).
|
|
3620
|
+
const _mod_10 = await import('./db-Lw0KVZmc.js');
|
|
3621
|
+
const _ns_10 = _mod_10.Y;
|
|
3622
|
+
const { resolveModelRecord } = _ns_10;
|
|
3623
|
+
const modelRecord = await resolveModelRecord(modelName, { modelFileId: context.id, schemaName: context.schemaName }, db);
|
|
3624
|
+
if (!modelRecord?.id) {
|
|
3329
3625
|
return undefined;
|
|
3330
3626
|
}
|
|
3331
|
-
dbId =
|
|
3332
|
-
// Update context with _dbId
|
|
3627
|
+
dbId = modelRecord.id;
|
|
3628
|
+
// Update context with _dbId (unless the model was stopped while the lookup ran)
|
|
3629
|
+
if (isActorStopped(model._service))
|
|
3630
|
+
return undefined;
|
|
3333
3631
|
model._service.send({
|
|
3334
3632
|
type: 'updateContext',
|
|
3335
3633
|
_dbId: dbId,
|
|
@@ -3389,6 +3687,12 @@ class Model {
|
|
|
3389
3687
|
schemaFileId: row.schemaFileId,
|
|
3390
3688
|
}));
|
|
3391
3689
|
},
|
|
3690
|
+
// The model writes from its writeProcess child while itself idle; wait for that write to end.
|
|
3691
|
+
canRetryEntityId: (model) => {
|
|
3692
|
+
const writeProcess = model._getSnapshotContext().writeProcess;
|
|
3693
|
+
const writeState = writeProcess?.getSnapshot().value;
|
|
3694
|
+
return writeState !== 'validating' && writeState !== 'writing';
|
|
3695
|
+
},
|
|
3392
3696
|
instanceState: modelInstanceState,
|
|
3393
3697
|
loggerName: 'seedSdk:model:liveQuery',
|
|
3394
3698
|
});
|
|
@@ -3412,6 +3716,9 @@ class Model {
|
|
|
3412
3716
|
.select({ schemaFileId: properties.schemaFileId })
|
|
3413
3717
|
.from(properties)
|
|
3414
3718
|
.where(eq(properties.modelId, dbId)); // Use _dbId (database integer ID)
|
|
3719
|
+
// Stopped while querying: don't re-cache ModelProperty instances for an evicted/unloaded model
|
|
3720
|
+
if (isActorStopped(this._service))
|
|
3721
|
+
return;
|
|
3415
3722
|
const propertyIds = propertyRows
|
|
3416
3723
|
.map((row) => row.schemaFileId)
|
|
3417
3724
|
.filter((id) => id !== null && id !== undefined);
|
|
@@ -3446,7 +3753,10 @@ class Model {
|
|
|
3446
3753
|
logger(`[Model._refreshPropertiesFromDb] Error importing ModelProperty or creating instances: ${error}`);
|
|
3447
3754
|
}
|
|
3448
3755
|
}
|
|
3449
|
-
// Update context with refreshed property IDs AFTER creating instances
|
|
3756
|
+
// Update context with refreshed property IDs AFTER creating instances (the awaits above can
|
|
3757
|
+
// outlive the instance)
|
|
3758
|
+
if (isActorStopped(this._service))
|
|
3759
|
+
return;
|
|
3450
3760
|
this._service.send({
|
|
3451
3761
|
type: 'updateContext',
|
|
3452
3762
|
_liveQueryPropertyIds: propertyIds,
|
|
@@ -3463,6 +3773,30 @@ class Model {
|
|
|
3463
3773
|
async refreshProperties() {
|
|
3464
3774
|
await this._refreshPropertiesFromDb();
|
|
3465
3775
|
}
|
|
3776
|
+
/**
|
|
3777
|
+
* Refresh the property ids of every cached Model whose DB row is `dbId`. Called when a property
|
|
3778
|
+
* write for that model finishes: until then `properties` includes it as a pending write, and in Node
|
|
3779
|
+
* (no reactive liveQuery) nothing else adds it to `_liveQueryPropertyIds`.
|
|
3780
|
+
*/
|
|
3781
|
+
static async refreshPropertiesForDbId(dbId) {
|
|
3782
|
+
const instances = new Set();
|
|
3783
|
+
for (const { instance } of this.instanceCacheById.values())
|
|
3784
|
+
instances.add(instance);
|
|
3785
|
+
for (const { instance } of this.instanceCache.values())
|
|
3786
|
+
instances.add(instance);
|
|
3787
|
+
for (const instance of instances) {
|
|
3788
|
+
let context;
|
|
3789
|
+
try {
|
|
3790
|
+
context = instance._getSnapshotContext();
|
|
3791
|
+
}
|
|
3792
|
+
catch {
|
|
3793
|
+
continue;
|
|
3794
|
+
}
|
|
3795
|
+
if (context._dbId !== dbId)
|
|
3796
|
+
continue;
|
|
3797
|
+
await instance._refreshPropertiesFromDb();
|
|
3798
|
+
}
|
|
3799
|
+
}
|
|
3466
3800
|
}
|
|
3467
3801
|
// Primary cache: ID-based (never changes on rename)
|
|
3468
3802
|
Model.instanceCacheById = new Map();
|
|
@@ -3488,5 +3822,5 @@ var Model$1 = /*#__PURE__*/Object.freeze({
|
|
|
3488
3822
|
const TModelValues = Type.Record(Type.String(), Type.Any());
|
|
3489
3823
|
const TModelSchema = Type.Record(Type.String(), TProperty);
|
|
3490
3824
|
|
|
3491
|
-
export { ConflictError as C, Model as M, TModelSchema as T, TModelValues as a, Model$1 as
|
|
3492
|
-
//# sourceMappingURL=index-
|
|
3825
|
+
export { ConflictError as C, Model as M, TModelSchema as T, TModelValues as a, anyEvictionSince as b, currentEvictionEpoch as c, setupEntityLiveQuery as d, writeToDatabase$1 as e, Model$1 as f, isActorStopped as i, schemaEvictedSince as s, writeProcessMachine as w };
|
|
3826
|
+
//# sourceMappingURL=index-Y-yYyRBf.js.map
|