@heavybit/shared-lib 1.3.1 → 2.1.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 (128) hide show
  1. package/README.md +100 -0
  2. package/dist/cjs/common/errors.js +44 -5
  3. package/dist/cjs/common/errors.js.map +1 -1
  4. package/dist/cjs/common/phone.js +43 -10
  5. package/dist/cjs/common/phone.js.map +1 -1
  6. package/dist/cjs/common/response.js +78 -5
  7. package/dist/cjs/common/response.js.map +1 -1
  8. package/dist/cjs/config/index.js +1 -1
  9. package/dist/cjs/config/index.js.map +1 -1
  10. package/dist/cjs/context/index.js +49 -0
  11. package/dist/cjs/context/index.js.map +1 -0
  12. package/dist/cjs/contracts/index.js +0 -2
  13. package/dist/cjs/contracts/index.js.map +1 -1
  14. package/dist/cjs/contracts/notification-dispatch.js +87 -63
  15. package/dist/cjs/contracts/notification-dispatch.js.map +1 -1
  16. package/dist/cjs/express/auth.js +44 -11
  17. package/dist/cjs/express/auth.js.map +1 -1
  18. package/dist/cjs/express/index.js +1 -0
  19. package/dist/cjs/express/index.js.map +1 -1
  20. package/dist/cjs/express/middleware.js +154 -34
  21. package/dist/cjs/express/middleware.js.map +1 -1
  22. package/dist/cjs/express/respond.js +47 -0
  23. package/dist/cjs/express/respond.js.map +1 -0
  24. package/dist/cjs/index.js +1 -0
  25. package/dist/cjs/index.js.map +1 -1
  26. package/dist/cjs/logging/index.js +76 -40
  27. package/dist/cjs/logging/index.js.map +1 -1
  28. package/dist/cjs/logging/redact.js +117 -0
  29. package/dist/cjs/logging/redact.js.map +1 -0
  30. package/dist/cjs/messaging/index.js +1 -0
  31. package/dist/cjs/messaging/index.js.map +1 -1
  32. package/dist/cjs/messaging/staff-notifier.js +36 -44
  33. package/dist/cjs/messaging/staff-notifier.js.map +1 -1
  34. package/dist/cjs/messaging/staff-recipients.js +57 -0
  35. package/dist/cjs/messaging/staff-recipients.js.map +1 -0
  36. package/dist/cjs/validation/index.js +27 -3
  37. package/dist/cjs/validation/index.js.map +1 -1
  38. package/dist/esm/common/errors.js +42 -4
  39. package/dist/esm/common/errors.js.map +1 -1
  40. package/dist/esm/common/phone.js +43 -10
  41. package/dist/esm/common/phone.js.map +1 -1
  42. package/dist/esm/common/response.js +75 -5
  43. package/dist/esm/common/response.js.map +1 -1
  44. package/dist/esm/config/index.js +1 -1
  45. package/dist/esm/config/index.js.map +1 -1
  46. package/dist/esm/context/index.js +44 -0
  47. package/dist/esm/context/index.js.map +1 -0
  48. package/dist/esm/contracts/index.js +0 -2
  49. package/dist/esm/contracts/index.js.map +1 -1
  50. package/dist/esm/contracts/notification-dispatch.js +85 -62
  51. package/dist/esm/contracts/notification-dispatch.js.map +1 -1
  52. package/dist/esm/express/auth.js +45 -12
  53. package/dist/esm/express/auth.js.map +1 -1
  54. package/dist/esm/express/index.js +1 -0
  55. package/dist/esm/express/index.js.map +1 -1
  56. package/dist/esm/express/middleware.js +146 -27
  57. package/dist/esm/express/middleware.js.map +1 -1
  58. package/dist/esm/express/respond.js +42 -0
  59. package/dist/esm/express/respond.js.map +1 -0
  60. package/dist/esm/index.js +1 -0
  61. package/dist/esm/index.js.map +1 -1
  62. package/dist/esm/logging/index.js +68 -39
  63. package/dist/esm/logging/index.js.map +1 -1
  64. package/dist/esm/logging/redact.js +110 -0
  65. package/dist/esm/logging/redact.js.map +1 -0
  66. package/dist/esm/messaging/index.js +1 -0
  67. package/dist/esm/messaging/index.js.map +1 -1
  68. package/dist/esm/messaging/staff-notifier.js +36 -43
  69. package/dist/esm/messaging/staff-notifier.js.map +1 -1
  70. package/dist/esm/messaging/staff-recipients.js +53 -0
  71. package/dist/esm/messaging/staff-recipients.js.map +1 -0
  72. package/dist/esm/validation/index.js +27 -2
  73. package/dist/esm/validation/index.js.map +1 -1
  74. package/dist/types/alerting/index.d.ts +1 -1
  75. package/dist/types/alerting/index.d.ts.map +1 -1
  76. package/dist/types/cache/index.d.ts +1 -1
  77. package/dist/types/cache/index.d.ts.map +1 -1
  78. package/dist/types/common/errors.d.ts +48 -7
  79. package/dist/types/common/errors.d.ts.map +1 -1
  80. package/dist/types/common/phone.d.ts +35 -6
  81. package/dist/types/common/phone.d.ts.map +1 -1
  82. package/dist/types/common/response.d.ts +66 -5
  83. package/dist/types/common/response.d.ts.map +1 -1
  84. package/dist/types/config/index.d.ts +1 -1
  85. package/dist/types/config/index.d.ts.map +1 -1
  86. package/dist/types/context/index.d.ts +39 -0
  87. package/dist/types/context/index.d.ts.map +1 -0
  88. package/dist/types/contracts/index.d.ts +0 -2
  89. package/dist/types/contracts/index.d.ts.map +1 -1
  90. package/dist/types/contracts/notification-dispatch.d.ts +208 -90
  91. package/dist/types/contracts/notification-dispatch.d.ts.map +1 -1
  92. package/dist/types/express/auth.d.ts +42 -6
  93. package/dist/types/express/auth.d.ts.map +1 -1
  94. package/dist/types/express/index.d.ts +1 -0
  95. package/dist/types/express/index.d.ts.map +1 -1
  96. package/dist/types/express/middleware.d.ts +86 -7
  97. package/dist/types/express/middleware.d.ts.map +1 -1
  98. package/dist/types/express/respond.d.ts +41 -0
  99. package/dist/types/express/respond.d.ts.map +1 -0
  100. package/dist/types/index.d.ts +1 -0
  101. package/dist/types/index.d.ts.map +1 -1
  102. package/dist/types/logging/index.d.ts +30 -4
  103. package/dist/types/logging/index.d.ts.map +1 -1
  104. package/dist/types/logging/redact.d.ts +54 -0
  105. package/dist/types/logging/redact.d.ts.map +1 -0
  106. package/dist/types/messaging/index.d.ts +1 -0
  107. package/dist/types/messaging/index.d.ts.map +1 -1
  108. package/dist/types/messaging/staff-notifier.d.ts +67 -36
  109. package/dist/types/messaging/staff-notifier.d.ts.map +1 -1
  110. package/dist/types/messaging/staff-recipients.d.ts +50 -0
  111. package/dist/types/messaging/staff-recipients.d.ts.map +1 -0
  112. package/dist/types/types/index.d.ts +36 -1
  113. package/dist/types/types/index.d.ts.map +1 -1
  114. package/dist/types/validation/index.d.ts +33 -2
  115. package/dist/types/validation/index.d.ts.map +1 -1
  116. package/package.json +2 -2
  117. package/dist/cjs/contracts/editorial-draft.js +0 -120
  118. package/dist/cjs/contracts/editorial-draft.js.map +0 -1
  119. package/dist/cjs/contracts/upload-import.js +0 -54
  120. package/dist/cjs/contracts/upload-import.js.map +0 -1
  121. package/dist/esm/contracts/editorial-draft.js +0 -117
  122. package/dist/esm/contracts/editorial-draft.js.map +0 -1
  123. package/dist/esm/contracts/upload-import.js +0 -51
  124. package/dist/esm/contracts/upload-import.js.map +0 -1
  125. package/dist/types/contracts/editorial-draft.d.ts +0 -610
  126. package/dist/types/contracts/editorial-draft.d.ts.map +0 -1
  127. package/dist/types/contracts/upload-import.d.ts +0 -96
  128. package/dist/types/contracts/upload-import.d.ts.map +0 -1
