@terreno/api 0.7.0 → 0.7.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/dist/__tests__/versionCheck.test.d.ts +1 -0
- package/dist/__tests__/versionCheck.test.js +263 -0
- package/dist/expressServer.js +2 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/models/versionConfig.d.ts +17 -0
- package/dist/models/versionConfig.js +66 -0
- package/dist/terrenoApp.js +2 -2
- package/dist/vendor/wesleytodd-openapi/index.d.ts +27 -0
- package/dist/vendor/wesleytodd-openapi/index.js +176 -0
- package/dist/vendor/wesleytodd-openapi/lib/convert-yaml.d.ts +2 -0
- package/dist/vendor/wesleytodd-openapi/lib/convert-yaml.js +13 -0
- package/dist/vendor/wesleytodd-openapi/lib/generate-doc.d.ts +2 -0
- package/dist/vendor/wesleytodd-openapi/lib/generate-doc.js +148 -0
- package/dist/vendor/wesleytodd-openapi/lib/layer-schema.d.ts +2 -0
- package/dist/vendor/wesleytodd-openapi/lib/layer-schema.js +12 -0
- package/dist/vendor/wesleytodd-openapi/lib/minimum-doc.d.ts +6 -0
- package/dist/vendor/wesleytodd-openapi/lib/minimum-doc.js +11 -0
- package/dist/vendor/wesleytodd-openapi/lib/ui.d.ts +1 -0
- package/dist/vendor/wesleytodd-openapi/lib/ui.js +37 -0
- package/dist/vendor/wesleytodd-openapi/lib/validate.d.ts +2 -0
- package/dist/vendor/wesleytodd-openapi/lib/validate.js +168 -0
- package/dist/versionCheckPlugin.d.ts +15 -0
- package/dist/versionCheckPlugin.js +106 -0
- package/package.json +9 -2
- package/src/__tests__/versionCheck.test.ts +132 -0
- package/src/expressServer.ts +1 -2
- package/src/index.ts +2 -0
- package/src/models/versionConfig.ts +92 -0
- package/src/terrenoApp.ts +1 -2
- package/src/vendor/wesleytodd-openapi/LICENSE +15 -0
- package/src/vendor/wesleytodd-openapi/index.js +189 -0
- package/src/vendor/wesleytodd-openapi/lib/convert-yaml.js +13 -0
- package/src/vendor/wesleytodd-openapi/lib/generate-doc.js +153 -0
- package/src/vendor/wesleytodd-openapi/lib/layer-schema.js +13 -0
- package/src/vendor/wesleytodd-openapi/lib/minimum-doc.js +12 -0
- package/src/vendor/wesleytodd-openapi/lib/ui.js +71 -0
- package/src/vendor/wesleytodd-openapi/lib/validate.js +152 -0
- package/src/versionCheckPlugin.ts +81 -0
- package/tsconfig.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,263 @@
|
|
|
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
|
+
var bun_test_1 = require("bun:test");
|
|
43
|
+
var supertest_1 = __importDefault(require("supertest"));
|
|
44
|
+
var versionConfig_1 = require("../models/versionConfig");
|
|
45
|
+
var terrenoApp_1 = require("../terrenoApp");
|
|
46
|
+
var tests_1 = require("../tests");
|
|
47
|
+
var versionCheckPlugin_1 = require("../versionCheckPlugin");
|
|
48
|
+
(0, bun_test_1.describe)("VersionCheckPlugin", function () {
|
|
49
|
+
var app;
|
|
50
|
+
(0, bun_test_1.beforeEach)(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
51
|
+
var expressApp;
|
|
52
|
+
return __generator(this, function (_a) {
|
|
53
|
+
switch (_a.label) {
|
|
54
|
+
case 0: return [4 /*yield*/, (0, tests_1.setupDb)()];
|
|
55
|
+
case 1:
|
|
56
|
+
_a.sent();
|
|
57
|
+
return [4 /*yield*/, versionConfig_1.VersionConfig.deleteMany({})];
|
|
58
|
+
case 2:
|
|
59
|
+
_a.sent();
|
|
60
|
+
expressApp = new terrenoApp_1.TerrenoApp({
|
|
61
|
+
skipListen: true,
|
|
62
|
+
userModel: tests_1.UserModel,
|
|
63
|
+
})
|
|
64
|
+
.register(new versionCheckPlugin_1.VersionCheckPlugin())
|
|
65
|
+
.build();
|
|
66
|
+
app = (0, supertest_1.default)(expressApp);
|
|
67
|
+
return [2 /*return*/];
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}); });
|
|
71
|
+
(0, bun_test_1.afterEach)(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*/, versionConfig_1.VersionConfig.deleteMany({})];
|
|
75
|
+
case 1:
|
|
76
|
+
_a.sent();
|
|
77
|
+
return [2 /*return*/];
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
}); });
|
|
81
|
+
(0, bun_test_1.it)("returns ok when no VersionConfig exists", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
82
|
+
var res;
|
|
83
|
+
return __generator(this, function (_a) {
|
|
84
|
+
switch (_a.label) {
|
|
85
|
+
case 0: return [4 /*yield*/, app.get("/version-check").query({ platform: "web", version: 100 })];
|
|
86
|
+
case 1:
|
|
87
|
+
res = _a.sent();
|
|
88
|
+
(0, bun_test_1.expect)(res.status).toBe(200);
|
|
89
|
+
(0, bun_test_1.expect)(res.body).toEqual({ status: "ok" });
|
|
90
|
+
return [2 /*return*/];
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
}); });
|
|
94
|
+
(0, bun_test_1.it)("returns ok when version param is missing", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
95
|
+
var res;
|
|
96
|
+
return __generator(this, function (_a) {
|
|
97
|
+
switch (_a.label) {
|
|
98
|
+
case 0: return [4 /*yield*/, app.get("/version-check")];
|
|
99
|
+
case 1:
|
|
100
|
+
res = _a.sent();
|
|
101
|
+
(0, bun_test_1.expect)(res.status).toBe(200);
|
|
102
|
+
(0, bun_test_1.expect)(res.body).toEqual({ status: "ok" });
|
|
103
|
+
return [2 /*return*/];
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
}); });
|
|
107
|
+
(0, bun_test_1.it)("returns ok when version param is invalid", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
108
|
+
var res;
|
|
109
|
+
return __generator(this, function (_a) {
|
|
110
|
+
switch (_a.label) {
|
|
111
|
+
case 0: return [4 /*yield*/, app.get("/version-check").query({ platform: "web", version: "invalid" })];
|
|
112
|
+
case 1:
|
|
113
|
+
res = _a.sent();
|
|
114
|
+
(0, bun_test_1.expect)(res.status).toBe(200);
|
|
115
|
+
(0, bun_test_1.expect)(res.body).toEqual({ status: "ok" });
|
|
116
|
+
return [2 /*return*/];
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
}); });
|
|
120
|
+
(0, bun_test_1.it)("returns ok when client version >= warning and required (web)", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
121
|
+
var res;
|
|
122
|
+
return __generator(this, function (_a) {
|
|
123
|
+
switch (_a.label) {
|
|
124
|
+
case 0: return [4 /*yield*/, versionConfig_1.VersionConfig.create({
|
|
125
|
+
webRequiredVersion: 50,
|
|
126
|
+
webWarningVersion: 100,
|
|
127
|
+
})];
|
|
128
|
+
case 1:
|
|
129
|
+
_a.sent();
|
|
130
|
+
return [4 /*yield*/, app.get("/version-check").query({ platform: "web", version: 150 })];
|
|
131
|
+
case 2:
|
|
132
|
+
res = _a.sent();
|
|
133
|
+
(0, bun_test_1.expect)(res.status).toBe(200);
|
|
134
|
+
(0, bun_test_1.expect)(res.body).toEqual({ status: "ok" });
|
|
135
|
+
return [2 /*return*/];
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
}); });
|
|
139
|
+
(0, bun_test_1.it)("returns warning when client version < warning (web)", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
140
|
+
var res;
|
|
141
|
+
return __generator(this, function (_a) {
|
|
142
|
+
switch (_a.label) {
|
|
143
|
+
case 0: return [4 /*yield*/, versionConfig_1.VersionConfig.create({
|
|
144
|
+
warningMessage: "Please update!",
|
|
145
|
+
webRequiredVersion: 50,
|
|
146
|
+
webWarningVersion: 100,
|
|
147
|
+
})];
|
|
148
|
+
case 1:
|
|
149
|
+
_a.sent();
|
|
150
|
+
return [4 /*yield*/, app.get("/version-check").query({ platform: "web", version: 80 })];
|
|
151
|
+
case 2:
|
|
152
|
+
res = _a.sent();
|
|
153
|
+
(0, bun_test_1.expect)(res.status).toBe(200);
|
|
154
|
+
(0, bun_test_1.expect)(res.body.status).toBe("warning");
|
|
155
|
+
(0, bun_test_1.expect)(res.body.message).toBe("Please update!");
|
|
156
|
+
return [2 /*return*/];
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
}); });
|
|
160
|
+
(0, bun_test_1.it)("returns required when client version < required (web)", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
161
|
+
var res;
|
|
162
|
+
return __generator(this, function (_a) {
|
|
163
|
+
switch (_a.label) {
|
|
164
|
+
case 0: return [4 /*yield*/, versionConfig_1.VersionConfig.create({
|
|
165
|
+
requiredMessage: "Update required",
|
|
166
|
+
updateUrl: "https://example.com/update",
|
|
167
|
+
webRequiredVersion: 100,
|
|
168
|
+
webWarningVersion: 150,
|
|
169
|
+
})];
|
|
170
|
+
case 1:
|
|
171
|
+
_a.sent();
|
|
172
|
+
return [4 /*yield*/, app.get("/version-check").query({ platform: "web", version: 50 })];
|
|
173
|
+
case 2:
|
|
174
|
+
res = _a.sent();
|
|
175
|
+
(0, bun_test_1.expect)(res.status).toBe(200);
|
|
176
|
+
(0, bun_test_1.expect)(res.body.status).toBe("required");
|
|
177
|
+
(0, bun_test_1.expect)(res.body.message).toBe("Update required");
|
|
178
|
+
(0, bun_test_1.expect)(res.body.updateUrl).toBe("https://example.com/update");
|
|
179
|
+
return [2 /*return*/];
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
}); });
|
|
183
|
+
(0, bun_test_1.it)("uses mobile thresholds when platform is mobile", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
184
|
+
var webRes, mobileRes;
|
|
185
|
+
return __generator(this, function (_a) {
|
|
186
|
+
switch (_a.label) {
|
|
187
|
+
case 0: return [4 /*yield*/, versionConfig_1.VersionConfig.create({
|
|
188
|
+
mobileRequiredVersion: 200,
|
|
189
|
+
mobileWarningVersion: 250,
|
|
190
|
+
webRequiredVersion: 50,
|
|
191
|
+
webWarningVersion: 80,
|
|
192
|
+
})];
|
|
193
|
+
case 1:
|
|
194
|
+
_a.sent();
|
|
195
|
+
return [4 /*yield*/, app.get("/version-check").query({ platform: "web", version: 100 })];
|
|
196
|
+
case 2:
|
|
197
|
+
webRes = _a.sent();
|
|
198
|
+
(0, bun_test_1.expect)(webRes.body.status).toBe("ok");
|
|
199
|
+
return [4 /*yield*/, app.get("/version-check").query({ platform: "mobile", version: 100 })];
|
|
200
|
+
case 3:
|
|
201
|
+
mobileRes = _a.sent();
|
|
202
|
+
(0, bun_test_1.expect)(mobileRes.body.status).toBe("required");
|
|
203
|
+
return [2 /*return*/];
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
}); });
|
|
207
|
+
(0, bun_test_1.it)("defaults to web when platform is invalid", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
208
|
+
var res;
|
|
209
|
+
return __generator(this, function (_a) {
|
|
210
|
+
switch (_a.label) {
|
|
211
|
+
case 0: return [4 /*yield*/, versionConfig_1.VersionConfig.create({
|
|
212
|
+
webRequiredVersion: 100,
|
|
213
|
+
webWarningVersion: 150,
|
|
214
|
+
})];
|
|
215
|
+
case 1:
|
|
216
|
+
_a.sent();
|
|
217
|
+
return [4 /*yield*/, app.get("/version-check").query({ platform: "invalid", version: 50 })];
|
|
218
|
+
case 2:
|
|
219
|
+
res = _a.sent();
|
|
220
|
+
(0, bun_test_1.expect)(res.body.status).toBe("required");
|
|
221
|
+
return [2 /*return*/];
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
}); });
|
|
225
|
+
(0, bun_test_1.it)("version equal to threshold returns ok (not warning)", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
226
|
+
var res;
|
|
227
|
+
return __generator(this, function (_a) {
|
|
228
|
+
switch (_a.label) {
|
|
229
|
+
case 0: return [4 /*yield*/, versionConfig_1.VersionConfig.create({
|
|
230
|
+
webRequiredVersion: 50,
|
|
231
|
+
webWarningVersion: 100,
|
|
232
|
+
})];
|
|
233
|
+
case 1:
|
|
234
|
+
_a.sent();
|
|
235
|
+
return [4 /*yield*/, app.get("/version-check").query({ platform: "web", version: 100 })];
|
|
236
|
+
case 2:
|
|
237
|
+
res = _a.sent();
|
|
238
|
+
(0, bun_test_1.expect)(res.status).toBe(200);
|
|
239
|
+
(0, bun_test_1.expect)(res.body).toEqual({ status: "ok" });
|
|
240
|
+
return [2 /*return*/];
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
}); });
|
|
244
|
+
(0, bun_test_1.it)("version equal to required returns warning not required", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
245
|
+
var res;
|
|
246
|
+
return __generator(this, function (_a) {
|
|
247
|
+
switch (_a.label) {
|
|
248
|
+
case 0: return [4 /*yield*/, versionConfig_1.VersionConfig.create({
|
|
249
|
+
webRequiredVersion: 100,
|
|
250
|
+
webWarningVersion: 150,
|
|
251
|
+
})];
|
|
252
|
+
case 1:
|
|
253
|
+
_a.sent();
|
|
254
|
+
return [4 /*yield*/, app.get("/version-check").query({ platform: "web", version: 100 })];
|
|
255
|
+
case 2:
|
|
256
|
+
res = _a.sent();
|
|
257
|
+
(0, bun_test_1.expect)(res.status).toBe(200);
|
|
258
|
+
(0, bun_test_1.expect)(res.body.status).toBe("warning");
|
|
259
|
+
return [2 /*return*/];
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
}); });
|
|
263
|
+
});
|
package/dist/expressServer.js
CHANGED
|
@@ -105,7 +105,6 @@ exports.setupServer = setupServer;
|
|
|
105
105
|
exports.cronjob = cronjob;
|
|
106
106
|
exports.wrapScript = wrapScript;
|
|
107
107
|
var Sentry = __importStar(require("@sentry/bun"));
|
|
108
|
-
var openapi_1 = __importDefault(require("@wesleytodd/openapi"));
|
|
109
108
|
var cors_1 = __importDefault(require("cors"));
|
|
110
109
|
var cron_1 = __importDefault(require("cron"));
|
|
111
110
|
var express_1 = __importDefault(require("express"));
|
|
@@ -120,6 +119,7 @@ var logger_1 = require("./logger");
|
|
|
120
119
|
var notifiers_1 = require("./notifiers");
|
|
121
120
|
var openApiCompat_1 = require("./openApiCompat");
|
|
122
121
|
var openApiEtag_1 = require("./openApiEtag");
|
|
122
|
+
var index_1 = __importDefault(require("./vendor/wesleytodd-openapi/index"));
|
|
123
123
|
var SLOW_READ_MAX = 200;
|
|
124
124
|
var SLOW_WRITE_MAX = 500;
|
|
125
125
|
var IS_JEST = process.env.JEST_WORKER_ID !== undefined;
|
|
@@ -276,7 +276,7 @@ function initializeRoutes(UserModel, addRoutes, options) {
|
|
|
276
276
|
// Add ETag middleware for OpenAPI JSON endpoint before the openapi middleware
|
|
277
277
|
app.use(openApiCompat_1.openApiCompatMiddleware);
|
|
278
278
|
app.use(openApiEtag_1.openApiEtagMiddleware);
|
|
279
|
-
var oapi = (0,
|
|
279
|
+
var oapi = (0, index_1.default)({
|
|
280
280
|
info: {
|
|
281
281
|
description: "Generated docs from an Express api",
|
|
282
282
|
title: "Express Application",
|
package/dist/index.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export * from "./expressServer";
|
|
|
10
10
|
export * from "./githubAuth";
|
|
11
11
|
export * from "./logger";
|
|
12
12
|
export * from "./middleware";
|
|
13
|
+
export * from "./models/versionConfig";
|
|
13
14
|
export * from "./notifiers";
|
|
14
15
|
export * from "./openApiBuilder";
|
|
15
16
|
export * from "./openApiCompat";
|
|
@@ -24,3 +25,4 @@ export * from "./terrenoApp";
|
|
|
24
25
|
export * from "./terrenoPlugin";
|
|
25
26
|
export * from "./transformers";
|
|
26
27
|
export * from "./utils";
|
|
28
|
+
export * from "./versionCheckPlugin";
|
package/dist/index.js
CHANGED
|
@@ -26,6 +26,7 @@ __exportStar(require("./expressServer"), exports);
|
|
|
26
26
|
__exportStar(require("./githubAuth"), exports);
|
|
27
27
|
__exportStar(require("./logger"), exports);
|
|
28
28
|
__exportStar(require("./middleware"), exports);
|
|
29
|
+
__exportStar(require("./models/versionConfig"), exports);
|
|
29
30
|
__exportStar(require("./notifiers"), exports);
|
|
30
31
|
__exportStar(require("./openApiBuilder"), exports);
|
|
31
32
|
__exportStar(require("./openApiCompat"), exports);
|
|
@@ -40,3 +41,4 @@ __exportStar(require("./terrenoApp"), exports);
|
|
|
40
41
|
__exportStar(require("./terrenoPlugin"), exports);
|
|
41
42
|
__exportStar(require("./transformers"), exports);
|
|
42
43
|
__exportStar(require("./utils"), exports);
|
|
44
|
+
__exportStar(require("./versionCheckPlugin"), exports);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import mongoose, { type Document } from "mongoose";
|
|
2
|
+
import { type APIErrorConstructor } from "../errors";
|
|
3
|
+
export interface VersionConfigDocument extends mongoose.Document {
|
|
4
|
+
webWarningVersion: number;
|
|
5
|
+
webRequiredVersion: number;
|
|
6
|
+
mobileWarningVersion: number;
|
|
7
|
+
mobileRequiredVersion: number;
|
|
8
|
+
warningMessage: string;
|
|
9
|
+
requiredMessage: string;
|
|
10
|
+
updateUrl?: string;
|
|
11
|
+
created?: Date;
|
|
12
|
+
updated?: Date;
|
|
13
|
+
}
|
|
14
|
+
export interface VersionConfigModel extends mongoose.Model<VersionConfigDocument> {
|
|
15
|
+
findOneOrNone(query: Record<string, any>, errorArgs?: Partial<APIErrorConstructor>): Promise<(Document & VersionConfigDocument) | null>;
|
|
16
|
+
}
|
|
17
|
+
export declare const VersionConfig: VersionConfigModel;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.VersionConfig = void 0;
|
|
7
|
+
var mongoose_1 = __importDefault(require("mongoose"));
|
|
8
|
+
var plugins_1 = require("../plugins");
|
|
9
|
+
var versionConfigSchema = new mongoose_1.default.Schema({
|
|
10
|
+
mobileRequiredVersion: {
|
|
11
|
+
default: 0,
|
|
12
|
+
description: "Build number at which mobile users are blocked from using the app",
|
|
13
|
+
min: 0,
|
|
14
|
+
type: Number,
|
|
15
|
+
},
|
|
16
|
+
mobileWarningVersion: {
|
|
17
|
+
default: 0,
|
|
18
|
+
description: "Build number at which mobile users see a warning toast",
|
|
19
|
+
min: 0,
|
|
20
|
+
type: Number,
|
|
21
|
+
},
|
|
22
|
+
requiredMessage: {
|
|
23
|
+
default: "This version is no longer supported. Please update to continue.",
|
|
24
|
+
description: "Message shown on the blocking screen",
|
|
25
|
+
type: String,
|
|
26
|
+
},
|
|
27
|
+
updateUrl: {
|
|
28
|
+
description: "App store or download URL for mobile updates (optional, falls back to expo-updates)",
|
|
29
|
+
type: String,
|
|
30
|
+
},
|
|
31
|
+
warningMessage: {
|
|
32
|
+
default: "A new version is available. Please update for the best experience.",
|
|
33
|
+
description: "Message shown in the warning toast",
|
|
34
|
+
type: String,
|
|
35
|
+
},
|
|
36
|
+
webRequiredVersion: {
|
|
37
|
+
default: 0,
|
|
38
|
+
description: "Build number at which web users are blocked from using the app",
|
|
39
|
+
min: 0,
|
|
40
|
+
type: Number,
|
|
41
|
+
},
|
|
42
|
+
webWarningVersion: {
|
|
43
|
+
default: 0,
|
|
44
|
+
description: "Build number at which web users see a warning toast",
|
|
45
|
+
min: 0,
|
|
46
|
+
type: Number,
|
|
47
|
+
},
|
|
48
|
+
}, { strict: "throw", toJSON: { virtuals: true }, toObject: { virtuals: true } });
|
|
49
|
+
// Enforce singleton: only one VersionConfig document can exist.
|
|
50
|
+
// The _singleton field is always "config" (required, immutable, enum-constrained)
|
|
51
|
+
// and a unique index guarantees at most one document.
|
|
52
|
+
versionConfigSchema.add({
|
|
53
|
+
_singleton: {
|
|
54
|
+
default: "config",
|
|
55
|
+
description: "Sentinel field to enforce singleton via unique index",
|
|
56
|
+
enum: ["config"],
|
|
57
|
+
immutable: true,
|
|
58
|
+
required: true,
|
|
59
|
+
select: false,
|
|
60
|
+
type: String,
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
versionConfigSchema.index({ _singleton: 1 }, { unique: true });
|
|
64
|
+
versionConfigSchema.plugin(plugins_1.createdUpdatedPlugin);
|
|
65
|
+
versionConfigSchema.plugin(plugins_1.findOneOrNone);
|
|
66
|
+
exports.VersionConfig = mongoose_1.default.model("VersionConfig", versionConfigSchema);
|
package/dist/terrenoApp.js
CHANGED
|
@@ -60,7 +60,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
60
60
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
61
61
|
exports.TerrenoApp = void 0;
|
|
62
62
|
var Sentry = __importStar(require("@sentry/bun"));
|
|
63
|
-
var openapi_1 = __importDefault(require("@wesleytodd/openapi"));
|
|
64
63
|
var cors_1 = __importDefault(require("cors"));
|
|
65
64
|
var express_1 = __importDefault(require("express"));
|
|
66
65
|
var qs_1 = __importDefault(require("qs"));
|
|
@@ -72,6 +71,7 @@ var githubAuth_1 = require("./githubAuth");
|
|
|
72
71
|
var logger_1 = require("./logger");
|
|
73
72
|
var openApiCompat_1 = require("./openApiCompat");
|
|
74
73
|
var openApiEtag_1 = require("./openApiEtag");
|
|
74
|
+
var index_1 = __importDefault(require("./vendor/wesleytodd-openapi/index"));
|
|
75
75
|
/**
|
|
76
76
|
* Fluent API for building Express applications with Terreno framework.
|
|
77
77
|
*
|
|
@@ -300,7 +300,7 @@ var TerrenoApp = /** @class */ (function () {
|
|
|
300
300
|
// OpenAPI
|
|
301
301
|
app.use(openApiCompat_1.openApiCompatMiddleware);
|
|
302
302
|
app.use(openApiEtag_1.openApiEtagMiddleware);
|
|
303
|
-
var oapi = (0,
|
|
303
|
+
var oapi = (0, index_1.default)({
|
|
304
304
|
info: {
|
|
305
305
|
description: "Generated docs from an Express api",
|
|
306
306
|
title: "Express Application",
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
declare function _exports(_routePrefix: any, _doc: any, _opts: any): {
|
|
2
|
+
(req: any, res: any, next: any): void;
|
|
3
|
+
routePrefix: any;
|
|
4
|
+
document: any;
|
|
5
|
+
generateDocument: (baseDocument: any, router: any, basePath: any) => any;
|
|
6
|
+
options: any;
|
|
7
|
+
path(schema?: {}): (req: any, res: any, next: any) => void;
|
|
8
|
+
validPath(schema?: {}, pathOpts?: {}): (req: any, res: any, next: any) => any;
|
|
9
|
+
component(type: any, name: any, description: any): any;
|
|
10
|
+
schema: (name?: any, description?: any) => any;
|
|
11
|
+
response: (name?: any, description?: any) => any;
|
|
12
|
+
parameters: (name?: any, description?: any) => any;
|
|
13
|
+
examples: (name?: any, description?: any) => any;
|
|
14
|
+
requestBodies: (name?: any, description?: any) => any;
|
|
15
|
+
headers: (name?: any, description?: any) => any;
|
|
16
|
+
securitySchemes: (name?: any, description?: any) => any;
|
|
17
|
+
links: (name?: any, description?: any) => any;
|
|
18
|
+
callbacks: (name?: any, description?: any) => any;
|
|
19
|
+
swaggerui(options: any): any[];
|
|
20
|
+
};
|
|
21
|
+
declare namespace _exports {
|
|
22
|
+
export { minimumViableDocument };
|
|
23
|
+
export { defaultRoutePrefix };
|
|
24
|
+
}
|
|
25
|
+
export = _exports;
|
|
26
|
+
import minimumViableDocument = require("./lib/minimum-doc");
|
|
27
|
+
declare const defaultRoutePrefix: "/openapi";
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
// Vendored from https://github.com/wesleytodd/express-openapi (branch: express-5)
|
|
2
|
+
// Package: @wesleytodd/openapi v1.1.0
|
|
3
|
+
// License: ISC (see LICENSE)
|
|
4
|
+
// Vendored to allow local modifications and avoid external dependency drift.
|
|
5
|
+
'use strict';
|
|
6
|
+
var __assign = (this && this.__assign) || function () {
|
|
7
|
+
__assign = Object.assign || function(t) {
|
|
8
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
9
|
+
s = arguments[i];
|
|
10
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
11
|
+
t[p] = s[p];
|
|
12
|
+
}
|
|
13
|
+
return t;
|
|
14
|
+
};
|
|
15
|
+
return __assign.apply(this, arguments);
|
|
16
|
+
};
|
|
17
|
+
var httpErrors = require('http-errors');
|
|
18
|
+
var Router = require('router');
|
|
19
|
+
var SwaggerParser = require('swagger-parser');
|
|
20
|
+
var ui = require('./lib/ui');
|
|
21
|
+
var makeValidator = require('./lib/validate');
|
|
22
|
+
var _a = require('./lib/layer-schema'), getSchema = _a.get, setSchema = _a.set;
|
|
23
|
+
var minimumViableDocument = require('./lib/minimum-doc');
|
|
24
|
+
var generateDocument = require('./lib/generate-doc');
|
|
25
|
+
var defaultRoutePrefix = '/openapi';
|
|
26
|
+
var YAML = require('yaml');
|
|
27
|
+
module.exports = function ExpressOpenApi(_routePrefix, _doc, _opts) {
|
|
28
|
+
// Acceptable arguments:
|
|
29
|
+
// oapi()
|
|
30
|
+
// oapi('/path')
|
|
31
|
+
// oapi('/path', doc)
|
|
32
|
+
// oapi('/path', doc, opts)
|
|
33
|
+
// oapi(doc)
|
|
34
|
+
// oapi(doc, opts)
|
|
35
|
+
//
|
|
36
|
+
// The below logic is correct, but very hard to reason about
|
|
37
|
+
var routePrefix = _routePrefix || defaultRoutePrefix;
|
|
38
|
+
var doc = _doc || minimumViableDocument;
|
|
39
|
+
var opts = _opts || {};
|
|
40
|
+
if (typeof _routePrefix !== 'string') {
|
|
41
|
+
routePrefix = defaultRoutePrefix;
|
|
42
|
+
doc = _routePrefix || minimumViableDocument;
|
|
43
|
+
opts = _doc || {};
|
|
44
|
+
}
|
|
45
|
+
// We need to route a bit, seems a safe addition
|
|
46
|
+
// to use the express router in an express middleware
|
|
47
|
+
var router = new Router();
|
|
48
|
+
// Fully generate the doc on the first request
|
|
49
|
+
var isFirstRequest = true;
|
|
50
|
+
// Where the magic happens
|
|
51
|
+
var middleware = function OpenApiMiddleware(req, res, next) {
|
|
52
|
+
if (isFirstRequest) {
|
|
53
|
+
middleware.document = generateDocument(middleware.document, req.app._router || req.app.router, opts.basePath);
|
|
54
|
+
isFirstRequest = false;
|
|
55
|
+
}
|
|
56
|
+
router.handle(req, res, next);
|
|
57
|
+
};
|
|
58
|
+
// Expose the current document and prefix
|
|
59
|
+
middleware.routePrefix = routePrefix;
|
|
60
|
+
middleware.document = generateDocument(doc, undefined, opts.basePath);
|
|
61
|
+
middleware.generateDocument = generateDocument;
|
|
62
|
+
middleware.options = opts;
|
|
63
|
+
// Add a path schema to the document
|
|
64
|
+
middleware.path = function (schema) {
|
|
65
|
+
if (schema === void 0) { schema = {}; }
|
|
66
|
+
function schemaMiddleware(req, res, next) {
|
|
67
|
+
next();
|
|
68
|
+
}
|
|
69
|
+
setSchema(schemaMiddleware, schema);
|
|
70
|
+
return schemaMiddleware;
|
|
71
|
+
};
|
|
72
|
+
// Validate path middleware
|
|
73
|
+
middleware.validPath = function (schema, pathOpts) {
|
|
74
|
+
if (schema === void 0) { schema = {}; }
|
|
75
|
+
if (pathOpts === void 0) { pathOpts = {}; }
|
|
76
|
+
var validate;
|
|
77
|
+
function validSchemaMiddleware(req, res, next) {
|
|
78
|
+
if (!validate) {
|
|
79
|
+
validate = makeValidator(middleware, getSchema(validSchemaMiddleware), __assign(__assign({}, pathOpts), opts));
|
|
80
|
+
}
|
|
81
|
+
return validate(req, res, next);
|
|
82
|
+
}
|
|
83
|
+
setSchema(validSchemaMiddleware, schema);
|
|
84
|
+
return validSchemaMiddleware;
|
|
85
|
+
};
|
|
86
|
+
// Component definitions
|
|
87
|
+
middleware.component = function (type, name, description) {
|
|
88
|
+
if (!type) {
|
|
89
|
+
throw new TypeError('Component type is required');
|
|
90
|
+
}
|
|
91
|
+
// Return whole component type
|
|
92
|
+
if (!name && !description) {
|
|
93
|
+
return middleware.document.components && middleware.document.components[type];
|
|
94
|
+
}
|
|
95
|
+
// Return ref to type
|
|
96
|
+
if (name && !description) {
|
|
97
|
+
if (!middleware.document.components || !middleware.document.components[type] || !middleware.document.components[type][name]) {
|
|
98
|
+
throw new Error("Unknown ".concat(type, " ref: ").concat(name));
|
|
99
|
+
}
|
|
100
|
+
return { $ref: "#/components/".concat(type, "/").concat(name) };
|
|
101
|
+
}
|
|
102
|
+
// Set name on parameter if not passed
|
|
103
|
+
if (type === 'parameters') {
|
|
104
|
+
description.name = description.name || name;
|
|
105
|
+
}
|
|
106
|
+
// Define a new component
|
|
107
|
+
middleware.document.components = middleware.document.components || {};
|
|
108
|
+
middleware.document.components[type] = middleware.document.components[type] || {};
|
|
109
|
+
middleware.document.components[type][name] = description;
|
|
110
|
+
return middleware;
|
|
111
|
+
};
|
|
112
|
+
middleware.schema = middleware.component.bind(null, 'schemas');
|
|
113
|
+
middleware.response = middleware.component.bind(null, 'responses');
|
|
114
|
+
middleware.parameters = middleware.component.bind(null, 'parameters');
|
|
115
|
+
middleware.examples = middleware.component.bind(null, 'examples');
|
|
116
|
+
middleware.requestBodies = middleware.component.bind(null, 'requestBodies');
|
|
117
|
+
middleware.headers = middleware.component.bind(null, 'headers');
|
|
118
|
+
middleware.securitySchemes = middleware.component.bind(null, 'securitySchemes');
|
|
119
|
+
middleware.links = middleware.component.bind(null, 'links');
|
|
120
|
+
middleware.callbacks = middleware.component.bind(null, 'callbacks');
|
|
121
|
+
// Expose ui middleware
|
|
122
|
+
middleware.swaggerui = function (options) { return ui.serveSwaggerUI("".concat(routePrefix, ".json"), options); };
|
|
123
|
+
// OpenAPI document as json
|
|
124
|
+
router.get("".concat(routePrefix, ".json"), function (req, res) {
|
|
125
|
+
middleware.document = generateDocument(middleware.document, req.app._router || req.app.router, opts.basePath);
|
|
126
|
+
res.json(middleware.document);
|
|
127
|
+
});
|
|
128
|
+
// OpenAPI document as yaml
|
|
129
|
+
router.get(["".concat(routePrefix, ".yaml"), "".concat(routePrefix, ".yml")], function (req, res) {
|
|
130
|
+
var jsonSpec = generateDocument(middleware.document, req.app._router || req.app.router, opts.basePath);
|
|
131
|
+
var yamlSpec = YAML.stringify(jsonSpec);
|
|
132
|
+
res.type('yaml');
|
|
133
|
+
res.send(yamlSpec);
|
|
134
|
+
});
|
|
135
|
+
router.get("".concat(routePrefix, "/components/:type/:name.json"), function (req, res, next) {
|
|
136
|
+
var _a = req.params, type = _a.type, name = _a.name;
|
|
137
|
+
middleware.document = generateDocument(middleware.document, req.app._router || req.app.router, opts.basePath);
|
|
138
|
+
// No component by that identifer
|
|
139
|
+
if (!middleware.document.components[type] || !middleware.document.components[type][name]) {
|
|
140
|
+
return next(httpErrors(404, "Component does not exist: ".concat(type, "/").concat(name)));
|
|
141
|
+
}
|
|
142
|
+
// Return component
|
|
143
|
+
res.json(middleware.document.components[type][name]);
|
|
144
|
+
});
|
|
145
|
+
// Validate full open api document
|
|
146
|
+
router.get("".concat(routePrefix, "/validate"), function (req, res) {
|
|
147
|
+
middleware.document = generateDocument(middleware.document, req.app._router || req.app.router, opts.basePath);
|
|
148
|
+
SwaggerParser.validate(middleware.document, function (err, api) {
|
|
149
|
+
if (err) {
|
|
150
|
+
return res.json({
|
|
151
|
+
valid: false,
|
|
152
|
+
details: err.details,
|
|
153
|
+
document: middleware.document
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
res.json({
|
|
157
|
+
valid: true,
|
|
158
|
+
document: middleware.document
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
// Serve up the for exploring the document
|
|
163
|
+
if (opts.htmlui) {
|
|
164
|
+
var ui_1 = opts.htmlui;
|
|
165
|
+
if (!Array.isArray(opts.htmlui)) {
|
|
166
|
+
ui_1 = [opts.htmlui];
|
|
167
|
+
}
|
|
168
|
+
if (ui_1.includes('swagger-ui')) {
|
|
169
|
+
router.get("".concat(routePrefix), function (req, res) { res.redirect("".concat(routePrefix, "/swagger-ui")); });
|
|
170
|
+
router.use("".concat(routePrefix, "/swagger-ui"), middleware.swaggerui);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return middleware;
|
|
174
|
+
};
|
|
175
|
+
module.exports.minimumViableDocument = minimumViableDocument;
|
|
176
|
+
module.exports.defaultRoutePrefix = defaultRoutePrefix;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Vendored from https://github.com/wesleytodd/express-openapi (branch: express-5)
|
|
3
|
+
// License: ISC (see ../LICENSE)
|
|
4
|
+
var YAML = require('yaml');
|
|
5
|
+
/**
|
|
6
|
+
* Converts a json to yaml
|
|
7
|
+
* @param {object} jsonObject
|
|
8
|
+
* @returns {string} yamlString
|
|
9
|
+
*/
|
|
10
|
+
module.exports = function (jsonObject) {
|
|
11
|
+
var doc = YAML.stringify(jsonObject);
|
|
12
|
+
return doc;
|
|
13
|
+
};
|