@porulle/core 0.54.0 → 0.56.0

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 (32) hide show
  1. package/dist/index.d.ts +2 -0
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +1 -0
  4. package/dist/modules/catalog/brand-service.d.ts +2 -2
  5. package/dist/modules/catalog/brand-service.d.ts.map +1 -1
  6. package/dist/modules/catalog/brand-service.js +3 -3
  7. package/dist/modules/catalog/category-service.d.ts +2 -2
  8. package/dist/modules/catalog/category-service.d.ts.map +1 -1
  9. package/dist/modules/catalog/category-service.js +3 -3
  10. package/dist/modules/catalog/entity-links.d.ts +84 -0
  11. package/dist/modules/catalog/entity-links.d.ts.map +1 -0
  12. package/dist/modules/catalog/entity-links.js +90 -0
  13. package/dist/modules/catalog/import-service.d.ts.map +1 -1
  14. package/dist/modules/catalog/import-service.js +13 -17
  15. package/dist/modules/catalog/repository/index.d.ts +4 -2
  16. package/dist/modules/catalog/repository/index.d.ts.map +1 -1
  17. package/dist/modules/catalog/repository/index.js +10 -4
  18. package/dist/modules/catalog/service.d.ts +6 -0
  19. package/dist/modules/catalog/service.d.ts.map +1 -1
  20. package/dist/modules/catalog/service.js +35 -12
  21. package/dist/modules/media/service.d.ts.map +1 -1
  22. package/dist/modules/media/service.js +3 -0
  23. package/package.json +3 -3
  24. package/src/index.ts +2 -0
  25. package/src/modules/catalog/brand-service.ts +5 -5
  26. package/src/modules/catalog/category-service.ts +5 -5
  27. package/src/modules/catalog/entity-links.ts +158 -0
  28. package/src/modules/catalog/import-service.ts +12 -17
  29. package/src/modules/catalog/repository/index.ts +12 -6
  30. package/src/modules/catalog/service.ts +43 -8
  31. package/src/modules/media/service.ts +4 -0
  32. package/dist/tsconfig.tsbuildinfo +0 -1
@@ -379,6 +379,16 @@ export interface CatalogService {
379
379
  actor: Actor | null,
380
380
  ctx?: TxContext,
381
381
  ): Promise<Result<{ created: Variant[]; skipped: number }>>;
382
+ /**
383
+ * Move the entity's `updated_at` and fire `catalog.afterUpdate` for a change to rows RELATED to
384
+ * it (links, media) — the versioning contract consumers rely on to re-read a product.
385
+ */
386
+ notifyEntityChanged(
387
+ entityId: string,
388
+ changedFieldPaths: readonly string[],
389
+ actor: Actor | null,
390
+ ctx?: TxContext,
391
+ ): Promise<void>;
382
392
  recordEntityRevision(
383
393
  entityId: string,
384
394
  actor: Actor | null,
@@ -678,6 +688,15 @@ export class CatalogServiceImpl implements CatalogService {
678
688
  }, ctx);
679
689
  }
680
690
 
