@endora-commerce/mod-pwa 0.100.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 (119) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +63 -0
  3. package/dist/admin/api/pwa-client.d.ts +15 -0
  4. package/dist/admin/api/pwa-client.d.ts.map +1 -0
  5. package/dist/admin/api/pwa-client.js +56 -0
  6. package/dist/admin/api/pwa-client.js.map +1 -0
  7. package/dist/admin/components/PushAudienceRuleBuilder.d.ts +19 -0
  8. package/dist/admin/components/PushAudienceRuleBuilder.d.ts.map +1 -0
  9. package/dist/admin/components/PushAudienceRuleBuilder.js +211 -0
  10. package/dist/admin/components/PushAudienceRuleBuilder.js.map +1 -0
  11. package/dist/admin/index.d.ts +39 -0
  12. package/dist/admin/index.d.ts.map +1 -0
  13. package/dist/admin/index.js +61 -0
  14. package/dist/admin/index.js.map +1 -0
  15. package/dist/admin/pages/PwaPage.d.ts +16 -0
  16. package/dist/admin/pages/PwaPage.d.ts.map +1 -0
  17. package/dist/admin/pages/PwaPage.js +207 -0
  18. package/dist/admin/pages/PwaPage.js.map +1 -0
  19. package/dist/backend/entities/push-message-delivery.entity.d.ts +18 -0
  20. package/dist/backend/entities/push-message-delivery.entity.d.ts.map +1 -0
  21. package/dist/backend/entities/push-message-delivery.entity.js +68 -0
  22. package/dist/backend/entities/push-message-delivery.entity.js.map +1 -0
  23. package/dist/backend/entities/push-message.entity.d.ts +26 -0
  24. package/dist/backend/entities/push-message.entity.d.ts.map +1 -0
  25. package/dist/backend/entities/push-message.entity.js +102 -0
  26. package/dist/backend/entities/push-message.entity.js.map +1 -0
  27. package/dist/backend/entities/push-subscription.entity.d.ts +49 -0
  28. package/dist/backend/entities/push-subscription.entity.d.ts.map +1 -0
  29. package/dist/backend/entities/push-subscription.entity.js +117 -0
  30. package/dist/backend/entities/push-subscription.entity.js.map +1 -0
  31. package/dist/backend/entities/pwa-icon-rendition.entity.d.ts +21 -0
  32. package/dist/backend/entities/pwa-icon-rendition.entity.d.ts.map +1 -0
  33. package/dist/backend/entities/pwa-icon-rendition.entity.js +69 -0
  34. package/dist/backend/entities/pwa-icon-rendition.entity.js.map +1 -0
  35. package/dist/backend/index.d.ts +100 -0
  36. package/dist/backend/index.d.ts.map +1 -0
  37. package/dist/backend/index.js +107 -0
  38. package/dist/backend/index.js.map +1 -0
  39. package/dist/backend/plugin.d.ts +119 -0
  40. package/dist/backend/plugin.d.ts.map +1 -0
  41. package/dist/backend/plugin.js +109 -0
  42. package/dist/backend/plugin.js.map +1 -0
  43. package/dist/backend/request-actor.d.ts +24 -0
  44. package/dist/backend/request-actor.d.ts.map +1 -0
  45. package/dist/backend/request-actor.js +29 -0
  46. package/dist/backend/request-actor.js.map +1 -0
  47. package/dist/backend/routes.admin.d.ts +52 -0
  48. package/dist/backend/routes.admin.d.ts.map +1 -0
  49. package/dist/backend/routes.admin.js +222 -0
  50. package/dist/backend/routes.admin.js.map +1 -0
  51. package/dist/backend/routes.storefront.d.ts +29 -0
  52. package/dist/backend/routes.storefront.d.ts.map +1 -0
  53. package/dist/backend/routes.storefront.js +66 -0
  54. package/dist/backend/routes.storefront.js.map +1 -0
  55. package/dist/backend/services/cross-module-context.d.ts +90 -0
  56. package/dist/backend/services/cross-module-context.d.ts.map +1 -0
  57. package/dist/backend/services/cross-module-context.js +84 -0
  58. package/dist/backend/services/cross-module-context.js.map +1 -0
  59. package/dist/backend/services/providers/web-push-provider.d.ts +31 -0
  60. package/dist/backend/services/providers/web-push-provider.d.ts.map +1 -0
  61. package/dist/backend/services/providers/web-push-provider.js +72 -0
  62. package/dist/backend/services/providers/web-push-provider.js.map +1 -0
  63. package/dist/backend/services/push-audience-evaluator.d.ts +24 -0
  64. package/dist/backend/services/push-audience-evaluator.d.ts.map +1 -0
  65. package/dist/backend/services/push-audience-evaluator.js +29 -0
  66. package/dist/backend/services/push-audience-evaluator.js.map +1 -0
  67. package/dist/backend/services/push-delivery-queue.d.ts +14 -0
  68. package/dist/backend/services/push-delivery-queue.d.ts.map +1 -0
  69. package/dist/backend/services/push-delivery-queue.js +30 -0
  70. package/dist/backend/services/push-delivery-queue.js.map +1 -0
  71. package/dist/backend/services/push-event-subscriber.d.ts +86 -0
  72. package/dist/backend/services/push-event-subscriber.d.ts.map +1 -0
  73. package/dist/backend/services/push-event-subscriber.js +109 -0
  74. package/dist/backend/services/push-event-subscriber.js.map +1 -0
  75. package/dist/backend/services/push-message-service.d.ts +58 -0
  76. package/dist/backend/services/push-message-service.d.ts.map +1 -0
  77. package/dist/backend/services/push-message-service.js +145 -0
  78. package/dist/backend/services/push-message-service.js.map +1 -0
  79. package/dist/backend/services/push-provider-registry.d.ts +17 -0
  80. package/dist/backend/services/push-provider-registry.d.ts.map +1 -0
  81. package/dist/backend/services/push-provider-registry.js +32 -0
  82. package/dist/backend/services/push-provider-registry.js.map +1 -0
  83. package/dist/backend/services/push-subscription-service.d.ts +67 -0
  84. package/dist/backend/services/push-subscription-service.d.ts.map +1 -0
  85. package/dist/backend/services/push-subscription-service.js +165 -0
  86. package/dist/backend/services/push-subscription-service.js.map +1 -0
  87. package/dist/backend/services/pwa-config-resolver.d.ts +29 -0
  88. package/dist/backend/services/pwa-config-resolver.d.ts.map +1 -0
  89. package/dist/backend/services/pwa-config-resolver.js +92 -0
  90. package/dist/backend/services/pwa-config-resolver.js.map +1 -0
  91. package/dist/backend/services/pwa-icon-service.d.ts +44 -0
  92. package/dist/backend/services/pwa-icon-service.d.ts.map +1 -0
  93. package/dist/backend/services/pwa-icon-service.js +105 -0
  94. package/dist/backend/services/pwa-icon-service.js.map +1 -0
  95. package/dist/backend/workers/push-delivery-worker.d.ts +17 -0
  96. package/dist/backend/workers/push-delivery-worker.d.ts.map +1 -0
  97. package/dist/backend/workers/push-delivery-worker.js +105 -0
  98. package/dist/backend/workers/push-delivery-worker.js.map +1 -0
  99. package/dist/manifest.d.ts +184 -0
  100. package/dist/manifest.d.ts.map +1 -0
  101. package/dist/manifest.js +207 -0
  102. package/dist/manifest.js.map +1 -0
  103. package/dist/migrations/20260625T144228_pwa_init.d.ts +18 -0
  104. package/dist/migrations/20260625T144228_pwa_init.d.ts.map +1 -0
  105. package/dist/migrations/20260625T144228_pwa_init.js +105 -0
  106. package/dist/migrations/20260625T144228_pwa_init.js.map +1 -0
  107. package/dist/migrations/20260830T172022_pwa_organization_attribution.d.ts +102 -0
  108. package/dist/migrations/20260830T172022_pwa_organization_attribution.d.ts.map +1 -0
  109. package/dist/migrations/20260830T172022_pwa_organization_attribution.js +169 -0
  110. package/dist/migrations/20260830T172022_pwa_organization_attribution.js.map +1 -0
  111. package/dist/migrations/index.d.ts +28 -0
  112. package/dist/migrations/index.d.ts.map +1 -0
  113. package/dist/migrations/index.js +31 -0
  114. package/dist/migrations/index.js.map +1 -0
  115. package/docs/pwa.md +93 -0
  116. package/i18n/en.json +43 -0
  117. package/i18n/pl.json +43 -0
  118. package/package.json +105 -0
  119. package/tailwind.css +14 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pwa-config-resolver.js","sourceRoot":"","sources":["../../../src/backend/services/pwa-config-resolver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ import type { EntityManager } from '@mikro-orm/postgresql';
