@seedprotocol/sdk 0.7.5-next.850.g9ab585b → 0.7.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{BasePathResolver-CsZHPrk9.js → BasePathResolver-CBTXCMFL.js} +20 -6
- package/dist/BasePathResolver-CBTXCMFL.js.map +1 -0
- package/dist/{ClientManager-DETTj0_z.js → ClientManager-DRf4uuei.js} +348 -222
- package/dist/ClientManager-DRf4uuei.js.map +1 -0
- package/dist/{Item-TMrVEPeX.js → Item-DTJPMjFk.js} +241 -157
- package/dist/Item-DTJPMjFk.js.map +1 -0
- package/dist/{ModelProperty-Bw6N8OMK.js → ModelProperty-Dto5C0om.js} +66 -31
- package/dist/ModelProperty-Dto5C0om.js.map +1 -0
- package/dist/{Schema-VLenyJDy.js → Schema-8DxGcORY.js} +39 -37
- package/dist/{Schema-VLenyJDy.js.map → Schema-8DxGcORY.js.map} +1 -1
- package/dist/{SchemaValidationService-CLGadxgf.js → SchemaValidationService-CE92y1TT.js} +6 -6
- package/dist/{SchemaValidationService-CLGadxgf.js.map → SchemaValidationService-CE92y1TT.js.map} +1 -1
- package/dist/{backfillMetadataPropertyIds-C8fSvzy2.js → backfillMetadataPropertyIds-CRqp-BqX.js} +3 -3
- package/dist/{backfillMetadataPropertyIds-C8fSvzy2.js.map → backfillMetadataPropertyIds-CRqp-BqX.js.map} +1 -1
- package/dist/{configurePlatform-C3E0BS3u.js → configurePlatform-D4aGjKNk.js} +2 -2
- package/dist/{configurePlatform-C3E0BS3u.js.map → configurePlatform-D4aGjKNk.js.map} +1 -1
- package/dist/{detachRowsBeforeDelete-D1gTseFW.js → detachRowsBeforeDelete-BVetHtn2.js} +2 -2
- package/dist/{detachRowsBeforeDelete-D1gTseFW.js.map → detachRowsBeforeDelete-BVetHtn2.js.map} +1 -1
- package/dist/discardNewDraft-CEOouygG.js +78 -0
- package/dist/discardNewDraft-CEOouygG.js.map +1 -0
- package/dist/{eas-A82zVNQ9.js → eas-D7jvWMnI.js} +3 -3
- package/dist/{eas-A82zVNQ9.js.map → eas-D7jvWMnI.js.map} +1 -1
- package/dist/{errors-CWKup8tw.js → errors-CIrbsN_i.js} +46 -39
- package/dist/errors-CIrbsN_i.js.map +1 -0
- package/dist/{getItem-ChieGxJV.js → getItem-CxU_kT5W.js} +4 -4
- package/dist/{getItem-ChieGxJV.js.map → getItem-CxU_kT5W.js.map} +1 -1
- package/dist/{getPublishPayload-CWfjl8PM.js → getPublishPayload-DTjOKd3y.js} +13 -13
- package/dist/{getPublishPayload-CWfjl8PM.js.map → getPublishPayload-DTjOKd3y.js.map} +1 -1
- package/dist/{getPublishUploads-cLbSEXLk.js → getPublishUploads-CVTBo_OV.js} +506 -45
- package/dist/getPublishUploads-CVTBo_OV.js.map +1 -0
- package/dist/{index-CXkcz4hT.js → index-CMxEil8T.js} +8 -8
- package/dist/index-CMxEil8T.js.map +1 -0
- package/dist/{index-CURf9L4d.js → index-DWK-LOUY.js} +2 -2
- package/dist/index-DWK-LOUY.js.map +1 -0
- package/dist/{index.browser-47W0fJPw.js → index.browser-shRXMeB3.js} +11 -11
- package/dist/{index.browser-47W0fJPw.js.map → index.browser-shRXMeB3.js.map} +1 -1
- package/dist/{index.node-BiQhZQvH.js → index.node-DAKJNYp5.js} +20 -6
- package/dist/index.node-DAKJNYp5.js.map +1 -0
- package/dist/main.js +89 -504
- package/dist/main.js.map +1 -1
- package/dist/{mimeTypes-DHAHC4eZ.js → mimeTypes-C9r76DCH.js} +7 -2
- package/dist/{mimeTypes-DHAHC4eZ.js.map → mimeTypes-C9r76DCH.js.map} +1 -1
- package/dist/node.js +10 -10
- package/dist/platform.browser.js +6 -6
- package/dist/platform.node.js +4 -4
- package/dist/{property-tgPI5hMu.js → property-lz9yIpyA.js} +6 -6
- package/dist/{property-tgPI5hMu.js.map → property-lz9yIpyA.js.map} +1 -1
- package/dist/{propertyValidationRules-BLVxTejW.js → propertyValidationRules-LuIwoQoJ.js} +6 -6
- package/dist/{propertyValidationRules-BLVxTejW.js.map → propertyValidationRules-LuIwoQoJ.js.map} +1 -1
- package/dist/{publishDraftGraph-FAfecR_4.js → publishDraftGraph-CgSLPKvQ.js} +6 -6
- package/dist/{publishDraftGraph-FAfecR_4.js.map → publishDraftGraph-CgSLPKvQ.js.map} +1 -1
- package/dist/{resetAmbiguousLegacyItemData-kz2PYdZi.js → resetAmbiguousLegacyItemData-CuamkAAh.js} +2 -2
- package/dist/{resetAmbiguousLegacyItemData-kz2PYdZi.js.map → resetAmbiguousLegacyItemData-CuamkAAh.js.map} +1 -1
- package/dist/{resolveModelForSyncedSeed-Dm1E4ebt.js → resolveModelForSyncedSeed-BbSctSvz.js} +2 -2
- package/dist/{resolveModelForSyncedSeed-Dm1E4ebt.js.map → resolveModelForSyncedSeed-BbSctSvz.js.map} +1 -1
- package/dist/src/Item/Item.d.ts +9 -1
- package/dist/src/Item/Item.d.ts.map +1 -1
- package/dist/src/Item/errors.d.ts +3 -1
- package/dist/src/Item/errors.d.ts.map +1 -1
- package/dist/src/ItemProperty/ItemProperty.d.ts.map +1 -1
- package/dist/src/ItemProperty/service/actors/saveValueToDb/saveItemStorage.d.ts.map +1 -1
- package/dist/src/Model/Model.d.ts.map +1 -1
- package/dist/src/Model/service/actors/createModelProperties.d.ts.map +1 -1
- package/dist/src/ModelProperty/ModelProperty.d.ts +17 -0
- package/dist/src/ModelProperty/ModelProperty.d.ts.map +1 -1
- package/dist/src/Schema/Schema.d.ts.map +1 -1
- package/dist/src/client/ClientManager.d.ts +2 -2
- package/dist/src/client/ClientManager.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/db/alignRowPublishers.d.ts +25 -0
- package/dist/src/db/alignRowPublishers.d.ts.map +1 -0
- package/dist/src/db/read/getPublishUploads.d.ts.map +1 -1
- package/dist/src/db/read/getSchemaUidForModel.d.ts.map +1 -1
- package/dist/src/db/read/getSeedPublisher.d.ts +7 -0
- package/dist/src/db/read/getSeedPublisher.d.ts.map +1 -0
- package/dist/src/db/read/summarizePublishWork.d.ts.map +1 -1
- package/dist/src/db/write/applyArweaveL1TransactionIdLocal.d.ts +5 -3
- package/dist/src/db/write/applyArweaveL1TransactionIdLocal.d.ts.map +1 -1
- package/dist/src/db/write/claimUnpublishedDrafts.d.ts +4 -2
- package/dist/src/db/write/claimUnpublishedDrafts.d.ts.map +1 -1
- package/dist/src/db/write/createMetadata.d.ts.map +1 -1
- package/dist/src/db/write/createNewItem.d.ts.map +1 -1
- package/dist/src/db/write/createSeed.d.ts.map +1 -1
- package/dist/src/db/write/createVersion.d.ts.map +1 -1
- package/dist/src/db/write/discardNewDraft.d.ts +8 -0
- package/dist/src/db/write/discardNewDraft.d.ts.map +1 -0
- package/dist/src/db/write/restoreDataItemIdsOverwrittenByL1.d.ts +18 -0
- package/dist/src/db/write/restoreDataItemIdsOverwrittenByL1.d.ts.map +1 -0
- package/dist/src/db/write/updateItemPropertyValue.d.ts.map +1 -1
- package/dist/src/helpers/db.d.ts.map +1 -1
- package/dist/src/helpers/htmlEmbeddedDataUriPublish.d.ts +13 -2
- package/dist/src/helpers/htmlEmbeddedDataUriPublish.d.ts.map +1 -1
- package/dist/src/helpers/ownership.d.ts +9 -12
- package/dist/src/helpers/ownership.d.ts.map +1 -1
- package/dist/src/helpers/publishConfig.d.ts +9 -4
- package/dist/src/helpers/publishConfig.d.ts.map +1 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/node/db/Db.d.ts.map +1 -1
- package/dist/{syncDbWithEas-CMCAihFh.js → syncDbWithEas-CrAY9Rl2.js} +13 -13
- package/dist/{syncDbWithEas-CMCAihFh.js.map → syncDbWithEas-CrAY9Rl2.js.map} +1 -1
- package/dist/{tabEvents-BEAmMncP.js → tabEvents-BGBYV65P.js} +4 -4
- package/dist/{tabEvents-BEAmMncP.js.map → tabEvents-BGBYV65P.js.map} +1 -1
- package/dist/{tolerantWebAccess-CqiDGEyR.js → tolerantWebAccess-DVHCEulL.js} +7 -7
- package/dist/{tolerantWebAccess-CqiDGEyR.js.map → tolerantWebAccess-DVHCEulL.js.map} +1 -1
- package/dist/{updateSeedRevokedAt-Bw3uEStt.js → updateSeedRevokedAt-Dy5J8CfQ.js} +3 -3
- package/dist/{updateSeedRevokedAt-Bw3uEStt.js.map → updateSeedRevokedAt-Dy5J8CfQ.js.map} +1 -1
- package/package.json +5 -5
- package/dist/BasePathResolver-CsZHPrk9.js.map +0 -1
- package/dist/ClientManager-DETTj0_z.js.map +0 -1
- package/dist/Item-TMrVEPeX.js.map +0 -1
- package/dist/ModelProperty-Bw6N8OMK.js.map +0 -1
- package/dist/errors-CWKup8tw.js.map +0 -1
- package/dist/getPublishUploads-cLbSEXLk.js.map +0 -1
- package/dist/index-CURf9L4d.js.map +0 -1
- package/dist/index-CXkcz4hT.js.map +0 -1
- package/dist/index.node-BiQhZQvH.js.map +0 -1
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { startCase, isEqual } from 'lodash-es';
|
|
2
|
-
import {
|
|
2
|
+
import { B as BaseDb, o as easSyncProcesses, I as eventEmitter, a4 as isNode, af as isBrowser, K as BasePathResolver, aF as normalizeAddressConfig, j as appState, aS as downloadAllFilesRequestHandler, aT as downloadAllFilesBinaryRequestHandler, h as BaseFileManager, t as models$1, s as modelUids, C as seeds, aG as normalizeAddressList, A as schemas, aQ as loadModelsFromDbForSchema, aN as addSchemaToDb, aK as isInternalSchema, aU as warnOnInvalidNameMatch, aV as INTERNAL_SCHEMA_IDS, al as generateId, aW as linkModelToSchema, aR as clearNameMatchLevels, n as normalizeDataType, ae as easPropertyNameForPublish, av as SEED_PROTOCOL_SCHEMA_NAME, r as modelSchemas, m as metadata$1, v as properties, N as resolveItemModelFileId, F as versions, ah as normalizePublisher, aj as loadNameMatchLevels, p as htmlEmbeddedImageCoPublish, k as arweaveL1FinalizeJobs, z as publishProcesses, aX as getWatchedAddressesFromDb, aY as getOwnedAddressesFromDb, aZ as CLIENT_NOT_INITIALIZED } from './BasePathResolver-CBTXCMFL.js';
|
|
3
3
|
import debug from 'debug';
|
|
4
4
|
import { createActor, setup, assign, fromPromise, fromCallback, waitFor } from 'xstate';
|
|
5
|
-
import { u as MachineIds, a0 as ClientManagerEvents, a1 as withLockedItemStorageRow, a2 as getItemStorageFilePath, a3 as writeItemStorageFile,
|
|
5
|
+
import { u as MachineIds, a0 as ClientManagerEvents, a1 as withLockedItemStorageRow, a2 as getItemStorageFilePath, a3 as writeItemStorageFile, e as compareMetadataRowsLatestFirst, w as writeInBatches, a4 as resolvePublisherFromSeedRow, C as ClientManagerState, G as isLocalUnsealedDraft, s as selectInBatches, I as Item } from './Item-DTJPMjFk.js';
|
|
6
6
|
import { eq, inArray, and, isNotNull, ne, desc, countDistinct, isNull, or, sql, like } from 'drizzle-orm';
|
|
7
|
-
import { a as withDbTabLock, i as isLeaderTab, c as postTabMessage, o as onTabMessage, w as whenLeaderTab, l as listenForOtherTabsEvents, s as startTabCoordination, b as withSeedDbLock, e as emitAcrossTabs, A as ADDRESSES_PERSISTED_EVENT, p as parseAddressesPersistedPayload, L as LOCAL_COPIES_REMOVED_EVENT } from './tabEvents-
|
|
7
|
+
import { a as withDbTabLock, i as isLeaderTab, c as postTabMessage, o as onTabMessage, w as whenLeaderTab, l as listenForOtherTabsEvents, s as startTabCoordination, b as withSeedDbLock, e as emitAcrossTabs, A as ADDRESSES_PERSISTED_EVENT, p as parseAddressesPersistedPayload, L as LOCAL_COPIES_REMOVED_EVENT } from './tabEvents-BGBYV65P.js';
|
|
8
8
|
import { seedGatewayConfigFromSeedConfig, setPreferredArweaveReadBaseUrls, resolveSeedGatewayEndpoints, setResolvedSeedGatewayEndpoints, BaseArweaveClient, ensureReadGatewaySelected, DEFAULT_ARWEAVE_HOST } from '@seedprotocol/arweave';
|
|
9
|
-
import { configureEasReadChain, easName, BaseQueryClient, BaseEasClient, GET_SCHEMAS, whenEasReadChainSettled, getEasReadChainId, DEFAULT_EAS_CHAIN_ID, isEasReadChainConfigured, localNamesInBestMatchTier, isValidEasAttestationUid } from '@seedprotocol/eas';
|
|
9
|
+
import { configureEasReadChain, easName, BaseQueryClient, BaseEasClient, GET_SCHEMAS, whenEasReadChainSettled, getEasReadChainId, DEFAULT_EAS_CHAIN_ID, isEasReadChainConfigured, isPlaceholderUid, localNamesInBestMatchTier, isValidEasAttestationUid } from '@seedprotocol/eas';
|
|
10
10
|
import 'pluralize';
|
|
11
11
|
import { sha3_256 } from '@noble/hashes/sha3';
|
|
12
12
|
import { utf8ToBytes, bytesToHex } from '@noble/hashes/utils';
|
|
@@ -212,7 +212,7 @@ function toRunSyncArg(options) {
|
|
|
212
212
|
return undefined;
|
|
213
213
|
}
|
|
214
214
|
const runEasSync = fromPromise(async ({ input, }) => {
|
|
215
|
-
const { runSyncFromEas } = await import('./syncDbWithEas-
|
|
215
|
+
const { runSyncFromEas } = await import('./syncDbWithEas-CrAY9Rl2.js');
|
|
216
216
|
// Sync checks for rows and then inserts the rest (no unique index on uids), so syncs in
|
|
217
217
|
// different tabs take turns. A sync can run for minutes, so wait without a timeout.
|
|
218
218
|
await withDbTabLock('eas-sync', async () => {
|
|
@@ -422,7 +422,7 @@ function newCorrelationId() {
|
|
|
422
422
|
return `${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
423
423
|
}
|
|
424
424
|
/** Requests deferred in this tab until it leads, by source; each runs once on takeover. */
|
|
425
|
-
const deferredUntilLeader$
|
|
425
|
+
const deferredUntilLeader$4 = new Set();
|
|
426
426
|
/**
|
|
427
427
|
* Automatic syncs run in the leader tab only (docs/MULTI_TAB.md). A tab that skips one runs it if
|
|
428
428
|
* it later becomes leader, so closing the leader doesn't lose the catch-up sync.
|
|
@@ -433,11 +433,11 @@ function runInLeaderTab(source, request) {
|
|
|
433
433
|
return;
|
|
434
434
|
}
|
|
435
435
|
log(`${source} sync skipped: another tab leads`);
|
|
436
|
-
if (deferredUntilLeader$
|
|
436
|
+
if (deferredUntilLeader$4.has(source))
|
|
437
437
|
return;
|
|
438
|
-
deferredUntilLeader$
|
|
438
|
+
deferredUntilLeader$4.add(source);
|
|
439
439
|
void whenLeaderTab().then(() => {
|
|
440
|
-
deferredUntilLeader$
|
|
440
|
+
deferredUntilLeader$4.delete(source);
|
|
441
441
|
request();
|
|
442
442
|
});
|
|
443
443
|
}
|
|
@@ -511,10 +511,10 @@ var easSyncManager = /*#__PURE__*/Object.freeze({
|
|
|
511
511
|
startEasSyncActor: startEasSyncActor
|
|
512
512
|
});
|
|
513
513
|
|
|
514
|
-
const logger$
|
|
514
|
+
const logger$f = debug('seedSdk:services:events');
|
|
515
515
|
const handleServiceSaveState = (event) => {
|
|
516
516
|
const { state, serviceId } = event;
|
|
517
|
-
logger$
|
|
517
|
+
logger$f(`[browser] [service.saveState.request] serviceId: ${serviceId}`);
|
|
518
518
|
// TODO: This is called from Node as well. Do we need it? If so, need to generalize this to all platforms.
|
|
519
519
|
// localStorage.setItem(`seed_sdk_service_${serviceId}`, JSON.stringify(state))
|
|
520
520
|
};
|
|
@@ -565,7 +565,7 @@ function normalizeSeedConfigEndpoints(config) {
|
|
|
565
565
|
return { ...config, endpoints: next };
|
|
566
566
|
}
|
|
567
567
|
|
|
568
|
-
const logger$
|
|
568
|
+
const logger$e = debug('seedSdk:ClientManager:initialize');
|
|
569
569
|
/**
|
|
570
570
|
* Whether a relative filesDir already names the .seed directory or a path inside
|
|
571
571
|
* it ('.seed', '.seed/files', './.seed/files'). '.seed-alt/x' is not: it is
|
|
@@ -576,7 +576,7 @@ function isUnderDotSeed(relativePath) {
|
|
|
576
576
|
return firstSegment === '.seed';
|
|
577
577
|
}
|
|
578
578
|
const platformClassesInit = fromCallback(({ sendBack, input: { context, event } }) => {
|
|
579
|
-
logger$
|
|
579
|
+
logger$e('initialize from ClientManager');
|
|
580
580
|
const { isInitialized } = context;
|
|
581
581
|
if (!event || !('options' in event)) {
|
|
582
582
|
throw new Error('Initialize event must include options');
|
|
@@ -609,7 +609,7 @@ const platformClassesInit = fromCallback(({ sendBack, input: { context, event }
|
|
|
609
609
|
}
|
|
610
610
|
// Prefer the condition-resolved factory when available; fall back to explicit
|
|
611
611
|
// platform imports so source/vitest resolution stays reliable.
|
|
612
|
-
const { configurePlatform } = await import('./configurePlatform-
|
|
612
|
+
const { configurePlatform } = await import('./configurePlatform-D4aGjKNk.js');
|
|
613
613
|
if (isBrowser()) {
|
|
614
614
|
const { createPlatformServices } = await import('./platform.browser.js');
|
|
615
615
|
configurePlatform(createPlatformServices());
|
|
@@ -651,11 +651,9 @@ const platformClassesInit = fromCallback(({ sendBack, input: { context, event }
|
|
|
651
651
|
if (isNode() && !isBrowser() && normalizedFilesDir) {
|
|
652
652
|
const path = (await import('node:path')).default;
|
|
653
653
|
const fs = (await import('node:fs')).default;
|
|
654
|
+
// Not created here: prepareDb creates filesDir (under .seed when it's relative), so an absolute
|
|
655
|
+
// filesDir works from a read-only working directory (e.g. a packaged Electron app's cwd `/`).
|
|
654
656
|
const dotSeedDir = BasePathResolver.getDotSeedDir();
|
|
655
|
-
// Ensure .seed directory exists
|
|
656
|
-
if (!fs.existsSync(dotSeedDir)) {
|
|
657
|
-
fs.mkdirSync(dotSeedDir, { recursive: true });
|
|
658
|
-
}
|
|
659
657
|
// Check if filesDir is a browser OPFS-style path (absolute path starting with '/'
|
|
660
658
|
// that is a simple single-level path like '/app-files', not a real filesystem path)
|
|
661
659
|
// Browser OPFS paths are typically simple like '/app-files', '/files', etc.
|
|
@@ -749,7 +747,7 @@ const platformClassesInit = fromCallback(({ sendBack, input: { context, event }
|
|
|
749
747
|
};
|
|
750
748
|
});
|
|
751
749
|
|
|
752
|
-
const logger$
|
|
750
|
+
const logger$d = debug('seedSdk:client:writeToDb');
|
|
753
751
|
const saveAppState = fromCallback(({ sendBack, input: { key, value } }) => {
|
|
754
752
|
const _saveAppState = async () => {
|
|
755
753
|
try {
|
|
@@ -757,7 +755,7 @@ const saveAppState = fromCallback(({ sendBack, input: { key, value } }) => {
|
|
|
757
755
|
if (!appDb) {
|
|
758
756
|
// In test environments, continue anyway
|
|
759
757
|
if (process.env.NODE_ENV === 'test' || process.env.IS_SEED_DEV) {
|
|
760
|
-
logger$
|
|
758
|
+
logger$d('[client/actors] [saveAppState] App DB not found, but continuing in test environment');
|
|
761
759
|
return;
|
|
762
760
|
}
|
|
763
761
|
throw new Error('App DB not found');
|
|
@@ -773,13 +771,13 @@ const saveAppState = fromCallback(({ sendBack, input: { key, value } }) => {
|
|
|
773
771
|
value: JSON.stringify(value),
|
|
774
772
|
},
|
|
775
773
|
});
|
|
776
|
-
logger$
|
|
774
|
+
logger$d('result', result);
|
|
777
775
|
}
|
|
778
776
|
catch (error) {
|
|
779
|
-
logger$
|
|
777
|
+
logger$d('[client/actors] [saveAppState] Error saving app state:', error);
|
|
780
778
|
// In test environments, continue anyway
|
|
781
779
|
if (process.env.NODE_ENV === 'test' || process.env.IS_SEED_DEV) {
|
|
782
|
-
logger$
|
|
780
|
+
logger$d('[client/actors] [saveAppState] Continuing despite error in test environment');
|
|
783
781
|
return;
|
|
784
782
|
}
|
|
785
783
|
throw error;
|
|
@@ -794,10 +792,10 @@ const saveAppState = fromCallback(({ sendBack, input: { key, value } }) => {
|
|
|
794
792
|
});
|
|
795
793
|
})
|
|
796
794
|
.catch((error) => {
|
|
797
|
-
logger$
|
|
795
|
+
logger$d('[client/actors] [saveAppState] Error in promise chain:', error);
|
|
798
796
|
// In test environments, still send success to allow state machine to progress
|
|
799
797
|
if (process.env.NODE_ENV === 'test' || process.env.IS_SEED_DEV) {
|
|
800
|
-
logger$
|
|
798
|
+
logger$d('[client/actors] [saveAppState] Sending success despite error in test environment');
|
|
801
799
|
sendBack({
|
|
802
800
|
type: 'saveAppStateSuccess',
|
|
803
801
|
key,
|
|
@@ -867,7 +865,7 @@ const fileSystemInit = fromCallback(({ sendBack, input: { context }, }) => {
|
|
|
867
865
|
};
|
|
868
866
|
});
|
|
869
867
|
|
|
870
|
-
const logger$
|
|
868
|
+
const logger$c = debug('seedSdk:client:actors:dbInit');
|
|
871
869
|
const dbInit = fromCallback(({ sendBack, input: { context } }) => {
|
|
872
870
|
const _dbInit = async () => {
|
|
873
871
|
const { filesDir, dbConfig } = context;
|
|
@@ -881,14 +879,14 @@ const dbInit = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
881
879
|
if (!appDb) {
|
|
882
880
|
throw new Error('Database not available after preparation');
|
|
883
881
|
}
|
|
884
|
-
logger$
|
|
882
|
+
logger$c('[client/actors] [dbInit] Database prepared and ready');
|
|
885
883
|
};
|
|
886
884
|
_dbInit()
|
|
887
885
|
.then(() => {
|
|
888
886
|
sendBack({ type: ClientManagerEvents.DB_READY });
|
|
889
887
|
})
|
|
890
888
|
.catch((error) => {
|
|
891
|
-
logger$
|
|
889
|
+
logger$c('Error in dbInit:', error);
|
|
892
890
|
sendBack({
|
|
893
891
|
type: 'error',
|
|
894
892
|
error: error instanceof Error ? error : new Error(String(error))
|
|
@@ -896,7 +894,7 @@ const dbInit = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
896
894
|
});
|
|
897
895
|
});
|
|
898
896
|
|
|
899
|
-
const logger$
|
|
897
|
+
const logger$b = debug('seedSdk:client:actors:addModelsToStore');
|
|
900
898
|
const addModelsToStore = fromCallback(({ sendBack, input: { context } }) => {
|
|
901
899
|
const _addModelsToStore = async () => {
|
|
902
900
|
let { models } = context;
|
|
@@ -910,7 +908,7 @@ const addModelsToStore = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
910
908
|
// Models are now Model instances, no registration needed
|
|
911
909
|
// They should be created via Model.create() and are accessible via Model static methods
|
|
912
910
|
for (const [key] of Object.entries(allModels)) {
|
|
913
|
-
logger$
|
|
911
|
+
logger$b('model available:', key);
|
|
914
912
|
}
|
|
915
913
|
};
|
|
916
914
|
_addModelsToStore()
|
|
@@ -918,7 +916,7 @@ const addModelsToStore = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
918
916
|
sendBack({ type: ClientManagerEvents.ADD_MODELS_TO_STORE_SUCCESS });
|
|
919
917
|
})
|
|
920
918
|
.catch((error) => {
|
|
921
|
-
logger$
|
|
919
|
+
logger$b('[client/actors] [addModelsToStore] Error:', error);
|
|
922
920
|
sendBack({
|
|
923
921
|
type: 'error',
|
|
924
922
|
error: error instanceof Error ? error : new Error(String(error)),
|
|
@@ -926,7 +924,7 @@ const addModelsToStore = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
926
924
|
});
|
|
927
925
|
});
|
|
928
926
|
|
|
929
|
-
const logger$
|
|
927
|
+
const logger$a = debug('seedSdk:client:actors:addModelsToDb');
|
|
930
928
|
/**
|
|
931
929
|
* Returns every `models` row named in `modelNames`, inserting a null-schemaFileId stub for each name
|
|
932
930
|
* with no row yet (the schema import adopts stubs via findOrCreateModelRecord). Check-then-insert:
|
|
@@ -949,7 +947,7 @@ async function ensureModelStubs(appDb, modelNames, filesDir) {
|
|
|
949
947
|
.returning({ id: models$1.id, name: models$1.name, schemaFileId: models$1.schemaFileId }));
|
|
950
948
|
rows.push(...newlyInserted);
|
|
951
949
|
for (const name of modelsToInsert) {
|
|
952
|
-
logger$
|
|
950
|
+
logger$a('[client/actors] [addModelsToDb] inserted model:', name);
|
|
953
951
|
}
|
|
954
952
|
}
|
|
955
953
|
return rows;
|
|
@@ -989,7 +987,7 @@ const addModelsToDb = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
989
987
|
for (const modelName of modelNames) {
|
|
990
988
|
const foundModel = rowFor(modelName);
|
|
991
989
|
if (!foundModel) {
|
|
992
|
-
logger$
|
|
990
|
+
logger$a('[client/actors] [addModelsToDb] Warning: Could not find or create model:', modelName);
|
|
993
991
|
hasModelsInDb = false;
|
|
994
992
|
continue;
|
|
995
993
|
}
|
|
@@ -1001,7 +999,7 @@ const addModelsToDb = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
1001
999
|
}
|
|
1002
1000
|
// If we have no models to process, still send success (empty models is valid)
|
|
1003
1001
|
if (schemaDefsByModelName.size === 0) {
|
|
1004
|
-
logger$
|
|
1002
|
+
logger$a('[client/actors] [addModelsToDb] No models to process, but continuing');
|
|
1005
1003
|
sendBack({ type: ClientManagerEvents.ADD_MODELS_TO_DB_SUCCESS });
|
|
1006
1004
|
return;
|
|
1007
1005
|
}
|
|
@@ -1049,15 +1047,15 @@ const addModelsToDb = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
1049
1047
|
requestEasSyncFromModelsInit();
|
|
1050
1048
|
}
|
|
1051
1049
|
else {
|
|
1052
|
-
logger$
|
|
1050
|
+
logger$a('[client/actors] [addModelsToDb] No schemas found from EAS, but continuing');
|
|
1053
1051
|
}
|
|
1054
1052
|
}
|
|
1055
1053
|
catch (error) {
|
|
1056
1054
|
if (process.env.NODE_ENV === 'test' || process.env.IS_SEED_DEV) {
|
|
1057
|
-
logger$
|
|
1055
|
+
logger$a('[client/actors] [addModelsToDb] Warning: Could not fetch schemas from EAS (background):', error.message);
|
|
1058
1056
|
}
|
|
1059
1057
|
else {
|
|
1060
|
-
logger$
|
|
1058
|
+
logger$a('[client/actors] [addModelsToDb] Error fetching schemas (background):', error.message);
|
|
1061
1059
|
}
|
|
1062
1060
|
// Probably offline: the startup sync waits for this lookup, so try again.
|
|
1063
1061
|
modelUidsRetry.schedule();
|
|
@@ -1073,10 +1071,10 @@ const addModelsToDb = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
1073
1071
|
sendBack({ type: ClientManagerEvents.ADD_MODELS_TO_DB_SUCCESS });
|
|
1074
1072
|
})
|
|
1075
1073
|
.catch((error) => {
|
|
1076
|
-
logger$
|
|
1074
|
+
logger$a('[client/actors] [addModelsToDb] Error:', error);
|
|
1077
1075
|
// In test environments, still send success to allow initialization to complete
|
|
1078
1076
|
if (process.env.NODE_ENV === 'test' || process.env.IS_SEED_DEV) {
|
|
1079
|
-
logger$
|
|
1077
|
+
logger$a('[client/actors] [addModelsToDb] Continuing despite error in test environment');
|
|
1080
1078
|
sendBack({ type: ClientManagerEvents.ADD_MODELS_TO_DB_SUCCESS });
|
|
1081
1079
|
}
|
|
1082
1080
|
else {
|
|
@@ -1089,7 +1087,7 @@ const addModelsToDb = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
1089
1087
|
return () => { };
|
|
1090
1088
|
});
|
|
1091
1089
|
|
|
1092
|
-
const logger$
|
|
1090
|
+
const logger$9 = debug('seedSdk:helpers:localDbChain');
|
|
1093
1091
|
/** appState key recording which EAS chain the local database holds attestations from. */
|
|
1094
1092
|
const EAS_CHAIN_ID_APP_STATE_KEY = 'easChainId';
|
|
1095
1093
|
/**
|
|
@@ -1159,7 +1157,7 @@ async function loadLocalDbChain() {
|
|
|
1159
1157
|
const localChainId = await resolveLocalDbChainId(appDb);
|
|
1160
1158
|
if (localChainId !== undefined) {
|
|
1161
1159
|
configureEasReadChain('localDb', { chainId: localChainId });
|
|
1162
|
-
logger$
|
|
1160
|
+
logger$9('local DB holds chain %d', localChainId);
|
|
1163
1161
|
return;
|
|
1164
1162
|
}
|
|
1165
1163
|
if (isEasReadChainConfigured()) {
|
|
@@ -1185,7 +1183,7 @@ async function assertLocalDbChain() {
|
|
|
1185
1183
|
configureEasReadChain('localDb', { chainId: localChainId ?? chainId });
|
|
1186
1184
|
}
|
|
1187
1185
|
|
|
1188
|
-
const logger$
|
|
1186
|
+
const logger$8 = debug('seedSdk:client:actors:saveConfig');
|
|
1189
1187
|
let warnedKeptStoredAddresses = false;
|
|
1190
1188
|
/**
|
|
1191
1189
|
* Saves the addresses passed to init.
|
|
@@ -1226,13 +1224,13 @@ async function persistInitAddresses(appDb, { addresses, addressesProvided, owned
|
|
|
1226
1224
|
emitAcrossTabs(ADDRESSES_PERSISTED_EVENT, { owned, watched });
|
|
1227
1225
|
}
|
|
1228
1226
|
const saveConfig = fromCallback(({ sendBack, input: { context } }) => {
|
|
1229
|
-
logger$
|
|
1227
|
+
logger$8('saveConfig starting');
|
|
1230
1228
|
const { endpoints, addresses, addressesProvided, ownedAddresses, watchedAddresses, arweaveDomain, uploadApiBaseUrl, gatewayTransport, gatewayHyperKey, gatewaySidecarHost, gatewaySidecarPort, gatewayProxyBaseUrl, } = context;
|
|
1231
1229
|
// Validate endpoints - required for proper initialization
|
|
1232
1230
|
// If endpoints are missing or invalid, initialization should fail
|
|
1233
1231
|
if (!endpoints || !endpoints.filePaths || !endpoints.files) {
|
|
1234
1232
|
const error = new Error('saveConfig called with invalid endpoints: endpoints must include both filePaths and files');
|
|
1235
|
-
logger$
|
|
1233
|
+
logger$8('[internal/actors] [saveConfig] Invalid endpoints:', { endpoints });
|
|
1236
1234
|
throw error;
|
|
1237
1235
|
}
|
|
1238
1236
|
const _saveConfig = async () => {
|
|
@@ -1241,7 +1239,7 @@ const saveConfig = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
1241
1239
|
if (!appDb) {
|
|
1242
1240
|
// In test environments, continue anyway
|
|
1243
1241
|
if (process.env.NODE_ENV === 'test' || process.env.IS_SEED_DEV) {
|
|
1244
|
-
logger$
|
|
1242
|
+
logger$8('[internal/actors] [saveConfig] App DB not found, but continuing in test environment');
|
|
1245
1243
|
return;
|
|
1246
1244
|
}
|
|
1247
1245
|
throw new Error('App DB not found');
|
|
@@ -1296,10 +1294,10 @@ const saveConfig = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
1296
1294
|
await loadLocalDbChain();
|
|
1297
1295
|
}
|
|
1298
1296
|
catch (error) {
|
|
1299
|
-
logger$
|
|
1297
|
+
logger$8('[internal/actors] [saveConfig] Error saving config:', error);
|
|
1300
1298
|
// In test environments, continue anyway
|
|
1301
1299
|
if (process.env.NODE_ENV === 'test' || process.env.IS_SEED_DEV) {
|
|
1302
|
-
logger$
|
|
1300
|
+
logger$8('[internal/actors] [saveConfig] Continuing despite error in test environment');
|
|
1303
1301
|
return;
|
|
1304
1302
|
}
|
|
1305
1303
|
throw error;
|
|
@@ -1308,14 +1306,14 @@ const saveConfig = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
1308
1306
|
// Init writes run one tab at a time (docs/MULTI_TAB.md).
|
|
1309
1307
|
withSeedDbLock('init', context.filesDir, _saveConfig)
|
|
1310
1308
|
.then(() => {
|
|
1311
|
-
logger$
|
|
1309
|
+
logger$8('[internal/actors] [saveConfig] saveConfig success');
|
|
1312
1310
|
return sendBack({ type: ClientManagerEvents.SAVE_CONFIG_SUCCESS });
|
|
1313
1311
|
})
|
|
1314
1312
|
.catch((error) => {
|
|
1315
|
-
logger$
|
|
1313
|
+
logger$8('[internal/actors] [saveConfig] Error in saveConfig promise chain:', error);
|
|
1316
1314
|
// In test environments, still send success to allow state machine to progress
|
|
1317
1315
|
if (process.env.NODE_ENV === 'test' || process.env.IS_SEED_DEV) {
|
|
1318
|
-
logger$
|
|
1316
|
+
logger$8('[internal/actors] [saveConfig] Sending success despite error in test environment');
|
|
1319
1317
|
sendBack({ type: ClientManagerEvents.SAVE_CONFIG_SUCCESS });
|
|
1320
1318
|
}
|
|
1321
1319
|
else {
|
|
@@ -1328,7 +1326,7 @@ const saveConfig = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
1328
1326
|
return () => { };
|
|
1329
1327
|
});
|
|
1330
1328
|
|
|
1331
|
-
const logger$
|
|
1329
|
+
const logger$7 = debug('seedSdk:helpers:schema');
|
|
1332
1330
|
/**
|
|
1333
1331
|
* Sanitize a schema name to be filesystem-safe
|
|
1334
1332
|
* Replaces all special characters (except alphanumeric, hyphens, underscores) with underscores
|
|
@@ -1524,7 +1522,7 @@ async function listCompleteSchemaFiles() {
|
|
|
1524
1522
|
const dirExists = await BaseFileManager.pathExists(workingDir);
|
|
1525
1523
|
if (!dirExists) {
|
|
1526
1524
|
// Directory doesn't exist yet - return empty array (not an error condition)
|
|
1527
|
-
logger$
|
|
1525
|
+
logger$7(`Working directory does not exist yet: ${workingDir}, returning empty schema list`);
|
|
1528
1526
|
return [];
|
|
1529
1527
|
}
|
|
1530
1528
|
const files = await fs.promises.readdir(workingDir);
|
|
@@ -1661,7 +1659,7 @@ async function loadAllSchemasFromDb() {
|
|
|
1661
1659
|
}
|
|
1662
1660
|
catch (error) {
|
|
1663
1661
|
// If we can't list schema files (e.g., directory doesn't exist yet), continue without file-based loading
|
|
1664
|
-
logger$
|
|
1662
|
+
logger$7(`Error listing complete schema files (continuing with DB data): ${error instanceof Error ? error.message : String(error)}`);
|
|
1665
1663
|
completeSchemaFiles = [];
|
|
1666
1664
|
}
|
|
1667
1665
|
}
|
|
@@ -1714,7 +1712,7 @@ async function loadAllSchemasFromDb() {
|
|
|
1714
1712
|
continue;
|
|
1715
1713
|
}
|
|
1716
1714
|
catch (error) {
|
|
1717
|
-
logger$
|
|
1715
|
+
logger$7(`Error parsing schemaData for ${schemaName}:`, error);
|
|
1718
1716
|
// Fall through to file-based loading
|
|
1719
1717
|
}
|
|
1720
1718
|
}
|
|
@@ -1756,7 +1754,7 @@ async function loadAllSchemasFromDb() {
|
|
|
1756
1754
|
continue;
|
|
1757
1755
|
}
|
|
1758
1756
|
catch (error) {
|
|
1759
|
-
logger$
|
|
1757
|
+
logger$7(`Error loading schema file for ${schemaName}:`, error);
|
|
1760
1758
|
// Fall through to try loading from schemaData if available
|
|
1761
1759
|
}
|
|
1762
1760
|
}
|
|
@@ -1800,7 +1798,7 @@ async function loadAllSchemasFromDb() {
|
|
|
1800
1798
|
continue;
|
|
1801
1799
|
}
|
|
1802
1800
|
catch (error) {
|
|
1803
|
-
logger$
|
|
1801
|
+
logger$7(`Error parsing schemaData for ${schemaName}:`, error);
|
|
1804
1802
|
}
|
|
1805
1803
|
}
|
|
1806
1804
|
}
|
|
@@ -1811,11 +1809,11 @@ async function loadAllSchemasFromDb() {
|
|
|
1811
1809
|
// Only process if not already in result
|
|
1812
1810
|
if (!processedSchemaNames.has(schemaFileInfo.name)) {
|
|
1813
1811
|
if (isInternalSchema(schemaFileInfo.name, schemaFileInfo.schemaFileId)) {
|
|
1814
|
-
logger$
|
|
1812
|
+
logger$7(`STEP 3: skipping internal schema file: ${schemaFileInfo.filePath}`);
|
|
1815
1813
|
continue;
|
|
1816
1814
|
}
|
|
1817
1815
|
try {
|
|
1818
|
-
logger$
|
|
1816
|
+
logger$7(`STEP 3: processing schema file: ${schemaFileInfo.name} from ${schemaFileInfo.filePath}`);
|
|
1819
1817
|
const content = await BaseFileManager.readFileAsString(schemaFileInfo.filePath);
|
|
1820
1818
|
const schemaFile = JSON.parse(content);
|
|
1821
1819
|
// Import this schema to database (mark as non-draft since it's in a file)
|
|
@@ -1835,7 +1833,7 @@ async function loadAllSchemasFromDb() {
|
|
|
1835
1833
|
processedSchemaNames.add(schemaFileInfo.name);
|
|
1836
1834
|
}
|
|
1837
1835
|
catch (error) {
|
|
1838
|
-
logger$
|
|
1836
|
+
logger$7(`Error loading schema file ${schemaFileInfo.filePath}:`, error);
|
|
1839
1837
|
}
|
|
1840
1838
|
}
|
|
1841
1839
|
}
|
|
@@ -1852,7 +1850,7 @@ async function migrateFileSchemasToDb() {
|
|
|
1852
1850
|
if (!db) {
|
|
1853
1851
|
throw new Error('Database not found');
|
|
1854
1852
|
}
|
|
1855
|
-
logger$
|
|
1853
|
+
logger$7('Starting migration of file-based schemas to database');
|
|
1856
1854
|
// Get all complete schema files
|
|
1857
1855
|
const completeSchemas = await listCompleteSchemaFiles();
|
|
1858
1856
|
let migratedCount = 0;
|
|
@@ -1862,7 +1860,7 @@ async function migrateFileSchemasToDb() {
|
|
|
1862
1860
|
const content = await BaseFileManager.readFileAsString(schemaFileInfo.filePath);
|
|
1863
1861
|
const schemaFile = JSON.parse(content);
|
|
1864
1862
|
if (!schemaFile.$schema || !schemaFile.metadata?.name) {
|
|
1865
|
-
logger$
|
|
1863
|
+
logger$7(`Skipping invalid schema file: ${schemaFileInfo.filePath}`);
|
|
1866
1864
|
continue;
|
|
1867
1865
|
}
|
|
1868
1866
|
const schemaName = schemaFile.metadata.name;
|
|
@@ -1884,17 +1882,17 @@ async function migrateFileSchemasToDb() {
|
|
|
1884
1882
|
JSON.stringify(schemaFile, null, 2), // schemaData
|
|
1885
1883
|
false);
|
|
1886
1884
|
migratedCount++;
|
|
1887
|
-
logger$
|
|
1885
|
+
logger$7(`Migrated schema: ${schemaName} v${schemaFile.version}`);
|
|
1888
1886
|
}
|
|
1889
1887
|
else {
|
|
1890
|
-
logger$
|
|
1888
|
+
logger$7(`Schema ${schemaName} already exists in database, skipping`);
|
|
1891
1889
|
}
|
|
1892
1890
|
}
|
|
1893
1891
|
catch (error) {
|
|
1894
|
-
logger$
|
|
1892
|
+
logger$7(`Error migrating schema file ${schemaFileInfo.filePath}:`, error);
|
|
1895
1893
|
}
|
|
1896
1894
|
}
|
|
1897
|
-
logger$
|
|
1895
|
+
logger$7(`Migration complete: ${migratedCount} schemas migrated`);
|
|
1898
1896
|
return migratedCount;
|
|
1899
1897
|
}
|
|
1900
1898
|
/**
|
|
@@ -1947,7 +1945,7 @@ const getDeterministicIdsWithPrefix = (prefix) => {
|
|
|
1947
1945
|
return (suffix) => bytesToHex(prefixHash.clone().update(utf8ToBytes(suffix)).digest()).slice(0, 10);
|
|
1948
1946
|
};
|
|
1949
1947
|
|
|
1950
|
-
const logger$
|
|
1948
|
+
const logger$6 = debug('seedSdk:imports:json');
|
|
1951
1949
|
/**
|
|
1952
1950
|
* Get refValueType from a property object with case-insensitive key lookup.
|
|
1953
1951
|
* Handles refValueType, refvaluetype, ref_value_type, elementType, and legacy items.type / items.Type.
|
|
@@ -2025,7 +2023,7 @@ function getRefValueType(prop) {
|
|
|
2025
2023
|
* @returns Promise that resolves when properties are found, or rejects if not found after max retries
|
|
2026
2024
|
*/
|
|
2027
2025
|
const verifyPropertiesPersisted = async (db, modelId, modelName, maxRetries = 10, retryDelay = 100) => {
|
|
2028
|
-
const _mod_0 = await import('./BasePathResolver-
|
|
2026
|
+
const _mod_0 = await import('./BasePathResolver-CBTXCMFL.js');
|
|
2029
2027
|
const _ns_0 = _mod_0.bb;
|
|
2030
2028
|
const modelSchemaMod = _ns_0;
|
|
2031
2029
|
const { properties: propertiesTable } = modelSchemaMod;
|
|
@@ -2038,11 +2036,11 @@ const verifyPropertiesPersisted = async (db, modelId, modelName, maxRetries = 10
|
|
|
2038
2036
|
.where(eq(propertiesTable.modelId, modelId))
|
|
2039
2037
|
.limit(1);
|
|
2040
2038
|
if (props.length > 0) {
|
|
2041
|
-
logger$
|
|
2039
|
+
logger$6(`Verified properties exist for model "${modelName}" (modelId: ${modelId}) after ${attempt + 1} attempt(s)`);
|
|
2042
2040
|
return;
|
|
2043
2041
|
}
|
|
2044
2042
|
if (attempt < maxRetries - 1) {
|
|
2045
|
-
logger$
|
|
2043
|
+
logger$6(`Properties not yet visible for model "${modelName}" (modelId: ${modelId}), retrying in ${retryDelay}ms (attempt ${attempt + 1}/${maxRetries})`);
|
|
2046
2044
|
await new Promise(resolve => setTimeout(resolve, retryDelay));
|
|
2047
2045
|
}
|
|
2048
2046
|
}
|
|
@@ -2393,7 +2391,7 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
|
|
|
2393
2391
|
if (parsed.$schema && parsed.metadata) {
|
|
2394
2392
|
// It's already a complete schema format - preserve it (id may be missing, will be generated)
|
|
2395
2393
|
originalSchemaFile = parsed;
|
|
2396
|
-
logger$
|
|
2394
|
+
logger$6(`Input is complete schema format (${originalSchemaFile.id ? `preserving ID: ${originalSchemaFile.id}` : 'id will be generated'})`);
|
|
2397
2395
|
}
|
|
2398
2396
|
}
|
|
2399
2397
|
catch {
|
|
@@ -2418,7 +2416,7 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
|
|
|
2418
2416
|
// Check DB for existing schema by name+version (same as minimal path)
|
|
2419
2417
|
const db = BaseDb.getAppDb();
|
|
2420
2418
|
if (db) {
|
|
2421
|
-
const _mod_1 = await import('./BasePathResolver-
|
|
2419
|
+
const _mod_1 = await import('./BasePathResolver-CBTXCMFL.js');
|
|
2422
2420
|
const _ns_1 = _mod_1.bd;
|
|
2423
2421
|
const schemaSchemaMod = _ns_1;
|
|
2424
2422
|
const { schemas: schemasTable } = schemaSchemaMod;
|
|
@@ -2432,16 +2430,16 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
|
|
|
2432
2430
|
.limit(1);
|
|
2433
2431
|
if (existingByName.length > 0 && existingByName[0].schemaData) {
|
|
2434
2432
|
const existing = existingByName[0];
|
|
2435
|
-
logger$
|
|
2433
|
+
logger$6(`Idempotency: found existing schema by name+version: ${schemaFile.metadata.name} v${schemaFile.version ?? version}`);
|
|
2436
2434
|
const existingSchema = JSON.parse(existing.schemaData);
|
|
2437
2435
|
const contentMatches = compareSchemaContent(schemaFile, existingSchema);
|
|
2438
|
-
logger$
|
|
2436
|
+
logger$6(`Idempotency: compareSchemaContent=${contentMatches} for ${schemaFile.metadata.name}`);
|
|
2439
2437
|
if (contentMatches) {
|
|
2440
2438
|
if (existing.schemaFileId) {
|
|
2441
2439
|
const workingDir = BaseFileManager.getWorkingDir();
|
|
2442
2440
|
const existingFilePath = getSchemaFilePath(workingDir, schemaFile.metadata.name, schemaFile.version ?? version, existing.schemaFileId);
|
|
2443
2441
|
if (await BaseFileManager.pathExists(existingFilePath)) {
|
|
2444
|
-
logger$
|
|
2442
|
+
logger$6(`Schema ${schemaFile.metadata.name} v${schemaFile.version} already exists with same content, loading existing file`);
|
|
2445
2443
|
return await loadSchemaFromFile(existingFilePath);
|
|
2446
2444
|
}
|
|
2447
2445
|
await BaseFileManager.createDirIfNotExists(workingDir);
|
|
@@ -2449,7 +2447,7 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
|
|
|
2449
2447
|
await BaseFileManager.waitForFileWithContent(existingFilePath, 100, 5000);
|
|
2450
2448
|
return await loadSchemaFromFile(existingFilePath);
|
|
2451
2449
|
}
|
|
2452
|
-
logger$
|
|
2450
|
+
logger$6(`Schema ${schemaFile.metadata.name} v${schemaFile.version} already exists with same content (no schemaFileId), using DB`);
|
|
2453
2451
|
return '';
|
|
2454
2452
|
}
|
|
2455
2453
|
}
|
|
@@ -2465,7 +2463,7 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
|
|
|
2465
2463
|
// processSchemaFiles runs multiple times (React StrictMode, app restarts).
|
|
2466
2464
|
if (!schemaFile.id) {
|
|
2467
2465
|
schemaFile.id = await getDeterministicSchemaFileId(schemaFile);
|
|
2468
|
-
logger$
|
|
2466
|
+
logger$6(`Generated deterministic schema ID for ${schemaFile.metadata.name}:`, schemaFile.id);
|
|
2469
2467
|
}
|
|
2470
2468
|
// Before generating IDs, check if a file already exists with this schemaFileId
|
|
2471
2469
|
// This handles the case where the schema was already loaded via loadSchemaFromFile
|
|
@@ -2475,7 +2473,7 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
|
|
|
2475
2473
|
const existingFileExists = await BaseFileManager.pathExists(existingFilePath);
|
|
2476
2474
|
if (existingFileExists) {
|
|
2477
2475
|
// File already exists with this schemaFileId - just load it instead of creating a new one
|
|
2478
|
-
logger$
|
|
2476
|
+
logger$6(`Schema file already exists with schemaFileId ${schemaFile.id}, loading it instead of creating new file`);
|
|
2479
2477
|
return await loadSchemaFromFile(existingFilePath);
|
|
2480
2478
|
}
|
|
2481
2479
|
// Generate missing model and property IDs.
|
|
@@ -2486,12 +2484,12 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
|
|
|
2486
2484
|
for (const [modelName, model] of Object.entries(schemaFile.models || {})) {
|
|
2487
2485
|
if (!model.id) {
|
|
2488
2486
|
model.id = getDeterministicId(modelName);
|
|
2489
|
-
logger$
|
|
2487
|
+
logger$6(`Generated deterministic model ID for ${modelName}:`, model.id);
|
|
2490
2488
|
}
|
|
2491
2489
|
for (const [propName, prop] of Object.entries(model.properties || {})) {
|
|
2492
2490
|
if (!prop.id) {
|
|
2493
2491
|
prop.id = getDeterministicId(modelName + propName);
|
|
2494
|
-
logger$
|
|
2492
|
+
logger$6(`Generated deterministic property ID for ${modelName}.${propName}:`, prop.id);
|
|
2495
2493
|
}
|
|
2496
2494
|
}
|
|
2497
2495
|
}
|
|
@@ -2503,7 +2501,7 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
|
|
|
2503
2501
|
// For minimal imports: check DB for existing schema before creating new file
|
|
2504
2502
|
const db = BaseDb.getAppDb();
|
|
2505
2503
|
if (db) {
|
|
2506
|
-
const _mod_2 = await import('./BasePathResolver-
|
|
2504
|
+
const _mod_2 = await import('./BasePathResolver-CBTXCMFL.js');
|
|
2507
2505
|
const _ns_2 = _mod_2.bd;
|
|
2508
2506
|
const schemaSchemaMod = _ns_2;
|
|
2509
2507
|
const { schemas: schemasTable } = schemaSchemaMod;
|
|
@@ -2527,14 +2525,14 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
|
|
|
2527
2525
|
const workingDir = BaseFileManager.getWorkingDir();
|
|
2528
2526
|
const existingFilePath = getSchemaFilePath(workingDir, importData.name, version, existing.schemaFileId);
|
|
2529
2527
|
if (await BaseFileManager.pathExists(existingFilePath)) {
|
|
2530
|
-
logger$
|
|
2528
|
+
logger$6(`Schema ${importData.name} v${version} already exists with same content, loading existing file`);
|
|
2531
2529
|
return await loadSchemaFromFile(existingFilePath);
|
|
2532
2530
|
}
|
|
2533
2531
|
// File missing but schemaData exists - restore file from schemaData
|
|
2534
2532
|
await BaseFileManager.createDirIfNotExists(workingDir);
|
|
2535
2533
|
await BaseFileManager.saveFile(existingFilePath, existing.schemaData);
|
|
2536
2534
|
await BaseFileManager.waitForFileWithContent(existingFilePath, 100, 5000);
|
|
2537
|
-
logger$
|
|
2535
|
+
logger$6(`Restored schema file from schemaData for ${importData.name} v${version}`);
|
|
2538
2536
|
return await loadSchemaFromFile(existingFilePath);
|
|
2539
2537
|
}
|
|
2540
2538
|
// No schemaFileId - restore file from schemaData using id from parsed schema
|
|
@@ -2545,10 +2543,10 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
|
|
|
2545
2543
|
await BaseFileManager.createDirIfNotExists(workingDir);
|
|
2546
2544
|
await BaseFileManager.saveFile(existingFilePath, existing.schemaData);
|
|
2547
2545
|
await BaseFileManager.waitForFileWithContent(existingFilePath, 100, 5000);
|
|
2548
|
-
logger$
|
|
2546
|
+
logger$6(`Restored schema file from schemaData for ${importData.name} v${version}`);
|
|
2549
2547
|
return await loadSchemaFromFile(existingFilePath);
|
|
2550
2548
|
}
|
|
2551
|
-
logger$
|
|
2549
|
+
logger$6(`Schema ${importData.name} v${version} already exists with same content (no id), using DB`);
|
|
2552
2550
|
return '';
|
|
2553
2551
|
}
|
|
2554
2552
|
// Content differs - create new version
|
|
@@ -2559,7 +2557,7 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
|
|
|
2559
2557
|
.orderBy(desc(schemasTable.version))
|
|
2560
2558
|
.limit(1);
|
|
2561
2559
|
const newVersion = latestVersionRows.length > 0 ? latestVersionRows[0].version + 1 : version;
|
|
2562
|
-
logger$
|
|
2560
|
+
logger$6(`Schema ${importData.name} content changed, creating new version v${newVersion}`);
|
|
2563
2561
|
schemaFile = transformImportToSchemaFile(importData, newVersion);
|
|
2564
2562
|
version = newVersion;
|
|
2565
2563
|
}
|
|
@@ -2585,7 +2583,7 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
|
|
|
2585
2583
|
// Check if this is an internal SDK schema (should not create files in app directory)
|
|
2586
2584
|
const isInternal = isInternalSchema(schemaFile.metadata.name, schemaFile.id);
|
|
2587
2585
|
if (isInternal) {
|
|
2588
|
-
logger$
|
|
2586
|
+
logger$6(`Skipping file creation for internal schema: ${schemaFile.metadata.name}`);
|
|
2589
2587
|
// For internal schemas, just load to database and store, don't create file
|
|
2590
2588
|
// Extract schema name and version
|
|
2591
2589
|
const schemaName = schemaFile.metadata?.name;
|
|
@@ -2642,7 +2640,7 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
|
|
|
2642
2640
|
// Use fixed internal schema ID if missing (never generate for internal)
|
|
2643
2641
|
if (!schemaFile.id) {
|
|
2644
2642
|
schemaFile.id = INTERNAL_SCHEMA_IDS[0];
|
|
2645
|
-
logger$
|
|
2643
|
+
logger$6('Using fixed internal schema ID:', schemaFile.id);
|
|
2646
2644
|
}
|
|
2647
2645
|
// Extract schemaFileIds from JSON file and generate missing ones BEFORE creating models
|
|
2648
2646
|
// This ensures Model instances are created with correct IDs
|
|
@@ -2652,7 +2650,7 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
|
|
|
2652
2650
|
// Generate model ID if missing
|
|
2653
2651
|
if (!model.id) {
|
|
2654
2652
|
model.id = generateId();
|
|
2655
|
-
logger$
|
|
2653
|
+
logger$6(`Generated model ID for ${modelName}:`, model.id);
|
|
2656
2654
|
// Update the schemaFile object so it's included in schemaData
|
|
2657
2655
|
schemaFile.models[modelName].id = model.id;
|
|
2658
2656
|
}
|
|
@@ -2662,7 +2660,7 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
|
|
|
2662
2660
|
// Generate property ID if missing
|
|
2663
2661
|
if (!prop.id) {
|
|
2664
2662
|
prop.id = generateId();
|
|
2665
|
-
logger$
|
|
2663
|
+
logger$6(`Generated property ID for ${modelName}.${propName}:`, prop.id);
|
|
2666
2664
|
// Update the schemaFile object so it's included in schemaData
|
|
2667
2665
|
schemaFile.models[modelName].properties[propName].id = prop.id;
|
|
2668
2666
|
}
|
|
@@ -2674,7 +2672,7 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
|
|
|
2674
2672
|
}
|
|
2675
2673
|
// Convert JSON models to Model classes, passing modelFileIds and propertyFileIds so Model instances use correct IDs
|
|
2676
2674
|
const modelDefinitions = await createModelsFromJson(importDataForInternal, modelFileIds, propertyFileIds);
|
|
2677
|
-
logger$
|
|
2675
|
+
logger$6('loadSchemaFromFile (internal) - modelDefinitions length:', Object.keys(modelDefinitions).length);
|
|
2678
2676
|
// Convert schema file metadata to schema input for database
|
|
2679
2677
|
const schemaInput = {
|
|
2680
2678
|
name: schemaName,
|
|
@@ -2684,7 +2682,7 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
|
|
|
2684
2682
|
updatedAt: new Date(schemaFile.metadata.updatedAt).getTime(),
|
|
2685
2683
|
};
|
|
2686
2684
|
// Use dynamic import to break circular dependency
|
|
2687
|
-
const _mod_3 = await import('./BasePathResolver-
|
|
2685
|
+
const _mod_3 = await import('./BasePathResolver-CBTXCMFL.js');
|
|
2688
2686
|
const _ns_3 = _mod_3.bg;
|
|
2689
2687
|
const dbMod = _ns_3;
|
|
2690
2688
|
const { addSchemaToDb, addModelsToDb } = dbMod;
|
|
@@ -2706,11 +2704,11 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
|
|
|
2706
2704
|
});
|
|
2707
2705
|
// Verify expected models are linked (single attempt - addModelsToDb already confirmed)
|
|
2708
2706
|
const expectedModelNames = Object.keys(schemaFile.models || {});
|
|
2709
|
-
const _mod_4 = await import('./BasePathResolver-
|
|
2707
|
+
const _mod_4 = await import('./BasePathResolver-CBTXCMFL.js');
|
|
2710
2708
|
const _ns_4 = _mod_4.be;
|
|
2711
2709
|
const modelSchemaSchemaMod = _ns_4;
|
|
2712
2710
|
const { modelSchemas } = modelSchemaSchemaMod;
|
|
2713
|
-
const _mod_5 = await import('./BasePathResolver-
|
|
2711
|
+
const _mod_5 = await import('./BasePathResolver-CBTXCMFL.js');
|
|
2714
2712
|
const _ns_5 = _mod_5.bb;
|
|
2715
2713
|
const modelSchemaMod = _ns_5;
|
|
2716
2714
|
const { models: modelsTable } = modelSchemaMod;
|
|
@@ -2800,12 +2798,12 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
|
|
|
2800
2798
|
}
|
|
2801
2799
|
catch (dbError) {
|
|
2802
2800
|
// Database not available - log warning but continue
|
|
2803
|
-
logger$
|
|
2801
|
+
logger$6('Database not available, skipping database operations:', dbError instanceof Error ? dbError.message : String(dbError));
|
|
2804
2802
|
}
|
|
2805
2803
|
// Models are now Model instances, no registration needed
|
|
2806
2804
|
// They should be created via Model.create() and are accessible via Model static methods
|
|
2807
2805
|
for (const [modelName] of Object.entries(modelDefinitions)) {
|
|
2808
|
-
logger$
|
|
2806
|
+
logger$6('loadSchemaFromFile (internal) - model available:', modelName);
|
|
2809
2807
|
}
|
|
2810
2808
|
// Schema is now saved to database
|
|
2811
2809
|
// useSchemas hook will pick it up via database queries
|
|
@@ -2816,7 +2814,7 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
|
|
|
2816
2814
|
// Ensure schema ID is defined (should always be set by this point, but check for safety)
|
|
2817
2815
|
if (!schemaFile.id) {
|
|
2818
2816
|
schemaFile.id = generateId();
|
|
2819
|
-
logger$
|
|
2817
|
+
logger$6('Generated schema ID before file path creation:', schemaFile.id);
|
|
2820
2818
|
}
|
|
2821
2819
|
// Get the target file path using ID-based naming (preferred)
|
|
2822
2820
|
const filePath = getSchemaFilePath(workingDir, schemaFile.metadata.name, version, schemaFile.id);
|
|
@@ -2835,7 +2833,7 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
|
|
|
2835
2833
|
const data = JSON.parse(content);
|
|
2836
2834
|
if (data.$schema) {
|
|
2837
2835
|
// File is already a complete schema, just load it
|
|
2838
|
-
logger$
|
|
2836
|
+
logger$6(`Schema file ${filePath} already exists and is complete, loading it`);
|
|
2839
2837
|
return await loadSchemaFromFile(filePath);
|
|
2840
2838
|
}
|
|
2841
2839
|
}
|
|
@@ -2853,7 +2851,7 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
|
|
|
2853
2851
|
// Compare schemas structurally
|
|
2854
2852
|
if (compareSchemasStructurally(schemaFile, existingSchema)) {
|
|
2855
2853
|
// Schemas match - just load the existing file
|
|
2856
|
-
logger$
|
|
2854
|
+
logger$6(`Schema ${schemaFile.metadata.name} v${version} already exists with matching content, loading it`);
|
|
2857
2855
|
return await loadSchemaFromFile(filePath);
|
|
2858
2856
|
}
|
|
2859
2857
|
else {
|
|
@@ -2909,7 +2907,7 @@ async function applySchemaToDb(schemaFile, modelDefinitions, modelFileIds, prope
|
|
|
2909
2907
|
createdAt: new Date(schemaFile.metadata.createdAt).getTime(),
|
|
2910
2908
|
updatedAt: new Date(schemaFile.metadata.updatedAt).getTime(),
|
|
2911
2909
|
};
|
|
2912
|
-
const _mod_6 = await import('./BasePathResolver-
|
|
2910
|
+
const _mod_6 = await import('./BasePathResolver-CBTXCMFL.js');
|
|
2913
2911
|
const _ns_6 = _mod_6.bg;
|
|
2914
2912
|
const dbMod = _ns_6;
|
|
2915
2913
|
const { addSchemaToDb, addModelsToDb } = dbMod;
|
|
@@ -3032,7 +3030,7 @@ const loadSchemaFromFile = async (schemaFilePath) => {
|
|
|
3032
3030
|
// Generate schema ID if missing (before creating schemaInput)
|
|
3033
3031
|
if (!schemaFile.id) {
|
|
3034
3032
|
schemaFile.id = generateId();
|
|
3035
|
-
logger$
|
|
3033
|
+
logger$6('Generated schema ID for schema file:', schemaFile.id);
|
|
3036
3034
|
}
|
|
3037
3035
|
// Extract schemaFileIds from JSON file and generate missing ones BEFORE creating models
|
|
3038
3036
|
// This ensures Model instances are created with correct IDs
|
|
@@ -3042,7 +3040,7 @@ const loadSchemaFromFile = async (schemaFilePath) => {
|
|
|
3042
3040
|
// Generate model ID if missing
|
|
3043
3041
|
if (!model.id) {
|
|
3044
3042
|
model.id = generateId();
|
|
3045
|
-
logger$
|
|
3043
|
+
logger$6(`Generated model ID for ${modelName}:`, model.id);
|
|
3046
3044
|
// Update the schemaFile object so it's included in schemaData
|
|
3047
3045
|
schemaFile.models[modelName].id = model.id;
|
|
3048
3046
|
}
|
|
@@ -3052,7 +3050,7 @@ const loadSchemaFromFile = async (schemaFilePath) => {
|
|
|
3052
3050
|
// Generate property ID if missing
|
|
3053
3051
|
if (!prop.id) {
|
|
3054
3052
|
prop.id = generateId();
|
|
3055
|
-
logger$
|
|
3053
|
+
logger$6(`Generated property ID for ${modelName}.${propName}:`, prop.id);
|
|
3056
3054
|
// Update the schemaFile object so it's included in schemaData
|
|
3057
3055
|
schemaFile.models[modelName].properties[propName].id = prop.id;
|
|
3058
3056
|
}
|
|
@@ -3064,7 +3062,7 @@ const loadSchemaFromFile = async (schemaFilePath) => {
|
|
|
3064
3062
|
}
|
|
3065
3063
|
// Convert JSON models to Model classes, passing modelFileIds and propertyFileIds so Model instances use correct IDs
|
|
3066
3064
|
const modelDefinitions = await createModelsFromJson(importData, modelFileIds, propertyFileIds);
|
|
3067
|
-
logger$
|
|
3065
|
+
logger$6('loadSchemaFromFile - modelDefinitions length:', Object.keys(modelDefinitions).length);
|
|
3068
3066
|
// Try to add schema and models to database if database is available
|
|
3069
3067
|
try {
|
|
3070
3068
|
const db = BaseDb.getAppDb();
|
|
@@ -3078,11 +3076,11 @@ const loadSchemaFromFile = async (schemaFilePath) => {
|
|
|
3078
3076
|
]));
|
|
3079
3077
|
const { schemaRecord } = await applySchemaToDb(schemaFile, modelDefinitions, modelFileIds, propertyFileIds, propertyDefinitions);
|
|
3080
3078
|
// Query the database to get model IDs that were just created
|
|
3081
|
-
const _mod_7 = await import('./BasePathResolver-
|
|
3079
|
+
const _mod_7 = await import('./BasePathResolver-CBTXCMFL.js');
|
|
3082
3080
|
const _ns_7 = _mod_7.be;
|
|
3083
3081
|
const modelSchemaSchemaMod = _ns_7;
|
|
3084
3082
|
const { modelSchemas } = modelSchemaSchemaMod;
|
|
3085
|
-
const _mod_8 = await import('./BasePathResolver-
|
|
3083
|
+
const _mod_8 = await import('./BasePathResolver-CBTXCMFL.js');
|
|
3086
3084
|
const _ns_8 = _mod_8.bb;
|
|
3087
3085
|
const modelSchemaMod = _ns_8;
|
|
3088
3086
|
const { models: modelsTable } = modelSchemaMod;
|
|
@@ -3130,17 +3128,17 @@ const loadSchemaFromFile = async (schemaFilePath) => {
|
|
|
3130
3128
|
await new Promise(resolve => setTimeout(resolve, 100));
|
|
3131
3129
|
}
|
|
3132
3130
|
}
|
|
3133
|
-
logger$
|
|
3131
|
+
logger$6(`Verifying properties: found ${modelLinks.length} model links for schema ${schemaName} (id: ${schemaRecord.id})`);
|
|
3134
3132
|
// If we didn't verify via direct lookup, verify via join table
|
|
3135
3133
|
if (!seedModelId || (seedModel.length === 0 || !seedModel[0].id)) {
|
|
3136
3134
|
const seedModelLink = modelLinks.find((link) => link.modelName === 'Seed');
|
|
3137
3135
|
if (seedModelLink && seedModelLink.modelId) {
|
|
3138
|
-
logger$
|
|
3136
|
+
logger$6(`Verifying properties for Seed model via join table (modelId: ${seedModelLink.modelId})`);
|
|
3139
3137
|
await verifyPropertiesPersisted(db, seedModelLink.modelId, 'Seed', 10, 100);
|
|
3140
3138
|
}
|
|
3141
3139
|
else if (modelLinks.length > 0 && modelLinks[0].modelId) {
|
|
3142
3140
|
// Fallback to first model if Seed not found
|
|
3143
|
-
logger$
|
|
3141
|
+
logger$6(`Verifying properties for ${modelLinks[0].modelName} model via join table (modelId: ${modelLinks[0].modelId})`);
|
|
3144
3142
|
await verifyPropertiesPersisted(db, modelLinks[0].modelId, modelLinks[0].modelName || 'unknown', 10, 100);
|
|
3145
3143
|
}
|
|
3146
3144
|
}
|
|
@@ -3148,7 +3146,7 @@ const loadSchemaFromFile = async (schemaFilePath) => {
|
|
|
3148
3146
|
// After properties are created (file path), ensure schemaFile has the correct IDs from database
|
|
3149
3147
|
// Query the database to get the actual schemaFileId values that were used
|
|
3150
3148
|
// This ensures schemaData matches what's actually in the database
|
|
3151
|
-
const _mod_9 = await import('./BasePathResolver-
|
|
3149
|
+
const _mod_9 = await import('./BasePathResolver-CBTXCMFL.js');
|
|
3152
3150
|
const _ns_9 = _mod_9.bb;
|
|
3153
3151
|
const modelSchemaMod2 = _ns_9;
|
|
3154
3152
|
const { properties: propertiesTable } = modelSchemaMod2;
|
|
@@ -3173,7 +3171,7 @@ const loadSchemaFromFile = async (schemaFilePath) => {
|
|
|
3173
3171
|
const currentId = schemaFile.models[modelName].properties[propRecord.name].id;
|
|
3174
3172
|
if (currentId !== propRecord.schemaFileId) {
|
|
3175
3173
|
schemaFile.models[modelName].properties[propRecord.name].id = propRecord.schemaFileId;
|
|
3176
|
-
logger$
|
|
3174
|
+
logger$6(`Updated schemaFile property ID for ${modelName}.${propRecord.name} from ${currentId} to ${propRecord.schemaFileId}`);
|
|
3177
3175
|
schemaFileUpdated = true;
|
|
3178
3176
|
}
|
|
3179
3177
|
}
|
|
@@ -3184,7 +3182,7 @@ const loadSchemaFromFile = async (schemaFilePath) => {
|
|
|
3184
3182
|
// This is important even if nothing changed, to ensure consistency
|
|
3185
3183
|
const updatedSchemaData = JSON.stringify(schemaFile, null, 2);
|
|
3186
3184
|
// Update the schema record in the database with current schemaData
|
|
3187
|
-
const _mod_10 = await import('./BasePathResolver-
|
|
3185
|
+
const _mod_10 = await import('./BasePathResolver-CBTXCMFL.js');
|
|
3188
3186
|
const _ns_10 = _mod_10.bd;
|
|
3189
3187
|
const schemaSchemaMod = _ns_10;
|
|
3190
3188
|
const { schemas: schemasTable } = schemaSchemaMod;
|
|
@@ -3194,21 +3192,21 @@ const loadSchemaFromFile = async (schemaFilePath) => {
|
|
|
3194
3192
|
.where(eq(schemasTable.id, schemaRecord.id));
|
|
3195
3193
|
clearNameMatchLevels();
|
|
3196
3194
|
if (schemaFileUpdated) {
|
|
3197
|
-
logger$
|
|
3195
|
+
logger$6(`Updated schemaData in database with actual property IDs for schema "${schemaName}"`);
|
|
3198
3196
|
}
|
|
3199
3197
|
else {
|
|
3200
|
-
logger$
|
|
3198
|
+
logger$6(`Verified schemaData in database matches schemaFile for schema "${schemaName}"`);
|
|
3201
3199
|
}
|
|
3202
3200
|
}
|
|
3203
3201
|
}
|
|
3204
3202
|
catch (dbError) {
|
|
3205
3203
|
// Database not available - log warning but continue
|
|
3206
|
-
logger$
|
|
3204
|
+
logger$6('Database not available, skipping database operations:', dbError instanceof Error ? dbError.message : String(dbError));
|
|
3207
3205
|
}
|
|
3208
3206
|
// Models are now Model instances, no registration needed
|
|
3209
3207
|
// They should be created via Model.create() and are accessible via Model static methods
|
|
3210
3208
|
for (const [modelName] of Object.entries(modelDefinitions)) {
|
|
3211
|
-
logger$
|
|
3209
|
+
logger$6('loadSchemaFromFile - model available:', modelName);
|
|
3212
3210
|
}
|
|
3213
3211
|
return schemaFilePath;
|
|
3214
3212
|
}
|
|
@@ -3295,7 +3293,7 @@ const jsonPropertiesToSchemaProperties = (modelName, modelDef, propertyFileIds)
|
|
|
3295
3293
|
*/
|
|
3296
3294
|
const createModelFromJson = async (modelName, modelDef, schemaName, modelFileId, // Optional modelFileId from JSON file
|
|
3297
3295
|
propertyFileIds) => {
|
|
3298
|
-
const _mod_11 = await import('./errors-
|
|
3296
|
+
const _mod_11 = await import('./errors-CIrbsN_i.js');
|
|
3299
3297
|
const _ns_11 = _mod_11.h;
|
|
3300
3298
|
const modelMod = _ns_11;
|
|
3301
3299
|
const { Model } = modelMod;
|
|
@@ -3304,10 +3302,10 @@ propertyFileIds) => {
|
|
|
3304
3302
|
// Pass id (schemaFileId) if provided to ensure Model instance uses correct ID
|
|
3305
3303
|
// Note: indexes and description are ignored - they remain in JSON for schema file format compliance but are not used by Model instances
|
|
3306
3304
|
if (modelFileId) {
|
|
3307
|
-
logger$
|
|
3305
|
+
logger$6(`Creating schema model "${modelName}" with modelFileId: ${modelFileId}`);
|
|
3308
3306
|
}
|
|
3309
3307
|
else {
|
|
3310
|
-
logger$
|
|
3308
|
+
logger$6(`Warning: Creating schema model "${modelName}" without modelFileId - it will be renamed if duplicates exist`);
|
|
3311
3309
|
}
|
|
3312
3310
|
const modelInstance = Model.create(modelName, schemaName, {
|
|
3313
3311
|
modelFileId: modelFileId, // Pass modelFileId (preferred) as id (schemaFileId) from JSON file
|
|
@@ -3333,7 +3331,7 @@ const createModelsFromJson = async (importData, modelFileIds, propertyFileIds) =
|
|
|
3333
3331
|
// Use modelFileId from map (no fallback to modelDef.id as JsonImportSchema doesn't have id property)
|
|
3334
3332
|
const finalModelFileId = modelFileId;
|
|
3335
3333
|
if (!finalModelFileId) {
|
|
3336
|
-
logger$
|
|
3334
|
+
logger$6(`Warning: No modelFileId found for model "${modelName}" - model will be created without ID`);
|
|
3337
3335
|
}
|
|
3338
3336
|
// Get propertyFileIds for this model if available
|
|
3339
3337
|
const modelPropertyFileIds = propertyFileIds?.get(modelName);
|
|
@@ -3523,7 +3521,7 @@ var SEEDPROTOCOL_Seed_Protocol_v1 = /*#__PURE__*/Object.freeze({
|
|
|
3523
3521
|
version: version
|
|
3524
3522
|
});
|
|
3525
3523
|
|
|
3526
|
-
const logger$
|
|
3524
|
+
const logger$5 = debug('seedSdk:client:actors:processSchemaFiles');
|
|
3527
3525
|
let processSchemaFilesChain = Promise.resolve();
|
|
3528
3526
|
function resolveSchemaFilePath(schemaFile) {
|
|
3529
3527
|
const path = BaseFileManager.getPathModule();
|
|
@@ -3551,7 +3549,7 @@ async function resolveSchemaNameFromSource(source) {
|
|
|
3551
3549
|
}
|
|
3552
3550
|
}
|
|
3553
3551
|
catch (error) {
|
|
3554
|
-
logger$
|
|
3552
|
+
logger$5('Could not resolve schema name from path:', source, error);
|
|
3555
3553
|
}
|
|
3556
3554
|
}
|
|
3557
3555
|
return null;
|
|
@@ -3566,7 +3564,7 @@ function userSchemaLoadError(option, source, error) {
|
|
|
3566
3564
|
// Schema processing can be slow with syncSchemaFromSource, loadAllSchemasFromDb, and OPFS file I/O
|
|
3567
3565
|
const PROCESS_SCHEMA_FILES_TIMEOUT_MS = 120000;
|
|
3568
3566
|
const processSchemaFiles = fromCallback(({ sendBack, input: { context } }) => {
|
|
3569
|
-
logger$
|
|
3567
|
+
logger$5('processSchemaFiles started');
|
|
3570
3568
|
let hasResponded = false;
|
|
3571
3569
|
let timeoutId = null;
|
|
3572
3570
|
const reportError = (error) => {
|
|
@@ -3576,7 +3574,7 @@ const processSchemaFiles = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
3576
3574
|
clearTimeout(timeoutId);
|
|
3577
3575
|
timeoutId = null;
|
|
3578
3576
|
}
|
|
3579
|
-
logger$
|
|
3577
|
+
logger$5('processSchemaFiles error:', error);
|
|
3580
3578
|
sendBack({
|
|
3581
3579
|
type: 'error',
|
|
3582
3580
|
error: error instanceof Error ? error : new Error(String(error))
|
|
@@ -3590,7 +3588,7 @@ const processSchemaFiles = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
3590
3588
|
clearTimeout(timeoutId);
|
|
3591
3589
|
timeoutId = null;
|
|
3592
3590
|
}
|
|
3593
|
-
logger$
|
|
3591
|
+
logger$5('processSchemaFiles completed');
|
|
3594
3592
|
sendBack({ type: ClientManagerEvents.PROCESS_SCHEMA_FILES_SUCCESS });
|
|
3595
3593
|
}
|
|
3596
3594
|
};
|
|
@@ -3602,7 +3600,7 @@ const processSchemaFiles = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
3602
3600
|
// Schemas written (or confirmed present) this run — skip redundant loadSchemaFromFile later
|
|
3603
3601
|
const schemasWrittenThisRun = new Set();
|
|
3604
3602
|
// First, load the internal seed-protocol schema
|
|
3605
|
-
logger$
|
|
3603
|
+
logger$5('Loading internal seed-protocol schema');
|
|
3606
3604
|
const internalSchemaData = internalSchema;
|
|
3607
3605
|
const db = BaseDb.getAppDb();
|
|
3608
3606
|
const internalSchemaExists = db
|
|
@@ -3611,21 +3609,21 @@ const processSchemaFiles = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
3611
3609
|
// Always mark internal schema as written so the DB/file loop does not re-apply it
|
|
3612
3610
|
schemasWrittenThisRun.add(SEED_PROTOCOL_SCHEMA_NAME);
|
|
3613
3611
|
if (internalSchemaExists) {
|
|
3614
|
-
logger$
|
|
3612
|
+
logger$5('Internal seed-protocol schema already in DB, skipping import');
|
|
3615
3613
|
}
|
|
3616
3614
|
else {
|
|
3617
3615
|
try {
|
|
3618
3616
|
// Import the internal schema to database (will create models and add to store)
|
|
3619
3617
|
await importJsonSchema({ contents: JSON.stringify(internalSchemaData) }, internalSchemaData.version);
|
|
3620
|
-
logger$
|
|
3618
|
+
logger$5(`Loaded internal seed-protocol schema v${internalSchemaData.version}`);
|
|
3621
3619
|
}
|
|
3622
3620
|
catch (error) {
|
|
3623
3621
|
// If schema already exists, that's fine - it means it was already loaded
|
|
3624
3622
|
if (error?.message?.includes('already exists')) {
|
|
3625
|
-
logger$
|
|
3623
|
+
logger$5('Internal seed-protocol schema already loaded');
|
|
3626
3624
|
}
|
|
3627
3625
|
else {
|
|
3628
|
-
logger$
|
|
3626
|
+
logger$5('Error loading internal seed-protocol schema:', error);
|
|
3629
3627
|
// Don't fail if internal schema can't be loaded - it might already be in DB
|
|
3630
3628
|
}
|
|
3631
3629
|
}
|
|
@@ -3638,7 +3636,7 @@ const processSchemaFiles = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
3638
3636
|
: '';
|
|
3639
3637
|
const schemaId = typeof context.schema === 'object' && context.schema?.id ? String(context.schema.id) : undefined;
|
|
3640
3638
|
if (isInternalSchema(schemaName, schemaId)) {
|
|
3641
|
-
logger$
|
|
3639
|
+
logger$5('Schema is internal (Seed Protocol), already loaded - skipping syncSchemaFromSource');
|
|
3642
3640
|
}
|
|
3643
3641
|
else {
|
|
3644
3642
|
try {
|
|
@@ -3647,7 +3645,7 @@ const processSchemaFiles = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
3647
3645
|
if (syncedName) {
|
|
3648
3646
|
schemasWrittenThisRun.add(syncedName);
|
|
3649
3647
|
}
|
|
3650
|
-
logger$
|
|
3648
|
+
logger$5(`Synced canonical schema from ${typeof context.schema === 'string' ? context.schema : 'object'}`);
|
|
3651
3649
|
}
|
|
3652
3650
|
catch (error) {
|
|
3653
3651
|
// A schema the app passed in failed (missing file, bad JSON, DB write). Re-running an
|
|
@@ -3666,7 +3664,7 @@ const processSchemaFiles = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
3666
3664
|
if (parsed?.metadata?.name) {
|
|
3667
3665
|
schemasWrittenThisRun.add(String(parsed.metadata.name));
|
|
3668
3666
|
}
|
|
3669
|
-
logger$
|
|
3667
|
+
logger$5(`Loaded schema from ${resolvedPath}`);
|
|
3670
3668
|
}
|
|
3671
3669
|
catch (error) {
|
|
3672
3670
|
throw userSchemaLoadError('schemaFile', context.schemaFile, error);
|
|
@@ -3674,14 +3672,14 @@ const processSchemaFiles = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
3674
3672
|
}
|
|
3675
3673
|
// Process minimal import files (files without $schema) - skip when canonical schema is set
|
|
3676
3674
|
if (!context.schema) {
|
|
3677
|
-
logger$
|
|
3675
|
+
logger$5('Listing schema files');
|
|
3678
3676
|
let schemaFiles = [];
|
|
3679
3677
|
try {
|
|
3680
3678
|
schemaFiles = await listSchemaFiles();
|
|
3681
|
-
logger$
|
|
3679
|
+
logger$5(`Found ${schemaFiles.length} schema files to process`);
|
|
3682
3680
|
}
|
|
3683
3681
|
catch (error) {
|
|
3684
|
-
logger$
|
|
3682
|
+
logger$5('Error listing schema files (continuing anyway):', error);
|
|
3685
3683
|
schemaFiles = [];
|
|
3686
3684
|
}
|
|
3687
3685
|
for (const schemaFile of schemaFiles) {
|
|
@@ -3692,19 +3690,19 @@ const processSchemaFiles = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
3692
3690
|
}
|
|
3693
3691
|
}
|
|
3694
3692
|
catch (error) {
|
|
3695
|
-
logger$
|
|
3693
|
+
logger$5(`Error importing schema file ${schemaFile.filePath}:`, error);
|
|
3696
3694
|
}
|
|
3697
3695
|
}
|
|
3698
3696
|
}
|
|
3699
3697
|
// Then, load all schemas using the unified database-first approach
|
|
3700
|
-
logger$
|
|
3698
|
+
logger$5('Loading schemas from database and files');
|
|
3701
3699
|
let allSchemasData = [];
|
|
3702
3700
|
try {
|
|
3703
3701
|
allSchemasData = await loadAllSchemasFromDb();
|
|
3704
|
-
logger$
|
|
3702
|
+
logger$5(`Loaded ${allSchemasData.length} schemas (${allSchemasData.filter(s => s.isDraft).length} drafts, ${allSchemasData.filter(s => !s.isDraft).length} published)`);
|
|
3705
3703
|
}
|
|
3706
3704
|
catch (error) {
|
|
3707
|
-
logger$
|
|
3705
|
+
logger$5('Error loading schemas from database (continuing anyway):', error);
|
|
3708
3706
|
// Continue with empty array - this is not critical for initialization
|
|
3709
3707
|
// Schemas can be loaded on-demand later
|
|
3710
3708
|
allSchemasData = [];
|
|
@@ -3725,13 +3723,13 @@ const processSchemaFiles = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
3725
3723
|
}
|
|
3726
3724
|
}
|
|
3727
3725
|
catch (error) {
|
|
3728
|
-
logger$
|
|
3726
|
+
logger$5('Error counting linked models (re-applying all schema files):', error);
|
|
3729
3727
|
}
|
|
3730
3728
|
}
|
|
3731
3729
|
for (const schemaData of allSchemasData) {
|
|
3732
3730
|
const schema = schemaData.schema;
|
|
3733
3731
|
const schemaName = schema.metadata?.name || 'unknown';
|
|
3734
|
-
logger$
|
|
3732
|
+
logger$5(`Processing schema: ${schemaName} v${schema.version} (${schemaData.isDraft ? 'draft' : 'published'}, source: ${schemaData.source})`);
|
|
3735
3733
|
// For published schemas (not drafts), load models from file if available
|
|
3736
3734
|
if (!schemaData.isDraft && schema.id) {
|
|
3737
3735
|
// loadAllSchemasFromDb already picked the latest file for this schema (and read it)
|
|
@@ -3761,7 +3759,7 @@ const processSchemaFiles = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
3761
3759
|
}
|
|
3762
3760
|
}
|
|
3763
3761
|
catch (error) {
|
|
3764
|
-
logger$
|
|
3762
|
+
logger$5(`Error loading schema file for ${schemaName}:`, error);
|
|
3765
3763
|
}
|
|
3766
3764
|
}
|
|
3767
3765
|
else {
|
|
@@ -3810,11 +3808,11 @@ const processSchemaFiles = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
3810
3808
|
};
|
|
3811
3809
|
const modelDefinitions = await createModelsFromJson(importData, modelFileIds, propertyFileIds);
|
|
3812
3810
|
Object.assign(allModels, modelDefinitions);
|
|
3813
|
-
logger$
|
|
3811
|
+
logger$5(`Loaded ${Object.keys(modelDefinitions).length} models from schema data for ${schemaName}`);
|
|
3814
3812
|
}
|
|
3815
3813
|
}
|
|
3816
3814
|
catch (error) {
|
|
3817
|
-
logger$
|
|
3815
|
+
logger$5(`Error creating models from schema data for ${schemaName}:`, error);
|
|
3818
3816
|
}
|
|
3819
3817
|
}
|
|
3820
3818
|
}
|
|
@@ -3864,11 +3862,11 @@ const processSchemaFiles = fromCallback(({ sendBack, input: { context } }) => {
|
|
|
3864
3862
|
};
|
|
3865
3863
|
const modelDefinitions = await createModelsFromJson(importData, modelFileIds, propertyFileIds);
|
|
3866
3864
|
Object.assign(allModels, modelDefinitions);
|
|
3867
|
-
logger$
|
|
3865
|
+
logger$5(`Loaded ${Object.keys(modelDefinitions).length} models from draft schema ${schemaName}`);
|
|
3868
3866
|
}
|
|
3869
3867
|
}
|
|
3870
3868
|
catch (error) {
|
|
3871
|
-
logger$
|
|
3869
|
+
logger$5(`Error creating models from draft schema ${schemaName}:`, error);
|
|
3872
3870
|
}
|
|
3873
3871
|
}
|
|
3874
3872
|
// Schemas are now loaded on-demand via database queries (useSchemas hook uses loadAllSchemasFromDb)
|
|
@@ -3965,7 +3963,7 @@ const convertVerbatimItemStorageRow = async (localId, storage = {}) => {
|
|
|
3965
3963
|
});
|
|
3966
3964
|
};
|
|
3967
3965
|
|
|
3968
|
-
const logger$
|
|
3966
|
+
const logger$4 = debug('seedSdk:db:migrateLegacyItemStorageRows');
|
|
3969
3967
|
/** appState key recording that legacy ItemStorage rows have been written to their files. */
|
|
3970
3968
|
const LEGACY_ITEM_STORAGE_MIGRATION_KEY = 'legacyItemStorageFiles:v1';
|
|
3971
3969
|
/** Runs in a row that left rows unconverted because a file write failed, before giving up. */
|
|
@@ -4119,7 +4117,7 @@ async function migrateLegacyItemStorageRows(options = {}) {
|
|
|
4119
4117
|
});
|
|
4120
4118
|
if (converted) {
|
|
4121
4119
|
result.converted++;
|
|
4122
|
-
logger$
|
|
4120
|
+
logger$4(`wrote ${row.propertyName} of ${row.seedLocalId} to ${converted.filePath}`);
|
|
4123
4121
|
}
|
|
4124
4122
|
else {
|
|
4125
4123
|
result.skipped++;
|
|
@@ -4127,7 +4125,7 @@ async function migrateLegacyItemStorageRows(options = {}) {
|
|
|
4127
4125
|
}
|
|
4128
4126
|
catch (error) {
|
|
4129
4127
|
result.failed++;
|
|
4130
|
-
logger$
|
|
4128
|
+
logger$4(`converting ${row.propertyName} of ${row.seedLocalId} (${row.localId}) failed; left as is`, error);
|
|
4131
4129
|
}
|
|
4132
4130
|
}
|
|
4133
4131
|
const attempts = previousAttempts + 1;
|
|
@@ -4139,24 +4137,24 @@ async function migrateLegacyItemStorageRows(options = {}) {
|
|
|
4139
4137
|
at: Date.now(),
|
|
4140
4138
|
});
|
|
4141
4139
|
if (result.candidates > 0) {
|
|
4142
|
-
logger$
|
|
4140
|
+
logger$4(`legacy ItemStorage rows: ${result.converted} converted, ${result.failed} failed, ` +
|
|
4143
4141
|
`${result.skipped} skipped of ${result.candidates}`);
|
|
4144
4142
|
}
|
|
4145
4143
|
return result;
|
|
4146
4144
|
}
|
|
4147
|
-
let running$
|
|
4148
|
-
let deferredUntilLeader$
|
|
4149
|
-
const runInBackground$
|
|
4150
|
-
running$
|
|
4145
|
+
let running$3;
|
|
4146
|
+
let deferredUntilLeader$3 = false;
|
|
4147
|
+
const runInBackground$3 = () => {
|
|
4148
|
+
running$3 ?? (running$3 = withDbTabLock('item-storage-migration', () => migrateLegacyItemStorageRows())
|
|
4151
4149
|
.then(() => undefined)
|
|
4152
4150
|
.catch((error) => {
|
|
4153
4151
|
// Never fails init: rows stay as they were and publish converts them lazily.
|
|
4154
|
-
logger$
|
|
4152
|
+
logger$4('legacy ItemStorage migration failed', error);
|
|
4155
4153
|
})
|
|
4156
4154
|
.finally(() => {
|
|
4157
|
-
running$
|
|
4155
|
+
running$3 = undefined;
|
|
4158
4156
|
}));
|
|
4159
|
-
return running$
|
|
4157
|
+
return running$3;
|
|
4160
4158
|
};
|
|
4161
4159
|
/**
|
|
4162
4160
|
* Starts {@link migrateLegacyItemStorageRows} in the background once client init has finished
|
|
@@ -4166,19 +4164,19 @@ const runInBackground$2 = () => {
|
|
|
4166
4164
|
*/
|
|
4167
4165
|
function startLegacyItemStorageMigration() {
|
|
4168
4166
|
if (isLeaderTab()) {
|
|
4169
|
-
void runInBackground$
|
|
4167
|
+
void runInBackground$3();
|
|
4170
4168
|
return;
|
|
4171
4169
|
}
|
|
4172
|
-
if (deferredUntilLeader$
|
|
4170
|
+
if (deferredUntilLeader$3)
|
|
4173
4171
|
return;
|
|
4174
|
-
deferredUntilLeader$
|
|
4172
|
+
deferredUntilLeader$3 = true;
|
|
4175
4173
|
void whenLeaderTab().then(() => {
|
|
4176
|
-
deferredUntilLeader$
|
|
4177
|
-
void runInBackground$
|
|
4174
|
+
deferredUntilLeader$3 = false;
|
|
4175
|
+
void runInBackground$3();
|
|
4178
4176
|
});
|
|
4179
4177
|
}
|
|
4180
4178
|
|
|
4181
|
-
const logger$
|
|
4179
|
+
const logger$3 = debug('seedSdk:db:removeForeignAttestationRows');
|
|
4182
4180
|
/** appState key recording that the cleanup below has run on this database. */
|
|
4183
4181
|
const FOREIGN_ATTESTATION_CLEANUP_KEY = 'foreignAttestationRowsRemoved';
|
|
4184
4182
|
/** Lowercased `attester` of a stored attestation JSON; NULL when the JSON is invalid or has none. */
|
|
@@ -4220,7 +4218,7 @@ async function removeForeignAttestationRows() {
|
|
|
4220
4218
|
return { versionRows: foreignVersionUids.length, propertyRows };
|
|
4221
4219
|
}
|
|
4222
4220
|
/** Runs the cleanup unless this database has had it, and records that it has. */
|
|
4223
|
-
async function runOnce() {
|
|
4221
|
+
async function runOnce$1() {
|
|
4224
4222
|
const appDb = BaseDb.getAppDb();
|
|
4225
4223
|
const marker = await appDb
|
|
4226
4224
|
.select()
|
|
@@ -4236,22 +4234,22 @@ async function runOnce() {
|
|
|
4236
4234
|
.values({ key: FOREIGN_ATTESTATION_CLEANUP_KEY, value })
|
|
4237
4235
|
.onConflictDoUpdate({ target: appState.key, set: { value } });
|
|
4238
4236
|
if (result.versionRows > 0 || result.propertyRows > 0) {
|
|
4239
|
-
logger$
|
|
4237
|
+
logger$3(`removed ${result.versionRows} version and ${result.propertyRows} property rows from other attesters`);
|
|
4240
4238
|
}
|
|
4241
4239
|
}
|
|
4242
|
-
let running$
|
|
4243
|
-
let deferredUntilLeader$
|
|
4244
|
-
const runInBackground$
|
|
4240
|
+
let running$2;
|
|
4241
|
+
let deferredUntilLeader$2 = false;
|
|
4242
|
+
const runInBackground$2 = () => {
|
|
4245
4243
|
// Under the sync's lock, so it can't interleave with a sync writing the same rows.
|
|
4246
|
-
running$
|
|
4244
|
+
running$2 ?? (running$2 = withDbTabLock('eas-sync', runOnce$1, { timeoutMs: Infinity })
|
|
4247
4245
|
.catch((error) => {
|
|
4248
4246
|
// Never fails init: the rows stay until the next sync of their seeds removes them.
|
|
4249
|
-
logger$
|
|
4247
|
+
logger$3('foreign attestation cleanup failed', error);
|
|
4250
4248
|
})
|
|
4251
4249
|
.finally(() => {
|
|
4252
|
-
running$
|
|
4250
|
+
running$2 = undefined;
|
|
4253
4251
|
}));
|
|
4254
|
-
return running$
|
|
4252
|
+
return running$2;
|
|
4255
4253
|
};
|
|
4256
4254
|
/**
|
|
4257
4255
|
* Starts {@link removeForeignAttestationRows} in the background after client init, once per
|
|
@@ -4260,6 +4258,123 @@ const runInBackground$1 = () => {
|
|
|
4260
4258
|
* tab only (docs/MULTI_TAB.md); a tab that isn't leader runs it if it takes over. Never throws.
|
|
4261
4259
|
*/
|
|
4262
4260
|
function startForeignAttestationCleanup() {
|
|
4261
|
+
if (isLeaderTab()) {
|
|
4262
|
+
void runInBackground$2();
|
|
4263
|
+
return;
|
|
4264
|
+
}
|
|
4265
|
+
if (deferredUntilLeader$2)
|
|
4266
|
+
return;
|
|
4267
|
+
deferredUntilLeader$2 = true;
|
|
4268
|
+
void whenLeaderTab().then(() => {
|
|
4269
|
+
deferredUntilLeader$2 = false;
|
|
4270
|
+
void runInBackground$2();
|
|
4271
|
+
});
|
|
4272
|
+
}
|
|
4273
|
+
|
|
4274
|
+
const logger$2 = debug('seedSdk:db:alignRowPublishers');
|
|
4275
|
+
/** appState key recording that the fix below has run on this database. */
|
|
4276
|
+
const ROW_PUBLISHERS_ALIGNED_KEY = 'rowPublishersAligned';
|
|
4277
|
+
/**
|
|
4278
|
+
* Gives version and property rows their seed's publisher. Before, edits wrote property rows with no
|
|
4279
|
+
* publisher, and versions and property rows took the session's publisher rather than the seed's,
|
|
4280
|
+
* so connecting another wallet could claim rows of a seed that already had one. Local query reads
|
|
4281
|
+
* report a row's publisher as its attester and leave out rows whose attester isn't their parent's.
|
|
4282
|
+
*
|
|
4283
|
+
* Only rows without a stored attestation are changed: synced rows carry their attester in
|
|
4284
|
+
* `attestation_raw`. When the seed belongs to no wallet yet, its unsealed rows lose any publisher,
|
|
4285
|
+
* so they're claimed with it.
|
|
4286
|
+
*/
|
|
4287
|
+
async function alignRowPublishers() {
|
|
4288
|
+
const appDb = BaseDb.getAppDb();
|
|
4289
|
+
const align = async (table) => {
|
|
4290
|
+
const rows = (await appDb
|
|
4291
|
+
.select({
|
|
4292
|
+
localId: table.localId,
|
|
4293
|
+
uid: table.uid,
|
|
4294
|
+
publisher: table.publisher,
|
|
4295
|
+
seedPublisher: seeds.publisher,
|
|
4296
|
+
seedAttestationRaw: seeds.attestationRaw,
|
|
4297
|
+
seedUid: seeds.uid,
|
|
4298
|
+
attestationRaw: table.attestationRaw,
|
|
4299
|
+
})
|
|
4300
|
+
.from(table)
|
|
4301
|
+
.innerJoin(seeds, eq(seeds.localId, table.seedLocalId)));
|
|
4302
|
+
const byTarget = new Map();
|
|
4303
|
+
for (const row of rows) {
|
|
4304
|
+
if (!row.localId || (row.attestationRaw != null && row.attestationRaw !== ''))
|
|
4305
|
+
continue;
|
|
4306
|
+
const seedPublisher = normalizePublisher(resolvePublisherFromSeedRow({
|
|
4307
|
+
publisher: row.seedPublisher,
|
|
4308
|
+
attestationRaw: row.seedAttestationRaw,
|
|
4309
|
+
uid: row.seedUid,
|
|
4310
|
+
}));
|
|
4311
|
+
const current = normalizePublisher(row.publisher);
|
|
4312
|
+
let target;
|
|
4313
|
+
if (seedPublisher) {
|
|
4314
|
+
if (current === seedPublisher)
|
|
4315
|
+
continue;
|
|
4316
|
+
target = seedPublisher;
|
|
4317
|
+
}
|
|
4318
|
+
else {
|
|
4319
|
+
// A seed with no wallet yet: its unsealed rows go with it when it's claimed.
|
|
4320
|
+
if (!current || !isPlaceholderUid(row.uid))
|
|
4321
|
+
continue;
|
|
4322
|
+
target = null;
|
|
4323
|
+
}
|
|
4324
|
+
const ids = byTarget.get(target) ?? [];
|
|
4325
|
+
ids.push(row.localId);
|
|
4326
|
+
byTarget.set(target, ids);
|
|
4327
|
+
}
|
|
4328
|
+
let changed = 0;
|
|
4329
|
+
for (const [target, ids] of byTarget) {
|
|
4330
|
+
await writeInBatches(ids, (chunk) => appDb.update(table).set({ publisher: target }).where(inArray(table.localId, chunk)));
|
|
4331
|
+
changed += ids.length;
|
|
4332
|
+
}
|
|
4333
|
+
return changed;
|
|
4334
|
+
};
|
|
4335
|
+
const versionRows = await align(versions);
|
|
4336
|
+
const propertyRows = await align(metadata$1);
|
|
4337
|
+
return { versionRows, propertyRows };
|
|
4338
|
+
}
|
|
4339
|
+
/** Runs the fix unless this database has had it, and records that it has. */
|
|
4340
|
+
async function runOnce() {
|
|
4341
|
+
const appDb = BaseDb.getAppDb();
|
|
4342
|
+
const marker = await appDb
|
|
4343
|
+
.select()
|
|
4344
|
+
.from(appState)
|
|
4345
|
+
.where(eq(appState.key, ROW_PUBLISHERS_ALIGNED_KEY))
|
|
4346
|
+
.limit(1);
|
|
4347
|
+
if (marker.length > 0)
|
|
4348
|
+
return;
|
|
4349
|
+
const result = await alignRowPublishers();
|
|
4350
|
+
const value = JSON.stringify({ ...result, at: Date.now() });
|
|
4351
|
+
await appDb
|
|
4352
|
+
.insert(appState)
|
|
4353
|
+
.values({ key: ROW_PUBLISHERS_ALIGNED_KEY, value })
|
|
4354
|
+
.onConflictDoUpdate({ target: appState.key, set: { value } });
|
|
4355
|
+
if (result.versionRows > 0 || result.propertyRows > 0) {
|
|
4356
|
+
logger$2(`gave ${result.versionRows} version and ${result.propertyRows} property rows their seed's publisher`);
|
|
4357
|
+
}
|
|
4358
|
+
}
|
|
4359
|
+
let running$1;
|
|
4360
|
+
let deferredUntilLeader$1 = false;
|
|
4361
|
+
const runInBackground$1 = () => {
|
|
4362
|
+
// Under the sync's lock: sync writes these rows too.
|
|
4363
|
+
running$1 ?? (running$1 = withDbTabLock('eas-sync', runOnce, { timeoutMs: Infinity })
|
|
4364
|
+
.catch((error) => {
|
|
4365
|
+
// Never fails init: the rows keep their old publisher.
|
|
4366
|
+
logger$2('row publisher fix failed', error);
|
|
4367
|
+
})
|
|
4368
|
+
.finally(() => {
|
|
4369
|
+
running$1 = undefined;
|
|
4370
|
+
}));
|
|
4371
|
+
return running$1;
|
|
4372
|
+
};
|
|
4373
|
+
/**
|
|
4374
|
+
* Starts {@link alignRowPublishers} in the background after client init, once per database, like
|
|
4375
|
+
* the foreign-attestation cleanup. Leader tab only (docs/MULTI_TAB.md). Never throws.
|
|
4376
|
+
*/
|
|
4377
|
+
function startAlignRowPublishers() {
|
|
4263
4378
|
if (isLeaderTab()) {
|
|
4264
4379
|
void runInBackground$1();
|
|
4265
4380
|
return;
|
|
@@ -4580,6 +4695,8 @@ const clientManagerMachine = setup({
|
|
|
4580
4695
|
() => startLegacyItemStorageMigration(),
|
|
4581
4696
|
// Also once, in the background: rows an older sync stored from other accounts' attestations.
|
|
4582
4697
|
() => startForeignAttestationCleanup(),
|
|
4698
|
+
// Also once: version and property rows get their seed's publisher (rows from older edits had none).
|
|
4699
|
+
() => startAlignRowPublishers(),
|
|
4583
4700
|
// Stored model types to the ADR 0008 form (html_page), so exact type filters find old rows.
|
|
4584
4701
|
() => startCanonicalizeModelTypes(),
|
|
4585
4702
|
],
|
|
@@ -5193,8 +5310,10 @@ const emptyResult = () => ({
|
|
|
5193
5310
|
seedLocalIds: [],
|
|
5194
5311
|
});
|
|
5195
5312
|
/**
|
|
5196
|
-
*
|
|
5197
|
-
*
|
|
5313
|
+
* Gives `publisher` to local drafts that belong to no wallet yet: seeds with no publisher, no real
|
|
5314
|
+
* uid and no attestationRaw, and those seeds' versions and property rows that are unsealed too.
|
|
5315
|
+
* Versions and property rows go only with their seed, so rows of a seed that already has a
|
|
5316
|
+
* publisher are never claimed. Sealed rows (real EAS uid or attestationRaw) are never touched.
|
|
5198
5317
|
*/
|
|
5199
5318
|
async function claimUnpublishedDrafts(publisher) {
|
|
5200
5319
|
const normalized = normalizePublisher(publisher);
|
|
@@ -5204,33 +5323,38 @@ async function claimUnpublishedDrafts(publisher) {
|
|
|
5204
5323
|
if (!appDb)
|
|
5205
5324
|
return emptyResult();
|
|
5206
5325
|
const now = Date.now();
|
|
5207
|
-
const
|
|
5208
|
-
|
|
5326
|
+
const isClaimable = (row) => typeof row.localId === 'string' && row.localId !== '' && isLocalUnsealedDraft(row);
|
|
5327
|
+
const stamp = async (table, ids) => {
|
|
5328
|
+
await writeInBatches(ids, (chunk) => appDb.update(table).set({ publisher: normalized, updatedAt: now }).where(inArray(table.localId, chunk)));
|
|
5329
|
+
};
|
|
5330
|
+
const seedRows = (await appDb
|
|
5331
|
+
.select({
|
|
5332
|
+
localId: seeds.localId,
|
|
5333
|
+
uid: seeds.uid,
|
|
5334
|
+
publisher: seeds.publisher,
|
|
5335
|
+
attestationRaw: seeds.attestationRaw,
|
|
5336
|
+
})
|
|
5337
|
+
.from(seeds));
|
|
5338
|
+
const seedIds = seedRows.filter(isClaimable).map((row) => row.localId);
|
|
5339
|
+
if (seedIds.length === 0)
|
|
5340
|
+
return emptyResult();
|
|
5341
|
+
const claimChildren = async (table) => {
|
|
5342
|
+
const rows = (await selectInBatches(seedIds, (chunk) => appDb
|
|
5209
5343
|
.select({
|
|
5210
5344
|
localId: table.localId,
|
|
5211
5345
|
uid: table.uid,
|
|
5212
5346
|
publisher: table.publisher,
|
|
5213
5347
|
attestationRaw: table.attestationRaw,
|
|
5214
5348
|
})
|
|
5215
|
-
.from(table)
|
|
5216
|
-
|
|
5217
|
-
|
|
5218
|
-
|
|
5219
|
-
isLocalUnsealedDraft(row))
|
|
5220
|
-
.map((row) => row.localId);
|
|
5221
|
-
if (ids.length === 0)
|
|
5222
|
-
return [];
|
|
5223
|
-
await appDb
|
|
5224
|
-
.update(table)
|
|
5225
|
-
.set({ publisher: normalized, updatedAt: now })
|
|
5226
|
-
.where(inArray(table.localId, ids));
|
|
5349
|
+
.from(table)
|
|
5350
|
+
.where(inArray(table.seedLocalId, chunk))));
|
|
5351
|
+
const ids = rows.filter(isClaimable).map((row) => row.localId);
|
|
5352
|
+
await stamp(table, ids);
|
|
5227
5353
|
return ids;
|
|
5228
5354
|
};
|
|
5229
|
-
|
|
5230
|
-
|
|
5231
|
-
|
|
5232
|
-
claimTable(metadata$1),
|
|
5233
|
-
]);
|
|
5355
|
+
await stamp(seeds, seedIds);
|
|
5356
|
+
const versionIds = await claimChildren(versions);
|
|
5357
|
+
const metadataIds = await claimChildren(metadata$1);
|
|
5234
5358
|
return {
|
|
5235
5359
|
seeds: seedIds.length,
|
|
5236
5360
|
versions: versionIds.length,
|
|
@@ -5240,19 +5364,24 @@ async function claimUnpublishedDrafts(publisher) {
|
|
|
5240
5364
|
}
|
|
5241
5365
|
|
|
5242
5366
|
const logger = debug('seedSdk:client');
|
|
5243
|
-
const
|
|
5244
|
-
|
|
5245
|
-
|
|
5246
|
-
|
|
5247
|
-
|
|
5248
|
-
|
|
5249
|
-
|
|
5250
|
-
}
|
|
5251
|
-
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
|
|
5255
|
-
|
|
5367
|
+
const createClientManager = () => {
|
|
5368
|
+
const actor = createActor(clientManagerMachine, {
|
|
5369
|
+
input: {
|
|
5370
|
+
isInitialized: false,
|
|
5371
|
+
addressesSet: false,
|
|
5372
|
+
isSaving: false,
|
|
5373
|
+
syncFromEasOnAddressChange: false,
|
|
5374
|
+
}
|
|
5375
|
+
});
|
|
5376
|
+
const actorSubscription = actor.subscribe((snapshot) => {
|
|
5377
|
+
logger('ClientManager snapshot.value:', snapshot.value);
|
|
5378
|
+
logger('ClientManager snapshot.context.isInitialized:', snapshot.context.isInitialized);
|
|
5379
|
+
});
|
|
5380
|
+
actor.start();
|
|
5381
|
+
return { actor, actorSubscription };
|
|
5382
|
+
};
|
|
5383
|
+
// Replaced when init runs after stop(): an xstate actor can't be started again once stopped.
|
|
5384
|
+
let { actor: clientManager, actorSubscription: subscription } = createClientManager();
|
|
5256
5385
|
/** Config of the init that is running or has succeeded; cleared when init fails or the client stops. */
|
|
5257
5386
|
let activeInitConfig;
|
|
5258
5387
|
const INIT_CONFIG_CONFLICT_MESSAGE = 'client.init was already called with a different config. The SDK keeps the config it was ' +
|
|
@@ -5269,19 +5398,13 @@ const coalescedInit = createCoalescedAsync(async (options) => {
|
|
|
5269
5398
|
const currentState = snapshot.value;
|
|
5270
5399
|
const isStopped = snapshot.status === 'stopped';
|
|
5271
5400
|
if (isStopped) {
|
|
5272
|
-
|
|
5273
|
-
|
|
5274
|
-
|
|
5275
|
-
try {
|
|
5276
|
-
await waitFor(clientManager, (snapshot) => snapshot.status !== 'stopped', { timeout: 1000 });
|
|
5277
|
-
}
|
|
5278
|
-
catch (e) {
|
|
5279
|
-
logger('Timeout waiting for actor to restart, continuing anyway...');
|
|
5280
|
-
}
|
|
5401
|
+
// stop() (or a failed test) stopped it: start over with a new actor and a clean context.
|
|
5402
|
+
logger('Client manager was stopped, creating a new one');
|
|
5403
|
+
({ actor: clientManager, actorSubscription: subscription } = createClientManager());
|
|
5281
5404
|
}
|
|
5282
5405
|
// Clear any stale context from previous failed initializations
|
|
5283
5406
|
// This ensures we start with a clean slate before the new init updates it
|
|
5284
|
-
if (currentState !== 'uninitialized') {
|
|
5407
|
+
if (!isStopped && currentState !== 'uninitialized') {
|
|
5285
5408
|
logger(`Client manager is in state ${currentState}, clearing stale context before re-init...`);
|
|
5286
5409
|
clientManager.send({
|
|
5287
5410
|
type: 'updateContext',
|
|
@@ -5340,7 +5463,9 @@ const coalescedInit = createCoalescedAsync(async (options) => {
|
|
|
5340
5463
|
registerSeedQueryLocalSource({ force: true });
|
|
5341
5464
|
}, () => {
|
|
5342
5465
|
const snapshot = clientManager.getSnapshot();
|
|
5343
|
-
|
|
5466
|
+
// A stopped client keeps its last state and context: init must run again, not be skipped.
|
|
5467
|
+
return (snapshot.status === 'active' &&
|
|
5468
|
+
snapshot.value === ClientManagerState.IDLE &&
|
|
5344
5469
|
snapshot.context.isInitialized === true &&
|
|
5345
5470
|
!snapshot.context.initError);
|
|
5346
5471
|
});
|
|
@@ -5348,7 +5473,8 @@ const coalescedInit = createCoalescedAsync(async (options) => {
|
|
|
5348
5473
|
// ES modules cache exports, ensuring all imports get the same instance
|
|
5349
5474
|
const clientInstance = {
|
|
5350
5475
|
isInitialized: () => {
|
|
5351
|
-
|
|
5476
|
+
const snapshot = clientManager.getSnapshot();
|
|
5477
|
+
return snapshot.status === 'active' && snapshot.context.isInitialized;
|
|
5352
5478
|
},
|
|
5353
5479
|
getService: () => {
|
|
5354
5480
|
// ensureInitialized();
|
|
@@ -5520,9 +5646,9 @@ var ClientManager$1 = /*#__PURE__*/Object.freeze({
|
|
|
5520
5646
|
__proto__: null,
|
|
5521
5647
|
ClientManager: ClientManager,
|
|
5522
5648
|
INIT_CONFIG_CONFLICT_MESSAGE: INIT_CONFIG_CONFLICT_MESSAGE,
|
|
5523
|
-
clientManager
|
|
5649
|
+
get clientManager () { return clientManager; },
|
|
5524
5650
|
getClient: getClient
|
|
5525
5651
|
});
|
|
5526
5652
|
|
|
5527
|
-
export {
|
|
5528
|
-
//# sourceMappingURL=ClientManager-
|
|
5653
|
+
export { requestEasSyncFromEventBus as A, requestEasSyncFromModelsInit as B, ClientManager as C, sendEasSyncClientRequest as D, EAS_CHAIN_ID_APP_STATE_KEY as E, setRetriesWhenOnlineEnabled as F, startEasSyncActor as G, unregisterSeedQueryLocalSource as H, INIT_CONFIG_CONFLICT_MESSAGE as I, createModelsFromJson as J, getLatestSchemaVersion as K, jsonPropertiesToSchemaProperties as L, schema as M, ClientManager$1 as N, SEEDPROTOCOL_Seed_Protocol_v1 as S, getContentHash as a, isVerbatimItemStorageDraftRow as b, convertVerbatimItemStorageRow as c, assertLocalDbChain as d, claimUnpublishedDrafts as e, createLocalQueryDataSource as f, getRefValueType as g, hardDeleteLocalSeedsByLocalIds as h, importJsonSchema as i, createSchema as j, easSyncActor as k, loadSchemaFromFile as l, getClient as m, getPublishedSeedRecord as n, getSchemaNameFromId as o, isSeedQueryLocalSourceRegistered as p, listCompleteSchemaFiles as q, readJsonImportFile as r, syncSchemaFromSource as s, transformImportToSchemaFile as t, loadAllSchemasFromDb as u, mergeEasSyncRequestIntents as v, waitForEasReadChain as w, readSchema as x, registerSeedQueryLocalSource as y, requestEasSyncFromAddressChange as z };
|
|
5654
|
+
//# sourceMappingURL=ClientManager-DRf4uuei.js.map
|