@endora-commerce/mod-meta-ads 0.0.0-stage → 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 (59) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +57 -2
  3. package/dist/admin/api/meta-ads-client.d.ts +32 -0
  4. package/dist/admin/api/meta-ads-client.d.ts.map +1 -0
  5. package/dist/admin/api/meta-ads-client.js +34 -0
  6. package/dist/admin/api/meta-ads-client.js.map +1 -0
  7. package/dist/admin/index.d.ts +30 -0
  8. package/dist/admin/index.d.ts.map +1 -0
  9. package/dist/admin/index.js +59 -0
  10. package/dist/admin/index.js.map +1 -0
  11. package/dist/admin/pages/CustomEventMappingEditPage.d.ts +4 -0
  12. package/dist/admin/pages/CustomEventMappingEditPage.d.ts.map +1 -0
  13. package/dist/admin/pages/CustomEventMappingEditPage.js +85 -0
  14. package/dist/admin/pages/CustomEventMappingEditPage.js.map +1 -0
  15. package/dist/admin/pages/CustomEventMappingsListPage.d.ts +7 -0
  16. package/dist/admin/pages/CustomEventMappingsListPage.d.ts.map +1 -0
  17. package/dist/admin/pages/CustomEventMappingsListPage.js +90 -0
  18. package/dist/admin/pages/CustomEventMappingsListPage.js.map +1 -0
  19. package/dist/backend/entities/meta-custom-event-mapping.entity.d.ts +24 -0
  20. package/dist/backend/entities/meta-custom-event-mapping.entity.d.ts.map +1 -0
  21. package/dist/backend/entities/meta-custom-event-mapping.entity.js +75 -0
  22. package/dist/backend/entities/meta-custom-event-mapping.entity.js.map +1 -0
  23. package/dist/backend/index.d.ts +67 -0
  24. package/dist/backend/index.d.ts.map +1 -0
  25. package/dist/backend/index.js +56 -0
  26. package/dist/backend/index.js.map +1 -0
  27. package/dist/backend/routes.admin.d.ts +16 -0
  28. package/dist/backend/routes.admin.d.ts.map +1 -0
  29. package/dist/backend/routes.admin.js +31 -0
  30. package/dist/backend/routes.admin.js.map +1 -0
  31. package/dist/backend/routes.storefront.d.ts +11 -0
  32. package/dist/backend/routes.storefront.d.ts.map +1 -0
  33. package/dist/backend/routes.storefront.js +13 -0
  34. package/dist/backend/routes.storefront.js.map +1 -0
  35. package/dist/backend/services/custom-event-mappings.service.d.ts +40 -0
  36. package/dist/backend/services/custom-event-mappings.service.d.ts.map +1 -0
  37. package/dist/backend/services/custom-event-mappings.service.js +134 -0
  38. package/dist/backend/services/custom-event-mappings.service.js.map +1 -0
  39. package/dist/backend/services/meta-config.service.d.ts +22 -0
  40. package/dist/backend/services/meta-config.service.d.ts.map +1 -0
  41. package/dist/backend/services/meta-config.service.js +55 -0
  42. package/dist/backend/services/meta-config.service.js.map +1 -0
  43. package/dist/manifest.d.ts +194 -0
  44. package/dist/manifest.d.ts.map +1 -0
  45. package/dist/manifest.js +102 -0
  46. package/dist/manifest.js.map +1 -0
  47. package/dist/migrations/20260728T002715_meta_ads_init.d.ts +12 -0
  48. package/dist/migrations/20260728T002715_meta_ads_init.d.ts.map +1 -0
  49. package/dist/migrations/20260728T002715_meta_ads_init.js +35 -0
  50. package/dist/migrations/20260728T002715_meta_ads_init.js.map +1 -0
  51. package/dist/migrations/index.d.ts +27 -0
  52. package/dist/migrations/index.d.ts.map +1 -0
  53. package/dist/migrations/index.js +29 -0
  54. package/dist/migrations/index.js.map +1 -0
  55. package/docs/meta-ads.md +82 -0
  56. package/i18n/en.json +35 -0
  57. package/i18n/pl.json +35 -0
  58. package/package.json +89 -3
  59. package/tailwind.css +14 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Endora sp. z o.o. and the Endora Commerce contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,58 @@
