@seedprotocol/sdk 0.4.21 → 0.4.23
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/{ArweaveClient-DxpJnJXU.js → ArweaveClient-DoBABTLW.js} +3 -4
- package/dist/{ArweaveClient-DxpJnJXU.js.map → ArweaveClient-DoBABTLW.js.map} +1 -1
- package/dist/{ArweaveClient-Cz9ZLiEV.js → ArweaveClient-KF_T3NSr.js} +3 -4
- package/dist/{ArweaveClient-Cz9ZLiEV.js.map → ArweaveClient-KF_T3NSr.js.map} +1 -1
- package/dist/{Db-DkTBncAM.js → Db-Cg7Q5gIc.js} +4 -5
- package/dist/{Db-DkTBncAM.js.map → Db-Cg7Q5gIc.js.map} +1 -1
- package/dist/{Db-CXwQVLZv.js → Db-DA_e7Jcc.js} +107 -7
- package/dist/Db-DA_e7Jcc.js.map +1 -0
- package/dist/{EasClient-DjpbHjU9.js → EasClient-B4VivHxM.js} +2 -3
- package/dist/{EasClient-JYkmHxu1.js.map → EasClient-B4VivHxM.js.map} +1 -1
- package/dist/{EasClient-JYkmHxu1.js → EasClient-CVPHYGNP.js} +2 -3
- package/dist/{EasClient-DjpbHjU9.js.map → EasClient-CVPHYGNP.js.map} +1 -1
- package/dist/{FileManager-DHnyb040.js → FileManager-BOxbzROS.js} +18 -3
- package/dist/FileManager-BOxbzROS.js.map +1 -0
- package/dist/{FileManager-CKyoLrBP.js → FileManager-Ba5BCbCL.js} +2 -3
- package/dist/{FileManager-CKyoLrBP.js.map → FileManager-Ba5BCbCL.js.map} +1 -1
- package/dist/{ModelProperty-DWtv9fQr.js → ModelProperty-D6JLRqQW.js} +24 -25
- package/dist/ModelProperty-D6JLRqQW.js.map +1 -0
- package/dist/{PathResolver-Ce4K9acQ.js → PathResolver-D7WqjJCo.js} +2 -3
- package/dist/{PathResolver-Ce4K9acQ.js.map → PathResolver-D7WqjJCo.js.map} +1 -1
- package/dist/{PathResolver-pmw--Ea2.js → PathResolver-DHTAlCzo.js} +2 -3
- package/dist/{PathResolver-pmw--Ea2.js.map → PathResolver-DHTAlCzo.js.map} +1 -1
- package/dist/{QueryClient-unspcsWa.js → QueryClient-B12y2daD.js} +7 -4
- package/dist/QueryClient-B12y2daD.js.map +1 -0
- package/dist/{QueryClient-OUjfvY3g.js → QueryClient-BCxuWg7f.js} +3 -3
- package/dist/QueryClient-BCxuWg7f.js.map +1 -0
- package/dist/{Schema-CqqcEexA.js → Schema-B5_B8nM5.js} +38 -38
- package/dist/{Schema-CqqcEexA.js.map → Schema-B5_B8nM5.js.map} +1 -1
- package/dist/{SchemaValidationService-Cb-b4kpD.js → SchemaValidationService-DXYRdSYa.js} +2 -3
- package/dist/{SchemaValidationService-Cb-b4kpD.js.map → SchemaValidationService-DXYRdSYa.js.map} +1 -1
- package/dist/{backfillMetadataPropertyIds-CRyRez3h.js → backfillMetadataPropertyIds-BWEhAJPS.js} +2 -3
- package/dist/{backfillMetadataPropertyIds-CRyRez3h.js.map → backfillMetadataPropertyIds-BWEhAJPS.js.map} +1 -1
- package/dist/cjs/{ModelProperty-sNx_ZQZX.js → ModelProperty-Ov1_YL9l.js} +17 -18
- package/dist/cjs/{ModelProperty-sNx_ZQZX.js.map → ModelProperty-Ov1_YL9l.js.map} +1 -1
- package/dist/cjs/{Schema-B4RRA-0g.js → Schema-CeG5iRX_.js} +20 -21
- package/dist/cjs/{Schema-B4RRA-0g.js.map → Schema-CeG5iRX_.js.map} +1 -1
- package/dist/cjs/{SchemaValidationService-DCflhpcI.js → SchemaValidationService-C8mdrNnp.js} +2 -3
- package/dist/cjs/{SchemaValidationService-DCflhpcI.js.map → SchemaValidationService-C8mdrNnp.js.map} +1 -1
- package/dist/cjs/{backfillMetadataPropertyIds-DhAXAuSf.js → backfillMetadataPropertyIds-LDYghZxU.js} +2 -3
- package/dist/cjs/{backfillMetadataPropertyIds-DhAXAuSf.js.map → backfillMetadataPropertyIds-LDYghZxU.js.map} +1 -1
- package/dist/cjs/{getItem-lyM2x5pT.js → getItem-CW3BFytl.js} +2 -3
- package/dist/cjs/{getItem-lyM2x5pT.js.map → getItem-CW3BFytl.js.map} +1 -1
- package/dist/cjs/{getPublishPayload-DP2fm4q8.js → getPublishPayload-C0hWIYCX.js} +11 -12
- package/dist/cjs/{getPublishPayload-DP2fm4q8.js.map → getPublishPayload-C0hWIYCX.js.map} +1 -1
- package/dist/cjs/{getPublishUploads-DdVy-5fK.js → getPublishUploads-CMpPR2JJ.js} +39 -7
- package/dist/cjs/getPublishUploads-CMpPR2JJ.js.map +1 -0
- package/dist/cjs/{getSegmentedItemProperties-DtHofn5i.js → getSegmentedItemProperties-B4ao_B1Q.js} +3 -3
- package/dist/cjs/{getSegmentedItemProperties-DtHofn5i.js.map → getSegmentedItemProperties-B4ao_B1Q.js.map} +1 -1
- package/dist/cjs/{index-DTkoTvcq.js → index-Dty7eE10.js} +3 -4
- package/dist/cjs/index-Dty7eE10.js.map +1 -0
- package/dist/cjs/{index-D1qR8xnb.js → index-Far6-WGM.js} +2034 -1118
- package/dist/cjs/index-Far6-WGM.js.map +1 -0
- package/dist/cjs/{ownership-DanM_n8E.js → ownership-TCXiKRY_.js} +2 -3
- package/dist/cjs/{ownership-DanM_n8E.js.map → ownership-TCXiKRY_.js.map} +1 -1
- package/dist/cjs/{property-BQokoaRe.js → property-BT7i8Tl-.js} +4 -5
- package/dist/cjs/{property-BQokoaRe.js.map → property-BT7i8Tl-.js.map} +1 -1
- package/dist/cjs/syncDbWithEas-DUi78csI.js +609 -0
- package/dist/cjs/syncDbWithEas-DUi78csI.js.map +1 -0
- package/dist/db/drizzle/drizzle/0013_eas_sync_processes.sql +12 -0
- package/dist/db/drizzle/drizzle/meta/0013_snapshot.json +1262 -0
- package/dist/db/drizzle/drizzle/meta/_journal.json +7 -0
- package/dist/{getItem-VI3QqdZH.js → getItem-D5_bPYyC.js} +2 -3
- package/dist/{getItem-VI3QqdZH.js.map → getItem-D5_bPYyC.js.map} +1 -1
- package/dist/{getPublishPayload-DpYwi-rd.js → getPublishPayload-DEdHgrgC.js} +14 -15
- package/dist/getPublishPayload-DEdHgrgC.js.map +1 -0
- package/dist/{getPublishUploads-DS2dQ4Ho.js → getPublishUploads-CH72lAID.js} +39 -7
- package/dist/getPublishUploads-CH72lAID.js.map +1 -0
- package/dist/{getSegmentedItemProperties-Bz5B4DSA.js → getSegmentedItemProperties-Cp92QUHQ.js} +3 -3
- package/dist/{getSegmentedItemProperties-Bz5B4DSA.js.map → getSegmentedItemProperties-Cp92QUHQ.js.map} +1 -1
- package/dist/{index-BrD_NNaX.js → index-18lln0cM.js} +2045 -1130
- package/dist/index-18lln0cM.js.map +1 -0
- package/dist/{index-DdzhrbkF.js → index-Bp0ChnQr.js} +3 -2
- package/dist/index-Bp0ChnQr.js.map +1 -0
- package/dist/{index-Cqf_DxkJ.js → index-DB3nZ0lK.js} +3 -4
- package/dist/index-DB3nZ0lK.js.map +1 -0
- package/dist/main.cjs +1 -2
- package/dist/main.cjs.map +1 -1
- package/dist/main.js +16 -42
- package/dist/main.js.map +1 -1
- package/dist/node.js +10 -11
- package/dist/node.js.map +1 -1
- package/dist/{ownership-BK6suksO.js → ownership-D-KsIkxM.js} +2 -3
- package/dist/{ownership-BK6suksO.js.map → ownership-D-KsIkxM.js.map} +1 -1
- package/dist/{property-C63Ddzap.js → property-DViA9nga.js} +6 -7
- package/dist/property-DViA9nga.js.map +1 -0
- package/dist/{queries-BGuWjEqt.js → queries-ANFHy2e0.js} +2 -2
- package/dist/{queries-BGuWjEqt.js.map → queries-ANFHy2e0.js.map} +1 -1
- package/dist/seedSchema/EasSyncProcessSchema.ts +17 -0
- package/dist/seedSchema/index.ts +1 -0
- package/dist/src/Item/Item.d.ts +18 -0
- package/dist/src/Item/Item.d.ts.map +1 -1
- 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/saveImage.d.ts.map +1 -1
- package/dist/src/ItemProperty/service/propertyMachine.d.ts +4 -1
- package/dist/src/ItemProperty/service/propertyMachine.d.ts.map +1 -1
- package/dist/src/Model/service/modelMachine.d.ts +20 -20
- package/dist/src/ModelProperty/service/modelPropertyMachine.d.ts +2 -2
- package/dist/src/Schema/service/addModelsMachine.d.ts +1 -1
- package/dist/src/Schema/service/schemaMachine.d.ts +55 -55
- package/dist/src/browser/db/drizzleFiles.d.ts +3 -2
- package/dist/src/browser/db/drizzleFiles.d.ts.map +1 -1
- package/dist/src/browser/helpers/QueryClient.d.ts.map +1 -1
- package/dist/src/client/ClientManager.d.ts.map +1 -1
- 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/clientManagerMachine.d.ts.map +1 -1
- package/dist/src/client/constants.d.ts +1 -0
- package/dist/src/client/constants.d.ts.map +1 -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/write/applyPropertyAttestationUidsFromPublish.d.ts.map +1 -1
- package/dist/src/db/write/easSyncProcess.d.ts +12 -0
- package/dist/src/db/write/easSyncProcess.d.ts.map +1 -0
- package/dist/src/db/write/updateItemPropertyValue.d.ts.map +1 -1
- package/dist/src/eventBus.d.ts +13 -2
- package/dist/src/eventBus.d.ts.map +1 -1
- package/dist/src/events/files/download.d.ts +5 -1
- package/dist/src/events/files/download.d.ts.map +1 -1
- package/dist/src/events/item/easSyncManager.d.ts +71 -0
- package/dist/src/events/item/easSyncManager.d.ts.map +1 -0
- package/dist/src/events/item/index.d.ts.map +1 -1
- package/dist/src/events/item/mergeEasSyncOptions.d.ts +7 -0
- package/dist/src/events/item/mergeEasSyncOptions.d.ts.map +1 -0
- package/dist/src/events/item/syncDbWithEas.d.ts +0 -3
- package/dist/src/events/item/syncDbWithEas.d.ts.map +1 -1
- package/dist/src/helpers/ArweaveClient/BaseArweaveClient.d.ts +17 -0
- package/dist/src/helpers/ArweaveClient/BaseArweaveClient.d.ts.map +1 -1
- package/dist/src/helpers/ArweaveClient/arweaveL1UploadApi.d.ts +6 -0
- package/dist/src/helpers/ArweaveClient/arweaveL1UploadApi.d.ts.map +1 -1
- package/dist/src/helpers/ArweaveClient/selectReadGateway.d.ts +16 -0
- package/dist/src/helpers/ArweaveClient/selectReadGateway.d.ts.map +1 -0
- 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/compareMetadataRowsLatestFirst.d.ts +16 -0
- package/dist/src/helpers/compareMetadataRowsLatestFirst.d.ts.map +1 -0
- package/dist/src/helpers/constants.d.ts +20 -5
- package/dist/src/helpers/constants.d.ts.map +1 -1
- package/dist/src/helpers/environment.d.ts +5 -0
- package/dist/src/helpers/environment.d.ts.map +1 -1
- package/dist/src/helpers/htmlEmbeddedDataUriPublish.d.ts.map +1 -1
- package/dist/src/helpers/index.d.ts +1 -0
- package/dist/src/helpers/index.d.ts.map +1 -1
- package/dist/src/helpers/readHtmlBodyForStorageSeed.d.ts +8 -0
- package/dist/src/helpers/readHtmlBodyForStorageSeed.d.ts.map +1 -0
- package/dist/src/index.d.ts +7 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/interfaces/IQueryClient.d.ts +4 -0
- package/dist/src/interfaces/IQueryClient.d.ts.map +1 -1
- package/dist/src/node/helpers/QueryClient.d.ts.map +1 -1
- package/dist/src/seedSchema/EasSyncProcessSchema.d.ts +190 -0
- package/dist/src/seedSchema/EasSyncProcessSchema.d.ts.map +1 -0
- package/dist/src/seedSchema/index.d.ts +1 -0
- package/dist/src/seedSchema/index.d.ts.map +1 -1
- package/dist/src/services/write/writeProcessMachine.d.ts +1 -1
- package/dist/src/types/fileManager.d.ts +5 -0
- package/dist/src/types/fileManager.d.ts.map +1 -1
- package/dist/src/types/index.d.ts +3 -2
- package/dist/src/types/index.d.ts.map +1 -1
- package/dist/src/types/machines.d.ts +1 -1
- package/dist/src/types/machines.d.ts.map +1 -1
- package/dist/src/vite/index.d.ts.map +1 -1
- package/dist/syncDbWithEas-m-_3Ds7d.js +582 -0
- package/dist/syncDbWithEas-m-_3Ds7d.js.map +1 -0
- package/dist/updateSeedRevokedAt-BvAK-Rfh.js +22 -0
- package/dist/updateSeedRevokedAt-BvAK-Rfh.js.map +1 -0
- package/dist/vite.cjs +100 -26
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.js +100 -26
- package/dist/vite.js.map +1 -1
- package/package.json +1 -1
- package/dist/Db-CXwQVLZv.js.map +0 -1
- package/dist/FileManager-DHnyb040.js.map +0 -1
- package/dist/ModelProperty-DWtv9fQr.js.map +0 -1
- package/dist/QueryClient-OUjfvY3g.js.map +0 -1
- package/dist/QueryClient-unspcsWa.js.map +0 -1
- package/dist/cjs/getPublishUploads-DdVy-5fK.js.map +0 -1
- package/dist/cjs/index-D1qR8xnb.js.map +0 -1
- package/dist/cjs/index-DTkoTvcq.js.map +0 -1
- package/dist/getPublishPayload-DpYwi-rd.js.map +0 -1
- package/dist/getPublishUploads-DS2dQ4Ho.js.map +0 -1
- package/dist/index-BrD_NNaX.js.map +0 -1
- package/dist/index-Cqf_DxkJ.js.map +0 -1
- package/dist/index-DdzhrbkF.js.map +0 -1
- package/dist/property-C63Ddzap.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { waitFor, fromCallback, fromPromise, setup, assign, createActor } from 'xstate';
|
|
1
|
+
import { waitFor, fromCallback, fromPromise, setup, assign, stateIn, createActor, isMachineSnapshot } from 'xstate';
|
|
2
2
|
import { sqliteTable, integer, text, unique, int, blob, uniqueIndex } from 'drizzle-orm/sqlite-core';
|
|
3
3
|
import { relations, and, eq, isNull, isNotNull, not, or, max, count, getTableColumns, sql, desc, inArray, gt } from 'drizzle-orm';
|
|
4
4
|
import { customAlphabet } from 'nanoid';
|
|
@@ -8,9 +8,8 @@ import { ZeroAddress, getAddress } from 'ethers';
|
|
|
8
8
|
import pluralize from 'pluralize';
|
|
9
9
|
import { Type } from '@sinclair/typebox';
|
|
10
10
|
import { toSnakeCase as toSnakeCase$1 } from 'drizzle-orm/casing';
|
|
11
|
-
import { upperFirst, camelCase, startCase,
|
|
11
|
+
import { upperFirst, camelCase, startCase, throttle, orderBy } from 'lodash-es';
|
|
12
12
|
import { BehaviorSubject } from 'rxjs';
|
|
13
|
-
import EventEmitter from 'eventemitter3';
|
|
14
13
|
import 'arweave';
|
|
15
14
|
import * as sha3 from 'js-sha3';
|
|
16
15
|
|
|
@@ -157,6 +156,13 @@ class BaseFileManager {
|
|
|
157
156
|
static downloadAllFiles({ transactionIds, arweaveHost, excludedTransactions, }) {
|
|
158
157
|
return this.PlatformClass.downloadAllFiles({ transactionIds, arweaveHost, excludedTransactions });
|
|
159
158
|
}
|
|
159
|
+
static downloadFileByTransactionId({ transactionId, arweaveHost, excludedTransactions, }) {
|
|
160
|
+
return this.PlatformClass.downloadAllFiles({
|
|
161
|
+
transactionIds: [transactionId],
|
|
162
|
+
arweaveHost,
|
|
163
|
+
excludedTransactions,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
160
166
|
static resizeImage({ filePath, width, height }) {
|
|
161
167
|
return this.PlatformClass.resizeImage({ filePath, width, height });
|
|
162
168
|
}
|
|
@@ -365,12 +371,71 @@ var SeedModels;
|
|
|
365
371
|
// Internal SDK schema that should not be created in app's files directory
|
|
366
372
|
const SEED_PROTOCOL_SCHEMA_NAME = 'Seed Protocol';
|
|
367
373
|
const INTERNAL_SCHEMA_IDS = ['SEEDPROTOCOL'];
|
|
368
|
-
/** Default Arweave gateway host used across all packages */
|
|
369
|
-
const DEFAULT_ARWEAVE_HOST = '
|
|
374
|
+
/** Default Arweave gateway host used across all packages (first in {@link DEFAULT_ARWEAVE_GATEWAYS}) */
|
|
375
|
+
const DEFAULT_ARWEAVE_HOST = 'ar.seedprotocol.io';
|
|
370
376
|
/** Default Arweave gateway GraphQL endpoint (transaction / block queries). */
|
|
371
|
-
const DEFAULT_ARWEAVE_GRAPHQL_URL =
|
|
372
|
-
/**
|
|
373
|
-
|
|
377
|
+
const DEFAULT_ARWEAVE_GRAPHQL_URL = `https://${DEFAULT_ARWEAVE_HOST}/graphql`;
|
|
378
|
+
/**
|
|
379
|
+
* Default Arweave gateways for read fallback / metadata fetching (ordered by preference).
|
|
380
|
+
* Override order with `ARWEAVE_READ_GATEWAYS` or `NEXT_PUBLIC_ARWEAVE_READ_GATEWAYS` (comma-separated hosts).
|
|
381
|
+
*/
|
|
382
|
+
const DEFAULT_ARWEAVE_GATEWAYS = ['ar.seedprotocol.io', 'arweave.net', 'arweave.dev', 'g8way.io', 'permagate.io', 'zigza.xyz',];
|
|
383
|
+
const READ_GATEWAYS_ENV_KEYS = ['ARWEAVE_READ_GATEWAYS', 'NEXT_PUBLIC_ARWEAVE_READ_GATEWAYS'];
|
|
384
|
+
/** Ordered gateway hostnames for reads: env list if set, otherwise {@link DEFAULT_ARWEAVE_GATEWAYS}. */
|
|
385
|
+
function getDefaultArweaveReadGatewayHostsOrdered() {
|
|
386
|
+
if (typeof process === 'undefined' || !process.env) {
|
|
387
|
+
return [...DEFAULT_ARWEAVE_GATEWAYS];
|
|
388
|
+
}
|
|
389
|
+
for (const key of READ_GATEWAYS_ENV_KEYS) {
|
|
390
|
+
const raw = process.env[key]?.trim();
|
|
391
|
+
if (raw) {
|
|
392
|
+
return raw.split(',').map((s) => s.trim()).filter(Boolean);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
return [...DEFAULT_ARWEAVE_GATEWAYS];
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* Deduped host list: primary first, then each default not already present (case-insensitive).
|
|
399
|
+
*/
|
|
400
|
+
function mergePrimaryHostWithDefaults(primary, defaults) {
|
|
401
|
+
const seen = new Set();
|
|
402
|
+
const out = [];
|
|
403
|
+
const keyOf = (h) => h.trim().toLowerCase().replace(/\/$/, '');
|
|
404
|
+
const add = (h) => {
|
|
405
|
+
const t = h.trim().replace(/\/$/, '');
|
|
406
|
+
if (!t)
|
|
407
|
+
return;
|
|
408
|
+
const k = keyOf(t);
|
|
409
|
+
if (seen.has(k))
|
|
410
|
+
return;
|
|
411
|
+
seen.add(k);
|
|
412
|
+
out.push(t);
|
|
413
|
+
};
|
|
414
|
+
add(primary);
|
|
415
|
+
for (const d of defaults)
|
|
416
|
+
add(d);
|
|
417
|
+
return out;
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* True if `hostname` looks like a public Arweave gateway used in stored URLs (hydration / RSS).
|
|
421
|
+
*/
|
|
422
|
+
function isKnownArweaveGatewayHostname(hostname) {
|
|
423
|
+
const h = hostname.trim().toLowerCase();
|
|
424
|
+
if (!h)
|
|
425
|
+
return false;
|
|
426
|
+
if (h.endsWith('arweave.net'))
|
|
427
|
+
return true;
|
|
428
|
+
if (h.endsWith('ar-io.net'))
|
|
429
|
+
return true;
|
|
430
|
+
for (const g of DEFAULT_ARWEAVE_GATEWAYS) {
|
|
431
|
+
const gl = g.toLowerCase();
|
|
432
|
+
if (h === gl || h.endsWith(`.${gl}`))
|
|
433
|
+
return true;
|
|
434
|
+
}
|
|
435
|
+
return false;
|
|
436
|
+
}
|
|
437
|
+
/** Fired after `syncDbWithEas` persists EAS seeds/versions/metadata to SQLite (see `Item.rehydrateCachedItemsFromDbAfterEasSync`). */
|
|
438
|
+
const EAS_SEED_DATA_SYNCED_TO_DB_EVENT = 'easSeedDataSyncedToDb';
|
|
374
439
|
/**
|
|
375
440
|
* Check if a schema is an internal SDK schema that should not be created in app files
|
|
376
441
|
*/
|
|
@@ -385,6 +450,7 @@ var constants = /*#__PURE__*/Object.freeze({
|
|
|
385
450
|
DEFAULT_ARWEAVE_GATEWAYS: DEFAULT_ARWEAVE_GATEWAYS,
|
|
386
451
|
DEFAULT_ARWEAVE_GRAPHQL_URL: DEFAULT_ARWEAVE_GRAPHQL_URL,
|
|
387
452
|
DEFAULT_ARWEAVE_HOST: DEFAULT_ARWEAVE_HOST,
|
|
453
|
+
EAS_SEED_DATA_SYNCED_TO_DB_EVENT: EAS_SEED_DATA_SYNCED_TO_DB_EVENT,
|
|
388
454
|
INIT_SCRIPT_SUCCESS_MESSAGE: INIT_SCRIPT_SUCCESS_MESSAGE,
|
|
389
455
|
INTERNAL_DATA_TYPES: INTERNAL_DATA_TYPES,
|
|
390
456
|
INTERNAL_PROPERTY_NAMES: INTERNAL_PROPERTY_NAMES,
|
|
@@ -402,7 +468,10 @@ var constants = /*#__PURE__*/Object.freeze({
|
|
|
402
468
|
ZERO_BYTES: ZERO_BYTES,
|
|
403
469
|
ZERO_BYTES32: ZERO_BYTES32,
|
|
404
470
|
defaultAttestationData: defaultAttestationData,
|
|
405
|
-
|
|
471
|
+
getDefaultArweaveReadGatewayHostsOrdered: getDefaultArweaveReadGatewayHostsOrdered,
|
|
472
|
+
isInternalSchema: isInternalSchema,
|
|
473
|
+
isKnownArweaveGatewayHostname: isKnownArweaveGatewayHostname,
|
|
474
|
+
mergePrimaryHostWithDefaults: mergePrimaryHostWithDefaults
|
|
406
475
|
});
|
|
407
476
|
|
|
408
477
|
function parseGateway(input) {
|
|
@@ -419,6 +488,8 @@ function parseGateway(input) {
|
|
|
419
488
|
let _host = DEFAULT_ARWEAVE_HOST;
|
|
420
489
|
let _protocol = 'https';
|
|
421
490
|
let _hostExplicitlySet = false;
|
|
491
|
+
/** When true, production `ARWEAVE_HOST` / `NEXT_PUBLIC_ARWEAVE_HOST` does not override `_host` (after a successful read-gateway probe). */
|
|
492
|
+
let _suppressEnvGatewayOverride = false;
|
|
422
493
|
class BaseArweaveClient {
|
|
423
494
|
static setPlatformClass(platformClass) {
|
|
424
495
|
this.PlatformClass = platformClass;
|
|
@@ -431,7 +502,7 @@ class BaseArweaveClient {
|
|
|
431
502
|
const envHost = typeof process !== 'undefined' && process.env
|
|
432
503
|
? process.env.NEXT_PUBLIC_ARWEAVE_HOST || process.env.ARWEAVE_HOST
|
|
433
504
|
: undefined;
|
|
434
|
-
if (envHost && !_hostExplicitlySet) {
|
|
505
|
+
if (envHost && !_hostExplicitlySet && !_suppressEnvGatewayOverride) {
|
|
435
506
|
return parseGateway(envHost);
|
|
436
507
|
}
|
|
437
508
|
}
|
|
@@ -469,6 +540,39 @@ class BaseArweaveClient {
|
|
|
469
540
|
_host = parsed.host;
|
|
470
541
|
_protocol = parsed.protocol;
|
|
471
542
|
_hostExplicitlySet = true;
|
|
543
|
+
_suppressEnvGatewayOverride = false;
|
|
544
|
+
}
|
|
545
|
+
/**
|
|
546
|
+
* When true, read-path gateway probing does not change the host ({@link setHost}).
|
|
547
|
+
*/
|
|
548
|
+
static isReadGatewayLocked() {
|
|
549
|
+
return _hostExplicitlySet;
|
|
550
|
+
}
|
|
551
|
+
/**
|
|
552
|
+
* @internal Clears env override suppression after probing (for test isolation).
|
|
553
|
+
*/
|
|
554
|
+
static resetReadGatewaySelectionStateForTests() {
|
|
555
|
+
_suppressEnvGatewayOverride = false;
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* Sets the preferred read gateway without locking. Production env host still takes precedence until a probe applies a host.
|
|
559
|
+
* Used for seed `arweaveDomain`.
|
|
560
|
+
*/
|
|
561
|
+
static setPreferredReadGateway(host) {
|
|
562
|
+
const parsed = parseGateway(host);
|
|
563
|
+
_host = parsed.host;
|
|
564
|
+
_protocol = parsed.protocol;
|
|
565
|
+
_hostExplicitlySet = false;
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* Applies a gateway chosen by read-path health probing so {@link getHost} uses it instead of env override.
|
|
569
|
+
*/
|
|
570
|
+
static applyProbedReadGateway(host) {
|
|
571
|
+
const parsed = parseGateway(host);
|
|
572
|
+
_host = parsed.host;
|
|
573
|
+
_protocol = parsed.protocol;
|
|
574
|
+
_hostExplicitlySet = false;
|
|
575
|
+
_suppressEnvGatewayOverride = true;
|
|
472
576
|
}
|
|
473
577
|
/**
|
|
474
578
|
* Get the GraphQL endpoint URL
|
|
@@ -552,6 +656,11 @@ class BaseArweaveClient {
|
|
|
552
656
|
}
|
|
553
657
|
}
|
|
554
658
|
|
|
659
|
+
var BaseArweaveClient$1 = /*#__PURE__*/Object.freeze({
|
|
660
|
+
__proto__: null,
|
|
661
|
+
BaseArweaveClient: BaseArweaveClient
|
|
662
|
+
});
|
|
663
|
+
|
|
555
664
|
/**
|
|
556
665
|
* Trim and strip a trailing slash from an upload API base URL.
|
|
557
666
|
*/
|
|
@@ -603,6 +712,126 @@ async function getUploadPipelineTransactionStatus(uploadApiBaseUrl, txOrDataItem
|
|
|
603
712
|
}
|
|
604
713
|
}
|
|
605
714
|
|
|
715
|
+
const READ_GATEWAY_CACHE_TTL_MS = 3 * 60 * 1000;
|
|
716
|
+
const PROBE_TIMEOUT_MS = 5000;
|
|
717
|
+
let readGatewayCache = null;
|
|
718
|
+
let ensureInFlight = null;
|
|
719
|
+
/** Clears cached read gateway (e.g. after tests or to force a fresh probe). */
|
|
720
|
+
function invalidateReadGatewayCache() {
|
|
721
|
+
readGatewayCache = null;
|
|
722
|
+
ensureInFlight = null;
|
|
723
|
+
}
|
|
724
|
+
/** Clears probe cache, env override suppression, and preferred host (for tests). */
|
|
725
|
+
function resetArweaveReadGatewayForTests() {
|
|
726
|
+
invalidateReadGatewayCache();
|
|
727
|
+
BaseArweaveClient.resetReadGatewaySelectionStateForTests();
|
|
728
|
+
if (!BaseArweaveClient.isReadGatewayLocked()) {
|
|
729
|
+
BaseArweaveClient.setPreferredReadGateway(DEFAULT_ARWEAVE_HOST);
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
/**
|
|
733
|
+
* GET /info with timeout. Treat 2xx + JSON object as healthy.
|
|
734
|
+
*/
|
|
735
|
+
async function probeGateway(baseUrl, signal) {
|
|
736
|
+
const url = `${baseUrl.replace(/\/$/, '')}/info`;
|
|
737
|
+
let timer;
|
|
738
|
+
const controller = new AbortController();
|
|
739
|
+
const effectiveSignal = signal ?? controller.signal;
|
|
740
|
+
if (!signal) {
|
|
741
|
+
timer = setTimeout(() => controller.abort(), PROBE_TIMEOUT_MS);
|
|
742
|
+
}
|
|
743
|
+
try {
|
|
744
|
+
const response = await fetch(url, {
|
|
745
|
+
method: 'GET',
|
|
746
|
+
signal: effectiveSignal,
|
|
747
|
+
headers: { Accept: 'application/json' },
|
|
748
|
+
});
|
|
749
|
+
if (!response.ok)
|
|
750
|
+
return false;
|
|
751
|
+
const text = await response.text();
|
|
752
|
+
if (!text.trim())
|
|
753
|
+
return false;
|
|
754
|
+
try {
|
|
755
|
+
const json = JSON.parse(text);
|
|
756
|
+
return typeof json === 'object' && json !== null;
|
|
757
|
+
}
|
|
758
|
+
catch {
|
|
759
|
+
return false;
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
catch {
|
|
763
|
+
return false;
|
|
764
|
+
}
|
|
765
|
+
finally {
|
|
766
|
+
if (timer)
|
|
767
|
+
clearTimeout(timer);
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
async function selectFirstHealthyReadGateway(hosts, protocol = 'https', signal) {
|
|
771
|
+
for (const host of hosts) {
|
|
772
|
+
const h = host.trim().replace(/\/$/, '');
|
|
773
|
+
if (!h)
|
|
774
|
+
continue;
|
|
775
|
+
const baseUrl = `${protocol}://${h}`;
|
|
776
|
+
if (await probeGateway(baseUrl, signal)) {
|
|
777
|
+
return h;
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
return null;
|
|
781
|
+
}
|
|
782
|
+
function buildOrderedHostsForProbe() {
|
|
783
|
+
const primary = BaseArweaveClient.getHost();
|
|
784
|
+
const defaults = getDefaultArweaveReadGatewayHostsOrdered();
|
|
785
|
+
return mergePrimaryHostWithDefaults(primary, defaults);
|
|
786
|
+
}
|
|
787
|
+
/**
|
|
788
|
+
* Probes gateways in order and applies the first healthy host via {@link BaseArweaveClient.applyProbedReadGateway}.
|
|
789
|
+
* No-op when the read gateway is locked ({@link BaseArweaveClient.setHost}).
|
|
790
|
+
* Uses a short TTL cache to avoid probing on every read.
|
|
791
|
+
*/
|
|
792
|
+
async function ensureReadGatewaySelected(signal) {
|
|
793
|
+
if (BaseArweaveClient.isReadGatewayLocked()) {
|
|
794
|
+
return BaseArweaveClient.getHost();
|
|
795
|
+
}
|
|
796
|
+
const now = Date.now();
|
|
797
|
+
if (readGatewayCache && now < readGatewayCache.expiresAt) {
|
|
798
|
+
return readGatewayCache.host;
|
|
799
|
+
}
|
|
800
|
+
if (ensureInFlight) {
|
|
801
|
+
return ensureInFlight;
|
|
802
|
+
}
|
|
803
|
+
ensureInFlight = (async () => {
|
|
804
|
+
const ordered = buildOrderedHostsForProbe();
|
|
805
|
+
const protocol = BaseArweaveClient.getProtocol();
|
|
806
|
+
const picked = await selectFirstHealthyReadGateway(ordered, protocol, signal);
|
|
807
|
+
if (!BaseArweaveClient.isReadGatewayLocked()) {
|
|
808
|
+
if (picked) {
|
|
809
|
+
BaseArweaveClient.applyProbedReadGateway(picked);
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
readGatewayCache = {
|
|
813
|
+
host: BaseArweaveClient.getHost(),
|
|
814
|
+
expiresAt: Date.now() + READ_GATEWAY_CACHE_TTL_MS,
|
|
815
|
+
};
|
|
816
|
+
return readGatewayCache.host;
|
|
817
|
+
})();
|
|
818
|
+
try {
|
|
819
|
+
return await ensureInFlight;
|
|
820
|
+
}
|
|
821
|
+
finally {
|
|
822
|
+
ensureInFlight = null;
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
var selectReadGateway = /*#__PURE__*/Object.freeze({
|
|
827
|
+
__proto__: null,
|
|
828
|
+
ensureReadGatewaySelected: ensureReadGatewaySelected,
|
|
829
|
+
invalidateReadGatewayCache: invalidateReadGatewayCache,
|
|
830
|
+
probeGateway: probeGateway,
|
|
831
|
+
resetArweaveReadGatewayForTests: resetArweaveReadGatewayForTests,
|
|
832
|
+
selectFirstHealthyReadGateway: selectFirstHealthyReadGateway
|
|
833
|
+
});
|
|
834
|
+
|
|
606
835
|
const GATEWAY_TX_QUERY = `
|
|
607
836
|
query ArweaveGatewayTransaction($id: String!) {
|
|
608
837
|
transaction(id: $id) {
|
|
@@ -699,6 +928,42 @@ async function queryArweaveGatewayTransaction(graphqlUrl, dataItemId, init) {
|
|
|
699
928
|
return null;
|
|
700
929
|
}
|
|
701
930
|
}
|
|
931
|
+
/**
|
|
932
|
+
* Resolves GraphQL against the first healthy gateway (GET /info probe per host), then runs
|
|
933
|
+
* {@link queryArweaveGatewayTransaction}. Host order: optional `graphqlUrl` hostname first, then
|
|
934
|
+
* {@link getDefaultArweaveReadGatewayHostsOrdered}.
|
|
935
|
+
*/
|
|
936
|
+
async function queryArweaveGatewayTransactionWithFallback(graphqlUrl, dataItemId, init) {
|
|
937
|
+
const defaults = getDefaultArweaveReadGatewayHostsOrdered();
|
|
938
|
+
const trimmed = graphqlUrl?.trim();
|
|
939
|
+
let protocol = 'https';
|
|
940
|
+
let preferredHost = null;
|
|
941
|
+
if (trimmed) {
|
|
942
|
+
try {
|
|
943
|
+
const u = new URL(trimmed);
|
|
944
|
+
protocol = u.protocol === 'http:' ? 'http' : 'https';
|
|
945
|
+
preferredHost = u.hostname || null;
|
|
946
|
+
}
|
|
947
|
+
catch {
|
|
948
|
+
preferredHost = null;
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
const ordered = preferredHost && preferredHost.length > 0
|
|
952
|
+
? mergePrimaryHostWithDefaults(preferredHost, defaults)
|
|
953
|
+
: [...defaults];
|
|
954
|
+
const signal = init?.signal;
|
|
955
|
+
for (const host of ordered) {
|
|
956
|
+
const base = `${protocol}://${host}`;
|
|
957
|
+
if (!(await probeGateway(base, signal ?? undefined)))
|
|
958
|
+
continue;
|
|
959
|
+
const gqlUrl = `${protocol}://${host}/graphql`;
|
|
960
|
+
const result = await queryArweaveGatewayTransaction(gqlUrl, dataItemId, init);
|
|
961
|
+
if (result !== null) {
|
|
962
|
+
return result;
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
return null;
|
|
966
|
+
}
|
|
702
967
|
|
|
703
968
|
class BaseEasClient {
|
|
704
969
|
static setPlatformClass(platformClass) {
|
|
@@ -1374,6 +1639,19 @@ const arweaveL1FinalizeJobs = sqliteTable('arweave_l1_finalize_jobs', {
|
|
|
1374
1639
|
dataItemIdUnique: uniqueIndex('arweave_l1_finalize_jobs_data_item_id_unique').on(table.dataItemId),
|
|
1375
1640
|
}));
|
|
1376
1641
|
|
|
1642
|
+
const easSyncProcesses = sqliteTable('eas_sync_processes', {
|
|
1643
|
+
id: int('id').primaryKey({ autoIncrement: true }),
|
|
1644
|
+
status: text('status').notNull(), // 'in_progress' | 'completed' | 'failed'
|
|
1645
|
+
startedAt: int('started_at').notNull(),
|
|
1646
|
+
completedAt: int('completed_at'),
|
|
1647
|
+
requestPayload: text('request_payload').notNull(),
|
|
1648
|
+
errorMessage: text('error_message'),
|
|
1649
|
+
errorDetails: text('error_details'),
|
|
1650
|
+
persistedSnapshot: text('persisted_snapshot').notNull(),
|
|
1651
|
+
createdAt: int('created_at'),
|
|
1652
|
+
updatedAt: int('updated_at'),
|
|
1653
|
+
});
|
|
1654
|
+
|
|
1377
1655
|
/**
|
|
1378
1656
|
* Links Image seeds materialized from Html `data:image/*` URIs to the parent Item seed for co-publish.
|
|
1379
1657
|
* Rows are removed after a successful publish (see clearHtmlEmbeddedImageCoPublishRows).
|
|
@@ -1864,6 +2142,7 @@ var index = /*#__PURE__*/Object.freeze({
|
|
|
1864
2142
|
capitalizeFirstLetter: capitalizeFirstLetter,
|
|
1865
2143
|
classifyMediaRef: classifyMediaRef,
|
|
1866
2144
|
convertTxIdToImage: convertTxIdToImage,
|
|
2145
|
+
ensureReadGatewaySelected: ensureReadGatewaySelected,
|
|
1867
2146
|
generateId: generateId,
|
|
1868
2147
|
getAlternatePropertyNameForInstanceLookup: getAlternatePropertyNameForInstanceLookup,
|
|
1869
2148
|
getArweaveUploadStatus: getArweaveUploadStatus,
|
|
@@ -1883,6 +2162,7 @@ var index = /*#__PURE__*/Object.freeze({
|
|
|
1883
2162
|
getUploadExecutor: getUploadExecutor,
|
|
1884
2163
|
getUploadPipelineTransactionStatus: getUploadPipelineTransactionStatus,
|
|
1885
2164
|
identifyString: identifyString,
|
|
2165
|
+
invalidateReadGatewayCache: invalidateReadGatewayCache,
|
|
1886
2166
|
isArweaveL1AnchoringComplete: isArweaveL1AnchoringComplete,
|
|
1887
2167
|
isBinary: isBinary,
|
|
1888
2168
|
isPlaceholderUid: isPlaceholderUid,
|
|
@@ -1895,11 +2175,15 @@ var index = /*#__PURE__*/Object.freeze({
|
|
|
1895
2175
|
normalizeUploadApiBaseUrl: normalizeUploadApiBaseUrl,
|
|
1896
2176
|
parseEasRelationPropertyName: parseEasRelationPropertyName,
|
|
1897
2177
|
pickLatestPropertyAttestationsByRefAndSchema: pickLatestPropertyAttestationsByRefAndSchema,
|
|
2178
|
+
probeGateway: probeGateway,
|
|
1898
2179
|
queryArweaveGatewayTransaction: queryArweaveGatewayTransaction,
|
|
2180
|
+
queryArweaveGatewayTransactionWithFallback: queryArweaveGatewayTransactionWithFallback,
|
|
2181
|
+
resetArweaveReadGatewayForTests: resetArweaveReadGatewayForTests,
|
|
1899
2182
|
resolveMediaRef: resolveMediaRef,
|
|
1900
2183
|
resolveMetadataRecord: resolveMetadataRecord,
|
|
1901
2184
|
resolveSeedIdsFromRefString: resolveSeedIdsFromRefString,
|
|
1902
2185
|
resolveStorageNameToSchemaName: resolveStorageNameToSchemaName,
|
|
2186
|
+
selectFirstHealthyReadGateway: selectFirstHealthyReadGateway,
|
|
1903
2187
|
setAdditionalSyncAddresses: setAdditionalSyncAddresses,
|
|
1904
2188
|
setGetPublisherForNewSeeds: setGetPublisherForNewSeeds,
|
|
1905
2189
|
setRevokeExecutor: setRevokeExecutor,
|
|
@@ -1922,7 +2206,7 @@ const createPropertyInstances = async (propertyFileIds) => {
|
|
|
1922
2206
|
return;
|
|
1923
2207
|
}
|
|
1924
2208
|
try {
|
|
1925
|
-
const mod = await import('./ModelProperty-
|
|
2209
|
+
const mod = await import('./ModelProperty-D6JLRqQW.js');
|
|
1926
2210
|
const ModelProperty = mod?.ModelProperty ?? mod?.default;
|
|
1927
2211
|
if (!ModelProperty) {
|
|
1928
2212
|
logger$t('createPropertyInstances: ModelProperty not available from dynamic import');
|
|
@@ -2106,7 +2390,7 @@ const loadOrCreateModel = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
2106
2390
|
// Step 2: Fallback to Schema context (only if database doesn't have the model)
|
|
2107
2391
|
// This handles the case where model exists in schema file but not yet in database
|
|
2108
2392
|
try {
|
|
2109
|
-
const _mod_0 = await import('./Schema-
|
|
2393
|
+
const _mod_0 = await import('./Schema-B5_B8nM5.js');
|
|
2110
2394
|
const _ns_0 = _mod_0.b;
|
|
2111
2395
|
const schemaMod = _ns_0;
|
|
2112
2396
|
const { Schema } = schemaMod;
|
|
@@ -2352,7 +2636,7 @@ const loadOrCreateModel = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
2352
2636
|
}
|
|
2353
2637
|
// Mark schema as draft when a new model is created so saveNewVersion() can persist it
|
|
2354
2638
|
try {
|
|
2355
|
-
const _mod_1 = await import('./Schema-
|
|
2639
|
+
const _mod_1 = await import('./Schema-B5_B8nM5.js');
|
|
2356
2640
|
const _ns_1 = _mod_1.b;
|
|
2357
2641
|
const schemaMod = _ns_1;
|
|
2358
2642
|
const { Schema } = schemaMod;
|
|
@@ -2398,10 +2682,10 @@ const validateModel = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
2398
2682
|
const _validateModel = async () => {
|
|
2399
2683
|
try {
|
|
2400
2684
|
// Use dynamic imports to break circular dependencies
|
|
2401
|
-
const validationServiceMod = await import('./SchemaValidationService-
|
|
2685
|
+
const validationServiceMod = await import('./SchemaValidationService-DXYRdSYa.js');
|
|
2402
2686
|
const { SchemaValidationService } = validationServiceMod;
|
|
2403
2687
|
const validationService = new SchemaValidationService();
|
|
2404
|
-
const _mod_2 = await import('./Schema-
|
|
2688
|
+
const _mod_2 = await import('./Schema-B5_B8nM5.js');
|
|
2405
2689
|
const _ns_2 = _mod_2.b;
|
|
2406
2690
|
const schemaMod = _ns_2;
|
|
2407
2691
|
const { Schema } = schemaMod;
|
|
@@ -2513,7 +2797,7 @@ const createModelProperties = fromCallback(({ sendBack, input }) => {
|
|
|
2513
2797
|
return;
|
|
2514
2798
|
}
|
|
2515
2799
|
logger$r(`Creating ${Object.keys(propertyDefinitions).length} properties for model "${modelName}" (id: ${_dbId})`);
|
|
2516
|
-
const mod = await import('./ModelProperty-
|
|
2800
|
+
const mod = await import('./ModelProperty-D6JLRqQW.js');
|
|
2517
2801
|
const ModelProperty = mod?.ModelProperty ?? mod?.default;
|
|
2518
2802
|
if (!ModelProperty) {
|
|
2519
2803
|
logger$r('ModelProperty not available from dynamic import');
|
|
@@ -2617,7 +2901,7 @@ const validateEntity = fromPromise(async ({ input }) => {
|
|
|
2617
2901
|
const structureMsg = `[validateEntity] Validating model structure`;
|
|
2618
2902
|
logger$q(structureMsg);
|
|
2619
2903
|
// Use existing Model validation
|
|
2620
|
-
const validationServiceMod = await import('./SchemaValidationService-
|
|
2904
|
+
const validationServiceMod = await import('./SchemaValidationService-DXYRdSYa.js');
|
|
2621
2905
|
const { SchemaValidationService } = validationServiceMod;
|
|
2622
2906
|
const validationService = new SchemaValidationService();
|
|
2623
2907
|
// Validate model structure
|
|
@@ -2635,7 +2919,7 @@ const validateEntity = fromPromise(async ({ input }) => {
|
|
|
2635
2919
|
if (entityInput.entityData.schemaName) {
|
|
2636
2920
|
try {
|
|
2637
2921
|
logger$q(`[validateEntity] Validating model against schema "${entityInput.entityData.schemaName}"`);
|
|
2638
|
-
const _mod_3 = await import('./Schema-
|
|
2922
|
+
const _mod_3 = await import('./Schema-B5_B8nM5.js');
|
|
2639
2923
|
const _ns_3 = _mod_3.b;
|
|
2640
2924
|
const schemaMod = _ns_3;
|
|
2641
2925
|
const { Schema } = schemaMod;
|
|
@@ -2673,7 +2957,7 @@ const validateEntity = fromPromise(async ({ input }) => {
|
|
|
2673
2957
|
}
|
|
2674
2958
|
else if (entityInput.entityType === 'modelProperty') {
|
|
2675
2959
|
// Use existing ModelProperty validation
|
|
2676
|
-
const validationServiceMod = await import('./SchemaValidationService-
|
|
2960
|
+
const validationServiceMod = await import('./SchemaValidationService-DXYRdSYa.js');
|
|
2677
2961
|
const { SchemaValidationService } = validationServiceMod;
|
|
2678
2962
|
const validationService = new SchemaValidationService();
|
|
2679
2963
|
// Validate property structure
|
|
@@ -2688,7 +2972,7 @@ const validateEntity = fromPromise(async ({ input }) => {
|
|
|
2688
2972
|
// If schema name and model name provided, validate against schema
|
|
2689
2973
|
if (entityInput.entityData._schemaName && entityInput.entityData.modelName) {
|
|
2690
2974
|
try {
|
|
2691
|
-
const _mod_4 = await import('./Schema-
|
|
2975
|
+
const _mod_4 = await import('./Schema-B5_B8nM5.js');
|
|
2692
2976
|
const _ns_4 = _mod_4.b;
|
|
2693
2977
|
const schemaMod = _ns_4;
|
|
2694
2978
|
const { Schema } = schemaMod;
|
|
@@ -2719,7 +3003,7 @@ const validateEntity = fromPromise(async ({ input }) => {
|
|
|
2719
3003
|
}
|
|
2720
3004
|
else if (entityInput.entityType === 'schema') {
|
|
2721
3005
|
// Schema validation - use existing validation
|
|
2722
|
-
const validationServiceMod = await import('./SchemaValidationService-
|
|
3006
|
+
const validationServiceMod = await import('./SchemaValidationService-DXYRdSYa.js');
|
|
2723
3007
|
const { SchemaValidationService } = validationServiceMod;
|
|
2724
3008
|
const validationService = new SchemaValidationService();
|
|
2725
3009
|
const schemaResult = validationService.validateSchema(entityInput.entityData);
|
|
@@ -4671,7 +4955,7 @@ const writeToDatabase = fromCallback(({ sendBack, input }) => {
|
|
|
4671
4955
|
// initial write completes is not overwritten by the stale requestWrite payload.
|
|
4672
4956
|
let dataToWrite = input.entityData;
|
|
4673
4957
|
try {
|
|
4674
|
-
const mod = await import('./ModelProperty-
|
|
4958
|
+
const mod = await import('./ModelProperty-D6JLRqQW.js');
|
|
4675
4959
|
const ModelProperty = mod?.ModelProperty ?? mod?.default;
|
|
4676
4960
|
if (ModelProperty && typeof ModelProperty.getById === 'function') {
|
|
4677
4961
|
const instance = ModelProperty.getById(input.entityId);
|
|
@@ -5051,7 +5335,7 @@ const modelMachine = setup({
|
|
|
5051
5335
|
// Create ModelProperty instances for any new property IDs
|
|
5052
5336
|
if (Array.isArray(newPropertyIds) && newPropertyIds.length > 0) {
|
|
5053
5337
|
// Import and create instances asynchronously (fire-and-forget)
|
|
5054
|
-
import('./ModelProperty-
|
|
5338
|
+
import('./ModelProperty-D6JLRqQW.js').then(({ ModelProperty }) => {
|
|
5055
5339
|
const createPromises = newPropertyIds.map(async (propertyFileId) => {
|
|
5056
5340
|
try {
|
|
5057
5341
|
const property = await ModelProperty.createById(propertyFileId);
|
|
@@ -5354,6 +5638,7 @@ const ENV = (typeof process !== 'undefined' && process.env)
|
|
|
5354
5638
|
var MachineIds;
|
|
5355
5639
|
(function (MachineIds) {
|
|
5356
5640
|
MachineIds["CLIENT_MANAGER"] = "@seedSdk/clientManager";
|
|
5641
|
+
MachineIds["EAS_SYNC_MANAGER"] = "@seedSdk/easSyncManager";
|
|
5357
5642
|
MachineIds["GLOBAL"] = "@seedSdk/global";
|
|
5358
5643
|
MachineIds["INTERNAL"] = "@seedSdk/internal";
|
|
5359
5644
|
MachineIds["EAS"] = "@seedSdk/eas";
|
|
@@ -5426,7 +5711,7 @@ const EAS_ENDPOINT = ENV.NEXT_PUBLIC_EAS_ENDPOINT ||
|
|
|
5426
5711
|
* This constant is kept for backward compatibility but will be removed in a future version.
|
|
5427
5712
|
* Migration: import { BaseArweaveClient } from '@/helpers' and use BaseArweaveClient.getHost()
|
|
5428
5713
|
*/
|
|
5429
|
-
ENV.NEXT_PUBLIC_ARWEAVE_HOST || '
|
|
5714
|
+
ENV.NEXT_PUBLIC_ARWEAVE_HOST || 'ar.seedprotocol.io';
|
|
5430
5715
|
|
|
5431
5716
|
debug('seedSdk:item:service:actors:waitForDb');
|
|
5432
5717
|
const waitForDb$1 = fromCallback(({ sendBack }) => {
|
|
@@ -6347,7 +6632,7 @@ const getMetadataLatest = ({ seedLocalId, seedUid }) => {
|
|
|
6347
6632
|
rowNum: sql.raw(`
|
|
6348
6633
|
ROW_NUMBER() OVER (
|
|
6349
6634
|
PARTITION BY property_name
|
|
6350
|
-
ORDER BY COALESCE(attestation_created_at, created_at) DESC
|
|
6635
|
+
ORDER BY COALESCE(attestation_created_at, created_at) DESC, local_id DESC
|
|
6351
6636
|
)
|
|
6352
6637
|
`).as('rowNum')
|
|
6353
6638
|
})
|
|
@@ -6360,6 +6645,25 @@ var metadataLatest = /*#__PURE__*/Object.freeze({
|
|
|
6360
6645
|
getMetadataLatest: getMetadataLatest
|
|
6361
6646
|
});
|
|
6362
6647
|
|
|
6648
|
+
/**
|
|
6649
|
+
* Canonical "latest metadata row first" ordering. Must stay in sync with SQL that uses:
|
|
6650
|
+
* `ORDER BY COALESCE(attestation_created_at, created_at) DESC, local_id DESC`
|
|
6651
|
+
*/
|
|
6652
|
+
function metadataLatestFirstSortKey(row) {
|
|
6653
|
+
return {
|
|
6654
|
+
t: row.attestationCreatedAt ?? row.createdAt ?? 0,
|
|
6655
|
+
localId: String(row.localId ?? ''),
|
|
6656
|
+
};
|
|
6657
|
+
}
|
|
6658
|
+
/** Sort comparator: larger time first; on tie, larger localId (lexicographic) first. */
|
|
6659
|
+
function compareMetadataRowsLatestFirst(a, b) {
|
|
6660
|
+
const ka = metadataLatestFirstSortKey(a);
|
|
6661
|
+
const kb = metadataLatestFirstSortKey(b);
|
|
6662
|
+
if (kb.t !== ka.t)
|
|
6663
|
+
return kb.t - ka.t;
|
|
6664
|
+
return kb.localId.localeCompare(ka.localId);
|
|
6665
|
+
}
|
|
6666
|
+
|
|
6363
6667
|
const logger$l = debug('seedSdk:item:actors:loadOrCreateItem');
|
|
6364
6668
|
/**
|
|
6365
6669
|
* Maps metadata.property_name to the ItemProperty Map key (same rules as the instance loop below).
|
|
@@ -6401,9 +6705,8 @@ function pickBetterMetadataRowForSameInstance(a, b) {
|
|
|
6401
6705
|
return b;
|
|
6402
6706
|
if (sa !== sb)
|
|
6403
6707
|
return sa > sb ? a : b;
|
|
6404
|
-
const
|
|
6405
|
-
|
|
6406
|
-
return ta >= tb ? a : b;
|
|
6708
|
+
const cmp = compareMetadataRowsLatestFirst(a, b);
|
|
6709
|
+
return cmp < 0 ? a : b;
|
|
6407
6710
|
}
|
|
6408
6711
|
function dedupeMetadataRowsByInstanceKey(metadataRows, propertySchemas) {
|
|
6409
6712
|
const byKey = new Map();
|
|
@@ -6451,7 +6754,7 @@ const createItemPropertyInstances = async (metadataRows, seedLocalId, seedUid, m
|
|
|
6451
6754
|
const schemaNameToTry = model$1?.schemaName;
|
|
6452
6755
|
if (schemaNameToTry) {
|
|
6453
6756
|
try {
|
|
6454
|
-
const _mod_5 = await import('./Schema-
|
|
6757
|
+
const _mod_5 = await import('./Schema-B5_B8nM5.js');
|
|
6455
6758
|
const _ns_5 = _mod_5.b;
|
|
6456
6759
|
const { Schema } = _ns_5;
|
|
6457
6760
|
const schemaInstance = Schema.create(schemaNameToTry, { waitForReady: false });
|
|
@@ -6502,7 +6805,7 @@ const createItemPropertyInstances = async (metadataRows, seedLocalId, seedUid, m
|
|
|
6502
6805
|
}
|
|
6503
6806
|
}
|
|
6504
6807
|
if (Object.keys(propertySchemas).length === 0) {
|
|
6505
|
-
const schemaMod = await import('./index-
|
|
6808
|
+
const schemaMod = await import('./index-DB3nZ0lK.js');
|
|
6506
6809
|
const { ModelPropertyDataTypes } = schemaMod;
|
|
6507
6810
|
const KNOWN_MODEL_FALLBACKS = {
|
|
6508
6811
|
Post: {
|
|
@@ -6549,7 +6852,7 @@ const createItemPropertyInstances = async (metadataRows, seedLocalId, seedUid, m
|
|
|
6549
6852
|
// Infer propertyRecordSchema from metadata when schema is missing (enables persistence)
|
|
6550
6853
|
let propSchema = propertySchemas[propertyName];
|
|
6551
6854
|
if (!propSchema && isRefTypeFromMeta) {
|
|
6552
|
-
const schemaMod = await import('./index-
|
|
6855
|
+
const schemaMod = await import('./index-DB3nZ0lK.js');
|
|
6553
6856
|
const { ModelPropertyDataTypes } = schemaMod;
|
|
6554
6857
|
propSchema = {
|
|
6555
6858
|
dataType: refSeedType === 'html' ? ModelPropertyDataTypes.Html
|
|
@@ -6806,9 +7109,9 @@ const runPublish = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
6806
7109
|
sendBack({ type: 'publishError', error: new Error(`Item not found for seedLocalId: ${seedLocalId}`) });
|
|
6807
7110
|
return;
|
|
6808
7111
|
}
|
|
6809
|
-
const getPublishUploadsMod = await import('./getPublishUploads-
|
|
7112
|
+
const getPublishUploadsMod = await import('./getPublishUploads-CH72lAID.js');
|
|
6810
7113
|
const { getPublishUploads } = getPublishUploadsMod;
|
|
6811
|
-
const getPublishPayloadMod = await import('./getPublishPayload-
|
|
7114
|
+
const getPublishPayloadMod = await import('./getPublishPayload-DEdHgrgC.js');
|
|
6812
7115
|
const { getPublishPayload } = getPublishPayloadMod;
|
|
6813
7116
|
const uploads = await getPublishUploads(item);
|
|
6814
7117
|
let uploadedTransactions = [];
|
|
@@ -7154,6 +7457,11 @@ const getSeedData = async ({ seedLocalId, seedUid }) => {
|
|
|
7154
7457
|
return rows[0];
|
|
7155
7458
|
};
|
|
7156
7459
|
|
|
7460
|
+
var getSeedData$1 = /*#__PURE__*/Object.freeze({
|
|
7461
|
+
__proto__: null,
|
|
7462
|
+
getSeedData: getSeedData
|
|
7463
|
+
});
|
|
7464
|
+
|
|
7157
7465
|
/**
|
|
7158
7466
|
* Latest version row for the seed (by createdAt) whose uid is a real EAS attestation id.
|
|
7159
7467
|
* Skips legacy 'NULL' / ZERO_BYTES32 placeholders and non-bytes32 strings.
|
|
@@ -7643,7 +7951,7 @@ const resolveRelatedValue = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
7643
7951
|
const { isRelation, propertyValue, propertyName, seedUid, propertyRecordSchema, populatedFromDb, schemaUid, } = context;
|
|
7644
7952
|
const _resolveRelatedValue = async () => {
|
|
7645
7953
|
// Use dynamic import to break circular dependency
|
|
7646
|
-
const schemaMod = await import('./index-
|
|
7954
|
+
const schemaMod = await import('./index-DB3nZ0lK.js');
|
|
7647
7955
|
const { ModelPropertyDataTypes } = schemaMod;
|
|
7648
7956
|
if (!propertyValue || !isRelation || populatedFromDb) {
|
|
7649
7957
|
return;
|
|
@@ -8006,155 +8314,826 @@ function parseListPropertyValueFromStorage(raw) {
|
|
|
8006
8314
|
return trimmed.split(',').map((s) => s.trim()).filter(Boolean);
|
|
8007
8315
|
}
|
|
8008
8316
|
|
|
8009
|
-
|
|
8010
|
-
|
|
8011
|
-
|
|
8012
|
-
const hydrateFromDb = fromCallback(({ sendBack, input: { context } }) => {
|
|
8013
|
-
const { seedUid, seedLocalId, propertyName: propertyNameRaw, propertyRecordSchema, modelName, } = context;
|
|
8014
|
-
if (!propertyNameRaw) {
|
|
8015
|
-
throw new Error('propertyName is required');
|
|
8317
|
+
class SeedEventEmitter {
|
|
8318
|
+
constructor() {
|
|
8319
|
+
this.listeners = new Map();
|
|
8016
8320
|
}
|
|
8017
|
-
|
|
8018
|
-
|
|
8019
|
-
|
|
8020
|
-
|
|
8021
|
-
|
|
8022
|
-
|
|
8023
|
-
|
|
8024
|
-
|
|
8025
|
-
|
|
8026
|
-
|
|
8027
|
-
|
|
8028
|
-
|
|
8029
|
-
|
|
8030
|
-
|
|
8031
|
-
|
|
8032
|
-
|
|
8033
|
-
|
|
8034
|
-
|
|
8035
|
-
|
|
8036
|
-
|
|
8037
|
-
|
|
8038
|
-
|
|
8039
|
-
|
|
8040
|
-
|
|
8041
|
-
|
|
8042
|
-
|
|
8043
|
-
|
|
8044
|
-
|
|
8045
|
-
|
|
8046
|
-
|
|
8047
|
-
|
|
8048
|
-
|
|
8049
|
-
|
|
8050
|
-
|
|
8051
|
-
|
|
8052
|
-
|
|
8053
|
-
|
|
8054
|
-
|
|
8055
|
-
|
|
8056
|
-
|
|
8057
|
-
|
|
8058
|
-
|
|
8059
|
-
const firstRow = rows[0];
|
|
8060
|
-
const { localId, uid, propertyName: propertyNameFromDb, propertyValue: propertyValueFromDb, seedLocalId: seedLocalIdFromDb, seedUid: seedUidFromDb, schemaUid: schemaUidFromDb, versionLocalId: versionLocalIdFromDb, versionUid: versionUidFromDb, refValueType, } = firstRow;
|
|
8061
|
-
let { refResolvedDisplayValue, refResolvedValue, localStorageDir } = firstRow;
|
|
8062
|
-
let propertyValueProcessed = propertyValueFromDb;
|
|
8063
|
-
// Image: always resolve display value from file (blob URLs in DB are invalid after reload)
|
|
8064
|
-
if (isImageDynamic) {
|
|
8065
|
-
let dir = localStorageDir;
|
|
8066
|
-
if (!dir && isImageDynamic) {
|
|
8067
|
-
dir = 'images';
|
|
8068
|
-
}
|
|
8069
|
-
dir = dir.replace(/^\//, '');
|
|
8070
|
-
if (propertyValueFromDb &&
|
|
8071
|
-
propertyValueFromDb.length === 66) {
|
|
8072
|
-
// Here the storageTransactionId is stored on a different record and
|
|
8073
|
-
// we want to add it as the refResolvedValue
|
|
8074
|
-
const storageTransactionQuery = await appDb
|
|
8075
|
-
.select({
|
|
8076
|
-
propertyValue: metadata$1.propertyValue,
|
|
8077
|
-
})
|
|
8078
|
-
.from(metadata$1)
|
|
8079
|
-
.where(and(eq(metadata$1.seedUid, propertyValueFromDb), or(eq(metadata$1.propertyName, 'storageTransactionId'), eq(metadata$1.propertyName, 'transactionId'))));
|
|
8080
|
-
if (storageTransactionQuery && storageTransactionQuery.length > 0) {
|
|
8081
|
-
const row = storageTransactionQuery[0];
|
|
8082
|
-
refResolvedValue = row.propertyValue;
|
|
8083
|
-
await updateMetadata({
|
|
8084
|
-
localId,
|
|
8085
|
-
refResolvedValue,
|
|
8086
|
-
localStorageDir: '/images',
|
|
8087
|
-
});
|
|
8088
|
-
}
|
|
8089
|
-
}
|
|
8090
|
-
if (refResolvedValue) {
|
|
8091
|
-
try {
|
|
8092
|
-
const dirPath = BaseFileManager.getFilesPath(dir);
|
|
8093
|
-
const dirExists = await BaseFileManager.pathExists(dirPath);
|
|
8094
|
-
if (dirExists) {
|
|
8095
|
-
const fs = await BaseFileManager.getFs();
|
|
8096
|
-
const path = BaseFileManager.getPathModule();
|
|
8097
|
-
const files = await fs.promises.readdir(dirPath);
|
|
8098
|
-
const matchingFiles = files.filter((file) => {
|
|
8099
|
-
return path.basename(file).includes(refResolvedValue);
|
|
8100
|
-
});
|
|
8101
|
-
let fileExists = false;
|
|
8102
|
-
let filename;
|
|
8103
|
-
let filePath;
|
|
8104
|
-
if (matchingFiles && matchingFiles.length > 0) {
|
|
8105
|
-
fileExists = true;
|
|
8106
|
-
filename = matchingFiles[0];
|
|
8107
|
-
filePath = BaseFileManager.getFilesPath(dir, filename);
|
|
8108
|
-
}
|
|
8109
|
-
localStorageDir = `/${dir}`;
|
|
8110
|
-
if (fileExists && filename && filePath) {
|
|
8111
|
-
const file = await BaseFileManager.readFile(filePath);
|
|
8112
|
-
refResolvedDisplayValue = URL.createObjectURL(file);
|
|
8113
|
-
// Do not persist blob URL - it is session-scoped
|
|
8114
|
-
}
|
|
8115
|
-
}
|
|
8116
|
-
}
|
|
8117
|
-
catch (e) {
|
|
8118
|
-
logger$g('[hydrateFromDb] Image file resolution error', e);
|
|
8119
|
-
}
|
|
8120
|
-
}
|
|
8121
|
-
}
|
|
8122
|
-
if (propertyRecordSchema &&
|
|
8123
|
-
normalizedDataType === ModelPropertyDataTypes.List &&
|
|
8124
|
-
typeof propertyValueFromDb === 'string') {
|
|
8125
|
-
propertyValueProcessed = parseListPropertyValueFromStorage(propertyValueFromDb);
|
|
8321
|
+
on(event, listener) {
|
|
8322
|
+
const set = this.listeners.get(event) ?? new Set();
|
|
8323
|
+
set.add(listener);
|
|
8324
|
+
this.listeners.set(event, set);
|
|
8325
|
+
return this;
|
|
8326
|
+
}
|
|
8327
|
+
addListener(event, listener) {
|
|
8328
|
+
return this.on(event, listener);
|
|
8329
|
+
}
|
|
8330
|
+
once(event, listener) {
|
|
8331
|
+
const wrapped = (...args) => {
|
|
8332
|
+
this.off(event, wrapped);
|
|
8333
|
+
listener(...args);
|
|
8334
|
+
};
|
|
8335
|
+
return this.on(event, wrapped);
|
|
8336
|
+
}
|
|
8337
|
+
off(event, listener) {
|
|
8338
|
+
const set = this.listeners.get(event);
|
|
8339
|
+
if (!set)
|
|
8340
|
+
return this;
|
|
8341
|
+
set.delete(listener);
|
|
8342
|
+
if (set.size === 0)
|
|
8343
|
+
this.listeners.delete(event);
|
|
8344
|
+
return this;
|
|
8345
|
+
}
|
|
8346
|
+
removeListener(event, listener) {
|
|
8347
|
+
return this.off(event, listener);
|
|
8348
|
+
}
|
|
8349
|
+
removeAllListeners(event) {
|
|
8350
|
+
if (typeof event === 'undefined') {
|
|
8351
|
+
this.listeners.clear();
|
|
8352
|
+
return this;
|
|
8353
|
+
}
|
|
8354
|
+
this.listeners.delete(event);
|
|
8355
|
+
return this;
|
|
8356
|
+
}
|
|
8357
|
+
emit(event, ...args) {
|
|
8358
|
+
const set = this.listeners.get(event);
|
|
8359
|
+
if (!set || set.size === 0)
|
|
8360
|
+
return false;
|
|
8361
|
+
for (const listener of [...set]) {
|
|
8362
|
+
listener(...args);
|
|
8126
8363
|
}
|
|
8127
|
-
|
|
8128
|
-
|
|
8129
|
-
|
|
8130
|
-
|
|
8131
|
-
|
|
8132
|
-
|
|
8133
|
-
|
|
8134
|
-
|
|
8135
|
-
|
|
8136
|
-
|
|
8137
|
-
|
|
8138
|
-
|
|
8139
|
-
|
|
8140
|
-
|
|
8141
|
-
|
|
8142
|
-
|
|
8143
|
-
|
|
8144
|
-
|
|
8145
|
-
|
|
8146
|
-
|
|
8147
|
-
|
|
8148
|
-
|
|
8149
|
-
|
|
8150
|
-
|
|
8151
|
-
|
|
8152
|
-
|
|
8153
|
-
|
|
8154
|
-
|
|
8155
|
-
|
|
8156
|
-
|
|
8157
|
-
|
|
8364
|
+
return true;
|
|
8365
|
+
}
|
|
8366
|
+
}
|
|
8367
|
+
const eventEmitter = new SeedEventEmitter();
|
|
8368
|
+
|
|
8369
|
+
const GET_FILES_METADATA = graphql(/* GraphQL */ `
|
|
8370
|
+
query GetFilesMetadata($where: AttestationWhereInput!) {
|
|
8371
|
+
filesMetadata: attestations(
|
|
8372
|
+
where: $where
|
|
8373
|
+
orderBy: [{ timeCreated: desc }]
|
|
8374
|
+
) {
|
|
8375
|
+
...attestationFields
|
|
8376
|
+
}
|
|
8377
|
+
}
|
|
8378
|
+
`);
|
|
8379
|
+
|
|
8380
|
+
const getMetadata = async (props) => {
|
|
8381
|
+
const appDb = BaseDb.getAppDb();
|
|
8382
|
+
let storageTransactionId;
|
|
8383
|
+
if (props) {
|
|
8384
|
+
storageTransactionId = props.storageTransactionId;
|
|
8385
|
+
}
|
|
8386
|
+
const whereClauses = [];
|
|
8387
|
+
if (storageTransactionId) {
|
|
8388
|
+
whereClauses.push(eq(metadata$1.propertyName, 'storageTransactionId'));
|
|
8389
|
+
whereClauses.push(eq(metadata$1.propertyValue, storageTransactionId));
|
|
8390
|
+
}
|
|
8391
|
+
const metadataRows = await appDb
|
|
8392
|
+
.select()
|
|
8393
|
+
.from(metadata$1)
|
|
8394
|
+
.where(and(...whereClauses));
|
|
8395
|
+
if (!metadataRows || metadataRows.length === 0) {
|
|
8396
|
+
return;
|
|
8397
|
+
}
|
|
8398
|
+
return metadataRows[0];
|
|
8399
|
+
};
|
|
8400
|
+
|
|
8401
|
+
const saveMetadata = async (metadataRecord, metadataValues) => {
|
|
8402
|
+
if (!metadataRecord.localId) {
|
|
8403
|
+
return;
|
|
8404
|
+
}
|
|
8405
|
+
const appDb = BaseDb.getAppDb();
|
|
8406
|
+
await appDb
|
|
8407
|
+
.update(metadata$1)
|
|
8408
|
+
.set({
|
|
8409
|
+
...metadataValues,
|
|
8410
|
+
updatedAt: Date.now(),
|
|
8411
|
+
})
|
|
8412
|
+
.where(eq(metadata$1.localId, metadataRecord.localId));
|
|
8413
|
+
};
|
|
8414
|
+
|
|
8415
|
+
const isNode = () => {
|
|
8416
|
+
return (typeof process !== 'undefined' &&
|
|
8417
|
+
process.versions != null &&
|
|
8418
|
+
process.versions.node != null);
|
|
8419
|
+
};
|
|
8420
|
+
const isBrowser = () => {
|
|
8421
|
+
return !isElectron() && typeof document !== 'undefined' && typeof window !== 'undefined';
|
|
8422
|
+
};
|
|
8423
|
+
const isElectron = () => {
|
|
8424
|
+
return typeof process !== 'undefined' && process.versions != null && process.versions.electron != null;
|
|
8425
|
+
};
|
|
8426
|
+
/**
|
|
8427
|
+
* Detects if code is running in an Electron renderer process.
|
|
8428
|
+
*
|
|
8429
|
+
* Uses multiple detection methods for robustness:
|
|
8430
|
+
* 1. Checks process.type === 'renderer' (most reliable)
|
|
8431
|
+
* 2. Falls back to checking if Electron is present and window/document exist
|
|
8432
|
+
*
|
|
8433
|
+
* @returns true if running in Electron renderer process, false otherwise
|
|
8434
|
+
*/
|
|
8435
|
+
const isElectronRenderer = () => {
|
|
8436
|
+
// Method 1: Check process.type (most reliable - official Electron API)
|
|
8437
|
+
if (typeof process !== 'undefined' &&
|
|
8438
|
+
process.type === 'renderer') {
|
|
8439
|
+
return true;
|
|
8440
|
+
}
|
|
8441
|
+
// Method 2: Fallback - Electron + browser-like environment
|
|
8442
|
+
// Renderer processes have window/document, main process doesn't (in modern Electron)
|
|
8443
|
+
if (isElectron() &&
|
|
8444
|
+
typeof window !== 'undefined' &&
|
|
8445
|
+
typeof document !== 'undefined') {
|
|
8446
|
+
return true;
|
|
8447
|
+
}
|
|
8448
|
+
return false;
|
|
8449
|
+
};
|
|
8450
|
+
/**
|
|
8451
|
+
* True where OPFS-backed Arweave file downloads should run: normal browsers and
|
|
8452
|
+
* Electron renderer. {@link isBrowser} is false for every Electron build (including renderer).
|
|
8453
|
+
*/
|
|
8454
|
+
const supportsOpfsFileDownloads = () => {
|
|
8455
|
+
return isBrowser() || isElectronRenderer();
|
|
8456
|
+
};
|
|
8457
|
+
|
|
8458
|
+
const logger$g = debug('seedSdk:files:download');
|
|
8459
|
+
const AUTO_BULK_DOWNLOAD_THROTTLE_MS = 10000;
|
|
8460
|
+
/** Avoid refetch-on-every-call: transient empty indexer responses were overwriting good cache (see trailing throttle ~10s after success). */
|
|
8461
|
+
const GET_FILES_METADATA_STALE_MS = 120000;
|
|
8462
|
+
let bulkDownloadInFlight = null;
|
|
8463
|
+
const lazyDownloadInFlightByTransactionId = new Map();
|
|
8464
|
+
// syncDbFiles helper - internal service removed, functionality moved here
|
|
8465
|
+
const syncDbFiles = async (endpoints) => {
|
|
8466
|
+
// TODO: Implement syncDbFiles functionality if needed
|
|
8467
|
+
// This was previously in @/services/internal/helpers
|
|
8468
|
+
logger$g('[download] syncDbFiles called but not yet implemented');
|
|
8469
|
+
return Promise.resolve();
|
|
8470
|
+
};
|
|
8471
|
+
const getAppDbReady = async () => {
|
|
8472
|
+
if (!BaseDb.isAppDbReady()) {
|
|
8473
|
+
// Wait for ClientManager to be ready (DB_INIT state or later)
|
|
8474
|
+
const clientManagerMod = await Promise.resolve().then(function () { return ClientManager$1; });
|
|
8475
|
+
const { getClient } = clientManagerMod;
|
|
8476
|
+
const clientManager = getClient();
|
|
8477
|
+
const clientService = clientManager.getService();
|
|
8478
|
+
await waitFor(clientService, (snapshot) => {
|
|
8479
|
+
const state = snapshot.value;
|
|
8480
|
+
return state === 'dbInit' ||
|
|
8481
|
+
state === 'saveConfig' ||
|
|
8482
|
+
state === 'processSchemaFiles' ||
|
|
8483
|
+
state === 'addModelsToStore' ||
|
|
8484
|
+
state === 'addModelsToDb' ||
|
|
8485
|
+
state === 'idle';
|
|
8486
|
+
}, { timeout: 30000 });
|
|
8487
|
+
}
|
|
8488
|
+
return BaseDb.getAppDb();
|
|
8489
|
+
};
|
|
8490
|
+
const getExcludedTransactions = async () => {
|
|
8491
|
+
const appDb = await getAppDbReady();
|
|
8492
|
+
if (!appDb) {
|
|
8493
|
+
return new Set();
|
|
8494
|
+
}
|
|
8495
|
+
const excludedTransactionsQuery = await appDb
|
|
8496
|
+
.select()
|
|
8497
|
+
.from(appState)
|
|
8498
|
+
.where(eq(appState.key, 'excludedTransactions'));
|
|
8499
|
+
const excludedTransactions = new Set();
|
|
8500
|
+
if (excludedTransactionsQuery && excludedTransactionsQuery.length === 1) {
|
|
8501
|
+
const valueString = excludedTransactionsQuery[0].value;
|
|
8502
|
+
if (valueString) {
|
|
8503
|
+
const excludedTransactionsArray = JSON.parse(valueString);
|
|
8504
|
+
for (const txId of excludedTransactionsArray) {
|
|
8505
|
+
excludedTransactions.add(txId);
|
|
8506
|
+
}
|
|
8507
|
+
}
|
|
8508
|
+
}
|
|
8509
|
+
return excludedTransactions;
|
|
8510
|
+
};
|
|
8511
|
+
/** Arweave transaction ids are 43 chars in the URL-safe base64 alphabet. */
|
|
8512
|
+
const ARWEAVE_TX_ID_RE = /^[a-z0-9_-]{43}$/i;
|
|
8513
|
+
const normalizeArweaveTxId = (raw) => {
|
|
8514
|
+
if (raw == null || raw === '')
|
|
8515
|
+
return undefined;
|
|
8516
|
+
const t = String(raw).trim();
|
|
8517
|
+
if (ARWEAVE_TX_ID_RE.test(t))
|
|
8518
|
+
return t;
|
|
8519
|
+
const m = t.match(/^([a-z0-9_-]{43})(?:\.[^/]+)?$/i);
|
|
8520
|
+
if (m)
|
|
8521
|
+
return m[1];
|
|
8522
|
+
// Values may be full gateway URLs or paths; scan for the embedded tx id.
|
|
8523
|
+
const embedded = t.match(/[a-z0-9_-]{43}/gi);
|
|
8524
|
+
if (embedded) {
|
|
8525
|
+
for (const candidate of embedded) {
|
|
8526
|
+
if (ARWEAVE_TX_ID_RE.test(candidate))
|
|
8527
|
+
return candidate;
|
|
8528
|
+
}
|
|
8529
|
+
}
|
|
8530
|
+
return undefined;
|
|
8531
|
+
};
|
|
8532
|
+
const mergeAddressLists = (a, b) => {
|
|
8533
|
+
const seen = new Set();
|
|
8534
|
+
const out = [];
|
|
8535
|
+
for (const addr of [...(a ?? []), ...(b ?? [])]) {
|
|
8536
|
+
if (!addr || !addr.trim())
|
|
8537
|
+
continue;
|
|
8538
|
+
const k = addr.toLowerCase();
|
|
8539
|
+
if (seen.has(k))
|
|
8540
|
+
continue;
|
|
8541
|
+
seen.add(k);
|
|
8542
|
+
out.push(addr);
|
|
8543
|
+
}
|
|
8544
|
+
return out;
|
|
8545
|
+
};
|
|
8546
|
+
const collectTransactionIdsFromLocalMetadata = async () => {
|
|
8547
|
+
const appDb = await getAppDbReady();
|
|
8548
|
+
if (!appDb) {
|
|
8549
|
+
return [];
|
|
8550
|
+
}
|
|
8551
|
+
const nameOr = or(eq(metadata$1.propertyName, 'storageTransactionId'), eq(metadata$1.propertyName, 'storage_transaction_id'), eq(metadata$1.propertyName, 'transactionId'));
|
|
8552
|
+
const propRows = await appDb
|
|
8553
|
+
.select({ propertyValue: metadata$1.propertyValue })
|
|
8554
|
+
.from(metadata$1)
|
|
8555
|
+
.where(and(nameOr, isNotNull(metadata$1.propertyValue)));
|
|
8556
|
+
const refRows = await appDb
|
|
8557
|
+
.select({ refResolvedValue: metadata$1.refResolvedValue })
|
|
8558
|
+
.from(metadata$1)
|
|
8559
|
+
.where(isNotNull(metadata$1.refResolvedValue));
|
|
8560
|
+
const ids = new Set();
|
|
8561
|
+
for (const row of propRows) {
|
|
8562
|
+
const id = normalizeArweaveTxId(row.propertyValue ?? undefined);
|
|
8563
|
+
if (id)
|
|
8564
|
+
ids.add(id);
|
|
8565
|
+
}
|
|
8566
|
+
for (const row of refRows) {
|
|
8567
|
+
const id = normalizeArweaveTxId(row.refResolvedValue ?? undefined);
|
|
8568
|
+
if (id)
|
|
8569
|
+
ids.add(id);
|
|
8570
|
+
}
|
|
8571
|
+
return Array.from(ids);
|
|
8572
|
+
};
|
|
8573
|
+
const parseTransactionIdsFromMetadata = (filesMetadata, excludedTransactions) => {
|
|
8574
|
+
const transactionIds = [];
|
|
8575
|
+
for (const fileMetadata of filesMetadata) {
|
|
8576
|
+
// Validate and parse decodedDataJson
|
|
8577
|
+
if (!fileMetadata.decodedDataJson || fileMetadata.decodedDataJson.trim() === '') {
|
|
8578
|
+
console.warn('[events/files] [download] empty decodedDataJson for fileMetadata: ', fileMetadata.id);
|
|
8579
|
+
continue;
|
|
8580
|
+
}
|
|
8581
|
+
let json;
|
|
8582
|
+
try {
|
|
8583
|
+
json = JSON.parse(fileMetadata.decodedDataJson);
|
|
8584
|
+
}
|
|
8585
|
+
catch (error) {
|
|
8586
|
+
console.warn('[events/files] [download] failed to parse decodedDataJson for fileMetadata: ', fileMetadata.id, error);
|
|
8587
|
+
continue;
|
|
8588
|
+
}
|
|
8589
|
+
if (!Array.isArray(json) || json.length === 0 || !json[0]?.value?.value) {
|
|
8590
|
+
console.warn('[events/files] [download] invalid decodedDataJson structure for fileMetadata: ', fileMetadata.id);
|
|
8591
|
+
continue;
|
|
8592
|
+
}
|
|
8593
|
+
const rawTx = json[0].value.value;
|
|
8594
|
+
if (typeof rawTx !== 'string' || rawTx.trim().length === 0) {
|
|
8595
|
+
continue;
|
|
8596
|
+
}
|
|
8597
|
+
const transactionId = normalizeArweaveTxId(rawTx.trim());
|
|
8598
|
+
if (!transactionId) {
|
|
8599
|
+
continue;
|
|
8600
|
+
}
|
|
8601
|
+
if (excludedTransactions.has(transactionId) || excludedTransactions.has(rawTx.trim())) {
|
|
8602
|
+
continue;
|
|
8603
|
+
}
|
|
8604
|
+
transactionIds.push(transactionId);
|
|
8605
|
+
}
|
|
8606
|
+
return transactionIds;
|
|
8607
|
+
};
|
|
8608
|
+
const downloadTransactionIds = async (rawTransactionIds, options) => {
|
|
8609
|
+
if (!supportsOpfsFileDownloads()) {
|
|
8610
|
+
return false;
|
|
8611
|
+
}
|
|
8612
|
+
const transactionIds = Array.from(new Set(rawTransactionIds.filter((tx) => !!tx && tx.trim().length > 0)));
|
|
8613
|
+
if (transactionIds.length === 0) {
|
|
8614
|
+
return false;
|
|
8615
|
+
}
|
|
8616
|
+
const excludedTransactions = await getExcludedTransactions();
|
|
8617
|
+
const queryClient = BaseQueryClient.getQueryClient();
|
|
8618
|
+
const transactionIdsToDownload = [];
|
|
8619
|
+
await ensureReadGatewaySelected();
|
|
8620
|
+
for (const transactionId of transactionIds) {
|
|
8621
|
+
if (excludedTransactions.has(transactionId)) {
|
|
8622
|
+
continue;
|
|
8623
|
+
}
|
|
8624
|
+
try {
|
|
8625
|
+
// Browser: do not call getTransactionStatus() — many gateways (e.g. g8way.io) redirect or omit
|
|
8626
|
+
// CORS headers, so fetch() fails and we would wrongly exclude txs. The OPFS worker fetch decides success.
|
|
8627
|
+
let tags = [];
|
|
8628
|
+
try {
|
|
8629
|
+
tags = await queryClient.fetchQuery({
|
|
8630
|
+
queryKey: ['getTransactionTags', transactionId],
|
|
8631
|
+
queryFn: async () => BaseArweaveClient.getTransactionTags(transactionId),
|
|
8632
|
+
});
|
|
8633
|
+
}
|
|
8634
|
+
catch {
|
|
8635
|
+
tags = [];
|
|
8636
|
+
}
|
|
8637
|
+
if (tags && tags.length > 0) {
|
|
8638
|
+
for (const { name, value } of tags) {
|
|
8639
|
+
if (name !== 'Content-SHA-256')
|
|
8640
|
+
continue;
|
|
8641
|
+
const metadataRecord = await getMetadata({
|
|
8642
|
+
storageTransactionId: transactionId,
|
|
8643
|
+
});
|
|
8644
|
+
if (metadataRecord) {
|
|
8645
|
+
await saveMetadata(metadataRecord, {
|
|
8646
|
+
contentHash: value,
|
|
8647
|
+
});
|
|
8648
|
+
}
|
|
8649
|
+
}
|
|
8650
|
+
}
|
|
8651
|
+
transactionIdsToDownload.push(transactionId);
|
|
8652
|
+
}
|
|
8653
|
+
catch (error) {
|
|
8654
|
+
logger$g(error);
|
|
8655
|
+
}
|
|
8656
|
+
}
|
|
8657
|
+
if (transactionIdsToDownload.length === 0) {
|
|
8658
|
+
return false;
|
|
8659
|
+
}
|
|
8660
|
+
if (transactionIdsToDownload.length === 1) {
|
|
8661
|
+
await BaseFileManager.downloadFileByTransactionId({
|
|
8662
|
+
transactionId: transactionIdsToDownload[0],
|
|
8663
|
+
arweaveHost: BaseArweaveClient.getHost(),
|
|
8664
|
+
excludedTransactions,
|
|
8665
|
+
});
|
|
8666
|
+
}
|
|
8667
|
+
else {
|
|
8668
|
+
await BaseFileManager.downloadAllFiles({
|
|
8669
|
+
transactionIds: transactionIdsToDownload,
|
|
8670
|
+
arweaveHost: BaseArweaveClient.getHost(),
|
|
8671
|
+
excludedTransactions,
|
|
8672
|
+
});
|
|
8673
|
+
}
|
|
8674
|
+
if (options?.resizeAllImages !== false) {
|
|
8675
|
+
await BaseFileManager.resizeAllImages({
|
|
8676
|
+
width: 480,
|
|
8677
|
+
height: 480,
|
|
8678
|
+
});
|
|
8679
|
+
}
|
|
8680
|
+
return true;
|
|
8681
|
+
};
|
|
8682
|
+
const runBulkDownloadWithDedupe = async (transactionIds) => {
|
|
8683
|
+
if (bulkDownloadInFlight) {
|
|
8684
|
+
return bulkDownloadInFlight;
|
|
8685
|
+
}
|
|
8686
|
+
bulkDownloadInFlight = (async () => {
|
|
8687
|
+
try {
|
|
8688
|
+
await downloadTransactionIds(transactionIds, { resizeAllImages: true });
|
|
8689
|
+
}
|
|
8690
|
+
finally {
|
|
8691
|
+
bulkDownloadInFlight = null;
|
|
8692
|
+
}
|
|
8693
|
+
})();
|
|
8694
|
+
return bulkDownloadInFlight;
|
|
8695
|
+
};
|
|
8696
|
+
const downloadAllFilesRequestHandler = async ({ endpoints, eventId, }) => {
|
|
8697
|
+
if (!supportsOpfsFileDownloads()) {
|
|
8698
|
+
return;
|
|
8699
|
+
}
|
|
8700
|
+
await syncDbFiles();
|
|
8701
|
+
eventEmitter.emit('fs.downloadAll.success', { eventId });
|
|
8702
|
+
eventEmitter.emit('fs.downloadAllBinary.request', { endpoints });
|
|
8703
|
+
};
|
|
8704
|
+
const downloadAllFilesBinaryRequestHandler = async (addressesHintOrPayload) => {
|
|
8705
|
+
if (!supportsOpfsFileDownloads()) {
|
|
8706
|
+
return;
|
|
8707
|
+
}
|
|
8708
|
+
const addressesHint = Array.isArray(addressesHintOrPayload)
|
|
8709
|
+
? addressesHintOrPayload
|
|
8710
|
+
: undefined;
|
|
8711
|
+
let fromDb = [];
|
|
8712
|
+
if (BaseDb.isAppDbReady()) {
|
|
8713
|
+
fromDb = await getAllAddressesFromDb();
|
|
8714
|
+
}
|
|
8715
|
+
if (!BaseDb.isAppDbReady()) {
|
|
8716
|
+
await getAppDbReady();
|
|
8717
|
+
fromDb = await getAllAddressesFromDb();
|
|
8718
|
+
}
|
|
8719
|
+
const addresses = mergeAddressLists(addressesHint, fromDb);
|
|
8720
|
+
if (!addresses || addresses.length === 0) {
|
|
8721
|
+
return;
|
|
8722
|
+
}
|
|
8723
|
+
const queryClient = BaseQueryClient.getQueryClient();
|
|
8724
|
+
const easClient = BaseEasClient.getEasClient();
|
|
8725
|
+
const filesMetadataQueryKey = ['getFilesMetadata', ...addresses];
|
|
8726
|
+
const fetchFilesMetadata = () => easClient.request(GET_FILES_METADATA, {
|
|
8727
|
+
where: {
|
|
8728
|
+
attester: {
|
|
8729
|
+
in: addresses,
|
|
8730
|
+
},
|
|
8731
|
+
schema: {
|
|
8732
|
+
is: {
|
|
8733
|
+
id: {
|
|
8734
|
+
equals: '0x55fdefb36fcbbaebeb7d6b41dc3a1a9666e4e42154267c889de064faa7ede517',
|
|
8735
|
+
},
|
|
8736
|
+
},
|
|
8737
|
+
},
|
|
8738
|
+
},
|
|
8739
|
+
});
|
|
8740
|
+
let { filesMetadata } = await queryClient.fetchQuery({
|
|
8741
|
+
queryKey: filesMetadataQueryKey,
|
|
8742
|
+
queryFn: fetchFilesMetadata,
|
|
8743
|
+
staleTime: GET_FILES_METADATA_STALE_MS,
|
|
8744
|
+
});
|
|
8745
|
+
if ((!Array.isArray(filesMetadata) || filesMetadata.length === 0) && addresses.length > 0) {
|
|
8746
|
+
await queryClient.removeQueries({ queryKey: filesMetadataQueryKey });
|
|
8747
|
+
({ filesMetadata } = await queryClient.fetchQuery({
|
|
8748
|
+
queryKey: filesMetadataQueryKey,
|
|
8749
|
+
queryFn: fetchFilesMetadata,
|
|
8750
|
+
staleTime: GET_FILES_METADATA_STALE_MS,
|
|
8751
|
+
}));
|
|
8752
|
+
}
|
|
8753
|
+
const filesRoot = BaseFileManager.getWorkingDir();
|
|
8754
|
+
await BaseFileManager.createDirIfNotExists(filesRoot);
|
|
8755
|
+
await BaseFileManager.createDirIfNotExists(BaseFileManager.getFilesPath('html'));
|
|
8756
|
+
await BaseFileManager.createDirIfNotExists(BaseFileManager.getFilesPath('json'));
|
|
8757
|
+
await BaseFileManager.createDirIfNotExists(BaseFileManager.getFilesPath('images'));
|
|
8758
|
+
const excludedTransactions = await getExcludedTransactions();
|
|
8759
|
+
const fromEas = parseTransactionIdsFromMetadata(filesMetadata ?? [], excludedTransactions);
|
|
8760
|
+
const fromLocal = await collectTransactionIdsFromLocalMetadata();
|
|
8761
|
+
const transactionIds = Array.from(new Set([...fromEas, ...fromLocal]));
|
|
8762
|
+
await runBulkDownloadWithDedupe(transactionIds);
|
|
8763
|
+
};
|
|
8764
|
+
const downloadTransactionIdWithDedupe = async (transactionId) => {
|
|
8765
|
+
if (!supportsOpfsFileDownloads() || !transactionId || transactionId.trim().length === 0) {
|
|
8766
|
+
return false;
|
|
8767
|
+
}
|
|
8768
|
+
const normalizedTxId = normalizeArweaveTxId(transactionId) ?? transactionId.trim();
|
|
8769
|
+
const existing = lazyDownloadInFlightByTransactionId.get(normalizedTxId);
|
|
8770
|
+
if (existing) {
|
|
8771
|
+
return existing;
|
|
8772
|
+
}
|
|
8773
|
+
const inFlight = (async () => {
|
|
8774
|
+
try {
|
|
8775
|
+
const ok = await downloadTransactionIds([normalizedTxId], { resizeAllImages: false });
|
|
8776
|
+
return ok;
|
|
8777
|
+
}
|
|
8778
|
+
finally {
|
|
8779
|
+
lazyDownloadInFlightByTransactionId.delete(normalizedTxId);
|
|
8780
|
+
}
|
|
8781
|
+
})();
|
|
8782
|
+
lazyDownloadInFlightByTransactionId.set(normalizedTxId, inFlight);
|
|
8783
|
+
return inFlight;
|
|
8784
|
+
};
|
|
8785
|
+
const scheduleBulkFilesDownloadFromEasSyncThrottled = throttle((addressesHint) => {
|
|
8786
|
+
void downloadAllFilesBinaryRequestHandler(addressesHint).catch((error) => {
|
|
8787
|
+
logger$g('[scheduleBulkFilesDownloadFromEasSync] failed', error);
|
|
8788
|
+
});
|
|
8789
|
+
}, AUTO_BULK_DOWNLOAD_THROTTLE_MS, { leading: true, trailing: false });
|
|
8790
|
+
const scheduleBulkFilesDownloadFromEasSync = (addressesHint) => {
|
|
8791
|
+
if (!supportsOpfsFileDownloads()) {
|
|
8792
|
+
return;
|
|
8793
|
+
}
|
|
8794
|
+
scheduleBulkFilesDownloadFromEasSyncThrottled(addressesHint);
|
|
8795
|
+
};
|
|
8796
|
+
|
|
8797
|
+
var download = /*#__PURE__*/Object.freeze({
|
|
8798
|
+
__proto__: null,
|
|
8799
|
+
downloadAllFilesBinaryRequestHandler: downloadAllFilesBinaryRequestHandler,
|
|
8800
|
+
downloadAllFilesRequestHandler: downloadAllFilesRequestHandler,
|
|
8801
|
+
downloadTransactionIdWithDedupe: downloadTransactionIdWithDedupe,
|
|
8802
|
+
scheduleBulkFilesDownloadFromEasSync: scheduleBulkFilesDownloadFromEasSync
|
|
8803
|
+
});
|
|
8804
|
+
|
|
8805
|
+
/** Published storage seeds use `0x` + 64 hex; `saveHtml` still writes `html/{localId}.html`. */
|
|
8806
|
+
const SEED_UID_HEX_RE = /^0x[a-fA-F0-9]{64}$/;
|
|
8807
|
+
/** Arweave L1 transaction ids are 43 URL-safe base64 characters. */
|
|
8808
|
+
const ARWEAVE_TX_ID_IN_STRING_RE = /[a-z0-9_-]{43}/i;
|
|
8809
|
+
function extractArweaveTransactionId(raw) {
|
|
8810
|
+
const t = raw.trim();
|
|
8811
|
+
const embedded = t.match(ARWEAVE_TX_ID_IN_STRING_RE);
|
|
8812
|
+
if (embedded && /^[a-z0-9_-]{43}$/i.test(embedded[0])) {
|
|
8813
|
+
return embedded[0];
|
|
8814
|
+
}
|
|
8815
|
+
return t;
|
|
8816
|
+
}
|
|
8817
|
+
/**
|
|
8818
|
+
* GET /raw/{txId} on each configured gateway. Avoids arweave.js /tx/.../offset which often 404s on
|
|
8819
|
+
* arweave.net while another gateway (e.g. ar.seedprotocol.io) still serves the data.
|
|
8820
|
+
*/
|
|
8821
|
+
async function fetchHtmlViaRawAcrossGateways(txId) {
|
|
8822
|
+
const id = extractArweaveTransactionId(txId);
|
|
8823
|
+
if (!id || SEED_UID_HEX_RE.test(id))
|
|
8824
|
+
return undefined;
|
|
8825
|
+
try {
|
|
8826
|
+
const { ensureReadGatewaySelected } = await Promise.resolve().then(function () { return selectReadGateway; });
|
|
8827
|
+
await ensureReadGatewaySelected().catch(() => { });
|
|
8828
|
+
}
|
|
8829
|
+
catch {
|
|
8830
|
+
/* optional */
|
|
8831
|
+
}
|
|
8832
|
+
const { BaseArweaveClient } = await Promise.resolve().then(function () { return BaseArweaveClient$1; });
|
|
8833
|
+
const protocol = BaseArweaveClient.getProtocol();
|
|
8834
|
+
const hosts = mergePrimaryHostWithDefaults(BaseArweaveClient.getHost(), getDefaultArweaveReadGatewayHostsOrdered());
|
|
8835
|
+
for (const host of hosts) {
|
|
8836
|
+
const h = host.trim().replace(/\/$/, '');
|
|
8837
|
+
if (!h)
|
|
8838
|
+
continue;
|
|
8839
|
+
const url = `${protocol}://${h}/raw/${encodeURIComponent(id)}`;
|
|
8840
|
+
try {
|
|
8841
|
+
const res = await fetch(url, { method: 'GET', credentials: 'omit' });
|
|
8842
|
+
if (!res.ok)
|
|
8843
|
+
continue;
|
|
8844
|
+
const text = await res.text();
|
|
8845
|
+
if (typeof text === 'string' && text.length > 0) {
|
|
8846
|
+
return text;
|
|
8847
|
+
}
|
|
8848
|
+
}
|
|
8849
|
+
catch {
|
|
8850
|
+
/* next gateway */
|
|
8851
|
+
}
|
|
8852
|
+
}
|
|
8853
|
+
return undefined;
|
|
8854
|
+
}
|
|
8855
|
+
/**
|
|
8856
|
+
* Resolve the Html storage seed's `local_id` used for the `{localId}.html` file name.
|
|
8857
|
+
* `propertyValue` on the parent Html property is either that local id or the seed uid after publish.
|
|
8858
|
+
*/
|
|
8859
|
+
async function resolveHtmlStorageSeedLocalId(propertyValue) {
|
|
8860
|
+
const pv = String(propertyValue ?? '').trim();
|
|
8861
|
+
if (!pv)
|
|
8862
|
+
return undefined;
|
|
8863
|
+
if (SEED_UID_HEX_RE.test(pv)) {
|
|
8864
|
+
const { getSeedData } = await Promise.resolve().then(function () { return getSeedData$1; });
|
|
8865
|
+
return (await getSeedData({ seedUid: pv }))?.localId ?? undefined;
|
|
8866
|
+
}
|
|
8867
|
+
return pv;
|
|
8868
|
+
}
|
|
8869
|
+
/**
|
|
8870
|
+
* When the local draft file is gone (new device, OPFS cleared, etc.), load HTML from the
|
|
8871
|
+
* Html storage seed's published Arweave transaction id on that child seed.
|
|
8872
|
+
*/
|
|
8873
|
+
async function readHtmlBodyFromChildStorageArweave(seedLocalId) {
|
|
8874
|
+
const { getPropertyData } = await Promise.resolve().then(function () { return getPropertyData$1; });
|
|
8875
|
+
const pickTx = async (name) => {
|
|
8876
|
+
const row = await getPropertyData({ propertyName: name, seedLocalId });
|
|
8877
|
+
const v = row?.propertyValue != null ? String(row.propertyValue).trim() : '';
|
|
8878
|
+
return v || undefined;
|
|
8879
|
+
};
|
|
8880
|
+
const txId = (await pickTx('storageTransactionId')) ??
|
|
8881
|
+
(await pickTx('transactionId')) ??
|
|
8882
|
+
(await pickTx('storage_transaction_id'));
|
|
8883
|
+
if (!txId || SEED_UID_HEX_RE.test(txId)) {
|
|
8884
|
+
return { txIdLen: 0, gatewayStringLen: 0 };
|
|
8885
|
+
}
|
|
8886
|
+
const rawHtml = await fetchHtmlViaRawAcrossGateways(txId);
|
|
8887
|
+
if (rawHtml && rawHtml.length > 0) {
|
|
8888
|
+
return { body: rawHtml, txIdLen: txId.length, gatewayStringLen: rawHtml.length };
|
|
8889
|
+
}
|
|
8890
|
+
try {
|
|
8891
|
+
const { BaseArweaveClient } = await Promise.resolve().then(function () { return BaseArweaveClient$1; });
|
|
8892
|
+
const data = await BaseArweaveClient.getTransactionData(extractArweaveTransactionId(txId), {
|
|
8893
|
+
string: true,
|
|
8894
|
+
});
|
|
8895
|
+
if (typeof data === 'string' && data.length > 0) {
|
|
8896
|
+
return { body: data, txIdLen: txId.length, gatewayStringLen: data.length };
|
|
8897
|
+
}
|
|
8898
|
+
}
|
|
8899
|
+
catch {
|
|
8900
|
+
/* offline / bad tx id */
|
|
8901
|
+
}
|
|
8902
|
+
try {
|
|
8903
|
+
const { downloadTransactionIdWithDedupe } = await Promise.resolve().then(function () { return download; });
|
|
8904
|
+
await downloadTransactionIdWithDedupe(txId);
|
|
8905
|
+
const retryFp = BaseFileManager.getFilesPath('html', `${seedLocalId}.html`);
|
|
8906
|
+
if (await BaseFileManager.pathExists(retryFp)) {
|
|
8907
|
+
const s = await BaseFileManager.readFileAsString(retryFp);
|
|
8908
|
+
return { body: s, txIdLen: txId.length, gatewayStringLen: 0 };
|
|
8909
|
+
}
|
|
8910
|
+
const dirPath = BaseFileManager.getFilesPath('html');
|
|
8911
|
+
if (await BaseFileManager.pathExists(dirPath)) {
|
|
8912
|
+
const fs = await BaseFileManager.getFs();
|
|
8913
|
+
const pathMod = BaseFileManager.getPathModule();
|
|
8914
|
+
const files = await fs.promises.readdir(dirPath);
|
|
8915
|
+
const needle = txId.replace(/\.[^/.]+$/, '');
|
|
8916
|
+
const match = files.find((f) => f.includes(seedLocalId) || f.includes(needle) || (needle.length >= 20 && f.includes(needle.slice(0, 20))));
|
|
8917
|
+
if (match) {
|
|
8918
|
+
const s = await BaseFileManager.readFileAsString(pathMod.join(dirPath, match));
|
|
8919
|
+
return { body: s, txIdLen: txId.length, gatewayStringLen: 0 };
|
|
8920
|
+
}
|
|
8921
|
+
}
|
|
8922
|
+
}
|
|
8923
|
+
catch {
|
|
8924
|
+
/* OPFS unsupported or download failed */
|
|
8925
|
+
}
|
|
8926
|
+
return { txIdLen: txId.length, gatewayStringLen: 0 };
|
|
8927
|
+
}
|
|
8928
|
+
/** Read saved HTML body for a parent Html property whose `propertyValue` points at the Html storage seed. */
|
|
8929
|
+
async function readHtmlBodyForStorageSeedPropertyValue(propertyValue) {
|
|
8930
|
+
const pv = String(propertyValue ?? '').trim();
|
|
8931
|
+
if (!pv)
|
|
8932
|
+
return undefined;
|
|
8933
|
+
const localId = await resolveHtmlStorageSeedLocalId(propertyValue);
|
|
8934
|
+
const fp = localId ? BaseFileManager.getFilesPath('html', `${localId}.html`) : '';
|
|
8935
|
+
let fileExists = fp ? await BaseFileManager.pathExists(fp) : false;
|
|
8936
|
+
// OPFS: file can appear shortly after create/download; avoid false "missing" before hitting Arweave.
|
|
8937
|
+
if (!fileExists && fp) {
|
|
8938
|
+
await BaseFileManager.waitForFileWithContent(fp, 100, 5000).catch(() => { });
|
|
8939
|
+
fileExists = await BaseFileManager.pathExists(fp);
|
|
8940
|
+
}
|
|
8941
|
+
let body = fileExists && fp ? await BaseFileManager.readFileAsString(fp) : undefined;
|
|
8942
|
+
if (!body && localId) {
|
|
8943
|
+
const ar = await readHtmlBodyFromChildStorageArweave(localId);
|
|
8944
|
+
body = ar.body;
|
|
8945
|
+
}
|
|
8946
|
+
return body;
|
|
8947
|
+
}
|
|
8948
|
+
|
|
8949
|
+
// Dynamic import to break circular dependency: schema/index -> ... -> hydrateFromDb -> schema/index
|
|
8950
|
+
// import { ModelPropertyDataTypes } from '@/schema'
|
|
8951
|
+
const logger$f = debug('seedSdk:property:actors:hydrateFromDb');
|
|
8952
|
+
const hydrateFromDb = fromCallback(({ sendBack, input: { context } }) => {
|
|
8953
|
+
const { seedUid, seedLocalId, propertyName: propertyNameRaw, propertyRecordSchema, modelName, } = context;
|
|
8954
|
+
if (!propertyNameRaw) {
|
|
8955
|
+
throw new Error('propertyName is required');
|
|
8956
|
+
}
|
|
8957
|
+
let propertyName = propertyNameRaw;
|
|
8958
|
+
// Note: isRelation, isImage, isFile checks moved inside async function
|
|
8959
|
+
// to use dynamically imported ModelPropertyDataTypes
|
|
8960
|
+
const _hydrateFromDb = async () => {
|
|
8961
|
+
// Use dynamic import to break circular dependency
|
|
8962
|
+
const schemaMod = await import('./index-DB3nZ0lK.js');
|
|
8963
|
+
const { ModelPropertyDataTypes } = schemaMod;
|
|
8964
|
+
const appDb = BaseDb.getAppDb();
|
|
8965
|
+
const whereClauses = [];
|
|
8966
|
+
// Re-check types with dynamically imported ModelPropertyDataTypes
|
|
8967
|
+
// Use normalizeDataType for case-insensitive comparison (schema may use "image" vs "Image")
|
|
8968
|
+
const normalizedDataType = normalizeDataType(propertyRecordSchema?.dataType);
|
|
8969
|
+
const normalizedRefValueType = normalizeDataType(propertyRecordSchema?.refValueType);
|
|
8970
|
+
propertyRecordSchema &&
|
|
8971
|
+
propertyRecordSchema.ref &&
|
|
8972
|
+
normalizedDataType === ModelPropertyDataTypes.Relation;
|
|
8973
|
+
const isImageDynamic = propertyRecordSchema &&
|
|
8974
|
+
(normalizedDataType === ModelPropertyDataTypes.Image ||
|
|
8975
|
+
normalizedRefValueType === ModelPropertyDataTypes.Image);
|
|
8976
|
+
const isFileDynamic = propertyRecordSchema &&
|
|
8977
|
+
normalizedDataType === ModelPropertyDataTypes.File;
|
|
8978
|
+
const isHtmlDynamic = propertyRecordSchema &&
|
|
8979
|
+
normalizedDataType === ModelPropertyDataTypes.Html;
|
|
8980
|
+
// Html/Image/File/Relation store metadata with Id suffix (e.g. htmlId); query both variants
|
|
8981
|
+
const propertyNames = getMetadataPropertyNamesForQuery(propertyName, normalizedDataType, normalizedRefValueType);
|
|
8982
|
+
whereClauses.push(propertyNames.length > 1
|
|
8983
|
+
? or(...propertyNames.map((n) => eq(metadata$1.propertyName, n)))
|
|
8984
|
+
: eq(metadata$1.propertyName, propertyNames[0]));
|
|
8985
|
+
// Draft rows often have only seed_local_id populated; on-chain rows may have uid.
|
|
8986
|
+
// Requiring both with AND misses valid metadata when only one column is set.
|
|
8987
|
+
if (seedUid && seedLocalId) {
|
|
8988
|
+
whereClauses.push(or(eq(metadata$1.seedLocalId, seedLocalId), eq(metadata$1.seedUid, seedUid)));
|
|
8989
|
+
}
|
|
8990
|
+
else if (seedUid) {
|
|
8991
|
+
whereClauses.push(eq(metadata$1.seedUid, seedUid));
|
|
8992
|
+
}
|
|
8993
|
+
else if (seedLocalId) {
|
|
8994
|
+
whereClauses.push(eq(metadata$1.seedLocalId, seedLocalId));
|
|
8995
|
+
}
|
|
8996
|
+
const rows = await appDb
|
|
8997
|
+
.select()
|
|
8998
|
+
.from(metadata$1)
|
|
8999
|
+
.where(and(...whereClauses))
|
|
9000
|
+
.orderBy(sql.raw('COALESCE(attestation_created_at, created_at) DESC'));
|
|
9001
|
+
if (!rows || !rows.length) {
|
|
9002
|
+
return;
|
|
9003
|
+
}
|
|
9004
|
+
const firstRow = rows[0];
|
|
9005
|
+
const { localId, uid, propertyName: propertyNameFromDb, propertyValue: propertyValueFromDb, seedLocalId: seedLocalIdFromDb, seedUid: seedUidFromDb, schemaUid: schemaUidFromDb, versionLocalId: versionLocalIdFromDb, versionUid: versionUidFromDb, refValueType, } = firstRow;
|
|
9006
|
+
let { refResolvedDisplayValue, refResolvedValue, localStorageDir } = firstRow;
|
|
9007
|
+
let propertyValueProcessed = propertyValueFromDb;
|
|
9008
|
+
let renderValue = refResolvedDisplayValue ?? undefined;
|
|
9009
|
+
// Image: always resolve display value from file (blob URLs in DB are invalid after reload)
|
|
9010
|
+
if (isImageDynamic) {
|
|
9011
|
+
let dir = localStorageDir;
|
|
9012
|
+
if (!dir && isImageDynamic) {
|
|
9013
|
+
dir = 'images';
|
|
9014
|
+
}
|
|
9015
|
+
dir = dir.replace(/^\//, '');
|
|
9016
|
+
if (propertyValueFromDb &&
|
|
9017
|
+
propertyValueFromDb.length === 66) {
|
|
9018
|
+
// Here the storageTransactionId is stored on a different record and
|
|
9019
|
+
// we want to add it as the refResolvedValue
|
|
9020
|
+
const storageTransactionQuery = await appDb
|
|
9021
|
+
.select({
|
|
9022
|
+
propertyValue: metadata$1.propertyValue,
|
|
9023
|
+
})
|
|
9024
|
+
.from(metadata$1)
|
|
9025
|
+
.where(and(eq(metadata$1.seedUid, propertyValueFromDb), or(eq(metadata$1.propertyName, 'storageTransactionId'), eq(metadata$1.propertyName, 'transactionId'))));
|
|
9026
|
+
if (storageTransactionQuery && storageTransactionQuery.length > 0) {
|
|
9027
|
+
const row = storageTransactionQuery[0];
|
|
9028
|
+
refResolvedValue = row.propertyValue;
|
|
9029
|
+
await updateMetadata({
|
|
9030
|
+
localId,
|
|
9031
|
+
refResolvedValue,
|
|
9032
|
+
localStorageDir: '/images',
|
|
9033
|
+
});
|
|
9034
|
+
}
|
|
9035
|
+
}
|
|
9036
|
+
const resolveMatchingFilePath = async (dir, needle) => {
|
|
9037
|
+
const dirPath = BaseFileManager.getFilesPath(dir);
|
|
9038
|
+
const dirExists = await BaseFileManager.pathExists(dirPath);
|
|
9039
|
+
if (!dirExists)
|
|
9040
|
+
return undefined;
|
|
9041
|
+
const fs = await BaseFileManager.getFs();
|
|
9042
|
+
const path = BaseFileManager.getPathModule();
|
|
9043
|
+
const files = await fs.promises.readdir(dirPath);
|
|
9044
|
+
const matchingFiles = files.filter((file) => {
|
|
9045
|
+
return path.basename(file).includes(needle);
|
|
9046
|
+
});
|
|
9047
|
+
if (!matchingFiles?.length)
|
|
9048
|
+
return undefined;
|
|
9049
|
+
return BaseFileManager.getFilesPath(dir, matchingFiles[0]);
|
|
9050
|
+
};
|
|
9051
|
+
if (refResolvedValue) {
|
|
9052
|
+
try {
|
|
9053
|
+
let filePath = await resolveMatchingFilePath(dir, refResolvedValue);
|
|
9054
|
+
if (!filePath) {
|
|
9055
|
+
await downloadTransactionIdWithDedupe(refResolvedValue);
|
|
9056
|
+
filePath = await resolveMatchingFilePath(dir, refResolvedValue);
|
|
9057
|
+
}
|
|
9058
|
+
localStorageDir = `/${dir}`;
|
|
9059
|
+
if (filePath) {
|
|
9060
|
+
const file = await BaseFileManager.readFile(filePath);
|
|
9061
|
+
refResolvedDisplayValue = URL.createObjectURL(file);
|
|
9062
|
+
renderValue = refResolvedDisplayValue;
|
|
9063
|
+
// Do not persist blob URL - it is session-scoped
|
|
9064
|
+
}
|
|
9065
|
+
}
|
|
9066
|
+
catch (e) {
|
|
9067
|
+
logger$f('[hydrateFromDb] Image file resolution error', e);
|
|
9068
|
+
}
|
|
9069
|
+
}
|
|
9070
|
+
}
|
|
9071
|
+
if (isFileDynamic && refResolvedValue) {
|
|
9072
|
+
try {
|
|
9073
|
+
const dir = (localStorageDir ?? '/files').replace(/^\//, '');
|
|
9074
|
+
const resolveMatchingFilePath = async (needle) => {
|
|
9075
|
+
const dirPath = BaseFileManager.getFilesPath(dir);
|
|
9076
|
+
const dirExists = await BaseFileManager.pathExists(dirPath);
|
|
9077
|
+
if (!dirExists)
|
|
9078
|
+
return undefined;
|
|
9079
|
+
const fs = await BaseFileManager.getFs();
|
|
9080
|
+
const path = BaseFileManager.getPathModule();
|
|
9081
|
+
const files = await fs.promises.readdir(dirPath);
|
|
9082
|
+
const matchingFiles = files.filter((file) => path.basename(file).includes(needle));
|
|
9083
|
+
if (!matchingFiles?.length)
|
|
9084
|
+
return undefined;
|
|
9085
|
+
return BaseFileManager.getFilesPath(dir, matchingFiles[0]);
|
|
9086
|
+
};
|
|
9087
|
+
let filePath = await resolveMatchingFilePath(refResolvedValue);
|
|
9088
|
+
if (!filePath) {
|
|
9089
|
+
await downloadTransactionIdWithDedupe(refResolvedValue);
|
|
9090
|
+
filePath = await resolveMatchingFilePath(refResolvedValue);
|
|
9091
|
+
}
|
|
9092
|
+
if (filePath) {
|
|
9093
|
+
localStorageDir = `/${dir}`;
|
|
9094
|
+
renderValue = await BaseFileManager.readFileAsString(filePath);
|
|
9095
|
+
}
|
|
9096
|
+
}
|
|
9097
|
+
catch (e) {
|
|
9098
|
+
logger$f('[hydrateFromDb] File resolution error', e);
|
|
9099
|
+
}
|
|
9100
|
+
}
|
|
9101
|
+
if (propertyRecordSchema &&
|
|
9102
|
+
normalizedDataType === ModelPropertyDataTypes.List &&
|
|
9103
|
+
typeof propertyValueFromDb === 'string') {
|
|
9104
|
+
propertyValueProcessed = parseListPropertyValueFromStorage(propertyValueFromDb);
|
|
9105
|
+
}
|
|
9106
|
+
sendBack({
|
|
9107
|
+
type: 'updateContext',
|
|
9108
|
+
localId,
|
|
9109
|
+
uid,
|
|
9110
|
+
propertyValue: propertyValueProcessed,
|
|
9111
|
+
seedLocalId: seedLocalIdFromDb,
|
|
9112
|
+
seedUid: seedUidFromDb,
|
|
9113
|
+
versionLocalId: versionLocalIdFromDb,
|
|
9114
|
+
versionUid: versionUidFromDb,
|
|
9115
|
+
schemaUid: schemaUidFromDb,
|
|
9116
|
+
refValueType,
|
|
9117
|
+
localStorageDir,
|
|
9118
|
+
refResolvedValue,
|
|
9119
|
+
refResolvedDisplayValue,
|
|
9120
|
+
renderValue,
|
|
9121
|
+
populatedFromDb: true,
|
|
9122
|
+
});
|
|
9123
|
+
if (propertyRecordSchema &&
|
|
9124
|
+
propertyRecordSchema.storageType &&
|
|
9125
|
+
propertyRecordSchema.storageType === 'ItemStorage') {
|
|
9126
|
+
const itemMod = await Promise.resolve().then(function () { return Item$1; });
|
|
9127
|
+
const { Item } = itemMod;
|
|
9128
|
+
const item = await Item.find({
|
|
9129
|
+
seedLocalId: seedLocalId ?? undefined,
|
|
9130
|
+
modelName,
|
|
9131
|
+
});
|
|
9132
|
+
if (item) {
|
|
9133
|
+
const dir = localStorageDir?.replace(/^\//, '') || 'files';
|
|
9134
|
+
const filePath = BaseFileManager.getFilesPath(dir, refResolvedValue);
|
|
9135
|
+
const exists = await BaseFileManager.pathExists(filePath);
|
|
9136
|
+
if (!exists) {
|
|
8158
9137
|
return;
|
|
8159
9138
|
}
|
|
8160
9139
|
const renderValue = await BaseFileManager.readFileAsString(filePath);
|
|
@@ -8165,15 +9144,34 @@ const hydrateFromDb = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
8165
9144
|
return;
|
|
8166
9145
|
}
|
|
8167
9146
|
}
|
|
8168
|
-
// Html: read file content for renderValue (blob URLs from DB are invalid after reload)
|
|
8169
|
-
//
|
|
8170
|
-
|
|
8171
|
-
|
|
8172
|
-
|
|
8173
|
-
|
|
8174
|
-
|
|
8175
|
-
if (
|
|
8176
|
-
const
|
|
9147
|
+
// Html: read file content for renderValue (blob URLs from DB are invalid after reload).
|
|
9148
|
+
// When propertyValue is the Html storage seed uid, resolve localId and read `html/{localId}.html`.
|
|
9149
|
+
if (isHtmlDynamic) {
|
|
9150
|
+
const htmlLocalStorageDir = refResolvedValue && !localStorageDir ? '/html' : localStorageDir ?? '/html';
|
|
9151
|
+
let htmlContent;
|
|
9152
|
+
let outRef = refResolvedValue;
|
|
9153
|
+
let outDir = htmlLocalStorageDir;
|
|
9154
|
+
if (refResolvedValue && htmlLocalStorageDir) {
|
|
9155
|
+
const dir = htmlLocalStorageDir.replace(/^\//, '');
|
|
9156
|
+
const filePath = BaseFileManager.getFilesPath(dir, refResolvedValue);
|
|
9157
|
+
let exists = await BaseFileManager.pathExists(filePath);
|
|
9158
|
+
if (!exists) {
|
|
9159
|
+
await BaseFileManager.waitForFileWithContent(filePath, 100, 5000).catch(() => { });
|
|
9160
|
+
exists = await BaseFileManager.pathExists(filePath);
|
|
9161
|
+
}
|
|
9162
|
+
if (exists) {
|
|
9163
|
+
htmlContent = await BaseFileManager.readFileAsString(filePath);
|
|
9164
|
+
}
|
|
9165
|
+
}
|
|
9166
|
+
if (!htmlContent && propertyValueFromDb) {
|
|
9167
|
+
htmlContent = await readHtmlBodyForStorageSeedPropertyValue(propertyValueFromDb);
|
|
9168
|
+
const lid = await resolveHtmlStorageSeedLocalId(String(propertyValueFromDb));
|
|
9169
|
+
if (lid) {
|
|
9170
|
+
outRef = `${lid}.html`;
|
|
9171
|
+
outDir = '/html';
|
|
9172
|
+
}
|
|
9173
|
+
}
|
|
9174
|
+
if (htmlContent) {
|
|
8177
9175
|
sendBack({
|
|
8178
9176
|
type: 'updateContext',
|
|
8179
9177
|
localId,
|
|
@@ -8185,8 +9183,8 @@ const hydrateFromDb = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
8185
9183
|
versionUid: versionUidFromDb,
|
|
8186
9184
|
schemaUid: schemaUidFromDb,
|
|
8187
9185
|
refValueType,
|
|
8188
|
-
localStorageDir:
|
|
8189
|
-
refResolvedValue,
|
|
9186
|
+
localStorageDir: outDir,
|
|
9187
|
+
refResolvedValue: outRef ?? refResolvedValue,
|
|
8190
9188
|
refResolvedDisplayValue,
|
|
8191
9189
|
renderValue: htmlContent,
|
|
8192
9190
|
populatedFromDb: true,
|
|
@@ -8200,11 +9198,11 @@ const hydrateFromDb = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
8200
9198
|
});
|
|
8201
9199
|
});
|
|
8202
9200
|
|
|
8203
|
-
const logger$
|
|
9201
|
+
const logger$e = debug('seedSdk:itemProperty:actors:loadOrCreateProperty');
|
|
8204
9202
|
const loadOrCreateProperty = fromCallback(({ sendBack, input: { context } }) => {
|
|
8205
9203
|
const _loadOrCreateProperty = async () => {
|
|
8206
9204
|
const { seedLocalId, seedUid, propertyName, versionLocalId } = context;
|
|
8207
|
-
logger$
|
|
9205
|
+
logger$e(`loadOrCreateProperty called for propertyName: ${propertyName}, seedLocalId: ${seedLocalId}, seedUid: ${seedUid}`);
|
|
8208
9206
|
if (!seedLocalId && !seedUid) {
|
|
8209
9207
|
throw new Error('seedLocalId or seedUid is required');
|
|
8210
9208
|
}
|
|
@@ -8250,15 +9248,15 @@ const loadOrCreateProperty = fromCallback(({ sendBack, input: { context } }) =>
|
|
|
8250
9248
|
const schemas = modelPropertiesToObject(model$1.properties);
|
|
8251
9249
|
propertyRecordSchema = schemas[propertyName];
|
|
8252
9250
|
if (propertyRecordSchema) {
|
|
8253
|
-
logger$
|
|
9251
|
+
logger$e(`Metadata not found: loaded propertyRecordSchema from Model for propertyName "${propertyName}"`);
|
|
8254
9252
|
}
|
|
8255
9253
|
}
|
|
8256
9254
|
}
|
|
8257
9255
|
catch (error) {
|
|
8258
|
-
logger$
|
|
9256
|
+
logger$e(`Metadata not found: Model fallback failed for propertyName "${propertyName}": ${error}`);
|
|
8259
9257
|
}
|
|
8260
9258
|
}
|
|
8261
|
-
logger$
|
|
9259
|
+
logger$e(`Metadata not found in database for propertyName: ${propertyName}, seedLocalId: ${seedLocalId}`);
|
|
8262
9260
|
sendBack({
|
|
8263
9261
|
type: 'loadOrCreatePropertySuccess',
|
|
8264
9262
|
property: {
|
|
@@ -8324,7 +9322,7 @@ const loadOrCreateProperty = fromCallback(({ sendBack, input: { context } }) =>
|
|
|
8324
9322
|
};
|
|
8325
9323
|
// Merge with schema from file/DB to get validation rules (enum, pattern, etc.) - properties table doesn't store these
|
|
8326
9324
|
try {
|
|
8327
|
-
const { getPropertySchema } = await import('./property-
|
|
9325
|
+
const { getPropertySchema } = await import('./property-DViA9nga.js');
|
|
8328
9326
|
let schemaFromFile = await getPropertySchema(normalizedModelName, propertyName);
|
|
8329
9327
|
if (!schemaFromFile?.validation) {
|
|
8330
9328
|
// Fallback: get validation from schemaData in database (Schema context may not be loaded yet)
|
|
@@ -8362,7 +9360,7 @@ const loadOrCreateProperty = fromCallback(({ sendBack, input: { context } }) =>
|
|
|
8362
9360
|
}
|
|
8363
9361
|
}
|
|
8364
9362
|
catch (error) {
|
|
8365
|
-
logger$
|
|
9363
|
+
logger$e(`Error loading propertyRecordSchema from database: ${error}`);
|
|
8366
9364
|
// Continue without propertyRecordSchema
|
|
8367
9365
|
}
|
|
8368
9366
|
}
|
|
@@ -8380,22 +9378,27 @@ const loadOrCreateProperty = fromCallback(({ sendBack, input: { context } }) =>
|
|
|
8380
9378
|
const schemas = modelPropertiesToObject(model$1.properties);
|
|
8381
9379
|
propertyRecordSchema = schemas[propertyName];
|
|
8382
9380
|
if (propertyRecordSchema) {
|
|
8383
|
-
logger$
|
|
9381
|
+
logger$e(`Fallback: loaded propertyRecordSchema from Model for propertyName "${propertyName}"`);
|
|
8384
9382
|
}
|
|
8385
9383
|
}
|
|
8386
9384
|
}
|
|
8387
9385
|
catch (error) {
|
|
8388
|
-
logger$
|
|
9386
|
+
logger$e(`Fallback Model lookup failed for propertyName "${propertyName}": ${error}`);
|
|
8389
9387
|
}
|
|
8390
9388
|
}
|
|
8391
9389
|
// For Html: read file content for renderValue (propertyValue is seed ID; blob URLs in DB are invalid after reload)
|
|
8392
9390
|
let renderValue = metadataRecord.propertyValue || undefined;
|
|
8393
9391
|
const refSeedType = metadataRecord.refSeedType;
|
|
8394
|
-
const
|
|
8395
|
-
|
|
9392
|
+
const normalizedHtmlDt = normalizeDataType(propertyRecordSchema?.dataType);
|
|
9393
|
+
const isHtml = refSeedType === 'html' || normalizedHtmlDt === ModelPropertyDataTypes.Html;
|
|
9394
|
+
// Fallback: derive refResolvedValue/localStorageDir from propertyValue when missing (e.g. EAS sync, legacy data).
|
|
9395
|
+
// After publish, propertyValue may be the Html storage seed uid while files stay named `{localId}.html`.
|
|
8396
9396
|
if (isHtml && !metadataRecord.refResolvedValue && metadataRecord.propertyValue) {
|
|
8397
|
-
|
|
8398
|
-
|
|
9397
|
+
const lid = await resolveHtmlStorageSeedLocalId(metadataRecord.propertyValue);
|
|
9398
|
+
if (lid) {
|
|
9399
|
+
metadataRecord.refResolvedValue = `${lid}.html`;
|
|
9400
|
+
metadataRecord.localStorageDir = '/html';
|
|
9401
|
+
}
|
|
8399
9402
|
}
|
|
8400
9403
|
// Fallback: when Html has refResolvedValue but localStorageDir is null (e.g. EAS sync, legacy records)
|
|
8401
9404
|
if (isHtml && metadataRecord.refResolvedValue && !metadataRecord.localStorageDir) {
|
|
@@ -8405,13 +9408,34 @@ const loadOrCreateProperty = fromCallback(({ sendBack, input: { context } }) =>
|
|
|
8405
9408
|
try {
|
|
8406
9409
|
const dir = metadataRecord.localStorageDir.replace(/^\//, '');
|
|
8407
9410
|
const filePath = BaseFileManager.getFilesPath(dir, metadataRecord.refResolvedValue);
|
|
8408
|
-
|
|
9411
|
+
let exists = await BaseFileManager.pathExists(filePath);
|
|
9412
|
+
if (!exists) {
|
|
9413
|
+
await BaseFileManager.waitForFileWithContent(filePath, 100, 5000).catch(() => { });
|
|
9414
|
+
exists = await BaseFileManager.pathExists(filePath);
|
|
9415
|
+
}
|
|
8409
9416
|
if (exists) {
|
|
8410
9417
|
renderValue = await BaseFileManager.readFileAsString(filePath);
|
|
8411
9418
|
}
|
|
9419
|
+
else {
|
|
9420
|
+
const viaSeedPointer = await readHtmlBodyForStorageSeedPropertyValue(metadataRecord.propertyValue);
|
|
9421
|
+
if (viaSeedPointer) {
|
|
9422
|
+
renderValue = viaSeedPointer;
|
|
9423
|
+
}
|
|
9424
|
+
}
|
|
8412
9425
|
}
|
|
8413
9426
|
catch (e) {
|
|
8414
|
-
logger$
|
|
9427
|
+
logger$e(`Failed to read Html file for ${propertyName}: ${e}`);
|
|
9428
|
+
}
|
|
9429
|
+
}
|
|
9430
|
+
// Covers missing ref row, wrong ref, or DB dataType casing "html" (handled by isHtml above).
|
|
9431
|
+
if (isHtml && metadataRecord.propertyValue) {
|
|
9432
|
+
const pv = String(metadataRecord.propertyValue).trim();
|
|
9433
|
+
const rv = typeof renderValue === 'string' ? renderValue.trim() : '';
|
|
9434
|
+
if (!rv || rv === pv) {
|
|
9435
|
+
const recovered = await readHtmlBodyForStorageSeedPropertyValue(metadataRecord.propertyValue);
|
|
9436
|
+
if (recovered) {
|
|
9437
|
+
renderValue = recovered;
|
|
9438
|
+
}
|
|
8415
9439
|
}
|
|
8416
9440
|
}
|
|
8417
9441
|
// Image: always resolve display value from file (blob URLs in DB are invalid after reload)
|
|
@@ -8421,28 +9445,83 @@ const loadOrCreateProperty = fromCallback(({ sendBack, input: { context } }) =>
|
|
|
8421
9445
|
const isImage = refSeedType === 'image' ||
|
|
8422
9446
|
normalizedDataType === 'Image' ||
|
|
8423
9447
|
normalizedRefValueType === 'Image';
|
|
9448
|
+
const resolveMatchingFilePath = async (dir, needle) => {
|
|
9449
|
+
const dirPath = BaseFileManager.getFilesPath(dir);
|
|
9450
|
+
const dirExists = await BaseFileManager.pathExists(dirPath);
|
|
9451
|
+
if (!dirExists)
|
|
9452
|
+
return undefined;
|
|
9453
|
+
const fs = await BaseFileManager.getFs();
|
|
9454
|
+
const path = BaseFileManager.getPathModule();
|
|
9455
|
+
const files = await fs.promises.readdir(dirPath);
|
|
9456
|
+
const matchingFiles = files.filter((file) => path.basename(file).includes(needle));
|
|
9457
|
+
if (!matchingFiles?.length)
|
|
9458
|
+
return undefined;
|
|
9459
|
+
return BaseFileManager.getFilesPath(dir, matchingFiles[0]);
|
|
9460
|
+
};
|
|
9461
|
+
// EAS-synced rows: parent metadata stores the image seed uid in property_value; filename/Arweave id is on the image seed's metadata.
|
|
9462
|
+
// hydrateFromDb already repairs this; doing it here avoids a multi-second gap where UI shows a non-blob value until rehydrate runs.
|
|
9463
|
+
if (isImage &&
|
|
9464
|
+
!metadataRecord.refResolvedValue &&
|
|
9465
|
+
typeof metadataRecord.propertyValue === 'string' &&
|
|
9466
|
+
metadataRecord.propertyValue.length === 66) {
|
|
9467
|
+
const storageTxRows = await db
|
|
9468
|
+
.select({ propertyValue: metadata$1.propertyValue })
|
|
9469
|
+
.from(metadata$1)
|
|
9470
|
+
.where(and(eq(metadata$1.seedUid, metadataRecord.propertyValue), or(eq(metadata$1.propertyName, 'storageTransactionId'), eq(metadata$1.propertyName, 'transactionId'))))
|
|
9471
|
+
.limit(1);
|
|
9472
|
+
const derivedTxId = storageTxRows[0]?.propertyValue;
|
|
9473
|
+
if (derivedTxId) {
|
|
9474
|
+
metadataRecord.refResolvedValue = derivedTxId;
|
|
9475
|
+
metadataRecord.localStorageDir = metadataRecord.localStorageDir ?? '/images';
|
|
9476
|
+
if (metadataRecord.localId) {
|
|
9477
|
+
try {
|
|
9478
|
+
await updateMetadata({
|
|
9479
|
+
localId: metadataRecord.localId,
|
|
9480
|
+
refResolvedValue: derivedTxId,
|
|
9481
|
+
localStorageDir: '/images',
|
|
9482
|
+
});
|
|
9483
|
+
}
|
|
9484
|
+
catch (e) {
|
|
9485
|
+
logger$e(`loadOrCreateProperty: updateMetadata refResolvedValue failed for ${propertyName}:`, e);
|
|
9486
|
+
}
|
|
9487
|
+
}
|
|
9488
|
+
}
|
|
9489
|
+
}
|
|
8424
9490
|
if (isImage && metadataRecord.refResolvedValue) {
|
|
8425
9491
|
try {
|
|
8426
9492
|
const dir = (metadataRecord.localStorageDir ?? '/images').replace(/^\//, '');
|
|
8427
|
-
|
|
8428
|
-
|
|
8429
|
-
|
|
8430
|
-
|
|
8431
|
-
|
|
8432
|
-
|
|
8433
|
-
const
|
|
8434
|
-
|
|
8435
|
-
|
|
8436
|
-
|
|
8437
|
-
|
|
8438
|
-
|
|
8439
|
-
|
|
8440
|
-
|
|
8441
|
-
|
|
9493
|
+
let filePath = await resolveMatchingFilePath(dir, metadataRecord.refResolvedValue);
|
|
9494
|
+
if (!filePath) {
|
|
9495
|
+
await downloadTransactionIdWithDedupe(metadataRecord.refResolvedValue);
|
|
9496
|
+
filePath = await resolveMatchingFilePath(dir, metadataRecord.refResolvedValue);
|
|
9497
|
+
}
|
|
9498
|
+
if (filePath) {
|
|
9499
|
+
const file = await BaseFileManager.readFile(filePath);
|
|
9500
|
+
const freshBlobUrl = URL.createObjectURL(file);
|
|
9501
|
+
renderValue = freshBlobUrl;
|
|
9502
|
+
refResolvedDisplayValue = freshBlobUrl;
|
|
9503
|
+
}
|
|
9504
|
+
}
|
|
9505
|
+
catch (e) {
|
|
9506
|
+
logger$e(`Failed to resolve Image file for ${propertyName}: ${e}`);
|
|
9507
|
+
}
|
|
9508
|
+
}
|
|
9509
|
+
const isFile = refSeedType === 'file' ||
|
|
9510
|
+
normalizedDataType === 'File';
|
|
9511
|
+
if (isFile && metadataRecord.refResolvedValue) {
|
|
9512
|
+
try {
|
|
9513
|
+
const dir = (metadataRecord.localStorageDir ?? '/files').replace(/^\//, '');
|
|
9514
|
+
let filePath = await resolveMatchingFilePath(dir, metadataRecord.refResolvedValue);
|
|
9515
|
+
if (!filePath) {
|
|
9516
|
+
await downloadTransactionIdWithDedupe(metadataRecord.refResolvedValue);
|
|
9517
|
+
filePath = await resolveMatchingFilePath(dir, metadataRecord.refResolvedValue);
|
|
9518
|
+
}
|
|
9519
|
+
if (filePath) {
|
|
9520
|
+
renderValue = await BaseFileManager.readFileAsString(filePath);
|
|
8442
9521
|
}
|
|
8443
9522
|
}
|
|
8444
9523
|
catch (e) {
|
|
8445
|
-
logger$
|
|
9524
|
+
logger$e(`Failed to resolve File for ${propertyName}: ${e}`);
|
|
8446
9525
|
}
|
|
8447
9526
|
}
|
|
8448
9527
|
let propertyValueOut = metadataRecord.propertyValue || undefined;
|
|
@@ -8474,7 +9553,7 @@ const loadOrCreateProperty = fromCallback(({ sendBack, input: { context } }) =>
|
|
|
8474
9553
|
});
|
|
8475
9554
|
};
|
|
8476
9555
|
_loadOrCreateProperty().catch((error) => {
|
|
8477
|
-
logger$
|
|
9556
|
+
logger$e(`Error in loadOrCreateProperty: ${error}`);
|
|
8478
9557
|
sendBack({
|
|
8479
9558
|
type: 'loadOrCreatePropertyError',
|
|
8480
9559
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -8504,10 +9583,10 @@ const getVersionData = async ({ localId, seedLocalId, uid, }) => {
|
|
|
8504
9583
|
return queryRows[0];
|
|
8505
9584
|
};
|
|
8506
9585
|
|
|
8507
|
-
const logger$
|
|
9586
|
+
const logger$d = debug('seedSdk:write:updateItemPropertyValue');
|
|
8508
9587
|
const updateItemPropertyValue = async ({ localId: localIdParam, propertyName, newValue, seedUid, seedLocalId, modelName, refSeedType, refResolvedValue, refResolvedDisplayValue, versionLocalId, versionUid, schemaUid, localStorageDir, dataType, refValueType, }) => {
|
|
8509
9588
|
if (!localIdParam && !seedLocalId) {
|
|
8510
|
-
logger$
|
|
9589
|
+
logger$d(`[db/write] [updateItemPropertyValue] no propertyLocalId or seedLocalId for property: ${propertyName}`);
|
|
8511
9590
|
return;
|
|
8512
9591
|
}
|
|
8513
9592
|
let safeNewValue = newValue;
|
|
@@ -8535,7 +9614,7 @@ const updateItemPropertyValue = async ({ localId: localIdParam, propertyName, ne
|
|
|
8535
9614
|
.select()
|
|
8536
9615
|
.from(metadata$1)
|
|
8537
9616
|
.where(and(propertyNameWhere, eq(metadata$1.seedLocalId, seedLocalId)))
|
|
8538
|
-
.orderBy(sql.raw('COALESCE(attestation_created_at, created_at) DESC')));
|
|
9617
|
+
.orderBy(sql.raw('COALESCE(attestation_created_at, created_at) DESC, local_id DESC')));
|
|
8539
9618
|
}
|
|
8540
9619
|
}
|
|
8541
9620
|
else if (localIdParam) {
|
|
@@ -8555,7 +9634,7 @@ const updateItemPropertyValue = async ({ localId: localIdParam, propertyName, ne
|
|
|
8555
9634
|
.select()
|
|
8556
9635
|
.from(metadata$1)
|
|
8557
9636
|
.where(and(propertyNameWhere, eq(metadata$1.seedLocalId, seedLocalId)))
|
|
8558
|
-
.orderBy(sql.raw('COALESCE(attestation_created_at, created_at) DESC')));
|
|
9637
|
+
.orderBy(sql.raw('COALESCE(attestation_created_at, created_at) DESC, local_id DESC')));
|
|
8559
9638
|
}
|
|
8560
9639
|
// const mostRecentRecordStatement = `SELECT local_id,
|
|
8561
9640
|
// uid,
|
|
@@ -8571,7 +9650,7 @@ const updateItemPropertyValue = async ({ localId: localIdParam, propertyName, ne
|
|
|
8571
9650
|
// FROM metadata
|
|
8572
9651
|
// WHERE property_name = '${propertyName}'
|
|
8573
9652
|
// AND seed_local_id = '${seedLocalId}'
|
|
8574
|
-
// ORDER BY COALESCE(attestation_created_at, created_at) DESC;`
|
|
9653
|
+
// ORDER BY COALESCE(attestation_created_at, created_at) DESC, local_id DESC;`
|
|
8575
9654
|
//
|
|
8576
9655
|
// const { rows } = await runQueryForStatement(mostRecentRecordStatement)
|
|
8577
9656
|
if (rows && rows.length > 0) {
|
|
@@ -8580,7 +9659,7 @@ const updateItemPropertyValue = async ({ localId: localIdParam, propertyName, ne
|
|
|
8580
9659
|
modelType === modelName?.toLowerCase() &&
|
|
8581
9660
|
refSeedTypeFromDb === refSeedType &&
|
|
8582
9661
|
refResolvedValueFromDb === refResolvedValue) {
|
|
8583
|
-
logger$
|
|
9662
|
+
logger$d(`[db/write] [updateItemPropertyValue] value is the same as most recent record for property: ${propertyNameFromDb}`);
|
|
8584
9663
|
return;
|
|
8585
9664
|
}
|
|
8586
9665
|
// This means we already have a local-only record so we should just update that one
|
|
@@ -8708,9 +9787,9 @@ const analyzeInput = fromCallback(({ sendBack, input: { context, event } }) => {
|
|
|
8708
9787
|
}
|
|
8709
9788
|
const _analyzeInput = async () => {
|
|
8710
9789
|
// Use dynamic import to break circular dependency
|
|
8711
|
-
const schemaMod = await import('./index-
|
|
9790
|
+
const schemaMod = await import('./index-DB3nZ0lK.js');
|
|
8712
9791
|
const { ModelPropertyDataTypes } = schemaMod;
|
|
8713
|
-
const { SchemaValidationService } = await import('./SchemaValidationService-
|
|
9792
|
+
const { SchemaValidationService } = await import('./SchemaValidationService-DXYRdSYa.js');
|
|
8714
9793
|
let propertyName = propertyNameRaw;
|
|
8715
9794
|
if (!propertyName) {
|
|
8716
9795
|
throw new Error('propertyName is required');
|
|
@@ -8908,7 +9987,7 @@ const createMetadata = async (metadataValues, propertyRecordSchema, options) =>
|
|
|
8908
9987
|
propertyRecordSchema?.validation &&
|
|
8909
9988
|
metadataValues.propertyValue != null &&
|
|
8910
9989
|
metadataValues.propertyValue !== '') {
|
|
8911
|
-
const { SchemaValidationService } = await import('./SchemaValidationService-
|
|
9990
|
+
const { SchemaValidationService } = await import('./SchemaValidationService-DXYRdSYa.js');
|
|
8912
9991
|
const validationService = new SchemaValidationService();
|
|
8913
9992
|
const validationResult = validationService.validatePropertyValue(metadataValues.propertyValue, propertyRecordSchema.dataType, propertyRecordSchema.validation, propertyRecordSchema.refValueType);
|
|
8914
9993
|
if (!validationResult.isValid && validationResult.errors.length > 0) {
|
|
@@ -8986,8 +10065,6 @@ const createMetadata = async (metadataValues, propertyRecordSchema, options) =>
|
|
|
8986
10065
|
return inserted[0];
|
|
8987
10066
|
};
|
|
8988
10067
|
|
|
8989
|
-
const eventEmitter = new EventEmitter();
|
|
8990
|
-
|
|
8991
10068
|
const readFileAsArrayBuffer$1 = async (file) => {
|
|
8992
10069
|
return new Promise((resolve) => {
|
|
8993
10070
|
const reader = new FileReader();
|
|
@@ -9134,6 +10211,12 @@ const saveImage = fromCallback(({ sendBack, input: { context, event } }) => {
|
|
|
9134
10211
|
}
|
|
9135
10212
|
const refResolvedDisplayValue = await BaseFileManager.getContentUrlFromPath(filePath);
|
|
9136
10213
|
let newLocalId;
|
|
10214
|
+
const resolvedPropertySchemaUid = schemaUid && schemaUid !== imageSchemaUid
|
|
10215
|
+
? schemaUid
|
|
10216
|
+
: (await getEasSchemaForItemProperty({
|
|
10217
|
+
propertyName,
|
|
10218
|
+
easDataType: 'bytes32',
|
|
10219
|
+
}))?.id;
|
|
9137
10220
|
if (!localId) {
|
|
9138
10221
|
const result = await createMetadata({
|
|
9139
10222
|
propertyName,
|
|
@@ -9143,7 +10226,7 @@ const saveImage = fromCallback(({ sendBack, input: { context, event } }) => {
|
|
|
9143
10226
|
versionLocalId,
|
|
9144
10227
|
versionUid,
|
|
9145
10228
|
modelName,
|
|
9146
|
-
schemaUid:
|
|
10229
|
+
schemaUid: resolvedPropertySchemaUid,
|
|
9147
10230
|
refSeedType: 'image',
|
|
9148
10231
|
refModelUid: imageSchemaUid,
|
|
9149
10232
|
refResolvedValue: fileName,
|
|
@@ -9162,7 +10245,7 @@ const saveImage = fromCallback(({ sendBack, input: { context, event } }) => {
|
|
|
9162
10245
|
seedLocalId,
|
|
9163
10246
|
versionLocalId,
|
|
9164
10247
|
modelName,
|
|
9165
|
-
schemaUid,
|
|
10248
|
+
schemaUid: resolvedPropertySchemaUid,
|
|
9166
10249
|
refSeedType: 'image',
|
|
9167
10250
|
refResolvedValue: fileName,
|
|
9168
10251
|
localStorageDir: '/images',
|
|
@@ -9495,7 +10578,7 @@ const saveRelation = fromCallback(({ sendBack, input: { context, event } }) => {
|
|
|
9495
10578
|
}
|
|
9496
10579
|
const _saveRelation = async () => {
|
|
9497
10580
|
// Use dynamic import to break circular dependency
|
|
9498
|
-
const schemaMod = await import('./index-
|
|
10581
|
+
const schemaMod = await import('./index-DB3nZ0lK.js');
|
|
9499
10582
|
const { ModelPropertyDataTypes } = schemaMod;
|
|
9500
10583
|
if (!propertyNameRaw) {
|
|
9501
10584
|
throw new Error('propertyName is required');
|
|
@@ -9704,6 +10787,10 @@ const propertyMachine = setup({
|
|
|
9704
10787
|
context: {},
|
|
9705
10788
|
input: {},
|
|
9706
10789
|
},
|
|
10790
|
+
guards: {
|
|
10791
|
+
// stateIn return type does not satisfy setup() inference; runtime guard is correct for root state `idle`.
|
|
10792
|
+
propertyMachineIsIdle: stateIn('idle'),
|
|
10793
|
+
},
|
|
9707
10794
|
// actions: {
|
|
9708
10795
|
// updateContext: updateMachineContext,
|
|
9709
10796
|
// },
|
|
@@ -9726,7 +10813,11 @@ const propertyMachine = setup({
|
|
|
9726
10813
|
initial: 'waitingForDb',
|
|
9727
10814
|
context: ({ input }) => input,
|
|
9728
10815
|
on: {
|
|
9729
|
-
|
|
10816
|
+
/** Re-run DB hydration (e.g. after EAS sync wrote new metadata for this version). */
|
|
10817
|
+
rehydrateFromDb: {
|
|
10818
|
+
guard: 'propertyMachineIsIdle',
|
|
10819
|
+
target: '.hydratingFromDb',
|
|
10820
|
+
},
|
|
9730
10821
|
save: {
|
|
9731
10822
|
actions: assign({
|
|
9732
10823
|
isSaving: true,
|
|
@@ -10325,6 +11416,8 @@ function createReactiveProxy(config) {
|
|
|
10325
11416
|
return proxy;
|
|
10326
11417
|
}
|
|
10327
11418
|
|
|
11419
|
+
/** Parent Html property `propertyValue` after publish (66-char seed uid). */
|
|
11420
|
+
const HTML_PROP_SEED_UID_RE = /^0x[a-fA-F0-9]{64}$/;
|
|
10328
11421
|
// Start loading Model at module load time (non-blocking)
|
|
10329
11422
|
Promise.resolve().then(function () { return Model$1; }).then(module => {
|
|
10330
11423
|
module.Model;
|
|
@@ -10424,7 +11517,7 @@ const resolvePropertyRecordSchemaFromModel = async (modelName, propertyName, mod
|
|
|
10424
11517
|
};
|
|
10425
11518
|
/** Convert modelType (snake_case from DB) to Model name (PascalCase). startCase adds spaces ("Test Post"); Model names are "TestPost". */
|
|
10426
11519
|
const modelTypeToModelName = (modelType) => modelType ? upperFirst(camelCase(modelType)) : '';
|
|
10427
|
-
const logger$
|
|
11520
|
+
const logger$c = debug('seedSdk:property:class');
|
|
10428
11521
|
// Define tracked properties for the Proxy
|
|
10429
11522
|
// These properties will be read from/written to the actor context
|
|
10430
11523
|
const TRACKED_PROPERTIES$2 = [
|
|
@@ -10506,7 +11599,7 @@ class ItemProperty {
|
|
|
10506
11599
|
serviceInput.propertyValue = JSON.parse(propertyValue);
|
|
10507
11600
|
}
|
|
10508
11601
|
catch (e) {
|
|
10509
|
-
logger$
|
|
11602
|
+
logger$c('List property value is not JSON', e);
|
|
10510
11603
|
}
|
|
10511
11604
|
}
|
|
10512
11605
|
}
|
|
@@ -10529,7 +11622,7 @@ class ItemProperty {
|
|
|
10529
11622
|
return;
|
|
10530
11623
|
}
|
|
10531
11624
|
// Use dynamic import to break circular dependency
|
|
10532
|
-
const schemaMod = await import('./index-
|
|
11625
|
+
const schemaMod = await import('./index-DB3nZ0lK.js');
|
|
10533
11626
|
const { ModelPropertyDataTypes } = schemaMod;
|
|
10534
11627
|
const { context } = snapshot;
|
|
10535
11628
|
const { propertyRecordSchema } = context;
|
|
@@ -10552,7 +11645,8 @@ class ItemProperty {
|
|
|
10552
11645
|
propertyRecordSchema.storageType === 'ItemStorage' &&
|
|
10553
11646
|
context.refResolvedValue &&
|
|
10554
11647
|
context.localStorageDir;
|
|
10555
|
-
const
|
|
11648
|
+
const normalizedSchemaDt = normalizeDataType(propertyRecordSchema?.dataType);
|
|
11649
|
+
const isHtml = (context.refSeedType === 'html' || normalizedSchemaDt === ModelPropertyDataTypes.Html) &&
|
|
10556
11650
|
context.refResolvedValue;
|
|
10557
11651
|
// Fix: When File/Image property has a File object before save completes, set refResolvedValue and renderValue
|
|
10558
11652
|
// so the UI can display the filename and preview immediately (these update again when save completes)
|
|
@@ -10588,7 +11682,11 @@ class ItemProperty {
|
|
|
10588
11682
|
const dir = context.localStorageDir?.replace(/^\//, '') || (isHtml ? 'html' : 'images');
|
|
10589
11683
|
const filePath = BaseFileManager.getFilesPath(dir, context.refResolvedValue);
|
|
10590
11684
|
try {
|
|
10591
|
-
|
|
11685
|
+
let exists = await BaseFileManager.pathExists(filePath);
|
|
11686
|
+
if (!exists && isHtml) {
|
|
11687
|
+
await BaseFileManager.waitForFileWithContent(filePath, 100, 5000).catch(() => { });
|
|
11688
|
+
exists = await BaseFileManager.pathExists(filePath);
|
|
11689
|
+
}
|
|
10592
11690
|
if (exists && (isItemStorage || isHtml)) {
|
|
10593
11691
|
renderValue = await BaseFileManager.readFileAsString(filePath);
|
|
10594
11692
|
}
|
|
@@ -10608,8 +11706,8 @@ class ItemProperty {
|
|
|
10608
11706
|
if (isFile && isFileValue) {
|
|
10609
11707
|
renderValue = pv.name;
|
|
10610
11708
|
}
|
|
10611
|
-
else if (isImage) {
|
|
10612
|
-
// FS race
|
|
11709
|
+
else if (isImage || isHtml) {
|
|
11710
|
+
// FS race, OPFS cleared, or HTML served from Arweave: do not clobber hydrated/rehydrated value
|
|
10613
11711
|
renderValue = undefined;
|
|
10614
11712
|
}
|
|
10615
11713
|
else {
|
|
@@ -10618,13 +11716,21 @@ class ItemProperty {
|
|
|
10618
11716
|
}
|
|
10619
11717
|
}
|
|
10620
11718
|
catch (e) {
|
|
10621
|
-
logger$
|
|
10622
|
-
renderValue = 'No file found';
|
|
11719
|
+
logger$c(`[ItemProperty] [${context.seedLocalId}] [${context.propertyName}] [storageType] error`, e);
|
|
11720
|
+
renderValue = isHtml ? undefined : 'No file found';
|
|
10623
11721
|
}
|
|
10624
11722
|
}
|
|
10625
11723
|
if (!renderValue) {
|
|
10626
11724
|
renderValue = context.renderValue || context.propertyValue;
|
|
10627
11725
|
}
|
|
11726
|
+
const pvStr = typeof context.propertyValue === 'string' ? context.propertyValue.trim() : '';
|
|
11727
|
+
if (normalizedSchemaDt === ModelPropertyDataTypes.Html &&
|
|
11728
|
+
HTML_PROP_SEED_UID_RE.test(pvStr) &&
|
|
11729
|
+
renderValue === pvStr &&
|
|
11730
|
+
typeof context.renderValue === 'string' &&
|
|
11731
|
+
context.renderValue.length > pvStr.length) {
|
|
11732
|
+
renderValue = context.renderValue;
|
|
11733
|
+
}
|
|
10628
11734
|
let transformedPropertyName = propertyName;
|
|
10629
11735
|
const skipTransform = INTERNAL_PROPERTY_NAMES.includes(propertyName) || !!this._alias;
|
|
10630
11736
|
if (!skipTransform && transformedPropertyName.endsWith('Id')) {
|
|
@@ -10687,7 +11793,7 @@ class ItemProperty {
|
|
|
10687
11793
|
const normalizedRefValueType = normalizeDataType(propertyRecordSchema?.refValueType);
|
|
10688
11794
|
const propertyNames = getMetadataPropertyNamesForQuery(propertyName, normalizedDataType, normalizedRefValueType);
|
|
10689
11795
|
const propertyNameVariant = propertyNames.length > 1 ? propertyNames[1] : undefined;
|
|
10690
|
-
const _mod_6 = await import('./index-
|
|
11796
|
+
const _mod_6 = await import('./index-Bp0ChnQr.js');
|
|
10691
11797
|
const _ns_6 = _mod_6.s;
|
|
10692
11798
|
const seedSchemaMod = _ns_6;
|
|
10693
11799
|
const { metadata } = seedSchemaMod;
|
|
@@ -11039,6 +12145,35 @@ class ItemProperty {
|
|
|
11039
12145
|
instance._service.send({ type: 'updateContext', ...updates });
|
|
11040
12146
|
}
|
|
11041
12147
|
}
|
|
12148
|
+
// After wipe/reconnect, cached actors can stay idle with stale renderValue while DB + Arweave
|
|
12149
|
+
// paths would hydrate. Re-run DB hydration without clobbering propertyValue.
|
|
12150
|
+
const svc = instance._service;
|
|
12151
|
+
const snap = svc.getSnapshot();
|
|
12152
|
+
if (snap.status === 'active' && snap.value === 'idle') {
|
|
12153
|
+
const schema = props.propertyRecordSchema ?? ctx.propertyRecordSchema;
|
|
12154
|
+
const dt = normalizeDataType(schema?.dataType);
|
|
12155
|
+
const isHtmlProp = props.refSeedType === 'html' ||
|
|
12156
|
+
ctx.refSeedType === 'html' ||
|
|
12157
|
+
dt === ModelPropertyDataTypes.Html;
|
|
12158
|
+
const isListProp = dt === ModelPropertyDataTypes.List;
|
|
12159
|
+
const isRelationProp = dt === ModelPropertyDataTypes.Relation;
|
|
12160
|
+
const pv = ctx.propertyValue;
|
|
12161
|
+
const pvStr = typeof pv === 'string' ? pv.trim() : '';
|
|
12162
|
+
const renderVal = ctx.renderValue;
|
|
12163
|
+
const renderMissing = renderVal == null || (typeof renderVal === 'string' && renderVal.length === 0);
|
|
12164
|
+
const htmlStuckOnUid = isHtmlProp &&
|
|
12165
|
+
HTML_PROP_SEED_UID_RE.test(pvStr) &&
|
|
12166
|
+
(renderMissing || renderVal === pv);
|
|
12167
|
+
const pvPresent = pv != null &&
|
|
12168
|
+
(Array.isArray(pv) ? pv.length > 0 : String(pv).trim().length > 0);
|
|
12169
|
+
const listOrRelationNeedsResolve = (isListProp || isRelationProp) && renderMissing && pvPresent;
|
|
12170
|
+
const versionChanged = props.versionLocalId != null &&
|
|
12171
|
+
ctx.versionLocalId != null &&
|
|
12172
|
+
props.versionLocalId !== ctx.versionLocalId;
|
|
12173
|
+
if (htmlStuckOnUid || listOrRelationNeedsResolve || versionChanged) {
|
|
12174
|
+
svc.send({ type: 'rehydrateFromDb' });
|
|
12175
|
+
}
|
|
12176
|
+
}
|
|
11042
12177
|
// On cache hit, do not sync propertyValue: refetches can race with in-memory updates (e.g. save()).
|
|
11043
12178
|
if (!waitForReady)
|
|
11044
12179
|
return instance;
|
|
@@ -11388,7 +12523,7 @@ class ItemProperty {
|
|
|
11388
12523
|
}
|
|
11389
12524
|
async save() {
|
|
11390
12525
|
const ctx = this._getSnapshotContext();
|
|
11391
|
-
const { assertItemOwned } = await import('./ownership-
|
|
12526
|
+
const { assertItemOwned } = await import('./ownership-D-KsIkxM.js');
|
|
11392
12527
|
await assertItemOwned({
|
|
11393
12528
|
seedLocalId: ctx?.seedLocalId ?? undefined,
|
|
11394
12529
|
seedUid: ctx?.seedUid ?? undefined,
|
|
@@ -11481,7 +12616,7 @@ class ItemProperty {
|
|
|
11481
12616
|
if (!propertyName || (!seedLocalId && !seedUid))
|
|
11482
12617
|
return;
|
|
11483
12618
|
if (db) {
|
|
11484
|
-
const _mod_7 = await import('./index-
|
|
12619
|
+
const _mod_7 = await import('./index-Bp0ChnQr.js');
|
|
11485
12620
|
const _ns_7 = _mod_7.s;
|
|
11486
12621
|
const seedSchemaMod = _ns_7;
|
|
11487
12622
|
const { metadata } = seedSchemaMod;
|
|
@@ -11729,7 +12864,7 @@ class Item {
|
|
|
11729
12864
|
});
|
|
11730
12865
|
};
|
|
11731
12866
|
this.unpublish = async () => {
|
|
11732
|
-
const { assertItemOwned } = await import('./ownership-
|
|
12867
|
+
const { assertItemOwned } = await import('./ownership-D-KsIkxM.js');
|
|
11733
12868
|
const { getRevokeExecutor } = await Promise.resolve().then(function () { return publishConfig; });
|
|
11734
12869
|
await assertItemOwned(this);
|
|
11735
12870
|
const seedUid = this.seedUid;
|
|
@@ -11753,7 +12888,7 @@ class Item {
|
|
|
11753
12888
|
this._service.send({ type: 'updateContext', revokedAt });
|
|
11754
12889
|
};
|
|
11755
12890
|
this.publish = async () => {
|
|
11756
|
-
const { assertItemOwned } = await import('./ownership-
|
|
12891
|
+
const { assertItemOwned } = await import('./ownership-D-KsIkxM.js');
|
|
11757
12892
|
await assertItemOwned(this);
|
|
11758
12893
|
this._service.send({ type: 'startPublish' });
|
|
11759
12894
|
return new Promise((resolve, reject) => {
|
|
@@ -11789,12 +12924,12 @@ class Item {
|
|
|
11789
12924
|
};
|
|
11790
12925
|
this.getPublishUploads = async (options) => {
|
|
11791
12926
|
// Use dynamic import to break circular dependency
|
|
11792
|
-
const getPublishUploadsMod = await import('./getPublishUploads-
|
|
12927
|
+
const getPublishUploadsMod = await import('./getPublishUploads-CH72lAID.js');
|
|
11793
12928
|
const { getPublishUploads } = getPublishUploadsMod;
|
|
11794
12929
|
return await getPublishUploads(this, [], undefined, options);
|
|
11795
12930
|
};
|
|
11796
12931
|
this.getPublishPayload = async (uploadedTransactions, options) => {
|
|
11797
|
-
const getPublishPayloadMod = await import('./getPublishPayload-
|
|
12932
|
+
const getPublishPayloadMod = await import('./getPublishPayload-DEdHgrgC.js');
|
|
11798
12933
|
const { getPublishPayload } = getPublishPayloadMod;
|
|
11799
12934
|
return await getPublishPayload(this, uploadedTransactions, options);
|
|
11800
12935
|
};
|
|
@@ -11911,6 +13046,8 @@ class Item {
|
|
|
11911
13046
|
'schemaUid',
|
|
11912
13047
|
'latestVersionLocalId',
|
|
11913
13048
|
'latestVersionUid',
|
|
13049
|
+
'publishedVersionUid',
|
|
13050
|
+
'publishedVersionLocalId',
|
|
11914
13051
|
];
|
|
11915
13052
|
const keysFromInitial = Object.keys(initialValues).filter((key) => !metadataKeys.includes(key));
|
|
11916
13053
|
const schemaNameForModel = initialValues.schemaName;
|
|
@@ -11954,6 +13091,128 @@ class Item {
|
|
|
11954
13091
|
});
|
|
11955
13092
|
}
|
|
11956
13093
|
}
|
|
13094
|
+
/** Prefer local id so list rows (local + uid) resolve the same cache entry as early draft loads. */
|
|
13095
|
+
static findItemInstanceCacheEntryByProps(props) {
|
|
13096
|
+
const l = props.seedLocalId;
|
|
13097
|
+
const u = props.seedUid;
|
|
13098
|
+
if (typeof l === 'string' && l.length > 0) {
|
|
13099
|
+
const e = this.instanceCache.get(l);
|
|
13100
|
+
if (e)
|
|
13101
|
+
return e;
|
|
13102
|
+
}
|
|
13103
|
+
if (typeof u === 'string' && u.length > 0) {
|
|
13104
|
+
const e = this.instanceCache.get(u);
|
|
13105
|
+
if (e)
|
|
13106
|
+
return e;
|
|
13107
|
+
}
|
|
13108
|
+
return undefined;
|
|
13109
|
+
}
|
|
13110
|
+
static findItemInstanceCacheEntryById(id) {
|
|
13111
|
+
const direct = this.instanceCache.get(id);
|
|
13112
|
+
if (direct)
|
|
13113
|
+
return direct;
|
|
13114
|
+
for (const [, entry] of this.instanceCache) {
|
|
13115
|
+
const ctx = entry.instance._getSnapshotContext();
|
|
13116
|
+
if (ctx.seedLocalId === id || ctx.seedUid === id)
|
|
13117
|
+
return entry;
|
|
13118
|
+
}
|
|
13119
|
+
return undefined;
|
|
13120
|
+
}
|
|
13121
|
+
static collectInstanceCacheKeysForInstance(instance) {
|
|
13122
|
+
const keys = [];
|
|
13123
|
+
for (const [k, v] of this.instanceCache) {
|
|
13124
|
+
if (v.instance === instance)
|
|
13125
|
+
keys.push(k);
|
|
13126
|
+
}
|
|
13127
|
+
return keys;
|
|
13128
|
+
}
|
|
13129
|
+
static registerItemInInstanceCache(instance) {
|
|
13130
|
+
const ctx = instance._getSnapshotContext();
|
|
13131
|
+
const lid = typeof ctx.seedLocalId === 'string' && ctx.seedLocalId.length > 0
|
|
13132
|
+
? ctx.seedLocalId
|
|
13133
|
+
: undefined;
|
|
13134
|
+
const uid = typeof ctx.seedUid === 'string' && ctx.seedUid.length > 0 ? ctx.seedUid : undefined;
|
|
13135
|
+
const entry = { instance, refCount: 1 };
|
|
13136
|
+
if (lid)
|
|
13137
|
+
this.instanceCache.set(lid, entry);
|
|
13138
|
+
if (uid && uid !== lid)
|
|
13139
|
+
this.instanceCache.set(uid, entry);
|
|
13140
|
+
if (!lid && !uid) {
|
|
13141
|
+
throw new Error('Item.registerItemInInstanceCache: missing seedLocalId and seedUid');
|
|
13142
|
+
}
|
|
13143
|
+
}
|
|
13144
|
+
static releaseItemInstanceCacheHold(instance) {
|
|
13145
|
+
const keys = this.collectInstanceCacheKeysForInstance(instance);
|
|
13146
|
+
if (keys.length === 0)
|
|
13147
|
+
return;
|
|
13148
|
+
const entry = this.instanceCache.get(keys[0]);
|
|
13149
|
+
entry.refCount -= 1;
|
|
13150
|
+
if (entry.refCount <= 0) {
|
|
13151
|
+
for (const k of keys) {
|
|
13152
|
+
this.instanceCache.delete(k);
|
|
13153
|
+
}
|
|
13154
|
+
}
|
|
13155
|
+
}
|
|
13156
|
+
/**
|
|
13157
|
+
* Item machine can reach `idle` before `propertyInstances` is merged (race) or while
|
|
13158
|
+
* child ItemProperty actors are still hydrating. useItems / Item.all must not return that shell.
|
|
13159
|
+
*/
|
|
13160
|
+
static async waitForItemInstanceReadyForRead(item, readyTimeout) {
|
|
13161
|
+
await waitForEntityIdle(item, { timeout: readyTimeout });
|
|
13162
|
+
const svc = item.getService();
|
|
13163
|
+
try {
|
|
13164
|
+
await waitFor(svc, (snap) => {
|
|
13165
|
+
if ('value' in snap && snap.value === 'error') {
|
|
13166
|
+
throw new Error('Entity failed to load');
|
|
13167
|
+
}
|
|
13168
|
+
if (!('value' in snap) || snap.value !== 'idle') {
|
|
13169
|
+
return false;
|
|
13170
|
+
}
|
|
13171
|
+
const ctx = snap.context || {};
|
|
13172
|
+
const versionsCount = ctx.versionsCount ?? 0;
|
|
13173
|
+
const hasHeadVersion = !!ctx.latestVersionLocalId;
|
|
13174
|
+
if (versionsCount === 0 && !hasHeadVersion) {
|
|
13175
|
+
return true;
|
|
13176
|
+
}
|
|
13177
|
+
return (ctx.propertyInstances?.size ?? 0) > 0;
|
|
13178
|
+
}, { timeout: readyTimeout });
|
|
13179
|
+
}
|
|
13180
|
+
catch (e) {
|
|
13181
|
+
if (e?.message === 'Entity failed to load') {
|
|
13182
|
+
throw e;
|
|
13183
|
+
}
|
|
13184
|
+
const msg = typeof e?.message === 'string' ? e.message : '';
|
|
13185
|
+
const isWaitForTimeout = msg.includes('Timeout') || msg.toLowerCase().includes('timed out');
|
|
13186
|
+
if (!isWaitForTimeout) {
|
|
13187
|
+
throw e;
|
|
13188
|
+
}
|
|
13189
|
+
}
|
|
13190
|
+
const snap = svc.getSnapshot();
|
|
13191
|
+
const pis = snap.context?.propertyInstances;
|
|
13192
|
+
if (!pis || pis.size === 0) {
|
|
13193
|
+
return;
|
|
13194
|
+
}
|
|
13195
|
+
await Promise.all([...pis.values()].map((prop) => waitForEntityIdle(prop, {
|
|
13196
|
+
timeout: readyTimeout,
|
|
13197
|
+
throwOnError: false,
|
|
13198
|
+
})));
|
|
13199
|
+
}
|
|
13200
|
+
static itemCacheEntryLooksUnhydratedAfterIdle(instance, props) {
|
|
13201
|
+
const snap = instance.getService().getSnapshot();
|
|
13202
|
+
if (snap.value !== 'idle')
|
|
13203
|
+
return false;
|
|
13204
|
+
const mapSize = snap.context.propertyInstances?.size ?? 0;
|
|
13205
|
+
if (mapSize > 0)
|
|
13206
|
+
return false;
|
|
13207
|
+
const ctx = snap.context;
|
|
13208
|
+
const versionsCount = props.versionsCount ?? ctx.versionsCount ?? 0;
|
|
13209
|
+
const hasVersionHead = versionsCount > 0 ||
|
|
13210
|
+
!!props.latestVersionLocalId ||
|
|
13211
|
+
!!ctx.latestVersionLocalId ||
|
|
13212
|
+
!!props.latestVersionUid ||
|
|
13213
|
+
!!ctx.latestVersionUid;
|
|
13214
|
+
return hasVersionHead;
|
|
13215
|
+
}
|
|
11957
13216
|
static async create(props, options) {
|
|
11958
13217
|
const waitForReady = options?.waitForReady !== false;
|
|
11959
13218
|
const readyTimeout = options?.readyTimeout ?? 5000;
|
|
@@ -11961,45 +13220,66 @@ class Item {
|
|
|
11961
13220
|
props.modelName = startCase(props.type);
|
|
11962
13221
|
}
|
|
11963
13222
|
if (props.seedUid || props.seedLocalId) {
|
|
11964
|
-
|
|
11965
|
-
|
|
11966
|
-
|
|
11967
|
-
|
|
11968
|
-
|
|
11969
|
-
|
|
11970
|
-
|
|
11971
|
-
|
|
11972
|
-
|
|
11973
|
-
|
|
11974
|
-
|
|
11975
|
-
|
|
11976
|
-
|
|
11977
|
-
|
|
11978
|
-
|
|
11979
|
-
|
|
13223
|
+
cacheReuse: {
|
|
13224
|
+
const cachedEntry = this.findItemInstanceCacheEntryByProps(props);
|
|
13225
|
+
if (cachedEntry) {
|
|
13226
|
+
const instance = cachedEntry.instance;
|
|
13227
|
+
cachedEntry.refCount += 1;
|
|
13228
|
+
for (const [propertyName, propertyValue] of Object.entries(props)) {
|
|
13229
|
+
const snapshot = instance.getService().getSnapshot();
|
|
13230
|
+
const propertyInstances = snapshot.context.propertyInstances;
|
|
13231
|
+
if (!propertyInstances || !propertyInstances.has(propertyName)) {
|
|
13232
|
+
continue;
|
|
13233
|
+
}
|
|
13234
|
+
const propertyInstance = propertyInstances.get(propertyName);
|
|
13235
|
+
if (!propertyInstance) {
|
|
13236
|
+
continue;
|
|
13237
|
+
}
|
|
13238
|
+
propertyInstance.getService().send({
|
|
13239
|
+
type: 'updateContext',
|
|
13240
|
+
propertyValue,
|
|
13241
|
+
});
|
|
11980
13242
|
}
|
|
11981
|
-
|
|
11982
|
-
|
|
11983
|
-
propertyValue,
|
|
11984
|
-
});
|
|
11985
|
-
}
|
|
11986
|
-
if (!waitForReady)
|
|
11987
|
-
return instance;
|
|
11988
|
-
try {
|
|
11989
|
-
await waitForEntityIdle(instance, { timeout: readyTimeout });
|
|
11990
|
-
}
|
|
11991
|
-
catch (err) {
|
|
13243
|
+
if (!waitForReady)
|
|
13244
|
+
return instance;
|
|
11992
13245
|
try {
|
|
11993
|
-
|
|
13246
|
+
await this.waitForItemInstanceReadyForRead(instance, readyTimeout);
|
|
11994
13247
|
}
|
|
11995
|
-
catch {
|
|
11996
|
-
|
|
13248
|
+
catch (err) {
|
|
13249
|
+
try {
|
|
13250
|
+
instance.unload();
|
|
13251
|
+
}
|
|
13252
|
+
catch {
|
|
13253
|
+
/* best-effort cache cleanup */
|
|
13254
|
+
}
|
|
13255
|
+
throw err;
|
|
11997
13256
|
}
|
|
11998
|
-
|
|
13257
|
+
if (waitForReady &&
|
|
13258
|
+
this.itemCacheEntryLooksUnhydratedAfterIdle(instance, props)) {
|
|
13259
|
+
forceRemoveFromCaches(instance, {
|
|
13260
|
+
getCacheKeys: () => this.collectInstanceCacheKeysForInstance(instance),
|
|
13261
|
+
caches: [Item.instanceCache],
|
|
13262
|
+
});
|
|
13263
|
+
try {
|
|
13264
|
+
unloadEntity(instance, {
|
|
13265
|
+
getCacheKeys: () => [],
|
|
13266
|
+
caches: [],
|
|
13267
|
+
instanceState: itemInstanceState,
|
|
13268
|
+
getService: (inst) => inst._service,
|
|
13269
|
+
onUnload: (inst) => {
|
|
13270
|
+
inst._subscription?.unsubscribe();
|
|
13271
|
+
},
|
|
13272
|
+
});
|
|
13273
|
+
}
|
|
13274
|
+
catch {
|
|
13275
|
+
/* best-effort teardown for stale cached shell */
|
|
13276
|
+
}
|
|
13277
|
+
break cacheReuse;
|
|
13278
|
+
}
|
|
13279
|
+
return instance;
|
|
11999
13280
|
}
|
|
12000
|
-
return instance;
|
|
12001
13281
|
}
|
|
12002
|
-
if (!this.
|
|
13282
|
+
if (!this.findItemInstanceCacheEntryByProps(props)) {
|
|
12003
13283
|
// Item no longer needs modelInstance - it loads properties from database independently
|
|
12004
13284
|
// Exclude latestVersionUid from props as it has incompatible types (string vs VersionsType)
|
|
12005
13285
|
const { latestVersionUid, ...propsWithoutVersionUid } = props;
|
|
@@ -12088,14 +13368,11 @@ class Item {
|
|
|
12088
13368
|
return Reflect.getOwnPropertyDescriptor(target, prop);
|
|
12089
13369
|
},
|
|
12090
13370
|
});
|
|
12091
|
-
this.
|
|
12092
|
-
instance: proxiedInstance,
|
|
12093
|
-
refCount: 1,
|
|
12094
|
-
});
|
|
13371
|
+
this.registerItemInInstanceCache(proxiedInstance);
|
|
12095
13372
|
if (!waitForReady)
|
|
12096
13373
|
return proxiedInstance;
|
|
12097
13374
|
try {
|
|
12098
|
-
await
|
|
13375
|
+
await this.waitForItemInstanceReadyForRead(proxiedInstance, readyTimeout);
|
|
12099
13376
|
}
|
|
12100
13377
|
catch (err) {
|
|
12101
13378
|
try {
|
|
@@ -12271,14 +13548,11 @@ class Item {
|
|
|
12271
13548
|
return Reflect.getOwnPropertyDescriptor(target, prop);
|
|
12272
13549
|
},
|
|
12273
13550
|
});
|
|
12274
|
-
this.
|
|
12275
|
-
instance: proxiedInstance,
|
|
12276
|
-
refCount: 1,
|
|
12277
|
-
});
|
|
13551
|
+
this.registerItemInInstanceCache(proxiedInstance);
|
|
12278
13552
|
if (!waitForReady)
|
|
12279
13553
|
return proxiedInstance;
|
|
12280
13554
|
try {
|
|
12281
|
-
await
|
|
13555
|
+
await this.waitForItemInstanceReadyForRead(proxiedInstance, readyTimeout);
|
|
12282
13556
|
}
|
|
12283
13557
|
catch (err) {
|
|
12284
13558
|
try {
|
|
@@ -12301,14 +13575,10 @@ class Item {
|
|
|
12301
13575
|
if (!id) {
|
|
12302
13576
|
return null;
|
|
12303
13577
|
}
|
|
12304
|
-
|
|
12305
|
-
if (
|
|
12306
|
-
|
|
12307
|
-
|
|
12308
|
-
instance,
|
|
12309
|
-
refCount: refCount + 1,
|
|
12310
|
-
});
|
|
12311
|
-
return instance;
|
|
13578
|
+
const entry = this.findItemInstanceCacheEntryById(id);
|
|
13579
|
+
if (entry) {
|
|
13580
|
+
entry.refCount += 1;
|
|
13581
|
+
return entry.instance;
|
|
12312
13582
|
}
|
|
12313
13583
|
return null;
|
|
12314
13584
|
}
|
|
@@ -12354,8 +13624,8 @@ class Item {
|
|
|
12354
13624
|
if (!seedLocalId && !seedUid) {
|
|
12355
13625
|
return undefined;
|
|
12356
13626
|
}
|
|
12357
|
-
//
|
|
12358
|
-
const id =
|
|
13627
|
+
// Prefer local id so cache + findEntity align with Item.instanceCache (local-first, uid alias).
|
|
13628
|
+
const id = seedLocalId || seedUid;
|
|
12359
13629
|
if (!id) {
|
|
12360
13630
|
return undefined;
|
|
12361
13631
|
}
|
|
@@ -12386,10 +13656,129 @@ class Item {
|
|
|
12386
13656
|
}));
|
|
12387
13657
|
}
|
|
12388
13658
|
if (waitForReady && itemInstances.length > 0) {
|
|
12389
|
-
await Promise.all(itemInstances.map((item) =>
|
|
13659
|
+
await Promise.all(itemInstances.map((item) => this.waitForItemInstanceReadyForRead(item, readyTimeout)));
|
|
12390
13660
|
}
|
|
12391
13661
|
return orderBy(itemInstances, ['createdAt'], ['desc']);
|
|
12392
13662
|
}
|
|
13663
|
+
/**
|
|
13664
|
+
* After EAS sync writes metadata for the latest version, merge new property instances and
|
|
13665
|
+
* re-run DB hydration on cached Items. Item liveQuery watches seeds/versions, not metadata,
|
|
13666
|
+
* and useItems may not invalidate when the seed set is unchanged.
|
|
13667
|
+
*/
|
|
13668
|
+
static async rehydrateCachedItemsFromDbAfterEasSync() {
|
|
13669
|
+
const appDb = BaseDb.getAppDb();
|
|
13670
|
+
if (!appDb || Item.instanceCache.size === 0) {
|
|
13671
|
+
return;
|
|
13672
|
+
}
|
|
13673
|
+
const _mod_8 = await import('./index-Bp0ChnQr.js');
|
|
13674
|
+
const _ns_8 = _mod_8.s;
|
|
13675
|
+
const { metadata } = _ns_8;
|
|
13676
|
+
const { eq, and } = await import('drizzle-orm');
|
|
13677
|
+
const dedupedInstances = new Map();
|
|
13678
|
+
for (const entry of Item.instanceCache.values()) {
|
|
13679
|
+
dedupedInstances.set(entry.instance, entry);
|
|
13680
|
+
}
|
|
13681
|
+
const entries = [...dedupedInstances.values()];
|
|
13682
|
+
await Promise.all(entries.map(async ({ instance }) => {
|
|
13683
|
+
try {
|
|
13684
|
+
const svc = instance.getService();
|
|
13685
|
+
if (svc.getSnapshot().status !== 'active') {
|
|
13686
|
+
return;
|
|
13687
|
+
}
|
|
13688
|
+
const ctx = svc.getSnapshot().context;
|
|
13689
|
+
const seedLocalId = ctx.seedLocalId;
|
|
13690
|
+
const seedUid = ctx.seedUid;
|
|
13691
|
+
const versionLocalId = ctx.latestVersionLocalId;
|
|
13692
|
+
const itemModelName = ctx.modelName;
|
|
13693
|
+
const schemaNameForModel = ctx.schemaName;
|
|
13694
|
+
if (!seedLocalId || !versionLocalId || !itemModelName) {
|
|
13695
|
+
return;
|
|
13696
|
+
}
|
|
13697
|
+
const metadataRows = await appDb
|
|
13698
|
+
.select()
|
|
13699
|
+
.from(metadata)
|
|
13700
|
+
.where(and(eq(metadata.seedLocalId, seedLocalId), eq(metadata.versionLocalId, versionLocalId)));
|
|
13701
|
+
let propertySchemas = {};
|
|
13702
|
+
try {
|
|
13703
|
+
const M = getModel();
|
|
13704
|
+
const model = schemaNameForModel !== undefined
|
|
13705
|
+
? M?.getByName(itemModelName, schemaNameForModel)
|
|
13706
|
+
: M?.getByName(itemModelName);
|
|
13707
|
+
if (model?.properties?.length) {
|
|
13708
|
+
propertySchemas = modelPropertiesToObject(model.properties);
|
|
13709
|
+
}
|
|
13710
|
+
}
|
|
13711
|
+
catch {
|
|
13712
|
+
/* Model optional */
|
|
13713
|
+
}
|
|
13714
|
+
const sendToItemMachine = (event) => {
|
|
13715
|
+
if (svc.getSnapshot().status !== 'active') {
|
|
13716
|
+
return;
|
|
13717
|
+
}
|
|
13718
|
+
svc.send(event);
|
|
13719
|
+
};
|
|
13720
|
+
for (const metaRow of metadataRows) {
|
|
13721
|
+
try {
|
|
13722
|
+
let propertyName = metaRow.propertyName;
|
|
13723
|
+
const listSchemaKey = propertyName &&
|
|
13724
|
+
Object.keys(propertySchemas).length > 0 &&
|
|
13725
|
+
resolveStorageNameToSchemaName(propertySchemas, propertyName);
|
|
13726
|
+
if (listSchemaKey) {
|
|
13727
|
+
propertyName = listSchemaKey;
|
|
13728
|
+
}
|
|
13729
|
+
else {
|
|
13730
|
+
const baseName = propertyName?.endsWith('Id') ? propertyName.slice(0, -2) : undefined;
|
|
13731
|
+
const refSeedType = metaRow.refSeedType;
|
|
13732
|
+
const isRefTypeFromMeta = refSeedType === 'file' ||
|
|
13733
|
+
refSeedType === 'image' ||
|
|
13734
|
+
refSeedType === 'relation' ||
|
|
13735
|
+
refSeedType === 'html';
|
|
13736
|
+
if (baseName && (propertySchemas[baseName] || isRefTypeFromMeta)) {
|
|
13737
|
+
propertyName = baseName;
|
|
13738
|
+
}
|
|
13739
|
+
}
|
|
13740
|
+
if (!propertyName) {
|
|
13741
|
+
continue;
|
|
13742
|
+
}
|
|
13743
|
+
const property = await ItemProperty.find({
|
|
13744
|
+
propertyName,
|
|
13745
|
+
seedLocalId,
|
|
13746
|
+
seedUid,
|
|
13747
|
+
modelName: itemModelName,
|
|
13748
|
+
});
|
|
13749
|
+
if (property) {
|
|
13750
|
+
sendToItemMachine({
|
|
13751
|
+
type: 'addPropertyInstance',
|
|
13752
|
+
propertyName,
|
|
13753
|
+
propertyInstance: property,
|
|
13754
|
+
});
|
|
13755
|
+
}
|
|
13756
|
+
}
|
|
13757
|
+
catch {
|
|
13758
|
+
/* row skipped */
|
|
13759
|
+
}
|
|
13760
|
+
}
|
|
13761
|
+
const instances = svc.getSnapshot().context.propertyInstances;
|
|
13762
|
+
if (!instances) {
|
|
13763
|
+
return;
|
|
13764
|
+
}
|
|
13765
|
+
for (const propertyInstance of instances.values()) {
|
|
13766
|
+
try {
|
|
13767
|
+
const propertySnap = propertyInstance.getService().getSnapshot();
|
|
13768
|
+
if (isMachineSnapshot(propertySnap) && propertySnap.matches('idle')) {
|
|
13769
|
+
propertyInstance.getService().send({ type: 'rehydrateFromDb' });
|
|
13770
|
+
}
|
|
13771
|
+
}
|
|
13772
|
+
catch {
|
|
13773
|
+
/* best-effort */
|
|
13774
|
+
}
|
|
13775
|
+
}
|
|
13776
|
+
}
|
|
13777
|
+
catch (e) {
|
|
13778
|
+
itemLogger('rehydrateCachedItemsFromDbAfterEasSync item failed:', e);
|
|
13779
|
+
}
|
|
13780
|
+
}));
|
|
13781
|
+
}
|
|
12393
13782
|
_createPropertyInstance(props) {
|
|
12394
13783
|
if (this._storageTransactionId) {
|
|
12395
13784
|
props.storageTransactionId = this._storageTransactionId;
|
|
@@ -12732,9 +14121,9 @@ class Item {
|
|
|
12732
14121
|
itemActor.send(event);
|
|
12733
14122
|
};
|
|
12734
14123
|
try {
|
|
12735
|
-
const
|
|
12736
|
-
const
|
|
12737
|
-
const seedSchemaMod =
|
|
14124
|
+
const _mod_9 = await import('./index-Bp0ChnQr.js');
|
|
14125
|
+
const _ns_9 = _mod_9.s;
|
|
14126
|
+
const seedSchemaMod = _ns_9;
|
|
12738
14127
|
const { seeds, versions, metadata } = seedSchemaMod;
|
|
12739
14128
|
const drizzleMod = await import('drizzle-orm');
|
|
12740
14129
|
const { eq, and } = drizzleMod;
|
|
@@ -13006,15 +14395,10 @@ class Item {
|
|
|
13006
14395
|
}
|
|
13007
14396
|
unload() {
|
|
13008
14397
|
try {
|
|
13009
|
-
|
|
13010
|
-
const cacheKey = context.seedUid || context.seedLocalId;
|
|
13011
|
-
const cacheKeys = [];
|
|
13012
|
-
if (cacheKey) {
|
|
13013
|
-
cacheKeys.push(cacheKey);
|
|
13014
|
-
}
|
|
14398
|
+
Item.releaseItemInstanceCacheHold(this);
|
|
13015
14399
|
unloadEntity(this, {
|
|
13016
|
-
getCacheKeys: () =>
|
|
13017
|
-
caches: [
|
|
14400
|
+
getCacheKeys: () => [],
|
|
14401
|
+
caches: [],
|
|
13018
14402
|
instanceState: itemInstanceState,
|
|
13019
14403
|
getService: (instance) => instance._service,
|
|
13020
14404
|
onUnload: (instance) => {
|
|
@@ -13043,11 +14427,10 @@ class Item {
|
|
|
13043
14427
|
* Destroy the item: soft delete in DB, remove from caches, clean up subscriptions, stop service.
|
|
13044
14428
|
*/
|
|
13045
14429
|
async destroy() {
|
|
13046
|
-
const { assertItemOwned } = await import('./ownership-
|
|
14430
|
+
const { assertItemOwned } = await import('./ownership-D-KsIkxM.js');
|
|
13047
14431
|
await assertItemOwned(this);
|
|
13048
14432
|
const context = this._getSnapshotContext();
|
|
13049
|
-
const
|
|
13050
|
-
const cacheKeys = cacheKey ? [cacheKey] : [];
|
|
14433
|
+
const cacheKeys = Item.collectInstanceCacheKeysForInstance(this);
|
|
13051
14434
|
clearDestroySubscriptions(this, {
|
|
13052
14435
|
instanceState: itemInstanceState,
|
|
13053
14436
|
onUnload: (instance) => instance._subscription?.unsubscribe(),
|
|
@@ -13104,600 +14487,331 @@ function normalizeAddressConfig(addresses) {
|
|
|
13104
14487
|
};
|
|
13105
14488
|
}
|
|
13106
14489
|
|
|
13107
|
-
|
|
13108
|
-
|
|
13109
|
-
const
|
|
13110
|
-
|
|
13111
|
-
|
|
13112
|
-
|
|
13113
|
-
|
|
13114
|
-
|
|
13115
|
-
|
|
13116
|
-
|
|
13117
|
-
|
|
13118
|
-
|
|
13119
|
-
|
|
13120
|
-
|
|
13121
|
-
const
|
|
13122
|
-
|
|
13123
|
-
|
|
13124
|
-
|
|
13125
|
-
|
|
14490
|
+
let writeTail = Promise.resolve();
|
|
14491
|
+
function enqueueEasSyncDbWrite(fn) {
|
|
14492
|
+
const next = writeTail.then(fn);
|
|
14493
|
+
writeTail = next.catch(() => { });
|
|
14494
|
+
return next;
|
|
14495
|
+
}
|
|
14496
|
+
const MAX_ERROR_MESSAGE_LENGTH = 500;
|
|
14497
|
+
const MAX_ERROR_DETAILS_LENGTH = 2000;
|
|
14498
|
+
async function insertEasSyncProcessRow(params) {
|
|
14499
|
+
return enqueueEasSyncDbWrite(async () => {
|
|
14500
|
+
const db = BaseDb.getAppDb();
|
|
14501
|
+
if (!db) {
|
|
14502
|
+
throw new Error('[easSyncProcess] App DB not available');
|
|
14503
|
+
}
|
|
14504
|
+
const now = Date.now();
|
|
14505
|
+
const [row] = await db
|
|
14506
|
+
.insert(easSyncProcesses)
|
|
14507
|
+
.values({
|
|
14508
|
+
status: 'in_progress',
|
|
14509
|
+
startedAt: now,
|
|
14510
|
+
requestPayload: JSON.stringify(params.requestPayload),
|
|
14511
|
+
persistedSnapshot: JSON.stringify(params.persistedSnapshot),
|
|
14512
|
+
createdAt: now,
|
|
14513
|
+
updatedAt: now,
|
|
13126
14514
|
})
|
|
13127
|
-
.
|
|
13128
|
-
|
|
13129
|
-
|
|
13130
|
-
|
|
13131
|
-
|
|
13132
|
-
|
|
13133
|
-
|
|
13134
|
-
|
|
13135
|
-
|
|
13136
|
-
id: foundModelQuery[0].id,
|
|
13137
|
-
name: foundModelQuery[0].name,
|
|
13138
|
-
uid: foundModelQuery[0].uid,
|
|
13139
|
-
tableName: pluralize(foundModelQuery[0].name).toLowerCase(),
|
|
13140
|
-
};
|
|
13141
|
-
modelRecords.push(foundModel);
|
|
13142
|
-
if (modelName === 'Seed') {
|
|
13143
|
-
continue;
|
|
13144
|
-
}
|
|
13145
|
-
const schemaString = `bytes32 ${toSnakeCase(modelName)}`;
|
|
13146
|
-
schemaStringToModelRecord.set(schemaString, foundModel);
|
|
13147
|
-
}
|
|
13148
|
-
return {
|
|
13149
|
-
schemaStringToModelRecord,
|
|
13150
|
-
modelRecords,
|
|
13151
|
-
};
|
|
13152
|
-
};
|
|
13153
|
-
|
|
13154
|
-
const createSeeds = async (newSeeds) => {
|
|
13155
|
-
const appDb = BaseDb.getAppDb();
|
|
13156
|
-
const results = await appDb
|
|
13157
|
-
.insert(seeds)
|
|
13158
|
-
.values(newSeeds)
|
|
13159
|
-
.returning({ uid: seeds.uid });
|
|
13160
|
-
const newUids = results.reduce((acc, result) => {
|
|
13161
|
-
if (result.uid) {
|
|
13162
|
-
acc.push(result.uid);
|
|
14515
|
+
.returning({ id: easSyncProcesses.id });
|
|
14516
|
+
return row.id;
|
|
14517
|
+
});
|
|
14518
|
+
}
|
|
14519
|
+
async function finalizeEasSyncProcessRow(id, params) {
|
|
14520
|
+
return enqueueEasSyncDbWrite(async () => {
|
|
14521
|
+
const db = BaseDb.getAppDb();
|
|
14522
|
+
if (!db) {
|
|
14523
|
+
return;
|
|
13163
14524
|
}
|
|
13164
|
-
|
|
13165
|
-
|
|
13166
|
-
|
|
13167
|
-
|
|
14525
|
+
const now = Date.now();
|
|
14526
|
+
await db
|
|
14527
|
+
.update(easSyncProcesses)
|
|
14528
|
+
.set({
|
|
14529
|
+
status: params.status,
|
|
14530
|
+
completedAt: now,
|
|
14531
|
+
updatedAt: now,
|
|
14532
|
+
errorMessage: params.errorMessage?.slice(0, MAX_ERROR_MESSAGE_LENGTH) ?? null,
|
|
14533
|
+
errorDetails: params.errorDetails?.slice(0, MAX_ERROR_DETAILS_LENGTH) ?? null,
|
|
14534
|
+
persistedSnapshot: JSON.stringify(params.persistedSnapshot),
|
|
14535
|
+
})
|
|
14536
|
+
.where(eq(easSyncProcesses.id, id));
|
|
14537
|
+
});
|
|
14538
|
+
}
|
|
13168
14539
|
|
|
13169
14540
|
/**
|
|
13170
|
-
*
|
|
14541
|
+
* Merge multiple EAS sync intents: full sync (no concrete address list) wins;
|
|
14542
|
+
* otherwise union addresses (first-seen casing).
|
|
13171
14543
|
*/
|
|
13172
|
-
|
|
13173
|
-
|
|
13174
|
-
|
|
14544
|
+
function mergeEasSyncRequestIntents(parts) {
|
|
14545
|
+
const norm = parts.filter((p) => p != null);
|
|
14546
|
+
if (norm.length === 0) {
|
|
14547
|
+
return {};
|
|
13175
14548
|
}
|
|
13176
|
-
|
|
13177
|
-
|
|
13178
|
-
|
|
13179
|
-
.
|
|
13180
|
-
|
|
13181
|
-
|
|
13182
|
-
|
|
13183
|
-
|
|
13184
|
-
|
|
13185
|
-
|
|
13186
|
-
|
|
13187
|
-
'0x0000000000000000000000000000000000000000000000000000000000000020',
|
|
13188
|
-
];
|
|
13189
|
-
const seedUidToLocalId = new Map();
|
|
13190
|
-
const seedUidToModelType = new Map();
|
|
13191
|
-
const relatedSeedUids = new Set();
|
|
13192
|
-
const versionUidToLocalId = new Map();
|
|
13193
|
-
const versionUidToSeedUid = new Map();
|
|
13194
|
-
const propertyUidToLocalId = new Map();
|
|
13195
|
-
const saveEasSeedsToDb = async ({ itemSeeds }) => {
|
|
13196
|
-
const appDb = BaseDb.getAppDb();
|
|
13197
|
-
const seedUids = itemSeeds.map((seed) => seed.id);
|
|
13198
|
-
const existingSeedRecordsRows = await appDb
|
|
13199
|
-
.select()
|
|
13200
|
-
.from(seeds)
|
|
13201
|
-
.where(inArray(seeds.uid, seedUids));
|
|
13202
|
-
const existingSeedUids = new Set();
|
|
13203
|
-
if (existingSeedRecordsRows && existingSeedRecordsRows.length > 0) {
|
|
13204
|
-
for (const row of existingSeedRecordsRows) {
|
|
13205
|
-
if (row.uid) {
|
|
13206
|
-
existingSeedUids.add(row.uid);
|
|
13207
|
-
if (row.localId) {
|
|
13208
|
-
seedUidToLocalId.set(row.uid, row.localId);
|
|
13209
|
-
}
|
|
13210
|
-
if (row.type) {
|
|
13211
|
-
seedUidToModelType.set(row.uid, row.type);
|
|
13212
|
-
}
|
|
14549
|
+
let full = false;
|
|
14550
|
+
const addressMap = new Map();
|
|
14551
|
+
for (const p of norm) {
|
|
14552
|
+
if (!('addresses' in p) || p.addresses === undefined) {
|
|
14553
|
+
full = true;
|
|
14554
|
+
break;
|
|
14555
|
+
}
|
|
14556
|
+
for (const addr of p.addresses) {
|
|
14557
|
+
const k = addr.toLowerCase();
|
|
14558
|
+
if (!addressMap.has(k)) {
|
|
14559
|
+
addressMap.set(k, addr);
|
|
13213
14560
|
}
|
|
13214
14561
|
}
|
|
13215
14562
|
}
|
|
13216
|
-
|
|
13217
|
-
|
|
13218
|
-
const seedByUid = new Map(itemSeeds.map((s) => [s.id, s]));
|
|
13219
|
-
for (const row of existingSeedRecordsRows) {
|
|
13220
|
-
if (!row.uid || !row.localId)
|
|
13221
|
-
continue;
|
|
13222
|
-
const attestation = seedByUid.get(row.uid);
|
|
13223
|
-
if (!attestation?.revoked)
|
|
13224
|
-
continue;
|
|
13225
|
-
if (row.revokedAt != null)
|
|
13226
|
-
continue;
|
|
13227
|
-
const revokedAt = attestation.revocationTime > 0
|
|
13228
|
-
? attestation.revocationTime
|
|
13229
|
-
: Math.floor(Date.now() / 1000);
|
|
13230
|
-
await updateSeedRevokedAt({ seedLocalId: row.localId, revokedAt });
|
|
13231
|
-
}
|
|
13232
|
-
if (newSeeds.length === 0) {
|
|
13233
|
-
return { seedUidToLocalId, seedUids };
|
|
13234
|
-
}
|
|
13235
|
-
const newSeedsData = [];
|
|
13236
|
-
for (let i = 0; i < newSeeds.length; i++) {
|
|
13237
|
-
const seed = newSeeds[i];
|
|
13238
|
-
seedUidToModelType.set(seed.id, seed.schema.schemaNames[0].name);
|
|
13239
|
-
const seedLocalId = generateId();
|
|
13240
|
-
seedUidToLocalId.set(seed.id, seedLocalId);
|
|
13241
|
-
const attestationRaw = escapeSqliteString(JSON.stringify(seed));
|
|
13242
|
-
const revokedAt = seed.revoked && seed.revocationTime != null && seed.revocationTime > 0
|
|
13243
|
-
? seed.revocationTime
|
|
13244
|
-
: seed.revoked
|
|
13245
|
-
? Math.floor(Date.now() / 1000)
|
|
13246
|
-
: undefined;
|
|
13247
|
-
newSeedsData.push({
|
|
13248
|
-
localId: seedLocalId,
|
|
13249
|
-
uid: seed.id,
|
|
13250
|
-
schemaUid: seed.schemaId,
|
|
13251
|
-
type: seed.schema.schemaNames[0].name,
|
|
13252
|
-
publisher: seed.attester,
|
|
13253
|
-
createdAt: Date.now(),
|
|
13254
|
-
attestationCreatedAt: seed.timeCreated * 1000,
|
|
13255
|
-
attestationRaw,
|
|
13256
|
-
...(revokedAt !== undefined && { revokedAt }),
|
|
13257
|
-
});
|
|
13258
|
-
seedUidToLocalId.set(seed.id, seedLocalId);
|
|
14563
|
+
if (full) {
|
|
14564
|
+
return {};
|
|
13259
14565
|
}
|
|
13260
|
-
|
|
13261
|
-
|
|
13262
|
-
};
|
|
13263
|
-
const saveEasVersionsToDb = async ({ itemVersions }) => {
|
|
13264
|
-
const versionUids = itemVersions.map((version) => version.id);
|
|
13265
|
-
const appDb = BaseDb.getAppDb();
|
|
13266
|
-
const existingVersionRecordsRows = await appDb
|
|
13267
|
-
.select()
|
|
13268
|
-
.from(versions)
|
|
13269
|
-
.where(inArray(versions.uid, versionUids));
|
|
13270
|
-
const existingVersionUids = new Set();
|
|
13271
|
-
if (existingVersionRecordsRows && existingVersionRecordsRows.length > 0) {
|
|
13272
|
-
for (const row of existingVersionRecordsRows) {
|
|
13273
|
-
if (row.uid) {
|
|
13274
|
-
existingVersionUids.add(row.uid);
|
|
13275
|
-
if (row.localId) {
|
|
13276
|
-
versionUidToLocalId.set(row.uid, row.localId);
|
|
13277
|
-
}
|
|
13278
|
-
if (row.seedUid) {
|
|
13279
|
-
versionUidToSeedUid.set(row.uid, row.seedUid);
|
|
13280
|
-
}
|
|
13281
|
-
}
|
|
13282
|
-
}
|
|
13283
|
-
}
|
|
13284
|
-
const newVersions = itemVersions.filter((version) => !existingVersionUids.has(version.id));
|
|
13285
|
-
if (newVersions.length === 0) {
|
|
13286
|
-
return { versionUidToLocalId, versionUids };
|
|
13287
|
-
}
|
|
13288
|
-
let insertVersionsQuery = `INSERT INTO versions (local_id, uid, seed_uid, seed_local_id, seed_type, created_at,
|
|
13289
|
-
attestation_created_at,
|
|
13290
|
-
attestation_raw, publisher)
|
|
13291
|
-
VALUES `;
|
|
13292
|
-
for (let i = 0; i < newVersions.length; i++) {
|
|
13293
|
-
const version = newVersions[i];
|
|
13294
|
-
versionUidToSeedUid.set(version.id, version.refUID);
|
|
13295
|
-
const versionLocalId = generateId();
|
|
13296
|
-
versionUidToLocalId.set(version.id, versionLocalId);
|
|
13297
|
-
const seedUid = versionUidToSeedUid.get(version.id);
|
|
13298
|
-
const seedLocalId = seedUidToLocalId.get(seedUid);
|
|
13299
|
-
const seedType = seedUidToModelType.get(seedUid);
|
|
13300
|
-
const attestationRaw = escapeSqliteString(JSON.stringify(version));
|
|
13301
|
-
const publisher = escapeSqliteString(version.attester ?? '');
|
|
13302
|
-
const valuesString = `('${versionLocalId}', '${version.id}', '${seedUid}', '${seedLocalId}', '${seedType}', ${Date.now()}, ${version.timeCreated * 1000}, '${attestationRaw}', '${publisher}')`;
|
|
13303
|
-
if (i < newVersions.length - 1) {
|
|
13304
|
-
insertVersionsQuery += valuesString + ', ';
|
|
13305
|
-
}
|
|
13306
|
-
if (i === newVersions.length - 1) {
|
|
13307
|
-
insertVersionsQuery += valuesString + ';';
|
|
13308
|
-
}
|
|
13309
|
-
versionUidToLocalId.set(version.id, versionLocalId);
|
|
13310
|
-
}
|
|
13311
|
-
await appDb.run(sql.raw(insertVersionsQuery));
|
|
13312
|
-
return { versionUids };
|
|
13313
|
-
};
|
|
13314
|
-
const createMetadataRecordsForStorageTransactionId = async (storageTransactionIdProperty, modelSchema) => {
|
|
13315
|
-
// Early return if modelSchema is not provided
|
|
13316
|
-
if (!modelSchema) {
|
|
13317
|
-
console.warn('[item/events] [syncDbWithEas] modelSchema is undefined for storageTransactionIdProperty: ', storageTransactionIdProperty.id);
|
|
13318
|
-
return;
|
|
14566
|
+
if (addressMap.size === 0) {
|
|
14567
|
+
return { addresses: [] };
|
|
13319
14568
|
}
|
|
13320
|
-
|
|
13321
|
-
|
|
13322
|
-
|
|
13323
|
-
|
|
14569
|
+
return { addresses: [...addressMap.values()] };
|
|
14570
|
+
}
|
|
14571
|
+
|
|
14572
|
+
const log = debug('seedSdk:events:easSyncManager');
|
|
14573
|
+
function toRunSyncArg(options) {
|
|
14574
|
+
if (options &&
|
|
14575
|
+
'addresses' in options &&
|
|
14576
|
+
options.addresses !== undefined) {
|
|
14577
|
+
return options;
|
|
13324
14578
|
}
|
|
13325
|
-
|
|
14579
|
+
return undefined;
|
|
14580
|
+
}
|
|
14581
|
+
const runEasSync = fromPromise(async ({ input, }) => {
|
|
14582
|
+
const rowId = await insertEasSyncProcessRow({
|
|
14583
|
+
requestPayload: input.requestPayload,
|
|
14584
|
+
persistedSnapshot: input.runningSnapshot,
|
|
14585
|
+
});
|
|
14586
|
+
const { runSyncFromEas } = await import('./syncDbWithEas-m-_3Ds7d.js');
|
|
13326
14587
|
try {
|
|
13327
|
-
|
|
13328
|
-
|
|
13329
|
-
|
|
13330
|
-
|
|
13331
|
-
|
|
13332
|
-
|
|
13333
|
-
|
|
13334
|
-
console.warn('[item/events] [syncDbWithEas] invalid decodedDataJson structure for storageTransactionIdProperty: ', storageTransactionIdProperty.id);
|
|
13335
|
-
return;
|
|
13336
|
-
}
|
|
13337
|
-
const attestationData = parsedData[0].value;
|
|
13338
|
-
camelCase(attestationData.name);
|
|
13339
|
-
const propertyValue = attestationData.value;
|
|
13340
|
-
const itemStorageProperties = new Map();
|
|
13341
|
-
for (const [_propertyName, propertyDef] of Object.entries(modelSchema)) {
|
|
13342
|
-
if (propertyDef?.storageType && propertyDef.storageType === 'ItemStorage') {
|
|
13343
|
-
itemStorageProperties.set(_propertyName, propertyDef);
|
|
13344
|
-
}
|
|
13345
|
-
}
|
|
13346
|
-
if (itemStorageProperties.size === 0) {
|
|
13347
|
-
return;
|
|
13348
|
-
}
|
|
13349
|
-
const appDb = BaseDb.getAppDb();
|
|
13350
|
-
for (const [_propertyName, propertyDef] of itemStorageProperties.entries()) {
|
|
13351
|
-
const existingMetadataRecordRows = await appDb
|
|
13352
|
-
.select()
|
|
13353
|
-
.from(metadata$1)
|
|
13354
|
-
.where(and(eq(metadata$1.propertyName, _propertyName), eq(metadata$1.propertyValue, propertyValue), eq(metadata$1.versionUid, storageTransactionIdProperty.refUID)));
|
|
13355
|
-
if (existingMetadataRecordRows && existingMetadataRecordRows.length > 0) {
|
|
13356
|
-
continue;
|
|
13357
|
-
}
|
|
13358
|
-
const seedUid = versionUidToSeedUid.get(storageTransactionIdProperty.refUID);
|
|
13359
|
-
const seedLocalId = seedUidToLocalId.get(seedUid);
|
|
13360
|
-
const versionUid = storageTransactionIdProperty.refUID;
|
|
13361
|
-
const versionLocalId = versionUidToLocalId.get(versionUid);
|
|
13362
|
-
const modelType = seedUidToModelType.get(seedUid);
|
|
13363
|
-
const propertyId = modelType != null
|
|
13364
|
-
? await getPropertyIdForModelAndName(modelType, _propertyName)
|
|
13365
|
-
: null;
|
|
13366
|
-
const propertyLocalId = generateId();
|
|
13367
|
-
await appDb.insert(metadata$1).values({
|
|
13368
|
-
localId: propertyLocalId,
|
|
13369
|
-
propertyId: propertyId ?? undefined,
|
|
13370
|
-
propertyName: _propertyName,
|
|
13371
|
-
propertyValue,
|
|
13372
|
-
localStorageDir: propertyDef.localStorageDir,
|
|
13373
|
-
seedLocalId,
|
|
13374
|
-
seedUid,
|
|
13375
|
-
versionLocalId,
|
|
13376
|
-
versionUid,
|
|
13377
|
-
refValueType: 'file',
|
|
13378
|
-
refResolvedValue: `${propertyValue}${propertyDef.filenameSuffix}`,
|
|
13379
|
-
modelType: seedUidToModelType.get(seedUid),
|
|
13380
|
-
createdAt: Date.now(),
|
|
13381
|
-
updatedAt: Date.now(),
|
|
14588
|
+
await runSyncFromEas(toRunSyncArg(input.options));
|
|
14589
|
+
await finalizeEasSyncProcessRow(rowId, {
|
|
14590
|
+
status: 'completed',
|
|
14591
|
+
persistedSnapshot: {
|
|
14592
|
+
phase: 'completed',
|
|
14593
|
+
correlationIds: input.requestPayload.correlationIds,
|
|
14594
|
+
},
|
|
13382
14595
|
});
|
|
13383
14596
|
}
|
|
13384
|
-
|
|
13385
|
-
|
|
13386
|
-
const
|
|
13387
|
-
|
|
13388
|
-
|
|
13389
|
-
|
|
13390
|
-
|
|
13391
|
-
|
|
13392
|
-
|
|
13393
|
-
|
|
13394
|
-
|
|
13395
|
-
|
|
13396
|
-
|
|
13397
|
-
const appDb = BaseDb.getAppDb();
|
|
13398
|
-
const existingMetadataRecordsRows = await appDb
|
|
13399
|
-
.select()
|
|
13400
|
-
.from(metadata$1)
|
|
13401
|
-
.where(inArray(metadata$1.uid, propertyUids));
|
|
13402
|
-
const existingPropertyRecordsUids = new Set();
|
|
13403
|
-
if (existingMetadataRecordsRows && existingMetadataRecordsRows.length > 0) {
|
|
13404
|
-
for (const row of existingMetadataRecordsRows) {
|
|
13405
|
-
if (row.uid) {
|
|
13406
|
-
existingPropertyRecordsUids.add(row.uid);
|
|
13407
|
-
if (row.localId) {
|
|
13408
|
-
propertyUidToLocalId.set(row.uid, row.localId);
|
|
13409
|
-
}
|
|
13410
|
-
}
|
|
13411
|
-
}
|
|
13412
|
-
}
|
|
13413
|
-
const newProperties = itemProperties.filter((property) => !existingPropertyRecordsUids.has(property.id));
|
|
13414
|
-
if (newProperties.length === 0) {
|
|
13415
|
-
return { propertyUidToLocalId, propertyUids };
|
|
13416
|
-
}
|
|
13417
|
-
let insertPropertiesQuery = `INSERT INTO metadata (local_id, uid, schema_uid, property_id, property_name, property_value,
|
|
13418
|
-
eas_data_type, version_uid, version_local_id, seed_uid,
|
|
13419
|
-
seed_local_id, model_type, ref_value_type, ref_seed_type,
|
|
13420
|
-
ref_schema_uid,
|
|
13421
|
-
created_at, attestation_created_at, attestation_raw,
|
|
13422
|
-
local_storage_dir, ref_resolved_value, publisher)
|
|
13423
|
-
VALUES `;
|
|
13424
|
-
for (let i = 0; i < newProperties.length; i++) {
|
|
13425
|
-
const property = newProperties[i];
|
|
13426
|
-
const propertyLocalId = generateId();
|
|
13427
|
-
// Validate and parse decodedDataJson
|
|
13428
|
-
if (!property.decodedDataJson || property.decodedDataJson.trim() === '') {
|
|
13429
|
-
console.warn('[item/events] [syncDbWithEas] empty decodedDataJson for property: ', property.id);
|
|
13430
|
-
continue;
|
|
13431
|
-
}
|
|
13432
|
-
let parsedData;
|
|
13433
|
-
try {
|
|
13434
|
-
parsedData = JSON.parse(property.decodedDataJson);
|
|
13435
|
-
}
|
|
13436
|
-
catch (error) {
|
|
13437
|
-
console.warn('[item/events] [syncDbWithEas] failed to parse decodedDataJson for property: ', property.id, error);
|
|
13438
|
-
continue;
|
|
13439
|
-
}
|
|
13440
|
-
if (!Array.isArray(parsedData) || parsedData.length === 0 || !parsedData[0]?.value) {
|
|
13441
|
-
console.warn('[item/events] [syncDbWithEas] invalid decodedDataJson structure for property: ', property.id);
|
|
13442
|
-
continue;
|
|
13443
|
-
}
|
|
13444
|
-
const metadata = parsedData[0].value;
|
|
13445
|
-
let propertyNameSnake = metadata.name;
|
|
13446
|
-
if (!propertyNameSnake) {
|
|
13447
|
-
console.warn('[item/events] [syncDbWithEas] no propertyName found for property: ', property);
|
|
13448
|
-
continue;
|
|
13449
|
-
}
|
|
13450
|
-
let isRelation = false;
|
|
13451
|
-
let refValueType;
|
|
13452
|
-
let refSeedType;
|
|
13453
|
-
let refSchemaUid;
|
|
13454
|
-
let isList = false;
|
|
13455
|
-
const schemaUid = property.schemaId;
|
|
13456
|
-
setSchemaUidForSchemaDefinition({
|
|
13457
|
-
text: propertyNameSnake,
|
|
13458
|
-
schemaUid,
|
|
14597
|
+
catch (err) {
|
|
14598
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
14599
|
+
const details = err instanceof Error && err.stack
|
|
14600
|
+
? err.stack.slice(0, 2000)
|
|
14601
|
+
: undefined;
|
|
14602
|
+
await finalizeEasSyncProcessRow(rowId, {
|
|
14603
|
+
status: 'failed',
|
|
14604
|
+
errorMessage: message,
|
|
14605
|
+
errorDetails: details,
|
|
14606
|
+
persistedSnapshot: {
|
|
14607
|
+
phase: 'failed',
|
|
14608
|
+
correlationIds: input.requestPayload.correlationIds,
|
|
14609
|
+
},
|
|
13459
14610
|
});
|
|
13460
|
-
|
|
13461
|
-
|
|
13462
|
-
|
|
13463
|
-
|
|
13464
|
-
|
|
13465
|
-
|
|
13466
|
-
|
|
13467
|
-
|
|
13468
|
-
|
|
13469
|
-
|
|
13470
|
-
|
|
13471
|
-
|
|
13472
|
-
|
|
13473
|
-
metadata.value.forEach((value) => {
|
|
13474
|
-
relatedSeedUids.add(value);
|
|
13475
|
-
});
|
|
13476
|
-
}
|
|
13477
|
-
if (!isList) {
|
|
13478
|
-
if (relationValuesToExclude.includes(metadata.value)) {
|
|
13479
|
-
continue;
|
|
13480
|
-
}
|
|
13481
|
-
relatedSeedUids.add(metadata.value);
|
|
13482
|
-
}
|
|
13483
|
-
}
|
|
13484
|
-
let propertyValue = metadata.value;
|
|
13485
|
-
if (typeof propertyValue !== 'string') {
|
|
13486
|
-
propertyValue = JSON.stringify(propertyValue);
|
|
13487
|
-
}
|
|
13488
|
-
if (isRelation && !isList) {
|
|
13489
|
-
const relatedSeed = itemSeeds.find((seed) => seed.id === metadata.value);
|
|
13490
|
-
if (relatedSeed && relatedSeed.schema && relatedSeed.schema.schemaNames) {
|
|
13491
|
-
refSeedType = relatedSeed.schema.schemaNames[0].name;
|
|
13492
|
-
refSchemaUid = relatedSeed.schemaId;
|
|
13493
|
-
}
|
|
13494
|
-
}
|
|
13495
|
-
if (isRelation && isList) {
|
|
13496
|
-
const relatedSeeds = itemSeeds.filter((seed) => metadata.value.includes(seed.id));
|
|
13497
|
-
if (relatedSeeds && relatedSeeds.length > 0) {
|
|
13498
|
-
refSeedType = relatedSeeds[0].schema.schemaNames[0].name;
|
|
13499
|
-
refSchemaUid = relatedSeeds[0].schemaId;
|
|
13500
|
-
}
|
|
13501
|
-
}
|
|
13502
|
-
const propertyName = camelCase(propertyNameSnake);
|
|
13503
|
-
propertyValue = escapeSqliteString(propertyValue);
|
|
13504
|
-
const easDataType = metadata.type;
|
|
13505
|
-
const versionUid = property.refUID;
|
|
13506
|
-
const versionLocalId = versionUidToLocalId.get(versionUid);
|
|
13507
|
-
const attestationCreatedAt = property.timeCreated * 1000;
|
|
13508
|
-
const attestationRaw = escapeSqliteString(JSON.stringify(property));
|
|
13509
|
-
const seedUid = versionUidToSeedUid.get(versionUid);
|
|
13510
|
-
const seedLocalId = seedUidToLocalId.get(seedUid);
|
|
13511
|
-
const modelType = seedUidToModelType.get(seedUid);
|
|
13512
|
-
const modelName = startCase(modelType);
|
|
13513
|
-
const model = models[modelName];
|
|
13514
|
-
const modelSchema = model?.properties ? modelPropertiesToObject(model.properties) : undefined;
|
|
13515
|
-
if (propertyNameSnake === 'storage_transaction_id') {
|
|
13516
|
-
await createMetadataRecordsForStorageTransactionId(property, modelSchema);
|
|
13517
|
-
}
|
|
13518
|
-
const propertyId = modelType != null
|
|
13519
|
-
? await getPropertyIdForModelAndName(modelType, propertyName)
|
|
13520
|
-
: null;
|
|
13521
|
-
const propertyIdSql = propertyId != null ? String(propertyId) : 'NULL';
|
|
13522
|
-
const publisher = escapeSqliteString(property.attester ?? '');
|
|
13523
|
-
const valuesString = `('${propertyLocalId}', '${property.id}',
|
|
13524
|
-
'${property.schemaId}', ${propertyIdSql}, '${propertyName}',
|
|
13525
|
-
'${propertyValue}', '${easDataType}', '${versionUid}',
|
|
13526
|
-
'${versionLocalId}', '${seedUid}', '${seedLocalId}',
|
|
13527
|
-
'${modelType}', ${refValueType ? `'${refValueType}'` : 'NULL'},
|
|
13528
|
-
${refSeedType ? `'${refSeedType}'` : 'NULL'},
|
|
13529
|
-
${refSchemaUid ? `'${refSchemaUid}'` : 'NULL'},
|
|
13530
|
-
${Date.now()}, ${attestationCreatedAt}, '${attestationRaw}',
|
|
13531
|
-
${'NULL'},
|
|
13532
|
-
${'NULL'},
|
|
13533
|
-
'${publisher}')`;
|
|
13534
|
-
if (i < newProperties.length - 1) {
|
|
13535
|
-
insertPropertiesQuery += valuesString + ', ';
|
|
13536
|
-
}
|
|
13537
|
-
if (i === newProperties.length - 1) {
|
|
13538
|
-
insertPropertiesQuery += valuesString + ';';
|
|
13539
|
-
}
|
|
13540
|
-
propertyUidToLocalId.set(property.id, propertyLocalId);
|
|
13541
|
-
}
|
|
13542
|
-
if (insertPropertiesQuery.endsWith('VALUES ')) {
|
|
13543
|
-
return { propertyUids };
|
|
13544
|
-
}
|
|
13545
|
-
if (insertPropertiesQuery.endsWith(', ')) {
|
|
13546
|
-
insertPropertiesQuery = insertPropertiesQuery.slice(0, -2) + ';';
|
|
13547
|
-
}
|
|
13548
|
-
await appDb.run(sql.raw(insertPropertiesQuery));
|
|
13549
|
-
isSavingToDb = false;
|
|
13550
|
-
return { propertyUids };
|
|
14611
|
+
throw err;
|
|
14612
|
+
}
|
|
14613
|
+
});
|
|
14614
|
+
const initialContext = {
|
|
14615
|
+
runOptions: {},
|
|
14616
|
+
activeCorrelationIds: [],
|
|
14617
|
+
activePrimarySource: 'event_bus',
|
|
14618
|
+
pendingMergedOptions: undefined,
|
|
14619
|
+
pendingCorrelationIds: [],
|
|
14620
|
+
pendingPrimarySource: null,
|
|
14621
|
+
lastFinishedCorrelationIds: null,
|
|
14622
|
+
lastFinishedStatus: null,
|
|
14623
|
+
lastFinishedError: null,
|
|
13551
14624
|
};
|
|
13552
|
-
const
|
|
13553
|
-
|
|
13554
|
-
|
|
13555
|
-
|
|
13556
|
-
|
|
13557
|
-
|
|
13558
|
-
|
|
14625
|
+
const easSyncMachine = setup({
|
|
14626
|
+
types: {
|
|
14627
|
+
context: {},
|
|
14628
|
+
events: {},
|
|
14629
|
+
},
|
|
14630
|
+
actors: {
|
|
14631
|
+
runEasSync,
|
|
14632
|
+
},
|
|
14633
|
+
}).createMachine({
|
|
14634
|
+
id: MachineIds.EAS_SYNC_MANAGER,
|
|
14635
|
+
initial: 'idle',
|
|
14636
|
+
context: initialContext,
|
|
14637
|
+
states: {
|
|
14638
|
+
idle: {
|
|
14639
|
+
on: {
|
|
14640
|
+
REQUEST: {
|
|
14641
|
+
target: 'running',
|
|
14642
|
+
actions: assign({
|
|
14643
|
+
runOptions: ({ event }) => event.options === undefined
|
|
14644
|
+
? {}
|
|
14645
|
+
: mergeEasSyncRequestIntents([event.options]),
|
|
14646
|
+
activeCorrelationIds: ({ event }) => [event.correlationId],
|
|
14647
|
+
activePrimarySource: ({ event }) => event.source,
|
|
14648
|
+
}),
|
|
14649
|
+
},
|
|
14650
|
+
},
|
|
14651
|
+
},
|
|
14652
|
+
running: {
|
|
14653
|
+
on: {
|
|
14654
|
+
REQUEST: {
|
|
14655
|
+
actions: assign({
|
|
14656
|
+
pendingMergedOptions: ({ context, event }) => mergeEasSyncRequestIntents([
|
|
14657
|
+
context.runOptions,
|
|
14658
|
+
context.pendingMergedOptions,
|
|
14659
|
+
event.options === undefined ? {} : event.options,
|
|
14660
|
+
].filter((x) => x != null)),
|
|
14661
|
+
pendingCorrelationIds: ({ context, event }) => [
|
|
14662
|
+
...context.pendingCorrelationIds,
|
|
14663
|
+
event.correlationId,
|
|
14664
|
+
],
|
|
14665
|
+
pendingPrimarySource: ({ context, event }) => context.pendingPrimarySource ?? event.source,
|
|
14666
|
+
}),
|
|
14667
|
+
},
|
|
13559
14668
|
},
|
|
13560
|
-
|
|
13561
|
-
|
|
13562
|
-
|
|
13563
|
-
|
|
13564
|
-
|
|
13565
|
-
|
|
13566
|
-
|
|
14669
|
+
invoke: {
|
|
14670
|
+
src: 'runEasSync',
|
|
14671
|
+
input: ({ context }) => ({
|
|
14672
|
+
options: context.runOptions,
|
|
14673
|
+
requestPayload: {
|
|
14674
|
+
source: context.activePrimarySource,
|
|
14675
|
+
correlationIds: context.activeCorrelationIds,
|
|
14676
|
+
options: context.runOptions,
|
|
14677
|
+
},
|
|
14678
|
+
runningSnapshot: {
|
|
14679
|
+
phase: 'running',
|
|
14680
|
+
correlationIds: context.activeCorrelationIds,
|
|
14681
|
+
},
|
|
14682
|
+
}),
|
|
14683
|
+
onDone: {
|
|
14684
|
+
target: 'afterRun',
|
|
14685
|
+
actions: assign({
|
|
14686
|
+
lastFinishedCorrelationIds: ({ context }) => [
|
|
14687
|
+
...context.activeCorrelationIds,
|
|
14688
|
+
],
|
|
14689
|
+
lastFinishedStatus: () => 'success',
|
|
14690
|
+
lastFinishedError: () => null,
|
|
14691
|
+
activeCorrelationIds: () => [],
|
|
14692
|
+
runOptions: () => ({}),
|
|
14693
|
+
}),
|
|
14694
|
+
},
|
|
14695
|
+
onError: {
|
|
14696
|
+
target: 'afterRun',
|
|
14697
|
+
actions: [
|
|
14698
|
+
assign({
|
|
14699
|
+
lastFinishedCorrelationIds: ({ context }) => [
|
|
14700
|
+
...context.activeCorrelationIds,
|
|
14701
|
+
],
|
|
14702
|
+
lastFinishedStatus: () => 'failed',
|
|
14703
|
+
lastFinishedError: ({ event }) => {
|
|
14704
|
+
const e = event.error;
|
|
14705
|
+
if (e instanceof Error) {
|
|
14706
|
+
return e.message;
|
|
14707
|
+
}
|
|
14708
|
+
return e != null ? String(e) : 'EAS sync failed';
|
|
14709
|
+
},
|
|
14710
|
+
activeCorrelationIds: () => [],
|
|
14711
|
+
runOptions: () => ({}),
|
|
14712
|
+
}),
|
|
14713
|
+
({ event }) => {
|
|
14714
|
+
log('runEasSync error', event.error);
|
|
14715
|
+
},
|
|
14716
|
+
],
|
|
14717
|
+
},
|
|
13567
14718
|
},
|
|
13568
14719
|
},
|
|
13569
|
-
|
|
13570
|
-
|
|
13571
|
-
|
|
13572
|
-
|
|
13573
|
-
|
|
13574
|
-
|
|
13575
|
-
|
|
13576
|
-
|
|
14720
|
+
afterRun: {
|
|
14721
|
+
always: [
|
|
14722
|
+
{
|
|
14723
|
+
guard: ({ context }) => context.pendingCorrelationIds.length > 0,
|
|
14724
|
+
target: 'running',
|
|
14725
|
+
actions: assign({
|
|
14726
|
+
runOptions: ({ context }) => mergeEasSyncRequestIntents([context.pendingMergedOptions]),
|
|
14727
|
+
activeCorrelationIds: ({ context }) => [
|
|
14728
|
+
...context.pendingCorrelationIds,
|
|
14729
|
+
],
|
|
14730
|
+
activePrimarySource: ({ context }) => context.pendingPrimarySource ?? 'event_bus',
|
|
14731
|
+
pendingMergedOptions: () => undefined,
|
|
14732
|
+
pendingCorrelationIds: () => [],
|
|
14733
|
+
pendingPrimarySource: () => null,
|
|
14734
|
+
}),
|
|
14735
|
+
},
|
|
14736
|
+
{ target: 'idle' },
|
|
14737
|
+
],
|
|
13577
14738
|
},
|
|
13578
|
-
}
|
|
13579
|
-
|
|
13580
|
-
|
|
13581
|
-
|
|
13582
|
-
|
|
13583
|
-
|
|
13584
|
-
/**
|
|
13585
|
-
* Core sync logic: fetches item attestations from EAS for configured models and given addresses,
|
|
13586
|
-
* then saves seeds, versions, and properties to the local DB.
|
|
13587
|
-
* Uses owned + watched addresses from DB when addresses are not provided.
|
|
13588
|
-
*/
|
|
13589
|
-
const runSyncFromEas = async (options) => {
|
|
13590
|
-
let addresses = options?.addresses ?? (await getAllAddressesFromDb());
|
|
13591
|
-
const additionalGetter = getGetAdditionalSyncAddresses();
|
|
13592
|
-
if (additionalGetter) {
|
|
13593
|
-
const additional = await additionalGetter();
|
|
13594
|
-
if (additional?.length) {
|
|
13595
|
-
const seen = new Set(addresses.map((a) => a.toLowerCase()));
|
|
13596
|
-
for (const addr of additional) {
|
|
13597
|
-
if (addr && !seen.has(addr.toLowerCase())) {
|
|
13598
|
-
seen.add(addr.toLowerCase());
|
|
13599
|
-
addresses = [...addresses, addr];
|
|
13600
|
-
}
|
|
13601
|
-
}
|
|
13602
|
-
}
|
|
13603
|
-
}
|
|
13604
|
-
if (!addresses || addresses.length === 0) {
|
|
14739
|
+
},
|
|
14740
|
+
});
|
|
14741
|
+
const easSyncActor = createActor(easSyncMachine);
|
|
14742
|
+
let easSyncActorStarted = false;
|
|
14743
|
+
function startEasSyncActor() {
|
|
14744
|
+
if (easSyncActorStarted) {
|
|
13605
14745
|
return;
|
|
13606
14746
|
}
|
|
13607
|
-
|
|
13608
|
-
|
|
13609
|
-
|
|
13610
|
-
|
|
13611
|
-
|
|
13612
|
-
|
|
13613
|
-
|
|
13614
|
-
// Skip schemas that don't have a corresponding model in the user's config
|
|
13615
|
-
// This can happen with "bytes32 image" if there's no Image model defined
|
|
13616
|
-
console.warn(`[item/events] [syncDbWithEas] Model not found for schema ${modelSchema.schema}, skipping`);
|
|
13617
|
-
continue;
|
|
13618
|
-
}
|
|
13619
|
-
try {
|
|
13620
|
-
await appDb
|
|
13621
|
-
.insert(modelUids)
|
|
13622
|
-
.values({
|
|
13623
|
-
modelId: foundModel.id,
|
|
13624
|
-
uid: modelSchema.id,
|
|
13625
|
-
})
|
|
13626
|
-
.onConflictDoNothing();
|
|
13627
|
-
}
|
|
13628
|
-
catch (err) {
|
|
13629
|
-
// Model may have been deleted by test teardown or another process; skip to avoid unhandled rejection
|
|
13630
|
-
const e = err;
|
|
13631
|
-
const code = e?.code ?? e?.rawCode ?? e?.cause?.code ?? e?.cause?.rawCode;
|
|
13632
|
-
if (code === 'SQLITE_CONSTRAINT_FOREIGNKEY' || code === 787) {
|
|
13633
|
-
continue;
|
|
13634
|
-
}
|
|
13635
|
-
throw err;
|
|
13636
|
-
}
|
|
13637
|
-
schemaUids.push(modelSchema.id);
|
|
13638
|
-
}
|
|
13639
|
-
// If no schemas were found, skip the rest of the sync process
|
|
13640
|
-
// This can happen when models exist but don't have schemas registered in EAS yet
|
|
13641
|
-
if (schemaUids.length === 0) {
|
|
13642
|
-
return;
|
|
14747
|
+
easSyncActorStarted = true;
|
|
14748
|
+
easSyncActor.start();
|
|
14749
|
+
}
|
|
14750
|
+
function newCorrelationId() {
|
|
14751
|
+
const c = globalThis.crypto;
|
|
14752
|
+
if (c?.randomUUID) {
|
|
14753
|
+
return c.randomUUID();
|
|
13643
14754
|
}
|
|
13644
|
-
|
|
13645
|
-
|
|
13646
|
-
|
|
13647
|
-
|
|
13648
|
-
|
|
13649
|
-
|
|
13650
|
-
|
|
13651
|
-
|
|
13652
|
-
const itemVersions = await getItemVersionsFromEas({
|
|
13653
|
-
seedUids,
|
|
13654
|
-
excludeRevoked: false,
|
|
14755
|
+
return `${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
14756
|
+
}
|
|
14757
|
+
function requestEasSyncFromEventBus() {
|
|
14758
|
+
startEasSyncActor();
|
|
14759
|
+
easSyncActor.send({
|
|
14760
|
+
type: 'REQUEST',
|
|
14761
|
+
correlationId: newCorrelationId(),
|
|
14762
|
+
source: 'event_bus',
|
|
13655
14763
|
});
|
|
13656
|
-
|
|
13657
|
-
|
|
14764
|
+
}
|
|
14765
|
+
function requestEasSyncFromAddressChange(addresses) {
|
|
14766
|
+
startEasSyncActor();
|
|
14767
|
+
easSyncActor.send({
|
|
14768
|
+
type: 'REQUEST',
|
|
14769
|
+
correlationId: newCorrelationId(),
|
|
14770
|
+
options: { addresses },
|
|
14771
|
+
source: 'address_change',
|
|
13658
14772
|
});
|
|
13659
|
-
|
|
13660
|
-
|
|
13661
|
-
|
|
14773
|
+
}
|
|
14774
|
+
function requestEasSyncFromModelsInit() {
|
|
14775
|
+
startEasSyncActor();
|
|
14776
|
+
easSyncActor.send({
|
|
14777
|
+
type: 'REQUEST',
|
|
14778
|
+
correlationId: newCorrelationId(),
|
|
14779
|
+
source: 'models_init',
|
|
13662
14780
|
});
|
|
13663
|
-
|
|
13664
|
-
|
|
13665
|
-
|
|
13666
|
-
|
|
14781
|
+
}
|
|
14782
|
+
function sendEasSyncClientRequest(correlationId, options) {
|
|
14783
|
+
startEasSyncActor();
|
|
14784
|
+
easSyncActor.send({
|
|
14785
|
+
type: 'REQUEST',
|
|
14786
|
+
correlationId,
|
|
14787
|
+
options,
|
|
14788
|
+
source: 'client_api',
|
|
13667
14789
|
});
|
|
13668
|
-
|
|
13669
|
-
};
|
|
13670
|
-
const syncDbWithEasHandler = throttle(async (_) => {
|
|
13671
|
-
await runSyncFromEas();
|
|
13672
|
-
}, 30000, {
|
|
13673
|
-
leading: true,
|
|
13674
|
-
trailing: false,
|
|
13675
|
-
});
|
|
14790
|
+
}
|
|
13676
14791
|
|
|
13677
|
-
|
|
13678
|
-
|
|
13679
|
-
|
|
13680
|
-
|
|
13681
|
-
|
|
13682
|
-
|
|
13683
|
-
|
|
13684
|
-
|
|
13685
|
-
|
|
13686
|
-
|
|
13687
|
-
};
|
|
14792
|
+
var easSyncManager = /*#__PURE__*/Object.freeze({
|
|
14793
|
+
__proto__: null,
|
|
14794
|
+
easSyncActor: easSyncActor,
|
|
14795
|
+
easSyncMachine: easSyncMachine,
|
|
14796
|
+
requestEasSyncFromAddressChange: requestEasSyncFromAddressChange,
|
|
14797
|
+
requestEasSyncFromEventBus: requestEasSyncFromEventBus,
|
|
14798
|
+
requestEasSyncFromModelsInit: requestEasSyncFromModelsInit,
|
|
14799
|
+
sendEasSyncClientRequest: sendEasSyncClientRequest,
|
|
14800
|
+
startEasSyncActor: startEasSyncActor
|
|
14801
|
+
});
|
|
13688
14802
|
|
|
13689
14803
|
/**
|
|
13690
14804
|
* @deprecated Use BaseArweaveClient.setHost() instead.
|
|
13691
14805
|
* This function is kept for backward compatibility but will be removed in a future version.
|
|
13692
14806
|
*/
|
|
13693
14807
|
const setArweaveDomain = (newDomain) => {
|
|
13694
|
-
BaseArweaveClient.
|
|
14808
|
+
BaseArweaveClient.setPreferredReadGateway(newDomain);
|
|
13695
14809
|
};
|
|
13696
14810
|
|
|
13697
|
-
const logger$
|
|
14811
|
+
const logger$b = debug('seedSdk:services:events');
|
|
13698
14812
|
const handleServiceSaveState = (event) => {
|
|
13699
14813
|
const { state, serviceId } = event;
|
|
13700
|
-
logger$
|
|
14814
|
+
logger$b(`[browser] [service.saveState.request] serviceId: ${serviceId}`);
|
|
13701
14815
|
// TODO: This is called from Node as well. Do we need it? If so, need to generalize this to all platforms.
|
|
13702
14816
|
// localStorage.setItem(`seed_sdk_service_${serviceId}`, JSON.stringify(state))
|
|
13703
14817
|
};
|
|
@@ -13706,7 +14820,8 @@ const setupServicesEventHandlers = () => {
|
|
|
13706
14820
|
};
|
|
13707
14821
|
|
|
13708
14822
|
const setupAllItemsEventHandlers = () => {
|
|
13709
|
-
|
|
14823
|
+
startEasSyncActor();
|
|
14824
|
+
eventEmitter.addListener('syncDbWithEas', requestEasSyncFromEventBus);
|
|
13710
14825
|
};
|
|
13711
14826
|
// Note: getAreItemEventHandlersReady removed - was only used by useItemIsReady hook which has been removed
|
|
13712
14827
|
|
|
@@ -13740,9 +14855,9 @@ class BasePathResolver {
|
|
|
13740
14855
|
}
|
|
13741
14856
|
}
|
|
13742
14857
|
|
|
13743
|
-
const logger$
|
|
14858
|
+
const logger$a = debug('seedSdk:ClientManager:initialize');
|
|
13744
14859
|
const platformClassesInit = fromCallback(({ sendBack, input: { context, event } }) => {
|
|
13745
|
-
logger$
|
|
14860
|
+
logger$a('initialize from ClientManager');
|
|
13746
14861
|
const { isInitialized } = context;
|
|
13747
14862
|
if (!event || !('options' in event)) {
|
|
13748
14863
|
throw new Error('Initialize event must include options');
|
|
@@ -13778,20 +14893,20 @@ const platformClassesInit = fromCallback(({ sendBack, input: { context, event }
|
|
|
13778
14893
|
let PathResolver;
|
|
13779
14894
|
let EasClient;
|
|
13780
14895
|
if (isBrowser()) {
|
|
13781
|
-
FileManager = (await import('./FileManager-
|
|
13782
|
-
Db = (await import('./Db-
|
|
13783
|
-
QueryClient = (await import('./QueryClient-
|
|
13784
|
-
ArweaveClient = (await import('./ArweaveClient-
|
|
13785
|
-
PathResolver = (await import('./PathResolver-
|
|
13786
|
-
EasClient = (await import('./EasClient-
|
|
14896
|
+
FileManager = (await import('./FileManager-BOxbzROS.js')).FileManager;
|
|
14897
|
+
Db = (await import('./Db-DA_e7Jcc.js')).Db;
|
|
14898
|
+
QueryClient = (await import('./QueryClient-B12y2daD.js')).QueryClient;
|
|
14899
|
+
ArweaveClient = (await import('./ArweaveClient-KF_T3NSr.js')).ArweaveClient;
|
|
14900
|
+
PathResolver = (await import('./PathResolver-DHTAlCzo.js')).PathResolver;
|
|
14901
|
+
EasClient = (await import('./EasClient-CVPHYGNP.js')).EasClient;
|
|
13787
14902
|
}
|
|
13788
14903
|
else if (isNode()) {
|
|
13789
|
-
FileManager = (await import('./FileManager-
|
|
13790
|
-
Db = (await import('./Db-
|
|
13791
|
-
QueryClient = (await import('./QueryClient-
|
|
13792
|
-
ArweaveClient = (await import('./ArweaveClient-
|
|
13793
|
-
PathResolver = (await import('./PathResolver-
|
|
13794
|
-
EasClient = (await import('./EasClient-
|
|
14904
|
+
FileManager = (await import('./FileManager-Ba5BCbCL.js')).FileManager;
|
|
14905
|
+
Db = (await import('./Db-Cg7Q5gIc.js')).Db;
|
|
14906
|
+
QueryClient = (await import('./QueryClient-BCxuWg7f.js')).QueryClient;
|
|
14907
|
+
ArweaveClient = (await import('./ArweaveClient-DoBABTLW.js')).ArweaveClient;
|
|
14908
|
+
PathResolver = (await import('./PathResolver-D7WqjJCo.js')).PathResolver;
|
|
14909
|
+
EasClient = (await import('./EasClient-B4VivHxM.js')).EasClient;
|
|
13795
14910
|
}
|
|
13796
14911
|
else {
|
|
13797
14912
|
throw new Error(`Unable to determine environment. isBrowser()=${isBrowser()}, isNode()=${isNode()}. Platform-specific implementations could not be loaded.`);
|
|
@@ -13865,11 +14980,14 @@ const platformClassesInit = fromCallback(({ sendBack, input: { context, event }
|
|
|
13865
14980
|
dbConfig,
|
|
13866
14981
|
schemaFile,
|
|
13867
14982
|
schema,
|
|
13868
|
-
syncFromEasOnAddressChange: options.syncFromEasOnAddressChange ??
|
|
14983
|
+
syncFromEasOnAddressChange: options.syncFromEasOnAddressChange ?? true,
|
|
13869
14984
|
} });
|
|
13870
14985
|
if (arweaveDomain) {
|
|
13871
14986
|
setArweaveDomain(arweaveDomain);
|
|
13872
14987
|
}
|
|
14988
|
+
void ensureReadGatewaySelected().catch(() => {
|
|
14989
|
+
/* non-blocking warm-up for read gateway probe */
|
|
14990
|
+
});
|
|
13873
14991
|
// Models are now Model instances, no registration needed
|
|
13874
14992
|
// They should be created via Model.create() and are accessible via Model static methods
|
|
13875
14993
|
setupAllItemsEventHandlers();
|
|
@@ -13905,15 +15023,15 @@ const platformClassesInit = fromCallback(({ sendBack, input: { context, event }
|
|
|
13905
15023
|
};
|
|
13906
15024
|
});
|
|
13907
15025
|
|
|
13908
|
-
const logger$
|
|
13909
|
-
const saveAppState
|
|
15026
|
+
const logger$9 = debug('seedSdk:client:writeToDb');
|
|
15027
|
+
const saveAppState = fromCallback(({ sendBack, input: { key, value } }) => {
|
|
13910
15028
|
const _saveAppState = async () => {
|
|
13911
15029
|
try {
|
|
13912
15030
|
const appDb = BaseDb.getAppDb();
|
|
13913
15031
|
if (!appDb) {
|
|
13914
15032
|
// In test environments, continue anyway
|
|
13915
15033
|
if (process.env.NODE_ENV === 'test' || process.env.IS_SEED_DEV) {
|
|
13916
|
-
logger$
|
|
15034
|
+
logger$9('[client/actors] [saveAppState] App DB not found, but continuing in test environment');
|
|
13917
15035
|
return;
|
|
13918
15036
|
}
|
|
13919
15037
|
throw new Error('App DB not found');
|
|
@@ -13929,13 +15047,13 @@ const saveAppState$1 = fromCallback(({ sendBack, input: { key, value } }) => {
|
|
|
13929
15047
|
value: JSON.stringify(value),
|
|
13930
15048
|
},
|
|
13931
15049
|
});
|
|
13932
|
-
logger$
|
|
15050
|
+
logger$9('result', result);
|
|
13933
15051
|
}
|
|
13934
15052
|
catch (error) {
|
|
13935
|
-
logger$
|
|
15053
|
+
logger$9('[client/actors] [saveAppState] Error saving app state:', error);
|
|
13936
15054
|
// In test environments, continue anyway
|
|
13937
15055
|
if (process.env.NODE_ENV === 'test' || process.env.IS_SEED_DEV) {
|
|
13938
|
-
logger$
|
|
15056
|
+
logger$9('[client/actors] [saveAppState] Continuing despite error in test environment');
|
|
13939
15057
|
return;
|
|
13940
15058
|
}
|
|
13941
15059
|
throw error;
|
|
@@ -13950,10 +15068,10 @@ const saveAppState$1 = fromCallback(({ sendBack, input: { key, value } }) => {
|
|
|
13950
15068
|
});
|
|
13951
15069
|
})
|
|
13952
15070
|
.catch((error) => {
|
|
13953
|
-
logger$
|
|
15071
|
+
logger$9('[client/actors] [saveAppState] Error in promise chain:', error);
|
|
13954
15072
|
// In test environments, still send success to allow state machine to progress
|
|
13955
15073
|
if (process.env.NODE_ENV === 'test' || process.env.IS_SEED_DEV) {
|
|
13956
|
-
logger$
|
|
15074
|
+
logger$9('[client/actors] [saveAppState] Sending success despite error in test environment');
|
|
13957
15075
|
sendBack({
|
|
13958
15076
|
type: 'saveAppStateSuccess',
|
|
13959
15077
|
key,
|
|
@@ -13966,222 +15084,6 @@ const saveAppState$1 = fromCallback(({ sendBack, input: { key, value } }) => {
|
|
|
13966
15084
|
});
|
|
13967
15085
|
});
|
|
13968
15086
|
|
|
13969
|
-
const GET_FILES_METADATA = graphql(/* GraphQL */ `
|
|
13970
|
-
query GetFilesMetadata($where: AttestationWhereInput!) {
|
|
13971
|
-
filesMetadata: attestations(
|
|
13972
|
-
where: $where
|
|
13973
|
-
orderBy: [{ timeCreated: desc }]
|
|
13974
|
-
) {
|
|
13975
|
-
...attestationFields
|
|
13976
|
-
}
|
|
13977
|
-
}
|
|
13978
|
-
`);
|
|
13979
|
-
|
|
13980
|
-
const getMetadata = async (props) => {
|
|
13981
|
-
const appDb = BaseDb.getAppDb();
|
|
13982
|
-
let storageTransactionId;
|
|
13983
|
-
if (props) {
|
|
13984
|
-
storageTransactionId = props.storageTransactionId;
|
|
13985
|
-
}
|
|
13986
|
-
const whereClauses = [];
|
|
13987
|
-
if (storageTransactionId) {
|
|
13988
|
-
whereClauses.push(eq(metadata$1.propertyName, 'storageTransactionId'));
|
|
13989
|
-
whereClauses.push(eq(metadata$1.propertyValue, storageTransactionId));
|
|
13990
|
-
}
|
|
13991
|
-
const metadataRows = await appDb
|
|
13992
|
-
.select()
|
|
13993
|
-
.from(metadata$1)
|
|
13994
|
-
.where(and(...whereClauses));
|
|
13995
|
-
if (!metadataRows || metadataRows.length === 0) {
|
|
13996
|
-
return;
|
|
13997
|
-
}
|
|
13998
|
-
return metadataRows[0];
|
|
13999
|
-
};
|
|
14000
|
-
|
|
14001
|
-
const saveMetadata = async (metadataRecord, metadataValues) => {
|
|
14002
|
-
if (!metadataRecord.localId) {
|
|
14003
|
-
return;
|
|
14004
|
-
}
|
|
14005
|
-
const appDb = BaseDb.getAppDb();
|
|
14006
|
-
await appDb
|
|
14007
|
-
.update(metadata$1)
|
|
14008
|
-
.set({
|
|
14009
|
-
...metadataValues,
|
|
14010
|
-
updatedAt: Date.now(),
|
|
14011
|
-
})
|
|
14012
|
-
.where(eq(metadata$1.localId, metadataRecord.localId));
|
|
14013
|
-
};
|
|
14014
|
-
|
|
14015
|
-
const saveAppState = async (key, value) => {
|
|
14016
|
-
const appDb = BaseDb.getAppDb();
|
|
14017
|
-
await appDb
|
|
14018
|
-
.insert(appState)
|
|
14019
|
-
.values({
|
|
14020
|
-
key,
|
|
14021
|
-
value,
|
|
14022
|
-
})
|
|
14023
|
-
.onConflictDoUpdate({
|
|
14024
|
-
target: appState.key,
|
|
14025
|
-
set: {
|
|
14026
|
-
value,
|
|
14027
|
-
},
|
|
14028
|
-
});
|
|
14029
|
-
};
|
|
14030
|
-
|
|
14031
|
-
const logger$9 = debug('seedSdk:files:download');
|
|
14032
|
-
// syncDbFiles helper - internal service removed, functionality moved here
|
|
14033
|
-
const syncDbFiles = async (endpoints) => {
|
|
14034
|
-
// TODO: Implement syncDbFiles functionality if needed
|
|
14035
|
-
// This was previously in @/services/internal/helpers
|
|
14036
|
-
logger$9('[download] syncDbFiles called but not yet implemented');
|
|
14037
|
-
return Promise.resolve();
|
|
14038
|
-
};
|
|
14039
|
-
const downloadAllFilesRequestHandler = async ({ endpoints, eventId, }) => {
|
|
14040
|
-
if (!isBrowser()) {
|
|
14041
|
-
return;
|
|
14042
|
-
}
|
|
14043
|
-
await syncDbFiles();
|
|
14044
|
-
eventEmitter.emit('fs.downloadAll.success', { eventId });
|
|
14045
|
-
eventEmitter.emit('fs.downloadAllBinary.request', { endpoints });
|
|
14046
|
-
};
|
|
14047
|
-
const downloadAllFilesBinaryRequestHandler = async () => {
|
|
14048
|
-
let addresses;
|
|
14049
|
-
if (BaseDb.isAppDbReady()) {
|
|
14050
|
-
addresses = await getAllAddressesFromDb();
|
|
14051
|
-
}
|
|
14052
|
-
if (!BaseDb.isAppDbReady()) {
|
|
14053
|
-
// Wait for ClientManager to be ready (DB_INIT state or later)
|
|
14054
|
-
const clientManagerMod = await Promise.resolve().then(function () { return ClientManager$1; });
|
|
14055
|
-
const { getClient } = clientManagerMod;
|
|
14056
|
-
const clientManager = getClient();
|
|
14057
|
-
const clientService = clientManager.getService();
|
|
14058
|
-
await waitFor(clientService, (snapshot) => {
|
|
14059
|
-
const state = snapshot.value;
|
|
14060
|
-
return state === 'dbInit' ||
|
|
14061
|
-
state === 'saveConfig' ||
|
|
14062
|
-
state === 'processSchemaFiles' ||
|
|
14063
|
-
state === 'addModelsToStore' ||
|
|
14064
|
-
state === 'addModelsToDb' ||
|
|
14065
|
-
state === 'idle';
|
|
14066
|
-
}, { timeout: 30000 });
|
|
14067
|
-
addresses = await getAllAddressesFromDb();
|
|
14068
|
-
}
|
|
14069
|
-
if (!addresses || addresses.length === 0) {
|
|
14070
|
-
return;
|
|
14071
|
-
}
|
|
14072
|
-
const queryClient = BaseQueryClient.getQueryClient();
|
|
14073
|
-
const easClient = BaseEasClient.getEasClient();
|
|
14074
|
-
const { filesMetadata } = await queryClient.fetchQuery({
|
|
14075
|
-
queryKey: ['getFilesMetadata', ...addresses],
|
|
14076
|
-
queryFn: async () => easClient.request(GET_FILES_METADATA, {
|
|
14077
|
-
where: {
|
|
14078
|
-
attester: {
|
|
14079
|
-
in: addresses,
|
|
14080
|
-
},
|
|
14081
|
-
schema: {
|
|
14082
|
-
is: {
|
|
14083
|
-
id: {
|
|
14084
|
-
equals: '0x55fdefb36fcbbaebeb7d6b41dc3a1a9666e4e42154267c889de064faa7ede517',
|
|
14085
|
-
},
|
|
14086
|
-
},
|
|
14087
|
-
},
|
|
14088
|
-
},
|
|
14089
|
-
}),
|
|
14090
|
-
});
|
|
14091
|
-
const filesRoot = BaseFileManager.getWorkingDir();
|
|
14092
|
-
await BaseFileManager.createDirIfNotExists(filesRoot);
|
|
14093
|
-
await BaseFileManager.createDirIfNotExists(BaseFileManager.getFilesPath('html'));
|
|
14094
|
-
await BaseFileManager.createDirIfNotExists(BaseFileManager.getFilesPath('json'));
|
|
14095
|
-
await BaseFileManager.createDirIfNotExists(BaseFileManager.getFilesPath('images'));
|
|
14096
|
-
const appDb = BaseDb.getAppDb();
|
|
14097
|
-
if (!appDb) {
|
|
14098
|
-
console.warn('[fetchAll/actors] [fetchAllBinaryData] seedDb not available');
|
|
14099
|
-
return [];
|
|
14100
|
-
}
|
|
14101
|
-
const excludedTransactionsQuery = await appDb
|
|
14102
|
-
.select()
|
|
14103
|
-
.from(appState)
|
|
14104
|
-
.where(eq(appState.key, 'excludedTransactions'));
|
|
14105
|
-
let excludedTransactions = new Set();
|
|
14106
|
-
if (excludedTransactionsQuery && excludedTransactionsQuery.length === 1) {
|
|
14107
|
-
const valueString = excludedTransactionsQuery[0].value;
|
|
14108
|
-
if (valueString) {
|
|
14109
|
-
const excludedTransactionsArray = JSON.parse(valueString);
|
|
14110
|
-
excludedTransactions = new Set(excludedTransactionsArray);
|
|
14111
|
-
}
|
|
14112
|
-
}
|
|
14113
|
-
const transactionIds = [];
|
|
14114
|
-
for (const fileMetadata of filesMetadata) {
|
|
14115
|
-
// Validate and parse decodedDataJson
|
|
14116
|
-
if (!fileMetadata.decodedDataJson || fileMetadata.decodedDataJson.trim() === '') {
|
|
14117
|
-
console.warn('[events/files] [download] empty decodedDataJson for fileMetadata: ', fileMetadata.id);
|
|
14118
|
-
continue;
|
|
14119
|
-
}
|
|
14120
|
-
let json;
|
|
14121
|
-
try {
|
|
14122
|
-
json = JSON.parse(fileMetadata.decodedDataJson);
|
|
14123
|
-
}
|
|
14124
|
-
catch (error) {
|
|
14125
|
-
console.warn('[events/files] [download] failed to parse decodedDataJson for fileMetadata: ', fileMetadata.id, error);
|
|
14126
|
-
continue;
|
|
14127
|
-
}
|
|
14128
|
-
if (!Array.isArray(json) || json.length === 0 || !json[0]?.value?.value) {
|
|
14129
|
-
console.warn('[events/files] [download] invalid decodedDataJson structure for fileMetadata: ', fileMetadata.id);
|
|
14130
|
-
continue;
|
|
14131
|
-
}
|
|
14132
|
-
const transactionId = json[0].value.value;
|
|
14133
|
-
if (excludedTransactions.has(transactionId)) {
|
|
14134
|
-
continue;
|
|
14135
|
-
}
|
|
14136
|
-
transactionIds.push(transactionId);
|
|
14137
|
-
}
|
|
14138
|
-
const transactionIdsToDownload = [];
|
|
14139
|
-
for (const transactionId of transactionIds) {
|
|
14140
|
-
try {
|
|
14141
|
-
// Use BaseArweaveClient for transaction status check
|
|
14142
|
-
const status = await BaseArweaveClient.getTransactionStatus(transactionId);
|
|
14143
|
-
if (status.status !== 200) {
|
|
14144
|
-
logger$9(`[fetchAll/actors] [fetchAllBinaryData] error fetching transaction data for ${transactionId}`);
|
|
14145
|
-
excludedTransactions.add(transactionId);
|
|
14146
|
-
await saveAppState('excludedTransactions', JSON.stringify(Array.from(excludedTransactions)));
|
|
14147
|
-
continue;
|
|
14148
|
-
}
|
|
14149
|
-
// Use BaseArweaveClient for getting transaction tags
|
|
14150
|
-
const tags = await queryClient.fetchQuery({
|
|
14151
|
-
queryKey: ['getTransactionTags', transactionId],
|
|
14152
|
-
queryFn: async () => BaseArweaveClient.getTransactionTags(transactionId),
|
|
14153
|
-
});
|
|
14154
|
-
if (tags && tags.length > 0) {
|
|
14155
|
-
for (const { name, value } of tags) {
|
|
14156
|
-
if (name === 'Content-SHA-256') {
|
|
14157
|
-
const metadataRecord = await getMetadata({
|
|
14158
|
-
storageTransactionId: transactionId,
|
|
14159
|
-
});
|
|
14160
|
-
if (metadataRecord) {
|
|
14161
|
-
await saveMetadata(metadataRecord, {
|
|
14162
|
-
contentHash: value,
|
|
14163
|
-
});
|
|
14164
|
-
}
|
|
14165
|
-
}
|
|
14166
|
-
}
|
|
14167
|
-
}
|
|
14168
|
-
transactionIdsToDownload.push(transactionId);
|
|
14169
|
-
}
|
|
14170
|
-
catch (error) {
|
|
14171
|
-
logger$9(error);
|
|
14172
|
-
}
|
|
14173
|
-
}
|
|
14174
|
-
await BaseFileManager.downloadAllFiles({
|
|
14175
|
-
transactionIds: transactionIdsToDownload,
|
|
14176
|
-
arweaveHost: BaseArweaveClient.getHost(),
|
|
14177
|
-
excludedTransactions,
|
|
14178
|
-
});
|
|
14179
|
-
await BaseFileManager.resizeAllImages({
|
|
14180
|
-
width: 480,
|
|
14181
|
-
height: 480,
|
|
14182
|
-
});
|
|
14183
|
-
};
|
|
14184
|
-
|
|
14185
15087
|
let isInitialized = false;
|
|
14186
15088
|
const fsInitHandler = async () => {
|
|
14187
15089
|
if (isInitialized) {
|
|
@@ -14347,7 +15249,7 @@ const addModelsToDb = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
14347
15249
|
}
|
|
14348
15250
|
const schemaDefs = Array.from(schemaDefsByModelName.values()).map(({ schemaDef }) => schemaDef);
|
|
14349
15251
|
// Fetch schemas from EAS in background - do not block init. EAS can be slow (10s+);
|
|
14350
|
-
// modelUids will be populated async and
|
|
15252
|
+
// modelUids will be populated async and EAS sync orchestrator runs when done.
|
|
14351
15253
|
const fetchEasAndPopulateModelUids = async () => {
|
|
14352
15254
|
try {
|
|
14353
15255
|
const queryClient = BaseQueryClient.getQueryClient();
|
|
@@ -14380,7 +15282,8 @@ const addModelsToDb = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
14380
15282
|
}
|
|
14381
15283
|
}
|
|
14382
15284
|
}
|
|
14383
|
-
|
|
15285
|
+
const { requestEasSyncFromModelsInit } = await Promise.resolve().then(function () { return easSyncManager; });
|
|
15286
|
+
requestEasSyncFromModelsInit();
|
|
14384
15287
|
}
|
|
14385
15288
|
else {
|
|
14386
15289
|
logger$6('[client/actors] [addModelsToDb] No schemas found from EAS, but continuing');
|
|
@@ -16830,16 +17733,19 @@ function addressesFromPersistedAddressValue(value) {
|
|
|
16830
17733
|
return out;
|
|
16831
17734
|
}
|
|
16832
17735
|
function maybeRunSyncFromEasAfterAddressSave({ context, event, }) {
|
|
17736
|
+
const merged = addressesFromPersistedAddressValue(event.value);
|
|
16833
17737
|
if (!context.syncFromEasOnAddressChange)
|
|
16834
17738
|
return;
|
|
16835
17739
|
if (event.key !== "addresses")
|
|
16836
17740
|
return;
|
|
16837
|
-
const merged = addressesFromPersistedAddressValue(event.value);
|
|
16838
17741
|
if (merged.length === 0)
|
|
16839
17742
|
return;
|
|
16840
|
-
|
|
16841
|
-
|
|
16842
|
-
}
|
|
17743
|
+
try {
|
|
17744
|
+
requestEasSyncFromAddressChange(merged);
|
|
17745
|
+
}
|
|
17746
|
+
catch (err) {
|
|
17747
|
+
logSyncAfterAddressSave("requestEasSyncFromAddressChange after address save failed", err);
|
|
17748
|
+
}
|
|
16843
17749
|
}
|
|
16844
17750
|
function emitAddressesPersistedIfAddressesKey(event) {
|
|
16845
17751
|
if (event.key !== "addresses")
|
|
@@ -16857,7 +17763,7 @@ const clientManagerMachine = setup({
|
|
|
16857
17763
|
fileSystemInit,
|
|
16858
17764
|
dbInit,
|
|
16859
17765
|
saveConfig,
|
|
16860
|
-
saveAppState
|
|
17766
|
+
saveAppState,
|
|
16861
17767
|
addModelsToStore,
|
|
16862
17768
|
addModelsToDb,
|
|
16863
17769
|
processSchemaFiles,
|
|
@@ -17181,7 +18087,16 @@ const clientInstance = {
|
|
|
17181
18087
|
*/
|
|
17182
18088
|
syncFromEas: async (options) => {
|
|
17183
18089
|
ensureInitialized();
|
|
17184
|
-
|
|
18090
|
+
startEasSyncActor();
|
|
18091
|
+
const correlationId = typeof globalThis.crypto?.randomUUID === 'function'
|
|
18092
|
+
? globalThis.crypto.randomUUID()
|
|
18093
|
+
: `${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
18094
|
+
sendEasSyncClientRequest(correlationId, options);
|
|
18095
|
+
await waitFor(easSyncActor, (snapshot) => snapshot.context.lastFinishedCorrelationIds?.includes(correlationId) ?? false);
|
|
18096
|
+
const snap = easSyncActor.getSnapshot();
|
|
18097
|
+
if (snap.context.lastFinishedStatus === 'failed') {
|
|
18098
|
+
throw new Error(snap.context.lastFinishedError ?? 'EAS sync failed');
|
|
18099
|
+
}
|
|
17185
18100
|
},
|
|
17186
18101
|
addModel: async (modelDef) => {
|
|
17187
18102
|
const db = await BaseDb.getAppDb();
|
|
@@ -17391,7 +18306,7 @@ const saveDraftLogger = debug('seedSdk:model:saveDraftToDb');
|
|
|
17391
18306
|
// Lazy import cache for ModelProperty to avoid circular dependency
|
|
17392
18307
|
// Eagerly start loading to minimize delay on first access
|
|
17393
18308
|
let ModelPropertyClass = null;
|
|
17394
|
-
const modelPropertyImportPromise = import('./ModelProperty-
|
|
18309
|
+
const modelPropertyImportPromise = import('./ModelProperty-D6JLRqQW.js')
|
|
17395
18310
|
.then(module => {
|
|
17396
18311
|
ModelPropertyClass = module.ModelProperty;
|
|
17397
18312
|
return ModelPropertyClass;
|
|
@@ -17408,7 +18323,7 @@ function getModelProperty() {
|
|
|
17408
18323
|
}
|
|
17409
18324
|
// Lazy import cache for Schema to avoid circular dependency
|
|
17410
18325
|
let SchemaClass = null;
|
|
17411
|
-
const schemaImportPromise = (async () => { const
|
|
18326
|
+
const schemaImportPromise = (async () => { const _mod_10 = await import('./Schema-B5_B8nM5.js'); return _mod_10.b; })()
|
|
17412
18327
|
.then(module => {
|
|
17413
18328
|
SchemaClass = module.Schema;
|
|
17414
18329
|
return SchemaClass;
|
|
@@ -19148,5 +20063,5 @@ var Model$1 = /*#__PURE__*/Object.freeze({
|
|
|
19148
20063
|
const TModelValues = Type.Record(Type.String(), Type.Any());
|
|
19149
20064
|
const TModelSchema = Type.Record(Type.String(), TProperty);
|
|
19150
20065
|
|
|
19151
|
-
export { getItemData as $, models$1 as A, Boolean$1 as B, properties as C, Date$1 as D, isValidEasAttestationUid as E, File$1 as F, getLatestPublishedVersionRow as G, Html as H, Image as I, Json as J, modelPropertiesToObject as K, List as L, Model as M, Number$1 as N, parseListPropertyValueFromStorage as O, Property as P, getCorrectId as Q, Relation as R, INTERNAL_PROPERTY_NAMES as S, TModelValues as T, defaultAttestationData as U, VERSION_SCHEMA_UID_OPTIMISM_SEPOLIA as V, INTERNAL_DATA_TYPES as W, toSnakeCase as X, getEasSchemaUidForSchemaDefinition as Y, ZERO_BYTES32 as Z, getEasSchemaForItemProperty as _, TModelSchema as a,
|
|
19152
|
-
//# sourceMappingURL=index-
|
|
20066
|
+
export { getItemData as $, models$1 as A, Boolean$1 as B, properties as C, Date$1 as D, isValidEasAttestationUid as E, File$1 as F, getLatestPublishedVersionRow as G, Html as H, Image as I, Json as J, modelPropertiesToObject as K, List as L, Model as M, Number$1 as N, parseListPropertyValueFromStorage as O, Property as P, getCorrectId as Q, Relation as R, INTERNAL_PROPERTY_NAMES as S, TModelValues as T, defaultAttestationData as U, VERSION_SCHEMA_UID_OPTIMISM_SEPOLIA as V, INTERNAL_DATA_TYPES as W, toSnakeCase as X, getEasSchemaUidForSchemaDefinition as Y, ZERO_BYTES32 as Z, getEasSchemaForItemProperty as _, TModelSchema as a, compareMetadataRowsLatestFirst as a$, resolveStorageNameToSchemaName as a0, appState as a1, BasePathResolver as a2, SEED_CONFIG_FILE as a3, SEED_CONFIG_FALLBACKS as a4, BaseEasClient as a5, EAS_ENDPOINT as a6, BaseQueryClient as a7, arweaveL1FinalizeJobs as a8, config as a9, GET_SEEDS as aA, GET_VERSIONS as aB, GET_PROPERTIES as aC, setSchemaUidForSchemaDefinition as aD, parseEasRelationPropertyName as aE, addModelsToDb$1 as aF, SCHEMA_NJK as aG, ItemProperty as aH, ClientManager as aI, INIT_SCRIPT_SUCCESS_MESSAGE as aJ, SCHEMA_TS as aK, getRefValueType as aL, importJsonSchema as aM, loadSchemaFromFile as aN, readJsonImportFile as aO, syncSchemaFromSource as aP, transformImportToSchemaFile as aQ, writeProcessMachine as aR, getModelIdByFileId as aS, waitForEntityIdle as aT, createReactiveProxy as aU, findEntity as aV, forceRemoveFromCaches as aW, runDestroyLifecycle as aX, getModelId as aY, isPlaceholderUid as aZ, normalizeBytes32Hex as a_, easSyncProcesses as aa, metadata$1 as ab, modelRelations as ac, modelSchemas as ad, modelUids as ae, modelsRelations as af, propertiesRelations as ag, propertyUidRelations as ah, propertyUids as ai, publishProcesses as aj, schemas as ak, uploadProcesses as al, versions as am, graphql as an, getPropertyIdForModelAndName as ao, getAllAddressesFromDb as ap, getModelSchemasFromEas as aq, getSeedsFromSchemaUids as ar, getItemVersionsFromEas as as, getItemPropertiesFromEas as at, pickLatestPropertyAttestationsByRefAndSchema as au, scheduleBulkFilesDownloadFromEasSync as av, eventEmitter as aw, EAS_SEED_DATA_SYNCED_TO_DB_EVENT as ax, generateId as ay, escapeSqliteString as az, ModelPropertyDataTypes as b, isInternalSchema as b$, getArweaveUrlForTransaction as b0, ADDRESSES_PERSISTED_EVENT as b1, parseAddressesPersistedPayload as b2, getClient as b3, ClientManagerState as b4, MachineIds as b5, createNewItem as b6, getVersionData$1 as b7, getMetadataLatest as b8, loadAllSchemasFromDb as b9, queryArweaveGatewayTransaction as bA, queryArweaveGatewayTransactionWithFallback as bB, ensureReadGatewaySelected as bC, invalidateReadGatewayCache as bD, resetArweaveReadGatewayForTests as bE, setUploadExecutor as bF, getUploadExecutor as bG, setGetPublisherForNewSeeds as bH, getGetPublisherForNewSeeds as bI, setRevokeExecutor as bJ, getRevokeExecutor as bK, setAdditionalSyncAddresses as bL, createSchema as bM, readSchema as bN, listCompleteSchemaFiles as bO, getSchemaNameFromId as bP, easSyncActor as bQ, startEasSyncActor as bR, sendEasSyncClientRequest as bS, requestEasSyncFromAddressChange as bT, requestEasSyncFromEventBus as bU, requestEasSyncFromModelsInit as bV, mergeEasSyncRequestIntents as bW, addSchemaToDb as bX, createModelsFromJson as bY, loadModelsFromDbForSchema as bZ, getLatestSchemaVersion as b_, propertyMachine as ba, SEED_PROTOCOL_SCHEMA_NAME as bb, ImageSize as bc, setSchemaUidForModel as bd, getCanonicalItemPropertiesFromEas as be, getEasSchemaUidBySchemaName as bf, getSeedsBySchemaName as bg, withExcludeRevokedFilter as bh, classifyMediaRef as bi, resolveMediaRef as bj, normalizeFeedItemFields as bk, getFeedItemStringField as bl, SeedModels as bm, DEFAULT_ARWEAVE_HOST as bn, DEFAULT_ARWEAVE_GATEWAYS as bo, DEFAULT_ARWEAVE_GRAPHQL_URL as bp, getDefaultArweaveReadGatewayHostsOrdered as bq, mergePrimaryHostWithDefaults as br, isKnownArweaveGatewayHostname as bs, getAddressesForItemsFilter as bt, normalizeUploadApiBaseUrl as bu, getUploadApiArweaveDataUrl as bv, getUploadPipelineTransactionStatus as bw, getUploadApiArweaveStatusUrl as bx, getArweaveUploadStatus as by, isArweaveL1AnchoringComplete as bz, TPropertyDataType as c, createModelFromJson as c0, ConflictError as c1, unloadEntity as c2, clearDestroySubscriptions as c3, setupEntityLiveQuery as c4, ModelSchema as c5, BaseFileManager$1 as c6, db as c7, eas as c8, getPropertyData$1 as c9, Item$1 as ca, schema as cb, SEEDPROTOCOL_Seed_Protocol_v1 as cc, Model$1 as cd, TStorageType as d, THtmlEmbeddedDataUriPolicy as e, TProperty as f, TPropertyConstructor as g, TPropertyDefs as h, PropertyMetadataKey as i, PropertyConstructor as j, Text as k, DEFAULT_TEXT_MAX_LENGTH as l, TValidationRules as m, normalizeDataType as n, getOwnedAddressesFromDb as o, BaseDb as p, getGetAdditionalSyncAddresses as q, resolveSeedIdsFromRefString as r, seeds as s, normalizeRelationPropertyValue as t, Item as u, BaseFileManager as v, getContentHash as w, htmlEmbeddedImageCoPublish as x, BaseArweaveClient as y, getEasSchemaUidForModel as z };
|
|
20067
|
+
//# sourceMappingURL=index-18lln0cM.js.map
|