backend-manager 5.0.153 → 5.0.154
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/CHANGELOG.md
CHANGED
|
@@ -14,6 +14,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
|
14
14
|
- `Fixed` for any bug fixes.
|
|
15
15
|
- `Security` in case of vulnerabilities.
|
|
16
16
|
|
|
17
|
+
# [5.0.154] - 2026-03-16
|
|
18
|
+
### Changed
|
|
19
|
+
- Add `display` property to all marketing FIELDS entries so display names are defined in the SSOT
|
|
20
|
+
- Beehiiv provider now maps fields to display names instead of raw keys
|
|
21
|
+
- Add `skip` flag for per-provider field creation control (e.g., SendGrid has first/last name built-in)
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
- `user_personal_name_first` and `user_personal_name_last` fields to FIELDS dictionary (skipped for SendGrid which has them built-in)
|
|
25
|
+
|
|
17
26
|
# [5.0.152] - 2026-03-16
|
|
18
27
|
### Fixed
|
|
19
28
|
- Email queue documents all stored at `emails-queue/NaN` — `powertools.random()` doesn't support string generation, replaced with `pushid()`
|
package/package.json
CHANGED
|
@@ -122,10 +122,10 @@ function errorWithCode(message, code) {
|
|
|
122
122
|
return err;
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
// Master field dictionary —
|
|
125
|
+
// Master field dictionary — SSOT for all marketing custom fields.
|
|
126
126
|
//
|
|
127
|
-
// SendGrid:
|
|
128
|
-
// Beehiiv:
|
|
127
|
+
// SendGrid: `display` is the custom field name (created by OMEGA, resolved by ID at runtime).
|
|
128
|
+
// Beehiiv: `display` is the custom field name (matched by display name).
|
|
129
129
|
//
|
|
130
130
|
// Source types:
|
|
131
131
|
// 'user' — read from user doc via _.get(userDoc, path)
|
|
@@ -133,35 +133,41 @@ function errorWithCode(message, code) {
|
|
|
133
133
|
// 'config' — read from Manager.config via _.get(config, path)
|
|
134
134
|
//
|
|
135
135
|
// To add a new tracked marketing field:
|
|
136
|
-
// 1. Add an entry here
|
|
137
|
-
// 2.
|
|
138
|
-
// 3.
|
|
139
|
-
// 4.
|
|
140
|
-
//
|
|
136
|
+
// 1. Add an entry here (key, display, source, path, type)
|
|
137
|
+
// 2. Run OMEGA: npm start -- --service=sendgrid,beehiiv --brand=X
|
|
138
|
+
// 3. BEM resolves field IDs at runtime — no provider code changes needed
|
|
139
|
+
// 4. If 'resolved' source, ensure resolveFieldValues() computes it
|
|
140
|
+
//
|
|
141
|
+
// Flags:
|
|
142
|
+
// skip — Array of provider names to skip field creation for (e.g., ['sendgrid'])
|
|
143
|
+
// SendGrid has first_name/last_name as built-in contact fields
|
|
144
|
+
// Beehiiv needs them created as custom fields (preset templates)
|
|
141
145
|
const FIELDS = {
|
|
142
146
|
// Brand
|
|
143
|
-
brand_id: { source: 'config', path: 'brand.id', type: 'text' },
|
|
147
|
+
brand_id: { display: 'Brand ID', source: 'config', path: 'brand.id', type: 'text' },
|
|
144
148
|
|
|
145
149
|
// User identity
|
|
146
|
-
user_auth_uid: { source: 'user', path: 'auth.uid', type: 'text' },
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
150
|
+
user_auth_uid: { display: 'User UID', source: 'user', path: 'auth.uid', type: 'text' },
|
|
151
|
+
user_personal_name_first: { display: 'First Name', source: 'user', path: 'personal.name.first', type: 'text', skip: ['sendgrid'] },
|
|
152
|
+
user_personal_name_last: { display: 'Last Name', source: 'user', path: 'personal.name.last', type: 'text', skip: ['sendgrid'] },
|
|
153
|
+
user_personal_company: { display: 'Company', source: 'user', path: 'personal.company.name', type: 'text' },
|
|
154
|
+
user_personal_country: { display: 'Country', source: 'user', path: 'personal.location.country', type: 'text' },
|
|
155
|
+
user_metadata_signup_date: { display: 'Signup Date', source: 'user', path: 'metadata.created.timestamp', type: 'date' },
|
|
156
|
+
user_metadata_last_activity: { display: 'Last Activity', source: 'user', path: 'metadata.updated.timestamp', type: 'date' },
|
|
151
157
|
|
|
152
158
|
// Subscription
|
|
153
|
-
user_subscription_plan: { source: 'resolved', path: 'plan', type: 'text' },
|
|
154
|
-
user_subscription_status: { source: 'resolved', path: 'status', type: 'text' },
|
|
155
|
-
user_subscription_trialing: { source: 'resolved', path: 'trialing', type: 'text' },
|
|
156
|
-
user_subscription_cancelling: { source: 'resolved', path: 'cancelling', type: 'text' },
|
|
157
|
-
user_subscription_ever_paid: { source: 'resolved', path: 'everPaid', type: 'text' },
|
|
158
|
-
user_subscription_payment_processor: { source: 'user', path: 'subscription.payment.processor', type: 'text' },
|
|
159
|
-
user_subscription_payment_frequency: { source: 'user', path: 'subscription.payment.frequency', type: 'text' },
|
|
160
|
-
user_subscription_payment_price: { source: 'user', path: 'subscription.payment.price', type: 'number' },
|
|
161
|
-
user_subscription_payment_last_date: { source: 'user', path: 'subscription.payment.updatedBy.date.timestamp', type: 'date' },
|
|
159
|
+
user_subscription_plan: { display: 'Plan', source: 'resolved', path: 'plan', type: 'text' },
|
|
160
|
+
user_subscription_status: { display: 'Status', source: 'resolved', path: 'status', type: 'text' },
|
|
161
|
+
user_subscription_trialing: { display: 'Trialing', source: 'resolved', path: 'trialing', type: 'text' },
|
|
162
|
+
user_subscription_cancelling: { display: 'Cancelling', source: 'resolved', path: 'cancelling', type: 'text' },
|
|
163
|
+
user_subscription_ever_paid: { display: 'Ever Paid', source: 'resolved', path: 'everPaid', type: 'text' },
|
|
164
|
+
user_subscription_payment_processor: { display: 'Payment Processor', source: 'user', path: 'subscription.payment.processor', type: 'text' },
|
|
165
|
+
user_subscription_payment_frequency: { display: 'Payment Frequency', source: 'user', path: 'subscription.payment.frequency', type: 'text' },
|
|
166
|
+
user_subscription_payment_price: { display: 'Payment Price', source: 'user', path: 'subscription.payment.price', type: 'number' },
|
|
167
|
+
user_subscription_payment_last_date: { display: 'Last Payment Date', source: 'user', path: 'subscription.payment.updatedBy.date.timestamp', type: 'date' },
|
|
162
168
|
|
|
163
169
|
// Attribution
|
|
164
|
-
user_attribution_utm_source: { source: 'user', path: 'attribution.utm.tags.utm_source', type: 'text' },
|
|
170
|
+
user_attribution_utm_source: { display: 'UTM Source', source: 'user', path: 'attribution.utm.tags.utm_source', type: 'text' },
|
|
165
171
|
};
|
|
166
172
|
|
|
167
173
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
const fetch = require('wonderful-fetch');
|
|
7
7
|
const Manager = require('../../../index.js');
|
|
8
|
-
const { resolveFieldValues } = require('../constants.js');
|
|
8
|
+
const { FIELDS, resolveFieldValues } = require('../constants.js');
|
|
9
9
|
|
|
10
10
|
const BASE_URL = 'https://api.beehiiv.com/v2';
|
|
11
11
|
|
|
@@ -255,7 +255,8 @@ async function removeContact(email) {
|
|
|
255
255
|
|
|
256
256
|
/**
|
|
257
257
|
* Build Beehiiv custom_fields array from a user doc.
|
|
258
|
-
* Resolves all field values
|
|
258
|
+
* Resolves all field values, then maps to display names for Beehiiv.
|
|
259
|
+
* Beehiiv matches custom fields by their display name.
|
|
259
260
|
*
|
|
260
261
|
* @param {object} userDoc - User document from Firestore
|
|
261
262
|
* @returns {Array<{name: string, value: string}>} Custom fields in Beehiiv format
|
|
@@ -265,7 +266,9 @@ function buildFields(userDoc) {
|
|
|
265
266
|
const fields = [];
|
|
266
267
|
|
|
267
268
|
for (const [name, value] of Object.entries(values)) {
|
|
268
|
-
|
|
269
|
+
const fieldConfig = FIELDS[name];
|
|
270
|
+
const displayName = fieldConfig?.display || name;
|
|
271
|
+
fields.push({ name: displayName, value: String(value) });
|
|
269
272
|
}
|
|
270
273
|
|
|
271
274
|
return fields;
|
|
@@ -402,7 +402,7 @@ async function addContact({ email, firstName, lastName, company, customFields })
|
|
|
402
402
|
|
|
403
403
|
/**
|
|
404
404
|
* Build SendGrid custom_fields object from a user doc.
|
|
405
|
-
* Resolves all field values,
|
|
405
|
+
* Resolves all field values, maps to display names, then resolves SendGrid IDs.
|
|
406
406
|
*
|
|
407
407
|
* @param {object} userDoc - User document from Firestore
|
|
408
408
|
* @returns {object} Custom fields keyed by SendGrid field ID (e.g., { e1_T: 'basic' })
|