@seedprotocol/sdk 0.7.3-next.654.g52217f6 → 0.7.3

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.
Files changed (187) hide show
  1. package/dist/{db-D9K_f5cF.js → BasePathResolver-Cm4apKRb.js} +2041 -127
  2. package/dist/BasePathResolver-Cm4apKRb.js.map +1 -0
  3. package/dist/{ClientManager-C-QXqUK9.js → ClientManager-i3nJASkg.js} +249 -147
  4. package/dist/ClientManager-i3nJASkg.js.map +1 -0
  5. package/dist/{Item-C7sUUu2B.js → Item-DBFchXpC.js} +259 -169
  6. package/dist/Item-DBFchXpC.js.map +1 -0
  7. package/dist/{ModelProperty-DJxeOOrc.js → ModelProperty-BS49g01Y.js} +166 -47
  8. package/dist/ModelProperty-BS49g01Y.js.map +1 -0
  9. package/dist/{Schema-fXtvd-yL.js → Schema-CpMNEnUO.js} +53 -42
  10. package/dist/Schema-CpMNEnUO.js.map +1 -0
  11. package/dist/{SchemaValidationService-CvRS2HSO.js → SchemaValidationService-DieV4KL-.js} +15 -17
  12. package/dist/{SchemaValidationService-CvRS2HSO.js.map → SchemaValidationService-DieV4KL-.js.map} +1 -1
  13. package/dist/{backfillMetadataPropertyIds-SXW-8C64.js → backfillMetadataPropertyIds-DSoOoTnX.js} +14 -7
  14. package/dist/{backfillMetadataPropertyIds-SXW-8C64.js.map → backfillMetadataPropertyIds-DSoOoTnX.js.map} +1 -1
  15. package/dist/{configurePlatform-BRw2j0ZN.js → configurePlatform-D0lQGAMQ.js} +5 -7
  16. package/dist/{configurePlatform-BRw2j0ZN.js.map → configurePlatform-D0lQGAMQ.js.map} +1 -1
  17. package/dist/detachRowsBeforeDelete-S0q-DJPT.js +50 -0
  18. package/dist/detachRowsBeforeDelete-S0q-DJPT.js.map +1 -0
  19. package/dist/{eas-DHxfswCt.js → eas-6pjU-OuX.js} +6 -8
  20. package/dist/eas-6pjU-OuX.js.map +1 -0
  21. package/dist/{getItem-d6N_aM6S.js → getItem-CxBNZ-WL.js} +10 -11
  22. package/dist/{getItem-d6N_aM6S.js.map → getItem-CxBNZ-WL.js.map} +1 -1
  23. package/dist/{getPublishPayload-BHrxVtzY.js → getPublishPayload-CTCvRUoU.js} +50 -18
  24. package/dist/getPublishPayload-CTCvRUoU.js.map +1 -0
  25. package/dist/{getPublishUploads-BEqRiKIS.js → getPublishUploads-SFHCbf_y.js} +13 -22
  26. package/dist/{getPublishUploads-BEqRiKIS.js.map → getPublishUploads-SFHCbf_y.js.map} +1 -1
  27. package/dist/{index-s15q14rm.js → index-8O3Uow-Y.js} +125 -57
  28. package/dist/index-8O3Uow-Y.js.map +1 -0
  29. package/dist/{index-DglvthOk.js → index-AVFTVp1m.js} +2 -2
  30. package/dist/index-AVFTVp1m.js.map +1 -0
  31. package/dist/index-Cvt5UBz4.js +30 -0
  32. package/dist/index-Cvt5UBz4.js.map +1 -0
  33. package/dist/{index.browser-Cm06tP4X.js → index.browser-DBhxRoe8.js} +11 -10
  34. package/dist/{index.browser-Cm06tP4X.js.map → index.browser-DBhxRoe8.js.map} +1 -1
  35. package/dist/{index.node-C30dmFgn.js → index.node-CJhlcNHM.js} +25 -13
  36. package/dist/index.node-CJhlcNHM.js.map +1 -0
  37. package/dist/main.js +27 -32
  38. package/dist/main.js.map +1 -1
  39. package/dist/node.js +19 -22
  40. package/dist/node.js.map +1 -1
  41. package/dist/platform.browser.js +9 -9
  42. package/dist/platform.node.js +18 -5
  43. package/dist/platform.node.js.map +1 -1
  44. package/dist/{property-DhmmYAvQ.js → property-DwPD283A.js} +11 -12
  45. package/dist/property-DwPD283A.js.map +1 -0
  46. package/dist/{publishDraftGraph-yYP74WRt.js → publishDraftGraph-BOn3_Occ.js} +6 -9
  47. package/dist/{publishDraftGraph-yYP74WRt.js.map → publishDraftGraph-BOn3_Occ.js.map} +1 -1
  48. package/dist/{resetAmbiguousLegacyItemData-Bk0QyDW8.js → resetAmbiguousLegacyItemData-BkYmBeJc.js} +14 -3
  49. package/dist/{resetAmbiguousLegacyItemData-Bk0QyDW8.js.map → resetAmbiguousLegacyItemData-BkYmBeJc.js.map} +1 -1
  50. package/dist/{resolveModelForSyncedSeed-8cAzvUFd.js → resolveModelForSyncedSeed-BL24nLa7.js} +2 -2
  51. package/dist/{resolveModelForSyncedSeed-8cAzvUFd.js.map → resolveModelForSyncedSeed-BL24nLa7.js.map} +1 -1
  52. package/dist/src/Item/Item.d.ts +20 -2
  53. package/dist/src/Item/Item.d.ts.map +1 -1
  54. package/dist/src/Item/service/actors/runPublish.d.ts +11 -2
  55. package/dist/src/Item/service/actors/runPublish.d.ts.map +1 -1
  56. package/dist/src/Item/service/itemMachineSingle.d.ts +12 -2
  57. package/dist/src/Item/service/itemMachineSingle.d.ts.map +1 -1
  58. package/dist/src/ItemProperty/ItemProperty.d.ts +5 -3
  59. package/dist/src/ItemProperty/ItemProperty.d.ts.map +1 -1
  60. package/dist/src/ItemProperty/service/actors/saveValueToDb/analyzeInput.d.ts.map +1 -1
  61. package/dist/src/ItemProperty/service/propertyMachine.d.ts.map +1 -1
  62. package/dist/src/Model/Model.d.ts +10 -4
  63. package/dist/src/Model/Model.d.ts.map +1 -1
  64. package/dist/src/Model/index.d.ts +2 -2
  65. package/dist/src/ModelProperty/ModelProperty.d.ts +10 -2
  66. package/dist/src/ModelProperty/ModelProperty.d.ts.map +1 -1
  67. package/dist/src/ModelProperty/service/modelPropertyMachine.d.ts +3 -0
  68. package/dist/src/ModelProperty/service/modelPropertyMachine.d.ts.map +1 -1
  69. package/dist/src/Schema/Schema.d.ts +2 -2
  70. package/dist/src/Schema/Schema.d.ts.map +1 -1
  71. package/dist/src/Schema/index.d.ts +0 -1
  72. package/dist/src/Schema/index.d.ts.map +1 -1
  73. package/dist/src/client/ClientManager.d.ts +30 -11
  74. package/dist/src/client/ClientManager.d.ts.map +1 -1
  75. package/dist/src/client/actors/platformClassesInit.d.ts +6 -0
  76. package/dist/src/client/actors/platformClassesInit.d.ts.map +1 -1
  77. package/dist/src/client/actors/processSchemaFiles.d.ts.map +1 -1
  78. package/dist/src/client/actors/saveConfig.d.ts +13 -6
  79. package/dist/src/client/actors/saveConfig.d.ts.map +1 -1
  80. package/dist/src/db/read/getPublishPayload.d.ts +1 -1
  81. package/dist/src/db/read/getPublishPayload.d.ts.map +1 -1
  82. package/dist/src/db/write/claimUnpublishedDrafts.d.ts +2 -0
  83. package/dist/src/db/write/claimUnpublishedDrafts.d.ts.map +1 -1
  84. package/dist/src/eventBus.d.ts +5 -0
  85. package/dist/src/eventBus.d.ts.map +1 -1
  86. package/dist/src/helpers/cachedPropertyRefresh.d.ts +12 -0
  87. package/dist/src/helpers/cachedPropertyRefresh.d.ts.map +1 -0
  88. package/dist/src/helpers/db.d.ts +3 -0
  89. package/dist/src/helpers/db.d.ts.map +1 -1
  90. package/dist/src/helpers/easSdk.d.ts +16 -0
  91. package/dist/src/helpers/easSdk.d.ts.map +1 -0
  92. package/dist/src/helpers/entity/detachRowsBeforeDelete.d.ts +16 -0
  93. package/dist/src/helpers/entity/detachRowsBeforeDelete.d.ts.map +1 -0
  94. package/dist/src/helpers/entity/entityDestroy.d.ts +2 -0
  95. package/dist/src/helpers/entity/entityDestroy.d.ts.map +1 -1
  96. package/dist/src/helpers/ownership.d.ts +9 -1
  97. package/dist/src/helpers/ownership.d.ts.map +1 -1
  98. package/dist/src/helpers/property/index.d.ts +37 -51
  99. package/dist/src/helpers/property/index.d.ts.map +1 -1
  100. package/dist/src/helpers/publishConfig.d.ts +27 -8
  101. package/dist/src/helpers/publishConfig.d.ts.map +1 -1
  102. package/dist/src/helpers/updateSchema.d.ts +5 -0
  103. package/dist/src/helpers/updateSchema.d.ts.map +1 -1
  104. package/dist/src/helpers/waitForEntityIdle.d.ts +5 -0
  105. package/dist/src/helpers/waitForEntityIdle.d.ts.map +1 -1
  106. package/dist/src/imports/json.d.ts +9 -0
  107. package/dist/src/imports/json.d.ts.map +1 -1
  108. package/dist/src/index.d.ts +6 -4
  109. package/dist/src/index.d.ts.map +1 -1
  110. package/dist/src/interfaces/IItem.d.ts +7 -1
  111. package/dist/src/interfaces/IItem.d.ts.map +1 -1
  112. package/dist/src/node/db/Db.d.ts.map +1 -1
  113. package/dist/src/node/helpers/PathResolver.d.ts.map +1 -1
  114. package/dist/src/node/index.d.ts +8 -1
  115. package/dist/src/node/index.d.ts.map +1 -1
  116. package/dist/src/platform/index.browser.d.ts +2 -0
  117. package/dist/src/platform/index.browser.d.ts.map +1 -1
  118. package/dist/src/platform/index.node.d.ts +2 -0
  119. package/dist/src/platform/index.node.d.ts.map +1 -1
  120. package/dist/src/types/index.d.ts +12 -1
  121. package/dist/src/types/index.d.ts.map +1 -1
  122. package/dist/src/types/machines.d.ts +2 -0
  123. package/dist/src/types/machines.d.ts.map +1 -1
  124. package/dist/src/types/property.d.ts +8 -0
  125. package/dist/src/types/property.d.ts.map +1 -1
  126. package/dist/{syncDbWithEas--HUA9WNb.js → syncDbWithEas-Bv2Fe38J.js} +15 -16
  127. package/dist/syncDbWithEas-Bv2Fe38J.js.map +1 -0
  128. package/dist/tabEvents-9s2WCYw-.js +335 -0
  129. package/dist/tabEvents-9s2WCYw-.js.map +1 -0
  130. package/dist/{tolerantWebAccess-BZYWt09Y.js → tolerantWebAccess-iUu80pAP.js} +9 -9
  131. package/dist/{tolerantWebAccess-BZYWt09Y.js.map → tolerantWebAccess-iUu80pAP.js.map} +1 -1
  132. package/dist/{updateSeedRevokedAt-D_EG-q3b.js → updateSeedRevokedAt-zBfi931j.js} +3 -3
  133. package/dist/{updateSeedRevokedAt-D_EG-q3b.js.map → updateSeedRevokedAt-zBfi931j.js.map} +1 -1
  134. package/package.json +11 -12
  135. package/src/node/easLodashRegister.js +4 -0
  136. package/dist/BasePathResolver-CfSfMW5_.js +0 -676
  137. package/dist/BasePathResolver-CfSfMW5_.js.map +0 -1
  138. package/dist/ClientManager-C-QXqUK9.js.map +0 -1
  139. package/dist/Item-C7sUUu2B.js.map +0 -1
  140. package/dist/ModelProperty-DJxeOOrc.js.map +0 -1
  141. package/dist/Schema-fXtvd-yL.js.map +0 -1
  142. package/dist/cjs/ModelProperty-DXZ39Wyv.js +0 -1978
  143. package/dist/cjs/ModelProperty-DXZ39Wyv.js.map +0 -1
  144. package/dist/cjs/Schema-DdP109QD.js +0 -5257
  145. package/dist/cjs/Schema-DdP109QD.js.map +0 -1
  146. package/dist/cjs/SchemaValidationService-CSXxx7sQ.js +0 -779
  147. package/dist/cjs/SchemaValidationService-CSXxx7sQ.js.map +0 -1
  148. package/dist/cjs/backfillMetadataPropertyIds-CPYoaMl4.js +0 -90
  149. package/dist/cjs/backfillMetadataPropertyIds-CPYoaMl4.js.map +0 -1
  150. package/dist/cjs/eas-B2YDQssV.js +0 -139
  151. package/dist/cjs/eas-B2YDQssV.js.map +0 -1
  152. package/dist/cjs/getItem-DgnaQzbE.js +0 -59
  153. package/dist/cjs/getItem-DgnaQzbE.js.map +0 -1
  154. package/dist/cjs/getPublishPayload-CqlqRdot.js +0 -1604
  155. package/dist/cjs/getPublishPayload-CqlqRdot.js.map +0 -1
  156. package/dist/cjs/getPublishUploads-DsXY9S4U.js +0 -872
  157. package/dist/cjs/getPublishUploads-DsXY9S4U.js.map +0 -1
  158. package/dist/cjs/index-BHaWOwNF.js +0 -71
  159. package/dist/cjs/index-BHaWOwNF.js.map +0 -1
  160. package/dist/cjs/index-C4XlgCJ4.js +0 -22801
  161. package/dist/cjs/index-C4XlgCJ4.js.map +0 -1
  162. package/dist/cjs/index.browser-BSf8HpnU.js +0 -22
  163. package/dist/cjs/index.browser-BSf8HpnU.js.map +0 -1
  164. package/dist/cjs/property-fa0iju0J.js +0 -328
  165. package/dist/cjs/property-fa0iju0J.js.map +0 -1
  166. package/dist/cjs/publishDraftGraph-3ASwAlD7.js +0 -403
  167. package/dist/cjs/publishDraftGraph-3ASwAlD7.js.map +0 -1
  168. package/dist/cjs/resetAmbiguousLegacyItemData-Bu_MBBYt.js +0 -117
  169. package/dist/cjs/resetAmbiguousLegacyItemData-Bu_MBBYt.js.map +0 -1
  170. package/dist/cjs/resolveModelForSyncedSeed-BANIiuFU.js +0 -49
  171. package/dist/cjs/resolveModelForSyncedSeed-BANIiuFU.js.map +0 -1
  172. package/dist/cjs/syncDbWithEas-CrmxxmUW.js +0 -887
  173. package/dist/cjs/syncDbWithEas-CrmxxmUW.js.map +0 -1
  174. package/dist/db-D9K_f5cF.js.map +0 -1
  175. package/dist/eas-DHxfswCt.js.map +0 -1
  176. package/dist/getPublishPayload-BHrxVtzY.js.map +0 -1
  177. package/dist/index-CiMEoGu3.js +0 -32
  178. package/dist/index-CiMEoGu3.js.map +0 -1
  179. package/dist/index-DglvthOk.js.map +0 -1
  180. package/dist/index-s15q14rm.js.map +0 -1
  181. package/dist/index.node-C30dmFgn.js.map +0 -1
  182. package/dist/main.cjs +0 -85
  183. package/dist/main.cjs.map +0 -1
  184. package/dist/property-DhmmYAvQ.js.map +0 -1
  185. package/dist/syncDbWithEas--HUA9WNb.js.map +0 -1
  186. package/dist/tabEvents-DguZpCCv.js +0 -1580
  187. package/dist/tabEvents-DguZpCCv.js.map +0 -1
