@pkcprotocol/pkc-js 0.0.18 → 0.0.20

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 (149) hide show
  1. package/dist/browser/clients/base-client-manager.d.ts +6 -0
  2. package/dist/browser/clients/base-client-manager.js +36 -2
  3. package/dist/browser/clients/base-client-manager.js.map +1 -1
  4. package/dist/browser/community/community-client-manager.js +2 -2
  5. package/dist/browser/community/community-client-manager.js.map +1 -1
  6. package/dist/browser/errors.d.ts +1 -0
  7. package/dist/browser/errors.js +1 -0
  8. package/dist/browser/errors.js.map +1 -1
  9. package/dist/browser/generated-version.d.ts +1 -1
  10. package/dist/browser/generated-version.js +1 -1
  11. package/dist/browser/pages/pages-client-manager.d.ts +16 -3
  12. package/dist/browser/pages/pages-client-manager.js +32 -14
  13. package/dist/browser/pages/pages-client-manager.js.map +1 -1
  14. package/dist/browser/pages/pages.d.ts +5 -1
  15. package/dist/browser/pages/pages.js +16 -8
  16. package/dist/browser/pages/pages.js.map +1 -1
  17. package/dist/browser/pages/schema-util.js +2 -2
  18. package/dist/browser/pages/schema-util.js.map +1 -1
  19. package/dist/browser/pages/schema.d.ts +1 -1
  20. package/dist/browser/pages/schema.js +1 -1
  21. package/dist/browser/pages/schema.js.map +1 -1
  22. package/dist/browser/pages/types.d.ts +5 -2
  23. package/dist/browser/pages/util.js +15 -5
  24. package/dist/browser/pages/util.js.map +1 -1
  25. package/dist/browser/pkc/pkc.d.ts +2 -0
  26. package/dist/browser/pkc/pkc.js +8 -0
  27. package/dist/browser/pkc/pkc.js.map +1 -1
  28. package/dist/browser/pkc/tracked-instance-registry-util.js +2 -1
  29. package/dist/browser/pkc/tracked-instance-registry-util.js.map +1 -1
  30. package/dist/browser/pkc-error.d.ts +1 -1
  31. package/dist/browser/publications/comment/comment-client-manager.d.ts +3 -0
  32. package/dist/browser/publications/comment/comment-client-manager.js +33 -3
  33. package/dist/browser/publications/comment/comment-client-manager.js.map +1 -1
  34. package/dist/browser/publications/comment/comment.js +4 -4
  35. package/dist/browser/publications/comment/comment.js.map +1 -1
  36. package/dist/browser/publications/comment/schema.d.ts +16 -190
  37. package/dist/browser/publications/comment/schema.js +10 -1
  38. package/dist/browser/publications/comment/schema.js.map +1 -1
  39. package/dist/browser/publications/comment/types.d.ts +8 -1
  40. package/dist/browser/publications/publication-author.d.ts +1 -2
  41. package/dist/browser/publications/publication-author.js +2 -6
  42. package/dist/browser/publications/publication-author.js.map +1 -1
  43. package/dist/browser/publications/publication.js +21 -1
  44. package/dist/browser/publications/publication.js.map +1 -1
  45. package/dist/browser/rpc/src/index.d.ts +2 -1
  46. package/dist/browser/rpc/src/index.js +24 -8
  47. package/dist/browser/rpc/src/index.js.map +1 -1
  48. package/dist/browser/rpc/src/schema.d.ts +1 -0
  49. package/dist/browser/rpc/src/schema.js +4 -1
  50. package/dist/browser/rpc/src/schema.js.map +1 -1
  51. package/dist/browser/runtime/node/community/db-handler-types.d.ts +3 -3
  52. package/dist/browser/runtime/node/community/db-handler.d.ts +19 -4
  53. package/dist/browser/runtime/node/community/db-handler.js +367 -78
  54. package/dist/browser/runtime/node/community/db-handler.js.map +1 -1
  55. package/dist/browser/runtime/node/community/local-community.d.ts +1 -0
  56. package/dist/browser/runtime/node/community/local-community.js +108 -33
  57. package/dist/browser/runtime/node/community/local-community.js.map +1 -1
  58. package/dist/browser/runtime/node/community/page-generator.d.ts +11 -5
  59. package/dist/browser/runtime/node/community/page-generator.js +13 -8
  60. package/dist/browser/runtime/node/community/page-generator.js.map +1 -1
  61. package/dist/browser/runtime/node/util.d.ts +13 -1
  62. package/dist/browser/runtime/node/util.js +88 -1
  63. package/dist/browser/runtime/node/util.js.map +1 -1
  64. package/dist/browser/signer/encryption.js +8 -4
  65. package/dist/browser/signer/encryption.js.map +1 -1
  66. package/dist/browser/signer/signatures.d.ts +1 -1
  67. package/dist/browser/signer/signatures.js +3 -3
  68. package/dist/browser/signer/signatures.js.map +1 -1
  69. package/dist/browser/signer/util.js +4 -4
  70. package/dist/browser/signer/util.js.map +1 -1
  71. package/dist/browser/util.d.ts +11 -0
  72. package/dist/browser/util.js +43 -1
  73. package/dist/browser/util.js.map +1 -1
  74. package/dist/browser/version.js +1 -1
  75. package/dist/node/clients/base-client-manager.d.ts +6 -0
  76. package/dist/node/clients/base-client-manager.js +36 -2
  77. package/dist/node/clients/base-client-manager.js.map +1 -1
  78. package/dist/node/community/community-client-manager.js +2 -2
  79. package/dist/node/community/community-client-manager.js.map +1 -1
  80. package/dist/node/errors.d.ts +1 -0
  81. package/dist/node/errors.js +1 -0
  82. package/dist/node/errors.js.map +1 -1
  83. package/dist/node/generated-version.d.ts +1 -1
  84. package/dist/node/generated-version.js +1 -1
  85. package/dist/node/pages/pages-client-manager.d.ts +16 -3
  86. package/dist/node/pages/pages-client-manager.js +32 -14
  87. package/dist/node/pages/pages-client-manager.js.map +1 -1
  88. package/dist/node/pages/pages.d.ts +5 -1
  89. package/dist/node/pages/pages.js +16 -8
  90. package/dist/node/pages/pages.js.map +1 -1
  91. package/dist/node/pages/schema-util.js +2 -2
  92. package/dist/node/pages/schema-util.js.map +1 -1
  93. package/dist/node/pages/schema.d.ts +1 -1
  94. package/dist/node/pages/schema.js +1 -1
  95. package/dist/node/pages/schema.js.map +1 -1
  96. package/dist/node/pages/types.d.ts +5 -2
  97. package/dist/node/pages/util.js +15 -5
  98. package/dist/node/pages/util.js.map +1 -1
  99. package/dist/node/pkc/pkc.d.ts +2 -0
  100. package/dist/node/pkc/pkc.js +8 -0
  101. package/dist/node/pkc/pkc.js.map +1 -1
  102. package/dist/node/pkc/tracked-instance-registry-util.js +2 -1
  103. package/dist/node/pkc/tracked-instance-registry-util.js.map +1 -1
  104. package/dist/node/pkc-error.d.ts +1 -1
  105. package/dist/node/publications/comment/comment-client-manager.d.ts +3 -0
  106. package/dist/node/publications/comment/comment-client-manager.js +33 -3
  107. package/dist/node/publications/comment/comment-client-manager.js.map +1 -1
  108. package/dist/node/publications/comment/comment.js +4 -4
  109. package/dist/node/publications/comment/comment.js.map +1 -1
  110. package/dist/node/publications/comment/schema.d.ts +16 -190
  111. package/dist/node/publications/comment/schema.js +10 -1
  112. package/dist/node/publications/comment/schema.js.map +1 -1
  113. package/dist/node/publications/comment/types.d.ts +8 -1
  114. package/dist/node/publications/publication-author.d.ts +1 -2
  115. package/dist/node/publications/publication-author.js +2 -6
  116. package/dist/node/publications/publication-author.js.map +1 -1
  117. package/dist/node/publications/publication.js +21 -1
  118. package/dist/node/publications/publication.js.map +1 -1
  119. package/dist/node/rpc/src/index.d.ts +2 -1
  120. package/dist/node/rpc/src/index.js +24 -8
  121. package/dist/node/rpc/src/index.js.map +1 -1
  122. package/dist/node/rpc/src/schema.d.ts +1 -0
  123. package/dist/node/rpc/src/schema.js +4 -1
  124. package/dist/node/rpc/src/schema.js.map +1 -1
  125. package/dist/node/runtime/node/community/db-handler-types.d.ts +3 -3
  126. package/dist/node/runtime/node/community/db-handler.d.ts +19 -4
  127. package/dist/node/runtime/node/community/db-handler.js +367 -78
  128. package/dist/node/runtime/node/community/db-handler.js.map +1 -1
  129. package/dist/node/runtime/node/community/local-community.d.ts +1 -0
  130. package/dist/node/runtime/node/community/local-community.js +108 -33
  131. package/dist/node/runtime/node/community/local-community.js.map +1 -1
  132. package/dist/node/runtime/node/community/page-generator.d.ts +11 -5
  133. package/dist/node/runtime/node/community/page-generator.js +13 -8
  134. package/dist/node/runtime/node/community/page-generator.js.map +1 -1
  135. package/dist/node/runtime/node/util.d.ts +13 -1
  136. package/dist/node/runtime/node/util.js +88 -1
  137. package/dist/node/runtime/node/util.js.map +1 -1
  138. package/dist/node/signer/encryption.js +8 -4
  139. package/dist/node/signer/encryption.js.map +1 -1
  140. package/dist/node/signer/signatures.d.ts +1 -1
  141. package/dist/node/signer/signatures.js +3 -3
  142. package/dist/node/signer/signatures.js.map +1 -1
  143. package/dist/node/signer/util.js +4 -4
  144. package/dist/node/signer/util.js.map +1 -1
  145. package/dist/node/util.d.ts +11 -0
  146. package/dist/node/util.js +43 -1
  147. package/dist/node/util.js.map +1 -1
  148. package/dist/node/version.js +1 -1
  149. package/package.json +21 -22
