@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.
- package/LICENSE +21 -0
- package/README.md +63 -0
- package/dist/admin/api/pwa-client.d.ts +15 -0
- package/dist/admin/api/pwa-client.d.ts.map +1 -0
- package/dist/admin/api/pwa-client.js +56 -0
- package/dist/admin/api/pwa-client.js.map +1 -0
- package/dist/admin/components/PushAudienceRuleBuilder.d.ts +19 -0
- package/dist/admin/components/PushAudienceRuleBuilder.d.ts.map +1 -0
- package/dist/admin/components/PushAudienceRuleBuilder.js +211 -0
- package/dist/admin/components/PushAudienceRuleBuilder.js.map +1 -0
- package/dist/admin/index.d.ts +39 -0
- package/dist/admin/index.d.ts.map +1 -0
- package/dist/admin/index.js +61 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/admin/pages/PwaPage.d.ts +16 -0
- package/dist/admin/pages/PwaPage.d.ts.map +1 -0
- package/dist/admin/pages/PwaPage.js +207 -0
- package/dist/admin/pages/PwaPage.js.map +1 -0
- package/dist/backend/entities/push-message-delivery.entity.d.ts +18 -0
- package/dist/backend/entities/push-message-delivery.entity.d.ts.map +1 -0
- package/dist/backend/entities/push-message-delivery.entity.js +68 -0
- package/dist/backend/entities/push-message-delivery.entity.js.map +1 -0
- package/dist/backend/entities/push-message.entity.d.ts +26 -0
- package/dist/backend/entities/push-message.entity.d.ts.map +1 -0
- package/dist/backend/entities/push-message.entity.js +102 -0
- package/dist/backend/entities/push-message.entity.js.map +1 -0
- package/dist/backend/entities/push-subscription.entity.d.ts +49 -0
- package/dist/backend/entities/push-subscription.entity.d.ts.map +1 -0
- package/dist/backend/entities/push-subscription.entity.js +117 -0
- package/dist/backend/entities/push-subscription.entity.js.map +1 -0
- package/dist/backend/entities/pwa-icon-rendition.entity.d.ts +21 -0
- package/dist/backend/entities/pwa-icon-rendition.entity.d.ts.map +1 -0
- package/dist/backend/entities/pwa-icon-rendition.entity.js +69 -0
- package/dist/backend/entities/pwa-icon-rendition.entity.js.map +1 -0
- package/dist/backend/index.d.ts +100 -0
- package/dist/backend/index.d.ts.map +1 -0
- package/dist/backend/index.js +107 -0
- package/dist/backend/index.js.map +1 -0
- package/dist/backend/plugin.d.ts +119 -0
- package/dist/backend/plugin.d.ts.map +1 -0
- package/dist/backend/plugin.js +109 -0
- package/dist/backend/plugin.js.map +1 -0
- package/dist/backend/request-actor.d.ts +24 -0
- package/dist/backend/request-actor.d.ts.map +1 -0
- package/dist/backend/request-actor.js +29 -0
- package/dist/backend/request-actor.js.map +1 -0
- package/dist/backend/routes.admin.d.ts +52 -0
- package/dist/backend/routes.admin.d.ts.map +1 -0
- package/dist/backend/routes.admin.js +222 -0
- package/dist/backend/routes.admin.js.map +1 -0
- package/dist/backend/routes.storefront.d.ts +29 -0
- package/dist/backend/routes.storefront.d.ts.map +1 -0
- package/dist/backend/routes.storefront.js +66 -0
- package/dist/backend/routes.storefront.js.map +1 -0
- package/dist/backend/services/cross-module-context.d.ts +90 -0
- package/dist/backend/services/cross-module-context.d.ts.map +1 -0
- package/dist/backend/services/cross-module-context.js +84 -0
- package/dist/backend/services/cross-module-context.js.map +1 -0
- package/dist/backend/services/providers/web-push-provider.d.ts +31 -0
- package/dist/backend/services/providers/web-push-provider.d.ts.map +1 -0
- package/dist/backend/services/providers/web-push-provider.js +72 -0
- package/dist/backend/services/providers/web-push-provider.js.map +1 -0
- package/dist/backend/services/push-audience-evaluator.d.ts +24 -0
- package/dist/backend/services/push-audience-evaluator.d.ts.map +1 -0
- package/dist/backend/services/push-audience-evaluator.js +29 -0
- package/dist/backend/services/push-audience-evaluator.js.map +1 -0
- package/dist/backend/services/push-delivery-queue.d.ts +14 -0
- package/dist/backend/services/push-delivery-queue.d.ts.map +1 -0
- package/dist/backend/services/push-delivery-queue.js +30 -0
- package/dist/backend/services/push-delivery-queue.js.map +1 -0
- package/dist/backend/services/push-event-subscriber.d.ts +86 -0
- package/dist/backend/services/push-event-subscriber.d.ts.map +1 -0
- package/dist/backend/services/push-event-subscriber.js +109 -0
- package/dist/backend/services/push-event-subscriber.js.map +1 -0
- package/dist/backend/services/push-message-service.d.ts +58 -0
- package/dist/backend/services/push-message-service.d.ts.map +1 -0
- package/dist/backend/services/push-message-service.js +145 -0
- package/dist/backend/services/push-message-service.js.map +1 -0
- package/dist/backend/services/push-provider-registry.d.ts +17 -0
- package/dist/backend/services/push-provider-registry.d.ts.map +1 -0
- package/dist/backend/services/push-provider-registry.js +32 -0
- package/dist/backend/services/push-provider-registry.js.map +1 -0
- package/dist/backend/services/push-subscription-service.d.ts +67 -0
- package/dist/backend/services/push-subscription-service.d.ts.map +1 -0
- package/dist/backend/services/push-subscription-service.js +165 -0
- package/dist/backend/services/push-subscription-service.js.map +1 -0
- package/dist/backend/services/pwa-config-resolver.d.ts +29 -0
- package/dist/backend/services/pwa-config-resolver.d.ts.map +1 -0
- package/dist/backend/services/pwa-config-resolver.js +92 -0
- package/dist/backend/services/pwa-config-resolver.js.map +1 -0
- package/dist/backend/services/pwa-icon-service.d.ts +44 -0
- package/dist/backend/services/pwa-icon-service.d.ts.map +1 -0
- package/dist/backend/services/pwa-icon-service.js +105 -0
- package/dist/backend/services/pwa-icon-service.js.map +1 -0
- package/dist/backend/workers/push-delivery-worker.d.ts +17 -0
- package/dist/backend/workers/push-delivery-worker.d.ts.map +1 -0
- package/dist/backend/workers/push-delivery-worker.js +105 -0
- package/dist/backend/workers/push-delivery-worker.js.map +1 -0
- package/dist/manifest.d.ts +184 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +207 -0
- package/dist/manifest.js.map +1 -0
- package/dist/migrations/20260625T144228_pwa_init.d.ts +18 -0
- package/dist/migrations/20260625T144228_pwa_init.d.ts.map +1 -0
- package/dist/migrations/20260625T144228_pwa_init.js +105 -0
- package/dist/migrations/20260625T144228_pwa_init.js.map +1 -0
- package/dist/migrations/20260830T172022_pwa_organization_attribution.d.ts +102 -0
- package/dist/migrations/20260830T172022_pwa_organization_attribution.d.ts.map +1 -0
- package/dist/migrations/20260830T172022_pwa_organization_attribution.js +169 -0
- package/dist/migrations/20260830T172022_pwa_organization_attribution.js.map +1 -0
- package/dist/migrations/index.d.ts +28 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/migrations/index.js +31 -0
- package/dist/migrations/index.js.map +1 -0
- package/docs/pwa.md +93 -0
- package/i18n/en.json +43 -0
- package/i18n/pl.json +43 -0
- package/package.json +105 -0
- 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"}
|