@@ -1,92 +1,116 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DISPATCH_TEMPLATE_VARIABLES = exports.notificationDispatchSchema = exports.dispatchRecipientSchema = exports.dispatchValueSchema = exports.DISPATCH_LIMITS = exports.NOTIFICATION_CATEGORIES = exports.DISPATCH_CHANNELS = exports.NOTIFICATION_DISPATCH = void 0;
3
+ exports.dispatchDataKeySchema = exports.dispatchRecipientSchema = exports.dispatchValueSchema = exports.DISPATCH_LIMITS = exports.NOTIFICATION_DISPATCH = void 0;
4
+ exports.createNotificationDispatchSchema = createNotificationDispatchSchema;
5
+ /**
6
+ * Notification dispatch: a generic command contract (shared plumbing, no app vocabulary).
7
+ *
8
+ * Services never send email, SMS or push themselves. They stage one dispatch command (default
9
+ * `notification:dispatch`) through their outbox, and the app's notification-service renders a seeded
10
+ * template and delivers it. Both sides build their schema from {@link createNotificationDispatchSchema},
11
+ * so producers and the consumer cannot drift.
12
+ *
13
+ * App-specific parts are parameters: the app passes its own categories (e.g. `security`, `order`) and
14
+ * channels (e.g. `email`, `sms`, `in_app`). Template slugs and their variables also belong to the app
15
+ * (keep a table next to the notification-service seeds and test both sides against it).
16
+ */
4
17
  const zod_1 = require("zod");
5
18
  /**
6
- * `notification:dispatch` — the one command every Showbiz service stages (through its outbox) to have
7
- * notification-service render a seeded template and deliver it by email and/or the in-app feed. No
8
- * other service sends email itself. One contract for both sides: producers type their payload with it
9
- * and notification-service validates against it, so the two cannot drift.
19
+ * Default command name for a dispatch. An app may use another name and pass it to its producers.
20
+ *
21
+ * @example await outbox.command(tx, NOTIFICATION_DISPATCH, dispatch, { correlationId });
10
22
  */
11
23
  exports.NOTIFICATION_DISPATCH = 'notification:dispatch';
12
- /** Channels a dispatch may ask for. `in_app` needs a recipient `userId` (the bell feed is per user). */
13
- exports.DISPATCH_CHANNELS = ['email', 'in_app'];
14
24
  /**
15
- * What a dispatch is about. Account mail (`security`, `account`, `team`, `marketing`) goes to a user;
16
- * `staff` is an operational alert to a configured staff address.
25
+ * Size limits that keep a dispatch small enough for a queue message and safe to render.
26
+ *
27
+ * @example z.string().max(DISPATCH_LIMITS.template)
17
28
  */
18
- exports.NOTIFICATION_CATEGORIES = ['security', 'account', 'team', 'marketing', 'staff'];
19
29
  exports.DISPATCH_LIMITS = {
20
30
  template: 100,
21
31
  email: 254,
22
32
  name: 200,
33
+ userId: 36,
23
34
  dataKeys: 40,
24
35
  dataKey: 64,
25
36
  dataValue: 2000,
26
37
  secretKeys: 10,
27
38
  permission: 100,
28
39
  };
