@seedprotocol/sdk 0.7.8-next.1071.g2a141c1 → 0.7.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{ClientManager-Bv15o3Oz.js → ClientManager-B1r_8P5Z.js} +37 -40
- package/dist/ClientManager-B1r_8P5Z.js.map +1 -0
- package/dist/{Item-tX3kpbj4.js → Item-CjTEShfk.js} +384 -399
- package/dist/Item-CjTEShfk.js.map +1 -0
- package/dist/{ModelProperty-N-3gBfu5.js → ModelProperty-C3749Wjq.js} +36 -36
- package/dist/{ModelProperty-N-3gBfu5.js.map → ModelProperty-C3749Wjq.js.map} +1 -1
- package/dist/{Schema-CY3OxwKS.js → Schema-CX9CTtho.js} +35 -35
- package/dist/{Schema-CY3OxwKS.js.map → Schema-CX9CTtho.js.map} +1 -1
- package/dist/{SchemaValidationService-BR2ABK2r.js → SchemaValidationService-T5mqnY8q.js} +6 -6
- package/dist/{SchemaValidationService-BR2ABK2r.js.map → SchemaValidationService-T5mqnY8q.js.map} +1 -1
- package/dist/{backfillMetadataPropertyIds-vc_1RoDT.js → backfillMetadataPropertyIds-DWWkh-Ex.js} +3 -3
- package/dist/{backfillMetadataPropertyIds-vc_1RoDT.js.map → backfillMetadataPropertyIds-DWWkh-Ex.js.map} +1 -1
- package/dist/{tabEvents-BuorBItJ.js → changeFeed-DcsZ7deG.js} +369 -10
- package/dist/changeFeed-DcsZ7deG.js.map +1 -0
- package/dist/{configurePlatform-D-Pj9gTx.js → configurePlatform-AWild9o4.js} +2 -2
- package/dist/{configurePlatform-D-Pj9gTx.js.map → configurePlatform-AWild9o4.js.map} +1 -1
- package/dist/db/drizzle/0022_add_read_indexes.sql +5 -0
- package/dist/db/drizzle/0023_add_entity_changes.sql +48 -0
- package/dist/db/drizzle/meta/0022_snapshot.json +1585 -0
- package/dist/db/drizzle/meta/0023_snapshot.json +1645 -0
- package/dist/db/drizzle/meta/_journal.json +14 -0
- package/dist/{detachRowsBeforeDelete-sK1ye2W6.js → detachRowsBeforeDelete-Bo_pky-R.js} +2 -2
- package/dist/{detachRowsBeforeDelete-sK1ye2W6.js.map → detachRowsBeforeDelete-Bo_pky-R.js.map} +1 -1
- package/dist/dist/{ClientManager-Bv15o3Oz.d.ts → ClientManager-B1r_8P5Z.d.ts} +1 -1
- package/dist/dist/ClientManager-B1r_8P5Z.d.ts.map +1 -0
- package/dist/dist/{Item-tX3kpbj4.d.ts → Item-CjTEShfk.d.ts} +3 -2
- package/dist/dist/Item-CjTEShfk.d.ts.map +1 -0
- package/dist/dist/{ModelProperty-N-3gBfu5.d.ts → ModelProperty-C3749Wjq.d.ts} +1 -1
- package/dist/dist/{ModelProperty-N-3gBfu5.d.ts.map → ModelProperty-C3749Wjq.d.ts.map} +1 -1
- package/dist/dist/{Schema-CY3OxwKS.d.ts → Schema-CX9CTtho.d.ts} +2 -2
- package/dist/dist/{Schema-CY3OxwKS.d.ts.map → Schema-CX9CTtho.d.ts.map} +1 -1
- package/dist/dist/{SchemaValidationService-BR2ABK2r.d.ts → SchemaValidationService-T5mqnY8q.d.ts} +1 -1
- package/dist/dist/{SchemaValidationService-BR2ABK2r.d.ts.map → SchemaValidationService-T5mqnY8q.d.ts.map} +1 -1
- package/dist/dist/{backfillMetadataPropertyIds-vc_1RoDT.d.ts → backfillMetadataPropertyIds-DWWkh-Ex.d.ts} +1 -1
- package/dist/dist/backfillMetadataPropertyIds-DWWkh-Ex.d.ts.map +1 -0
- package/dist/dist/{tabEvents-BuorBItJ.d.ts → changeFeed-DcsZ7deG.d.ts} +101 -36
- package/dist/dist/changeFeed-DcsZ7deG.d.ts.map +1 -0
- package/dist/dist/{configurePlatform-D-Pj9gTx.d.ts → configurePlatform-AWild9o4.d.ts} +1 -1
- package/dist/dist/configurePlatform-AWild9o4.d.ts.map +1 -0
- package/dist/dist/{detachRowsBeforeDelete-sK1ye2W6.d.ts → detachRowsBeforeDelete-Bo_pky-R.d.ts} +1 -1
- package/dist/dist/detachRowsBeforeDelete-Bo_pky-R.d.ts.map +1 -0
- package/dist/dist/{eas-BSQxj7gN.d.ts → eas--9vtNkma.d.ts} +1 -1
- package/dist/dist/eas--9vtNkma.d.ts.map +1 -0
- package/dist/dist/{errors-a4Tj6hly.d.ts → errors-rIWK7gwJ.d.ts} +1 -1
- package/dist/dist/{errors-a4Tj6hly.d.ts.map → errors-rIWK7gwJ.d.ts.map} +1 -1
- package/dist/dist/{getItem-Ctps9gSs.d.ts → getItem-5j22EWWE.d.ts} +1 -1
- package/dist/dist/getItem-5j22EWWE.d.ts.map +1 -0
- package/dist/dist/{getPublishPayload-C2g5pPD2.d.ts → getPublishPayload-BGl2SaGK.d.ts} +1 -1
- package/dist/dist/{getPublishPayload-C2g5pPD2.d.ts.map → getPublishPayload-BGl2SaGK.d.ts.map} +1 -1
- package/dist/dist/{getPublishUploads-CaJHy3SL.d.ts → getPublishUploads-DVsDx6Xf.d.ts} +1 -1
- package/dist/dist/{getPublishUploads-CaJHy3SL.d.ts.map → getPublishUploads-DVsDx6Xf.d.ts.map} +1 -1
- package/dist/dist/{index-s73wD_LC.d.ts → index-C0SetTd1.d.ts} +1190 -1065
- package/dist/dist/index-C0SetTd1.d.ts.map +1 -0
- package/dist/dist/{index-BgEwcREa.d.ts → index-CJK3F_MK.d.ts} +13 -13
- package/dist/dist/index-CJK3F_MK.d.ts.map +1 -0
- package/dist/dist/{index-B6hPWSM4.d.ts → index-CZQrNqvq.d.ts} +130 -13
- package/dist/dist/{index-B6hPWSM4.d.ts.map → index-CZQrNqvq.d.ts.map} +1 -1
- package/dist/dist/{index-bOwhhJJL.d.ts → index-Dp4uyZYx.d.ts} +5 -5
- package/dist/dist/index-Dp4uyZYx.d.ts.map +1 -0
- package/dist/dist/{index.browser-C7iZp7mx.d.ts → index.browser-Ll71Y_Dl.d.ts} +391 -39
- package/dist/dist/{index.browser-C7iZp7mx.d.ts.map → index.browser-Ll71Y_Dl.d.ts.map} +1 -1
- package/dist/dist/{index.node-MPVTJR2J.d.ts → index.node-CgltN0cC.d.ts} +517 -49
- package/dist/dist/{index.node-MPVTJR2J.d.ts.map → index.node-CgltN0cC.d.ts.map} +1 -1
- package/dist/dist/modelPropertyRecordSchemas-C_lYTzMr.d.ts +7 -0
- package/dist/dist/modelPropertyRecordSchemas-C_lYTzMr.d.ts.map +1 -0
- package/dist/dist/platform.browser.d.ts +2 -2
- package/dist/dist/platform.node.d.ts +2 -2
- package/dist/dist/{property-mP9mOZ2L.d.ts → property-pcDxNEpy.d.ts} +3 -3
- package/dist/dist/property-pcDxNEpy.d.ts.map +1 -0
- package/dist/dist/{propertyValidationRules-DwzrYA7c.d.ts → propertyValidationRules-BEjN0f3-.d.ts} +6 -1
- package/dist/dist/propertyValidationRules-BEjN0f3-.d.ts.map +1 -0
- package/dist/dist/{publishDraftGraph-BzYVblZZ.d.ts → publishDraftGraph-I5yKe1Xz.d.ts} +1 -1
- package/dist/dist/{publishDraftGraph-BzYVblZZ.d.ts.map → publishDraftGraph-I5yKe1Xz.d.ts.map} +1 -1
- package/dist/dist/{resetAmbiguousLegacyItemData-B_IUQA09.d.ts → resetAmbiguousLegacyItemData-0Tin9-JK.d.ts} +1 -1
- package/dist/dist/resetAmbiguousLegacyItemData-0Tin9-JK.d.ts.map +1 -0
- package/dist/dist/{resolveModelForSyncedSeed-H-4tmU6l.d.ts → resolveModelForSyncedSeed-C5KXn6ex.d.ts} +1 -1
- package/dist/dist/resolveModelForSyncedSeed-C5KXn6ex.d.ts.map +1 -0
- package/dist/dist/{syncDbWithEas-y5VF623G.d.ts → syncDbWithEas-b4fESZ7C.d.ts} +1 -1
- package/dist/dist/syncDbWithEas-b4fESZ7C.d.ts.map +1 -0
- package/dist/dist/{tolerantWebAccess-DoI7QYT-.d.ts → tolerantWebAccess-CIpS7RLk.d.ts} +1 -1
- package/dist/dist/{tolerantWebAccess-DoI7QYT-.d.ts.map → tolerantWebAccess-CIpS7RLk.d.ts.map} +1 -1
- package/dist/dist/{updateSeedRevokedAt-BIzkbsUd.d.ts → updateSeedRevokedAt-CR4zwn-6.d.ts} +1 -1
- package/dist/dist/updateSeedRevokedAt-CR4zwn-6.d.ts.map +1 -0
- package/dist/{eas-BSQxj7gN.js → eas--9vtNkma.js} +3 -3
- package/dist/{eas-BSQxj7gN.js.map → eas--9vtNkma.js.map} +1 -1
- package/dist/{errors-a4Tj6hly.js → errors-rIWK7gwJ.js} +35 -35
- package/dist/{errors-a4Tj6hly.js.map → errors-rIWK7gwJ.js.map} +1 -1
- package/dist/{getItem-Ctps9gSs.js → getItem-5j22EWWE.js} +5 -5
- package/dist/{getItem-Ctps9gSs.js.map → getItem-5j22EWWE.js.map} +1 -1
- package/dist/{getPublishPayload-C2g5pPD2.js → getPublishPayload-BGl2SaGK.js} +14 -14
- package/dist/{getPublishPayload-C2g5pPD2.js.map → getPublishPayload-BGl2SaGK.js.map} +1 -1
- package/dist/{getPublishUploads-CaJHy3SL.js → getPublishUploads-DVsDx6Xf.js} +7 -7
- package/dist/{getPublishUploads-CaJHy3SL.js.map → getPublishUploads-DVsDx6Xf.js.map} +1 -1
- package/dist/{index-s73wD_LC.js → index-C0SetTd1.js} +52 -13
- package/dist/index-C0SetTd1.js.map +1 -0
- package/dist/{index-BgEwcREa.js → index-CJK3F_MK.js} +8 -8
- package/dist/index-CJK3F_MK.js.map +1 -0
- package/dist/{index-B6hPWSM4.js → index-CZQrNqvq.js} +3 -2
- package/dist/index-CZQrNqvq.js.map +1 -0
- package/dist/{index-bOwhhJJL.js → index-Dp4uyZYx.js} +8 -8
- package/dist/index-Dp4uyZYx.js.map +1 -0
- package/dist/{index.browser-C7iZp7mx.js → index.browser-Ll71Y_Dl.js} +243 -18
- package/dist/index.browser-Ll71Y_Dl.js.map +1 -0
- package/dist/{index.node-MPVTJR2J.js → index.node-CgltN0cC.js} +50 -15
- package/dist/index.node-CgltN0cC.js.map +1 -0
- package/dist/main.js +23 -30
- package/dist/main.js.map +1 -1
- package/dist/modelPropertyRecordSchemas-C_lYTzMr.js +94 -0
- package/dist/modelPropertyRecordSchemas-C_lYTzMr.js.map +1 -0
- package/dist/node.js +11 -11
- package/dist/platform.browser.js +5 -5
- package/dist/platform.node.js +4 -4
- package/dist/{property-mP9mOZ2L.js → property-pcDxNEpy.js} +7 -7
- package/dist/{property-mP9mOZ2L.js.map → property-pcDxNEpy.js.map} +1 -1
- package/dist/propertyValidationRules-BEjN0f3-.js +73 -0
- package/dist/propertyValidationRules-BEjN0f3-.js.map +1 -0
- package/dist/{publishDraftGraph-BzYVblZZ.js → publishDraftGraph-I5yKe1Xz.js} +6 -6
- package/dist/{publishDraftGraph-BzYVblZZ.js.map → publishDraftGraph-I5yKe1Xz.js.map} +1 -1
- package/dist/{resetAmbiguousLegacyItemData-B_IUQA09.js → resetAmbiguousLegacyItemData-0Tin9-JK.js} +2 -2
- package/dist/{resetAmbiguousLegacyItemData-B_IUQA09.js.map → resetAmbiguousLegacyItemData-0Tin9-JK.js.map} +1 -1
- package/dist/{resolveModelForSyncedSeed-H-4tmU6l.js → resolveModelForSyncedSeed-C5KXn6ex.js} +2 -2
- package/dist/{resolveModelForSyncedSeed-H-4tmU6l.js.map → resolveModelForSyncedSeed-C5KXn6ex.js.map} +1 -1
- package/dist/seedSchema/EntityChangeSchema.ts +28 -0
- package/dist/seedSchema/MetadataSchema.ts +12 -4
- package/dist/seedSchema/SeedSchema.ts +9 -3
- package/dist/seedSchema/VersionSchema.ts +9 -4
- package/dist/seedSchema/index.ts +1 -0
- package/dist/src/Item/Item.d.ts +2 -1
- 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/ItemProperty/ItemProperty.d.ts.map +1 -1
- package/dist/src/ItemProperty/service/actors/loadOrCreateProperty.d.ts.map +1 -1
- package/dist/src/ItemProperty/service/actors/modelPropertyRecordSchemas.d.ts +21 -0
- package/dist/src/ItemProperty/service/actors/modelPropertyRecordSchemas.d.ts.map +1 -0
- package/dist/src/browser/db/Db.d.ts +2 -2
- package/dist/src/browser/db/Db.d.ts.map +1 -1
- package/dist/src/browser/db/changeFeed.d.ts +77 -0
- package/dist/src/browser/db/changeFeed.d.ts.map +1 -0
- package/dist/src/browser/db/drizzleFiles.d.ts +4 -2
- package/dist/src/browser/db/drizzleFiles.d.ts.map +1 -1
- package/dist/src/db/write/applyArweaveL1TransactionIdLocal.d.ts.map +1 -1
- package/dist/src/db/write/claimUnpublishedDrafts.d.ts.map +1 -1
- package/dist/src/db/write/createMetadata.d.ts.map +1 -1
- package/dist/src/db/write/createSeed.d.ts.map +1 -1
- package/dist/src/db/write/createVersion.d.ts.map +1 -1
- package/dist/src/db/write/restoreDataItemIdsOverwrittenByL1.d.ts.map +1 -1
- package/dist/src/db/write/saveMetadata.d.ts.map +1 -1
- package/dist/src/db/write/updateItemPropertyValue.d.ts.map +1 -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.map +1 -1
- package/dist/src/events/item/syncDbWithEas.d.ts.map +1 -1
- package/dist/src/helpers/propertyValidationRules.d.ts +8 -0
- package/dist/src/helpers/propertyValidationRules.d.ts.map +1 -1
- package/dist/src/helpers/timing.d.ts +36 -0
- package/dist/src/helpers/timing.d.ts.map +1 -1
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/node/db/singleConnectionTransactions.d.ts +6 -0
- package/dist/src/node/db/singleConnectionTransactions.d.ts.map +1 -1
- package/dist/src/outbox/itemAppliers.d.ts.map +1 -1
- package/dist/src/outbox/outbox.d.ts +2 -0
- package/dist/src/outbox/outbox.d.ts.map +1 -1
- package/dist/src/outbox/pendingValues.d.ts.map +1 -1
- package/dist/src/seedSchema/EntityChangeSchema.d.ts +126 -0
- package/dist/src/seedSchema/EntityChangeSchema.d.ts.map +1 -0
- package/dist/src/seedSchema/MetadataSchema.d.ts +4 -4
- package/dist/src/seedSchema/MetadataSchema.d.ts.map +1 -1
- package/dist/src/seedSchema/SeedSchema.d.ts +4 -4
- package/dist/src/seedSchema/SeedSchema.d.ts.map +1 -1
- package/dist/src/seedSchema/VersionSchema.d.ts +4 -4
- package/dist/src/seedSchema/VersionSchema.d.ts.map +1 -1
- package/dist/src/seedSchema/index.d.ts +1 -0
- package/dist/src/seedSchema/index.d.ts.map +1 -1
- package/dist/{syncDbWithEas-y5VF623G.js → syncDbWithEas-b4fESZ7C.js} +17 -23
- package/dist/syncDbWithEas-b4fESZ7C.js.map +1 -0
- package/dist/{tolerantWebAccess-DoI7QYT-.js → tolerantWebAccess-CIpS7RLk.js} +6 -6
- package/dist/{tolerantWebAccess-DoI7QYT-.js.map → tolerantWebAccess-CIpS7RLk.js.map} +1 -1
- package/dist/{updateSeedRevokedAt-BIzkbsUd.js → updateSeedRevokedAt-CR4zwn-6.js} +5 -6
- package/dist/updateSeedRevokedAt-CR4zwn-6.js.map +1 -0
- package/package.json +6 -6
- package/dist/ClientManager-Bv15o3Oz.js.map +0 -1
- package/dist/Item-tX3kpbj4.js.map +0 -1
- package/dist/dist/ClientManager-Bv15o3Oz.d.ts.map +0 -1
- package/dist/dist/Item-tX3kpbj4.d.ts.map +0 -1
- package/dist/dist/backfillMetadataPropertyIds-vc_1RoDT.d.ts.map +0 -1
- package/dist/dist/configurePlatform-D-Pj9gTx.d.ts.map +0 -1
- package/dist/dist/detachRowsBeforeDelete-sK1ye2W6.d.ts.map +0 -1
- package/dist/dist/eas-BSQxj7gN.d.ts.map +0 -1
- package/dist/dist/getItem-Ctps9gSs.d.ts.map +0 -1
- package/dist/dist/index-BgEwcREa.d.ts.map +0 -1
- package/dist/dist/index-bOwhhJJL.d.ts.map +0 -1
- package/dist/dist/index-s73wD_LC.d.ts.map +0 -1
- package/dist/dist/property-mP9mOZ2L.d.ts.map +0 -1
- package/dist/dist/propertyValidationRules-DwzrYA7c.d.ts.map +0 -1
- package/dist/dist/resetAmbiguousLegacyItemData-B_IUQA09.d.ts.map +0 -1
- package/dist/dist/resolveModelForSyncedSeed-H-4tmU6l.d.ts.map +0 -1
- package/dist/dist/syncDbWithEas-y5VF623G.d.ts.map +0 -1
- package/dist/dist/tabEvents-BuorBItJ.d.ts.map +0 -1
- package/dist/dist/updateSeedRevokedAt-BIzkbsUd.d.ts.map +0 -1
- package/dist/index-B6hPWSM4.js.map +0 -1
- package/dist/index-BgEwcREa.js.map +0 -1
- package/dist/index-bOwhhJJL.js.map +0 -1
- package/dist/index-s73wD_LC.js.map +0 -1
- package/dist/index.browser-C7iZp7mx.js.map +0 -1
- package/dist/index.node-MPVTJR2J.js.map +0 -1
- package/dist/propertyValidationRules-DwzrYA7c.js +0 -51
- package/dist/propertyValidationRules-DwzrYA7c.js.map +0 -1
- package/dist/syncDbWithEas-y5VF623G.js.map +0 -1
- package/dist/tabEvents-BuorBItJ.js.map +0 -1
- package/dist/updateSeedRevokedAt-BIzkbsUd.js.map +0 -1
|
@@ -1,5 +1,132 @@
|
|
|
1
1
|
import debug from 'debug';
|
|
2
|
-
import {
|
|
2
|
+
import { au as isBrowser, J as eventEmitter, Q as BaseFileManager, ai as EAS_SEED_DATA_SYNCED_TO_DB_EVENT, o as entityChanges } from './index-C0SetTd1.js';
|
|
3
|
+
import { sql, gt, lt } from 'drizzle-orm';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Phase timings for item creates, finds and property saves, and ready waits that timed out but
|
|
7
|
+
* were allowed to continue, under `DEBUG=seedSdk:timing`. Timing lines are `<label> <ms>ms` plus
|
|
8
|
+
* any details, so an app can report where a slow call spent its time.
|
|
9
|
+
*/
|
|
10
|
+
const timingLogger = debug('seedSdk:timing');
|
|
11
|
+
const now = () => (typeof performance !== 'undefined' ? performance.now() : Date.now());
|
|
12
|
+
/** Runs `fn` and logs how long it took (also when it throws). Costs nothing when the namespace is off. */
|
|
13
|
+
async function timed(label, fn, details) {
|
|
14
|
+
if (!timingLogger.enabled)
|
|
15
|
+
return fn();
|
|
16
|
+
const start = now();
|
|
17
|
+
let failed = false;
|
|
18
|
+
try {
|
|
19
|
+
return await fn();
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
failed = true;
|
|
23
|
+
throw error;
|
|
24
|
+
}
|
|
25
|
+
finally {
|
|
26
|
+
const extra = details?.();
|
|
27
|
+
timingLogger(`${label} ${Math.round(now() - start)}ms${failed ? ' (failed)' : ''}${extra ? ` ${extra}` : ''}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Database work counted while the namespace is on, so a timing line can say how much of its time
|
|
32
|
+
* was the SQLite worker. Statements are the ones the SDK sends through the driver; their time runs
|
|
33
|
+
* from send to result, so it includes the wait behind everything queued before them on the one
|
|
34
|
+
* worker. Live-query runs are SQLocal reactive-query results (the first run and every re-run after
|
|
35
|
+
* a write to a watched table), which go through the same worker but not through the driver.
|
|
36
|
+
*/
|
|
37
|
+
const dbTimingCounters = {
|
|
38
|
+
statements: 0,
|
|
39
|
+
statementMs: 0,
|
|
40
|
+
inFlight: 0,
|
|
41
|
+
liveQueryRuns: 0,
|
|
42
|
+
liveQueryFirstRuns: 0,
|
|
43
|
+
liveQueryFirstRunMs: 0,
|
|
44
|
+
};
|
|
45
|
+
const snapshotCounters = () => ({ ...dbTimingCounters });
|
|
46
|
+
/** Wraps a driver function so each call is counted while timing is on. */
|
|
47
|
+
function countDbStatements(driver) {
|
|
48
|
+
return async (...args) => {
|
|
49
|
+
if (!timingLogger.enabled)
|
|
50
|
+
return driver(...args);
|
|
51
|
+
const start = now();
|
|
52
|
+
dbTimingCounters.inFlight += 1;
|
|
53
|
+
try {
|
|
54
|
+
return await driver(...args);
|
|
55
|
+
}
|
|
56
|
+
finally {
|
|
57
|
+
dbTimingCounters.inFlight -= 1;
|
|
58
|
+
dbTimingCounters.statements += 1;
|
|
59
|
+
dbTimingCounters.statementMs += now() - start;
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/** Starts the clock for one live query; call the result on each of its runs. */
|
|
64
|
+
function countLiveQueryRuns() {
|
|
65
|
+
if (!timingLogger.enabled)
|
|
66
|
+
return () => { };
|
|
67
|
+
const start = now();
|
|
68
|
+
let first = true;
|
|
69
|
+
return () => {
|
|
70
|
+
dbTimingCounters.liveQueryRuns += 1;
|
|
71
|
+
if (!first)
|
|
72
|
+
return;
|
|
73
|
+
first = false;
|
|
74
|
+
dbTimingCounters.liveQueryFirstRuns += 1;
|
|
75
|
+
dbTimingCounters.liveQueryFirstRunMs += now() - start;
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
const describeDbDelta = (before) => {
|
|
79
|
+
const after = dbTimingCounters;
|
|
80
|
+
const statements = after.statements - before.statements;
|
|
81
|
+
const statementMs = after.statementMs - before.statementMs;
|
|
82
|
+
const liveRuns = after.liveQueryRuns - before.liveQueryRuns;
|
|
83
|
+
const firstRuns = after.liveQueryFirstRuns - before.liveQueryFirstRuns;
|
|
84
|
+
const firstMs = after.liveQueryFirstRunMs - before.liveQueryFirstRunMs;
|
|
85
|
+
const parts = [`queued ${before.inFlight}`];
|
|
86
|
+
if (statements)
|
|
87
|
+
parts.push(`${statements} stmts avg ${Math.round(statementMs / statements)}ms`);
|
|
88
|
+
if (liveRuns)
|
|
89
|
+
parts.push(`${liveRuns} live runs`);
|
|
90
|
+
if (firstRuns)
|
|
91
|
+
parts.push(`${firstRuns} new live queries, first run avg ${Math.round(firstMs / firstRuns)}ms`);
|
|
92
|
+
return `[db: ${parts.join(', ')}]`;
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* Like `timed`, and the line also says how many statements and live-query runs went through the
|
|
96
|
+
* worker meanwhile (from any caller, since they share the queue) and how many statements were
|
|
97
|
+
* already queued when it started.
|
|
98
|
+
*/
|
|
99
|
+
async function timedDb(label, fn, details) {
|
|
100
|
+
if (!timingLogger.enabled)
|
|
101
|
+
return fn();
|
|
102
|
+
const before = snapshotCounters();
|
|
103
|
+
return timed(label, fn, () => [details?.(), describeDbDelta(before)].filter(Boolean).join(' '));
|
|
104
|
+
}
|
|
105
|
+
/** Milliseconds since `start` (a `timingNow()` value), rounded. */
|
|
106
|
+
const timingSince = (start) => Math.round(now() - start);
|
|
107
|
+
const timingNow = now;
|
|
108
|
+
/**
|
|
109
|
+
* Split timer for one multi-step call: `mark(step)` records the time since the previous mark, and
|
|
110
|
+
* `log(label)` writes one line with the total and every step. Does nothing when timing is off.
|
|
111
|
+
*/
|
|
112
|
+
function timingMarks() {
|
|
113
|
+
if (!timingLogger.enabled)
|
|
114
|
+
return { mark: () => { }, log: () => { } };
|
|
115
|
+
const start = now();
|
|
116
|
+
const before = snapshotCounters();
|
|
117
|
+
let last = start;
|
|
118
|
+
const steps = [];
|
|
119
|
+
return {
|
|
120
|
+
mark: (step) => {
|
|
121
|
+
const t = now();
|
|
122
|
+
steps.push(`${step} ${Math.round(t - last)}`);
|
|
123
|
+
last = t;
|
|
124
|
+
},
|
|
125
|
+
log: (label) => {
|
|
126
|
+
timingLogger(`${label} ${Math.round(now() - start)}ms: ${steps.join(', ')} ${describeDbDelta(before)}`);
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
}
|
|
3
130
|
|
|
4
131
|
/**
|
|
5
132
|
* Cross-tab exclusive sections, using the Web Locks API. All tabs of an origin share one SQLite
|
|
@@ -101,7 +228,7 @@ function waitForTurn(previous, name, timeoutMs) {
|
|
|
101
228
|
return Promise.race([previous, timedOut]).finally(() => clearTimeout(timer));
|
|
102
229
|
}
|
|
103
230
|
|
|
104
|
-
const logger$
|
|
231
|
+
const logger$2 = debug('seedSdk:helpers:tabCoordinator');
|
|
105
232
|
/** Identifies this tab (this page's SDK instance) in the messages it sends. */
|
|
106
233
|
const TAB_ID = typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function'
|
|
107
234
|
? crypto.randomUUID()
|
|
@@ -148,7 +275,7 @@ function becomeLeader() {
|
|
|
148
275
|
if (leader)
|
|
149
276
|
return;
|
|
150
277
|
leader = true;
|
|
151
|
-
logger$
|
|
278
|
+
logger$2(`this tab leads ${state?.dbKey}`);
|
|
152
279
|
const waiters = leaderWaiters;
|
|
153
280
|
leaderWaiters = [];
|
|
154
281
|
for (const resolve of waiters)
|
|
@@ -215,7 +342,7 @@ function parseAddressesPersistedPayload(value) {
|
|
|
215
342
|
return { owned, watched };
|
|
216
343
|
}
|
|
217
344
|
|
|
218
|
-
const logger = debug('seedSdk:helpers:tabEvents');
|
|
345
|
+
const logger$1 = debug('seedSdk:helpers:tabEvents');
|
|
219
346
|
/**
|
|
220
347
|
* Keeps other tabs current (docs/MULTI_TAB.md). The event bus is per tab, so events that mean "the
|
|
221
348
|
* shared database or OPFS changed" are also posted to the other tabs, which refresh their caches
|
|
@@ -303,14 +430,14 @@ function flushFilesChangedNotices() {
|
|
|
303
430
|
/** Refreshes this tab's in-memory state for an event another tab emitted, before re-emitting it. */
|
|
304
431
|
async function catchUpOn(name, payload) {
|
|
305
432
|
if (name === EAS_SEED_DATA_SYNCED_TO_DB_EVENT) {
|
|
306
|
-
const _mod_0 = await import('./Item-
|
|
433
|
+
const _mod_0 = await import('./Item-CjTEShfk.js');
|
|
307
434
|
const _ns_0 = _mod_0.av;
|
|
308
435
|
const { Item } = _ns_0;
|
|
309
436
|
await Item.rehydrateCachedItemsFromDbAfterEasSync();
|
|
310
437
|
}
|
|
311
438
|
else if (name === LOCAL_COPIES_REMOVED_EVENT) {
|
|
312
439
|
const { removedSeedLocalIds = [], removedSeedUids = [] } = (payload ?? {});
|
|
313
|
-
const _mod_1 = await import('./Item-
|
|
440
|
+
const _mod_1 = await import('./Item-CjTEShfk.js');
|
|
314
441
|
const _ns_1 = _mod_1.av;
|
|
315
442
|
const { Item } = _ns_1;
|
|
316
443
|
Item.dropCachedInstancesForSeedIds([...removedSeedLocalIds, ...removedSeedUids]);
|
|
@@ -330,7 +457,7 @@ function listenForOtherTabsEvents() {
|
|
|
330
457
|
onTabMessage((message) => {
|
|
331
458
|
if (message.type === 'event' && RELAYED_EVENTS.has(message.name)) {
|
|
332
459
|
void catchUpOn(message.name, message.payload)
|
|
333
|
-
.catch((error) => logger(`catching up on ${message.name} failed`, error))
|
|
460
|
+
.catch((error) => logger$1(`catching up on ${message.name} failed`, error))
|
|
334
461
|
.then(() => {
|
|
335
462
|
if (message.payload === undefined) {
|
|
336
463
|
eventEmitter.emit(message.name);
|
|
@@ -343,7 +470,7 @@ function listenForOtherTabsEvents() {
|
|
|
343
470
|
else if (message.type === 'files-changed') {
|
|
344
471
|
// Only refreshes caches: never writes, so never sends files-changed back.
|
|
345
472
|
void BaseFileManager.invalidateCachedPaths(message.paths)
|
|
346
|
-
.catch((error) => logger('refreshing changed files failed', error))
|
|
473
|
+
.catch((error) => logger$1('refreshing changed files failed', error))
|
|
347
474
|
.then(() => eventEmitter.emit(FILES_CHANGED_EVENT, message.paths));
|
|
348
475
|
}
|
|
349
476
|
});
|
|
@@ -362,5 +489,237 @@ var tabEvents = /*#__PURE__*/Object.freeze({
|
|
|
362
489
|
queueFilesChangedNotice: queueFilesChangedNotice
|
|
363
490
|
});
|
|
364
491
|
|
|
365
|
-
|
|
366
|
-
|
|
492
|
+
const logger = debug('seedSdk:browser:db:changeFeed');
|
|
493
|
+
/** Log rows older than this are pruned by the leader tab. */
|
|
494
|
+
const ENTITY_CHANGES_RETENTION_MS = 10 * 60000;
|
|
495
|
+
/** The leader prunes at most this often. */
|
|
496
|
+
const ENTITY_CHANGES_PRUNE_EVERY_MS = 60000;
|
|
497
|
+
const byLocalId = new Map();
|
|
498
|
+
const byUid = new Map();
|
|
499
|
+
const registrations = new Set();
|
|
500
|
+
let feed;
|
|
501
|
+
let cursor = 0;
|
|
502
|
+
let reading;
|
|
503
|
+
let readAgain = false;
|
|
504
|
+
let lastPrunedAt = 0;
|
|
505
|
+
const addTo = (map, key, registration) => {
|
|
506
|
+
let set = map.get(key);
|
|
507
|
+
if (!set)
|
|
508
|
+
map.set(key, (set = new Set()));
|
|
509
|
+
set.add(registration);
|
|
510
|
+
};
|
|
511
|
+
const removeFrom = (map, key, registration) => {
|
|
512
|
+
const set = map.get(key);
|
|
513
|
+
if (!set)
|
|
514
|
+
return;
|
|
515
|
+
set.delete(registration);
|
|
516
|
+
if (set.size === 0)
|
|
517
|
+
map.delete(key);
|
|
518
|
+
};
|
|
519
|
+
/**
|
|
520
|
+
* Calls `listener` after a committed write to one of `watch.tables` for the watched seed, matched
|
|
521
|
+
* by local id or (case-insensitively) by uid. A read of the log that has several matching rows
|
|
522
|
+
* calls it once. When the tab missed rows (its cursor is older than the oldest kept row), every
|
|
523
|
+
* listener is called once. Returns the unregister function.
|
|
524
|
+
*/
|
|
525
|
+
function watchEntityChanges(watch, listener) {
|
|
526
|
+
const registration = {
|
|
527
|
+
watch,
|
|
528
|
+
tables: new Set(watch.tables),
|
|
529
|
+
propertyNames: watch.propertyNames ? new Set(watch.propertyNames) : undefined,
|
|
530
|
+
listener,
|
|
531
|
+
};
|
|
532
|
+
const localId = watch.seedLocalId || undefined;
|
|
533
|
+
const uid = watch.seedUid ? watch.seedUid.toLowerCase() : undefined;
|
|
534
|
+
registrations.add(registration);
|
|
535
|
+
if (localId)
|
|
536
|
+
addTo(byLocalId, localId, registration);
|
|
537
|
+
if (uid)
|
|
538
|
+
addTo(byUid, uid, registration);
|
|
539
|
+
return () => {
|
|
540
|
+
registrations.delete(registration);
|
|
541
|
+
if (localId)
|
|
542
|
+
removeFrom(byLocalId, localId, registration);
|
|
543
|
+
if (uid)
|
|
544
|
+
removeFrom(byUid, uid, registration);
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
/**
|
|
548
|
+
* Watches `watch` and runs `read` once per dispatch, handing its result to `onRows` when it differs
|
|
549
|
+
* from the last one handed over. A read that finishes after a newer one started is dropped, so an
|
|
550
|
+
* older result never replaces a newer one.
|
|
551
|
+
*
|
|
552
|
+
* Pass `since` (the `changeFeedCursor()` taken before the caller's own initial read) to run `read`
|
|
553
|
+
* once right away when the feed moved on in between: a change dispatched before this watch was
|
|
554
|
+
* registered would otherwise be missed. Pass `immediate` to run it once right away regardless, as
|
|
555
|
+
* a liveQuery's first emission does.
|
|
556
|
+
*/
|
|
557
|
+
function watchEntityRows(watch, read, onRows, options = {}) {
|
|
558
|
+
let latest = 0;
|
|
559
|
+
let closed = false;
|
|
560
|
+
let lastJson;
|
|
561
|
+
const run = () => {
|
|
562
|
+
const token = ++latest;
|
|
563
|
+
read().then((rows) => {
|
|
564
|
+
if (closed || token !== latest)
|
|
565
|
+
return;
|
|
566
|
+
// Like BaseDb.liveQuery's distinctUntilChanged: a write that left these rows as they were
|
|
567
|
+
// (this entity's own write, read back) doesn't reach the handler again.
|
|
568
|
+
const json = JSON.stringify(rows);
|
|
569
|
+
if (json === lastJson)
|
|
570
|
+
return;
|
|
571
|
+
lastJson = json;
|
|
572
|
+
onRows(rows);
|
|
573
|
+
}, (error) => {
|
|
574
|
+
if (closed || token !== latest)
|
|
575
|
+
return;
|
|
576
|
+
if (options.onError)
|
|
577
|
+
options.onError(error);
|
|
578
|
+
else
|
|
579
|
+
logger('entity read failed', error);
|
|
580
|
+
});
|
|
581
|
+
};
|
|
582
|
+
const unregister = watchEntityChanges(watch, run);
|
|
583
|
+
if (options.immediate || (options.since !== undefined && cursor > options.since))
|
|
584
|
+
run();
|
|
585
|
+
return {
|
|
586
|
+
unsubscribe: () => {
|
|
587
|
+
closed = true;
|
|
588
|
+
unregister();
|
|
589
|
+
},
|
|
590
|
+
};
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* Runs an SQL-tag query once, the way BaseDb.liveQuery's query function is written
|
|
594
|
+
* (`(sql) => sql\`SELECT ...\``), so an entity can keep its liveQuery's text for its feed reads.
|
|
595
|
+
*/
|
|
596
|
+
async function queryEntityRows(query) {
|
|
597
|
+
if (!feed)
|
|
598
|
+
throw new Error('The change feed has not started');
|
|
599
|
+
return (await query(feed.sql));
|
|
600
|
+
}
|
|
601
|
+
/** Whether this tab's feed runs (a browser database is open); Node has none. */
|
|
602
|
+
function isChangeFeedRunning() {
|
|
603
|
+
return feed !== undefined;
|
|
604
|
+
}
|
|
605
|
+
const callAll = (targets) => {
|
|
606
|
+
for (const registration of targets) {
|
|
607
|
+
try {
|
|
608
|
+
registration.listener();
|
|
609
|
+
}
|
|
610
|
+
catch (error) {
|
|
611
|
+
logger('listener threw', error);
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
};
|
|
615
|
+
const dispatch = (rows) => {
|
|
616
|
+
const targets = new Set();
|
|
617
|
+
for (const row of rows) {
|
|
618
|
+
const candidates = [
|
|
619
|
+
...(row.seedLocalId ? byLocalId.get(row.seedLocalId) ?? [] : []),
|
|
620
|
+
...(row.seedUid ? byUid.get(row.seedUid.toLowerCase()) ?? [] : []),
|
|
621
|
+
];
|
|
622
|
+
for (const registration of candidates) {
|
|
623
|
+
if (!registration.tables.has(row.tbl))
|
|
624
|
+
continue;
|
|
625
|
+
if (row.tbl === 'metadata' &&
|
|
626
|
+
registration.propertyNames &&
|
|
627
|
+
row.propertyName != null &&
|
|
628
|
+
!registration.propertyNames.has(row.propertyName)) {
|
|
629
|
+
continue;
|
|
630
|
+
}
|
|
631
|
+
targets.add(registration);
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
callAll(targets);
|
|
635
|
+
};
|
|
636
|
+
const readNewRows = async (db) => {
|
|
637
|
+
const rows = await db
|
|
638
|
+
.select({
|
|
639
|
+
seq: entityChanges.seq,
|
|
640
|
+
tbl: entityChanges.tbl,
|
|
641
|
+
seedLocalId: entityChanges.seedLocalId,
|
|
642
|
+
seedUid: entityChanges.seedUid,
|
|
643
|
+
propertyName: entityChanges.propertyName,
|
|
644
|
+
})
|
|
645
|
+
.from(entityChanges)
|
|
646
|
+
.where(gt(entityChanges.seq, cursor))
|
|
647
|
+
.orderBy(entityChanges.seq);
|
|
648
|
+
if (feed?.db !== db || rows.length === 0)
|
|
649
|
+
return;
|
|
650
|
+
// Writers are serialized, so committed seqs have no holes: a missing first row was pruned.
|
|
651
|
+
const missed = rows[0].seq > cursor + 1;
|
|
652
|
+
cursor = rows[rows.length - 1].seq;
|
|
653
|
+
if (missed) {
|
|
654
|
+
logger(`cursor fell behind the log; notifying all ${registrations.size} watches`);
|
|
655
|
+
callAll([...registrations]);
|
|
656
|
+
}
|
|
657
|
+
else {
|
|
658
|
+
dispatch(rows);
|
|
659
|
+
}
|
|
660
|
+
await maybePrune(db);
|
|
661
|
+
};
|
|
662
|
+
const maybePrune = async (db) => {
|
|
663
|
+
const now = Date.now();
|
|
664
|
+
if (!isLeaderTab() || now - lastPrunedAt < ENTITY_CHANGES_PRUNE_EVERY_MS)
|
|
665
|
+
return;
|
|
666
|
+
lastPrunedAt = now;
|
|
667
|
+
try {
|
|
668
|
+
await pruneEntityChanges(db, now);
|
|
669
|
+
}
|
|
670
|
+
catch (error) {
|
|
671
|
+
logger('prune failed', error);
|
|
672
|
+
}
|
|
673
|
+
};
|
|
674
|
+
/** Deletes log rows older than ENTITY_CHANGES_RETENTION_MS. Deleting doesn't raise max(seq), so it dispatches nothing. */
|
|
675
|
+
async function pruneEntityChanges(db, now = Date.now()) {
|
|
676
|
+
await db.delete(entityChanges).where(lt(entityChanges.at, now - ENTITY_CHANGES_RETENTION_MS));
|
|
677
|
+
}
|
|
678
|
+
/** Reads once at a time; an emission during a read makes it read once more. */
|
|
679
|
+
const scheduleRead = (db) => {
|
|
680
|
+
if (reading) {
|
|
681
|
+
readAgain = true;
|
|
682
|
+
return;
|
|
683
|
+
}
|
|
684
|
+
reading = (async () => {
|
|
685
|
+
try {
|
|
686
|
+
do {
|
|
687
|
+
readAgain = false;
|
|
688
|
+
await readNewRows(db);
|
|
689
|
+
} while (readAgain && feed?.db === db);
|
|
690
|
+
}
|
|
691
|
+
catch (error) {
|
|
692
|
+
logger('read failed', error);
|
|
693
|
+
}
|
|
694
|
+
finally {
|
|
695
|
+
reading = undefined;
|
|
696
|
+
}
|
|
697
|
+
})();
|
|
698
|
+
};
|
|
699
|
+
/**
|
|
700
|
+
* Starts this tab's feed on `db` (once its migrations ran), at the newest seq allocated so far:
|
|
701
|
+
* entities do their own initial read. A second call replaces the first feed.
|
|
702
|
+
*/
|
|
703
|
+
async function startChangeFeed(db, { liveQuery, sql: sqlTag }) {
|
|
704
|
+
stopChangeFeed();
|
|
705
|
+
// sqlite_sequence keeps the last seq even when pruning emptied the table.
|
|
706
|
+
const [row] = await db.all(sql `SELECT seq FROM sqlite_sequence WHERE name = 'entity_changes'`);
|
|
707
|
+
cursor = Number(row?.seq ?? 0);
|
|
708
|
+
const subscription = liveQuery((tag) => tag `SELECT max(seq) AS seq FROM entity_changes`).subscribe({
|
|
709
|
+
next: ([latest]) => {
|
|
710
|
+
if (latest?.seq != null && Number(latest.seq) > cursor)
|
|
711
|
+
scheduleRead(db);
|
|
712
|
+
},
|
|
713
|
+
error: (error) => logger('feed query failed', error),
|
|
714
|
+
});
|
|
715
|
+
feed = { db, sql: sqlTag, unsubscribe: () => subscription.unsubscribe() };
|
|
716
|
+
logger(`started at seq ${cursor}`);
|
|
717
|
+
}
|
|
718
|
+
function stopChangeFeed() {
|
|
719
|
+
feed?.unsubscribe();
|
|
720
|
+
feed = undefined;
|
|
721
|
+
readAgain = false;
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
export { ADDRESSES_PERSISTED_EVENT as A, timed as B, revokeSessionObjectUrl as C, queryEntityRows as D, isSessionObjectUrl as E, FILES_CHANGED_EVENT as F, timedDb as G, tabEvents as H, LOCAL_COPIES_REMOVED_EVENT as L, TabLockTimeoutError as T, isLeaderTab as a, watchEntityRows as b, whenLeaderTab as c, withDbTabLock as d, emitAcrossTabs as e, createSessionObjectUrl as f, withSeedDbLock as g, countDbStatements as h, isChangeFeedRunning as i, countLiveQueryRuns as j, postTabMessage as k, listenForOtherTabsEvents as l, startTabCoordination as m, notifyFilesWrittenOutsideCache as n, onTabMessage as o, parseAddressesPersistedPayload as p, tryWithTabLock as q, withTabLock as r, startChangeFeed as s, timingMarks as t, notifyFileSaved as u, timingNow as v, watchEntityChanges as w, timingSince as x, timingLogger as y, TAB_ID as z };
|
|
725
|
+
//# sourceMappingURL=changeFeed-DcsZ7deG.js.map
|