@terreno/api 0.15.0 → 0.15.2
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 +21 -0
- package/dist/__tests__/versionCheckPlugin.test.js +83 -0
- package/dist/actions.d.ts +55 -0
- package/dist/actions.js +472 -0
- package/dist/actions.openApi.test.d.ts +1 -0
- package/dist/actions.openApi.test.js +252 -0
- package/dist/actions.test.d.ts +1 -0
- package/dist/actions.test.js +946 -0
- package/dist/api.d.ts +5 -0
- package/dist/api.js +4 -1
- package/dist/consentApp.js +118 -102
- package/dist/docLoader.d.ts +7 -0
- package/dist/docLoader.js +154 -0
- package/dist/docLoader.test.d.ts +1 -0
- package/dist/docLoader.test.js +137 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +4 -0
- package/dist/permissions.d.ts +2 -2
- package/dist/permissions.js +11 -107
- package/dist/zodOpenApi.d.ts +2 -0
- package/dist/zodOpenApi.js +7 -0
- package/package.json +6 -3
- package/src/__tests__/versionCheckPlugin.test.ts +36 -0
- package/src/actions.openApi.test.ts +176 -0
- package/src/actions.test.ts +636 -0
- package/src/actions.ts +441 -0
- package/src/api.ts +14 -1
- package/src/consentApp.ts +80 -81
- package/src/docLoader.test.ts +58 -0
- package/src/docLoader.ts +77 -0
- package/src/index.ts +2 -0
- package/src/permissions.ts +4 -62
- package/src/zodOpenApi.ts +6 -0
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
13
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
14
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
15
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
16
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
17
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
18
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
19
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
23
|
+
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);
|
|
24
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
25
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
26
|
+
function step(op) {
|
|
27
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
28
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
29
|
+
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;
|
|
30
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
31
|
+
switch (op[0]) {
|
|
32
|
+
case 0: case 1: t = op; break;
|
|
33
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
34
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
35
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
36
|
+
default:
|
|
37
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
38
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
39
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
40
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
41
|
+
if (t[2]) _.ops.pop();
|
|
42
|
+
_.trys.pop(); continue;
|
|
43
|
+
}
|
|
44
|
+
op = body.call(thisArg, _);
|
|
45
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
46
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
var __read = (this && this.__read) || function (o, n) {
|
|
50
|
+
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
51
|
+
if (!m) return o;
|
|
52
|
+
var i = m.call(o), r, ar = [], e;
|
|
53
|
+
try {
|
|
54
|
+
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
55
|
+
}
|
|
56
|
+
catch (error) { e = { error: error }; }
|
|
57
|
+
finally {
|
|
58
|
+
try {
|
|
59
|
+
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
60
|
+
}
|
|
61
|
+
finally { if (e) throw e.error; }
|
|
62
|
+
}
|
|
63
|
+
return ar;
|
|
64
|
+
};
|
|
65
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
66
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
67
|
+
};
|
|
68
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
69
|
+
// biome-ignore-all lint/suspicious/noExplicitAny: test mock typing
|
|
70
|
+
var bun_test_1 = require("bun:test");
|
|
71
|
+
var supertest_1 = __importDefault(require("supertest"));
|
|
72
|
+
var api_1 = require("./api");
|
|
73
|
+
var auth_1 = require("./auth");
|
|
74
|
+
var expressServer_1 = require("./expressServer");
|
|
75
|
+
var permissions_1 = require("./permissions");
|
|
76
|
+
var terrenoApp_1 = require("./terrenoApp");
|
|
77
|
+
var tests_1 = require("./tests");
|
|
78
|
+
var zodOpenApi_1 = require("./zodOpenApi");
|
|
79
|
+
var foodActionPermissions = {
|
|
80
|
+
create: [permissions_1.Permissions.IsAny],
|
|
81
|
+
delete: [permissions_1.Permissions.IsAny],
|
|
82
|
+
list: [permissions_1.Permissions.IsAny],
|
|
83
|
+
read: [permissions_1.Permissions.IsAny],
|
|
84
|
+
update: [permissions_1.Permissions.IsAny],
|
|
85
|
+
};
|
|
86
|
+
var foodActionRouterOptions = {
|
|
87
|
+
allowAnonymous: true,
|
|
88
|
+
collectionActions: {
|
|
89
|
+
summarize: {
|
|
90
|
+
body: zodOpenApi_1.z
|
|
91
|
+
.object({
|
|
92
|
+
label: zodOpenApi_1.z.string(),
|
|
93
|
+
})
|
|
94
|
+
.strict(),
|
|
95
|
+
handler: function (_a) { return __awaiter(void 0, [_a], void 0, function (_b) {
|
|
96
|
+
var body = _b.body;
|
|
97
|
+
return __generator(this, function (_c) {
|
|
98
|
+
return [2 /*return*/, ({ label: body.label, total: 1 })];
|
|
99
|
+
});
|
|
100
|
+
}); },
|
|
101
|
+
method: "POST",
|
|
102
|
+
permissions: [permissions_1.Permissions.IsAny],
|
|
103
|
+
response: zodOpenApi_1.z.object({ label: zodOpenApi_1.z.string(), total: zodOpenApi_1.z.number() }).strict(),
|
|
104
|
+
summary: "Summarize foods collection",
|
|
105
|
+
tag: "CustomFoodTag",
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
instanceActions: {
|
|
109
|
+
ping: {
|
|
110
|
+
handler: function (_a) { return __awaiter(void 0, [_a], void 0, function (_b) {
|
|
111
|
+
var doc = _b.doc;
|
|
112
|
+
return __generator(this, function (_c) {
|
|
113
|
+
return [2 /*return*/, ({ id: String(doc._id) })];
|
|
114
|
+
});
|
|
115
|
+
}); },
|
|
116
|
+
method: "GET",
|
|
117
|
+
permissions: [permissions_1.Permissions.IsAny],
|
|
118
|
+
response: zodOpenApi_1.z.object({ id: zodOpenApi_1.z.string() }),
|
|
119
|
+
summary: "Ping a food document",
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
permissions: foodActionPermissions,
|
|
123
|
+
sort: "-created",
|
|
124
|
+
};
|
|
125
|
+
var primeActionOpenApiRoutes = function (server, foodId) { return __awaiter(void 0, void 0, void 0, function () {
|
|
126
|
+
return __generator(this, function (_a) {
|
|
127
|
+
switch (_a.label) {
|
|
128
|
+
case 0: return [4 /*yield*/, server.get("/food/".concat(foodId, "/ping")).expect(200)];
|
|
129
|
+
case 1:
|
|
130
|
+
_a.sent();
|
|
131
|
+
return [4 /*yield*/, server.post("/food/summarize").send({ label: "test" }).expect(200)];
|
|
132
|
+
case 2:
|
|
133
|
+
_a.sent();
|
|
134
|
+
return [2 /*return*/];
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
}); };
|
|
138
|
+
var assertActionOpenApiSpec = function (spec) {
|
|
139
|
+
var _a, _b, _c, _d, _e;
|
|
140
|
+
var paths = spec.paths;
|
|
141
|
+
var collectionPath = paths["/food/summarize"];
|
|
142
|
+
var instancePath = paths["/food/{id}/ping"];
|
|
143
|
+
(0, bun_test_1.expect)(collectionPath === null || collectionPath === void 0 ? void 0 : collectionPath.post).toBeDefined();
|
|
144
|
+
(0, bun_test_1.expect)(instancePath === null || instancePath === void 0 ? void 0 : instancePath.get).toBeDefined();
|
|
145
|
+
var collectionOp = collectionPath.post;
|
|
146
|
+
var instanceOp = instancePath.get;
|
|
147
|
+
(0, bun_test_1.expect)(collectionOp.operationId).toBe("CustomFoodTag_summarize");
|
|
148
|
+
(0, bun_test_1.expect)(collectionOp.tags).toEqual(["CustomFoodTag"]);
|
|
149
|
+
(0, bun_test_1.expect)(collectionOp.summary).toBe("Summarize foods collection");
|
|
150
|
+
(0, bun_test_1.expect)(instanceOp.operationId).toBe("foods_ping");
|
|
151
|
+
(0, bun_test_1.expect)(instanceOp.tags).toEqual(["foods"]);
|
|
152
|
+
(0, bun_test_1.expect)(instanceOp.summary).toBe("Ping a food document");
|
|
153
|
+
var collectionParams = (_a = collectionOp.parameters) !== null && _a !== void 0 ? _a : [];
|
|
154
|
+
(0, bun_test_1.expect)(collectionParams.some(function (p) { return p.in === "path" && p.name === "id"; })).toBe(false);
|
|
155
|
+
var instanceParams = (_b = instanceOp.parameters) !== null && _b !== void 0 ? _b : [];
|
|
156
|
+
var idParam = instanceParams.find(function (p) { return p.in === "path" && p.name === "id"; });
|
|
157
|
+
(0, bun_test_1.expect)(idParam).toBeDefined();
|
|
158
|
+
(0, bun_test_1.expect)(idParam === null || idParam === void 0 ? void 0 : idParam.required).toBe(true);
|
|
159
|
+
var collectionRequestSchema = collectionOp.requestBody.content["application/json"].schema;
|
|
160
|
+
(0, bun_test_1.expect)((_c = collectionRequestSchema.properties) === null || _c === void 0 ? void 0 : _c.label).toBeDefined();
|
|
161
|
+
var collectionResponseSchema = collectionOp.responses["200"].content["application/json"].schema;
|
|
162
|
+
(0, bun_test_1.expect)((_d = collectionResponseSchema.properties) === null || _d === void 0 ? void 0 : _d.data).toBeDefined();
|
|
163
|
+
var instanceResponseSchema = instanceOp.responses["200"].content["application/json"].schema;
|
|
164
|
+
(0, bun_test_1.expect)((_e = instanceResponseSchema.properties) === null || _e === void 0 ? void 0 : _e.data).toBeDefined();
|
|
165
|
+
};
|
|
166
|
+
(0, bun_test_1.describe)("action OpenAPI emission", function () {
|
|
167
|
+
var admin;
|
|
168
|
+
var foodId;
|
|
169
|
+
(0, bun_test_1.beforeEach)(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
170
|
+
var food;
|
|
171
|
+
var _a;
|
|
172
|
+
return __generator(this, function (_b) {
|
|
173
|
+
switch (_b.label) {
|
|
174
|
+
case 0:
|
|
175
|
+
process.env.REFRESH_TOKEN_SECRET = "testsecret1234";
|
|
176
|
+
process.env.ENABLE_SWAGGER = "true";
|
|
177
|
+
return [4 /*yield*/, (0, tests_1.setupDb)()];
|
|
178
|
+
case 1:
|
|
179
|
+
_a = __read.apply(void 0, [_b.sent(), 1]), admin = _a[0];
|
|
180
|
+
return [4 /*yield*/, tests_1.FoodModel.create({
|
|
181
|
+
calories: 1,
|
|
182
|
+
hidden: false,
|
|
183
|
+
name: "OpenApiFood",
|
|
184
|
+
ownerId: admin._id,
|
|
185
|
+
source: { name: "test" },
|
|
186
|
+
})];
|
|
187
|
+
case 2:
|
|
188
|
+
food = _b.sent();
|
|
189
|
+
foodId = String(food._id);
|
|
190
|
+
return [2 /*return*/];
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
}); });
|
|
194
|
+
(0, bun_test_1.describe)("TerrenoApp", function () {
|
|
195
|
+
(0, bun_test_1.it)("includes action operations in openapi.json after first request", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
196
|
+
var foodRegistration, app, server, specRes;
|
|
197
|
+
return __generator(this, function (_a) {
|
|
198
|
+
switch (_a.label) {
|
|
199
|
+
case 0:
|
|
200
|
+
foodRegistration = (0, api_1.modelRouter)("/food", tests_1.FoodModel, foodActionRouterOptions);
|
|
201
|
+
app = new terrenoApp_1.TerrenoApp({
|
|
202
|
+
skipListen: true,
|
|
203
|
+
userModel: tests_1.UserModel,
|
|
204
|
+
})
|
|
205
|
+
.register(foodRegistration)
|
|
206
|
+
.build();
|
|
207
|
+
server = (0, supertest_1.default)(app);
|
|
208
|
+
return [4 /*yield*/, primeActionOpenApiRoutes(server, foodId)];
|
|
209
|
+
case 1:
|
|
210
|
+
_a.sent();
|
|
211
|
+
return [4 /*yield*/, server.get("/openapi.json").expect(200)];
|
|
212
|
+
case 2:
|
|
213
|
+
specRes = _a.sent();
|
|
214
|
+
assertActionOpenApiSpec(specRes.body);
|
|
215
|
+
return [2 /*return*/];
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
}); });
|
|
219
|
+
});
|
|
220
|
+
(0, bun_test_1.describe)("setupServer", function () {
|
|
221
|
+
var app;
|
|
222
|
+
(0, bun_test_1.beforeEach)(function () {
|
|
223
|
+
var addRoutes = function (router, routerOptions) {
|
|
224
|
+
router.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, __assign(__assign({}, foodActionRouterOptions), routerOptions)));
|
|
225
|
+
};
|
|
226
|
+
app = (0, expressServer_1.setupServer)({
|
|
227
|
+
addRoutes: addRoutes,
|
|
228
|
+
skipListen: true,
|
|
229
|
+
userModel: tests_1.UserModel,
|
|
230
|
+
});
|
|
231
|
+
(0, auth_1.setupAuth)(app, tests_1.UserModel);
|
|
232
|
+
(0, auth_1.addAuthRoutes)(app, tests_1.UserModel);
|
|
233
|
+
});
|
|
234
|
+
(0, bun_test_1.it)("emits the same action operations on first hit via legacy setupServer", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
235
|
+
var server, specRes;
|
|
236
|
+
return __generator(this, function (_a) {
|
|
237
|
+
switch (_a.label) {
|
|
238
|
+
case 0:
|
|
239
|
+
server = (0, supertest_1.default)(app);
|
|
240
|
+
return [4 /*yield*/, primeActionOpenApiRoutes(server, foodId)];
|
|
241
|
+
case 1:
|
|
242
|
+
_a.sent();
|
|
243
|
+
return [4 /*yield*/, server.get("/openapi.json").expect(200)];
|
|
244
|
+
case 2:
|
|
245
|
+
specRes = _a.sent();
|
|
246
|
+
assertActionOpenApiSpec(specRes.body);
|
|
247
|
+
return [2 /*return*/];
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
}); });
|
|
251
|
+
});
|
|
252
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|