29
- /** Template variables are flat scalars: they are printed into the copy, never serialised objects. */
40
+ /**
41
+ * Template variables are flat scalars: they are printed into the copy, never serialised objects.
42
+ *
43
+ * @example dispatchValueSchema.parse('1250.00')
44
+ */
30
45
  exports.dispatchValueSchema = zod_1.z.union([zod_1.z.string().max(exports.DISPATCH_LIMITS.dataValue), zod_1.z.number().finite(), zod_1.z.boolean(), zod_1.z.null()]);
46
+ /**
47
+ * Who receives a dispatch. `userId` is needed for per-user channels such as an in-app feed;
48
+ * addresses with no account behind them carry only `email`.
49
+ *
50
+ * @example { email: 'wanjiru@example.com', name: 'Wanjiru', userId: '01J…', timezone: 'Africa/Nairobi' }
51
+ */
31
52
  exports.dispatchRecipientSchema = zod_1.z.object({
32
53
  email: zod_1.z.string().trim().email().max(exports.DISPATCH_LIMITS.email),
33
54
  name: zod_1.z.string().trim().max(exports.DISPATCH_LIMITS.name).optional(),
34
- userId: zod_1.z.string().max(36).nullish(),
55
+ userId: zod_1.z.string().max(exports.DISPATCH_LIMITS.userId).nullish(),
35
56
  locale: zod_1.z.string().max(20).nullish(),
36
57
  /** IANA zone; time variables are rendered in it. */
37
58
  timezone: zod_1.z.string().max(64).nullish(),
38
59
  });
39
- const dataKey = zod_1.z.string().regex(/^[A-Za-z][A-Za-z0-9_]*$/, 'Use a template variable name').max(exports.DISPATCH_LIMITS.dataKey);
40
- exports.notificationDispatchSchema = zod_1.z
41
- .object({
42
- /** Seeded `notification_templates.slug`. */
43
- template: zod_1.z.string().trim().min(1).max(exports.DISPATCH_LIMITS.template),
44
- category: zod_1.z.enum(exports.NOTIFICATION_CATEGORIES),
45
- recipient: exports.dispatchRecipientSchema,
46
- channels: zod_1.z.array(zod_1.z.enum(exports.DISPATCH_CHANNELS)).min(1).max(exports.DISPATCH_CHANNELS.length),
47
- data: zod_1.z
48
- .record(dataKey, exports.dispatchValueSchema)
49
- .default({})
50
- .refine((data) => Object.keys(data).length <= exports.DISPATCH_LIMITS.dataKeys, `At most ${exports.DISPATCH_LIMITS.dataKeys} variables`),
51
- /**
52
- * Keys of `data` holding a one-time secret (a sign-in code, a reset or confirm link). They are used to
53
- * render the email and nothing else: notification-service never stores them and never puts them in the
54
- * in-app feed, and email-service masks them in what it keeps.
55
- */
56
- secretKeys: zod_1.z.array(dataKey).max(exports.DISPATCH_LIMITS.secretKeys).default([]),
57
- /** Security and staff alerts are always delivered, whatever the recipient's preferences. */
58
- bypassPreferences: zod_1.z.boolean().optional(),
59
- /** The permission staff recipients hold; informational until recipients are resolved by permission. */
60
- targetPermission: zod_1.z.string().max(exports.DISPATCH_LIMITS.permission).optional(),
61
- })
62
- .superRefine((dispatch, ctx) => {
63
- for (const key of dispatch.secretKeys) {
64
- if (!(key in dispatch.data)) {
65
- ctx.addIssue({ code: zod_1.z.ZodIssueCode.custom, path: ['secretKeys'], message: `Secret key "${key}" is not in data` });
66
- }
67
- }
68
- });
69
60
  /**
70
- * The seeded templates Showbiz services dispatch, with the variables (`data` keys) each dispatch carries.
71
- * Producers send exactly these keys; a seeded template may use any subset (notification-service dead-letters
72
- * a dispatch missing a variable its template uses). Both sides test against this table.
61
+ * A template variable name the renderer can match.
62
+ *
63
+ * @example dispatchDataKeySchema.parse('expiresInMinutes')
73
64
  */
