@terreno/announcements 57.4.0 → 57.6.1
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/README.md +4 -4
- package/dist/announcementsApp.js +378 -639
- package/dist/help.js +38 -46
- package/dist/helpRoutes.js +80 -200
- package/dist/models/announcement.js +42 -95
- package/dist/models/announcementAcknowledgement.js +6 -6
- package/dist/models/announcementClickEvent.js +7 -9
- package/dist/models/announcementImpression.js +7 -9
- package/dist/overview.js +151 -300
- package/dist/pending.js +62 -140
- package/package.json +6 -6
- package/src/models/announcement.ts +6 -2
- package/src/models/announcementAcknowledgement.ts +5 -4
- package/src/models/announcementClickEvent.ts +5 -4
- package/src/models/announcementImpression.ts +5 -4
- package/src/tests/index.test.ts +43 -2
- package/tsconfig.json +6 -21
package/dist/pending.js
CHANGED
|
@@ -1,129 +1,64 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
13
|
-
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
-
function step(op) {
|
|
16
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
18
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
-
switch (op[0]) {
|
|
21
|
-
case 0: case 1: t = op; break;
|
|
22
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
-
default:
|
|
26
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
-
if (t[2]) _.ops.pop();
|
|
31
|
-
_.trys.pop(); continue;
|
|
32
|
-
}
|
|
33
|
-
op = body.call(thisArg, _);
|
|
34
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
var __read = (this && this.__read) || function (o, n) {
|
|
39
|
-
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
40
|
-
if (!m) return o;
|
|
41
|
-
var i = m.call(o), r, ar = [], e;
|
|
42
|
-
try {
|
|
43
|
-
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
44
|
-
}
|
|
45
|
-
catch (error) { e = { error: error }; }
|
|
46
|
-
finally {
|
|
47
|
-
try {
|
|
48
|
-
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
49
|
-
}
|
|
50
|
-
finally { if (e) throw e.error; }
|
|
51
|
-
}
|
|
52
|
-
return ar;
|
|
53
|
-
};
|
|
54
|
-
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
55
|
-
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
56
|
-
if (ar || !(i in from)) {
|
|
57
|
-
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
58
|
-
ar[i] = from[i];
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
return to.concat(ar || Array.prototype.slice.call(from));
|
|
62
|
-
};
|
|
63
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
64
3
|
exports.isAnnouncementVisibleToUser = exports.selectPendingAnnouncements = exports.sortAnnouncementsForQueue = exports.isAnnouncementPendingForUser = exports.matchesPlatform = exports.isAnnouncementVisibleNow = exports.isInterruptDisplayMode = exports.passesMinBuildNumber = exports.parseQueryVersion = exports.matchAudienceByType = exports.resolveAudienceType = exports.resolveDisplayMode = exports.requiresAcknowledgementForAnnouncement = exports.resolveAcknowledgementPolicy = void 0;
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
var announcement = _a.announcement, _b = _a.defaultAcknowledgementPolicy, defaultAcknowledgementPolicy = _b === void 0 ? "dismiss-only" : _b;
|
|
4
|
+
const luxon_1 = require("luxon");
|
|
5
|
+
const resolveAcknowledgementPolicy = ({ announcement, defaultAcknowledgementPolicy = "dismiss-only", }) => {
|
|
68
6
|
if (announcement.acknowledgementPolicy) {
|
|
69
7
|
return announcement.acknowledgementPolicy;
|
|
70
8
|
}
|
|
71
|
-
|
|
9
|
+
const legacyRequiresAck = announcement.requiresAcknowledgement;
|
|
72
10
|
if (legacyRequiresAck === true) {
|
|
73
11
|
return "required";
|
|
74
12
|
}
|
|
75
13
|
return defaultAcknowledgementPolicy;
|
|
76
14
|
};
|
|
77
15
|
exports.resolveAcknowledgementPolicy = resolveAcknowledgementPolicy;
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
var policy = (0, exports.resolveAcknowledgementPolicy)({ announcement: announcement, defaultAcknowledgementPolicy: defaultAcknowledgementPolicy });
|
|
16
|
+
const requiresAcknowledgementForAnnouncement = ({ announcement, defaultAcknowledgementPolicy = "dismiss-only", }) => {
|
|
17
|
+
const policy = (0, exports.resolveAcknowledgementPolicy)({ announcement, defaultAcknowledgementPolicy });
|
|
81
18
|
return policy === "required";
|
|
82
19
|
};
|
|
83
20
|
exports.requiresAcknowledgementForAnnouncement = requiresAcknowledgementForAnnouncement;
|
|
84
|
-
|
|
85
|
-
|
|
21
|
+
const resolveDisplayMode = (announcement) => {
|
|
22
|
+
const mode = announcement.displayMode;
|
|
86
23
|
if (mode === "modal" || mode === "banner" || mode === "feed") {
|
|
87
24
|
return mode;
|
|
88
25
|
}
|
|
89
26
|
return "modal";
|
|
90
27
|
};
|
|
91
28
|
exports.resolveDisplayMode = resolveDisplayMode;
|
|
92
|
-
|
|
93
|
-
|
|
29
|
+
const resolveAudienceType = (announcement) => {
|
|
30
|
+
const audienceType = announcement.audienceType;
|
|
94
31
|
if (audienceType === "staff" || audienceType === "patient" || audienceType === "all") {
|
|
95
32
|
return audienceType;
|
|
96
33
|
}
|
|
97
34
|
return "all";
|
|
98
35
|
};
|
|
99
36
|
exports.resolveAudienceType = resolveAudienceType;
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
var audienceType = (0, exports.resolveAudienceType)(announcement);
|
|
37
|
+
const matchAudienceByType = ({ announcement, isStaff, user, }) => {
|
|
38
|
+
const audienceType = (0, exports.resolveAudienceType)(announcement);
|
|
103
39
|
if (audienceType === "all") {
|
|
104
40
|
return true;
|
|
105
41
|
}
|
|
106
|
-
|
|
42
|
+
const staff = isStaff(user);
|
|
107
43
|
if (audienceType === "staff") {
|
|
108
44
|
return staff;
|
|
109
45
|
}
|
|
110
46
|
return !staff;
|
|
111
47
|
};
|
|
112
48
|
exports.matchAudienceByType = matchAudienceByType;
|
|
113
|
-
|
|
49
|
+
const parseQueryVersion = (raw) => {
|
|
114
50
|
if (raw === undefined || raw === null || raw === "") {
|
|
115
51
|
return undefined;
|
|
116
52
|
}
|
|
117
|
-
|
|
53
|
+
const parsed = Number(raw);
|
|
118
54
|
if (!Number.isFinite(parsed) || !Number.isInteger(parsed)) {
|
|
119
55
|
return undefined;
|
|
120
56
|
}
|
|
121
57
|
return parsed;
|
|
122
58
|
};
|
|
123
59
|
exports.parseQueryVersion = parseQueryVersion;
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
var minBuildNumber = announcement.minBuildNumber;
|
|
60
|
+
const passesMinBuildNumber = ({ announcement, queryVersion, }) => {
|
|
61
|
+
const minBuildNumber = announcement.minBuildNumber;
|
|
127
62
|
if (minBuildNumber === undefined || minBuildNumber === null || minBuildNumber === 0) {
|
|
128
63
|
return true;
|
|
129
64
|
}
|
|
@@ -133,24 +68,23 @@ var passesMinBuildNumber = function (_a) {
|
|
|
133
68
|
return queryVersion >= minBuildNumber;
|
|
134
69
|
};
|
|
135
70
|
exports.passesMinBuildNumber = passesMinBuildNumber;
|
|
136
|
-
|
|
137
|
-
|
|
71
|
+
const isInterruptDisplayMode = (announcement) => {
|
|
72
|
+
const displayMode = (0, exports.resolveDisplayMode)(announcement);
|
|
138
73
|
return displayMode === "modal" || displayMode === "banner";
|
|
139
74
|
};
|
|
140
75
|
exports.isInterruptDisplayMode = isInterruptDisplayMode;
|
|
141
|
-
|
|
142
|
-
var announcement = _a.announcement, _b = _a.now, now = _b === void 0 ? luxon_1.DateTime.utc() : _b;
|
|
76
|
+
const isAnnouncementVisibleNow = ({ announcement, now = luxon_1.DateTime.utc(), }) => {
|
|
143
77
|
if (announcement.status !== "published") {
|
|
144
78
|
return false;
|
|
145
79
|
}
|
|
146
80
|
if (announcement.publishAt) {
|
|
147
|
-
|
|
81
|
+
const publishAt = luxon_1.DateTime.fromJSDate(announcement.publishAt);
|
|
148
82
|
if (publishAt > now) {
|
|
149
83
|
return false;
|
|
150
84
|
}
|
|
151
85
|
}
|
|
152
86
|
if (announcement.expiresAt) {
|
|
153
|
-
|
|
87
|
+
const expiresAt = luxon_1.DateTime.fromJSDate(announcement.expiresAt);
|
|
154
88
|
if (expiresAt <= now) {
|
|
155
89
|
return false;
|
|
156
90
|
}
|
|
@@ -158,85 +92,73 @@ var isAnnouncementVisibleNow = function (_a) {
|
|
|
158
92
|
return true;
|
|
159
93
|
};
|
|
160
94
|
exports.isAnnouncementVisibleNow = isAnnouncementVisibleNow;
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
var announcement = _a.announcement, platform = _a.platform;
|
|
164
|
-
var platforms = ((_b = announcement.platforms) === null || _b === void 0 ? void 0 : _b.length)
|
|
95
|
+
const matchesPlatform = ({ announcement, platform, }) => {
|
|
96
|
+
const platforms = announcement.platforms?.length
|
|
165
97
|
? announcement.platforms
|
|
166
98
|
: ["ios", "android", "web"];
|
|
167
99
|
return platforms.includes(platform);
|
|
168
100
|
};
|
|
169
101
|
exports.matchesPlatform = matchesPlatform;
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
defaultAcknowledgementPolicy: defaultAcknowledgementPolicy,
|
|
102
|
+
const isAnnouncementPendingForUser = ({ acknowledgements, announcement, defaultAcknowledgementPolicy = "dismiss-only", impressions, }) => {
|
|
103
|
+
const announcementId = announcement._id.toString();
|
|
104
|
+
const needsAck = (0, exports.requiresAcknowledgementForAnnouncement)({
|
|
105
|
+
announcement,
|
|
106
|
+
defaultAcknowledgementPolicy,
|
|
176
107
|
});
|
|
177
108
|
if (needsAck) {
|
|
178
|
-
|
|
109
|
+
const hasAck = acknowledgements.some((ack) => ack.announcementId === announcementId && ack.version === announcement.version);
|
|
179
110
|
return !hasAck;
|
|
180
111
|
}
|
|
181
|
-
|
|
182
|
-
return impression.announcementId === announcementId && impression.version === announcement.version;
|
|
183
|
-
});
|
|
112
|
+
const hasImpression = impressions.some((impression) => impression.announcementId === announcementId && impression.version === announcement.version);
|
|
184
113
|
return !hasImpression;
|
|
185
114
|
};
|
|
186
115
|
exports.isAnnouncementPendingForUser = isAnnouncementPendingForUser;
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
return rightPublished - leftPublished;
|
|
196
|
-
});
|
|
197
|
-
};
|
|
116
|
+
const sortAnnouncementsForQueue = (announcements) => [...announcements].sort((left, right) => {
|
|
117
|
+
if (right.priority !== left.priority) {
|
|
118
|
+
return right.priority - left.priority;
|
|
119
|
+
}
|
|
120
|
+
const rightPublished = right.publishedAt?.getTime() ?? 0;
|
|
121
|
+
const leftPublished = left.publishedAt?.getTime() ?? 0;
|
|
122
|
+
return rightPublished - leftPublished;
|
|
123
|
+
});
|
|
198
124
|
exports.sortAnnouncementsForQueue = sortAnnouncementsForQueue;
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
if (!(0, exports.isAnnouncementVisibleNow)({ announcement: announcement, now: now })) {
|
|
125
|
+
const selectPendingAnnouncements = ({ acknowledgements, announcements, defaultAcknowledgementPolicy = "dismiss-only", impressions, now, platform, queryVersion, }) => {
|
|
126
|
+
const visible = announcements.filter((announcement) => {
|
|
127
|
+
if (!(0, exports.isAnnouncementVisibleNow)({ announcement, now })) {
|
|
203
128
|
return false;
|
|
204
129
|
}
|
|
205
|
-
if (!(0, exports.matchesPlatform)({ announcement
|
|
130
|
+
if (!(0, exports.matchesPlatform)({ announcement, platform })) {
|
|
206
131
|
return false;
|
|
207
132
|
}
|
|
208
133
|
if (!(0, exports.isInterruptDisplayMode)(announcement)) {
|
|
209
134
|
return false;
|
|
210
135
|
}
|
|
211
|
-
if (!(0, exports.passesMinBuildNumber)({ announcement
|
|
136
|
+
if (!(0, exports.passesMinBuildNumber)({ announcement, queryVersion })) {
|
|
212
137
|
return false;
|
|
213
138
|
}
|
|
214
139
|
return (0, exports.isAnnouncementPendingForUser)({
|
|
215
|
-
acknowledgements
|
|
216
|
-
announcement
|
|
217
|
-
defaultAcknowledgementPolicy
|
|
218
|
-
impressions
|
|
140
|
+
acknowledgements,
|
|
141
|
+
announcement,
|
|
142
|
+
defaultAcknowledgementPolicy,
|
|
143
|
+
impressions,
|
|
219
144
|
});
|
|
220
145
|
});
|
|
221
146
|
return (0, exports.sortAnnouncementsForQueue)(visible);
|
|
222
147
|
};
|
|
223
148
|
exports.selectPendingAnnouncements = selectPendingAnnouncements;
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
return [2 /*return*/, matchAudience(user, announcement)];
|
|
240
|
-
});
|
|
241
|
-
}); };
|
|
149
|
+
const isAnnouncementVisibleToUser = async ({ announcement, isStaff, matchAudience, now, platform, queryVersion, user, }) => {
|
|
150
|
+
if (!(0, exports.isAnnouncementVisibleNow)({ announcement, now })) {
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
if (!(0, exports.matchesPlatform)({ announcement, platform })) {
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
if (!(0, exports.passesMinBuildNumber)({ announcement, queryVersion })) {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
if (!(0, exports.matchAudienceByType)({ announcement, isStaff, user })) {
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
return matchAudience(user, announcement);
|
|
163
|
+
};
|
|
242
164
|
exports.isAnnouncementVisibleToUser = isAnnouncementVisibleToUser;
|
package/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"author": "Josh Gachnang",
|
|
3
3
|
"bugs": {
|
|
4
|
-
"url": "https://github.com/
|
|
4
|
+
"url": "https://github.com/TerrenoLabs/terreno/issues"
|
|
5
5
|
},
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"@terreno/api": "57.
|
|
7
|
+
"@terreno/api": "57.6.1",
|
|
8
8
|
"express": "^5.2.1",
|
|
9
9
|
"luxon": "^3.7.2"
|
|
10
10
|
},
|
|
11
11
|
"description": "In-app product update announcements plugin for @terreno/api — part of Terreno, the batteries-included TypeScript framework for universal apps.",
|
|
12
12
|
"devDependencies": {
|
|
13
13
|
"@biomejs/biome": "^2.3.6",
|
|
14
|
-
"@terreno/test": "57.
|
|
14
|
+
"@terreno/test": "57.6.1",
|
|
15
15
|
"@types/bun": "^1.4.0",
|
|
16
16
|
"@types/express": "^5.0.6",
|
|
17
17
|
"@types/supertest": "^7.2.0",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"supertest": "^7.2.2",
|
|
21
21
|
"typescript": "~6.0.3"
|
|
22
22
|
},
|
|
23
|
-
"homepage": "https://github.com/
|
|
23
|
+
"homepage": "https://github.com/TerrenoLabs/terreno#readme",
|
|
24
24
|
"keywords": [
|
|
25
25
|
"announcements",
|
|
26
26
|
"api",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
},
|
|
40
40
|
"repository": {
|
|
41
41
|
"type": "git",
|
|
42
|
-
"url": "git+ssh://git@github.com/
|
|
42
|
+
"url": "git+ssh://git@github.com/TerrenoLabs/terreno.git"
|
|
43
43
|
},
|
|
44
44
|
"scripts": {
|
|
45
45
|
"compile": "bun tsc",
|
|
@@ -53,5 +53,5 @@
|
|
|
53
53
|
"test:coverage": "bun run ../scripts/check-coverage.ts"
|
|
54
54
|
},
|
|
55
55
|
"types": "dist/index.d.ts",
|
|
56
|
-
"version": "57.
|
|
56
|
+
"version": "57.6.1"
|
|
57
57
|
}
|
|
@@ -167,8 +167,12 @@ announcementSchema.pre("validate", function validatePrimaryAction() {
|
|
|
167
167
|
});
|
|
168
168
|
|
|
169
169
|
export const Announcement =
|
|
170
|
-
(mongoose.models.
|
|
171
|
-
mongoose.model<AnnouncementDocument, AnnouncementModel>(
|
|
170
|
+
(mongoose.models.TerrenoAnnouncement as AnnouncementModel) ??
|
|
171
|
+
mongoose.model<AnnouncementDocument, AnnouncementModel>(
|
|
172
|
+
"TerrenoAnnouncement",
|
|
173
|
+
announcementSchema,
|
|
174
|
+
"announcements"
|
|
175
|
+
);
|
|
172
176
|
|
|
173
177
|
export const toAnnouncementPublic = (
|
|
174
178
|
doc: AnnouncementDocument,
|
|
@@ -15,7 +15,7 @@ const announcementAcknowledgementSchema = new mongoose.Schema<
|
|
|
15
15
|
announcementId: {
|
|
16
16
|
description: "Announcement that was acknowledged",
|
|
17
17
|
index: true,
|
|
18
|
-
ref: "
|
|
18
|
+
ref: "TerrenoAnnouncement",
|
|
19
19
|
required: true,
|
|
20
20
|
type: mongoose.Schema.Types.ObjectId,
|
|
21
21
|
},
|
|
@@ -43,8 +43,9 @@ announcementAcknowledgementSchema.plugin(findOneOrNone);
|
|
|
43
43
|
announcementAcknowledgementSchema.index({announcementId: 1, userId: 1, version: 1}, {unique: true});
|
|
44
44
|
|
|
45
45
|
export const AnnouncementAcknowledgement =
|
|
46
|
-
(mongoose.models.
|
|
46
|
+
(mongoose.models.TerrenoAnnouncementAcknowledgement as AnnouncementAcknowledgementModel) ??
|
|
47
47
|
mongoose.model<AnnouncementAcknowledgementDocument, AnnouncementAcknowledgementModel>(
|
|
48
|
-
"
|
|
49
|
-
announcementAcknowledgementSchema
|
|
48
|
+
"TerrenoAnnouncementAcknowledgement",
|
|
49
|
+
announcementAcknowledgementSchema,
|
|
50
|
+
"announcementacknowledgements"
|
|
50
51
|
);
|
|
@@ -20,7 +20,7 @@ const announcementClickEventSchema = new mongoose.Schema<
|
|
|
20
20
|
announcementId: {
|
|
21
21
|
description: "Announcement whose primary action was clicked",
|
|
22
22
|
index: true,
|
|
23
|
-
ref: "
|
|
23
|
+
ref: "TerrenoAnnouncement",
|
|
24
24
|
required: true,
|
|
25
25
|
type: mongoose.Schema.Types.ObjectId,
|
|
26
26
|
},
|
|
@@ -58,10 +58,11 @@ announcementClickEventSchema.plugin(findOneOrNone);
|
|
|
58
58
|
announcementClickEventSchema.index({announcementId: 1, clickedAt: -1});
|
|
59
59
|
|
|
60
60
|
export const AnnouncementClickEvent =
|
|
61
|
-
(mongoose.models.
|
|
61
|
+
(mongoose.models.TerrenoAnnouncementClickEvent as AnnouncementClickEventModel) ??
|
|
62
62
|
mongoose.model<AnnouncementClickEventDocument, AnnouncementClickEventModel>(
|
|
63
|
-
"
|
|
64
|
-
announcementClickEventSchema
|
|
63
|
+
"TerrenoAnnouncementClickEvent",
|
|
64
|
+
announcementClickEventSchema,
|
|
65
|
+
"announcementclickevents"
|
|
65
66
|
);
|
|
66
67
|
|
|
67
68
|
export const isValidClickAction = (value: unknown): value is AnnouncementClickAction =>
|
|
@@ -14,7 +14,7 @@ const announcementImpressionSchema = new mongoose.Schema<
|
|
|
14
14
|
announcementId: {
|
|
15
15
|
description: "Announcement that was viewed",
|
|
16
16
|
index: true,
|
|
17
|
-
ref: "
|
|
17
|
+
ref: "TerrenoAnnouncement",
|
|
18
18
|
required: true,
|
|
19
19
|
type: mongoose.Schema.Types.ObjectId,
|
|
20
20
|
},
|
|
@@ -52,10 +52,11 @@ announcementImpressionSchema.plugin(findOneOrNone);
|
|
|
52
52
|
announcementImpressionSchema.index({announcementId: 1, viewedAt: -1});
|
|
53
53
|
|
|
54
54
|
export const AnnouncementImpression =
|
|
55
|
-
(mongoose.models.
|
|
55
|
+
(mongoose.models.TerrenoAnnouncementImpression as AnnouncementImpressionModel) ??
|
|
56
56
|
mongoose.model<AnnouncementImpressionDocument, AnnouncementImpressionModel>(
|
|
57
|
-
"
|
|
58
|
-
announcementImpressionSchema
|
|
57
|
+
"TerrenoAnnouncementImpression",
|
|
58
|
+
announcementImpressionSchema,
|
|
59
|
+
"announcementimpressions"
|
|
59
60
|
);
|
|
60
61
|
|
|
61
62
|
export const isValidPlatform = (value: unknown): value is AnnouncementPlatform =>
|
package/src/tests/index.test.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
import {describe, expect, it} from "bun:test";
|
|
1
|
+
import {afterAll, describe, expect, it} from "bun:test";
|
|
2
|
+
import {assert} from "chai";
|
|
3
|
+
import mongoose from "mongoose";
|
|
2
4
|
|
|
3
5
|
import {
|
|
4
6
|
Announcement,
|
|
7
|
+
AnnouncementAcknowledgement,
|
|
8
|
+
AnnouncementClickEvent,
|
|
9
|
+
AnnouncementImpression,
|
|
5
10
|
AnnouncementsApp,
|
|
6
11
|
excerptBody,
|
|
7
12
|
isAnnouncementPendingForUser,
|
|
@@ -9,10 +14,25 @@ import {
|
|
|
9
14
|
toAnnouncementPublic,
|
|
10
15
|
} from "../index";
|
|
11
16
|
|
|
17
|
+
const CONSUMER_MODEL_NAMES = [
|
|
18
|
+
"Announcement",
|
|
19
|
+
"AnnouncementAcknowledgement",
|
|
20
|
+
"AnnouncementClickEvent",
|
|
21
|
+
"AnnouncementImpression",
|
|
22
|
+
] as const;
|
|
23
|
+
|
|
24
|
+
afterAll(() => {
|
|
25
|
+
for (const modelName of CONSUMER_MODEL_NAMES) {
|
|
26
|
+
if (mongoose.models[modelName]) {
|
|
27
|
+
mongoose.deleteModel(modelName);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
|
|
12
32
|
describe("@terreno/announcements package exports", () => {
|
|
13
33
|
it("re-exports the announcements plugin surface", () => {
|
|
14
34
|
expect(typeof AnnouncementsApp).toBe("function");
|
|
15
|
-
expect(Announcement.modelName).toBe("
|
|
35
|
+
expect(Announcement.modelName).toBe("TerrenoAnnouncement");
|
|
16
36
|
expect(excerptBody("hello world")).toBe("hello world");
|
|
17
37
|
expect(
|
|
18
38
|
isAnnouncementPendingForUser({
|
|
@@ -54,4 +74,25 @@ describe("@terreno/announcements package exports", () => {
|
|
|
54
74
|
expect(toAnnouncementPublic(omittedPolicy, "required").requiresAcknowledgement).toBe(true);
|
|
55
75
|
expect(resolveAcknowledgementPolicy({announcement: dismissOnly})).toBe("dismiss-only");
|
|
56
76
|
});
|
|
77
|
+
|
|
78
|
+
it("uses namespaced model names while preserving collections", () => {
|
|
79
|
+
const models = [
|
|
80
|
+
[Announcement, "TerrenoAnnouncement", "announcements"],
|
|
81
|
+
[
|
|
82
|
+
AnnouncementAcknowledgement,
|
|
83
|
+
"TerrenoAnnouncementAcknowledgement",
|
|
84
|
+
"announcementacknowledgements",
|
|
85
|
+
],
|
|
86
|
+
[AnnouncementClickEvent, "TerrenoAnnouncementClickEvent", "announcementclickevents"],
|
|
87
|
+
[AnnouncementImpression, "TerrenoAnnouncementImpression", "announcementimpressions"],
|
|
88
|
+
] as const;
|
|
89
|
+
|
|
90
|
+
for (const [model, modelName, collectionName] of models) {
|
|
91
|
+
assert.equal(model.modelName, modelName);
|
|
92
|
+
assert.equal(model.collection.collectionName, collectionName);
|
|
93
|
+
}
|
|
94
|
+
for (const modelName of CONSUMER_MODEL_NAMES) {
|
|
95
|
+
assert.doesNotThrow(() => mongoose.model(modelName, new mongoose.Schema({})));
|
|
96
|
+
}
|
|
97
|
+
});
|
|
57
98
|
});
|
package/tsconfig.json
CHANGED
|
@@ -1,33 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"compilerOptions": {
|
|
3
|
-
"allowJs": true,
|
|
4
|
-
"allowSyntheticDefaultImports": true,
|
|
5
|
-
"baseUrl": "./",
|
|
6
3
|
"declaration": true,
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"ignoreDeprecations": "6.0",
|
|
11
|
-
"jsx": "react",
|
|
12
|
-
"lib": ["es2017", "dom", "es2017.object"],
|
|
13
|
-
"module": "commonjs",
|
|
14
|
-
"moduleResolution": "node",
|
|
15
|
-
"noEmit": false,
|
|
4
|
+
"isolatedModules": true,
|
|
5
|
+
"lib": ["es2023"],
|
|
6
|
+
"module": "nodenext",
|
|
16
7
|
"noImplicitAny": false,
|
|
17
8
|
"noImplicitReturns": true,
|
|
18
|
-
"noImplicitThis": true,
|
|
19
|
-
"noUnusedLocals": false,
|
|
20
|
-
"noUnusedParameters": false,
|
|
21
9
|
"outDir": "./dist",
|
|
22
10
|
"rootDir": "./src",
|
|
23
|
-
"preserveConstEnums": true,
|
|
24
|
-
"removeComments": false,
|
|
25
11
|
"skipLibCheck": true,
|
|
26
12
|
"strict": true,
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"target": "es5"
|
|
13
|
+
"target": "es2023",
|
|
14
|
+
"types": ["node"]
|
|
30
15
|
},
|
|
31
16
|
"exclude": ["node_modules", "src/tests", "**/*.test.ts"],
|
|
32
|
-
"include": ["src
|
|
17
|
+
"include": ["src"]
|
|
33
18
|
}
|