@@ -1,17 +1,16 @@
1
+ import { startCase, isEqual } from 'lodash-es';
2
+ import { E as BaseDb, l as easSyncProcesses, G as eventEmitter, a8 as isNode, ah as isBrowser, I as BasePathResolver, aA as normalizeAddressConfig, h as appState, aL as downloadAllFilesRequestHandler, aM as downloadAllFilesBinaryRequestHandler, J as BaseFileManager, H as toSnakeCase, s as models$1, r as modelUids, A as seeds, aB as normalizeAddressList, z as schemas, aK as loadModelsFromDbForSchema, aI as addSchemaToDb, aF as isInternalSchema, aN as INTERNAL_SCHEMA_IDS, $ as generateId, aO as linkModelToSchema, n as normalizeDataType, aq as SEED_PROTOCOL_SCHEMA_NAME, q as modelSchemas, m as metadata$1, u as properties, L as resolveItemModelFileId, C as versions, o as htmlEmbeddedImageCoPublish, j as arweaveL1FinalizeJobs, y as publishProcesses, X as normalizePublisher, aP as getWatchedAddressesFromDb, aQ as getOwnedAddressesFromDb, aR as CLIENT_NOT_INITIALIZED } from './BasePathResolver-Cm4apKRb.js';
1
3
  import debug from 'debug';
