@terreno/api 0.21.0 → 0.22.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.
- package/bunfig.toml +1 -1
- package/dist/auth.test.js +408 -33
- package/dist/models/consentForm.js +2 -1
- package/dist/models/consentResponse.js +2 -1
- package/dist/models/versionConfig.js +2 -1
- package/dist/openApiBuilder.d.ts +18 -0
- package/dist/openApiBuilder.js +21 -0
- package/dist/openApiBuilder.test.js +16 -0
- package/dist/permissions.test.js +10 -43
- package/dist/populate.test.js +10 -42
- package/dist/syncConsents.test.js +2 -2
- package/dist/tests/bunSetup.js +33 -283
- package/dist/tests/createTestData.d.ts +9 -0
- package/dist/tests/createTestData.js +272 -0
- package/dist/tests/models.d.ts +71 -0
- package/dist/tests/models.js +134 -0
- package/dist/tests/mongoTestSetup.d.ts +7 -0
- package/dist/tests/mongoTestSetup.js +150 -0
- package/dist/tests/testEnv.d.ts +0 -0
- package/dist/tests/testEnv.js +6 -0
- package/dist/tests/testHelper.d.ts +22 -0
- package/dist/tests/testHelper.js +115 -0
- package/dist/tests/types.d.ts +29 -0
- package/dist/tests/types.js +2 -0
- package/dist/tests.d.ts +10 -78
- package/dist/tests.js +24 -264
- package/dist/transformers.test.js +14 -50
- package/package.json +18 -4
- package/src/__snapshots__/openApiBuilder.test.ts.snap +1 -0
- package/src/auth.test.ts +277 -29
- package/src/models/consentForm.ts +3 -4
- package/src/models/consentResponse.ts +6 -4
- package/src/models/versionConfig.ts +3 -4
- package/src/openApiBuilder.test.ts +9 -0
- package/src/openApiBuilder.ts +24 -0
- package/src/permissions.test.ts +8 -23
- package/src/populate.test.ts +7 -22
- package/src/syncConsents.test.ts +1 -1
- package/src/tests/bunSetup.ts +22 -249
- package/src/tests/createTestData.ts +176 -0
- package/src/tests/models.ts +164 -0
- package/src/tests/mongoTestSetup.ts +69 -0
- package/src/tests/testEnv.ts +4 -0
- package/src/tests/testHelper.ts +57 -0
- package/src/tests/types.ts +35 -0
- package/src/tests.ts +40 -244
- package/src/transformers.test.ts +11 -30
- package/tsconfig.typedoc.json +4 -0
- package/dist/tests/index.d.ts +0 -1
- package/dist/tests/index.js +0 -17
- package/src/tests/index.ts +0 -1
|
@@ -0,0 +1,272 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
55
|
+
exports.loadTestDataFromDocuments = exports.toCachedTestData = exports.createTestData = exports.createRequiredFixtures = exports.createStandardFoods = exports.createTestUsers = exports.clearTestCollections = void 0;
|
|
56
|
+
var logger_1 = require("../logger");
|
|
57
|
+
var models_1 = require("./models");
|
|
58
|
+
var setPassword = function (user, password) { return __awaiter(void 0, void 0, void 0, function () {
|
|
59
|
+
return __generator(this, function (_a) {
|
|
60
|
+
switch (_a.label) {
|
|
61
|
+
case 0: return [4 /*yield*/, user.setPassword(password)];
|
|
62
|
+
case 1:
|
|
63
|
+
_a.sent();
|
|
64
|
+
return [4 /*yield*/, user.save()];
|
|
65
|
+
case 2:
|
|
66
|
+
_a.sent();
|
|
67
|
+
return [2 /*return*/];
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}); };
|
|
71
|
+
var clearTestCollections = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
72
|
+
return __generator(this, function (_a) {
|
|
73
|
+
switch (_a.label) {
|
|
74
|
+
case 0: return [4 /*yield*/, Promise.all([
|
|
75
|
+
models_1.UserModel.deleteMany({}),
|
|
76
|
+
models_1.FoodModel.deleteMany({}),
|
|
77
|
+
models_1.RequiredModel.deleteMany({}),
|
|
78
|
+
]).catch(logger_1.logger.catch)];
|
|
79
|
+
case 1:
|
|
80
|
+
_a.sent();
|
|
81
|
+
return [2 /*return*/];
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
}); };
|
|
85
|
+
exports.clearTestCollections = clearTestCollections;
|
|
86
|
+
var createTestUsers = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
87
|
+
var _a, notAdmin, admin, adminOther;
|
|
88
|
+
return __generator(this, function (_b) {
|
|
89
|
+
switch (_b.label) {
|
|
90
|
+
case 0: return [4 /*yield*/, Promise.all([
|
|
91
|
+
models_1.UserModel.create({ email: "notAdmin@example.com", name: "Not Admin" }),
|
|
92
|
+
models_1.UserModel.create({ admin: true, email: "admin@example.com", name: "Admin" }),
|
|
93
|
+
models_1.UserModel.create({ admin: true, email: "admin+other@example.com", name: "Admin Other" }),
|
|
94
|
+
])];
|
|
95
|
+
case 1:
|
|
96
|
+
_a = __read.apply(void 0, [_b.sent(), 3]), notAdmin = _a[0], admin = _a[1], adminOther = _a[2];
|
|
97
|
+
return [4 /*yield*/, Promise.all([
|
|
98
|
+
setPassword(notAdmin, "password"),
|
|
99
|
+
setPassword(admin, "securePassword"),
|
|
100
|
+
setPassword(adminOther, "otherPassword"),
|
|
101
|
+
])];
|
|
102
|
+
case 2:
|
|
103
|
+
_b.sent();
|
|
104
|
+
return [2 /*return*/, { admin: admin, adminOther: adminOther, notAdmin: notAdmin }];
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
}); };
|
|
108
|
+
exports.createTestUsers = createTestUsers;
|
|
109
|
+
var createStandardFoods = function (users) { return __awaiter(void 0, void 0, void 0, function () {
|
|
110
|
+
var admin, adminOther, notAdmin, _a, spinach, apple, carrots, pizza;
|
|
111
|
+
return __generator(this, function (_b) {
|
|
112
|
+
switch (_b.label) {
|
|
113
|
+
case 0:
|
|
114
|
+
admin = users.admin, adminOther = users.adminOther, notAdmin = users.notAdmin;
|
|
115
|
+
return [4 /*yield*/, Promise.all([
|
|
116
|
+
models_1.FoodModel.create({
|
|
117
|
+
calories: 1,
|
|
118
|
+
categories: [{ name: "Vegetables", show: true }],
|
|
119
|
+
created: new Date("2021-12-03T00:00:20.000Z"),
|
|
120
|
+
eatenBy: [admin._id],
|
|
121
|
+
expiration: "2026-12-31",
|
|
122
|
+
hidden: false,
|
|
123
|
+
lastEatenWith: {
|
|
124
|
+
dressing: new Date("2021-12-03T19:00:30.000Z"),
|
|
125
|
+
},
|
|
126
|
+
likesIds: [
|
|
127
|
+
{ likes: true, userId: admin._id },
|
|
128
|
+
{ likes: false, userId: notAdmin._id },
|
|
129
|
+
],
|
|
130
|
+
name: "Spinach",
|
|
131
|
+
ownerId: notAdmin._id,
|
|
132
|
+
source: {
|
|
133
|
+
dateAdded: "2023-12-13T12:30:00.000Z",
|
|
134
|
+
href: "https://www.example.com/spinach",
|
|
135
|
+
name: "Brand",
|
|
136
|
+
},
|
|
137
|
+
tags: ["healthy"],
|
|
138
|
+
}),
|
|
139
|
+
models_1.FoodModel.create({
|
|
140
|
+
calories: 100,
|
|
141
|
+
created: new Date("2021-12-03T00:00:30.000Z"),
|
|
142
|
+
expiration: "2026-12-31",
|
|
143
|
+
hidden: true,
|
|
144
|
+
likesIds: [{ likes: true, userId: admin._id }],
|
|
145
|
+
name: "Apple",
|
|
146
|
+
ownerId: admin._id,
|
|
147
|
+
source: { name: "Orchard" },
|
|
148
|
+
tags: ["healthy"],
|
|
149
|
+
}),
|
|
150
|
+
models_1.FoodModel.create({
|
|
151
|
+
calories: 100,
|
|
152
|
+
created: new Date("2021-12-03T00:00:00.000Z"),
|
|
153
|
+
eatenBy: [admin._id, notAdmin._id],
|
|
154
|
+
expiration: "2026-12-31",
|
|
155
|
+
hidden: false,
|
|
156
|
+
likesIds: [{ likes: false, userId: notAdmin._id }],
|
|
157
|
+
name: "Carrots",
|
|
158
|
+
ownerId: admin._id,
|
|
159
|
+
source: { name: "Farm" },
|
|
160
|
+
tags: ["vegetable"],
|
|
161
|
+
}),
|
|
162
|
+
models_1.FoodModel.create({
|
|
163
|
+
calories: 800,
|
|
164
|
+
created: new Date("2022-01-01T00:00:00.000Z"),
|
|
165
|
+
expiration: "2026-12-31",
|
|
166
|
+
hidden: false,
|
|
167
|
+
likesIds: [{ likes: true, userId: adminOther._id }],
|
|
168
|
+
name: "Pizza",
|
|
169
|
+
ownerId: adminOther._id,
|
|
170
|
+
source: { name: "Pizzeria" },
|
|
171
|
+
tags: ["comfort"],
|
|
172
|
+
}),
|
|
173
|
+
])];
|
|
174
|
+
case 1:
|
|
175
|
+
_a = __read.apply(void 0, [_b.sent(), 4]), spinach = _a[0], apple = _a[1], carrots = _a[2], pizza = _a[3];
|
|
176
|
+
return [2 /*return*/, { apple: apple, carrots: carrots, pizza: pizza, spinach: spinach }];
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
}); };
|
|
180
|
+
exports.createStandardFoods = createStandardFoods;
|
|
181
|
+
var createRequiredFixtures = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
182
|
+
var _a, sample, withAbout;
|
|
183
|
+
return __generator(this, function (_b) {
|
|
184
|
+
switch (_b.label) {
|
|
185
|
+
case 0: return [4 /*yield*/, Promise.all([
|
|
186
|
+
models_1.RequiredModel.create({ name: "Sample Required" }),
|
|
187
|
+
models_1.RequiredModel.create({ about: "Optional about text", name: "Required With About" }),
|
|
188
|
+
])];
|
|
189
|
+
case 1:
|
|
190
|
+
_a = __read.apply(void 0, [_b.sent(), 2]), sample = _a[0], withAbout = _a[1];
|
|
191
|
+
return [2 /*return*/, { sample: sample, withAbout: withAbout }];
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
}); };
|
|
195
|
+
exports.createRequiredFixtures = createRequiredFixtures;
|
|
196
|
+
/** Builds the standard Terreno API test database (users, foods, required docs). */
|
|
197
|
+
var createTestData = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
198
|
+
var users, _a, foods, required;
|
|
199
|
+
return __generator(this, function (_b) {
|
|
200
|
+
switch (_b.label) {
|
|
201
|
+
case 0: return [4 /*yield*/, (0, exports.clearTestCollections)()];
|
|
202
|
+
case 1:
|
|
203
|
+
_b.sent();
|
|
204
|
+
return [4 /*yield*/, (0, exports.createTestUsers)()];
|
|
205
|
+
case 2:
|
|
206
|
+
users = _b.sent();
|
|
207
|
+
return [4 /*yield*/, Promise.all([
|
|
208
|
+
(0, exports.createStandardFoods)(users),
|
|
209
|
+
(0, exports.createRequiredFixtures)(),
|
|
210
|
+
])];
|
|
211
|
+
case 3:
|
|
212
|
+
_a = __read.apply(void 0, [_b.sent(), 2]), foods = _a[0], required = _a[1];
|
|
213
|
+
return [2 /*return*/, { foods: foods, required: required, users: users }];
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
}); };
|
|
217
|
+
exports.createTestData = createTestData;
|
|
218
|
+
var toCachedTestData = function (testData) { return ({
|
|
219
|
+
foods: {
|
|
220
|
+
apple: testData.foods.apple.id,
|
|
221
|
+
carrots: testData.foods.carrots.id,
|
|
222
|
+
pizza: testData.foods.pizza.id,
|
|
223
|
+
spinach: testData.foods.spinach.id,
|
|
224
|
+
},
|
|
225
|
+
required: {
|
|
226
|
+
sample: testData.required.sample.id,
|
|
227
|
+
withAbout: testData.required.withAbout.id,
|
|
228
|
+
},
|
|
229
|
+
users: {
|
|
230
|
+
admin: testData.users.admin.id,
|
|
231
|
+
adminOther: testData.users.adminOther.id,
|
|
232
|
+
notAdmin: testData.users.notAdmin.id,
|
|
233
|
+
},
|
|
234
|
+
}); };
|
|
235
|
+
exports.toCachedTestData = toCachedTestData;
|
|
236
|
+
var loadTestDataFromDocuments = function (cached) { return __awaiter(void 0, void 0, void 0, function () {
|
|
237
|
+
var _a, admin, notAdmin, adminOther, spinach, apple, carrots, pizza, sample, withAbout;
|
|
238
|
+
return __generator(this, function (_b) {
|
|
239
|
+
switch (_b.label) {
|
|
240
|
+
case 0: return [4 /*yield*/, Promise.all([
|
|
241
|
+
models_1.UserModel.findById(cached.users.admin),
|
|
242
|
+
models_1.UserModel.findById(cached.users.notAdmin),
|
|
243
|
+
models_1.UserModel.findById(cached.users.adminOther),
|
|
244
|
+
models_1.FoodModel.findById(cached.foods.spinach),
|
|
245
|
+
models_1.FoodModel.findById(cached.foods.apple),
|
|
246
|
+
models_1.FoodModel.findById(cached.foods.carrots),
|
|
247
|
+
models_1.FoodModel.findById(cached.foods.pizza),
|
|
248
|
+
models_1.RequiredModel.findById(cached.required.sample),
|
|
249
|
+
models_1.RequiredModel.findById(cached.required.withAbout),
|
|
250
|
+
])];
|
|
251
|
+
case 1:
|
|
252
|
+
_a = __read.apply(void 0, [_b.sent(), 9]), admin = _a[0], notAdmin = _a[1], adminOther = _a[2], spinach = _a[3], apple = _a[4], carrots = _a[5], pizza = _a[6], sample = _a[7], withAbout = _a[8];
|
|
253
|
+
if (!admin ||
|
|
254
|
+
!notAdmin ||
|
|
255
|
+
!adminOther ||
|
|
256
|
+
!spinach ||
|
|
257
|
+
!apple ||
|
|
258
|
+
!carrots ||
|
|
259
|
+
!pizza ||
|
|
260
|
+
!sample ||
|
|
261
|
+
!withAbout) {
|
|
262
|
+
throw new Error("[createTestData] Cached test data references missing documents");
|
|
263
|
+
}
|
|
264
|
+
return [2 /*return*/, {
|
|
265
|
+
foods: { apple: apple, carrots: carrots, pizza: pizza, spinach: spinach },
|
|
266
|
+
required: { sample: sample, withAbout: withAbout },
|
|
267
|
+
users: { admin: admin, adminOther: adminOther, notAdmin: notAdmin },
|
|
268
|
+
}];
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
}); };
|
|
272
|
+
exports.loadTestDataFromDocuments = loadTestDataFromDocuments;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import mongoose, { type Model, Schema } from "mongoose";
|
|
2
|
+
export interface User {
|
|
3
|
+
admin: boolean;
|
|
4
|
+
name?: string;
|
|
5
|
+
username: string;
|
|
6
|
+
email: string;
|
|
7
|
+
age?: number;
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface SuperUser extends User {
|
|
11
|
+
superTitle: string;
|
|
12
|
+
}
|
|
13
|
+
export interface StaffUser extends User {
|
|
14
|
+
department: string;
|
|
15
|
+
}
|
|
16
|
+
export interface FoodCategory {
|
|
17
|
+
_id?: string;
|
|
18
|
+
name: string;
|
|
19
|
+
show: boolean;
|
|
20
|
+
created: Date;
|
|
21
|
+
updated: Date;
|
|
22
|
+
}
|
|
23
|
+
export interface Food {
|
|
24
|
+
_id: string;
|
|
25
|
+
name: string;
|
|
26
|
+
calories: number;
|
|
27
|
+
created: Date;
|
|
28
|
+
ownerId: mongoose.Types.ObjectId | User;
|
|
29
|
+
hidden?: boolean;
|
|
30
|
+
source: {
|
|
31
|
+
name: string;
|
|
32
|
+
href?: string;
|
|
33
|
+
dateAdded?: string;
|
|
34
|
+
};
|
|
35
|
+
tags: string[];
|
|
36
|
+
eatenBy: [Schema.Types.ObjectId | User];
|
|
37
|
+
lastEatenWith: {
|
|
38
|
+
[name: string]: Date;
|
|
39
|
+
};
|
|
40
|
+
categories: FoodCategory[];
|
|
41
|
+
expiration: string;
|
|
42
|
+
likesIds: {
|
|
43
|
+
userId: string;
|
|
44
|
+
likes: boolean;
|
|
45
|
+
}[];
|
|
46
|
+
}
|
|
47
|
+
export interface RequiredField {
|
|
48
|
+
name: string;
|
|
49
|
+
about?: string;
|
|
50
|
+
}
|
|
51
|
+
export declare const UserModel: mongoose.Model<User, {}, {}, {}, mongoose.Document<unknown, {}, User, {}, {}> & User & {
|
|
52
|
+
_id: mongoose.Types.ObjectId;
|
|
53
|
+
} & {
|
|
54
|
+
__v: number;
|
|
55
|
+
}, any>;
|
|
56
|
+
export declare const SuperUserModel: mongoose.Model<User & SuperUser, {}, {}, {}, mongoose.Document<unknown, {}, User & SuperUser, {}, {}> & User & SuperUser & {
|
|
57
|
+
_id: mongoose.Types.ObjectId;
|
|
58
|
+
} & {
|
|
59
|
+
__v: number;
|
|
60
|
+
}, any>;
|
|
61
|
+
export declare const StaffUserModel: mongoose.Model<User & StaffUser, {}, {}, {}, mongoose.Document<unknown, {}, User & StaffUser, {}, {}> & User & StaffUser & {
|
|
62
|
+
_id: mongoose.Types.ObjectId;
|
|
63
|
+
} & {
|
|
64
|
+
__v: number;
|
|
65
|
+
}, any>;
|
|
66
|
+
export declare const FoodModel: Model<Food>;
|
|
67
|
+
export declare const RequiredModel: mongoose.Model<RequiredField, {}, {}, {}, mongoose.Document<unknown, {}, RequiredField, {}, {}> & RequiredField & {
|
|
68
|
+
_id: mongoose.Types.ObjectId;
|
|
69
|
+
} & {
|
|
70
|
+
__v: number;
|
|
71
|
+
}, any>;
|
|
@@ -0,0 +1,134 @@
|
|
|
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 __importDefault = (this && this.__importDefault) || function (mod) {
|
|
39
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
40
|
+
};
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.RequiredModel = exports.FoodModel = exports.StaffUserModel = exports.SuperUserModel = exports.UserModel = void 0;
|
|
43
|
+
var mongoose_1 = require("mongoose");
|
|
44
|
+
var passport_local_mongoose_1 = __importDefault(require("passport-local-mongoose"));
|
|
45
|
+
var plugins_1 = require("../plugins");
|
|
46
|
+
var userSchema = new mongoose_1.Schema({
|
|
47
|
+
admin: { default: false, description: "Whether the user has admin privileges", type: Boolean },
|
|
48
|
+
age: { description: "The user's age", type: Number },
|
|
49
|
+
name: { description: "The user's display name", type: String },
|
|
50
|
+
username: { description: "The user's username", type: String },
|
|
51
|
+
});
|
|
52
|
+
userSchema.plugin(passport_local_mongoose_1.default, {
|
|
53
|
+
attemptsField: "attempts",
|
|
54
|
+
interval: process.env.NODE_ENV === "test" ? 1 : 100,
|
|
55
|
+
limitAttempts: true,
|
|
56
|
+
maxAttempts: 3,
|
|
57
|
+
maxInterval: process.env.NODE_ENV === "test" ? 1 : 300000,
|
|
58
|
+
usernameCaseInsensitive: true,
|
|
59
|
+
usernameField: "email",
|
|
60
|
+
});
|
|
61
|
+
userSchema.plugin(plugins_1.createdUpdatedPlugin);
|
|
62
|
+
userSchema.plugin(plugins_1.isDisabledPlugin);
|
|
63
|
+
userSchema.methods.postCreate = function (body) {
|
|
64
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
65
|
+
return __generator(this, function (_a) {
|
|
66
|
+
this.age = body.age;
|
|
67
|
+
return [2 /*return*/, this.save()];
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
};
|
|
71
|
+
exports.UserModel = (0, mongoose_1.model)("User", userSchema);
|
|
72
|
+
var superUserSchema = new mongoose_1.Schema({
|
|
73
|
+
superTitle: { description: "The super user's title", required: true, type: String },
|
|
74
|
+
});
|
|
75
|
+
exports.SuperUserModel = exports.UserModel.discriminator("SuperUser", superUserSchema);
|
|
76
|
+
var staffUserSchema = new mongoose_1.Schema({
|
|
77
|
+
department: {
|
|
78
|
+
description: "The department the staff member belongs to",
|
|
79
|
+
required: true,
|
|
80
|
+
type: String,
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
exports.StaffUserModel = exports.UserModel.discriminator("Staff", staffUserSchema);
|
|
84
|
+
var foodCategorySchema = new mongoose_1.Schema({
|
|
85
|
+
name: { description: "The name of the food category", type: String },
|
|
86
|
+
show: { description: "Whether this category is visible", type: Boolean },
|
|
87
|
+
}, { timestamps: { createdAt: "created", updatedAt: "updated" } });
|
|
88
|
+
var likesSchema = new mongoose_1.Schema({
|
|
89
|
+
likes: { description: "Whether the user liked the item", type: Boolean },
|
|
90
|
+
userId: { description: "The user who liked the item", ref: "User", type: "ObjectId" },
|
|
91
|
+
});
|
|
92
|
+
var foodSchema = new mongoose_1.Schema({
|
|
93
|
+
calories: { description: "Number of calories in the food", type: Number },
|
|
94
|
+
categories: { description: "Categories this food belongs to", type: [foodCategorySchema] },
|
|
95
|
+
created: { description: "When this food was created", type: Date },
|
|
96
|
+
eatenBy: [
|
|
97
|
+
{
|
|
98
|
+
description: "Users who have eaten this food",
|
|
99
|
+
ref: "User",
|
|
100
|
+
required: true,
|
|
101
|
+
type: mongoose_1.Schema.Types.ObjectId,
|
|
102
|
+
},
|
|
103
|
+
],
|
|
104
|
+
// biome-ignore lint/suspicious/noExplicitAny: DateOnly is a custom SchemaType not recognized by Mongoose's built-in type definitions
|
|
105
|
+
expiration: { description: "Expiration date of the food", type: plugins_1.DateOnly },
|
|
106
|
+
hidden: {
|
|
107
|
+
default: false,
|
|
108
|
+
description: "Whether this food is hidden from listings",
|
|
109
|
+
type: Boolean,
|
|
110
|
+
},
|
|
111
|
+
lastEatenWith: {
|
|
112
|
+
description: "Map of user names to dates they last ate this food with",
|
|
113
|
+
of: Date,
|
|
114
|
+
type: Map,
|
|
115
|
+
},
|
|
116
|
+
likesIds: { description: "User likes for this food", required: true, type: [likesSchema] },
|
|
117
|
+
name: { description: "The name of the food", type: String },
|
|
118
|
+
ownerId: { description: "The user who owns this food entry", ref: "User", type: "ObjectId" },
|
|
119
|
+
source: {
|
|
120
|
+
dateAdded: { description: "When the source was added", type: String },
|
|
121
|
+
href: { description: "URL of the source", type: String },
|
|
122
|
+
name: { description: "Name of the source", type: String },
|
|
123
|
+
},
|
|
124
|
+
tags: { description: "Tags associated with this food", type: [String] },
|
|
125
|
+
}, { strict: "throw", toJSON: { virtuals: true }, toObject: { virtuals: true } });
|
|
126
|
+
foodSchema.virtual("description").get(function () {
|
|
127
|
+
return "".concat(this.name, " has ").concat(this.calories, " calories");
|
|
128
|
+
});
|
|
129
|
+
exports.FoodModel = (0, mongoose_1.model)("Food", foodSchema);
|
|
130
|
+
var requiredSchema = new mongoose_1.Schema({
|
|
131
|
+
about: { description: "Information about the item", type: String },
|
|
132
|
+
name: { description: "The name of the item", required: true, type: String },
|
|
133
|
+
});
|
|
134
|
+
exports.RequiredModel = (0, mongoose_1.model)("Required", requiredSchema);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { TestData } from "./types";
|
|
2
|
+
export declare const cacheFilesExist: () => boolean, cleanCache: () => void, loadTestDataFromCache: () => Promise<void>, setupTestCache: (options?: {
|
|
3
|
+
force?: boolean;
|
|
4
|
+
}) => Promise<void>;
|
|
5
|
+
/** Loads fixture documents after the collection cache has been restored. */
|
|
6
|
+
export declare const loadTestData: () => Promise<TestData>;
|
|
7
|
+
export declare const resetCachedTestData: () => void;
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
36
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
37
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
38
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
39
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
40
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
41
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
45
|
+
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);
|
|
46
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
47
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
48
|
+
function step(op) {
|
|
49
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
50
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
51
|
+
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;
|
|
52
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
53
|
+
switch (op[0]) {
|
|
54
|
+
case 0: case 1: t = op; break;
|
|
55
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
56
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
57
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
58
|
+
default:
|
|
59
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
60
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
61
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
62
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
63
|
+
if (t[2]) _.ops.pop();
|
|
64
|
+
_.trys.pop(); continue;
|
|
65
|
+
}
|
|
66
|
+
op = body.call(thisArg, _);
|
|
67
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
68
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
var _a;
|
|
72
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
73
|
+
exports.resetCachedTestData = exports.loadTestData = exports.setupTestCache = exports.loadTestDataFromCache = exports.cleanCache = exports.cacheFilesExist = void 0;
|
|
74
|
+
var fs = __importStar(require("node:fs"));
|
|
75
|
+
var path = __importStar(require("node:path"));
|
|
76
|
+
var test_1 = require("@terreno/test");
|
|
77
|
+
var createTestData_1 = require("./createTestData");
|
|
78
|
+
var moduleDir = __dirname;
|
|
79
|
+
var defaultCacheDir = process.env.TERRENO_TEST_CACHE_DIR || path.join("/tmp", "terreno-api-test-cache");
|
|
80
|
+
var apiTestCache = (0, test_1.createMongoTestCache)({
|
|
81
|
+
baseDatabaseName: "terrenoTest_base",
|
|
82
|
+
cacheDir: defaultCacheDir,
|
|
83
|
+
createTestData: function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
84
|
+
var testData;
|
|
85
|
+
return __generator(this, function (_a) {
|
|
86
|
+
switch (_a.label) {
|
|
87
|
+
case 0: return [4 /*yield*/, (0, createTestData_1.createTestData)()];
|
|
88
|
+
case 1:
|
|
89
|
+
testData = _a.sent();
|
|
90
|
+
return [2 /*return*/, (0, createTestData_1.toCachedTestData)(testData)];
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
}); },
|
|
94
|
+
sourceDirs: [path.resolve(moduleDir, "..")],
|
|
95
|
+
});
|
|
96
|
+
exports.cacheFilesExist = apiTestCache.cacheFilesExist, exports.cleanCache = apiTestCache.cleanCache, exports.loadTestDataFromCache = apiTestCache.loadTestDataFromCache, exports.setupTestCache = apiTestCache.setupTestCache;
|
|
97
|
+
var cachedTestData;
|
|
98
|
+
/** Loads fixture documents after the collection cache has been restored. */
|
|
99
|
+
var loadTestData = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
100
|
+
var cachedFilePath, cached;
|
|
101
|
+
return __generator(this, function (_a) {
|
|
102
|
+
switch (_a.label) {
|
|
103
|
+
case 0:
|
|
104
|
+
if (cachedTestData) {
|
|
105
|
+
return [2 /*return*/, cachedTestData];
|
|
106
|
+
}
|
|
107
|
+
cachedFilePath = path.join(defaultCacheDir, "cached-data.json");
|
|
108
|
+
cached = JSON.parse(fs.readFileSync(cachedFilePath, "utf-8"));
|
|
109
|
+
return [4 /*yield*/, (0, createTestData_1.loadTestDataFromDocuments)(cached)];
|
|
110
|
+
case 1:
|
|
111
|
+
cachedTestData = _a.sent();
|
|
112
|
+
return [2 /*return*/, cachedTestData];
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
}); };
|
|
116
|
+
exports.loadTestData = loadTestData;
|
|
117
|
+
var resetCachedTestData = function () {
|
|
118
|
+
cachedTestData = undefined;
|
|
119
|
+
};
|
|
120
|
+
exports.resetCachedTestData = resetCachedTestData;
|
|
121
|
+
if ((_a = process.argv[1]) === null || _a === void 0 ? void 0 : _a.includes("mongoTestSetup")) {
|
|
122
|
+
var command_1 = process.argv[2];
|
|
123
|
+
var force_1 = process.argv.includes("--force");
|
|
124
|
+
void (function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
125
|
+
return __generator(this, function (_a) {
|
|
126
|
+
switch (_a.label) {
|
|
127
|
+
case 0:
|
|
128
|
+
if (!(command_1 === "setup")) return [3 /*break*/, 2];
|
|
129
|
+
return [4 /*yield*/, (0, exports.setupTestCache)({ force: force_1 })];
|
|
130
|
+
case 1:
|
|
131
|
+
_a.sent();
|
|
132
|
+
process.exit(0);
|
|
133
|
+
_a.label = 2;
|
|
134
|
+
case 2:
|
|
135
|
+
if (command_1 === "clean") {
|
|
136
|
+
(0, exports.cleanCache)();
|
|
137
|
+
(0, exports.resetCachedTestData)();
|
|
138
|
+
process.exit(0);
|
|
139
|
+
}
|
|
140
|
+
if (command_1 === "status") {
|
|
141
|
+
console.info("[mongoTestSetup] cache exists: ".concat((0, exports.cacheFilesExist)()));
|
|
142
|
+
process.exit(0);
|
|
143
|
+
}
|
|
144
|
+
console.error("[mongoTestSetup] Unknown command: ".concat(command_1 !== null && command_1 !== void 0 ? command_1 : "(none)", ". Usage: setup | clean | status"));
|
|
145
|
+
process.exit(1);
|
|
146
|
+
return [2 /*return*/];
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
}); })();
|
|
150
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var _a;
|
|
3
|
+
/** Use in-memory MongoDB when no external test URI is configured (local / CI without mongod). */
|
|
4
|
+
if (!((_a = process.env.TERRENO_TEST_MONGODB_URI) === null || _a === void 0 ? void 0 : _a.trim())) {
|
|
5
|
+
process.env.TERRENO_TEST_USE_MEMORY_MONGO = "true";
|
|
6
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { TestData } from "./types";
|
|
2
|
+
export declare const applyTestAuthEnv: () => void;
|
|
3
|
+
/** Seeds only the standard users (legacy helper). */
|
|
4
|
+
export declare const setupDb: () => Promise<readonly [import("mongoose").Document<unknown, {}, import("./models").User, {}, {}> & import("./models").User & {
|
|
5
|
+
_id: import("mongoose").Types.ObjectId;
|
|
6
|
+
} & {
|
|
7
|
+
__v: number;
|
|
8
|
+
}, import("mongoose").Document<unknown, {}, import("./models").User, {}, {}> & import("./models").User & {
|
|
9
|
+
_id: import("mongoose").Types.ObjectId;
|
|
10
|
+
} & {
|
|
11
|
+
__v: number;
|
|
12
|
+
}, import("mongoose").Document<unknown, {}, import("./models").User, {}, {}> & import("./models").User & {
|
|
13
|
+
_id: import("mongoose").Types.ObjectId;
|
|
14
|
+
} & {
|
|
15
|
+
__v: number;
|
|
16
|
+
}]>;
|
|
17
|
+
/** Seeds users, foods, and required docs — the recommended API test baseline. */
|
|
18
|
+
export declare const setupTestData: () => Promise<TestData>;
|
|
19
|
+
/** Clears all API test collections without re-seeding. */
|
|
20
|
+
export declare const resetTestCollections: () => Promise<void>;
|
|
21
|
+
export { createTestData } from "./createTestData";
|
|
22
|
+
export { loadTestData } from "./mongoTestSetup";
|