691
+ notifyEntityChanged(
692
+ entityId: string,
693
+ changedFieldPaths: readonly string[],
694
+ actor: Actor | null,
695
+ ctx?: TxContext,
696
+ ): Promise<void> {
697
+ return this.entities.notifyEntityUpdated(entityId, changedFieldPaths, actor, ctx);
698
+ }
699
+
681
700
  async recordEntityRevision(
682
701
  entityId: string,
683
702
  actor: Actor | null,
@@ -1134,16 +1153,24 @@ export class CatalogServiceImpl implements CatalogService {
1134
1153
  addToCategory(entityId: string, categoryId: string, actor: Actor | null, ctx?: TxContext): Promise<Result<void>> {
1135
1154
  return this.withMutationResult(actor, ctx, async (txCtx) => {
1136
1155
  const result = await this.categories.addToCategory(entityId, categoryId, actor, txCtx);
1137
- if (result.ok) await this.captureRevision(entityId, actor, "update", txCtx);
1138
- return result;
1156
+ if (!result.ok) return result;
1157
+ // A link that actually changed versions the entity (an indexed facet moved); re-linking what
1158
+ // is already linked moves nothing.
1159
+ if (result.value) await this.entities.notifyEntityUpdated(entityId, ["categories"], actor, txCtx);
1160
+ await this.captureRevision(entityId, actor, "update", txCtx);
1161
+ return Ok(undefined);
1139
1162
  });
1140
1163
  }
1141
1164
 
1142
1165
  removeFromCategory(entityId: string, categoryId: string, actor: Actor | null, ctx?: TxContext): Promise<Result<void>> {
1143
1166
  return this.withMutationResult(actor, ctx, async (txCtx) => {
1144
1167
  const result = await this.categories.removeFromCategory(entityId, categoryId, actor, txCtx);
1145
- if (result.ok) await this.captureRevision(entityId, actor, "update", txCtx);
1146
- return result;
1168
+ if (!result.ok) return result;
1169
+ // A link that actually changed versions the entity (an indexed facet moved); re-linking what
1170
+ // is already linked moves nothing.
1171
+ if (result.value) await this.entities.notifyEntityUpdated(entityId, ["categories"], actor, txCtx);
1172
+ await this.captureRevision(entityId, actor, "update", txCtx);
1173
+ return Ok(undefined);
1147
1174
  });
1148
1175
  }
1149
1176
 
@@ -1166,16 +1193,24 @@ export class CatalogServiceImpl implements CatalogService {
1166
1193
  addToBrand(entityId: string, brandId: string, actor: Actor | null, ctx?: TxContext): Promise<Result<void>> {
1167
1194
  return this.withMutationResult(actor, ctx, async (txCtx) => {
1168
1195
  const result = await this.brands.addToBrand(entityId, brandId, actor, txCtx);
1169
- if (result.ok) await this.captureRevision(entityId, actor, "update", txCtx);
1170
- return result;
1196
+ if (!result.ok) return result;
1197
+ // A link that actually changed versions the entity (an indexed facet moved); re-linking what
1198
+ // is already linked moves nothing.
1199
+ if (result.value) await this.entities.notifyEntityUpdated(entityId, ["brand"], actor, txCtx);
1200
+ await this.captureRevision(entityId, actor, "update", txCtx);
1201
+ return Ok(undefined);
1171
1202
  });
1172
1203
  }
1173
1204
 
1174
1205
  removeFromBrand(entityId: string, brandId: string, actor: Actor | null, ctx?: TxContext): Promise<Result<void>> {
1175
1206
  return this.withMutationResult(actor, ctx, async (txCtx) => {
1176
1207
  const result = await this.brands.removeFromBrand(entityId, brandId, actor, txCtx);
1177
- if (result.ok) await this.captureRevision(entityId, actor, "update", txCtx);
1178
- return result;
1208
+ if (!result.ok) return result;
1209
+ // A link that actually changed versions the entity (an indexed facet moved); re-linking what
1210
+ // is already linked moves nothing.
1211
+ if (result.value) await this.entities.notifyEntityUpdated(entityId, ["brand"], actor, txCtx);
1212
+ await this.captureRevision(entityId, actor, "update", txCtx);
1213
+ return Ok(undefined);
1179
1214
  });
1180
1215
  }
1181
1216
 
@@ -287,6 +287,7 @@ export class MediaService {
287
287
  throw new Error("Catalog service is required for media revision capture.");
288
288
  }
289
289
  const catalogService = catalog as {
290
+ notifyEntityChanged: (entityId: string, changedFieldPaths: readonly string[], actor: Actor | null, ctx?: TxContext) => Promise<void>;
290
291
  recordEntityRevision: (
291
292
  entityId: string,
292
293
  actor: Actor | null,
@@ -294,6 +295,9 @@ export class MediaService {
294
295
  ctx?: TxContext,
295
296
  ) => Promise<Result<unknown>>;
296
297
  };
298
+ // A new attachment versions the entity: the hero drives the image embedding, so a consumer
299
+ // that versions on `updated_at` must see it.
300
+ await catalogService.notifyEntityChanged(input.entityId, [`media.${input.role}`], actor ?? txCtx.actor, txCtx);
297
301
  const revision = await catalogService.recordEntityRevision(input.entityId, actor ?? txCtx.actor, "update", txCtx);
298
302
  if (!revision.ok) throw revision.error;
299
303
  return Ok(undefined);