2
4
  import { createActor, setup, assign, fromPromise, fromCallback, waitFor } from 'xstate';
3
- import { m as eventEmitter, C as normalizeAddressConfig, E as normalizeAddressList, S as loadModelsFromDbForSchema, O as addSchemaToDb, n as normalizeDataType, U as linkModelToSchema, r as resolveItemModelFileId, s as normalizePublisher, V as getWatchedAddressesFromDb, W as getOwnedAddressesFromDb } from './db-D9K_f5cF.js';
4
- import { u as MachineIds, Y as ClientManagerEvents, Z as withLockedItemStorageRow, _ as getItemStorageFilePath, $ as writeItemStorageFile, c as compareMetadataRowsLatestFirst, C as ClientManagerState, a0 as resolvePublisherFromSeedRow, F as isLocalUnsealedDraft, I as Item } from './Item-C7sUUu2B.js';
5
- import { B as BaseDb, e as easSyncProcesses, r as BasePathResolver, a as appState, t as BaseFileManager, i as models$1, g as modelUids, q as seeds, s as schemas, K as isInternalSchema, L as INTERNAL_SCHEMA_IDS, F as SEED_PROTOCOL_SCHEMA_NAME, f as modelSchemas, m as metadata$1, p as properties, v as versions, h as htmlEmbeddedImageCoPublish, b as arweaveL1FinalizeJobs, o as publishProcesses, M as CLIENT_NOT_INITIALIZED } from './BasePathResolver-CfSfMW5_.js';
5
+ import { x as MachineIds, a2 as ClientManagerEvents, a3 as withLockedItemStorageRow, a4 as getItemStorageFilePath, a5 as writeItemStorageFile, c as compareMetadataRowsLatestFirst, C as ClientManagerState, a6 as resolvePublisherFromSeedRow, J as isLocalUnsealedDraft, I as Item } from './Item-DBFchXpC.js';
6
6
  import { eq, inArray, and, isNotNull, ne, desc, countDistinct, isNull, or, like } from 'drizzle-orm';
7
- import { D as withDbTabLock, v as isLeaderTab, H as postTabMessage, I as onTabMessage, B as whenLeaderTab, J as listenForOtherTabsEvents, K as isNode, M as isBrowser, N as startTabCoordination, O as downloadAllFilesRequestHandler, P as downloadAllFilesBinaryRequestHandler, t as toSnakeCase, G as withSeedDbLock, j as generateId, y as parseAddressesPersistedPayload, h as emitAcrossTabs, A as ADDRESSES_PERSISTED_EVENT, L as LOCAL_COPIES_REMOVED_EVENT } from './tabEvents-DguZpCCv.js';
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, p as parseAddressesPersistedPayload, e as emitAcrossTabs, A as ADDRESSES_PERSISTED_EVENT, L as LOCAL_COPIES_REMOVED_EVENT } from './tabEvents-9s2WCYw-.js';
8
8
  import { seedGatewayConfigFromSeedConfig, setPreferredArweaveReadBaseUrls, resolveSeedGatewayEndpoints, setResolvedSeedGatewayEndpoints, BaseArweaveClient, ensureReadGatewaySelected, DEFAULT_ARWEAVE_HOST } from '@seedprotocol/arweave';