74
- exports.DISPATCH_TEMPLATE_VARIABLES = {
75
- // auth-admin-service: account and security mail
76
- 'account-activation': ['name', 'code', 'expiresInHours'],
77
- 'login-otp': ['name', 'code', 'expiresInMinutes', 'device'],
78
- 'password-reset': ['name', 'resetUrl', 'expiresInMinutes'],
79
- 'staff-invitation': ['name', 'resetUrl', 'expiresInMinutes'],
80
- 'password-changed': ['name', 'changedAt'],
81
- 'new-device-login': ['name', 'device', 'ip', 'country', 'occurredAt', 'confirmUrl', 'disputeUrl'],
82
- 'team-member-added': ['name', 'profileName', 'role', 'invitedBy'],
83
- 'account-suspended': ['name', 'reason'],
84
- 'welcome-listener': ['name'],
85
- 'welcome-creator': ['name'],
86
- // ai / newswire / editorial: staff alerts
87
- 'ai_budget_threshold': ['requester', 'period', 'threshold_pct', 'spent_usd', 'limit_usd'],
88
- 'newswire_source_unhealthy': ['source_name', 'source_slug', 'consecutive_failures', 'last_error', 'last_success_at'],
89
- 'newswire_block_rate_high': ['blocked', 'total', 'block_rate_pct', 'window_hours'],
90
- 'autopublish_audit_alert': ['problem_rate_pct', 'problem_count', 'sample_count', 'window_days', 'action_taken'],
91
- };
65
+ exports.dispatchDataKeySchema = zod_1.z.string().regex(/^[A-Za-z][A-Za-z0-9_]*$/, 'Use a template variable name').max(exports.DISPATCH_LIMITS.dataKey);
66
+ /**
67
+ * Build the dispatch schema for an app's categories and channels. Producers type their payload with it;
68
+ * the notification-service validates incoming commands with the same schema.
69
+ *
70
+ * Rules every app gets: a seeded `template` slug; one or more distinct channels; at most 40 flat-scalar `data`
71
+ * variables with renderer-safe names; `secretKeys` (one-time codes, reset links) must be keys of `data`;
72
+ * the consumer must use them only to render, never store them or show them in a feed.
73
+ *
74
+ * @typeParam C The app's categories (inferred as literals).
75
+ * @typeParam Ch The app's channels (inferred as literals).
76
+ * @param vocabulary The app's categories and channels.
77
+ * @returns A Zod schema; `data` defaults to `{}` and `secretKeys` to `[]`.
78
+ * @example
79
+ * export const dispatchSchema = createNotificationDispatchSchema({
80
+ * categories: ['security', 'account', 'order', 'staff'],
81
+ * channels: ['email', 'sms'],
82
+ * });
83
+ * export type Dispatch = z.input<typeof dispatchSchema>;
84
+ */
85
+ function createNotificationDispatchSchema(vocabulary) {
86
+ return zod_1.z
87
+ .object({
88
+ /** Seeded template slug in the notification-service. */
89
+ template: zod_1.z.string().trim().min(1).max(exports.DISPATCH_LIMITS.template),
90
+ category: zod_1.z.enum([...vocabulary.categories]),
91
+ recipient: exports.dispatchRecipientSchema,
92
+ channels: zod_1.z
93
+ .array(zod_1.z.enum([...vocabulary.channels]))
94
+ .min(1)
95
+ .max(vocabulary.channels.length)
96
+ .refine((channels) => new Set(channels).size === channels.length, 'Each channel at most once'),
97
+ data: zod_1.z
98
+ .record(exports.dispatchDataKeySchema, exports.dispatchValueSchema)
99
+ .default({})
100
+ .refine((data) => Object.keys(data).length <= exports.DISPATCH_LIMITS.dataKeys, `At most ${exports.DISPATCH_LIMITS.dataKeys} variables`),
101
+ /** Keys of `data` holding a one-time secret: used to render, never stored or shown in a feed. */
102
+ secretKeys: zod_1.z.array(exports.dispatchDataKeySchema).max(exports.DISPATCH_LIMITS.secretKeys).default([]),
103
+ /** Deliver whatever the recipient's notification preferences say (for mail the recipient cannot opt out of). */
104
+ bypassPreferences: zod_1.z.boolean().optional(),
105
+ /** The permission the recipients were resolved by, when they were (traceability only). */
106
+ targetPermission: zod_1.z.string().max(exports.DISPATCH_LIMITS.permission).optional(),
107
+ })
108
+ .superRefine((dispatch, ctx) => {
109
+ for (const key of dispatch.secretKeys) {
110
+ if (!(key in dispatch.data)) {
111
+ ctx.addIssue({ code: zod_1.z.ZodIssueCode.custom, path: ['secretKeys'], message: `Secret key "${key}" is not in data` });
112
+ }
113
+ }
114
+ });
115
+ }
92
116
  //# sourceMappingURL=notification-dispatch.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"notification-dispatch.js","sourceRoot":"","sources":["../../../src/contracts/notification-dispatch.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"notification-dispatch.js","sourceRoot":"","sources":["../../../src/contracts/notification-dispatch.ts"],"names":[],"mappings":";;;AAoGA,4EA8BC;AAlID;;;;;;;;;;;GAWG;AACH,6BAAwB;AAExB;;;;GAIG;AACU,QAAA,qBAAqB,GAAG,uBAAuB,CAAC;AAE7D;;;;GAIG;AACU,QAAA,eAAe,GAAG;IAC7B,QAAQ,EAAE,GAAG;IACb,KAAK,EAAE,GAAG;IACV,IAAI,EAAE,GAAG;IACT,MAAM,EAAE,EAAE;IACV,QAAQ,EAAE,EAAE;IACZ,OAAO,EAAE,EAAE;IACX,SAAS,EAAE,IAAI;IACf,UAAU,EAAE,EAAE;IACd,UAAU,EAAE,GAAG;CACP,CAAC;AAEX;;;;GAIG;AACU,QAAA,mBAAmB,GAAG,OAAC,CAAC,KAAK,CAAC,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,uBAAe,CAAC,SAAS,CAAC,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE,OAAC,CAAC,OAAO,EAAE,EAAE,OAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;AAGpI;;;;;GAKG;AACU,QAAA,uBAAuB,GAAG,OAAC,CAAC,MAAM,CAAC;IAC9C,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,uBAAe,CAAC,KAAK,CAAC;IAC3D,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,uBAAe,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE;IAC5D,MAAM,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,uBAAe,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE;IACxD,MAAM,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE;IACpC,oDAAoD;IACpD,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE;CACvC,CAAC,CAAC;AAGH;;;;GAIG;AACU,QAAA,qBAAqB,GAAG,OAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,yBAAyB,EAAE,8BAA8B,CAAC,CAAC,GAAG,CAAC,uBAAe,CAAC,OAAO,CAAC,CAAC;AAc9I;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAgB,gCAAgC,CAAkD,UAAqC;IACrI,OAAO,OAAC;SACL,MAAM,CAAC;QACN,wDAAwD;QACxD,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,uBAAe,CAAC,QAAQ,CAAC;QAChE,QAAQ,EAAE,OAAC,CAAC,IAAI,CAAC,CAAC,GAAG,UAAU,CAAC,UAAU,CAAgB,CAAC;QAC3D,SAAS,EAAE,+BAAuB;QAClC,QAAQ,EAAE,OAAC;aACR,KAAK,CAAC,OAAC,CAAC,IAAI,CAAC,CAAC,GAAG,UAAU,CAAC,QAAQ,CAAkB,CAAC,CAAC;aACxD,GAAG,CAAC,CAAC,CAAC;aACN,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC;aAC/B,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,MAAM,EAAE,2BAA2B,CAAC;QAChG,IAAI,EAAE,OAAC;aACJ,MAAM,CAAC,6BAAqB,EAAE,2BAAmB,CAAC;aAClD,OAAO,CAAC,EAAE,CAAC;aACX,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,IAAI,uBAAe,CAAC,QAAQ,EAAE,WAAW,uBAAe,CAAC,QAAQ,YAAY,CAAC;QAC1H,iGAAiG;QACjG,UAAU,EAAE,OAAC,CAAC,KAAK,CAAC,6BAAqB,CAAC,CAAC,GAAG,CAAC,uBAAe,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;QACtF,gHAAgH;QAChH,iBAAiB,EAAE,OAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;QACzC,0FAA0F;QAC1F,gBAAgB,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,uBAAe,CAAC,UAAU,CAAC,CAAC,QAAQ,EAAE;KACxE,CAAC;SACD,WAAW,CAAC,CAAC,QAAQ,EAAE,GAAG,EAAE,EAAE;QAC7B,KAAK,MAAM,GAAG,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;YACtC,IAAI,CAAC,CAAC,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC5B,GAAG,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAC,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,YAAY,CAAC,EAAE,OAAO,EAAE,eAAe,GAAG,kBAAkB,EAAE,CAAC,CAAC;YACrH,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -7,6 +7,7 @@ exports.requireInternalServiceSecret = requireInternalServiceSecret;