2
+ import { type PwaIconPurpose, type PwaIconRendition as PwaIconRenditionDto } from '@endora-commerce/contracts';
3
+ /** Thrown when an uploaded icon fails validation (FR-010). */
4
+ export declare class PwaIconInvalid extends Error {
5
+ readonly name = "PwaIconInvalid";
6
+ readonly code: "PWA_ICON_INVALID";
7
+ constructor(message: string);
8
+ }
9
+ /** Minimal upload port over the assets_library service. */
10
+ export interface AssetUploadPort {
11
+ upload(input: {
12
+ filename: string;
13
+ declaredMime: string;
14
+ stream: NodeJS.ReadableStream;
15
+ declaredSize: number;
16
+ folderId: string | null;
17
+ label: string | null;
18
+ visibility: 'public' | 'private';
19
+ }): Promise<{
20
+ id: string;
21
+ }>;
22
+ }
23
+ /**
24
+ * Derives the PWA icon rendition set (FR-005) from a single admin-uploaded
25
+ * source image using `sharp`, after validating format/dimensions/aspect
26
+ * (FR-010). Source + derived PNGs are stored via the assets_library; rendition
27
+ * rows replace the channel's prior set transactionally.
28
+ */
29
+ export declare class PwaIconService {
30
+ private readonly emFactory;
31
+ private readonly assets;
32
+ constructor(emFactory: () => EntityManager, assets: AssetUploadPort);
33
+ ingest(input: {
34
+ salesChannelId: string | null;
35
+ declaredMime: string;
36
+ buffer: Buffer;
37
+ }): Promise<{
38
+ sourceAssetId: string;
39
+ renditions: PwaIconRenditionDto[];
40
+ }>;
41
+ /** Resolve the asset id of a rendition for a channel (or global fallback). */
42
+ resolveRenditionAssetId(salesChannelId: string, size: number, purpose: PwaIconPurpose): Promise<string | null>;
43
+ }
44
+ //# sourceMappingURL=pwa-icon-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pwa-icon-service.d.ts","sourceRoot":"","sources":["../../../src/backend/services/pwa-icon-service.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAkB,KAAK,cAAc,EAAE,KAAK,gBAAgB,IAAI,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAG/H,8DAA8D;AAC9D,qBAAa,cAAe,SAAQ,KAAK;IACvC,SAAkB,IAAI,oBAAoB;IAC1C,QAAQ,CAAC,IAAI,EAAG,kBAAkB,CAAU;gBAChC,OAAO,EAAE,MAAM;CAG5B;AAED,2DAA2D;AAC3D,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,KAAK,EAAE;QACZ,QAAQ,EAAE,MAAM,CAAC;QACjB,YAAY,EAAE,MAAM,CAAC;QACrB,MAAM,EAAE,MAAM,CAAC,cAAc,CAAC;QAC9B,YAAY,EAAE,MAAM,CAAC;QACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QACrB,UAAU,EAAE,QAAQ,GAAG,SAAS,CAAC;KAClC,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC7B;AAUD;;;;;GAKG;AACH,qBAAa,cAAc;IAEvB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,SAAS,EAAE,MAAM,aAAa,EAC9B,MAAM,EAAE,eAAe;IAGpC,MAAM,CAAC,KAAK,EAAE;QAClB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;QAC9B,YAAY,EAAE,MAAM,CAAC;QACrB,MAAM,EAAE,MAAM,CAAC;KAChB,GAAG,OAAO,CAAC;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,mBAAmB,EAAE,CAAA;KAAE,CAAC;IAkEzE,8EAA8E;IACxE,uBAAuB,CAC3B,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;CAO1B"}
@@ -0,0 +1,105 @@
1
+ import { Readable } from 'node:stream';
2
+ import { createHash } from 'node:crypto';
3
+ import sharp from 'sharp';
4
+ import { PWA_ICON_SIZES } from '@endora-commerce/contracts';
5
+ import { PwaIconRendition } from '../entities/pwa-icon-rendition.entity.js';
6
+ /** Thrown when an uploaded icon fails validation (FR-010). */
7
+ export class PwaIconInvalid extends Error {
8
+ name = 'PwaIconInvalid';
9
+ code = 'PWA_ICON_INVALID';
10
+ constructor(message) {
11
+ super(message);
12
+ }
13
+ }
14
+ const MIN_SIZE = 512;
15
+ const ALLOWED_MIME = new Set(['image/png', 'image/webp']);
16
+ /** (size, purpose) pairs to derive. 'maskable' only for the largest size. */
17
+ const RENDITION_PLAN = [
18
+ ...PWA_ICON_SIZES.map((size) => ({ size, purpose: 'any' })),
19
+ { size: 512, purpose: 'maskable' },
20
+ ];
21
+ /**
22
+ * Derives the PWA icon rendition set (FR-005) from a single admin-uploaded
23
+ * source image using `sharp`, after validating format/dimensions/aspect
24
+ * (FR-010). Source + derived PNGs are stored via the assets_library; rendition
25
+ * rows replace the channel's prior set transactionally.
26
+ */
27
+ export class PwaIconService {
28
+ emFactory;
29
+ assets;
30
+ constructor(emFactory, assets) {
31
+ this.emFactory = emFactory;
32
+ this.assets = assets;
33
+ }
34
+ async ingest(input) {
35
+ // command-coverage-ignore: push-notification infrastructure — device
36
+ // subscription / message delivery / icon asset, not audited domain state.
37
+ if (!ALLOWED_MIME.has(input.declaredMime)) {
38
+ throw new PwaIconInvalid('The icon must be a PNG or WebP image.');
39
+ }
40
+ const meta = await sharp(input.buffer).metadata();
41
+ const width = meta.width ?? 0;
42
+ const height = meta.height ?? 0;
43
+ if (width < MIN_SIZE || height < MIN_SIZE) {
44
+ throw new PwaIconInvalid(`The icon must be at least ${MIN_SIZE}×${MIN_SIZE} pixels.`);
45
+ }
46
+ // Square within ±1%.
47
+ if (Math.abs(width - height) / Math.max(width, height) > 0.01) {
48
+ throw new PwaIconInvalid('The icon must be square.');
49
+ }
50
+ // Store the source image.
51
+ const source = await this.assets.upload({
52
+ filename: 'pwa-icon-source.png',
53
+ declaredMime: 'image/png',
54
+ stream: Readable.from(input.buffer),
55
+ declaredSize: input.buffer.length,
56
+ folderId: null,
57
+ label: 'PWA icon source',
58
+ visibility: 'public',
59
+ });
60
+ // Derive + store each rendition.
61
+ const renditions = [];
62
+ const em = this.emFactory();
63
+ // Replace the channel's prior renditions (best-effort cleanup of rows).
64
+ const prior = await em.find(PwaIconRendition, { salesChannelId: input.salesChannelId });
65
+ if (prior.length > 0)
66
+ await em.removeAndFlush(prior);
67
+ for (const plan of RENDITION_PLAN) {
68
+ const pipeline = sharp(input.buffer).resize(plan.size, plan.size, { fit: 'cover' });
69
+ // Maskable icons need safe padding; keep it simple — cover then flatten.
70
+ const png = await pipeline.png().toBuffer();
71
+ const contentHash = createHash('sha256').update(png).digest('hex');
72
+ const asset = await this.assets.upload({
73
+ filename: `pwa-icon-${plan.size}-${plan.purpose}.png`,
74
+ declaredMime: 'image/png',
75
+ stream: Readable.from(png),
76
+ declaredSize: png.length,
77
+ folderId: null,
78
+ label: `PWA icon ${plan.size} ${plan.purpose}`,
79
+ visibility: 'public',
80
+ });
81
+ const row = em.create(PwaIconRendition, {
82
+ salesChannelId: input.salesChannelId,
83
+ sourceAssetId: source.id,
84
+ size: plan.size,
85
+ purpose: plan.purpose,
86
+ assetId: asset.id,
87
+ contentHash,
88
+ });
89
+ em.persist(row);
90
+ renditions.push({ size: plan.size, purpose: plan.purpose, assetId: asset.id, contentHash });
91
+ }
92
+ await em.flush();
93
+ return { sourceAssetId: source.id, renditions };
94
+ }
95
+ /** Resolve the asset id of a rendition for a channel (or global fallback). */
96
+ async resolveRenditionAssetId(salesChannelId, size, purpose) {
97
+ const em = this.emFactory();
98
+ const channelRow = await em.findOne(PwaIconRendition, { salesChannelId, size, purpose });
99
+ if (channelRow)
100
+ return channelRow.assetId;
101
+ const globalRow = await em.findOne(PwaIconRendition, { salesChannelId: null, size, purpose });
102
+ return globalRow?.assetId ?? null;
103
+ }
104
+ }
105
+ //# sourceMappingURL=pwa-icon-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pwa-icon-service.js","sourceRoot":"","sources":["../../../src/backend/services/pwa-icon-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { EntityManager } from '@mikro-orm/postgresql';
2
+ import type { Job } from 'bullmq';
3
+ import type { PushProviderRegistryPort } from '@endora-commerce/contracts';
4
+ import type { PushDeliveryJobData } from '../services/push-delivery-queue.js';
5
+ export interface PushDeliveryProcessorDeps {
6
+ emFactory: () => EntityManager;
7
+ registry: PushProviderRegistryPort;
8
+ }
9
+ /**
10
+ * Push delivery processor (Principle X). Sends one delivery row, idempotent on
11
+ * the unique (message_id, subscription_id): an already-`sent` row is skipped so
12
+ * BullMQ retries never produce a duplicate user-visible push. A `gone` result
13
+ * prunes the dead subscription (FR-022). Retryable failures throw to let BullMQ
14
+ * back off and retry.
15
+ */
16
+ export declare function makePushDeliveryProcessor(deps: PushDeliveryProcessorDeps): (job: Job<PushDeliveryJobData>) => Promise<void>;
17
+ //# sourceMappingURL=push-delivery-worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push-delivery-worker.d.ts","sourceRoot":"","sources":["../../../src/backend/workers/push-delivery-worker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAClC,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAI3E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AAE9E,MAAM,WAAW,yBAAyB;IACxC,SAAS,EAAE,MAAM,aAAa,CAAC;IAC/B,QAAQ,EAAE,wBAAwB,CAAC;CACpC;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,yBAAyB,IAYzD,KAAK,GAAG,CAAC,mBAAmB,CAAC,KAAG,OAAO,CAAC,IAAI,CAAC,CAyE5D"}
@@ -0,0 +1,105 @@
1
+ import { PushMessage } from '../entities/push-message.entity.js';
2
+ import { PushMessageDelivery } from '../entities/push-message-delivery.entity.js';
3
+ import { PushSubscription } from '../entities/push-subscription.entity.js';
4
+ /**
5
+ * Push delivery processor (Principle X). Sends one delivery row, idempotent on
6
+ * the unique (message_id, subscription_id): an already-`sent` row is skipped so
7
+ * BullMQ retries never produce a duplicate user-visible push. A `gone` result
8
+ * prunes the dead subscription (FR-022). Retryable failures throw to let BullMQ
9
+ * back off and retry.
10
+ */
11
+ export function makePushDeliveryProcessor(deps) {
12
+ // command-coverage-ignore: delivery-state bookkeeping for an operation already
13
+ // audited at its start — the operator's write was creating and sending the
14
+ // PushMessage. Attempt counters, `sent`/`failed`/`pruned` transitions and the
15
+ // pruning of a subscription the push endpoint reported `gone` are the machine
16
+ // reporting on that one decision; an audit row per delivery would say nothing
17
+ // about who did what, and there are as many as there are subscribers.
18
+ //
19
+ // Feature 050 — a BullMQ job runs detached and needs an ambient tenant
20
+ // context for the PushSubscription reads (fail-closed guard). Feature 072
21
+ // (T033) moved that wrapper out to the `new Worker(...)` site, where every
22
+ // other queue in the tree puts it, so the processor is a plain function again.
23
+ return async (job) => {
24
+ const em = deps.emFactory();
25
+ const delivery = await em.findOne(PushMessageDelivery, { id: job.data.deliveryId });
26
+ if (!delivery)
27
+ return; // delivery (or its message) was removed — nothing to do
28
+ if (delivery.status === 'sent' || delivery.status === 'pruned')
29
+ return; // idempotent
30
+ const [message, subscription] = await Promise.all([
31
+ em.findOne(PushMessage, { id: delivery.messageId }),
32
+ em.findOne(PushSubscription, { id: delivery.subscriptionId }),
33
+ ]);
34
+ if (!message || !subscription || subscription.status !== 'active') {
35
+ delivery.status = 'failed';
36
+ delivery.lastError = 'message or subscription missing/inactive';
37
+ delivery.attemptedAt = new Date();
38
+ await em.flush();
39
+ return;
40
+ }
41
+ const provider = deps.registry.get(subscription.provider) ??
42
+ (await deps.registry.resolveDefault(message.salesChannelId));
43
+ delivery.attempts += 1;
44
+ delivery.attemptedAt = new Date();
45
+ const result = await provider.send({
46
+ endpoint: subscription.endpoint,
47
+ keys: { p256dh: subscription.p256dh, auth: subscription.auth },
48
+ provider: subscription.provider,
49
+ salesChannelId: message.salesChannelId,
50
+ }, {
51
+ title: message.title,
52
+ body: message.body,
53
+ ...(message.iconUrl ? { iconUrl: message.iconUrl } : {}),
54
+ ...(message.url ? { url: message.url } : {}),
55
+ tag: message.id,
56
+ });
57
+ if (result.ok) {
58
+ delivery.status = 'sent';
59
+ message.sentCount += 1;
60
+ await em.flush();
61
+ await maybeFinalize(em, message);
62
+ return;
63
+ }
64
+ if (result.gone === true) {
65
+ delivery.status = 'pruned';
66
+ subscription.status = 'invalid';
67
+ message.failedCount += 1;
68
+ await em.flush();
69
+ await em.removeAndFlush(subscription);
70
+ await maybeFinalize(em, message);
71
+ return;
72
+ }
73
+ // Non-`gone` failure.
74
+ delivery.lastError = result.error;
75
+ if (result.retryable) {
76
+ // Persist the attempt counter, then throw so BullMQ retries/backs off.
77
+ delivery.status = 'pending';
78
+ await em.flush();
79
+ throw new Error(`push delivery ${delivery.id} failed (retryable): ${result.error}`);
80
+ }
81
+ delivery.status = 'failed';
82
+ message.failedCount += 1;
83
+ await em.flush();
84
+ await maybeFinalize(em, message);
85
+ };
86
+ }
87
+ /**
88
+ * Flip the parent message to a terminal status once every delivery has resolved.
89
+ * Best-effort — not transactional with the delivery write (the counts are the
90
+ * source of truth for the admin history).
91
+ */
92
+ async function maybeFinalize(em, message) {
93
+ // command-coverage-ignore: closes out the same already-audited send. The
94
+ // terminal status is derived from the delivery counts, not chosen by anybody.
95
+ const pending = await em.count(PushMessageDelivery, {
96
+ messageId: message.id,
97
+ status: 'pending',
98
+ });
99
+ if (pending > 0)
100
+ return;
101
+ message.status = message.failedCount > 0 && message.sentCount === 0 ? 'failed' : 'sent';
102
+ message.sentAt = new Date();
103
+ await em.flush();
104
+ }
105
+ //# sourceMappingURL=push-delivery-worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push-delivery-worker.js","sourceRoot":"","sources":["../../../src/backend/workers/push-delivery-worker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,184 @@
1
+ /** Settings-only export consumed by the boot-time ManifestReconciler list. */
2
+ export declare const pwaSettingsManifest: {
3
+ moduleCode: string;
4
+ groups: {
5
+ code: string;
6
+ name: string;
7
+ salesChannelCodes?: string[] | undefined;
8
+ isSystemProtected?: boolean | undefined;
9
+ }[];
10
+ settings: {
11
+ code: string;
12
+ name: string;
13
+ valueType: "string" | "number" | "boolean" | "json" | "string_list" | "secret" | "credential_ref";
14
+ defaultValue: unknown;
15
+ description?: string | undefined;
16
+ groupCode?: string | undefined;
17
+ previousDefaultValues?: unknown[] | undefined;
18
+ salesChannelCodes?: string[] | undefined;
19
+ enumOptions?: string[] | undefined;
20
+ configurationType?: string | undefined;
21
+ hidden?: boolean | undefined;
22
+ }[];
23
+ };
24
+ export declare const manifest: {
25
+ id: string;
26
+ name: string;
27
+ version: string;
28
+ dependencies: string[];
29
+ description?: string | undefined;
30
+ acknowledgedDependencies?: {
31
+ moduleId: string;
32
+ port: string;
33
+ reason: string;
34
+ }[] | undefined;
35
+ nonBindingDependencies?: {
36
+ moduleId: string;
37
+ name: string;
38
+ kind: "contributes-to" | "degrades-without" | "refuses-without";
39
+ reason: string;
40
+ whenAbsent?: string | undefined;
41
+ }[] | undefined;
42
+ activation?: {
43
+ settingCode: string;
44
+ default: boolean;
45
+ } | {
46
+ nonDeactivatable: true;
47
+ reason: string;
48
+ } | undefined;
49
+ settings?: {
50
+ moduleCode: string;
51
+ groups: {
52
+ code: string;
53
+ name: string;
54
+ salesChannelCodes?: string[] | undefined;
55
+ isSystemProtected?: boolean | undefined;
56
+ }[];
57
+ settings: {
58
+ code: string;
59
+ name: string;
60
+ valueType: "string" | "number" | "boolean" | "json" | "string_list" | "secret" | "credential_ref";
61
+ defaultValue: unknown;
62
+ description?: string | undefined;
63
+ groupCode?: string | undefined;
64
+ previousDefaultValues?: unknown[] | undefined;
65
+ salesChannelCodes?: string[] | undefined;
66
+ enumOptions?: string[] | undefined;
67
+ configurationType?: string | undefined;
68
+ hidden?: boolean | undefined;
69
+ }[];
70
+ } | undefined;
71
+ i18n?: {
72
+ bundlesDir: string;
73
+ } | undefined;
74
+ docs?: false | {
75
+ dir: string;
76
+ } | undefined;
77
+ demo?: false | {
78
+ summary: string;
79
+ seed: (context: import("@endora-commerce/contracts").ModuleDemoContext<never>) => Promise<import("@endora-commerce/contracts").DemoSeedResult>;
80
+ reset: (context: import("@endora-commerce/contracts").ModuleDemoContext<never>) => Promise<import("@endora-commerce/contracts").DemoResetResult>;
81
+ after?: readonly string[] | undefined;
82
+ package?: string | undefined;
83
+ } | undefined;
84
+ actions?: {
85
+ id: string;
86
+ labelKey: string;
87
+ icon: "Plus" | "Sparkles" | "Settings" | "Search" | "Boxes" | "Layers" | "Menu" | "PlusCircle" | "PlusSquare" | "FilePlus" | "FolderPlus" | "Upload" | "FileUp" | "CloudUpload" | "Download" | "FileDown" | "FileText" | "BookOpen" | "Rss" | "Package" | "Tag" | "ShoppingCart" | "Receipt" | "CreditCard" | "Users" | "UserPlus" | "Inbox" | "ListChecks" | "ClipboardList" | "Image" | "Video" | "LayoutDashboard" | "PanelLeft" | "KeyRound" | "ShieldCheck" | "Edit" | "Archive" | "Box" | "Truck" | "CircleDollarSign" | "Activity" | "LineChart" | "Smartphone" | "Webhook" | "Scale" | "PlugZap" | "PercentDiamond" | "Newspaper" | "Languages" | "Eraser" | "Warehouse" | "TrendingDown" | "Bell" | "PackageOpen" | "Building2" | "Store" | "ClipboardCheck";
88
+ targetRoute: string;
89
+ keywords: string[];
90
+ weight: number;
91
+ descriptionKey?: string | undefined;
92
+ requiredPermission?: string | undefined;
93
+ }[] | undefined;
94
+ permissions?: {
95
+ code: string;
96
+ label: string;
97
+ module?: string | undefined;
98
+ description?: string | undefined;
99
+ requires?: string[] | undefined;
100
+ }[] | undefined;
101
+ transactionalEmails?: {
102
+ code: string;
103
+ name: string;
104
+ variables: {
105
+ key: string;
106
+ label: string;
107
+ sampleValue?: string | undefined;
108
+ description?: string | undefined;
109
+ }[];
110
+ description?: string | undefined;
111
+ group?: string | undefined;
112
+ }[] | undefined;
113
+ capabilities?: string[] | undefined;
114
+ exclusiveCapabilities?: {
115
+ key: string;
116
+ errorCode: string;
117
+ }[] | undefined;
118
+ errorCodes?: {
119
+ code: string;
120
+ tokens?: string[] | undefined;
121
+ }[] | undefined;
122
+ blocks?: {
123
+ name: string;
124
+ labelKey: string;
125
+ category: string;
126
+ contexts: ("invoice" | "email" | "cms" | "newsletter")[];
127
+ fields: Record<string, {
128
+ type: "number" | "object" | "array" | "text" | "textarea" | "select" | "radio" | "external" | "uuid" | "richtext";
129
+ label?: string | undefined;
130
+ required?: boolean | undefined;
131
+ options?: {
132
+ label: string;
133
+ value: string | number;
134
+ }[] | undefined;
135
+ refKind?: string | undefined;
136
+ }>;
137
+ descriptionKey?: string | undefined;
138
+ defaultProps?: Record<string, unknown> | undefined;
139
+ responsiveFields?: string[] | undefined;
140
+ previewIcon?: string | undefined;
141
+ weight?: number | undefined;
142
+ }[] | undefined;
143
+ blockCategories?: {
144
+ key: string;
145
+ titleKey: string;
146
+ contexts: ("invoice" | "email" | "cms" | "newsletter")[];
147
+ weight?: number | undefined;
148
+ visible?: boolean | undefined;
149
+ }[] | undefined;
150
+ env?: {
151
+ name: string;
152
+ describes: {
153
+ en: string;
154
+ pl: string;
155
+ };
156
+ requirement: {
157
+ kind: "required";
158
+ } | {
159
+ kind: "requiredWhen";
160
+ input: string;
161
+ equals: string;
162
+ } | {
163
+ kind: "optional";
164
+ without: {
165
+ en: string;
166
+ pl: string;
167
+ };
168
+ };
169
+ secret: boolean;
170
+ generable: boolean;
171
+ owner: {
172
+ kind: "platform";
173
+ } | {
174
+ kind: "application";
175
+ application: "admin" | "backend" | "storefront";
176
+ } | {
177
+ kind: "module";
178
+ moduleId: string;
179
+ };
180
+ consumers: ("admin" | "backend" | "storefront")[];
181
+ addressOf: "admin" | "backend" | "storefront" | null;
182
+ }[] | undefined;
183
+ };
184
+ //# sourceMappingURL=manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAyIA,8EAA8E;AAC9E,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;CAAW,CAAC;AAE5C,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8EnB,CAAC"}