@@ -2,6 +2,7 @@ import Logger from "../../../logger.js";
2
2
  import { LRUCache } from "lru-cache";
3
3
  import { PageGenerator } from "./page-generator.js";
4
4
  import { DbHandler } from "./db-handler.js";
5
+ import { deriveDbReplies, deriveDbPosts, resolveDbPostsCidRefs } from "../util.js";
5
6
  import { of as calculateIpfsHash } from "typestub-ipfs-only-hash";
6
7
  import { derivePublicationFromChallengeRequest, doesDomainAddressHaveCapitalLetter, genToArray, hideClassPrivateProps, ipnsNameToIpnsOverPubsubTopic, isLinkOfMedia, isLinkOfImage, isLinkOfVideo, isLinkOfAnimatedImage, isLinkValid, isStringDomain, pubsubTopicToDhtKey, timestamp, getErrorCodeFromMessage, removeMfsFilesSafely, removeBlocksFromKuboNode, writeKuboFilesWithTimeout, retryKuboIpfsAddAndProvide, retryKuboBlockPutPinAndProvidePubsubTopic, calculateIpfsCidV0, calculateStringSizeSameAsIpfsAddCidV0, getIpnsRecordInLocalKuboNode, contentContainsMarkdownImages, contentContainsMarkdownVideos, isLinkOfAudio, contentContainsMarkdownAudio, areEquivalentCommunityAddresses } from "../../../util.js";