7
7
  const index_js_1 = require("../access/index.js");
8
8
  const crypto_js_1 = require("../common/crypto.js");
9
9
  const response_js_1 = require("../common/response.js");
10
+ const middleware_js_1 = require("./middleware.js");
10
11
  const index_js_2 = require("../identity/index.js");
11
12
  function resolveIdentity(req, options) {
12
13
  const result = (0, index_js_2.verifyIdentityHeaders)(req.headers, options.secret, { maxSkewMs: options.maxSkewMs });
@@ -20,19 +21,32 @@ function resolveIdentity(req, options) {
20
21
  }
21
22
  return 'anonymous';
22
23
  }
23
- /** Requires a valid gateway-signed identity; 401 otherwise. */
24
+ /**
25
+ * Requires a valid gateway-signed identity and sets `req.user`; 401 UNAUTHENTICATED (with `requestId`) otherwise.
26
+ *
27
+ * @param options Secret, skew window and logger.
28
+ * @returns Express middleware.
29
+ * @example router.use(authenticateFromGateway({ secret: config.gatewaySecret, logger }));
30
+ */
24
31
  function authenticateFromGateway(options) {
25
32
  return (req, res, next) => {
26
33
  if (resolveIdentity(req, options) === 'ok')
27
34
  return next();
28
- res.status(401).json((0, response_js_1.errorResponse)('Authentication required', undefined, 'UNAUTHENTICATED'));
35
+ res.status(401).json((0, response_js_1.errorBody)('UNAUTHENTICATED', 'Authentication required', { requestId: (0, middleware_js_1.correlationId)(req) }));
29
36
  };
30
37
  }