9
9
  import { configureEasReadChain, BaseQueryClient, BaseEasClient, GET_SCHEMAS, whenEasReadChainSettled, getEasReadChainId, DEFAULT_EAS_CHAIN_ID, isEasReadChainConfigured, 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';
13
13
  import { clearLocalQuerySource, registerLocalQuerySource, getSeed } from '@seedprotocol/query';
14
- import { startCase } from 'lodash-es';
15
14
 
16
15
  let writeTail = Promise.resolve();
17
16
  function enqueueEasSyncDbWrite(fn) {
@@ -109,7 +108,7 @@ const runEasSync = fromPromise(async ({ input, }) => {
109
108
  requestPayload: input.requestPayload,
110
109
  persistedSnapshot: input.runningSnapshot,
111
110
  });
112
- const { runSyncFromEas } = await import('./syncDbWithEas--HUA9WNb.js');
111
+ const { runSyncFromEas } = await import('./syncDbWithEas-Bv2Fe38J.js');
113
112
  try {
114
113
  // Sync checks for rows and then inserts the rest (no unique index on uids), so syncs in
115
114
  // different tabs take turns. A sync can run for minutes, so wait without a timeout.
@@ -429,6 +428,15 @@ function normalizeSeedConfigEndpoints(config) {
429
428
  }
430
429
 
431
430
  const logger$b = debug('seedSdk:ClientManager:initialize');
431
+ /**
432
+ * Whether a relative filesDir already names the .seed directory or a path inside
433
+ * it ('.seed', '.seed/files', './.seed/files'). '.seed-alt/x' is not: it is
434
+ * resolved under .seed like any other relative path.
435
+ */
436
+ function isUnderDotSeed(relativePath) {
437
+ const firstSegment = relativePath.split(/[\\/]+/).find((segment) => segment !== '' && segment !== '.');
438
+ return firstSegment === '.seed';
439
+ }
432
440
  const platformClassesInit = fromCallback(({ sendBack, input: { context, event } }) => {
433
441
  logger$b('initialize from ClientManager');
434
442
  const { isInitialized } = context;
@@ -463,7 +471,7 @@ const platformClassesInit = fromCallback(({ sendBack, input: { context, event }
463
471
  }
464
472
  // Prefer the condition-resolved factory when available; fall back to explicit
465
473
  // platform imports so source/vitest resolution stays reliable.
466
- const { configurePlatform } = await import('./configurePlatform-BRw2j0ZN.js');
474
+ const { configurePlatform } = await import('./configurePlatform-D0lQGAMQ.js');
467
475
  if (isBrowser()) {
468
476
  const { createPlatformServices } = await import('./platform.browser.js');
469
477
  configurePlatform(createPlatformServices());
@@ -526,8 +534,8 @@ const platformClassesInit = fromCallback(({ sendBack, input: { context, event }
526
534
  normalizedFilesDir = path.join(dotSeedDir, dirName);
527
535
  }
528
536
  else if (!path.isAbsolute(normalizedFilesDir)) {
529
- // If it's a relative path, check if it already starts with .seed
530
- if (normalizedFilesDir.startsWith('.seed') || normalizedFilesDir.startsWith('.seed/')) {
537
+ // If it's a relative path, check if it is already under .seed
538
+ if (isUnderDotSeed(normalizedFilesDir)) {
531
539
  // Already relative to project root, resolve it
532
540
  normalizedFilesDir = path.resolve(normalizedFilesDir);
533
541
  }
@@ -550,6 +558,7 @@ const platformClassesInit = fromCallback(({ sendBack, input: { context, event }
550
558
  gatewaySidecarPort: gatewayConfig.hyper?.localSidecarPort,
551
559
  gatewayProxyBaseUrl: resolvedGateway.proxyBaseUrl ?? gatewayConfig.proxyBaseUrl,
552
560
  addresses: normalizedAddresses.owned,
561
+ addressesProvided: addresses !== undefined,
553
562
  ownedAddresses: normalizedAddresses.owned,
554
563
  watchedAddresses: normalizedAddresses.watched,
555
564
  filesDir: normalizedFilesDir,
@@ -1027,14 +1036,32 @@ async function assertLocalDbChain() {
1027
1036
  }
1028
1037
 
1029
1038
  const logger$5 = debug('seedSdk:client:actors:saveConfig');
1039
+ let warnedKeptStoredAddresses = false;
1030
1040
  /**
1031
- * Saves the addresses passed to init. Hosts pass `addresses: []` before a wallet connects. In the
1032
- * first (leader) tab that clears stored addresses, as it always has, so drafts made before the
1033
- * wallet reconnects stay editable. A tab opened while another is running (`keepStoredWhenEmpty`)
1034
- * keeps them instead: they're the other tab's connected wallet, which EAS sync, downloads and
1035
- * publishing read. See docs/MULTI_TAB.md.
1041
+ * Saves the addresses passed to init.
1042
+ *
1043
+ * - No `addresses` option (`addressesProvided: false`): stored addresses are kept, with a
1044
+ * one-time warning when there are any, since a forgotten option would otherwise act on
1045
+ * an earlier session's wallet.
1046
+ * - `addresses: []`: hosts pass this before a wallet connects. In the first (leader) tab it
1047
+ * clears stored addresses, so drafts made before the wallet reconnects stay editable. A tab
1048
+ * opened while another is running (`keepStoredWhenEmpty`) keeps them instead: they're the
1049
+ * other tab's connected wallet, which EAS sync, downloads and publishing read. See
1050
+ * docs/MULTI_TAB.md.
1036
1051
  */
1037
- async function persistInitAddresses(appDb, { addresses, ownedAddresses, watchedAddresses }, { keepStoredWhenEmpty }) {
1052
+ async function persistInitAddresses(appDb, { addresses, addressesProvided, ownedAddresses, watchedAddresses, }, { keepStoredWhenEmpty }) {
1053
+ if (addressesProvided === false) {
1054
+ if (!warnedKeptStoredAddresses) {
1055
+ const rows = await appDb.select().from(appState).where(eq(appState.key, 'addresses')).limit(1);
1056
+ const stored = rows[0]?.value ? normalizeAddressConfig(JSON.parse(rows[0].value)) : undefined;
1057
+ if (stored && (stored.owned.length > 0 || stored.watched.length > 0)) {
1058
+ warnedKeptStoredAddresses = true;
1059
+ console.warn(`[seed] client.init was called without \`addresses\`, so the stored addresses are kept ` +
1060
+ `(${stored.owned.length} owned, ${stored.watched.length} watched). Pass \`addresses: []\` to clear them.`);
1061
+ }
1062
+ }
1063
+ return;
1064
+ }
1038
1065
  const owned = normalizeAddressList(ownedAddresses ?? addresses ?? []);
1039
1066
  const watched = normalizeAddressList(watchedAddresses ?? []);
1040
1067
  if (owned.length === 0 && watched.length === 0 && keepStoredWhenEmpty)
@@ -1047,7 +1074,7 @@ async function persistInitAddresses(appDb, { addresses, ownedAddresses, watchedA
1047
1074
  }
1048
1075
  const saveConfig = fromCallback(({ sendBack, input: { context } }) => {
1049
1076
  logger$5('saveConfig starting');
1050
- const { endpoints, addresses, ownedAddresses, watchedAddresses, arweaveDomain, uploadApiBaseUrl, gatewayTransport, gatewayHyperKey, gatewaySidecarHost, gatewaySidecarPort, gatewayProxyBaseUrl, } = context;
1077
+ const { endpoints, addresses, addressesProvided, ownedAddresses, watchedAddresses, arweaveDomain, uploadApiBaseUrl, gatewayTransport, gatewayHyperKey, gatewaySidecarHost, gatewaySidecarPort, gatewayProxyBaseUrl, } = context;
1051
1078
  // Validate endpoints - required for proper initialization
1052
1079
  // If endpoints are missing or invalid, initialization should fail
1053
1080
  if (!endpoints || !endpoints.filePaths || !endpoints.files) {
@@ -1080,7 +1107,7 @@ const saveConfig = fromCallback(({ sendBack, input: { context } }) => {
1080
1107
  value: endpointsValueString,
1081
1108
  },
1082
1109
  });
1083
- await persistInitAddresses(appDb, { addresses, ownedAddresses, watchedAddresses }, { keepStoredWhenEmpty: !isLeaderTab() });
1110
+ await persistInitAddresses(appDb, { addresses, addressesProvided, ownedAddresses, watchedAddresses }, { keepStoredWhenEmpty: !isLeaderTab() });
1084
1111
  await appDb
1085
1112
  .insert(appState)
1086
1113
  .values({
@@ -1846,8 +1873,8 @@ function getRefValueType(prop) {
1846
1873
  * @returns Promise that resolves when properties are found, or rejects if not found after max retries
1847
1874
  */
1848
1875
  const verifyPropertiesPersisted = async (db, modelId, modelName, maxRetries = 10, retryDelay = 100) => {
1849
- const _mod_0 = await import('./BasePathResolver-CfSfMW5_.js');
1850
- const _ns_0 = _mod_0.N;
1876
+ const _mod_0 = await import('./BasePathResolver-Cm4apKRb.js');
1877
+ const _ns_0 = _mod_0.aZ;
1851
1878
  const modelSchemaMod = _ns_0;
1852
1879
  const { properties: propertiesTable } = modelSchemaMod;
1853
1880
  const drizzleMod = await import('drizzle-orm');
@@ -2194,8 +2221,8 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
2194
2221
  // Check DB for existing schema by name+version (same as minimal path)
2195
2222
  const db = BaseDb.getAppDb();
2196
2223
  if (db) {
2197
- const _mod_1 = await import('./BasePathResolver-CfSfMW5_.js');
2198
- const _ns_1 = _mod_1.Q;
2224
+ const _mod_1 = await import('./BasePathResolver-Cm4apKRb.js');
2225
+ const _ns_1 = _mod_1.a$;
2199
2226
  const schemaSchemaMod = _ns_1;
2200
2227
  const { schemas: schemasTable } = schemaSchemaMod;
2201
2228
  const drizzleMod = await import('drizzle-orm');
@@ -2279,8 +2306,8 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
2279
2306
  // For minimal imports: check DB for existing schema before creating new file
2280
2307
  const db = BaseDb.getAppDb();
2281
2308
  if (db) {
2282
- const _mod_2 = await import('./BasePathResolver-CfSfMW5_.js');
2283
- const _ns_2 = _mod_2.Q;
2309
+ const _mod_2 = await import('./BasePathResolver-Cm4apKRb.js');
2310
+ const _ns_2 = _mod_2.a$;
2284
2311
  const schemaSchemaMod = _ns_2;
2285
2312
  const { schemas: schemasTable } = schemaSchemaMod;
2286
2313
  const drizzleMod = await import('drizzle-orm');
@@ -2458,8 +2485,8 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
2458
2485
  updatedAt: new Date(schemaFile.metadata.updatedAt).getTime(),
2459
2486
  };
2460
2487
  // Use dynamic import to break circular dependency
2461
- const _mod_3 = await import('./db-D9K_f5cF.js');
2462
- const _ns_3 = _mod_3.Z;
2488
+ const _mod_3 = await import('./BasePathResolver-Cm4apKRb.js');
2489
+ const _ns_3 = _mod_3.b2;
2463
2490
  const dbMod = _ns_3;
2464
2491
  const { addSchemaToDb, addModelsToDb } = dbMod;
2465
2492
  // Try to add schema and models to database if database is available
@@ -2480,12 +2507,12 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
2480
2507
  });
2481
2508
  // Verify expected models are linked (single attempt - addModelsToDb already confirmed)
2482
2509
  const expectedModelNames = Object.keys(schemaFile.models || {});
2483
- const _mod_4 = await import('./BasePathResolver-CfSfMW5_.js');
2484
- const _ns_4 = _mod_4.R;
2510
+ const _mod_4 = await import('./BasePathResolver-Cm4apKRb.js');
2511
+ const _ns_4 = _mod_4.b0;
2485
2512
  const modelSchemaSchemaMod = _ns_4;
2486
2513
  const { modelSchemas } = modelSchemaSchemaMod;
2487
- const _mod_5 = await import('./BasePathResolver-CfSfMW5_.js');
2488
- const _ns_5 = _mod_5.N;
2514
+ const _mod_5 = await import('./BasePathResolver-Cm4apKRb.js');
2515
+ const _ns_5 = _mod_5.aZ;
2489
2516
  const modelSchemaMod = _ns_5;
2490
2517
  const { models: modelsTable } = modelSchemaMod;
2491
2518
  const drizzleMod = await import('drizzle-orm');
@@ -2670,7 +2697,7 @@ async function importJsonSchema(importFilePathOrContents, version = 1) {
2670
2697
  * Apply schema and models to the database. Shared by loadSchemaFromFile and syncSchemaFromSource.
2671
2698
  * @internal
2672
2699
  */
2673
- async function applySchemaToDb(schemaFile, modelDefinitions, modelFileIds, propertyFileIds) {
2700
+ async function applySchemaToDb(schemaFile, modelDefinitions, modelFileIds, propertyFileIds, propertyDefinitions) {
2674
2701
  const schemaName = schemaFile.metadata?.name;
2675
2702
  const version = schemaFile.version;
2676
2703
  if (!schemaName) {
@@ -2683,8 +2710,8 @@ async function applySchemaToDb(schemaFile, modelDefinitions, modelFileIds, prope
2683
2710
  createdAt: new Date(schemaFile.metadata.createdAt).getTime(),
2684
2711
  updatedAt: new Date(schemaFile.metadata.updatedAt).getTime(),
2685
2712
  };
2686
- const _mod_6 = await import('./db-D9K_f5cF.js');
2687
- const _ns_6 = _mod_6.Z;
2713
+ const _mod_6 = await import('./BasePathResolver-Cm4apKRb.js');
2714
+ const _ns_6 = _mod_6.b2;
2688
2715
  const dbMod = _ns_6;
2689
2716
  const { addSchemaToDb, addModelsToDb } = dbMod;
2690
2717
  const db = BaseDb.getAppDb();
@@ -2698,6 +2725,7 @@ async function applySchemaToDb(schemaFile, modelDefinitions, modelFileIds, prope
2698
2725
  schemaFileId: schemaFile.id,
2699
2726
  modelFileIds,
2700
2727
  propertyFileIds,
2728
+ propertyDefinitions,
2701
2729
  });
2702
2730
  await new Promise(resolve => setTimeout(resolve, 200));
2703
2731
  }
@@ -2841,14 +2869,21 @@ const loadSchemaFromFile = async (schemaFilePath) => {
2841
2869
  try {
2842
2870
  const db = BaseDb.getAppDb();
2843
2871
  if (db) {
2844
- const { schemaRecord } = await applySchemaToDb(schemaFile, modelDefinitions, modelFileIds, propertyFileIds);
2872
+ // A model already in the instance cache keeps its old properties (Model.create ignores the
2873
+ // ones passed), so give addModelsToDb this file's definitions: a renamed or changed property
2874
+ // must come from the file, not from the cached model.
2875
+ const propertyDefinitions = new Map(Object.entries(importData.models).map(([modelName, modelDef]) => [
2876
+ modelName,
2877
+ jsonPropertiesToSchemaProperties(modelName, modelDef, propertyFileIds.get(modelName)),
2878
+ ]));
2879
+ const { schemaRecord } = await applySchemaToDb(schemaFile, modelDefinitions, modelFileIds, propertyFileIds, propertyDefinitions);
2845
2880
  // Query the database to get model IDs that were just created
2846
- const _mod_7 = await import('./BasePathResolver-CfSfMW5_.js');
2847
- const _ns_7 = _mod_7.R;
2881
+ const _mod_7 = await import('./BasePathResolver-Cm4apKRb.js');
2882
+ const _ns_7 = _mod_7.b0;
2848
2883
  const modelSchemaSchemaMod = _ns_7;
2849
2884
  const { modelSchemas } = modelSchemaSchemaMod;
2850
- const _mod_8 = await import('./BasePathResolver-CfSfMW5_.js');
2851
- const _ns_8 = _mod_8.N;
2885
+ const _mod_8 = await import('./BasePathResolver-Cm4apKRb.js');
2886
+ const _ns_8 = _mod_8.aZ;
2852
2887
  const modelSchemaMod = _ns_8;
2853
2888
  const { models: modelsTable } = modelSchemaMod;
2854
2889
  const drizzleMod = await import('drizzle-orm');
@@ -2913,8 +2948,8 @@ const loadSchemaFromFile = async (schemaFilePath) => {
2913
2948
  // After properties are created (file path), ensure schemaFile has the correct IDs from database
2914
2949
  // Query the database to get the actual schemaFileId values that were used
2915
2950
  // This ensures schemaData matches what's actually in the database
2916
- const _mod_9 = await import('./BasePathResolver-CfSfMW5_.js');
2917
- const _ns_9 = _mod_9.N;
2951
+ const _mod_9 = await import('./BasePathResolver-Cm4apKRb.js');
2952
+ const _ns_9 = _mod_9.aZ;
2918
2953
  const modelSchemaMod2 = _ns_9;
2919
2954
  const { properties: propertiesTable } = modelSchemaMod2;
2920
2955
  let schemaFileUpdated = false;
@@ -2949,8 +2984,8 @@ const loadSchemaFromFile = async (schemaFilePath) => {
2949
2984
  // This is important even if nothing changed, to ensure consistency
2950
2985
  const updatedSchemaData = JSON.stringify(schemaFile, null, 2);
2951
2986
  // Update the schema record in the database with current schemaData
2952
- const _mod_10 = await import('./BasePathResolver-CfSfMW5_.js');
2953
- const _ns_10 = _mod_10.Q;
2987
+ const _mod_10 = await import('./BasePathResolver-Cm4apKRb.js');
2988
+ const _ns_10 = _mod_10.a$;
2954
2989
  const schemaSchemaMod = _ns_10;
2955
2990
  const { schemas: schemasTable } = schemaSchemaMod;
2956
2991
  await db
@@ -2984,19 +3019,12 @@ const loadSchemaFromFile = async (schemaFilePath) => {
2984
3019
  }
2985
3020
  };
2986
3021
  /**
2987
- * Create a Model class from a JSON model definition
2988
- * @param modelName - The name of the model
3022
+ * Convert a JSON model's properties to the schema property format Model.create and addModelsToDb take
3023
+ * @param modelName - The name of the model (for error messages)
2989
3024
  * @param modelDef - The JSON model definition
2990
- * @param schemaName - The name of the schema this model belongs to
2991
- * @returns A Model class that can be used with the SDK
3025
+ * @param propertyFileIds - Optional map of property names to their file IDs from the JSON file
2992
3026
  */
2993
- const createModelFromJson = async (modelName, modelDef, schemaName, modelFileId, // Optional modelFileId from JSON file
2994
- propertyFileIds) => {
2995
- const _mod_11 = await import('./index-s15q14rm.js');
2996
- const _ns_11 = _mod_11.f;
2997
- const modelMod = _ns_11;
2998
- const { Model } = modelMod;
2999
- // Convert JSON properties to schema format
3027
+ const jsonPropertiesToSchemaProperties = (modelName, modelDef, propertyFileIds) => {
3000
3028
  const convertedProperties = {};
3001
3029
  if (modelDef.properties) {
3002
3030
  for (const [propName, propDef] of Object.entries(modelDef.properties)) {
@@ -3055,6 +3083,22 @@ propertyFileIds) => {
3055
3083
  convertedProperties[propName] = schemaProp;
3056
3084
  }
3057
3085
  }
3086
+ return convertedProperties;
3087
+ };
3088
+ /**
3089
+ * Create a Model class from a JSON model definition
3090
+ * @param modelName - The name of the model
3091
+ * @param modelDef - The JSON model definition
3092
+ * @param schemaName - The name of the schema this model belongs to
3093
+ * @returns A Model class that can be used with the SDK
3094
+ */
3095
+ const createModelFromJson = async (modelName, modelDef, schemaName, modelFileId, // Optional modelFileId from JSON file
3096
+ propertyFileIds) => {
3097
+ const _mod_11 = await import('./index-8O3Uow-Y.js');
3098
+ const _ns_11 = _mod_11.f;
3099
+ const modelMod = _ns_11;
3100
+ const { Model } = modelMod;
3101
+ const convertedProperties = jsonPropertiesToSchemaProperties(modelName, modelDef, propertyFileIds);
3058
3102
  // Create Model instance with the definition
3059
3103
  // Pass id (schemaFileId) if provided to ensure Model instance uses correct ID
3060
3104
  // Note: indexes and description are ignored - they remain in JSON for schema file format compliance but are not used by Model instances
@@ -3311,6 +3355,12 @@ async function resolveSchemaNameFromSource(source) {
3311
3355
  }
3312
3356
  return null;
3313
3357
  }
3358
+ /** Error for a schema the app passed in config, so init fails with what went wrong and where. */
3359
+ function userSchemaLoadError(option, source, error) {
3360
+ const where = typeof source === 'string' ? ` from "${source}"` : '';
3361
+ const reason = error instanceof Error ? error.message : String(error);
3362
+ return new Error(`Could not load config.${option}${where}: ${reason}`, { cause: error });
3363
+ }
3314
3364
  // Timeout for the entire schema processing operation (120 seconds)
3315
3365
  // Schema processing can be slow with syncSchemaFromSource, loadAllSchemasFromDb, and OPFS file I/O
3316
3366
  const PROCESS_SCHEMA_FILES_TIMEOUT_MS = 120000;
@@ -3399,8 +3449,9 @@ const processSchemaFiles = fromCallback(({ sendBack, input: { context } }) => {
3399
3449
  logger$2(`Synced canonical schema from ${typeof context.schema === 'string' ? context.schema : 'object'}`);
3400
3450
  }
3401
3451
  catch (error) {
3402
- logger$2(`Error syncing canonical schema:`, error);
3403
- // Don't fail init - schema might already be in DB
3452
+ // A schema the app passed in failed (missing file, bad JSON, DB write). Re-running an
3453
+ // unchanged schema does not throw, so this is not the already-loaded case: fail init.
3454
+ throw userSchemaLoadError('schema', context.schema, error);
3404
3455
  }
3405
3456
  }
3406
3457
  }
@@ -3417,8 +3468,7 @@ const processSchemaFiles = fromCallback(({ sendBack, input: { context } }) => {
3417
3468
  logger$2(`Loaded schema from ${resolvedPath}`);
3418
3469
  }
3419
3470
  catch (error) {
3420
- logger$2(`Error loading schema file ${context.schemaFile}:`, error);
3421
- // Don't fail init - schema might already be in DB
3471
+ throw userSchemaLoadError('schemaFile', context.schemaFile, error);
3422
3472
  }
3423
3473
  }
3424
3474
  // Process minimal import files (files without $schema) - skip when canonical schema is set
@@ -3631,14 +3681,12 @@ const processSchemaFiles = fromCallback(({ sendBack, input: { context } }) => {
3631
3681
  }
3632
3682
  });
3633
3683
  };
3634
- processSchemaFilesChain = processSchemaFilesChain
3684
+ const run = processSchemaFilesChain
3635
3685
  // Its schema and model inserts check for rows first, so tabs take turns (docs/MULTI_TAB.md).
3636
- .then(() => withSeedDbLock('init', context.filesDir, _processSchemaFiles))
3637
- .catch((err) => {
3638
- logger$2('processSchemaFiles chain error:', err);
3639
- throw err;
3640
- });
3641
- processSchemaFilesChain.then(reportSuccess).catch((error) => {
3686
+ .then(() => withSeedDbLock('init', context.filesDir, _processSchemaFiles));
3687
+ // The chain only orders runs; a failed run must not fail the next init too.
3688
+ processSchemaFilesChain = run.catch(() => { });
3689
+ run.then(reportSuccess).catch((error) => {
3642
3690
  reportError(error instanceof Error ? error : new Error(String(error)));
3643
3691
  });
3644
3692
  // Cleanup function to clear timeout if actor is stopped
@@ -4771,6 +4819,7 @@ const emptyResult = () => ({
4771
4819
  seeds: 0,
4772
4820
  versions: 0,
4773
4821
  metadata: 0,
4822
+ seedLocalIds: [],
4774
4823
  });
4775
4824
  /**
4776
4825
  * Stamp local seeds/versions/metadata that have no publisher and no real uid.
@@ -4799,22 +4848,23 @@ async function claimUnpublishedDrafts(publisher) {
4799
4848
  isLocalUnsealedDraft(row))
4800
4849
  .map((row) => row.localId);
4801
4850
  if (ids.length === 0)
4802
- return 0;
4851
+ return [];
4803
4852
  await appDb
4804
4853
  .update(table)
4805
4854
  .set({ publisher: normalized, updatedAt: now })
4806
4855
  .where(inArray(table.localId, ids));
4807
- return ids.length;
4856
+ return ids;
4808
4857
  };
4809
- const [seedCount, versionCount, metadataCount] = await Promise.all([
4858
+ const [seedIds, versionIds, metadataIds] = await Promise.all([
4810
4859
  claimTable(seeds),
4811
4860
  claimTable(versions),
4812
4861
  claimTable(metadata$1),
4813
4862
  ]);
4814
4863
  return {
4815
- seeds: seedCount,
4816
- versions: versionCount,
4817
- metadata: metadataCount,
4864
+ seeds: seedIds.length,
4865
+ versions: versionIds.length,
4866
+ metadata: metadataIds.length,
4867
+ seedLocalIds: seedIds,
4818
4868
  };
4819
4869
  }
4820
4870
 
@@ -4832,11 +4882,97 @@ const subscription = clientManager.subscribe((snapshot) => {
4832
4882
  logger('ClientManager snapshot.context.isInitialized:', snapshot.context.isInitialized);
4833
4883
  });
4834
4884
  clientManager.start();
4885
+ /** Config of the init that is running or has succeeded; cleared when init fails or the client stops. */
4886
+ let activeInitConfig;
4887
+ const INIT_CONFIG_CONFLICT_MESSAGE = 'client.init was already called with a different config. The SDK keeps the config it was ' +
4888
+ 'initialised with: pass the same config, or call client.stop() before initialising with a new one. ' +
4889
+ 'To change addresses, use client.setAddresses() (or call init again with the same config and new addresses).';
4835
4890
  const ensureInitialized = () => {
4836
4891
  if (!clientManager.getSnapshot().context.isInitialized) {
4837
4892
  throw new Error(CLIENT_NOT_INITIALIZED);
4838
4893
  }
4839
4894
  };
4895
+ const coalescedInit = createCoalescedAsync(async (options) => {
4896
+ // If the actor is stopped (e.g., from a previous failed test), restart it
4897
+ const snapshot = clientManager.getSnapshot();
4898
+ const currentState = snapshot.value;
4899
+ const isStopped = snapshot.status === 'stopped';
4900
+ if (isStopped) {
4901
+ logger('Client manager was stopped, restarting...');
4902
+ clientManager.start();
4903
+ // Wait for the actor to be ready
4904
+ try {
4905
+ await waitFor(clientManager, (snapshot) => snapshot.status !== 'stopped', { timeout: 1000 });
4906
+ }
4907
+ catch (e) {
4908
+ logger('Timeout waiting for actor to restart, continuing anyway...');
4909
+ }
4910
+ }
4911
+ // Clear any stale context from previous failed initializations
4912
+ // This ensures we start with a clean slate before the new init updates it
4913
+ if (currentState !== 'uninitialized') {
4914
+ logger(`Client manager is in state ${currentState}, clearing stale context before re-init...`);
4915
+ clientManager.send({
4916
+ type: 'updateContext',
4917
+ context: {
4918
+ isInitialized: false,
4919
+ addressesSet: false,
4920
+ isSaving: false,
4921
+ syncFromEasOnAddressChange: false,
4922
+ endpoints: undefined,
4923
+ addresses: undefined,
4924
+ ownedAddresses: undefined,
4925
+ watchedAddresses: undefined,
4926
+ models: undefined,
4927
+ arweaveDomain: undefined,
4928
+ filesDir: undefined,
4929
+ dbConfig: undefined,
4930
+ initError: undefined,
4931
+ saveError: undefined,
4932
+ }
4933
+ });
4934
+ // Wait a moment for the context update to be processed
4935
+ await new Promise(resolve => setTimeout(resolve, 10));
4936
+ }
4937
+ // Send init event - the root-level handler will transition to PLATFORM_CLASSES_INIT
4938
+ // which will stop any running actors and start fresh with the new options
4939
+ // The platformClassesInit actor will update the context with the correct endpoints from options
4940
+ clientManager.send({ type: 'init', options });
4941
+ // Wait for the state machine to transition to PLATFORM_CLASSES_INIT to ensure
4942
+ // any old actors are stopped and the new initialization flow begins
4943
+ try {
4944
+ await waitFor(clientManager, (snapshot) => {
4945
+ return snapshot.value === 'platformClassesInit' || snapshot.context.isInitialized;
4946
+ }, { timeout: 1000 });
4947
+ }
4948
+ catch (e) {
4949
+ // If we can't transition, continue anyway - the waitFor below will catch any errors
4950
+ logger('Timeout waiting for state transition, continuing...');
4951
+ }
4952
+ try {
4953
+ await waitFor(clientManager, (snapshot) => {
4954
+ return snapshot.context.isInitialized || snapshot.context.initError != null;
4955
+ }, { timeout: 120000 });
4956
+ const initError = clientManager.getSnapshot().context.initError;
4957
+ if (initError) {
4958
+ throw initError instanceof Error ? initError : new Error(String(initError));
4959
+ }
4960
+ }
4961
+ catch (error) {
4962
+ // Ensure we never throw undefined
4963
+ if (error === undefined || error === null) {
4964
+ throw new Error('Initialization failed with undefined error');
4965
+ }
4966
+ throw error;
4967
+ }
4968
+ // Wire `@seedprotocol/query` local source once DB is ready
4969
+ registerSeedQueryLocalSource({ force: true });
4970
+ }, () => {
4971
+ const snapshot = clientManager.getSnapshot();
4972
+ return (snapshot.value === ClientManagerState.IDLE &&
4973
+ snapshot.context.isInitialized === true &&
4974
+ !snapshot.context.initError);
4975
+ });
4840
4976
  // Singleton instance - created once at module load time
4841
4977
  // ES modules cache exports, ensuring all imports get the same instance
4842
4978
  const clientInstance = {
@@ -4847,87 +4983,32 @@ const clientInstance = {
4847
4983
  // ensureInitialized();
4848
4984
  return clientManager;
4849
4985
  },
4850
- init: createCoalescedAsync(async (options) => {
4851
- // If the actor is stopped (e.g., from a previous failed test), restart it
4852
- const snapshot = clientManager.getSnapshot();
4853
- const currentState = snapshot.value;
4854
- const isStopped = snapshot.status === 'stopped';
4855
- if (isStopped) {
4856
- logger('Client manager was stopped, restarting...');
4857
- clientManager.start();
4858
- // Wait for the actor to be ready
4859
- try {
4860
- await waitFor(clientManager, (snapshot) => snapshot.status !== 'stopped', { timeout: 1000 });
4861
- }
4862
- catch (e) {
4863
- logger('Timeout waiting for actor to restart, continuing anyway...');
4864
- }
4865
- }
4866
- // Clear any stale context from previous failed initializations
4867
- // This ensures we start with a clean slate before the new init updates it
4868
- if (currentState !== 'uninitialized') {
4869
- logger(`Client manager is in state ${currentState}, clearing stale context before re-init...`);
4870
- clientManager.send({
4871
- type: 'updateContext',
4872
- context: {
4873
- isInitialized: false,
4874
- addressesSet: false,
4875
- isSaving: false,
4876
- syncFromEasOnAddressChange: false,
4877
- endpoints: undefined,
4878
- addresses: undefined,
4879
- ownedAddresses: undefined,
4880
- watchedAddresses: undefined,
4881
- models: undefined,
4882
- arweaveDomain: undefined,
4883
- filesDir: undefined,
4884
- dbConfig: undefined,
4885
- initError: undefined,
4886
- saveError: undefined,
4887
- }
4888
- });
4889
- // Wait a moment for the context update to be processed
4890
- await new Promise(resolve => setTimeout(resolve, 10));
4891
- }
4892
- // Send init event - the root-level handler will transition to PLATFORM_CLASSES_INIT
4893
- // which will stop any running actors and start fresh with the new options
4894
- // The platformClassesInit actor will update the context with the correct endpoints from options
4895
- clientManager.send({ type: 'init', options });
4896
- // Wait for the state machine to transition to PLATFORM_CLASSES_INIT to ensure
4897
- // any old actors are stopped and the new initialization flow begins
4898
- try {
4899
- await waitFor(clientManager, (snapshot) => {
4900
- return snapshot.value === 'platformClassesInit' || snapshot.context.isInitialized;
4901
- }, { timeout: 1000 });
4902
- }
4903
- catch (e) {
4904
- // If we can't transition, continue anyway - the waitFor below will catch any errors
4905
- logger('Timeout waiting for state transition, continuing...');
4986
+ /**
4987
+ * Initialise the SDK. Calls made while an init is running share it. Once initialised, a
4988
+ * call with the same config resolves at once and applies any change in `addresses`; a
4989
+ * call with a different config throws INIT_CONFIG_CONFLICT_MESSAGE (call stop() first).
4990
+ */
4991
+ init: async (options) => {
4992
+ if (activeInitConfig !== undefined && !isEqual(activeInitConfig, options?.config)) {
4993
+ throw new Error(INIT_CONFIG_CONFLICT_MESSAGE);
4906
4994
  }
4995
+ const isRepeat = activeInitConfig !== undefined;
4996
+ activeInitConfig = options?.config;
4907
4997
  try {
4908
- await waitFor(clientManager, (snapshot) => {
4909
- return snapshot.context.isInitialized || snapshot.context.initError != null;
4910
- }, { timeout: 120000 });
4911
- const initError = clientManager.getSnapshot().context.initError;
4912
- if (initError) {
4913
- throw initError instanceof Error ? initError : new Error(String(initError));
4914
- }
4998
+ await coalescedInit(options);
4915
4999
  }
4916
5000
  catch (error) {
4917
- // Ensure we never throw undefined
4918
- if (error === undefined || error === null) {
4919
- throw new Error('Initialization failed with undefined error');
4920
- }
5001
+ activeInitConfig = undefined;
4921
5002
  throw error;
4922
5003
  }
4923
- // Wire `@seedprotocol/query` local source once DB is ready
4924
- registerSeedQueryLocalSource({ force: true });
4925
- }, () => {
4926
- const snapshot = clientManager.getSnapshot();
4927
- return (snapshot.value === ClientManagerState.IDLE &&
4928
- snapshot.context.isInitialized === true &&
4929
- !snapshot.context.initError);
4930
- }),
5004
+ if (isRepeat && options?.addresses !== undefined) {
5005
+ const wanted = normalizeAddressConfig(options.addresses);
5006
+ const current = { owned: await getOwnedAddressesFromDb(), watched: await getWatchedAddressesFromDb() };
5007
+ if (!isEqual(wanted, current)) {
5008
+ await clientInstance.setAddresses(wanted);
5009
+ }
5010
+ }
5011
+ },
4931
5012
  setAddresses: async (addresses) => {
4932
5013
  ensureInitialized();
4933
5014
  logger('setAddresses', addresses);
@@ -4960,7 +5041,10 @@ const clientInstance = {
4960
5041
  */
4961
5042
  claimUnpublishedDrafts: async (publisher) => {
4962
5043
  ensureInitialized();
4963
- return claimUnpublishedDrafts(publisher);
5044
+ const result = await claimUnpublishedDrafts(publisher);
5045
+ // Loaded Items read publisher from their context; give the claimed ones the new value.
5046
+ Item.setPublisherForCachedSeeds(result.seedLocalIds, publisher);
5047
+ return result;
4964
5048
  },
4965
5049
  /**
4966
5050
  * Hard-delete local on-chain seed copies for the given publisher addresses.
@@ -5015,21 +5099,38 @@ const clientInstance = {
5015
5099
  // Global service removed - model registration is now handled by ClientManager
5016
5100
  // Models are added to DB during the ADD_MODELS_TO_DB state
5017
5101
  },
5102
+ /**
5103
+ * Calls `callback` once the client is initialised, or on the next microtask if it already
5104
+ * is. Returns a function that cancels the callback.
5105
+ */
5018
5106
  onReady: (callback) => {
5107
+ if (clientManager.getSnapshot().context.isInitialized) {
5108
+ let cancelled = false;
5109
+ queueMicrotask(() => {
5110
+ if (!cancelled)
5111
+ callback();
5112
+ });
5113
+ return () => {
5114
+ cancelled = true;
5115
+ };
5116
+ }
5019
5117
  const subscription = clientManager.subscribe((snapshot) => {
5020
5118
  if (snapshot.context.isInitialized) {
5021
5119
  subscription.unsubscribe();
5022
5120
  callback();
5023
5121
  }
5024
5122
  });
5123
+ return () => subscription.unsubscribe();
5025
5124
  },
5026
5125
  stop: () => {
5027
5126
  ensureInitialized();
5127
+ activeInitConfig = undefined;
5028
5128
  unregisterSeedQueryLocalSource();
5029
5129
  clientManager.stop();
5030
5130
  },
5031
5131
  unload: () => {
5032
5132
  ensureInitialized();
5133
+ activeInitConfig = undefined;
5033
5134
  unregisterSeedQueryLocalSource();
5034
5135
  clientManager.stop();
5035
5136
  subscription.unsubscribe();
@@ -5045,9 +5146,10 @@ const getClient = () => {
5045
5146
  var ClientManager$1 = /*#__PURE__*/Object.freeze({
5046
5147
  __proto__: null,
5047
5148
  ClientManager: ClientManager,
5149
+ INIT_CONFIG_CONFLICT_MESSAGE: INIT_CONFIG_CONFLICT_MESSAGE,
5048
5150
  clientManager: clientManager,
5049
5151
  getClient: getClient
5050
5152
  });
5051
5153
 
5052
- export { requestEasSyncFromModelsInit as A, sendEasSyncClientRequest as B, ClientManager as C, startEasSyncActor as D, EAS_CHAIN_ID_APP_STATE_KEY as E, unregisterSeedQueryLocalSource as F, createModelsFromJson as G, getLatestSchemaVersion as H, schema as I, ClientManager$1 as J, SEEDPROTOCOL_Seed_Protocol_v1 as S, assertLocalDbChain as a, importJsonSchema as b, convertVerbatimItemStorageRow as c, getContentHash as d, claimUnpublishedDrafts as e, createLocalQueryDataSource as f, getRefValueType as g, createSchema as h, isVerbatimItemStorageDraftRow as i, easSyncActor as j, getClient as k, loadSchemaFromFile as l, getPublishedSeedRecord as m, getSchemaNameFromId as n, isSeedQueryLocalSourceRegistered as o, listCompleteSchemaFiles as p, loadAllSchemasFromDb as q, readJsonImportFile as r, syncSchemaFromSource as s, transformImportToSchemaFile as t, mergeEasSyncRequestIntents as u, readSchema as v, waitForEasReadChain as w, registerSeedQueryLocalSource as x, requestEasSyncFromAddressChange as y, requestEasSyncFromEventBus as z };
5053
- //# sourceMappingURL=ClientManager-C-QXqUK9.js.map
5154
+ export { requestEasSyncFromModelsInit as A, sendEasSyncClientRequest as B, ClientManager as C, startEasSyncActor as D, EAS_CHAIN_ID_APP_STATE_KEY as E, unregisterSeedQueryLocalSource as F, createModelsFromJson as G, getLatestSchemaVersion as H, INIT_CONFIG_CONFLICT_MESSAGE as I, jsonPropertiesToSchemaProperties as J, schema as K, ClientManager$1 as L, SEEDPROTOCOL_Seed_Protocol_v1 as S, assertLocalDbChain as a, importJsonSchema as b, convertVerbatimItemStorageRow as c, getContentHash as d, claimUnpublishedDrafts as e, createLocalQueryDataSource as f, getRefValueType as g, createSchema as h, isVerbatimItemStorageDraftRow as i, easSyncActor as j, getClient as k, loadSchemaFromFile as l, getPublishedSeedRecord as m, getSchemaNameFromId as n, isSeedQueryLocalSourceRegistered as o, listCompleteSchemaFiles as p, loadAllSchemasFromDb as q, readJsonImportFile as r, syncSchemaFromSource as s, transformImportToSchemaFile as t, mergeEasSyncRequestIntents as u, readSchema as v, waitForEasReadChain as w, registerSeedQueryLocalSource as x, requestEasSyncFromAddressChange as y, requestEasSyncFromEventBus as z };
5155
+ //# sourceMappingURL=ClientManager-i3nJASkg.js.map