1
- # Temporary Holding Version
1
+ <!-- Generated by `pnpm --filter backend run manifests:generate`. Delete this line to take the file over; a README without it is never regenerated. -->
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ # @endora-commerce/mod-meta-ads
4
+
5
+ Meta Ads integration: per-sales-channel Meta Pixel, consent-gated tracking, standard commerce events, and configurable custom events.
6
+
7
+ ## What this is
8
+
9
+ An **Endora Commerce module package**. Its module id is `meta_ads` — the identity of record in the platform's registries, in its migrations and in its setting, permission and translation codes.
10
+
11
+ A module is not imported by application code. The platform discovers the extension packages an instance has installed, reads the manifest on the root subpath and composes the module from it, so installing this package and starting the instance is the whole integration.
12
+
13
+ ## Entry points
14
+
15
+ | Import | Contents |
16
+ | --- | --- |
17
+ | `@endora-commerce/mod-meta-ads` | the module manifest — its id, version, dependencies, settings and activation |
18
+ | `@endora-commerce/mod-meta-ads/admin` | the Admin UI contribution: the screens, navigation and palette actions it adds |
19
+ | `@endora-commerce/mod-meta-ads/backend` | the composition root the platform calls, with the entities, services, routes and workers it registers |
20
+ | `@endora-commerce/mod-meta-ads/migrations` | the module’s own schema migrations, in the order the platform runs them |
21
+ | `@endora-commerce/mod-meta-ads/tailwind.css` | the Tailwind source declaration for the admin code above |
22
+
23
+ ## Depends on
24
+
25
+ Everything below is a **peer** dependency, so the application resolves exactly one copy of each — two copies of a host or of React are a runtime failure rather than a type error. An entry marked *optional* is needed only by the layers that use it.
26
+
27
+ **Endora packages**
28
+
29
+ - `@endora-commerce/admin-kit` — *optional*
30
+ - `@endora-commerce/contracts`
31
+ - `@endora-commerce/platform`
32
+
33
+ **Third-party**
34
+
35
+ - `@mikro-orm/core` ^6
36
+ - `@mikro-orm/migrations` ^6
37
+ - `@mikro-orm/postgresql` ^6
38
+ - `fastify` ^5
39
+ - `react` ^19 — *optional*
40
+ - `react-router-dom` ^7 — *optional*
41
+ - `zod` ^4
42
+
43
+ ## What the tarball carries
44
+
45
+ - `dist/` — the compiled JavaScript and its type declarations
46
+ - `i18n/` — the translation bundles this package ships (`en`, `pl`), loaded by the platform
47
+ - `docs/` — the package’s own pages in the Endora Commerce documentation site
48
+ - `tailwind.css` — the Tailwind source declaration
49
+
50
+ ## Install
51
+
52
+ ```bash
53
+ pnpm add @endora-commerce/mod-meta-ads
54
+ ```
55
+
56
+ ## Licence
57
+
58
+ MIT — the text is in `LICENSE`, beside this file.
@@ -0,0 +1,32 @@
1
+ import type { CreateMetaCustomEventMapping, MetaCustomEventMapping, MetaTriggerAction, SalesChannelListResponse, UpdateMetaCustomEventMapping } from '@endora-commerce/contracts';
2
+ /** Typed admin client for the Meta Ads module (feature 064). */
3
+ export declare const metaAdsClient: {
4
+ actionCatalogue: () => Promise<MetaTriggerAction[]>;
5
+ list: () => Promise<MetaCustomEventMapping[]>;
6
+ get: (id: string) => Promise<MetaCustomEventMapping>;
7
+ create: (body: CreateMetaCustomEventMapping) => Promise<MetaCustomEventMapping>;
8
+ update: (id: string, body: UpdateMetaCustomEventMapping) => Promise<MetaCustomEventMapping>;
9
+ remove: (id: string) => Promise<void>;
10
+ };
11
+ /**
12
+ * The sales channels this module's two screens label a mapping's channel with.
13
+ *
14
+ * **This is a drained cross-module reach, not a convenience** (feature 091,
15
+ * Phase 4 batch three). Both screens used to import `salesChannelsClient` from
16
+ * `@/modules/sales_channels/api/sales-channels-client`, which
17
+ * `backend/scripts/ledgers/cross-module-imports/meta_ads.ts` recorded as a
18
+ * boundary reach before any admin directory moved. That entry named the exit
19
+ * taken here: *"the reach is the client module, not the HTTP call — the request
20
+ * and response shapes are already in `@endora-commerce/contracts`, which both
21
+ * sides compile"*, so the caller builds the request itself and no module names
22
+ * a file another module owns. Rewriting the specifier as a package subpath was
23
+ * the exit the entry refuses: it is the same coupling under a supported name.
24
+ *
25
+ * It is duplicated in `linkedin_ads`' client rather than shared, and that is
26
+ * the design and not an oversight. The only place two modules could share it is
27
+ * `@endora-commerce/admin-kit`, and the kit holds no module knowledge (R6) —
28
+ * `/api/v1/admin/sales-channels` is `sales_channels`' knowledge. Two callers of
29
+ * one published HTTP route is what an API boundary is for.
30
+ */
31
+ export declare const listSalesChannels: () => Promise<SalesChannelListResponse>;
32
+ //# sourceMappingURL=meta-ads-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meta-ads-client.d.ts","sourceRoot":"","sources":["../../../src/admin/api/meta-ads-client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,4BAA4B,EAC5B,sBAAsB,EACtB,iBAAiB,EACjB,wBAAwB,EACxB,4BAA4B,EAC7B,MAAM,4BAA4B,CAAC;AAMpC,gEAAgE;AAChE,eAAO,MAAM,aAAa;2BACH,OAAO,CAAC,iBAAiB,EAAE,CAAC;gBAGvC,OAAO,CAAC,sBAAsB,EAAE,CAAC;cAGjC,MAAM,KAAG,OAAO,CAAC,sBAAsB,CAAC;mBAGnC,4BAA4B,KAAG,OAAO,CAAC,sBAAsB,CAAC;iBAGhE,MAAM,QAAQ,4BAA4B,KAAG,OAAO,CAAC,sBAAsB,CAAC;iBAG5E,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;CACpC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,iBAAiB,QAAO,OAAO,CAAC,wBAAwB,CAGlE,CAAC"}
@@ -0,0 +1,34 @@
1
+ import { apiClient } from '@endora-commerce/admin-kit/lib';
2
+ const unwrap = (p) => p.then((r) => r.data);
3
+ const BASE = '/api/v1/admin/meta-ads';
4
+ /** Typed admin client for the Meta Ads module (feature 064). */
5
+ export const metaAdsClient = {
6
+ actionCatalogue: () => unwrap(apiClient.get(`${BASE}/action-catalogue`)),
7
+ list: () => unwrap(apiClient.get(`${BASE}/custom-events`)),
8
+ get: (id) => unwrap(apiClient.get(`${BASE}/custom-events/${id}`)),
9
+ create: (body) => unwrap(apiClient.post(`${BASE}/custom-events`, body)),
10
+ update: (id, body) => unwrap(apiClient.patch(`${BASE}/custom-events/${id}`, body)),
11
+ remove: (id) => apiClient.delete(`${BASE}/custom-events/${id}`),
12
+ };
13
+ /**
14
+ * The sales channels this module's two screens label a mapping's channel with.
15
+ *
16
+ * **This is a drained cross-module reach, not a convenience** (feature 091,
17
+ * Phase 4 batch three). Both screens used to import `salesChannelsClient` from
18
+ * `@/modules/sales_channels/api/sales-channels-client`, which
19
+ * `backend/scripts/ledgers/cross-module-imports/meta_ads.ts` recorded as a
20
+ * boundary reach before any admin directory moved. That entry named the exit
21
+ * taken here: *"the reach is the client module, not the HTTP call — the request
22
+ * and response shapes are already in `@endora-commerce/contracts`, which both
23
+ * sides compile"*, so the caller builds the request itself and no module names
24
+ * a file another module owns. Rewriting the specifier as a package subpath was
25
+ * the exit the entry refuses: it is the same coupling under a supported name.
26
+ *
27
+ * It is duplicated in `linkedin_ads`' client rather than shared, and that is
28
+ * the design and not an oversight. The only place two modules could share it is
29
+ * `@endora-commerce/admin-kit`, and the kit holds no module knowledge (R6) —
30
+ * `/api/v1/admin/sales-channels` is `sales_channels`' knowledge. Two callers of
31
+ * one published HTTP route is what an API boundary is for.
32
+ */
33
+ export const listSalesChannels = () => apiClient.get('/api/v1/admin/sales-channels?activeOnly=false&pageSize=100');
34
+ //# sourceMappingURL=meta-ads-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meta-ads-client.js","sourceRoot":"","sources":["../../../src/admin/api/meta-ads-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAU3D,MAAM,MAAM,GAAG,CAAI,CAAmB,EAAc,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AAC7E,MAAM,IAAI,GAAG,wBAAwB,CAAC;AAEtC,gEAAgE;AAChE,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,eAAe,EAAE,GAAiC,EAAE,CAClD,MAAM,CAAC,SAAS,CAAC,GAAG,CAA4B,GAAG,IAAI,mBAAmB,CAAC,CAAC;IAE9E,IAAI,EAAE,GAAsC,EAAE,CAC5C,MAAM,CAAC,SAAS,CAAC,GAAG,CAAiC,GAAG,IAAI,gBAAgB,CAAC,CAAC;IAEhF,GAAG,EAAE,CAAC,EAAU,EAAmC,EAAE,CACnD,MAAM,CAAC,SAAS,CAAC,GAAG,CAA+B,GAAG,IAAI,kBAAkB,EAAE,EAAE,CAAC,CAAC;IAEpF,MAAM,EAAE,CAAC,IAAkC,EAAmC,EAAE,CAC9E,MAAM,CAAC,SAAS,CAAC,IAAI,CAA+B,GAAG,IAAI,gBAAgB,EAAE,IAAI,CAAC,CAAC;IAErF,MAAM,EAAE,CAAC,EAAU,EAAE,IAAkC,EAAmC,EAAE,CAC1F,MAAM,CAAC,SAAS,CAAC,KAAK,CAA+B,GAAG,IAAI,kBAAkB,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;IAE5F,MAAM,EAAE,CAAC,EAAU,EAAiB,EAAE,CAAC,SAAS,CAAC,MAAM,CAAO,GAAG,IAAI,kBAAkB,EAAE,EAAE,CAAC;CAC7F,CAAC;AAEF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAsC,EAAE,CACvE,SAAS,CAAC,GAAG,CACX,4DAA4D,CAC7D,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * `meta_ads`' admin surface — three routes and one sidebar entry, declared by
3
+ * the module that owns them (feature 091, Phase 4;
4
+ * `specs/091-module-owned-admin-surfaces/contracts/admin-contribution.md`).
5
+ *
6
+ * **The twin of `linkedin_ads`, and the pair is deliberate.** Both carry zero
7
+ * incoming admin cross-module reach, both reach `sales_channels`' admin client
8
+ * twice and nothing else, and both take the exit their ledger shard names — the
9
+ * caller building the request from the published `apiClient` and the contract's
10
+ * own types. Taking one and not the other would have left the two remaining
11
+ * host-declared entries of the *Analytics & Ads* section at one, which is the
12
+ * state that makes the section's order half a weight and half a position; both
13
+ * gone, the weights are the whole order and the order is the one the
14
+ * hand-written table had. `linkedin_ads`' own `src/admin/index.ts` records the
15
+ * measurement that chose them.
16
+ *
17
+ * **This entry exports data and nothing else** (R2), like every `./admin`
18
+ * layer: `check:module-boundary`'s D-171 rule designates a subpath as contract
19
+ * surface when it emits no runtime binding, and `./admin` deliberately does not
20
+ * qualify, so a consumer reaching into another module's `./admin` stays a
21
+ * counted boundary reach.
22
+ *
23
+ * **Every component is a dynamic-import factory** (R6). The editor is named
24
+ * twice below — once for `/new` and once for `/:id` — and both are the same
25
+ * factory value, so Vite emits one chunk for the screen rather than one per
26
+ * route.
27
+ */
28
+ import type { AdminContributions } from '@endora-commerce/admin-kit/contributions';
29
+ export declare const contributions: AdminContributions;
30
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/admin/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0CAA0C,CAAC;AAgBnF,eAAO,MAAM,aAAa,EAAE,kBA8C3B,CAAC"}
@@ -0,0 +1,59 @@
1
+ /** The module's landing route: the custom-event mapping list. */
2
+ const ROUTE_PATH = '/meta-ads';
3
+ /**
4
+ * The create and edit screens are one component behind one factory.
5
+ *
6
+ * `react-router` matches `/meta-ads/new` against the parametric route too, so
7
+ * the two declarations are deliberately separate — the editor reads
8
+ * `id === 'new'` as its create mode, which is the behaviour the host route
9
+ * table had when it declared both paths against one imported component.
10
+ */
11
+ const editor = () => import('./pages/CustomEventMappingEditPage.js');
12
+ export const contributions = {
13
+ routes: [
14
+ {
15
+ path: ROUTE_PATH,
16
+ component: () => import('./pages/CustomEventMappingsListPage.js'),
17
+ // Read from the route this screen calls — `requireAdmin('meta_ads:read')`
18
+ // on `GET /admin/meta-ads/custom-events` — and the same code the module's
19
+ // `open-meta-ads` palette action declares, which
20
+ // `check:action-route-permissions` holds to that route.
21
+ requiredPermission: 'meta_ads:read',
22
+ index: true,
23
+ },
24
+ {
25
+ path: `${ROUTE_PATH}/new`,
26
+ component: editor,
27
+ // The create form posts to `POST /admin/meta-ads/custom-events`, which
28
+ // enforces the write code — the same code the `new-meta-custom-event`
29
+ // palette action declares for this path.
30
+ requiredPermission: 'meta_ads:write',
31
+ },
32
+ {
33
+ path: `${ROUTE_PATH}/:id`,
34
+ component: editor,
35
+ requiredPermission: 'meta_ads:write',
36
+ },
37
+ ],
38
+ nav: [
39
+ {
40
+ to: ROUTE_PATH,
41
+ // Module-relative (R8), resolved in this module's own namespace out of
42
+ // `packages/modules/meta_ads/i18n/`. It was `appShell.nav.metaAds` in the
43
+ // shared `_i18n` bundle, one of the four shared files a module author had
44
+ // to edit.
45
+ labelKey: 'nav.metaAds.label',
46
+ // The icon the hand-written NAV entry carried.
47
+ icon: 'Sparkles',
48
+ section: 'analyticsAds',
49
+ // Last of the four entries the hand-written NAV gave this section, after
50
+ // `analytics` (100), `google_analytics` (200) and `linkedin_ads` (300).
51
+ weight: 400,
52
+ // The code that opens the screen. The sidebar advertises a destination,
53
+ // so it gates on the read code the landing route enforces and not on the
54
+ // write code its editor does.
55
+ requiredPermission: 'meta_ads:read',
56
+ },
57
+ ],
58
+ };
59
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/admin/index.ts"],"names":[],"mappings":"AA6BA,iEAAiE;AACjE,MAAM,UAAU,GAAG,WAAW,CAAC;AAE/B;;;;;;;GAOG;AACH,MAAM,MAAM,GAAG,GAA2C,EAAE,CAC1D,MAAM,CAAC,uCAAuC,CAAC,CAAC;AAElD,MAAM,CAAC,MAAM,aAAa,GAAuB;IAC/C,MAAM,EAAE;QACN;YACE,IAAI,EAAE,UAAU;YAChB,SAAS,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,wCAAwC,CAAC;YACjE,0EAA0E;YAC1E,0EAA0E;YAC1E,iDAAiD;YACjD,wDAAwD;YACxD,kBAAkB,EAAE,eAAe;YACnC,KAAK,EAAE,IAAI;SACZ;QACD;YACE,IAAI,EAAE,GAAG,UAAU,MAAM;YACzB,SAAS,EAAE,MAAM;YACjB,uEAAuE;YACvE,sEAAsE;YACtE,yCAAyC;YACzC,kBAAkB,EAAE,gBAAgB;SACrC;QACD;YACE,IAAI,EAAE,GAAG,UAAU,MAAM;YACzB,SAAS,EAAE,MAAM;YACjB,kBAAkB,EAAE,gBAAgB;SACrC;KACF;IACD,GAAG,EAAE;QACH;YACE,EAAE,EAAE,UAAU;YACd,uEAAuE;YACvE,0EAA0E;YAC1E,0EAA0E;YAC1E,WAAW;YACX,QAAQ,EAAE,mBAAmB;YAC7B,+CAA+C;YAC/C,IAAI,EAAE,UAAU;YAChB,OAAO,EAAE,cAAc;YACvB,yEAAyE;YACzE,wEAAwE;YACxE,MAAM,EAAE,GAAG;YACX,wEAAwE;YACxE,yEAAyE;YACzE,8BAA8B;YAC9B,kBAAkB,EAAE,eAAe;SACpC;KACF;CACF,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { type ReactNode } from 'react';
2
+ /** Create / edit one Meta custom event mapping (feature 064, US4). */
3
+ export default function CustomEventMappingEditPage(): ReactNode;
4
+ //# sourceMappingURL=CustomEventMappingEditPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CustomEventMappingEditPage.d.ts","sourceRoot":"","sources":["../../../src/admin/pages/CustomEventMappingEditPage.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AA0BzE,sEAAsE;AACtE,MAAM,CAAC,OAAO,UAAU,0BAA0B,IAAI,SAAS,CAsJ9D"}
@@ -0,0 +1,85 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useCallback, useEffect, useState } from 'react';
3
+ import { useNavigate, useParams } from 'react-router-dom';
4
+ import { META_STANDARD_EVENTS, META_TRIGGER_ACTIONS, } from '@endora-commerce/contracts';
5
+ import { Alert, AlertDescription, Button, Card, CardContent, Input, Label, PageHeader, Select, } from '@endora-commerce/admin-kit/ui';
6
+ import { ApiError } from '@endora-commerce/admin-kit/lib';
7
+ import { useTranslation } from '@endora-commerce/admin-kit/i18n';
8
+ import { metaAdsClient, listSalesChannels } from '../api/meta-ads-client.js';
9
+ const ALL_CHANNELS = '__all__';
10
+ /** Create / edit one Meta custom event mapping (feature 064, US4). */
11
+ export default function CustomEventMappingEditPage() {
12
+ const t = useTranslation('meta_ads');
13
+ const navigate = useNavigate();
14
+ const { id } = useParams();
15
+ const isNew = id === undefined;
16
+ const [channels, setChannels] = useState([]);
17
+ const [existing, setExisting] = useState(null);
18
+ const [triggerAction, setTriggerAction] = useState('purchase');
19
+ const [eventName, setEventName] = useState('');
20
+ const [salesChannelId, setSalesChannelId] = useState(ALL_CHANNELS);
21
+ const [enabled, setEnabled] = useState(true);
22
+ const [busy, setBusy] = useState(false);
23
+ const [error, setError] = useState(null);
24
+ const messageFor = useCallback((err) => {
25
+ if (err instanceof ApiError) {
26
+ if (err.envelope.error.code === 'VERSION_CONFLICT')
27
+ return t('error.versionConflict');
28
+ return err.envelope.error.message;
29
+ }
30
+ return t('error.generic');
31
+ }, [t]);
32
+ useEffect(() => {
33
+ void (async () => {
34
+ const chans = await listSalesChannels().catch(() => ({ items: [] }));
35
+ setChannels(chans.items);
36
+ if (isNew)
37
+ return;
38
+ try {
39
+ const row = await metaAdsClient.get(id);
40
+ setExisting(row);
41
+ setTriggerAction(row.triggerAction);
42
+ setEventName(row.eventName);
43
+ setSalesChannelId(row.salesChannelId ?? ALL_CHANNELS);
44
+ setEnabled(row.enabled);
45
+ }
46
+ catch (err) {
47
+ setError(messageFor(err));
48
+ }
49
+ })();
50
+ }, [id, isNew, messageFor]);
51
+ const save = async () => {
52
+ setBusy(true);
53
+ setError(null);
54
+ const channel = salesChannelId === ALL_CHANNELS ? null : salesChannelId;
55
+ try {
56
+ if (isNew) {
57
+ await metaAdsClient.create({
58
+ triggerAction,
59
+ eventName: eventName.trim(),
60
+ salesChannelId: channel,
61
+ enabled,
62
+ });
63
+ }
64
+ else if (existing) {
65
+ await metaAdsClient.update(existing.id, {
66
+ triggerAction,
67
+ eventName: eventName.trim(),
68
+ salesChannelId: channel,
69
+ enabled,
70
+ version: existing.version,
71
+ });
72
+ }
73
+ navigate('/meta-ads');
74
+ }
75
+ catch (err) {
76
+ setError(messageFor(err));
77
+ }
78
+ finally {
79
+ setBusy(false);
80
+ }
81
+ };
82
+ const standard = META_STANDARD_EVENTS[triggerAction];
83
+ return (_jsxs("div", { children: [_jsx(PageHeader, { title: isNew ? t('customEvents.new') : t('customEvents.edit') }), error ? (_jsx(Alert, { variant: "destructive", className: "mb-3", children: _jsx(AlertDescription, { children: error }) })) : null, _jsx(Card, { children: _jsxs(CardContent, { className: "space-y-4 pt-6", children: [_jsxs("div", { children: [_jsx(Label, { htmlFor: "triggerAction", children: t('customEvents.triggerAction') }), _jsx(Select, { id: "triggerAction", value: triggerAction, onChange: (e) => setTriggerAction(e.target.value), children: META_TRIGGER_ACTIONS.map((a) => (_jsx("option", { value: a, children: t(`customEvents.action.${a}`) }, a))) }), _jsxs("p", { className: "mt-1 text-xs text-muted-foreground", children: [t('customEvents.standardEvent'), ": ", standard ?? t('customEvents.standardEventNone')] })] }), _jsxs("div", { children: [_jsx(Label, { htmlFor: "eventName", children: t('customEvents.eventName') }), _jsx(Input, { id: "eventName", value: eventName, onChange: (e) => setEventName(e.target.value), placeholder: "SubmitQuote" }), _jsx("p", { className: "mt-1 text-xs text-muted-foreground", children: t('customEvents.eventNameHint') })] }), _jsxs("div", { children: [_jsx(Label, { htmlFor: "salesChannelId", children: t('customEvents.salesChannel') }), _jsxs(Select, { id: "salesChannelId", value: salesChannelId, onChange: (e) => setSalesChannelId(e.target.value), children: [_jsx("option", { value: ALL_CHANNELS, children: t('customEvents.allChannels') }), channels.map((c) => (_jsx("option", { value: c.id, children: c.code }, c.id)))] })] }), _jsxs("label", { className: "flex items-center gap-2 text-sm", children: [_jsx("input", { type: "checkbox", checked: enabled, onChange: (e) => setEnabled(e.target.checked) }), t('customEvents.enabled')] }), _jsx(Button, { disabled: busy || eventName.trim() === '', onClick: () => void save(), children: t('customEvents.save') })] }) })] }));
84
+ }
85
+ //# sourceMappingURL=CustomEventMappingEditPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CustomEventMappingEditPage.js","sourceRoot":"","sources":["../../../src/admin/pages/CustomEventMappingEditPage.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { type ReactNode } from 'react';
2
+ /**
3
+ * Meta custom events list (feature 064, US4). Per-channel Settings (Pixel ID,
4
+ * consent) live on the generic Settings page.
5
+ */
6
+ export default function CustomEventMappingsListPage(): ReactNode;
7
+ //# sourceMappingURL=CustomEventMappingsListPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CustomEventMappingsListPage.d.ts","sourceRoot":"","sources":["../../../src/admin/pages/CustomEventMappingsListPage.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAmBzE;;;GAGG;AACH,MAAM,CAAC,OAAO,UAAU,2BAA2B,IAAI,SAAS,CA4H/D"}
@@ -0,0 +1,90 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useCallback, useEffect, useState } from 'react';
3
+ import { Link } from 'react-router-dom';
4
+ import { META_STANDARD_EVENTS, } from '@endora-commerce/contracts';
5
+ import { Alert, AlertDescription, Badge, Button, PageHeader, } from '@endora-commerce/admin-kit/ui';
6
+ import { ResponsiveTable } from '@endora-commerce/admin-kit/components';
7
+ import { ApiError } from '@endora-commerce/admin-kit/lib';
8
+ import { useTranslation } from '@endora-commerce/admin-kit/i18n';
9
+ import { metaAdsClient, listSalesChannels } from '../api/meta-ads-client.js';
10
+ /**
11
+ * Meta custom events list (feature 064, US4). Per-channel Settings (Pixel ID,
12
+ * consent) live on the generic Settings page.
13
+ */
14
+ export default function CustomEventMappingsListPage() {
15
+ const t = useTranslation('meta_ads');
16
+ const [items, setItems] = useState([]);
17
+ const [channels, setChannels] = useState([]);
18
+ const [loading, setLoading] = useState(true);
19
+ const [error, setError] = useState(null);
20
+ const messageFor = useCallback((err) => err instanceof ApiError ? err.envelope.error.message : t('error.generic'), [t]);
21
+ const reload = useCallback(async () => {
22
+ setLoading(true);
23
+ setError(null);
24
+ try {
25
+ const [rows, chans] = await Promise.all([
26
+ metaAdsClient.list(),
27
+ // A channel read failure must not hide the mappings — the channel
28
+ // column falls back to the raw id.
29
+ listSalesChannels().catch(() => ({ items: [] })),
30
+ ]);
31
+ setItems(rows);
32
+ setChannels(chans.items);
33
+ }
34
+ catch (err) {
35
+ setError(messageFor(err));
36
+ }
37
+ finally {
38
+ setLoading(false);
39
+ }
40
+ }, [messageFor]);
41
+ useEffect(() => {
42
+ void reload();
43
+ }, [reload]);
44
+ const onDelete = async (row) => {
45
+ if (!window.confirm(t('customEvents.deleteConfirm')))
46
+ return;
47
+ try {
48
+ await metaAdsClient.remove(row.id);
49
+ await reload();
50
+ }
51
+ catch (err) {
52
+ setError(messageFor(err));
53
+ }
54
+ };
55
+ const columns = [
56
+ {
57
+ id: 'triggerAction',
58
+ header: t('customEvents.triggerAction'),
59
+ primary: true,
60
+ render: (r) => t(`customEvents.action.${r.triggerAction}`),
61
+ },
62
+ {
63
+ id: 'eventName',
64
+ header: t('customEvents.eventName'),
65
+ render: (r) => _jsx("code", { className: "text-xs", children: r.eventName }),
66
+ },
67
+ {
68
+ // Shown so an operator can see the standard event still fires alongside
69
+ // their custom one — a mapping adds, it never replaces.
70
+ id: 'standardEvent',
71
+ header: t('customEvents.standardEvent'),
72
+ hideOnMobile: true,
73
+ render: (r) => META_STANDARD_EVENTS[r.triggerAction] ?? t('customEvents.standardEventNone'),
74
+ },
75
+ {
76
+ id: 'salesChannel',
77
+ header: t('customEvents.salesChannel'),
78
+ render: (r) => r.salesChannelId === null
79
+ ? t('customEvents.allChannels')
80
+ : (channels.find((c) => c.id === r.salesChannelId)?.code ?? r.salesChannelId),
81
+ },
82
+ {
83
+ id: 'enabled',
84
+ header: t('customEvents.enabled'),
85
+ render: (r) => r.enabled ? (_jsx(Badge, { children: t('customEvents.enabled') })) : (_jsx(Badge, { variant: "secondary", children: "\u2014" })),
86
+ },
87
+ ];
88
+ return (_jsxs("div", { children: [_jsx(PageHeader, { title: t('customEvents.title'), description: t('customEvents.subtitle'), actions: _jsx(Button, { asChild: true, children: _jsx(Link, { to: "/meta-ads/new", children: t('customEvents.new') }) }) }), error ? (_jsx(Alert, { variant: "destructive", className: "mb-3", children: _jsx(AlertDescription, { children: error }) })) : null, loading ? null : (_jsx(ResponsiveTable, { columns: columns, data: items, keyExtractor: (r) => r.id, emptyState: _jsx("p", { className: "text-sm text-muted-foreground", children: t('customEvents.empty') }), renderActions: (r) => (_jsxs("div", { className: "flex justify-end gap-2", children: [_jsx(Button, { asChild: true, variant: "outline", size: "sm", children: _jsx(Link, { to: `/meta-ads/${r.id}`, children: t('customEvents.edit') }) }), _jsx(Button, { variant: "destructive", size: "sm", onClick: () => void onDelete(r), children: t('customEvents.delete') })] })) }))] }));
89
+ }
90
+ //# sourceMappingURL=CustomEventMappingsListPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CustomEventMappingsListPage.js","sourceRoot":"","sources":["../../../src/admin/pages/CustomEventMappingsListPage.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import { OptionalProps } from '@mikro-orm/core';
2
+ import type { MetaTriggerAction } from '@endora-commerce/contracts';
3
+ /**
4
+ * MetaCustomEventMapping (feature 064, US4). Adds a custom Meta event to a
5
+ * storefront action.
6
+ *
7
+ * A mapping is **additive**: the standard Meta event for the action still
8
+ * fires, and this adds another beside it. It never suppresses the standard
9
+ * event — an operator adding an audience event would otherwise silently lose
10
+ * their `Purchase` reporting. This is the one semantic difference from the
11
+ * otherwise-identical `linkedin_conversion_mappings`.
12
+ */
13
+ export declare class MetaCustomEventMapping {
14
+ [OptionalProps]?: 'salesChannelId' | 'enabled' | 'version' | 'createdAt' | 'updatedAt';
15
+ id: string;
16
+ salesChannelId: string | null;
17
+ triggerAction: MetaTriggerAction;
18
+ eventName: string;
19
+ enabled: boolean;
20
+ version: number;
21
+ createdAt: Date;
22
+ updatedAt: Date;
23
+ }
24
+ //# sourceMappingURL=meta-custom-event-mapping.entity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meta-custom-event-mapping.entity.d.ts","sourceRoot":"","sources":["../../../src/backend/entities/meta-custom-event-mapping.entity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,aAAa,EAAwB,MAAM,iBAAiB,CAAC;AAGrF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAEpE;;;;;;;;;GASG;AACH,qBAMa,sBAAsB;IACjC,CAAC,aAAa,CAAC,CAAC,EAAE,gBAAgB,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,WAAW,CAAC;IAGvF,EAAE,EAAE,MAAM,CAAgB;IAG1B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAQ;IAGrC,aAAa,EAAG,iBAAiB,CAAC;IAGlC,SAAS,EAAG,MAAM,CAAC;IAGnB,OAAO,EAAE,OAAO,CAAQ;IAGxB,OAAO,EAAE,MAAM,CAAK;IAGpB,SAAS,EAAE,IAAI,CAAc;IAG7B,SAAS,EAAE,IAAI,CAAc;CAC9B"}
@@ -0,0 +1,75 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { Entity, Index, OptionalProps, PrimaryKey, Property } from '@mikro-orm/core';
11
+ import { GlobalEntity } from '@endora-commerce/platform/tenancy';
12
+ import { randomUUID } from 'crypto';
13
+ /**
14
+ * MetaCustomEventMapping (feature 064, US4). Adds a custom Meta event to a
15
+ * storefront action.
16
+ *
17
+ * A mapping is **additive**: the standard Meta event for the action still
18
+ * fires, and this adds another beside it. It never suppresses the standard
19
+ * event — an operator adding an audience event would otherwise silently lose
20
+ * their `Purchase` reporting. This is the one semantic difference from the
21
+ * otherwise-identical `linkedin_conversion_mappings`.
22
+ */
23
+ let MetaCustomEventMapping = class MetaCustomEventMapping {
24
+ [OptionalProps];
25
+ id = randomUUID();
26
+ salesChannelId = null;
27
+ triggerAction;
28
+ eventName;
29
+ enabled = true;
30
+ version = 1;
31
+ createdAt = new Date();
32
+ updatedAt = new Date();
33
+ };
34
+ __decorate([
35
+ PrimaryKey({ type: 'uuid' }),
36
+ __metadata("design:type", String)
37
+ ], MetaCustomEventMapping.prototype, "id", void 0);
38
+ __decorate([
39
+ Property({ type: 'uuid', fieldName: 'sales_channel_id', nullable: true }),
40
+ __metadata("design:type", Object)
41
+ ], MetaCustomEventMapping.prototype, "salesChannelId", void 0);
42
+ __decorate([
43
+ Property({ type: 'string', length: 32, fieldName: 'trigger_action' }),
44
+ __metadata("design:type", String)
45
+ ], MetaCustomEventMapping.prototype, "triggerAction", void 0);
46
+ __decorate([
47
+ Property({ type: 'string', length: 64, fieldName: 'event_name' }),
48
+ __metadata("design:type", String)
49
+ ], MetaCustomEventMapping.prototype, "eventName", void 0);
50
+ __decorate([
51
+ Property({ type: 'boolean' }),
52
+ __metadata("design:type", Boolean)
53
+ ], MetaCustomEventMapping.prototype, "enabled", void 0);
54
+ __decorate([
55
+ Property({ type: 'integer' }),
56
+ __metadata("design:type", Number)
57
+ ], MetaCustomEventMapping.prototype, "version", void 0);
58
+ __decorate([
59
+ Property({ type: 'datetime', fieldName: 'created_at', onCreate: () => new Date() }),
60
+ __metadata("design:type", Date)
61
+ ], MetaCustomEventMapping.prototype, "createdAt", void 0);
62
+ __decorate([
63
+ Property({ type: 'datetime', fieldName: 'updated_at', onUpdate: () => new Date() }),
64
+ __metadata("design:type", Date)
65
+ ], MetaCustomEventMapping.prototype, "updatedAt", void 0);
66
+ MetaCustomEventMapping = __decorate([
67
+ GlobalEntity(),
68
+ Entity({ tableName: 'meta_custom_event_mappings' }),
69
+ Index({
70
+ name: 'meta_custom_event_mappings_channel_action_idx',
71
+ properties: ['salesChannelId', 'triggerAction'],
72
+ })
73
+ ], MetaCustomEventMapping);
74
+ export { MetaCustomEventMapping };
75
+ //# sourceMappingURL=meta-custom-event-mapping.entity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meta-custom-event-mapping.entity.js","sourceRoot":"","sources":["../../../src/backend/entities/meta-custom-event-mapping.entity.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AACrF,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAGpC;;;;;;;;;GASG;AAOI,IAAM,sBAAsB,GAA5B,MAAM,sBAAsB;IACjC,CAAC,aAAa,CAAC,CAAwE;IAGvF,EAAE,GAAW,UAAU,EAAE,CAAC;IAG1B,cAAc,GAAkB,IAAI,CAAC;IAGrC,aAAa,CAAqB;IAGlC,SAAS,CAAU;IAGnB,OAAO,GAAY,IAAI,CAAC;IAGxB,OAAO,GAAW,CAAC,CAAC;IAGpB,SAAS,GAAS,IAAI,IAAI,EAAE,CAAC;IAG7B,SAAS,GAAS,IAAI,IAAI,EAAE,CAAC;CAC9B,CAAA;AAtBC;IADC,UAAU,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;kDACH;AAG1B;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,kBAAkB,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;8DACrC;AAGrC;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,gBAAgB,EAAE,CAAC;;6DACpC;AAGlC;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC;;yDAC/C;AAGnB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;;uDACN;AAGxB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;;uDACV;AAGpB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;8BACzE,IAAI;yDAAc;AAG7B;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;8BACzE,IAAI;yDAAc;AAzBlB,sBAAsB;IANlC,YAAY,EAAE;IACd,MAAM,CAAC,EAAE,SAAS,EAAE,4BAA4B,EAAE,CAAC;IACnD,KAAK,CAAC;QACL,IAAI,EAAE,+CAA+C;QACrD,UAAU,EAAE,CAAC,gBAAgB,EAAE,eAAe,CAAC;KAChD,CAAC;GACW,sBAAsB,CA0BlC"}