backend-manager 5.0.163 → 5.0.164
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,10 @@ 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.164] - 2026-03-18
|
|
18
|
+
### Added
|
|
19
|
+
- Default field backfill in campaign seed setup — missing fields are restored from seed defaults without overwriting user edits
|
|
20
|
+
|
|
17
21
|
# [5.0.163] - 2026-03-18
|
|
18
22
|
### Changed
|
|
19
23
|
- Refactored campaign POST/PUT routes to generic field passthrough — schema-validated fields flow through automatically via shared `buildCampaignDoc()` utility, no manual field assignments needed
|
package/package.json
CHANGED
|
@@ -25,7 +25,7 @@ class MarketingCampaignsSeededTest extends BaseTest {
|
|
|
25
25
|
return false;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
// Check enforced fields
|
|
28
|
+
// Check enforced fields + missing defaults
|
|
29
29
|
const data = doc.data();
|
|
30
30
|
|
|
31
31
|
for (const [path, expected] of Object.entries(seed.enforced)) {
|
|
@@ -35,6 +35,11 @@ class MarketingCampaignsSeededTest extends BaseTest {
|
|
|
35
35
|
return false;
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
|
+
|
|
39
|
+
// Check for missing fields that should exist from seed
|
|
40
|
+
if (hasMissingFields(data, seed.doc)) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
38
43
|
}
|
|
39
44
|
|
|
40
45
|
return true;
|
|
@@ -62,10 +67,14 @@ class MarketingCampaignsSeededTest extends BaseTest {
|
|
|
62
67
|
continue;
|
|
63
68
|
}
|
|
64
69
|
|
|
65
|
-
// Doc exists →
|
|
70
|
+
// Doc exists → fill missing defaults + enforce required fields
|
|
66
71
|
const data = doc.data();
|
|
67
72
|
const updates = {};
|
|
68
73
|
|
|
74
|
+
// Fill missing fields from seed defaults (never overwrite existing values)
|
|
75
|
+
fillMissing(data, seed.doc, updates, '');
|
|
76
|
+
|
|
77
|
+
// Enforce required fields (always overwrite to match seed)
|
|
69
78
|
for (const [path, expected] of Object.entries(seed.enforced)) {
|
|
70
79
|
const actual = _.get(data, path);
|
|
71
80
|
|
|
@@ -106,4 +115,58 @@ class MarketingCampaignsSeededTest extends BaseTest {
|
|
|
106
115
|
}
|
|
107
116
|
}
|
|
108
117
|
|
|
118
|
+
/**
|
|
119
|
+
* Check if the live doc is missing any fields defined in the seed.
|
|
120
|
+
*/
|
|
121
|
+
function hasMissingFields(live, seed, prefix) {
|
|
122
|
+
for (const [key, seedValue] of Object.entries(seed)) {
|
|
123
|
+
if (key === 'metadata') {
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const path = prefix ? `${prefix}.${key}` : key;
|
|
128
|
+
const liveValue = _.get(live, path);
|
|
129
|
+
|
|
130
|
+
if (liveValue === undefined) {
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (_.isPlainObject(seedValue) && _.isPlainObject(liveValue)) {
|
|
135
|
+
if (hasMissingFields(live, seedValue, path)) {
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Recursively fill missing fields from seed into updates.
|
|
146
|
+
* Only sets fields that don't exist in the live doc — never overwrites.
|
|
147
|
+
* Skips metadata (managed separately).
|
|
148
|
+
*/
|
|
149
|
+
function fillMissing(live, seed, updates, prefix) {
|
|
150
|
+
for (const [key, seedValue] of Object.entries(seed)) {
|
|
151
|
+
if (key === 'metadata') {
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const path = prefix ? `${prefix}.${key}` : key;
|
|
156
|
+
const liveValue = _.get(live, path);
|
|
157
|
+
|
|
158
|
+
// If live doc is missing this field entirely, set it from seed
|
|
159
|
+
if (liveValue === undefined) {
|
|
160
|
+
_.set(updates, path, seedValue);
|
|
161
|
+
console.log(chalk.blue(` + ${path}: ${chalk.dim('(missing)')} → ${chalk.bold(JSON.stringify(seedValue).slice(0, 80))}`));
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// If both are plain objects, recurse to check nested fields
|
|
166
|
+
if (_.isPlainObject(seedValue) && _.isPlainObject(liveValue)) {
|
|
167
|
+
fillMissing(live, seedValue, updates, path);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
109
172
|
module.exports = MarketingCampaignsSeededTest;
|