@seedprotocol/sdk 0.6.10 → 0.7.0
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-ndE8XTpw.js} +36 -2
- package/dist/BasePathResolver-ndE8XTpw.js.map +1 -0
- package/dist/ClientManager-DLleL_2e.js +4763 -0
- package/dist/ClientManager-DLleL_2e.js.map +1 -0
- package/dist/{ClientManager-ChcmUL47.js → Item-zBFWQDU9.js} +1119 -5893
- package/dist/Item-zBFWQDU9.js.map +1 -0
- package/dist/{ModelProperty-D79uV42p.js → ModelProperty-lth9L37R.js} +289 -101
- package/dist/ModelProperty-lth9L37R.js.map +1 -0
- package/dist/{Schema-a8uO-hIZ.js → Schema-DOhlrQ-N.js} +94 -864
- package/dist/Schema-DOhlrQ-N.js.map +1 -0
- package/dist/{SchemaValidationService-Y49vqast.js → SchemaValidationService-DDKr5piy.js} +26 -18
- package/dist/SchemaValidationService-DDKr5piy.js.map +1 -0
- package/dist/{backfillMetadataPropertyIds-CBsf7LnU.js → backfillMetadataPropertyIds-fG3ujaSh.js} +11 -6
- package/dist/backfillMetadataPropertyIds-fG3ujaSh.js.map +1 -0
- package/dist/cjs/{ModelProperty-D9FGaGuE.js → ModelProperty-BEsIHAjk.js} +260 -81
- package/dist/cjs/ModelProperty-BEsIHAjk.js.map +1 -0
- package/dist/cjs/{Schema-BiJIPLEL.js → Schema-qEp5mH1N.js} +66 -847
- package/dist/cjs/Schema-qEp5mH1N.js.map +1 -0
- package/dist/cjs/{SchemaValidationService-DtYs_CNY.js → SchemaValidationService-CWEnZmOH.js} +18 -11
- package/dist/cjs/SchemaValidationService-CWEnZmOH.js.map +1 -0
- package/dist/cjs/{backfillMetadataPropertyIds-2XaN3b9S.js → backfillMetadataPropertyIds-tw8JGMT0.js} +8 -3
- package/dist/cjs/backfillMetadataPropertyIds-tw8JGMT0.js.map +1 -0
- package/dist/cjs/{eas-CMNppmGE.js → eas-CLiV2Hmn.js} +4 -4
- package/dist/cjs/{eas-CMNppmGE.js.map → eas-CLiV2Hmn.js.map} +1 -1
- package/dist/cjs/{getItem-B6jEINjW.js → getItem-DSRtx_68.js} +2 -2
- package/dist/cjs/{getItem-B6jEINjW.js.map → getItem-DSRtx_68.js.map} +1 -1
- package/dist/cjs/getLatestVersionRow-DVizNNoI.js +59 -0
- package/dist/cjs/getLatestVersionRow-DVizNNoI.js.map +1 -0
- package/dist/cjs/{getPublishPayload-D5DhLGvN.js → getPublishPayload-D5-dYtNq.js} +249 -60
- package/dist/cjs/getPublishPayload-D5-dYtNq.js.map +1 -0
- package/dist/cjs/{getPublishUploads-DMhCCKYF.js → getPublishUploads-B5Lq6q-_.js} +20 -13
- package/dist/cjs/getPublishUploads-B5Lq6q-_.js.map +1 -0
- package/dist/cjs/{getSegmentedItemProperties-CU8rtBAo.js → getSegmentedItemProperties-giHO7R3d.js} +10 -11
- package/dist/cjs/getSegmentedItemProperties-giHO7R3d.js.map +1 -0
- package/dist/cjs/{index-DPp9rdRL.js → index-B3UDbm1C.js} +3 -3
- package/dist/cjs/index-B3UDbm1C.js.map +1 -0
- package/dist/cjs/{index-CSNtEnbF.js → index-C66AfYDG.js} +2510 -1694
- package/dist/cjs/index-C66AfYDG.js.map +1 -0
- package/dist/cjs/{property-DlKiAWt4.js → property-BVJIP7SX.js} +40 -35
- package/dist/cjs/property-BVJIP7SX.js.map +1 -0
- package/dist/cjs/resetAmbiguousLegacyItemData-BaZqUui9.js +116 -0
- package/dist/cjs/resetAmbiguousLegacyItemData-BaZqUui9.js.map +1 -0
- package/dist/cjs/resolveModelForSyncedSeed-CC6dQctx.js +49 -0
- package/dist/cjs/resolveModelForSyncedSeed-CC6dQctx.js.map +1 -0
- package/dist/cjs/syncDbWithEas-Dk96sAG-.js +873 -0
- package/dist/cjs/syncDbWithEas-Dk96sAG-.js.map +1 -0
- package/dist/{configurePlatform-CE0Vew17.js → configurePlatform-BMoPG9vY.js} +4 -4
- package/dist/{configurePlatform-CE0Vew17.js.map → configurePlatform-BMoPG9vY.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-BJZN0a0a.js} +546 -106
- package/dist/db-BJZN0a0a.js.map +1 -0
- package/dist/{eas-CfYCu4IX.js → eas-B0hsMLqt.js} +7 -7
- package/dist/eas-B0hsMLqt.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-DEh4WfHG.js} +8 -10
- package/dist/{getItem-Br-bGNFO.js.map → getItem-DEh4WfHG.js.map} +1 -1
- package/dist/getLatestVersionRow-Brrl1AnW.js +46 -0
- package/dist/getLatestVersionRow-Brrl1AnW.js.map +1 -0
- package/dist/{getPublishPayload-BIrTVUxb.js → getPublishPayload-H032DHC7.js} +263 -75
- package/dist/getPublishPayload-H032DHC7.js.map +1 -0
- package/dist/{getPublishUploads-C6cDeZdz.js → getPublishUploads-CR66RlGJ.js} +25 -17
- package/dist/{getPublishUploads-C6cDeZdz.js.map → getPublishUploads-CR66RlGJ.js.map} +1 -1
- package/dist/{getSegmentedItemProperties-BmKE71vU.js → getSegmentedItemProperties-C2EJ2G0N.js} +13 -14
- package/dist/getSegmentedItemProperties-C2EJ2G0N.js.map +1 -0
- package/dist/{index-ClSv5pTA.js → index-6bJuv5Tt.js} +12 -11
- package/dist/index-6bJuv5Tt.js.map +1 -0
- package/dist/{index-Djd3667v.js → index-B0LgJblD.js} +2 -2
- package/dist/index-B0LgJblD.js.map +1 -0
- package/dist/{index-HRHkbVQd.js → index-DtfjeuxC.js} +417 -174
- package/dist/index-DtfjeuxC.js.map +1 -0
- package/dist/index.browser-CNrqhvEA.js +4139 -0
- package/dist/index.browser-CNrqhvEA.js.map +1 -0
- package/dist/{index.node-DBtQkEfz.js → index.node-DrHiTuOr.js} +9 -4
- package/dist/index.node-DrHiTuOr.js.map +1 -0
- package/dist/main.cjs +1 -1
- package/dist/main.js +771 -521
- 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-D2Nnsmm1.js} +53 -48
- package/dist/property-D2Nnsmm1.js.map +1 -0
- package/dist/resetAmbiguousLegacyItemData-BqbHNUYk.js +88 -0
- package/dist/resetAmbiguousLegacyItemData-BqbHNUYk.js.map +1 -0
- package/dist/resolveModelForSyncedSeed-DQK6JfXS.js +46 -0
- package/dist/resolveModelForSyncedSeed-DQK6JfXS.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 +10 -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 +3 -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 +37 -0
- 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/modelMachine.d.ts +0 -8
- package/dist/src/Model/service/modelMachine.d.ts.map +1 -1
- package/dist/src/ModelProperty/ModelProperty.d.ts +33 -1
- 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/modelPropertyMachine.d.ts +2 -9
- package/dist/src/ModelProperty/service/modelPropertyMachine.d.ts.map +1 -1
- package/dist/src/Schema/Schema.d.ts +1 -2
- package/dist/src/Schema/Schema.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 +9 -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.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/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/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 +6 -0
- 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 +11 -2
- 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/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 +12 -3
- 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-LRKr_NZF.js +855 -0
- package/dist/syncDbWithEas-LRKr_NZF.js.map +1 -0
- package/dist/{index-280bL-n4.js → tabEvents-DYI2GU7i.js} +231 -68
- package/dist/tabEvents-DYI2GU7i.js.map +1 -0
- package/dist/tolerantWebAccess-CzOBz5M6.js +160 -0
- package/dist/tolerantWebAccess-CzOBz5M6.js.map +1 -0
- package/dist/updateSeedRevokedAt-B58ORbY3.js +32 -0
- package/dist/updateSeedRevokedAt-B58ORbY3.js.map +1 -0
- package/package.json +5 -5
- 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.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/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/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
|
@@ -0,0 +1,873 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var main_cjs = require('./index-C66AfYDG.js');
|
|
4
|
+
var resolveModelForSyncedSeed = require('./resolveModelForSyncedSeed-CC6dQctx.js');
|
|
5
|
+
var lodashEs = require('lodash-es');
|
|
6
|
+
var query = require('@seedprotocol/query');
|
|
7
|
+
var drizzleOrm = require('drizzle-orm');
|
|
8
|
+
var eas$1 = require('@seedprotocol/eas');
|
|
9
|
+
var pluralize = require('pluralize');
|
|
10
|
+
var eas = require('./eas-CLiV2Hmn.js');
|
|
11
|
+
require('immer');
|
|
12
|
+
require('reflect-metadata');
|
|
13
|
+
require('xstate');
|
|
14
|
+
require('drizzle-orm/sqlite-core');
|
|
15
|
+
require('debug');
|
|
16
|
+
require('@seedprotocol/arweave');
|
|
17
|
+
require('@sinclair/typebox');
|
|
18
|
+
require('drizzle-orm/casing');
|
|
19
|
+
require('nanoid');
|
|
20
|
+
require('nanoid-dictionary');
|
|
21
|
+
require('rxjs');
|
|
22
|
+
require('@noble/hashes/sha3');
|
|
23
|
+
require('@noble/hashes/utils');
|
|
24
|
+
require('fs/promises');
|
|
25
|
+
require('fs');
|
|
26
|
+
require('path');
|
|
27
|
+
require('url');
|
|
28
|
+
require('node:url');
|
|
29
|
+
require('@libsql/client');
|
|
30
|
+
require('drizzle-orm/libsql');
|
|
31
|
+
require('drizzle-orm/libsql/migrator');
|
|
32
|
+
require('js-yaml');
|
|
33
|
+
require('child_process');
|
|
34
|
+
require('@seedprotocol/arweave/node');
|
|
35
|
+
require('@seedprotocol/eas/node');
|
|
36
|
+
|
|
37
|
+
// Dynamic import to break circular dependency: Model -> BaseItem -> ... -> getModelSchemas -> Model
|
|
38
|
+
// import { Model } from '@/Model/Model'
|
|
39
|
+
const schemaStringToModelRecord = new Map();
|
|
40
|
+
const getModelSchemas = async () => {
|
|
41
|
+
// Dynamic import to break circular dependency
|
|
42
|
+
const modelMod = await Promise.resolve().then(function () { return require('./index-C66AfYDG.js'); }).then(function (n) { return n.Model$1; });
|
|
43
|
+
const { Model } = modelMod;
|
|
44
|
+
const allModels = await Model.all();
|
|
45
|
+
const modelRecords = [];
|
|
46
|
+
const appDb = main_cjs.BaseDb.getAppDb();
|
|
47
|
+
for (const model of allModels) {
|
|
48
|
+
const modelName = model.modelName;
|
|
49
|
+
if (!modelName)
|
|
50
|
+
continue;
|
|
51
|
+
const foundModelQuery = await appDb
|
|
52
|
+
.select({
|
|
53
|
+
id: main_cjs.models.id,
|
|
54
|
+
name: main_cjs.models.name,
|
|
55
|
+
uid: main_cjs.modelUids.uid,
|
|
56
|
+
})
|
|
57
|
+
.from(main_cjs.models)
|
|
58
|
+
.leftJoin(main_cjs.modelUids, drizzleOrm.eq(main_cjs.models.id, main_cjs.modelUids.modelId))
|
|
59
|
+
// Model names are only unique per schema: use this model's own row
|
|
60
|
+
.where(model.id ? drizzleOrm.eq(main_cjs.models.schemaFileId, model.id) : drizzleOrm.eq(main_cjs.models.name, modelName))
|
|
61
|
+
.limit(1);
|
|
62
|
+
if (!foundModelQuery[0]) {
|
|
63
|
+
console.error(`[item/events] [syncDbWithEas] model ${modelName} not found in SDK DB`);
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
const foundModel = {
|
|
67
|
+
id: foundModelQuery[0].id,
|
|
68
|
+
name: foundModelQuery[0].name,
|
|
69
|
+
uid: foundModelQuery[0].uid,
|
|
70
|
+
tableName: pluralize(foundModelQuery[0].name).toLowerCase(),
|
|
71
|
+
};
|
|
72
|
+
modelRecords.push(foundModel);
|
|
73
|
+
if (modelName === 'Seed') {
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
const schemaString = `bytes32 ${main_cjs.toSnakeCase(modelName)}`;
|
|
77
|
+
schemaStringToModelRecord.set(schemaString, foundModel);
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
schemaStringToModelRecord,
|
|
81
|
+
modelRecords,
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const createSeeds = async (newSeeds) => {
|
|
86
|
+
const appDb = main_cjs.BaseDb.getAppDb();
|
|
87
|
+
const values = newSeeds.map((row) => {
|
|
88
|
+
const publisher = main_cjs.normalizePublisher(row.publisher);
|
|
89
|
+
return {
|
|
90
|
+
...row,
|
|
91
|
+
...(publisher ? { publisher } : {}),
|
|
92
|
+
};
|
|
93
|
+
});
|
|
94
|
+
// Sync can create thousands of seeds at once: keep each INSERT under SQLite's parameter limit.
|
|
95
|
+
for (const chunk of main_cjs.chunkValues(values, main_cjs.rowsPerInsert(main_cjs.seeds))) {
|
|
96
|
+
await appDb.insert(main_cjs.seeds).values(chunk);
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Sets revokedAt timestamp on a seed record after attestations have been revoked on EAS.
|
|
102
|
+
*/
|
|
103
|
+
const updateSeedRevokedAt = async ({ seedLocalId, revokedAt, metadataUids, versionUids, }) => {
|
|
104
|
+
if (!seedLocalId) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const appDb = main_cjs.BaseDb.getAppDb();
|
|
108
|
+
await appDb
|
|
109
|
+
.update(main_cjs.seeds)
|
|
110
|
+
.set({
|
|
111
|
+
revokedAt,
|
|
112
|
+
updatedAt: Date.now(),
|
|
113
|
+
})
|
|
114
|
+
.where(drizzleOrm.eq(main_cjs.seeds.localId, seedLocalId));
|
|
115
|
+
// An item can have many property attestations; each list binds once per uid (twice for metadata).
|
|
116
|
+
await main_cjs.writeInBatches(metadataUids ?? [], (chunk) => appDb
|
|
117
|
+
.update(main_cjs.metadata)
|
|
118
|
+
.set({ revokedAt, updatedAt: Date.now() })
|
|
119
|
+
.where(drizzleOrm.and(drizzleOrm.or(drizzleOrm.inArray(main_cjs.metadata.uid, chunk), drizzleOrm.inArray(main_cjs.metadata.derivedFromUid, chunk)), drizzleOrm.isNull(main_cjs.metadata.revokedAt))));
|
|
120
|
+
await main_cjs.writeInBatches(versionUids ?? [], (chunk) => appDb
|
|
121
|
+
.update(main_cjs.versions)
|
|
122
|
+
.set({ revokedAt, updatedAt: Date.now() })
|
|
123
|
+
.where(drizzleOrm.and(drizzleOrm.inArray(main_cjs.versions.uid, chunk), drizzleOrm.isNull(main_cjs.versions.revokedAt))));
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Sync stores the newest non-revoked attestation per (version, property schema). When every
|
|
128
|
+
* attestation of a property is revoked (e.g. after `item.unpublish()`), keep the newest one so a
|
|
129
|
+
* revoked item synced to a new device still has its last values next to its seed's `revokedAt`.
|
|
130
|
+
*/
|
|
131
|
+
const SYNC_CANONICAL_OPTIONS = { ifAllRevoked: 'newestRevoked' };
|
|
132
|
+
/**
|
|
133
|
+
* When an attestation was revoked, in Unix seconds: EAS `revocationTime` is a block timestamp in
|
|
134
|
+
* seconds, the same unit local unpublish writes to `seeds.revoked_at`. `undefined` when not revoked.
|
|
135
|
+
* A revoked attestation without a revocation time (0 or not selected) falls back to now.
|
|
136
|
+
*/
|
|
137
|
+
const revokedAtSeconds = (attestation) => {
|
|
138
|
+
if (!attestation.revoked)
|
|
139
|
+
return undefined;
|
|
140
|
+
return attestation.revocationTime != null && attestation.revocationTime > 0
|
|
141
|
+
? attestation.revocationTime
|
|
142
|
+
: Math.floor(Date.now() / 1000);
|
|
143
|
+
};
|
|
144
|
+
/**
|
|
145
|
+
* `revoked_at` to store for an attestation that already has a row (seed, version or metadata), given the
|
|
146
|
+
* stored value. EAS's `revocationTime` wins once EAS reports one. A stored stamp is otherwise kept:
|
|
147
|
+
* local unpublish writes one only after its revoke transactions are mined, and revocation can't be
|
|
148
|
+
* undone, so EAS reporting the attestation as live then just means its index hasn't caught up yet.
|
|
149
|
+
*/
|
|
150
|
+
const syncedRevokedAt = (attestation, stored) => {
|
|
151
|
+
if (attestation.revoked && attestation.revocationTime != null && attestation.revocationTime > 0) {
|
|
152
|
+
return attestation.revocationTime;
|
|
153
|
+
}
|
|
154
|
+
return stored ?? revokedAtSeconds(attestation) ?? null;
|
|
155
|
+
};
|
|
156
|
+
const relationValuesToExclude = [
|
|
157
|
+
'0x0000000000000000000000000000000000000000000000000000000000000020',
|
|
158
|
+
];
|
|
159
|
+
const createSyncRunState = () => ({
|
|
160
|
+
seedUidToLocalId: new Map(),
|
|
161
|
+
seedUidToModelType: new Map(),
|
|
162
|
+
versionUidToLocalId: new Map(),
|
|
163
|
+
versionUidToSeedUid: new Map(),
|
|
164
|
+
relatedSeedUids: new Set(),
|
|
165
|
+
});
|
|
166
|
+
const isRelationPropertyName = (propertyNameSnake) => (propertyNameSnake.endsWith('_id') || propertyNameSnake.endsWith('_ids')) &&
|
|
167
|
+
propertyNameSnake !== 'storage_transaction_id' &&
|
|
168
|
+
propertyNameSnake !== 'storage_provider_transaction_id';
|
|
169
|
+
/**
|
|
170
|
+
* Seed UIDs that relation properties point at. Collected from every property the run fetched, not
|
|
171
|
+
* only newly stored ones, so related seeds are refreshed (new versions, revocations) on each sync.
|
|
172
|
+
*/
|
|
173
|
+
const collectRelatedSeedUids = (properties, into) => {
|
|
174
|
+
for (const property of properties) {
|
|
175
|
+
const parsed = query.parseEasPropertyMetadata(property.decodedDataJson);
|
|
176
|
+
if (!parsed.ok)
|
|
177
|
+
continue;
|
|
178
|
+
const { name, value } = parsed.metadata;
|
|
179
|
+
if (!name || !isRelationPropertyName(name))
|
|
180
|
+
continue;
|
|
181
|
+
const values = Array.isArray(value) ? value : [value];
|
|
182
|
+
for (const v of values) {
|
|
183
|
+
if (typeof v === 'string' && v && !relationValuesToExclude.includes(v))
|
|
184
|
+
into.add(v);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
/**
|
|
189
|
+
* Earlier syncs SQL-escaped a seed's attestation JSON (`'` -> `''`) and then bound it as a
|
|
190
|
+
* parameter, so stored `seeds.attestation_raw` had every quote doubled. Doubled JSON still parses,
|
|
191
|
+
* so a legacy row is recognized by comparing with the attestation EAS returns now: it is legacy
|
|
192
|
+
* when it equals that attestation with quotes doubled, ignoring the revocation fields (EAS may have
|
|
193
|
+
* revoked it since). A row whose data legitimately contains `''` equals the fresh JSON itself and is
|
|
194
|
+
* left alone.
|
|
195
|
+
*/
|
|
196
|
+
const isSqlEscapedAttestationRaw = (stored, fresh) => {
|
|
197
|
+
if (!stored.includes("''"))
|
|
198
|
+
return false;
|
|
199
|
+
const freshJson = JSON.stringify(fresh);
|
|
200
|
+
if (stored === freshJson || !freshJson.includes("'"))
|
|
201
|
+
return false;
|
|
202
|
+
let parsed;
|
|
203
|
+
try {
|
|
204
|
+
parsed = JSON.parse(stored);
|
|
205
|
+
}
|
|
206
|
+
catch {
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
if (!parsed || typeof parsed !== 'object')
|
|
210
|
+
return false;
|
|
211
|
+
const stored_ = parsed;
|
|
212
|
+
const withStoredRevocation = {
|
|
213
|
+
...fresh,
|
|
214
|
+
...('revoked' in stored_ && { revoked: stored_.revoked }),
|
|
215
|
+
...('revocationTime' in stored_ && { revocationTime: stored_.revocationTime }),
|
|
216
|
+
};
|
|
217
|
+
return stored === JSON.stringify(withStoredRevocation).replace(/'/g, "''");
|
|
218
|
+
};
|
|
219
|
+
const saveEasSeedsToDb = async ({ itemSeeds, state }) => {
|
|
220
|
+
const { seedUidToLocalId, seedUidToModelType } = state;
|
|
221
|
+
const appDb = main_cjs.BaseDb.getAppDb();
|
|
222
|
+
const seedUids = itemSeeds.map((seed) => seed.id);
|
|
223
|
+
const existingSeedRecordsRows = await main_cjs.selectInBatches(seedUids, (chunk) => appDb.select().from(main_cjs.seeds).where(drizzleOrm.inArray(main_cjs.seeds.uid, chunk)));
|
|
224
|
+
const existingSeedUids = new Set();
|
|
225
|
+
if (existingSeedRecordsRows && existingSeedRecordsRows.length > 0) {
|
|
226
|
+
for (const row of existingSeedRecordsRows) {
|
|
227
|
+
if (row.uid) {
|
|
228
|
+
existingSeedUids.add(row.uid);
|
|
229
|
+
if (row.localId) {
|
|
230
|
+
seedUidToLocalId.set(row.uid, row.localId);
|
|
231
|
+
}
|
|
232
|
+
if (row.type) {
|
|
233
|
+
seedUidToModelType.set(row.uid, row.type);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
const newSeeds = itemSeeds.filter((seed) => !existingSeedUids.has(seed.id));
|
|
239
|
+
// Update existing seeds when attestations are revoked on EAS, and replace a local unpublish stamp
|
|
240
|
+
// with EAS's revocationTime once EAS reports one (see `syncedRevokedAt`).
|
|
241
|
+
const seedByUid = new Map(itemSeeds.map((s) => [s.id, s]));
|
|
242
|
+
for (const row of existingSeedRecordsRows) {
|
|
243
|
+
if (!row.uid || !row.localId)
|
|
244
|
+
continue;
|
|
245
|
+
const attestation = seedByUid.get(row.uid);
|
|
246
|
+
if (!attestation)
|
|
247
|
+
continue;
|
|
248
|
+
const revokedAt = syncedRevokedAt(attestation, row.revokedAt);
|
|
249
|
+
if (revokedAt == null || revokedAt === row.revokedAt)
|
|
250
|
+
continue;
|
|
251
|
+
await updateSeedRevokedAt({ seedLocalId: row.localId, revokedAt });
|
|
252
|
+
}
|
|
253
|
+
// Repair seed rows an earlier sync stored with SQL-escaped (doubled) quotes.
|
|
254
|
+
for (const row of existingSeedRecordsRows) {
|
|
255
|
+
if (!row.uid || !row.attestationRaw)
|
|
256
|
+
continue;
|
|
257
|
+
const attestation = seedByUid.get(row.uid);
|
|
258
|
+
if (!attestation || !isSqlEscapedAttestationRaw(row.attestationRaw, attestation))
|
|
259
|
+
continue;
|
|
260
|
+
await appDb
|
|
261
|
+
.update(main_cjs.seeds)
|
|
262
|
+
.set({ attestationRaw: JSON.stringify(attestation) })
|
|
263
|
+
.where(drizzleOrm.eq(main_cjs.seeds.uid, row.uid));
|
|
264
|
+
}
|
|
265
|
+
if (newSeeds.length === 0) {
|
|
266
|
+
return { seedUids };
|
|
267
|
+
}
|
|
268
|
+
const newSeedsData = [];
|
|
269
|
+
for (let i = 0; i < newSeeds.length; i++) {
|
|
270
|
+
const seed = newSeeds[i];
|
|
271
|
+
seedUidToModelType.set(seed.id, seed.schema.schemaNames[0].name);
|
|
272
|
+
const seedLocalId = main_cjs.generateId();
|
|
273
|
+
seedUidToLocalId.set(seed.id, seedLocalId);
|
|
274
|
+
// createSeeds binds parameters: store the JSON as is.
|
|
275
|
+
const attestationRaw = JSON.stringify(seed);
|
|
276
|
+
const revokedAt = revokedAtSeconds(seed);
|
|
277
|
+
// EAS only knows the model by name; the seam may match it to a local model (not built yet).
|
|
278
|
+
const modelFileId = await resolveModelForSyncedSeed.resolveModelForSyncedSeed({
|
|
279
|
+
seedUid: seed.id,
|
|
280
|
+
modelType: seed.schema.schemaNames[0].name,
|
|
281
|
+
schemaUid: seed.schemaId,
|
|
282
|
+
});
|
|
283
|
+
newSeedsData.push({
|
|
284
|
+
localId: seedLocalId,
|
|
285
|
+
uid: seed.id,
|
|
286
|
+
schemaUid: seed.schemaId,
|
|
287
|
+
type: seed.schema.schemaNames[0].name,
|
|
288
|
+
...(modelFileId && { modelFileId }),
|
|
289
|
+
publisher: seed.attester ? main_cjs.normalizeHexAddress(seed.attester) : seed.attester,
|
|
290
|
+
createdAt: Date.now(),
|
|
291
|
+
attestationCreatedAt: seed.timeCreated * 1000,
|
|
292
|
+
attestationRaw,
|
|
293
|
+
...(revokedAt !== undefined && { revokedAt }),
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
await createSeeds(newSeedsData);
|
|
297
|
+
// All fetched seeds, not only the new ones: existing seeds can have new versions on EAS.
|
|
298
|
+
return { seedUids };
|
|
299
|
+
};
|
|
300
|
+
/**
|
|
301
|
+
* Rows per versions INSERT. A row binds at most one parameter per `versions` column (12 today, 10
|
|
302
|
+
* set by sync), so a batch binds at most 600: under SQLite's old default limit of 999 host
|
|
303
|
+
* parameters (sqlite-wasm and libsql allow more). saveEasVersionsBatches.test.ts checks this.
|
|
304
|
+
*/
|
|
305
|
+
const VERSION_INSERT_BATCH = 50;
|
|
306
|
+
const saveEasVersionsToDb = async ({ itemVersions, state }) => {
|
|
307
|
+
const { seedUidToLocalId, seedUidToModelType, versionUidToLocalId, versionUidToSeedUid } = state;
|
|
308
|
+
const versionUids = itemVersions.map((version) => version.id);
|
|
309
|
+
const appDb = main_cjs.BaseDb.getAppDb();
|
|
310
|
+
const existingVersionRecordsRows = await main_cjs.selectInBatches(versionUids, (chunk) => appDb.select().from(main_cjs.versions).where(drizzleOrm.inArray(main_cjs.versions.uid, chunk)));
|
|
311
|
+
const existingVersionUids = new Set();
|
|
312
|
+
const versionByUid = new Map(itemVersions.map((version) => [version.id, version]));
|
|
313
|
+
if (existingVersionRecordsRows && existingVersionRecordsRows.length > 0) {
|
|
314
|
+
for (const row of existingVersionRecordsRows) {
|
|
315
|
+
if (row.uid) {
|
|
316
|
+
existingVersionUids.add(row.uid);
|
|
317
|
+
if (row.localId) {
|
|
318
|
+
versionUidToLocalId.set(row.uid, row.localId);
|
|
319
|
+
}
|
|
320
|
+
if (row.seedUid) {
|
|
321
|
+
versionUidToSeedUid.set(row.uid, row.seedUid);
|
|
322
|
+
}
|
|
323
|
+
// Already-stored versions pick up revocations (and EAS's revocation time) too.
|
|
324
|
+
const attestation = versionByUid.get(row.uid);
|
|
325
|
+
const revokedAt = attestation ? syncedRevokedAt(attestation, row.revokedAt) : null;
|
|
326
|
+
if (attestation && revokedAt !== (row.revokedAt ?? null)) {
|
|
327
|
+
await appDb
|
|
328
|
+
.update(main_cjs.versions)
|
|
329
|
+
.set({ revokedAt, updatedAt: Date.now() })
|
|
330
|
+
.where(drizzleOrm.eq(main_cjs.versions.uid, row.uid));
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
const newVersions = itemVersions.filter((version) => !existingVersionUids.has(version.id));
|
|
336
|
+
const rows = [];
|
|
337
|
+
const storedVersionUids = new Set(existingVersionUids);
|
|
338
|
+
for (const version of newVersions) {
|
|
339
|
+
const seedUid = version.refUID;
|
|
340
|
+
const seedLocalId = seedUidToLocalId.get(seedUid);
|
|
341
|
+
if (!seedLocalId) {
|
|
342
|
+
// Storing it anyway would orphan the version (and its properties) from any local seed.
|
|
343
|
+
console.warn('[item/events] [syncDbWithEas] skipping version whose seed has no local id: ', version.id, seedUid);
|
|
344
|
+
continue;
|
|
345
|
+
}
|
|
346
|
+
const versionLocalId = main_cjs.generateId();
|
|
347
|
+
versionUidToSeedUid.set(version.id, seedUid);
|
|
348
|
+
versionUidToLocalId.set(version.id, versionLocalId);
|
|
349
|
+
storedVersionUids.add(version.id);
|
|
350
|
+
rows.push({
|
|
351
|
+
localId: versionLocalId,
|
|
352
|
+
uid: version.id,
|
|
353
|
+
seedUid,
|
|
354
|
+
seedLocalId,
|
|
355
|
+
seedType: seedUidToModelType.get(seedUid) ?? null,
|
|
356
|
+
createdAt: Date.now(),
|
|
357
|
+
attestationCreatedAt: version.timeCreated * 1000,
|
|
358
|
+
attestationRaw: JSON.stringify(version),
|
|
359
|
+
publisher: version.attester ? main_cjs.normalizeHexAddress(version.attester) : '',
|
|
360
|
+
revokedAt: revokedAtSeconds(version) ?? null,
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
// Bound parameters: keep each statement well under SQLite's host-parameter limit.
|
|
364
|
+
for (let i = 0; i < rows.length; i += VERSION_INSERT_BATCH) {
|
|
365
|
+
await appDb.insert(main_cjs.versions).values(rows.slice(i, i + VERSION_INSERT_BATCH));
|
|
366
|
+
}
|
|
367
|
+
// Only versions that are stored locally: properties of a skipped version would have no version row.
|
|
368
|
+
return { versionUids: versionUids.filter((uid) => storedVersionUids.has(uid)) };
|
|
369
|
+
};
|
|
370
|
+
const createMetadataRecordsForStorageTransactionId = async (storageTransactionIdProperty, modelSchema, state) => {
|
|
371
|
+
const { seedUidToLocalId, seedUidToModelType, versionUidToLocalId, versionUidToSeedUid } = state;
|
|
372
|
+
// Validate and parse decodedDataJson
|
|
373
|
+
const parsed = query.parseEasPropertyMetadata(storageTransactionIdProperty.decodedDataJson);
|
|
374
|
+
if (!parsed.ok) {
|
|
375
|
+
if (parsed.reason === 'empty') {
|
|
376
|
+
console.warn('[item/events] [syncDbWithEas] empty decodedDataJson for storageTransactionIdProperty: ', storageTransactionIdProperty.id);
|
|
377
|
+
}
|
|
378
|
+
else if (parsed.reason === 'parse') {
|
|
379
|
+
console.warn('[item/events] [syncDbWithEas] failed to parse decodedDataJson for storageTransactionIdProperty: ', storageTransactionIdProperty.id, parsed.error);
|
|
380
|
+
}
|
|
381
|
+
else {
|
|
382
|
+
console.warn('[item/events] [syncDbWithEas] invalid decodedDataJson structure for storageTransactionIdProperty: ', storageTransactionIdProperty.id);
|
|
383
|
+
}
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
const attestationData = parsed.metadata;
|
|
387
|
+
lodashEs.camelCase(attestationData.name);
|
|
388
|
+
const propertyValue = typeof attestationData.value === 'string'
|
|
389
|
+
? attestationData.value
|
|
390
|
+
: JSON.stringify(attestationData.value);
|
|
391
|
+
const seedUid = versionUidToSeedUid.get(storageTransactionIdProperty.refUID);
|
|
392
|
+
const seedLocalId = seedUidToLocalId.get(seedUid);
|
|
393
|
+
const versionUid = storageTransactionIdProperty.refUID;
|
|
394
|
+
const versionLocalId = versionUidToLocalId.get(versionUid);
|
|
395
|
+
const modelType = seedUidToModelType.get(seedUid);
|
|
396
|
+
// Storage settings come from the `properties` table. The model's property instances (modelSchema)
|
|
397
|
+
// are only a fallback: whether they have loaded, and with storage settings, depends on timing.
|
|
398
|
+
const itemStorageProperties = new Map();
|
|
399
|
+
if (modelType != null) {
|
|
400
|
+
const stored = (await resolveModelForSyncedSeed.skipSeedOnAmbiguousModel({ seedLocalId, seedUid }, 'easSync.storageTransactionId', async () => main_cjs.getItemStoragePropertiesForModel(modelType, {
|
|
401
|
+
modelFileId: await main_cjs.resolveItemModelFileId({ seedLocalId, seedUid }),
|
|
402
|
+
}))) ?? [];
|
|
403
|
+
for (const property of stored)
|
|
404
|
+
itemStorageProperties.set(property.name, property);
|
|
405
|
+
}
|
|
406
|
+
if (itemStorageProperties.size === 0 && modelSchema) {
|
|
407
|
+
for (const [_propertyName, propertyDef] of Object.entries(modelSchema)) {
|
|
408
|
+
if (propertyDef?.storageType === 'ItemStorage') {
|
|
409
|
+
itemStorageProperties.set(_propertyName, {
|
|
410
|
+
localStorageDir: propertyDef.localStorageDir,
|
|
411
|
+
filenameSuffix: propertyDef.filenameSuffix,
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
if (itemStorageProperties.size === 0) {
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
const appDb = main_cjs.BaseDb.getAppDb();
|
|
420
|
+
for (const [_propertyName, propertyDef] of itemStorageProperties.entries()) {
|
|
421
|
+
const existingMetadataRecordRows = await appDb
|
|
422
|
+
.select({ localId: main_cjs.metadata.localId })
|
|
423
|
+
.from(main_cjs.metadata)
|
|
424
|
+
.where(drizzleOrm.and(drizzleOrm.isNotNull(main_cjs.metadata.derivedFromUid), drizzleOrm.eq(main_cjs.metadata.propertyName, _propertyName), drizzleOrm.eq(main_cjs.metadata.propertyValue, propertyValue), drizzleOrm.eq(main_cjs.metadata.versionUid, storageTransactionIdProperty.refUID)));
|
|
425
|
+
// Already derived from another attestation carrying this transaction id: syncDerivedStorageRows
|
|
426
|
+
// points that row at the canonical attestation.
|
|
427
|
+
if (existingMetadataRecordRows && existingMetadataRecordRows.length > 0) {
|
|
428
|
+
continue;
|
|
429
|
+
}
|
|
430
|
+
const propertyId = propertyDef.id ??
|
|
431
|
+
(modelType != null
|
|
432
|
+
? ((await resolveModelForSyncedSeed.skipSeedOnAmbiguousModel({ seedLocalId, seedUid }, 'easSync.storageTransactionId', async () => main_cjs.getPropertyIdForModelAndName(modelType, _propertyName, {
|
|
433
|
+
modelFileId: await main_cjs.resolveItemModelFileId({ seedLocalId, seedUid }),
|
|
434
|
+
}))) ?? null)
|
|
435
|
+
: null);
|
|
436
|
+
const propertyLocalId = main_cjs.generateId();
|
|
437
|
+
await appDb.insert(main_cjs.metadata).values({
|
|
438
|
+
localId: propertyLocalId,
|
|
439
|
+
propertyId: propertyId ?? undefined,
|
|
440
|
+
propertyName: _propertyName,
|
|
441
|
+
propertyValue,
|
|
442
|
+
localStorageDir: propertyDef.localStorageDir ?? undefined,
|
|
443
|
+
seedLocalId,
|
|
444
|
+
seedUid,
|
|
445
|
+
versionLocalId,
|
|
446
|
+
versionUid,
|
|
447
|
+
refValueType: 'file',
|
|
448
|
+
refResolvedValue: `${propertyValue}${propertyDef.filenameSuffix ?? ''}`,
|
|
449
|
+
modelType: seedUidToModelType.get(seedUid),
|
|
450
|
+
derivedFromUid: storageTransactionIdProperty.id,
|
|
451
|
+
// Ranked like a synced row, at its attestation's time: a local edit made after that
|
|
452
|
+
// publish wins over it, a newer publish wins over an older edit.
|
|
453
|
+
attestationCreatedAt: storageTransactionIdProperty.timeCreated * 1000,
|
|
454
|
+
createdAt: Date.now(),
|
|
455
|
+
updatedAt: Date.now(),
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
};
|
|
459
|
+
/** Serialize property saves: concurrent `runSyncFromEas` used to hit `isSavingToDb` and return `{}` with no insert. */
|
|
460
|
+
let saveEasPropertiesDbChain = Promise.resolve();
|
|
461
|
+
/**
|
|
462
|
+
* Make local metadata match EAS for every fetched (version, property schema): exactly one synced
|
|
463
|
+
* row, for the canonical attestation (ADR 0006), with `revoked_at` set when that attestation is
|
|
464
|
+
* revoked (which, with `SYNC_CANONICAL_OPTIONS`, means all of the property's attestations on that
|
|
465
|
+
* version are).
|
|
466
|
+
*
|
|
467
|
+
* - Canonical attestation not stored yet: insert it. This also covers an older live attestation
|
|
468
|
+
* taking over from a revoked newer one, and a newer attestation superseding the stored one.
|
|
469
|
+
* - Stored row for a fetched attestation that isn't canonical (revoked, or superseded): delete it,
|
|
470
|
+
* so readers, which take the newest row per property, can't pick it.
|
|
471
|
+
* - Stored canonical row: bring `revoked_at` up to date.
|
|
472
|
+
*
|
|
473
|
+
* Rows without an attestation UID (local edits) and rows for attestations EAS didn't return are
|
|
474
|
+
* left alone.
|
|
475
|
+
*/
|
|
476
|
+
const saveEasPropertiesToDbBody = async ({ fetchedProperties, itemSeeds, state, }) => {
|
|
477
|
+
const itemProperties = eas$1.pickLatestPropertyAttestationsByRefAndSchema(fetchedProperties, SYNC_CANONICAL_OPTIONS);
|
|
478
|
+
const propertyUids = itemProperties.map((property) => property.id);
|
|
479
|
+
collectRelatedSeedUids(itemProperties, state.relatedSeedUids);
|
|
480
|
+
const appDb = main_cjs.BaseDb.getAppDb();
|
|
481
|
+
const storedRows = await main_cjs.selectInBatches(fetchedProperties.map((property) => property.id), (chunk) => appDb
|
|
482
|
+
.select({ uid: main_cjs.metadata.uid, revokedAt: main_cjs.metadata.revokedAt })
|
|
483
|
+
.from(main_cjs.metadata)
|
|
484
|
+
.where(drizzleOrm.inArray(main_cjs.metadata.uid, chunk)));
|
|
485
|
+
const canonicalByUid = new Map(itemProperties.map((property) => [property.id, property]));
|
|
486
|
+
const existingPropertyRecordsUids = new Set();
|
|
487
|
+
const staleUids = new Set();
|
|
488
|
+
const revokedAtUpdates = new Map();
|
|
489
|
+
for (const row of storedRows) {
|
|
490
|
+
if (!row.uid)
|
|
491
|
+
continue;
|
|
492
|
+
const canonical = canonicalByUid.get(row.uid);
|
|
493
|
+
if (!canonical) {
|
|
494
|
+
staleUids.add(row.uid);
|
|
495
|
+
continue;
|
|
496
|
+
}
|
|
497
|
+
existingPropertyRecordsUids.add(row.uid);
|
|
498
|
+
// Same policy as seeds and versions: a local unpublish stamp stays until EAS reports a
|
|
499
|
+
// revocationTime, even while EAS (its index lagging) still reports the attestation live.
|
|
500
|
+
const revokedAt = syncedRevokedAt(canonical, row.revokedAt);
|
|
501
|
+
if ((row.revokedAt ?? null) !== revokedAt) {
|
|
502
|
+
revokedAtUpdates.set(row.uid, revokedAt);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
const newProperties = itemProperties.filter((property) => !existingPropertyRecordsUids.has(property.id));
|
|
506
|
+
// Insert before deleting, so a property never goes without a row in between.
|
|
507
|
+
if (newProperties.length > 0) {
|
|
508
|
+
await insertSyncedProperties({ newProperties, itemSeeds, state });
|
|
509
|
+
}
|
|
510
|
+
if (staleUids.size > 0) {
|
|
511
|
+
await main_cjs.writeInBatches([...staleUids], (chunk) => appDb.delete(main_cjs.metadata).where(drizzleOrm.inArray(main_cjs.metadata.uid, chunk)));
|
|
512
|
+
}
|
|
513
|
+
for (const [uid, revokedAt] of revokedAtUpdates) {
|
|
514
|
+
await appDb
|
|
515
|
+
.update(main_cjs.metadata)
|
|
516
|
+
.set({ revokedAt, updatedAt: Date.now() })
|
|
517
|
+
.where(drizzleOrm.eq(main_cjs.metadata.uid, uid));
|
|
518
|
+
}
|
|
519
|
+
await syncDerivedStorageRows({ fetchedProperties, canonicalProperties: itemProperties });
|
|
520
|
+
return { propertyUids };
|
|
521
|
+
};
|
|
522
|
+
/** The transaction id a `storage_transaction_id` attestation carries; undefined for other properties. */
|
|
523
|
+
const storageTransactionIdOf = (property) => {
|
|
524
|
+
const parsed = query.parseEasPropertyMetadata(property.decodedDataJson);
|
|
525
|
+
if (!parsed.ok || parsed.metadata.name !== 'storage_transaction_id')
|
|
526
|
+
return undefined;
|
|
527
|
+
const { value } = parsed.metadata;
|
|
528
|
+
// Same serialization as the derived rows' property_value.
|
|
529
|
+
return typeof value === 'string' ? value : JSON.stringify(value);
|
|
530
|
+
};
|
|
531
|
+
/**
|
|
532
|
+
* Make derived ItemStorage rows follow their `storage_transaction_id` attestation the way synced
|
|
533
|
+
* rows follow theirs. Derived rows are identified by `derived_from_uid`, the attestation they were
|
|
534
|
+
* derived from:
|
|
535
|
+
* - A row derived from another fetched attestation with the canonical one's transaction id (on the
|
|
536
|
+
* same version) is pointed at the canonical one; creation makes one row per transaction id.
|
|
537
|
+
* - Rows derived from a fetched attestation that isn't canonical are deleted.
|
|
538
|
+
* - Rows derived from the canonical one take its `revoked_at` once it has one (a stamp is never
|
|
539
|
+
* cleared, see `syncedRevokedAt`).
|
|
540
|
+
* Local drafts (no uid, no `derived_from_uid`) are never touched.
|
|
541
|
+
*/
|
|
542
|
+
const syncDerivedStorageRows = async ({ fetchedProperties, canonicalProperties, }) => {
|
|
543
|
+
const canonical = canonicalProperties
|
|
544
|
+
.map((property) => ({ property, transactionId: storageTransactionIdOf(property) }))
|
|
545
|
+
.filter((c) => !!c.transactionId);
|
|
546
|
+
const canonicalUids = new Set(canonicalProperties.map((property) => property.id));
|
|
547
|
+
const appDb = main_cjs.BaseDb.getAppDb();
|
|
548
|
+
for (const { property, transactionId } of canonical) {
|
|
549
|
+
const sameTransaction = fetchedProperties
|
|
550
|
+
.filter((other) => other.id !== property.id &&
|
|
551
|
+
other.refUID === property.refUID &&
|
|
552
|
+
storageTransactionIdOf(other) === transactionId)
|
|
553
|
+
.map((other) => other.id);
|
|
554
|
+
if (sameTransaction.length === 0)
|
|
555
|
+
continue;
|
|
556
|
+
// A stamp belongs to the attestation it came from; the new source's is applied below.
|
|
557
|
+
await main_cjs.writeInBatches(sameTransaction, (chunk) => appDb
|
|
558
|
+
.update(main_cjs.metadata)
|
|
559
|
+
.set({
|
|
560
|
+
derivedFromUid: property.id,
|
|
561
|
+
revokedAt: null,
|
|
562
|
+
attestationCreatedAt: property.timeCreated * 1000,
|
|
563
|
+
updatedAt: Date.now(),
|
|
564
|
+
})
|
|
565
|
+
.where(drizzleOrm.inArray(main_cjs.metadata.derivedFromUid, chunk)));
|
|
566
|
+
}
|
|
567
|
+
const staleSourceUids = fetchedProperties
|
|
568
|
+
.filter((property) => !canonicalUids.has(property.id) && storageTransactionIdOf(property))
|
|
569
|
+
.map((property) => property.id);
|
|
570
|
+
if (staleSourceUids.length > 0) {
|
|
571
|
+
await main_cjs.writeInBatches(staleSourceUids, (chunk) => appDb.delete(main_cjs.metadata).where(drizzleOrm.inArray(main_cjs.metadata.derivedFromUid, chunk)));
|
|
572
|
+
}
|
|
573
|
+
if (canonical.length === 0)
|
|
574
|
+
return;
|
|
575
|
+
// The canonical rows' revoked_at as just stored (the saves above already applied EAS's state).
|
|
576
|
+
const sourceRows = await main_cjs.selectInBatches(canonical.map((c) => c.property.id), (chunk) => appDb
|
|
577
|
+
.select({ uid: main_cjs.metadata.uid, revokedAt: main_cjs.metadata.revokedAt })
|
|
578
|
+
.from(main_cjs.metadata)
|
|
579
|
+
.where(drizzleOrm.inArray(main_cjs.metadata.uid, chunk)));
|
|
580
|
+
const revokedAtByUid = new Map(sourceRows.map((row) => [row.uid, row.revokedAt ?? null]));
|
|
581
|
+
for (const { property } of canonical) {
|
|
582
|
+
const revokedAt = revokedAtByUid.get(property.id) ?? null;
|
|
583
|
+
// The source's revoked_at already follows `syncedRevokedAt`. A live source leaves a derived
|
|
584
|
+
// row's stamp alone: like a stamped synced row, it is only replaced by a revocation time.
|
|
585
|
+
if (revokedAt == null)
|
|
586
|
+
continue;
|
|
587
|
+
await appDb
|
|
588
|
+
.update(main_cjs.metadata)
|
|
589
|
+
.set({ revokedAt, updatedAt: Date.now() })
|
|
590
|
+
.where(drizzleOrm.and(drizzleOrm.eq(main_cjs.metadata.derivedFromUid, property.id), drizzleOrm.or(drizzleOrm.isNull(main_cjs.metadata.revokedAt), drizzleOrm.ne(main_cjs.metadata.revokedAt, revokedAt))));
|
|
591
|
+
}
|
|
592
|
+
};
|
|
593
|
+
/**
|
|
594
|
+
* The cached Model of a synced seed: its own model (seeds.model_file_id) when it has one, else by
|
|
595
|
+
* EAS schema name, the snake_case model name (`sync_storage_post` → SyncStoragePost; a
|
|
596
|
+
* `startCase` lookup never matched multi-word names). Throws AmbiguousModelError when several
|
|
597
|
+
* schemas define a model with that name; callers skip the seed (skipSeedOnAmbiguousModel).
|
|
598
|
+
*/
|
|
599
|
+
const resolveSyncedSeedModel = async (Model, modelType, seed) => {
|
|
600
|
+
const modelFileId = await main_cjs.resolveItemModelFileId(seed);
|
|
601
|
+
return (modelFileId ? Model.getById(modelFileId) : undefined) ?? Model.findByModelType(modelType);
|
|
602
|
+
};
|
|
603
|
+
const insertSyncedProperties = async ({ newProperties, itemSeeds, state, }) => {
|
|
604
|
+
const { seedUidToLocalId, seedUidToModelType, versionUidToLocalId, versionUidToSeedUid } = state;
|
|
605
|
+
// Dynamic import to break circular dependency
|
|
606
|
+
const modelMod = await Promise.resolve().then(function () { return require('./index-C66AfYDG.js'); }).then(function (n) { return n.Model$1; });
|
|
607
|
+
const { Model } = modelMod;
|
|
608
|
+
// Loads every model into Model's cache, where resolveSyncedSeedModel looks them up.
|
|
609
|
+
await Model.all();
|
|
610
|
+
const appDb = main_cjs.BaseDb.getAppDb();
|
|
611
|
+
// Bound as parameters, in batches of rowsPerInsert(metadata) rows, so no statement exceeds
|
|
612
|
+
// SQLite's parameter or statement-length limits however many properties a sync stores.
|
|
613
|
+
const rows = [];
|
|
614
|
+
for (const property of newProperties) {
|
|
615
|
+
const propertyLocalId = main_cjs.generateId();
|
|
616
|
+
// Validate and parse decodedDataJson
|
|
617
|
+
const parsed = query.parseEasPropertyMetadata(property.decodedDataJson);
|
|
618
|
+
if (!parsed.ok) {
|
|
619
|
+
if (parsed.reason === 'empty') {
|
|
620
|
+
console.warn('[item/events] [syncDbWithEas] empty decodedDataJson for property: ', property.id);
|
|
621
|
+
}
|
|
622
|
+
else if (parsed.reason === 'parse') {
|
|
623
|
+
console.warn('[item/events] [syncDbWithEas] failed to parse decodedDataJson for property: ', property.id, parsed.error);
|
|
624
|
+
}
|
|
625
|
+
else {
|
|
626
|
+
console.warn('[item/events] [syncDbWithEas] invalid decodedDataJson structure for property: ', property.id);
|
|
627
|
+
}
|
|
628
|
+
continue;
|
|
629
|
+
}
|
|
630
|
+
const propertyMetadata = parsed.metadata;
|
|
631
|
+
let propertyNameSnake = propertyMetadata.name;
|
|
632
|
+
if (!propertyNameSnake) {
|
|
633
|
+
console.warn('[item/events] [syncDbWithEas] no propertyName found for property: ', property);
|
|
634
|
+
continue;
|
|
635
|
+
}
|
|
636
|
+
let isRelation = false;
|
|
637
|
+
let refValueType;
|
|
638
|
+
let refSeedType;
|
|
639
|
+
let refSchemaUid;
|
|
640
|
+
let isList = false;
|
|
641
|
+
const schemaUid = property.schemaId;
|
|
642
|
+
eas$1.setSchemaUidForSchemaDefinition({
|
|
643
|
+
text: propertyNameSnake,
|
|
644
|
+
schemaUid,
|
|
645
|
+
});
|
|
646
|
+
if (isRelationPropertyName(propertyNameSnake)) {
|
|
647
|
+
isRelation = true;
|
|
648
|
+
if (Array.isArray(propertyMetadata.value)) {
|
|
649
|
+
isList = true;
|
|
650
|
+
refValueType = 'list';
|
|
651
|
+
const result = query.parseEasRelationPropertyName(propertyNameSnake);
|
|
652
|
+
if (result) {
|
|
653
|
+
propertyNameSnake = result.propertyName;
|
|
654
|
+
refSeedType = result.modelName;
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
if (!isList) {
|
|
658
|
+
if (relationValuesToExclude.includes(propertyMetadata.value)) {
|
|
659
|
+
continue;
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
let propertyValue = propertyMetadata.value;
|
|
664
|
+
if (typeof propertyValue !== 'string') {
|
|
665
|
+
propertyValue = JSON.stringify(propertyValue);
|
|
666
|
+
}
|
|
667
|
+
if (isRelation && !isList) {
|
|
668
|
+
const relatedSeed = itemSeeds.find((seed) => seed.id === propertyMetadata.value);
|
|
669
|
+
if (relatedSeed && relatedSeed.schema && relatedSeed.schema.schemaNames) {
|
|
670
|
+
refSeedType = relatedSeed.schema.schemaNames[0].name;
|
|
671
|
+
refSchemaUid = relatedSeed.schemaId;
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
if (isRelation && isList) {
|
|
675
|
+
const relatedSeeds = itemSeeds.filter((seed) => propertyMetadata.value.includes(seed.id));
|
|
676
|
+
if (relatedSeeds && relatedSeeds.length > 0) {
|
|
677
|
+
refSeedType = relatedSeeds[0].schema.schemaNames[0].name;
|
|
678
|
+
refSchemaUid = relatedSeeds[0].schemaId;
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
const propertyName = lodashEs.camelCase(propertyNameSnake);
|
|
682
|
+
const easDataType = propertyMetadata.type;
|
|
683
|
+
const versionUid = property.refUID;
|
|
684
|
+
const versionLocalId = versionUidToLocalId.get(versionUid);
|
|
685
|
+
const attestationCreatedAt = property.timeCreated * 1000;
|
|
686
|
+
const seedUid = versionUidToSeedUid.get(versionUid);
|
|
687
|
+
const seedLocalId = seedUidToLocalId.get(seedUid);
|
|
688
|
+
const modelType = seedUidToModelType.get(seedUid);
|
|
689
|
+
const model = modelType != null
|
|
690
|
+
? await resolveModelForSyncedSeed.skipSeedOnAmbiguousModel({ seedLocalId, seedUid }, 'easSync.metadata', async () => resolveSyncedSeedModel(Model, modelType, { seedLocalId, seedUid }))
|
|
691
|
+
: undefined;
|
|
692
|
+
const modelSchema = model?.properties ? main_cjs.modelPropertiesToObject(model.properties) : undefined;
|
|
693
|
+
if (propertyNameSnake === 'storage_transaction_id') {
|
|
694
|
+
await createMetadataRecordsForStorageTransactionId(property, modelSchema, state);
|
|
695
|
+
}
|
|
696
|
+
const propertyId = modelType != null
|
|
697
|
+
? ((await resolveModelForSyncedSeed.skipSeedOnAmbiguousModel({ seedLocalId, seedUid }, 'easSync.metadata', async () => main_cjs.getPropertyIdForModelAndName(modelType, propertyName, {
|
|
698
|
+
// EAS identifies models by name only; a locally-created seed still knows its model.
|
|
699
|
+
modelFileId: await main_cjs.resolveItemModelFileId({ seedLocalId, seedUid }),
|
|
700
|
+
}))) ?? null)
|
|
701
|
+
: null;
|
|
702
|
+
rows.push({
|
|
703
|
+
localId: propertyLocalId,
|
|
704
|
+
uid: property.id,
|
|
705
|
+
schemaUid: property.schemaId,
|
|
706
|
+
propertyId,
|
|
707
|
+
propertyName,
|
|
708
|
+
propertyValue,
|
|
709
|
+
easDataType,
|
|
710
|
+
versionUid,
|
|
711
|
+
versionLocalId: versionLocalId ?? null,
|
|
712
|
+
seedUid: seedUid ?? null,
|
|
713
|
+
seedLocalId: seedLocalId ?? null,
|
|
714
|
+
modelType: modelType ?? null,
|
|
715
|
+
refValueType: refValueType || null,
|
|
716
|
+
refSeedType: refSeedType || null,
|
|
717
|
+
refModelUid: refSchemaUid || null,
|
|
718
|
+
createdAt: Date.now(),
|
|
719
|
+
attestationCreatedAt,
|
|
720
|
+
attestationRaw: JSON.stringify(property),
|
|
721
|
+
publisher: property.attester ? main_cjs.normalizeHexAddress(property.attester) : '',
|
|
722
|
+
revokedAt: revokedAtSeconds(property) ?? null,
|
|
723
|
+
});
|
|
724
|
+
}
|
|
725
|
+
// No conflict clause, as before: every row has a fresh local_id, and callers pass only
|
|
726
|
+
// attestations with no stored row.
|
|
727
|
+
const batchSize = main_cjs.rowsPerInsert(main_cjs.metadata);
|
|
728
|
+
for (let i = 0; i < rows.length; i += batchSize) {
|
|
729
|
+
await appDb.insert(main_cjs.metadata).values(rows.slice(i, i + batchSize));
|
|
730
|
+
}
|
|
731
|
+
};
|
|
732
|
+
const saveEasPropertiesToDb = (params) => {
|
|
733
|
+
const next = saveEasPropertiesDbChain.then(() => saveEasPropertiesToDbBody(params));
|
|
734
|
+
saveEasPropertiesDbChain = next.then(() => undefined, () => undefined);
|
|
735
|
+
return next;
|
|
736
|
+
};
|
|
737
|
+
/**
|
|
738
|
+
* Fetch every version of `seedUids` and every property attestation of those versions, and store
|
|
739
|
+
* them. The main sync and the related-seed fetch both go through here, so they treat revocation
|
|
740
|
+
* the same way: revoked attestations are fetched on purpose (`excludeRevoked: false`), revoked
|
|
741
|
+
* seeds record `revokedAt` (in `saveEasSeedsToDb`), and properties go through the canonical pick
|
|
742
|
+
* (newest non-revoked per version and property schema, see ADR 0006).
|
|
743
|
+
*/
|
|
744
|
+
const syncVersionsAndPropertiesForSeeds = async ({ seedUids, itemSeeds, state, }) => {
|
|
745
|
+
if (seedUids.length === 0)
|
|
746
|
+
return;
|
|
747
|
+
const itemVersions = await eas$1.getItemVersionsFromEas({
|
|
748
|
+
seedUids,
|
|
749
|
+
excludeRevoked: false,
|
|
750
|
+
});
|
|
751
|
+
const { versionUids } = await saveEasVersionsToDb({
|
|
752
|
+
itemVersions,
|
|
753
|
+
state,
|
|
754
|
+
});
|
|
755
|
+
if (versionUids.length === 0)
|
|
756
|
+
return;
|
|
757
|
+
const fetchedProperties = await eas$1.getItemPropertiesFromEas({
|
|
758
|
+
versionUids,
|
|
759
|
+
excludeRevoked: false,
|
|
760
|
+
});
|
|
761
|
+
// The save makes the canonical pick; it also needs the other attestations to clean up after them.
|
|
762
|
+
await saveEasPropertiesToDb({
|
|
763
|
+
fetchedProperties,
|
|
764
|
+
itemSeeds,
|
|
765
|
+
state,
|
|
766
|
+
});
|
|
767
|
+
};
|
|
768
|
+
/**
|
|
769
|
+
* Relation targets of synced properties, fetched by id from any attester (one level deep).
|
|
770
|
+
*
|
|
771
|
+
* This deliberately matches the main sync instead of filtering out revoked attestations: a
|
|
772
|
+
* relation to an unpublished seed should still resolve locally, to the seed's last values next to
|
|
773
|
+
* its `revokedAt`, exactly as if that seed had been synced in its own right. Filtering at the query
|
|
774
|
+
* would also break the canonical pick, which needs the revoked attestations to skip them (or to
|
|
775
|
+
* keep the newest one when all are revoked), and would leave `seeds.revoked_at` unset.
|
|
776
|
+
*/
|
|
777
|
+
const getRelatedSeedsAndVersions = async (state) => {
|
|
778
|
+
// Snapshot: relations found on the related seeds themselves aren't followed (one level deep).
|
|
779
|
+
const uids = Array.from(state.relatedSeedUids);
|
|
780
|
+
if (uids.length === 0)
|
|
781
|
+
return;
|
|
782
|
+
const easClient = eas$1.BaseEasClient.getEasClient();
|
|
783
|
+
// No `revoked` filter, like `getSeedsFromSchemaUids({ excludeRevoked: false })` in the main sync.
|
|
784
|
+
const { itemSeeds } = await easClient.request(eas$1.GET_SEEDS, {
|
|
785
|
+
where: {
|
|
786
|
+
id: {
|
|
787
|
+
in: uids,
|
|
788
|
+
},
|
|
789
|
+
},
|
|
790
|
+
});
|
|
791
|
+
const { seedUids } = await saveEasSeedsToDb({ itemSeeds, state });
|
|
792
|
+
// Only seeds EAS returned: a version of an unknown seed would be stored without its seed.
|
|
793
|
+
await syncVersionsAndPropertiesForSeeds({ seedUids, itemSeeds, state });
|
|
794
|
+
};
|
|
795
|
+
/**
|
|
796
|
+
* Core sync logic: fetches item attestations from EAS for configured models and given addresses,
|
|
797
|
+
* then saves seeds, versions, and properties to the local DB.
|
|
798
|
+
* Uses owned + watched addresses from DB when addresses are not provided.
|
|
799
|
+
*/
|
|
800
|
+
const runSyncFromEas = async (options) => {
|
|
801
|
+
let addresses = options?.addresses ?? (await main_cjs.getAllAddressesFromDb());
|
|
802
|
+
if (!addresses || addresses.length === 0) {
|
|
803
|
+
return;
|
|
804
|
+
}
|
|
805
|
+
// Don't read the default chain while publish is about to configure another one.
|
|
806
|
+
await main_cjs.waitForEasReadChain();
|
|
807
|
+
// Never mix attestations from two chains in one local DB.
|
|
808
|
+
await main_cjs.assertLocalDbChain();
|
|
809
|
+
const appDb = main_cjs.BaseDb.getAppDb();
|
|
810
|
+
const { schemaStringToModelRecord } = await getModelSchemas();
|
|
811
|
+
const modelSchemas = await eas.getModelSchemasFromEas();
|
|
812
|
+
const schemaUids = [];
|
|
813
|
+
for (const modelSchema of modelSchemas) {
|
|
814
|
+
const foundModel = schemaStringToModelRecord.get(modelSchema.schema);
|
|
815
|
+
if (!foundModel) {
|
|
816
|
+
// Skip schemas that don't have a corresponding model in the user's config
|
|
817
|
+
// This can happen with "bytes32 image" if there's no Image model defined
|
|
818
|
+
console.warn(`[item/events] [syncDbWithEas] Model not found for schema ${modelSchema.schema}, skipping`);
|
|
819
|
+
continue;
|
|
820
|
+
}
|
|
821
|
+
try {
|
|
822
|
+
await appDb
|
|
823
|
+
.insert(main_cjs.modelUids)
|
|
824
|
+
.values({
|
|
825
|
+
modelId: foundModel.id,
|
|
826
|
+
uid: modelSchema.id,
|
|
827
|
+
})
|
|
828
|
+
.onConflictDoNothing();
|
|
829
|
+
}
|
|
830
|
+
catch (err) {
|
|
831
|
+
// Model may have been deleted by test teardown or another process; skip to avoid unhandled rejection
|
|
832
|
+
const e = err;
|
|
833
|
+
const code = e?.code ?? e?.rawCode ?? e?.cause?.code ?? e?.cause?.rawCode;
|
|
834
|
+
if (code === 'SQLITE_CONSTRAINT_FOREIGNKEY' || code === 787) {
|
|
835
|
+
continue;
|
|
836
|
+
}
|
|
837
|
+
throw err;
|
|
838
|
+
}
|
|
839
|
+
schemaUids.push(modelSchema.id);
|
|
840
|
+
}
|
|
841
|
+
// If no schemas were found, skip the rest of the sync process
|
|
842
|
+
// This can happen when models exist but don't have schemas registered in EAS yet
|
|
843
|
+
if (schemaUids.length === 0) {
|
|
844
|
+
return;
|
|
845
|
+
}
|
|
846
|
+
const itemSeeds = await eas$1.getSeedsFromSchemaUids({
|
|
847
|
+
schemaUids,
|
|
848
|
+
addresses,
|
|
849
|
+
excludeRevoked: false,
|
|
850
|
+
});
|
|
851
|
+
const state = createSyncRunState();
|
|
852
|
+
const { seedUids } = await saveEasSeedsToDb({
|
|
853
|
+
itemSeeds,
|
|
854
|
+
state,
|
|
855
|
+
});
|
|
856
|
+
await syncVersionsAndPropertiesForSeeds({ seedUids, itemSeeds, state });
|
|
857
|
+
await getRelatedSeedsAndVersions(state);
|
|
858
|
+
main_cjs.scheduleBulkFilesDownloadFromEasSync(addresses);
|
|
859
|
+
try {
|
|
860
|
+
const itemMod = await Promise.resolve().then(function () { return require('./index-C66AfYDG.js'); }).then(function (n) { return n.Item$1; });
|
|
861
|
+
await itemMod.Item.rehydrateCachedItemsFromDbAfterEasSync();
|
|
862
|
+
}
|
|
863
|
+
catch (err) {
|
|
864
|
+
console.warn('[item/events] [syncDbWithEas] rehydrateCachedItemsFromDbAfterEasSync:', err);
|
|
865
|
+
}
|
|
866
|
+
// Other tabs reload their cached Items too (docs/MULTI_TAB.md).
|
|
867
|
+
main_cjs.emitAcrossTabs(main_cjs.EAS_SEED_DATA_SYNCED_TO_DB_EVENT);
|
|
868
|
+
};
|
|
869
|
+
|
|
870
|
+
exports.VERSION_INSERT_BATCH = VERSION_INSERT_BATCH;
|
|
871
|
+
exports.isSqlEscapedAttestationRaw = isSqlEscapedAttestationRaw;
|
|
872
|
+
exports.runSyncFromEas = runSyncFromEas;
|
|
873
|
+
//# sourceMappingURL=syncDbWithEas-Dk96sAG-.js.map
|