@plusscommunities/pluss-core-aws 2.0.25-beta.6 → 2.0.25-beta.7

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.
@@ -145,14 +145,23 @@ const fanOutHqSource = async (hqSourceRow, tableName) => {
145
145
  return [];
146
146
  }
147
147
  const copyId = `hqcopy-${hqSourceRow.Id}`;
148
- // IMPORTANT: milliseconds (.valueOf), not seconds (.unix). Newsletter
149
- // rows written by addNewsletterEntry.js use `moment.utc().valueOf()` for
150
- // UnixTimestamp. UnixTimestampReverse-keyed feed queries (the standard
151
- // Pluss list pattern) would otherwise rank HQ copies ~1000× ahead of
152
- // locally-authored posts foreverMAX_SAFE_INTEGER minus a number 10^9
153
- // is vastly larger than MAX_SAFE_INTEGER minus 10^12. Keep parity with
154
- // the canonical addNewsletterEntry convention.
148
+ // Preserve the HQ-source row's own UnixTimestamp on each copy rather than
149
+ // stamping "now". For an immediate publish the source timestamp already IS
150
+ // ~now, so feed ranking is unchanged; for a SCHEDULED publish (future
151
+ // timestamp set via the compose "Schedule Post" tab) preserving it keeps the
152
+ // copies hidden until the scheduled moment BOTH consumers key off it: the
153
+ // noFuture feed filter, and the deferred-notification scheduler
154
+ // (watchNewsletter / the INSERT-path checkSendNotifications both gate on
155
+ // `UnixTimestamp < now`). Stamping "now" here published scheduled HQ posts
156
+ // (feed + push) immediately, ignoring the schedule. Fall back to now only if
157
+ // the source somehow lacks a timestamp.
158
+ //
159
+ // IMPORTANT: milliseconds (.valueOf), not seconds (.unix) — parity with the
160
+ // addNewsletterEntry UnixTimestamp convention. UnixTimestampReverse-keyed
161
+ // feed queries would otherwise mis-rank an ms value against a seconds value
162
+ // (MAX_SAFE_INTEGER minus 10^9 vs minus 10^12).
155
163
  const now = moment.utc().valueOf();
164
+ const publishTs = hqSourceRow.UnixTimestamp || now;
156
165
 
157
166
  const writes = targets.map((targetSiteId) => {
158
167
  // Spread + override pattern: keep all content fields, swap identity
@@ -164,8 +173,8 @@ const fanOutHqSource = async (hqSourceRow, tableName) => {
164
173
  copy.Site = targetSiteId;
165
174
  copy.RowId = `${targetSiteId}_${copyId}`;
166
175
  copy.HqSourceId = hqSourceRow.Id;
167
- copy.UnixTimestamp = now;
168
- copy.UnixTimestampReverse = Number.MAX_SAFE_INTEGER - now;
176
+ copy.UnixTimestamp = publishTs;
177
+ copy.UnixTimestampReverse = Number.MAX_SAFE_INTEGER - publishTs;
169
178
  // Each copy's own INSERT fires publishNotifications via the existing
170
179
  // pipeline. Setting UnsentNotification: "X" matches the convention
171
180
  // used by addNewsletterEntry when caller requested a notification.
@@ -173,6 +182,11 @@ const fanOutHqSource = async (hqSourceRow, tableName) => {
173
182
  // HQ-only fields don't travel:
174
183
  delete copy.PublishedToSites;
175
184
  delete copy.Deleted; // copies start undeleted; retract cascade is separate
185
+ // Tagged references HQ-site users; on a community copy those IDs are
186
+ // orphaned (cosmetic "tagged people" display + a createUserEntries write
187
+ // keyed on non-members in newsletterChanged's INSERT branch). Audience
188
+ // targeting (All/Category) already governs who sees the copy.
189
+ delete copy.Tagged;
176
190
  return updateRef(tableName, copy).then(() => copy);
177
191
  });
178
192
  return Promise.all(writes);
@@ -312,8 +326,8 @@ const cascadeHqRetract = async (hqSourceRow, tableName, options = {}) => {
312
326
  * @param {string} templateId — the `Id` of the contentLibrary row.
313
327
  * @param {string} contentLibraryTable — entity-agnostic; caller passes the
314
328
  * table name (without prefix).
315
- * @returns {Promise<boolean>} `true` if increment applied; `false` on graceful
316
- * skip (table not shipped yet, or no template with that Id exists).
329
+ * @returns {Promise<boolean>} `true` if increment applied; `false` if table
330
+ * doesn't exist (graceful skip).
317
331
  */
318
332
  const incrementTemplateUseCount = async (templateId, contentLibraryTable) => {
319
333
  if (!templateId || !contentLibraryTable) {
@@ -322,16 +336,11 @@ const incrementTemplateUseCount = async (templateId, contentLibraryTable) => {
322
336
  const params = {
323
337
  TableName: `${process.env.tablePrefix}${contentLibraryTable}`,
324
338
  Key: { Id: templateId },
325
- UpdateExpression: "ADD UseCount :inc SET LastUsedTimestamp = :now",
326
- // Guard against minting a phantom row: ADD on a missing key would CREATE
327
- // it with UseCount=1. Only increment a template that actually exists; a
328
- // stale/bogus TemplateId is skipped (ConditionalCheckFailed below).
329
- ConditionExpression: "attribute_exists(Id)",
339
+ UpdateExpression:
340
+ "ADD UseCount :inc SET LastUsedTimestamp = :now",
330
341
  ExpressionAttributeValues: {
331
342
  ":inc": 1,
332
- // epoch ms — the contentLibrary timestamp convention (matches
333
- // UpdatedAt). Was .unix() (seconds); reconciled to .valueOf().
334
- ":now": moment().utc().valueOf(),
343
+ ":now": moment.utc().unix(),
335
344
  },
336
345
  };
337
346
  try {
@@ -349,12 +358,6 @@ const incrementTemplateUseCount = async (templateId, contentLibraryTable) => {
349
358
  );
350
359
  return false;
351
360
  }
352
- if (error?.code === "ConditionalCheckFailedException") {
353
- // TemplateId references no existing template — skip rather than
354
- // create a phantom row. Not an error; continue the stream handler.
355
- log("incrementTemplateUseCount", "NoSuchTemplate", { templateId });
356
- return false;
357
- }
358
361
  // Anything else is genuinely unexpected — surface it.
359
362
  log("incrementTemplateUseCount", "Error", error);
360
363
  throw error;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plusscommunities/pluss-core-aws",
3
- "version": "2.0.25-beta.6",
3
+ "version": "2.0.25-beta.7",
4
4
  "description": "Core extension package for Pluss Communities platform",
5
5
  "scripts": {
6
6
  "betapatch": "npm version prepatch --preid=beta",