7
8
  import { STORAGE_KEYS } from "../../../constants.js";
@@ -18,7 +19,7 @@ import env from "../../../version.js";
18
19
  import { getIpfsKeyFromPrivateKey, getPKCAddressFromPublicKey, getPublicKeyFromPrivateKey } from "../../../signer/util.js";
19
20
  import { RpcLocalCommunity } from "../../../community/rpc-local-community.js";
20
21
  import * as remeda from "remeda";
21
- import { buildRuntimeAuthor, cleanWireAuthor, getAuthorDomainFromWire, getAuthorNameFromWire } from "../../../publications/publication-author.js";
22
+ import { buildRuntimeAuthor, cleanWireAuthor, getAuthorNameFromWire } from "../../../publications/publication-author.js";
22
23
  import { getCommunityPublicKeyFromWire, getCommunityNameFromWire } from "../../../publications/publication-community.js";
23
24
  import { CommentEditPubsubMessagePublicationSchema, CommentEditPubsubMessagePublicationWithFlexibleAuthorSchema, CommentEditReservedFields } from "../../../publications/comment-edit/schema.js";
24
25
  import { CommunityIpfsSchema, CommunitySignedPropertyNames } from "../../../community/schema.js";
@@ -83,6 +84,7 @@ export class LocalCommunity extends RpcLocalCommunity {
83
84
  this._mirroredStartedOrUpdatingCommunity = undefined; // The pkc._startedCommunities we're subscribed to
84
85
  this._pendingEditProps = [];
85
86
  this._blocksToRm = [];
87
+ this._postsAllPageCids = undefined;
86
88
  this.handleChallengeExchange = this.handleChallengeExchange.bind(this);
87
89
  this._setState("stopped");
88
90
  this.started = false;
@@ -104,7 +106,10 @@ export class LocalCommunity extends RpcLocalCommunity {
104
106
  this._dbHandler = undefined;
105
107
  hideClassPrivateProps(this);
106
108
  }
107
- // This will be stored in DB
109
+ // This will be stored in DB and also shared between instances via _updateInstancePropsWithStartedCommunityOrDb.
110
+ // Must NOT convert posts to CID-ref format here — that's only for DB storage (done in _updateDbInternalState).
111
+ // CID-ref conversion strips preloaded page data which breaks reply CommentUpdate resolution
112
+ // when other instances read the shared state.
108
113
  toJSONInternalAfterFirstUpdate() {
109
114
  const rpcJson = this.toJSONInternalRpcAfterFirstUpdate();
110
115
  return {
@@ -164,6 +169,29 @@ export class LocalCommunity extends RpcLocalCommunity {
164
169
  this.settings = newProps.settings;
165
170
  }
166
171
  async initInternalCommunityAfterFirstUpdateNoMerge(newProps) {
172
+ // Detect CID-ref format posts from DB: wire format always has 'pages' key, CID-ref format doesn't
173
+ if (newProps.posts && !("pages" in newProps.posts)) {
174
+ const dbPosts = newProps.posts;
175
+ // Extract allPageCids for future unpinning
176
+ const allPageCids = {};
177
+ for (const [sortName, entry] of Object.entries(dbPosts)) {
178
+ if (entry?.allPageCids?.length)
179
+ allPageCids[sortName] = entry.allPageCids;
180
+ }
181
+ this._postsAllPageCids = Object.keys(allPageCids).length > 0 ? allPageCids : undefined;
182
+ // Lightweight conversion: just pageCids from allPageCids[0], preloaded pages regenerated on next update.
183
+ // Never use resolveDbPostsCidRefs here — this method is called from many code paths
184
+ // where _dbHandler._db may not be initialized (e.g. updateListener from a mirrored community).
185
+ const pageCids = {};
186
+ for (const [sortName, entry] of Object.entries(dbPosts)) {
187
+ if (entry?.allPageCids?.[0])
188
+ pageCids[sortName] = entry.allPageCids[0];
189
+ }
190
+ newProps = {
191
+ ...newProps,
192
+ posts: { pages: {}, ...(Object.keys(pageCids).length > 0 ? { pageCids } : {}) }
193
+ };
194
+ }
167
195
  const keysOfCommunityIpfs = [...CommunitySignedPropertyNames, "signature"];
168
196
  this.initRpcInternalCommunityAfterFirstUpdateNoMerge({
169
197
  community: remeda.pick(newProps, keysOfCommunityIpfs),
@@ -288,7 +316,17 @@ export class LocalCommunity extends RpcLocalCommunity {
288
316
  await this._dbHandler.lockCommunityState();
289
317
  lockedIt = true;
290
318
  const internalStateBefore = await this._getDbInternalState(false);
291
- const mergedInternalState = { ...internalStateBefore, ...props };
319
+ // Convert posts to CID-ref format for compact DB storage (strip preloaded page data)
320
+ const propsToStore = "posts" in props && props.posts
321
+ ? {
322
+ ...props,
323
+ posts: deriveDbPosts({
324
+ posts: props.posts,
325
+ allPageCids: this._postsAllPageCids
326
+ })
327
+ }
328
+ : props;
329
+ const mergedInternalState = { ...internalStateBefore, ...propsToStore };
292
330
  await this._dbHandler.keyvSet(STORAGE_KEYS[STORAGE_KEYS.INTERNAL_COMMUNITY], mergedInternalState);
293
331
  this._internalStateUpdateId = props._internalStateUpdateId;
294
332
  log.trace("Updated community", this.address, "internal state in db with new props", Object.keys(props));
@@ -336,6 +374,13 @@ export class LocalCommunity extends RpcLocalCommunity {
336
374
  async _updateInstanceStateWithDbState() {
337
375
  const currentDbState = await this._getDbInternalState(false);
338
376
  if ("updatedAt" in currentDbState) {
377
+ // Resolve CID-ref posts from DB back to full wire format with preloaded pages.
378
+ // DB stores posts in compact CID-ref format (no preloaded page data).
379
+ // _dbHandler is guaranteed to be initialized here since we're loading from DB.
380
+ if (currentDbState.posts && !("pages" in currentDbState.posts)) {
381
+ const dbPosts = currentDbState.posts;
382
+ currentDbState.posts = resolveDbPostsCidRefs({ dbPosts, dbHandler: this._dbHandler });
383
+ }
339
384
  await this.initInternalCommunityAfterFirstUpdateNoMerge(currentDbState);
340
385
  }
341
386
  else
@@ -534,6 +579,8 @@ export class LocalCommunity extends RpcLocalCommunity {
534
579
  const availablePostsSize = MAX_FILE_SIZE_BYTES_FOR_COMMUNITY_IPFS - communityWithoutPostsSignatureSize - expectedSignatureSize - 1000;
535
580
  const generatedPosts = await this._pageGenerator.generateCommunityPosts(preloadedPostsPages, availablePostsSize);
536
581
  // posts should not be cleaned up because we want to make sure not to modify authors' posts
582
+ // Extract allPageCids from generation result for DB CID-ref storage and unpinning
583
+ const newPostsAllPageCids = generatedPosts && !("singlePreloadedPage" in generatedPosts) ? generatedPosts.allPageCids : undefined;
537
584
  if (generatedPosts) {
538
585
  if ("singlePreloadedPage" in generatedPosts)
539
586
  newIpns.posts = { pages: generatedPosts.singlePreloadedPage };
@@ -547,9 +594,17 @@ export class LocalCommunity extends RpcLocalCommunity {
547
594
  }
548
595
  else {
549
596
  await this._updateDbInternalState({ posts: undefined }); // make sure db resets posts as well
550
- // TODO make sure to capture this.posts cids to unpin
551
597
  }
552
- this._addOldPageCidsToCidsToUnpin(this.raw.communityIpfs?.posts, newIpns.posts).catch((err) => log.error("Failed to add old page cids of community.posts to _cidsToUnpin", err));
598
+ // Unpin old posts page CIDs using direct allPageCids comparison (no IPFS fetches needed)
599
+ {
600
+ const oldCids = new Set(this._postsAllPageCids ? Object.values(this._postsAllPageCids).flat() : []);
601
+ const newCids = new Set(newPostsAllPageCids ? Object.values(newPostsAllPageCids).flat() : []);
602
+ for (const cid of oldCids) {
603
+ if (!newCids.has(cid))
604
+ this._cidsToUnPin.add(cid);
605
+ }
606
+ }
607
+ this._postsAllPageCids = newPostsAllPageCids;
553
608
  if (newModQueue) {
554
609
  newIpns.modQueue = { pageCids: newModQueue.pageCids };
555
610
  }
@@ -779,12 +834,12 @@ export class LocalCommunity extends RpcLocalCommunity {
779
834
  // Check if the comment was published with pseudonymity - if so, get the original author address/domain
780
835
  const aliasInfo = this._dbHandler.queryPseudonymityAliasByCommentCid(commentModRaw.commentCid);
781
836
  if (aliasInfo) {
782
- targetAuthorSignerAddress = await getPKCAddressFromPublicKey(aliasInfo.originalAuthorSignerPublicKey);
783
- targetAuthorDomain = aliasInfo.originalAuthorDomain || undefined;
837
+ targetAuthorSignerAddress = await getPKCAddressFromPublicKey(aliasInfo.originalAuthorPublicKey);
838
+ targetAuthorDomain = aliasInfo.originalAuthorName || undefined;
784
839
  }
785
840
  else {
786
841
  targetAuthorSignerAddress = commentToBeEdited.authorSignerAddress;
787
- targetAuthorDomain = getAuthorDomainFromWire(commentToBeEdited.author);
842
+ targetAuthorDomain = getAuthorNameFromWire(commentToBeEdited.author);
788
843
  }
789
844
  }
790
845
  const modTableRow = {
@@ -905,7 +960,7 @@ export class LocalCommunity extends RpcLocalCommunity {
905
960
  if (opts.mode === "per-post") {
906
961
  // For a new post (no postCid yet), always generate a fresh alias; once stored the postCid will be used for reuse.
907
962
  if (opts.postCid) {
908
- const existing = this._dbHandler.queryPseudonymityAliasForPost(opts.originalAuthorSignerPublicKey, opts.postCid);
963
+ const existing = this._dbHandler.queryPseudonymityAliasForPost(opts.originalAuthorPublicKey, opts.postCid);
909
964
  if (existing?.aliasPrivateKey)
910
965
  return existing.aliasPrivateKey;
911
966
  }
@@ -916,7 +971,7 @@ export class LocalCommunity extends RpcLocalCommunity {
916
971
  return signer.privateKey;
917
972
  }
918
973
  else if (opts.mode === "per-author") {
919
- const existing = this._dbHandler.queryPseudonymityAliasForAuthor(opts.originalAuthorSignerPublicKey);
974
+ const existing = this._dbHandler.queryPseudonymityAliasForAuthor(opts.originalAuthorPublicKey);
920
975
  if (existing?.aliasPrivateKey)
921
976
  return existing.aliasPrivateKey;
922
977
  const signer = await this._pkc.createSigner();
@@ -933,11 +988,11 @@ export class LocalCommunity extends RpcLocalCommunity {
933
988
  const isAuthorMod = await this._isPublicationAuthorPartOfRoles(originalComment, ["owner", "admin", "moderator"]);
934
989
  if (isAuthorMod)
935
990
  return { publication: originalComment };
936
- const originalAuthorSignerPublicKey = originalComment.signature.publicKey;
991
+ const originalAuthorPublicKey = originalComment.signature.publicKey;
937
992
  const postCid = originalComment.postCid;
938
993
  const aliasPrivateKey = await this._resolveAliasPrivateKeyForCommentPublication({
939
994
  mode,
940
- originalAuthorSignerPublicKey,
995
+ originalAuthorPublicKey,
941
996
  postCid
942
997
  });
943
998
  const aliasSigner = await this._pkc.createSigner({ privateKey: aliasPrivateKey, type: "ed25519" });
@@ -958,7 +1013,7 @@ export class LocalCommunity extends RpcLocalCommunity {
958
1013
  publication: anonymizedComment,
959
1014
  anonymity: {
960
1015
  aliasPrivateKey,
961
- originalAuthorSignerPublicKey,
1016
+ originalAuthorPublicKey,
962
1017
  mode,
963
1018
  originalComment
964
1019
  }
@@ -1080,8 +1135,8 @@ export class LocalCommunity extends RpcLocalCommunity {
1080
1135
  {
1081
1136
  commentCid: storedComment.cid,
1082
1137
  aliasPrivateKey: anonymity.aliasPrivateKey,
1083
- originalAuthorSignerPublicKey: anonymity.originalAuthorSignerPublicKey,
1084
- originalAuthorDomain: getAuthorDomainFromWire(anonymity.originalComment.author) || null,
1138
+ originalAuthorPublicKey: anonymity.originalAuthorPublicKey,
1139
+ originalAuthorName: getAuthorNameFromWire(anonymity.originalComment.author) || null,
1085
1140
  mode: anonymity.mode,
1086
1141
  insertedAt: timestamp()
1087
1142
  }
@@ -1210,7 +1265,7 @@ export class LocalCommunity extends RpcLocalCommunity {
1210
1265
  }
1211
1266
  log("Returning idempotent success for duplicate comment", existingComment.cid);
1212
1267
  const authorSignerAddress = await getPKCAddressFromPublicKey(existingComment.signature.publicKey);
1213
- const authorDomain = getAuthorDomainFromWire(existingComment.author);
1268
+ const authorDomain = getAuthorNameFromWire(existingComment.author);
1214
1269
  const authorCommunity = this._dbHandler.queryCommunityAuthor(authorSignerAddress, authorDomain);
1215
1270
  if (!authorCommunity) {
1216
1271
  return this._publishFailedChallengeVerification({ reason: duplicateReason }, challengeRequestId);
@@ -1267,7 +1322,7 @@ export class LocalCommunity extends RpcLocalCommunity {
1267
1322
  if (!commentAfterAddingToIpfs)
1268
1323
  return undefined;
1269
1324
  const authorSignerAddress = await getPKCAddressFromPublicKey(commentAfterAddingToIpfs.comment.signature.publicKey);
1270
- const authorDomain = getAuthorDomainFromWire(commentAfterAddingToIpfs.comment.author);
1325
+ const authorDomain = getAuthorNameFromWire(commentAfterAddingToIpfs.comment.author);
1271
1326
  const authorCommunity = this._dbHandler.queryCommunityAuthor(authorSignerAddress, authorDomain);
1272
1327
  if (!authorCommunity)
1273
1328
  throw Error("author.community can never be undefined after adding a comment");
@@ -1667,7 +1722,7 @@ export class LocalCommunity extends RpcLocalCommunity {
1667
1722
  return messages.ERR_DUPLICATE_COMMENT_EDIT;
1668
1723
  const aliasSignerOfComment = this._dbHandler.queryPseudonymityAliasByCommentCid(commentToBeEdited.cid);
1669
1724
  if (aliasSignerOfComment) {
1670
- const editSignedByOriginalAuthor = commentEditPublication.signature.publicKey === aliasSignerOfComment.originalAuthorSignerPublicKey;
1725
+ const editSignedByOriginalAuthor = commentEditPublication.signature.publicKey === aliasSignerOfComment.originalAuthorPublicKey;
1671
1726
  if (!editSignedByOriginalAuthor)
1672
1727
  return messages.ERR_COMMENT_EDIT_CAN_NOT_EDIT_COMMENT_IF_NOT_ORIGINAL_AUTHOR;
1673
1728
  }
@@ -1812,7 +1867,7 @@ export class LocalCommunity extends RpcLocalCommunity {
1812
1867
  return this._publishFailedChallengeVerification({ reason: messages.ERR_PUBLICATION_USES_DEPRECATED_COMMUNITY_ADDRESS }, request.challengeRequestId);
1813
1868
  }
1814
1869
  const authorSignerAddress = await getPKCAddressFromPublicKey(publication.signature.publicKey);
1815
- const authorDomain = getAuthorDomainFromWire(publication.author);
1870
+ const authorDomain = getAuthorNameFromWire(publication.author);
1816
1871
  // Check publication props validity
1817
1872
  const communityAuthor = this._dbHandler.queryCommunityAuthor(authorSignerAddress, authorDomain);
1818
1873
  const decryptedRequestMsg = { ...request, ...decryptedRequest };
@@ -1988,8 +2043,8 @@ export class LocalCommunity extends RpcLocalCommunity {
1988
2043
  log.trace(`Attempting to calculate new CommentUpdate for comment (${comment.cid}) on community`, this.address);
1989
2044
  // This comment will have the local new CommentUpdate, which we will publish to IPFS fiels
1990
2045
  // It includes new author.community as well as updated values in CommentUpdate (except for replies field)
1991
- const storedCommentUpdate = this._dbHandler.queryStoredCommentUpdate(comment);
1992
- const authorDomain = getAuthorDomainFromWire(comment.author);
2046
+ const storedCommentUpdate = this._dbHandler.queryCommentUpdateTimestampBucketReplies({ cid: comment.cid });
2047
+ const authorDomain = getAuthorNameFromWire(comment.author);
1993
2048
  const calculatedCommentUpdate = this._dbHandler.queryCalculatedCommentUpdate({ comment, authorDomain });
1994
2049
  log.trace("Calculated comment update for comment", comment.cid, "on community", this.address, "with reply count", calculatedCommentUpdate.replyCount);
1995
2050
  const currentTimestamp = timestamp();
@@ -2023,7 +2078,18 @@ export class LocalCommunity extends RpcLocalCommunity {
2023
2078
  };
2024
2079
  }
2025
2080
  }
2026
- this._addOldPageCidsToCidsToUnpin(storedCommentUpdate?.replies, commentUpdatePriorToSigning.replies).catch((err) => log.error("Failed to add old page cids of comment.replies to _cidsToUnpin", err));
2081
+ // Extract allPageCids from the generation result (not available for singlePreloadedPage case)
2082
+ const allPageCids = generatedRepliesPages && !("singlePreloadedPage" in generatedRepliesPages) ? generatedRepliesPages.allPageCids : undefined;
2083
+ // Unpin old page CIDs that are no longer in the new generation
2084
+ {
2085
+ const oldDbReplies = storedCommentUpdate?.replies;
2086
+ const oldCids = new Set(oldDbReplies ? Object.values(oldDbReplies).flatMap((sort) => sort?.allPageCids ?? []) : []);
2087
+ const newCids = new Set(allPageCids ? Object.values(allPageCids).flat() : []);
2088
+ for (const cid of oldCids) {
2089
+ if (!newCids.has(cid))
2090
+ this._cidsToUnPin.add(cid);
2091
+ }
2092
+ }
2027
2093
  const newCommentUpdate = {
2028
2094
  ...commentUpdatePriorToSigning,
2029
2095
  signature: await signCommentUpdate({ update: commentUpdatePriorToSigning, signer: this.signer })
@@ -2040,12 +2106,12 @@ export class LocalCommunity extends RpcLocalCommunity {
2040
2106
  }
2041
2107
  const newCommentUpdateDbRecord = {
2042
2108
  ...newCommentUpdate,
2109
+ // Store CID refs instead of full inline page data — see deriveDbReplies()
2110
+ replies: deriveDbReplies({ replies: newCommentUpdate.replies, allPageCids }),
2043
2111
  postUpdatesBucket: newPostUpdateBucket,
2044
2112
  publishedToPostUpdatesMFS: false,
2045
2113
  insertedAt: timestamp()
2046
2114
  };
2047
- if (!generatedRepliesPages)
2048
- newCommentUpdateDbRecord.replies = undefined;
2049
2115
  return {
2050
2116
  newCommentUpdate,
2051
2117
  newCommentUpdateToWriteToDb: newCommentUpdateDbRecord,
@@ -2358,15 +2424,24 @@ export class LocalCommunity extends RpcLocalCommunity {
2358
2424
  }
2359
2425
  }
2360
2426
  async _addAllCidsUnderPurgedCommentToBeRemoved(purgedCommentAndCommentUpdate) {
2361
- const log = Logger("pkc-js:_addAllCidsUnderPurgedCommentToBeRemoved");
2362
2427
  this._cidsToUnPin.add(purgedCommentAndCommentUpdate.commentTableRow.cid);
2363
2428
  this._blocksToRm.push(purgedCommentAndCommentUpdate.commentTableRow.cid);
2364
2429
  if (typeof purgedCommentAndCommentUpdate.commentUpdateTableRow?.postUpdatesBucket === "number") {
2365
2430
  const localCommentUpdatePath = this._calculateLocalMfsPathForCommentUpdate(purgedCommentAndCommentUpdate.commentTableRow, purgedCommentAndCommentUpdate.commentUpdateTableRow?.postUpdatesBucket);
2366
2431
  this._mfsPathsToRemove.add(localCommentUpdatePath);
2367
2432
  }
2368
- if (purgedCommentAndCommentUpdate?.commentUpdateTableRow?.replies)
2369
- await this._addOldPageCidsToCidsToUnpin(purgedCommentAndCommentUpdate?.commentUpdateTableRow?.replies, undefined, true).catch((err) => log.error("Failed to add purged page cids to be unpinned and removed", err));
2433
+ if (purgedCommentAndCommentUpdate?.commentUpdateTableRow?.replies) {
2434
+ // replies is DbRepliesFormat flat per-sort with allPageCids
2435
+ const dbReplies = purgedCommentAndCommentUpdate.commentUpdateTableRow.replies;
2436
+ for (const sortEntry of Object.values(dbReplies)) {
2437
+ if (sortEntry?.allPageCids) {
2438
+ for (const cid of sortEntry.allPageCids) {
2439
+ this._cidsToUnPin.add(cid);
2440
+ this._blocksToRm.push(cid);
2441
+ }
2442
+ }
2443
+ }
2444
+ }
2370
2445
  }
2371
2446
  async _purgeDisapprovedCommentsOlderThan() {
2372
2447
  if (typeof this.settings?.purgeDisapprovedCommentsOlderThan !== "number")
@@ -2977,12 +3052,12 @@ export class LocalCommunity extends RpcLocalCommunity {
2977
3052
  await this.initDbHandlerIfNeeded();
2978
3053
  await this._dbHandler.initDbIfNeeded();
2979
3054
  const cidsAndReplies = this._dbHandler.queryAllCommentCidsAndTheirReplies();
2980
- cidsAndReplies.forEach((comment) => this._cidsToUnPin.add(comment.cid));
2981
- await Promise.all(cidsAndReplies
2982
- .filter((comment) => comment.replies)
2983
- .map(async (commentWithReplies) => {
2984
- await this._addOldPageCidsToCidsToUnpin(commentWithReplies.replies, undefined);
2985
- }));
3055
+ for (const comment of cidsAndReplies) {
3056
+ this._cidsToUnPin.add(comment.cid);
3057
+ for (const pageCid of comment.allPageCids) {
3058
+ this._cidsToUnPin.add(pageCid);
3059
+ }
3060
+ }
2986
3061
  }
2987
3062
  catch (e) {
2988
3063
  log.error("Failed to query all cids under this community to delete them", e);