31
- /** Attaches `req.user` when a valid identity is present; continues anonymously otherwise. */
38
+ /**
39
+ * Attaches `req.user` when a valid identity is present and continues anonymously when none is sent.
40
+ * A forged or stale identity is still rejected with 401, never downgraded to anonymous.
41
+ *
42
+ * @param options Secret, skew window and logger.
43
+ * @returns Express middleware.
44
+ * @example router.get('/products', optionalAuthFromGateway({ secret }), controller.list);
45
+ */
32
46
  function optionalAuthFromGateway(options) {
33
47
  return (req, res, next) => {
34
48
  if (resolveIdentity(req, options) === 'invalid') {
35
- res.status(401).json((0, response_js_1.errorResponse)('Invalid identity', undefined, 'UNAUTHENTICATED'));
49
+ res.status(401).json((0, response_js_1.errorBody)('UNAUTHENTICATED', 'Invalid identity', { requestId: (0, middleware_js_1.correlationId)(req) }));
36
50
  return;
37
51
  }
38
52
  next();
@@ -41,32 +55,51 @@ function optionalAuthFromGateway(options) {
41
55
  function guard(check, message = 'You do not have permission to perform this action') {
42
56
  return (req, res, next) => {
43
57
  if (!req.user) {
44
- res.status(401).json((0, response_js_1.errorResponse)('Authentication required', undefined, 'UNAUTHENTICATED'));
58
+ res.status(401).json((0, response_js_1.errorBody)('UNAUTHENTICATED', 'Authentication required', { requestId: (0, middleware_js_1.correlationId)(req) }));
45
59
  return;
46
60
  }
47
61
  if (!check(req.user)) {
48
- res.status(403).json((0, response_js_1.errorResponse)(message, undefined, 'FORBIDDEN'));
62
+ res.status(403).json((0, response_js_1.errorBody)('FORBIDDEN', message, { requestId: (0, middleware_js_1.correlationId)(req) }));
49
63
  return;
50
64
  }
51
65
  next();
52
66
  };
53
67
  }
54
- /** Allows callers holding any of `permissions`. */
68
+ /**
69
+ * Allows callers holding any of `permissions` (401 without identity, 403 FORBIDDEN otherwise).
70
+ *
71
+ * @example router.post('/refunds', requirePermission('refunds.create'), controller.create);
72
+ */
55
73
  const requirePermission = (...permissions) => guard((u) => (0, index_js_1.hasPermission)(u, ...permissions));
56
74
  exports.requirePermission = requirePermission;
57
- /** Allows callers holding every one of `permissions`. */
75
+ /**
76
+ * Allows callers holding every one of `permissions`.
77
+ *
78
+ * @example router.delete('/x/:id', requireAllPermissions('x.read', 'x.delete'), controller.remove);
79
+ */
58
80
  const requireAllPermissions = (...permissions) => guard((u) => (0, index_js_1.hasAllPermissions)(u, ...permissions));
59
81
  exports.requireAllPermissions = requireAllPermissions;
60
- /** Allows callers with any of `roles`. Prefer permissions; roles are for coarse gates only. */
82
+ /**
83
+ * Allows callers with any of `roles`. Prefer permissions; roles are for coarse gates only.
84
+ *
85
+ * @example router.use('/ops', requireRole('platform_admin'));
86
+ */
61
87
  const requireRole = (...roles) => guard((u) => (0, index_js_1.hasRole)(u, ...roles), 'Insufficient role');
62
88
  exports.requireRole = requireRole;
63
- /** Guards `/internal/*` routes: requires the shared service secret header. */
89
+ /**
90
+ * Guards `/internal/*` routes: requires the service secret header (constant-time compare);
91
+ * 401 UNAUTHENTICATED with `requestId` otherwise.
92
+ *
93
+ * @param secret The expected `x-internal-service-secret`; an empty secret rejects every call (fail closed).
94
+ * @returns Express middleware.
95
+ * @example router.use('/internal', requireInternalServiceSecret(config.internalSecret));
96
+ */
64
97
  function requireInternalServiceSecret(secret) {
65
98
  return (req, res, next) => {
66
99
  const provided = req.headers[index_js_2.CONTEXT_HEADERS.INTERNAL_SECRET];
67
100
  if (typeof provided === 'string' && secret && (0, crypto_js_1.safeEqual)(provided, secret))
68
101
  return next();
69
- res.status(401).json((0, response_js_1.errorResponse)('Invalid internal service credentials', undefined, 'UNAUTHENTICATED'));
102
+ res.status(401).json((0, response_js_1.errorBody)('UNAUTHENTICATED', 'Invalid internal service credentials', { requestId: (0, middleware_js_1.correlationId)(req) }));
70
103
  };
71
104
  }
72
105
  //# sourceMappingURL=auth.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/express/auth.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/express/auth.ts"],"names":[],"mappings":"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"}
@@ -18,4 +18,5 @@ __exportStar(require("./auth.js"), exports);
18
18
  __exportStar(require("./middleware.js"), exports);
19
19
  __exportStar(require("./health.js"), exports);
20
20
  __exportStar(require("./security.js"), exports);
21
+ __exportStar(require("./respond.js"), exports);
21
22
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/express/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,4CAA0B;AAC1B,kDAAgC;AAChC,8CAA4B;AAC5B,gDAA8B"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/express/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,4CAA0B;AAC1B,kDAAgC;AAChC,8CAA4B;AAC5B,gDAA8B;AAC9B,+CAA6B"}
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CORRELATION_ID_PATTERN = void 0;
3
4
  exports.correlationMiddleware = correlationMiddleware;
4
5
  exports.correlationId = correlationId;
5
6
  exports.clientIp = clientIp;
@@ -12,84 +13,203 @@ exports.notFoundHandler = notFoundHandler;
12
13
  const errors_js_1 = require("../common/errors.js");
13
14
  const id_js_1 = require("../common/id.js");
14
15
  const response_js_1 = require("../common/response.js");
15
- const index_js_1 = require("../identity/index.js");
16
- const index_js_2 = require("../validation/index.js");
17
- /** Ensures every request carries `x-correlation-id` (reused from the gateway when present). */
18
- function correlationMiddleware() {
16
+ const index_js_1 = require("../context/index.js");
17
+ const index_js_2 = require("../identity/index.js");
18
+ const index_js_3 = require("../validation/index.js");
19
+ /** An incoming correlation id is trusted only if it is 8–64 chars of `[A-Za-z0-9-]` (no log injection). */
20
+ exports.CORRELATION_ID_PATTERN = /^[A-Za-z0-9-]{8,64}$/;
21
+ /**
22
+ * Gives every request one correlation id and runs the rest of the request inside a
23
+ * {@link RequestContext}. A valid incoming `x-correlation-id` (see {@link CORRELATION_ID_PATTERN}) is
24
+ * kept; anything else is replaced with a new ULID. The id is echoed on the response, written back to
25
+ * the request header (so outbound calls forward it) and becomes every error body's `requestId`.
26
+ * Mount it first: correlation → json → routes → notFoundHandler → errorHandler.
27
+ *
28
+ * @param serviceName Recorded in the context (and so in log lines written without a service).
29
+ * @returns Express middleware.
30
+ * @example app.use(correlationMiddleware('orders'));
31
+ */
32
+ function correlationMiddleware(serviceName) {
19
33
  return (req, res, next) => {
20
- const incoming = req.headers[index_js_1.CONTEXT_HEADERS.CORRELATION_ID];
21
- const id = typeof incoming === 'string' && incoming.length <= 128 ? incoming : (0, id_js_1.newId)();
22
- req.headers[index_js_1.CONTEXT_HEADERS.CORRELATION_ID] = id;
23
- res.setHeader(index_js_1.CONTEXT_HEADERS.CORRELATION_ID, id);
24
- next();
34
+ const incoming = req.headers[index_js_2.CONTEXT_HEADERS.CORRELATION_ID];
35
+ const id = typeof incoming === 'string' && exports.CORRELATION_ID_PATTERN.test(incoming) ? incoming : (0, id_js_1.newId)();
36
+ req.headers[index_js_2.CONTEXT_HEADERS.CORRELATION_ID] = id;
37
+ res.setHeader(index_js_2.CONTEXT_HEADERS.CORRELATION_ID, id);
38
+ (0, index_js_1.runWithContext)({ correlationId: id, service: serviceName }, next);
25
39
  };
26
40
  }
41
+ /**
42
+ * The request's correlation id (the source of every error body's `requestId`): the active request
43
+ * context's id, else the `x-correlation-id` header.
44
+ *
45
+ * @param req Express request.
46
+ * @returns The id, or undefined when neither is present.
47
+ * @example logger.info('Order placed', { correlationId: correlationId(req) });
48
+ */
27
49
  function correlationId(req) {
28
- const value = req.headers[index_js_1.CONTEXT_HEADERS.CORRELATION_ID];
50
+ const fromContext = (0, index_js_1.getRequestContext)()?.correlationId;
51
+ if (fromContext)
52
+ return fromContext;
53
+ const value = req.headers[index_js_2.CONTEXT_HEADERS.CORRELATION_ID];
29
54
  return typeof value === 'string' ? value : undefined;
30
55
  }
31
- /** Real client IP: gateway-forwarded header first, then Express's `req.ip`. */
56
+ /**
57
+ * Real client IP: gateway-forwarded header first, then Express's `req.ip`.
58
+ *
59
+ * @param req Express request.
60
+ * @returns The IP, or null when unknown.
61
+ * @example const ip = clientIp(req);
62
+ */
32
63
  function clientIp(req) {
33
- const forwarded = req.headers[index_js_1.CONTEXT_HEADERS.CLIENT_IP];
64
+ const forwarded = req.headers[index_js_2.CONTEXT_HEADERS.CLIENT_IP];
34
65
  if (typeof forwarded === 'string' && forwarded)
35
66
  return forwarded;
36
67
  return req.ip ?? null;
37
68
  }
69
+ /**
70
+ * The caller's IANA time zone as forwarded by the gateway.
71
+ *
72
+ * @param req Express request.
73
+ * @returns e.g. `Europe/Paris`, or null when not sent.
74
+ * @example formatInTimeZone(date, clientTimezone(req) ?? 'UTC');
75
+ */
38
76
  function clientTimezone(req) {
39
- const tz = req.headers[index_js_1.CONTEXT_HEADERS.TIMEZONE];
77
+ const tz = req.headers[index_js_2.CONTEXT_HEADERS.TIMEZONE];
40
78
  return typeof tz === 'string' && tz ? tz : null;
41
79
  }
80
+ /**
81
+ * The anonymous visitor id forwarded by the gateway (for anonymous visitor state, rate limits and analytics).
82
+ *
83
+ * @param req Express request.
84
+ * @returns The id, or null when not sent.
85
+ * @example const visitor = req.user?.id ?? anonId(req);
86
+ */
42
87
  function anonId(req) {
43
- const id = req.headers[index_js_1.CONTEXT_HEADERS.ANON_ID];
88
+ const id = req.headers[index_js_2.CONTEXT_HEADERS.ANON_ID];
44
89
  return typeof id === 'string' && id ? id : null;
45
90
  }
46
- /** Validates and replaces `req[part]` with the parsed value; 422 with field errors on failure. */
47
- function validate(schema, part = 'body') {
48
- return (req, res, next) => {
49
- const result = schema.safeParse(req[part]);
50
- if (!result.success) {
51
- res.status(422).json((0, response_js_1.errorResponse)('Validation failed', (0, index_js_2.zodIssuesToErrors)(result.error), 'VALIDATION_FAILED'));
91
+ const PART_ORDER = ['params', 'query', 'body'];
92
+ /** Field-error keys: body fields keep their own path; params/query are prefixed (`query.limit`). */
93
+ function prefixErrors(part, errors) {
94
+ if (part === 'body')
95
+ return errors;
96
+ return Object.fromEntries(Object.entries(errors).map(([key, messages]) => [key === '_' ? part : `${part}.${key}`, messages]));
97
+ }
98
+ function isSchema(value) {
99
+ return typeof value?.safeParse === 'function';
100
+ }
101
+ /**
102
+ * Validates the request with Zod at the controller boundary. Each given part is parsed and
103
+ * `req[part]` is replaced with the parsed value, so unknown keys are stripped (or rejected with
104
+ * `.strict()`) and coercions/defaults apply. Every part is checked before failing, and the combined
105
+ * field errors are thrown as a 422 {@link ValidationError} for the error handler (body fields keep
106
+ * their path; params and query fields are prefixed, e.g. `params.id`).
107
+ *
108
+ * The older single-schema form `validate(schema, part = 'body')` still works.
109
+ *
110
+ * @param schemas `{ params?, query?, body? }`, or one schema.
111
+ * @param part With a single schema: the part it checks (default `body`).
112
+ * @returns Express middleware.
113
+ * @example router.patch('/:id', validate({ params: idParam, body: updateSchema }), controller.update);
114
+ */
115
+ function validate(schemas, part = 'body') {
116
+ const parts = isSchema(schemas) ? { [part]: schemas } : schemas;
117
+ return (req, _res, next) => {
118
+ let errors = {};
119
+ const parsed = {};
120
+ for (const name of PART_ORDER) {
121
+ const schema = parts[name];
122
+ if (!schema)
123
+ continue;
124
+ const result = schema.safeParse(req[name]);
125
+ if (result.success)
126
+ parsed[name] = result.data;
127
+ else
128
+ errors = { ...errors, ...prefixErrors(name, (0, index_js_3.zodIssuesToErrors)(result.error)) };
129
+ }
130
+ if (Object.keys(errors).length > 0) {
131
+ next(new errors_js_1.ValidationError(errors));
52
132
  return;
53
133
  }
54
- // Express 5 exposes req.query as a getter; redefine to store the parsed value.
55
- Object.defineProperty(req, part, { value: result.data, writable: true, configurable: true, enumerable: true });
134
+ for (const [name, value] of Object.entries(parsed)) {
135
+ // Express 5 exposes req.query as a getter; redefine to store the parsed value.
136
+ Object.defineProperty(req, name, { value, writable: true, configurable: true, enumerable: true });
137
+ }
56
138
  next();
57
139
  };
58
140
  }
59
- /** Wraps an async handler so rejections reach the error middleware (needed on Express 4). */
141
+ /**
142
+ * Wraps an async handler so rejections reach the error middleware (needed on Express 4; harmless on 5).
143
+ *
144
+ * @param fn Async route handler.
145
+ * @returns A handler that forwards rejections to `next(err)`.
146
+ * @example router.get('/:id', asyncHandler(controller.get));
147
+ */
60
148
  function asyncHandler(fn) {
61
149
  return (req, res, next) => {
62
150
  fn(req, res, next).catch(next);
63
151
  };
64
152
  }
65
- /** Maps AppErrors to their status; everything else becomes a logged 500 with a generic message. */
153
+ /** Zod's error, recognised structurally so a service on another zod copy/version still maps to 422. */
154
+ function isZodError(err) {
155
+ return err instanceof Error && err.name === 'ZodError' && Array.isArray(err.issues);
156
+ }
157
+ /**
158
+ * Last error middleware. Every body is `{ success: false, code, message, errors?, requestId }`:
159
+ * - body-parser failures → 400 BAD_REQUEST / 413 PAYLOAD_TOO_LARGE;
160
+ * - a thrown ZodError (e.g. from `schema.parse`) → 422 VALIDATION_FAILED with field errors;
161
+ * - AppError → its status, code and errors; 4xx keep their message, 5xx get a generic one; a
162
+ * `retryAfterSeconds` becomes the `Retry-After` header;
163
+ * - anything else → logged in full, answered 500 INTERNAL_ERROR with a generic message.
164
+ * `requestId` is the request context's correlation id (set by {@link correlationMiddleware}).
165
+ *
166
+ * @param logger Receives 5xx details (message, stack, path, correlation id); never sent to the client.
167
+ * @returns Express error middleware.
168
+ * @example app.use(notFoundHandler()); app.use(errorHandler(logger));
169
+ */
66
170
  function errorHandler(logger) {
67
- return (err, req, res, _next) => {
68
- if (res.headersSent)
171
+ return (err, req, res, next) => {
172
+ if (res.headersSent) {
173
+ next(err);
69
174
  return;
175
+ }
176
+ const requestId = correlationId(req);
70
177
  const bodyError = err;
71
178
  if (bodyError?.type === 'entity.parse.failed') {
72
- res.status(400).json((0, response_js_1.errorResponse)('Malformed JSON body', undefined, 'BAD_REQUEST'));
179
+ res.status(400).json((0, response_js_1.errorBody)('BAD_REQUEST', 'Malformed JSON body', { requestId }));
73
180
  return;
74
181
  }
75
182
  if (bodyError?.type === 'entity.too.large') {
76
- res.status(413).json((0, response_js_1.errorResponse)('Request body too large', undefined, 'PAYLOAD_TOO_LARGE'));
183
+ res.status(413).json((0, response_js_1.errorBody)('PAYLOAD_TOO_LARGE', 'Request body too large', { requestId }));
184
+ return;
185
+ }
186
+ if (isZodError(err)) {
187
+ res.status(422).json((0, response_js_1.errorBody)('VALIDATION_FAILED', 'Validation failed', { errors: (0, index_js_3.zodIssuesToErrors)(err), requestId }));
77
188
  return;
78
189
  }
79
190
  if ((0, errors_js_1.isAppError)(err)) {
80
191
  if (err.statusCode >= 500)
81
- logger?.error(err.message, { path: req.path, code: err.code, correlationId: correlationId(req) });
82
- res.status(err.statusCode).json((0, response_js_1.errorResponse)((0, errors_js_1.publicMessage)(err), err.errors, err.code));
192
+ logger?.error(err.message, { path: req.path, errorCode: err.code, stack: err.stack, correlationId: requestId });
193
+ if (err.retryAfterSeconds !== undefined)
194
+ res.setHeader('Retry-After', String(Math.max(0, Math.ceil(err.retryAfterSeconds))));
195
+ const errors = err.statusCode < 500 ? err.errors : undefined;
196
+ res.status(err.statusCode).json((0, response_js_1.errorBody)(err.code, (0, errors_js_1.publicMessage)(err), { errors, requestId }));
83
197
  return;
84
198
  }
85
199
  const error = err instanceof Error ? err : new Error(String(err));
86
- logger?.error('Unhandled error', { error: error.message, stack: error.stack, path: req.path, correlationId: correlationId(req) });
87
- res.status(500).json((0, response_js_1.errorResponse)('Internal server error', undefined, 'INTERNAL_ERROR'));
200
+ logger?.error('Unhandled error', { error: error.message, stack: error.stack, path: req.path, correlationId: requestId });
201
+ res.status(500).json((0, response_js_1.errorBody)('INTERNAL_ERROR', errors_js_1.GENERIC_ERROR_MESSAGE, { requestId }));
88
202
  };
89
203
  }
204
+ /**
205
+ * Catch-all for unmatched routes: 404 NOT_FOUND with the request id. Mount after every router.
206
+ *
207
+ * @returns Express middleware.
208
+ * @example app.use(notFoundHandler()); app.use(errorHandler(logger));
209
+ */
90
210
  function notFoundHandler() {
91
- return (_req, res) => {
92
- res.status(404).json((0, response_js_1.errorResponse)('Resource not found', undefined, 'NOT_FOUND'));
211
+ return (req, res) => {
212
+ res.status(404).json((0, response_js_1.errorBody)('NOT_FOUND', 'Resource not found', { requestId: correlationId(req) }));
93
213
  };
94
214
  }
95
215
  //# sourceMappingURL=middleware.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../../src/express/middleware.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../../src/express/middleware.ts"],"names":[],"mappings":"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"}