@terreno/api 0.6.0 → 0.7.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.
Files changed (41) hide show
  1. package/README.md +1 -5
  2. package/dist/__tests__/versionCheck.test.d.ts +1 -0
  3. package/dist/__tests__/versionCheck.test.js +263 -0
  4. package/dist/expressServer.js +2 -2
  5. package/dist/index.d.ts +2 -0
  6. package/dist/index.js +2 -0
  7. package/dist/models/versionConfig.d.ts +17 -0
  8. package/dist/models/versionConfig.js +66 -0
  9. package/dist/terrenoApp.js +2 -2
  10. package/dist/vendor/wesleytodd-openapi/index.d.ts +27 -0
  11. package/dist/vendor/wesleytodd-openapi/index.js +176 -0
  12. package/dist/vendor/wesleytodd-openapi/lib/convert-yaml.d.ts +2 -0
  13. package/dist/vendor/wesleytodd-openapi/lib/convert-yaml.js +13 -0
  14. package/dist/vendor/wesleytodd-openapi/lib/generate-doc.d.ts +2 -0
  15. package/dist/vendor/wesleytodd-openapi/lib/generate-doc.js +148 -0
  16. package/dist/vendor/wesleytodd-openapi/lib/layer-schema.d.ts +2 -0
  17. package/dist/vendor/wesleytodd-openapi/lib/layer-schema.js +12 -0
  18. package/dist/vendor/wesleytodd-openapi/lib/minimum-doc.d.ts +6 -0
  19. package/dist/vendor/wesleytodd-openapi/lib/minimum-doc.js +11 -0
  20. package/dist/vendor/wesleytodd-openapi/lib/ui.d.ts +1 -0
  21. package/dist/vendor/wesleytodd-openapi/lib/ui.js +37 -0
  22. package/dist/vendor/wesleytodd-openapi/lib/validate.d.ts +2 -0
  23. package/dist/vendor/wesleytodd-openapi/lib/validate.js +168 -0
  24. package/dist/versionCheckPlugin.d.ts +15 -0
  25. package/dist/versionCheckPlugin.js +106 -0
  26. package/package.json +10 -3
  27. package/src/__tests__/versionCheck.test.ts +132 -0
  28. package/src/expressServer.ts +1 -2
  29. package/src/index.ts +2 -0
  30. package/src/models/versionConfig.ts +92 -0
  31. package/src/terrenoApp.ts +1 -2
  32. package/src/vendor/wesleytodd-openapi/LICENSE +15 -0
  33. package/src/vendor/wesleytodd-openapi/index.js +189 -0
  34. package/src/vendor/wesleytodd-openapi/lib/convert-yaml.js +13 -0
  35. package/src/vendor/wesleytodd-openapi/lib/generate-doc.js +153 -0
  36. package/src/vendor/wesleytodd-openapi/lib/layer-schema.js +13 -0
  37. package/src/vendor/wesleytodd-openapi/lib/minimum-doc.js +12 -0
  38. package/src/vendor/wesleytodd-openapi/lib/ui.js +71 -0
  39. package/src/vendor/wesleytodd-openapi/lib/validate.js +152 -0
  40. package/src/versionCheckPlugin.ts +81 -0
  41. package/tsconfig.json +1 -1
@@ -0,0 +1,148 @@
1
+ // Vendored from https://github.com/wesleytodd/express-openapi (branch: main / tag: v1.1.0)
2
+ // NOTE: This file uses the main-branch algorithm (regexp-based route traversal) rather than
3
+ // the express-5 branch version, because the express-5 version requires router.getRoutes()
4
+ // which only exists on the bjohansebas/router fork and not on the Express 5 app router.
5
+ // The main-branch approach works correctly with the openApiCompat.ts regexp shim.
6
+ // License: ISC (see ../LICENSE)
7
+ 'use strict';
8
+ var __assign = (this && this.__assign) || function () {
9
+ __assign = Object.assign || function(t) {
10
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
11
+ s = arguments[i];
12
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
13
+ t[p] = s[p];
14
+ }
15
+ return t;
16
+ };
17
+ return __assign.apply(this, arguments);
18
+ };
19
+ var pathToRegexp = require('path-to-regexp');
20
+ var minimumViableDocument = require('./minimum-doc');
21
+ var _a = require('./layer-schema'), getSchema = _a.get, setSchema = _a.set;
22
+ module.exports = function generateDocument(baseDocument, router, basePath) {
23
+ // Merge document with select minimum defaults
24
+ var doc = Object.assign({
25
+ openapi: minimumViableDocument.openapi
26
+ }, baseDocument, {
27
+ info: Object.assign({}, minimumViableDocument.info, baseDocument.info),
28
+ paths: Object.assign({}, minimumViableDocument.paths, baseDocument.paths)
29
+ });
30
+ // Iterate the middleware stack and add any paths and schemas, etc
31
+ router && router.stack.forEach(function (_layer) {
32
+ iterateStack('', null, _layer, function (path, routeLayer, layer) {
33
+ if (basePath && path.startsWith(basePath)) {
34
+ path = path.replace(basePath, '');
35
+ }
36
+ var schema = getSchema(layer.handle);
37
+ if (!schema || !layer.method) {
38
+ return;
39
+ }
40
+ var operation = Object.assign({}, schema);
41
+ // Add route params to schema
42
+ if (routeLayer && routeLayer.keys && routeLayer.keys.length) {
43
+ var keys_1 = {};
44
+ var params_1 = routeLayer.keys.map(function (k, i) {
45
+ var prev = i > 0 && routeLayer.keys[i - 1];
46
+ // do not count parameters without a name if they are next to a named parameter
47
+ if (typeof k.name === 'number' && prev && prev.offset + prev.name.length + 1 >= k.offset) {
48
+ return null;
49
+ }
50
+ var param;
51
+ if (schema.parameters) {
52
+ param = schema.parameters.find(function (p) { return p.name === k.name && p.in === 'path'; });
53
+ }
54
+ // Reformat the path
55
+ keys_1[k.name] = '{' + k.name + '}';
56
+ return Object.assign({
57
+ name: k.name,
58
+ in: 'path',
59
+ required: !k.optional,
60
+ schema: k.schema || { type: 'string' }
61
+ }, param || {});
62
+ })
63
+ .filter(function (e) { return e; });
64
+ if (schema.parameters) {
65
+ schema.parameters.forEach(function (p) {
66
+ if (!params_1.find(function (pp) { return p.name === pp.name; })) {
67
+ params_1.push(p);
68
+ }
69
+ });
70
+ }
71
+ operation.parameters = params_1;
72
+ path = pathToRegexp.compile(path.replace(/\*|\(\*\)/g, '(.*)'))(keys_1, { encode: function (value) { return value; } });
73
+ }
74
+ doc.paths[path] = doc.paths[path] || {};
75
+ doc.paths[path][layer.method] = operation;
76
+ setSchema(layer.handle, operation);
77
+ });
78
+ });
79
+ return doc;
80
+ };
81
+ function iterateStack(path, routeLayer, layer, cb) {
82
+ cb(path, routeLayer, layer);
83
+ if (layer.name === 'router') {
84
+ layer.handle.stack.forEach(function (l) {
85
+ path = path || '';
86
+ iterateStack(path + split(layer.regexp, layer.keys).join('/'), layer, l, cb);
87
+ });
88
+ }
89
+ if (!layer.route) {
90
+ return;
91
+ }
92
+ if (Array.isArray(layer.route.path)) {
93
+ var r_1 = layer.regexp.toString();
94
+ layer.route.path.forEach(function (p, i) { return iterateStack(path + p, layer, __assign(__assign({}, layer), {
95
+ // Checking if p is a string here since p may be a regex expression
96
+ keys: layer.keys.filter(function (k) { return typeof p === 'string' ? p.includes("/:".concat(k.name)) : false; }),
97
+ // There may be an issue here if the regex has a '|', but that seems to only be the case with user defined regex
98
+ regexp: new RegExp("(".concat(r_1.substring(2, r_1.length - 3).split('|')[i], ")")), route: __assign(__assign({}, layer.route), { path: '' }) }), cb); });
99
+ return;
100
+ }
101
+ layer.route.stack.forEach(function (l) { return iterateStack(path + layer.route.path, layer, l, cb); });
102
+ }
103
+ function processComplexMatch(thing, keys) {
104
+ var i = 0;
105
+ return thing
106
+ .toString()
107
+ // The replace below replaces the regex used by Express to match dynamic parameters
108
+ // (i.e. /:id, /:name, etc...) with the name(s) of those parameter(s)
109
+ // This could have been accomplished with replaceAll for Node version 15 and above
110
+ // no-useless-escape is disabled since we need three backslashes
111
+ .replace(/\(\?\:\(\[\^\\\/\]\+\?\)\)/g, function () { return "{".concat(keys[i++].name, "}"); }) // eslint-disable-line no-useless-escape
112
+ .replace(/\\(.)/g, '$1')
113
+ // The replace below removes the regex used at the start of the string and
114
+ // the regex used to match the query parameters
115
+ .replace(/\/\^|\/\?(.*)/g, '')
116
+ .split('/');
117
+ }
118
+ // https://github.com/expressjs/express/issues/3308#issuecomment-300957572
119
+ function split(thing, keys) {
120
+ // In express v5 the router layers regexp (path-to-regexp@3.2.0)
121
+ // has some additional handling for end of lines, remove those
122
+ //
123
+ // layer.regexp
124
+ // v4 ^\\/sub-route\\/?(?=\\/|$)
125
+ // v5 ^\\/sub-route(?:\\/(?=$))?(?=\\/|$)
126
+ //
127
+ // l.regexp
128
+ // v4 ^\\/endpoint\\/?$
129
+ // v5 ^\\/endpoint(?:\\/)?$
130
+ if (typeof thing === 'string') {
131
+ return thing.split('/');
132
+ }
133
+ else if (thing.fast_slash) {
134
+ return [];
135
+ }
136
+ else {
137
+ var match = thing
138
+ .toString()
139
+ .replace('\\/?', '')
140
+ .replace('(?=\\/|$)', '$')
141
+ // Added this line to catch the express v5 case after the v4 part is stripped off
142
+ .replace('(?:\\/(?=$))?$', '$')
143
+ .match(/^\/\^((?:\\[.*+?^${}()|[\]\\/]|[^.*+?^${}()|[\]\\/])*)\$\//);
144
+ return match
145
+ ? match[1].replace(/\\(.)/g, '$1').split('/')
146
+ : processComplexMatch(thing, keys);
147
+ }
148
+ }
@@ -0,0 +1,2 @@
1
+ export function set(handler: any, schema: any): void;
2
+ export function get(handler: any): any;
@@ -0,0 +1,12 @@
1
+ // Vendored from https://github.com/wesleytodd/express-openapi (branch: express-5)
2
+ // License: ISC (see ../LICENSE)
3
+ 'use strict';
4
+ var schemas = new Map();
5
+ module.exports = {
6
+ set: function (handler, schema) {
7
+ schemas.set(handler, schema);
8
+ },
9
+ get: function (handler) {
10
+ return schemas.get(handler);
11
+ }
12
+ };
@@ -0,0 +1,6 @@
1
+ export let openapi: string;
2
+ export namespace info {
3
+ let title: string;
4
+ let version: string;
5
+ }
6
+ export let paths: {};
@@ -0,0 +1,11 @@
1
+ // Vendored from https://github.com/wesleytodd/express-openapi (branch: express-5)
2
+ // License: ISC (see ../LICENSE)
3
+ 'use strict';
4
+ module.exports = {
5
+ openapi: '3.0.0',
6
+ info: {
7
+ title: 'Express App',
8
+ version: '1.0.0'
9
+ },
10
+ paths: {}
11
+ };
@@ -0,0 +1 @@
1
+ export function serveSwaggerUI(documentUrl: any, opts?: {}): any[];
@@ -0,0 +1,37 @@
1
+ // Vendored from https://github.com/wesleytodd/express-openapi (branch: express-5)
2
+ // License: ISC (see ../LICENSE)
3
+ 'use strict';
4
+ var __rest = (this && this.__rest) || function (s, e) {
5
+ var t = {};
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
7
+ t[p] = s[p];
8
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
9
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
10
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
11
+ t[p[i]] = s[p[i]];
12
+ }
13
+ return t;
14
+ };
15
+ var path = require('path');
16
+ var serve = require('serve-static');
17
+ module.exports.serveSwaggerUI = function serveSwaggerUI(documentUrl, opts) {
18
+ if (opts === void 0) { opts = {}; }
19
+ var plugins = opts.plugins, options = __rest(opts, ["plugins"]);
20
+ return [serve(path.resolve(require.resolve('swagger-ui-dist'), '..'), { index: false }),
21
+ function returnUiInit(req, res, next) {
22
+ if (req.path.endsWith('/swagger-ui-init.js')) {
23
+ res.type('.js');
24
+ res.send("window.onload = function () {\n window.ui = SwaggerUIBundle({\n url: '".concat(documentUrl, "',\n dom_id: '#swagger-ui',\n ").concat((plugins === null || plugins === void 0 ? void 0 : plugins.length) ? "plugins: [".concat(plugins, "],") : '', "\n ...").concat(JSON.stringify(options), "\n })\n}"));
25
+ }
26
+ else {
27
+ next();
28
+ }
29
+ },
30
+ function renderSwaggerHtml(req, res) {
31
+ res.type('html').send(renderHtmlPage('Swagger UI', "\n <link rel=\"stylesheet\" type=\"text/css\" href=\"./swagger-ui.css\" >\n ", "\n <div id=\"swagger-ui\"></div>\n <script src=\"./swagger-ui-bundle.js\"></script>\n <script src=\"./swagger-ui-standalone-preset.js\"></script>\n <script src=\"./swagger-ui-init.js\"></script>\n "));
32
+ }
33
+ ];
34
+ };
35
+ function renderHtmlPage(title, head, body) {
36
+ return "<!DOCTYPE html>\n<html>\n <head>\n <title>".concat(title, "</title>\n <meta charset=\"utf-8\"/>\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <style>\n html {\n box-sizing: border-box;\n overflow: -moz-scrollbars-vertical;\n overflow-y: scroll;\n }\n *,\n *:before,\n *:after {\n box-sizing: inherit;\n }\n body {\n margin: 0;\n padding: 0;\n background: #fafafa;\n }\n </style>\n ").concat(head, "\n </head>\n <body>\n ").concat(body, "\n </body>\n</html>\n ");
37
+ }
@@ -0,0 +1,2 @@
1
+ declare function _exports(middleware: any, schema: any, opts: any): (req: any, res: any, next: any) => any;
2
+ export = _exports;
@@ -0,0 +1,168 @@
1
+ // Vendored from https://github.com/wesleytodd/express-openapi (branch: express-5)
2
+ // License: ISC (see ../LICENSE)
3
+ 'use strict';
4
+ var __assign = (this && this.__assign) || function () {
5
+ __assign = Object.assign || function(t) {
6
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
7
+ s = arguments[i];
8
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
9
+ t[p] = s[p];
10
+ }
11
+ return t;
12
+ };
13
+ return __assign.apply(this, arguments);
14
+ };
15
+ var __read = (this && this.__read) || function (o, n) {
16
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
17
+ if (!m) return o;
18
+ var i = m.call(o), r, ar = [], e;
19
+ try {
20
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
21
+ }
22
+ catch (error) { e = { error: error }; }
23
+ finally {
24
+ try {
25
+ if (r && !r.done && (m = i["return"])) m.call(i);
26
+ }
27
+ finally { if (e) throw e.error; }
28
+ }
29
+ return ar;
30
+ };
31
+ var Ajv = require('ajv');
32
+ var addFormats = require('ajv-formats');
33
+ var addKeywords = require('ajv-keywords');
34
+ var httpErrors = require('http-errors');
35
+ var BASE_REQ_SCHEMA = {
36
+ type: 'object',
37
+ required: ['headers', 'params', 'query'],
38
+ properties: {
39
+ headers: {
40
+ type: 'object',
41
+ required: [],
42
+ properties: {}
43
+ },
44
+ params: {
45
+ type: 'object',
46
+ required: [],
47
+ properties: {}
48
+ },
49
+ query: {
50
+ type: 'object',
51
+ required: [],
52
+ properties: {}
53
+ },
54
+ body: {
55
+ type: 'object',
56
+ required: [],
57
+ properties: {}
58
+ }
59
+ }
60
+ };
61
+ module.exports = function makeValidatorMiddleware(middleware, schema, opts) {
62
+ var ajv;
63
+ var validate;
64
+ function makeValidator() {
65
+ var reqSchema = structuredClone(BASE_REQ_SCHEMA);
66
+ // Compile req schema on first request
67
+ // Build param validation
68
+ schema.parameters && schema.parameters.forEach(function (p) {
69
+ switch (p.in) {
70
+ case 'path':
71
+ reqSchema.properties.params.properties[p.name] = p.schema;
72
+ p.required && !reqSchema.properties.params.required.includes(p.name) && reqSchema.properties.params.required.push(p.name);
73
+ break;
74
+ case 'query':
75
+ reqSchema.properties.query.properties[p.name] = p.schema;
76
+ p.required && !reqSchema.properties.query.required.includes(p.name) && reqSchema.properties.query.required.push(p.name);
77
+ break;
78
+ case 'header': {
79
+ var name_1 = p.name.toLowerCase();
80
+ reqSchema.properties.headers.properties[name_1] = p.schema;
81
+ p.required && !reqSchema.properties.headers.required.includes(p.name) && reqSchema.properties.headers.required.push(name_1);
82
+ break;
83
+ }
84
+ }
85
+ });
86
+ // Compile req body schema
87
+ schema.requestBody && Object.entries(schema.requestBody.content)
88
+ .forEach(function (_a) {
89
+ var _b = __read(_a, 2), contentType = _b[0], schema = _b[1].schema;
90
+ switch (contentType) {
91
+ case 'application/json':
92
+ reqSchema.properties.body = schema;
93
+ break;
94
+ default:
95
+ throw new TypeError("Validation of content type not supported: ".concat(contentType));
96
+ }
97
+ });
98
+ // Add components for references
99
+ reqSchema.components = middleware.document && middleware.document.components;
100
+ return ajv.compile(reqSchema);
101
+ }
102
+ return function validateMiddleware(req, res, next) {
103
+ // Restrict validation to only "route" layers
104
+ // This prevents running any validation
105
+ // if we are in a .use call which could
106
+ // be a non-routable request thus
107
+ if (!req.route) {
108
+ return next();
109
+ }
110
+ // Create ajv instance on first request
111
+ if (!ajv) {
112
+ ajv = new Ajv({
113
+ coerceTypes: opts.coerce === 'false' ? opts.coerce : true,
114
+ strict: opts.strict === true ? opts.strict : false
115
+ });
116
+ addFormats(ajv);
117
+ if (middleware.router && !middleware.router.handle) {
118
+ return next();
119
+ }
120
+ if (opts.keywords) {
121
+ addKeywords(ajv, opts.keywords);
122
+ }
123
+ }
124
+ if (!validate) {
125
+ validate = makeValidator();
126
+ }
127
+ // Validate request
128
+ var r = req;
129
+ if (opts.coerce !== true) {
130
+ r = makeReqCopy(req);
131
+ }
132
+ else {
133
+ // Redifine query and params as normal objects we can write to, so we can coerce the data
134
+ Object.defineProperty(req, 'query', {
135
+ value: __assign({}, req.query),
136
+ writable: true,
137
+ enumerable: true,
138
+ configurable: true
139
+ });
140
+ Object.defineProperty(req, 'params', {
141
+ value: __assign({}, req.params),
142
+ writable: true,
143
+ enumerable: true,
144
+ configurable: true
145
+ });
146
+ }
147
+ var validationStatus = validate(r);
148
+ if (validationStatus === true) {
149
+ return next();
150
+ }
151
+ // build error?
152
+ var err = new Error('Request validation failed');
153
+ err.validationErrors = validate.errors;
154
+ err.validationSchema = validate.schema;
155
+ next(httpErrors(400, err));
156
+ };
157
+ };
158
+ // This is because ajv modifies the original data,
159
+ // preventing this requires that we dont pass the
160
+ // actual req. An issue has been opened (@TODO open the issue)
161
+ function makeReqCopy(req) {
162
+ return JSON.parse(JSON.stringify({
163
+ headers: req.headers,
164
+ params: req.params,
165
+ query: req.query,
166
+ body: req.body
167
+ }));
168
+ }
@@ -0,0 +1,15 @@
1
+ import type express from "express";
2
+ import type { TerrenoPlugin } from "./terrenoPlugin";
3
+ export type VersionCheckStatus = "ok" | "warning" | "required";
4
+ export interface VersionCheckResponse {
5
+ message?: string;
6
+ status: VersionCheckStatus;
7
+ updateUrl?: string;
8
+ }
9
+ /**
10
+ * TerrenoPlugin that adds a public GET /version-check endpoint for upgrade enforcement.
11
+ * Compares client build number against admin-configured thresholds per platform.
12
+ */
13
+ export declare class VersionCheckPlugin implements TerrenoPlugin {
14
+ register(app: express.Application): void;
15
+ }
@@ -0,0 +1,106 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.VersionCheckPlugin = void 0;
40
+ var api_1 = require("./api");
41
+ var versionConfig_1 = require("./models/versionConfig");
42
+ var DEFAULT_WARNING_MESSAGE = "A new version is available. Please update for the best experience.";
43
+ var DEFAULT_REQUIRED_MESSAGE = "This version is no longer supported. Please update to continue.";
44
+ /**
45
+ * TerrenoPlugin that adds a public GET /version-check endpoint for upgrade enforcement.
46
+ * Compares client build number against admin-configured thresholds per platform.
47
+ */
48
+ var VersionCheckPlugin = /** @class */ (function () {
49
+ function VersionCheckPlugin() {
50
+ }
51
+ VersionCheckPlugin.prototype.register = function (app) {
52
+ var _this = this;
53
+ app.get("/version-check", (0, api_1.asyncHandler)(function (req, res) { return __awaiter(_this, void 0, void 0, function () {
54
+ var versionParam, platform, version, platformNormalized, config, requiredVersion, warningVersion, response;
55
+ var _a, _b, _c, _d, _e, _f;
56
+ return __generator(this, function (_g) {
57
+ switch (_g.label) {
58
+ case 0:
59
+ versionParam = req.query.version;
60
+ platform = req.query.platform;
61
+ version = typeof versionParam === "string"
62
+ ? parseInt(versionParam, 10)
63
+ : typeof versionParam === "number"
64
+ ? versionParam
65
+ : undefined;
66
+ if (version === undefined || Number.isNaN(version)) {
67
+ return [2 /*return*/, res.json({ status: "ok" })];
68
+ }
69
+ platformNormalized = platform === "web" || platform === "mobile" ? platform : "web";
70
+ return [4 /*yield*/, versionConfig_1.VersionConfig.findOneOrNone({ _singleton: "config" })];
71
+ case 1:
72
+ config = _g.sent();
73
+ if (!config) {
74
+ return [2 /*return*/, res.json({ status: "ok" })];
75
+ }
76
+ requiredVersion = platformNormalized === "web"
77
+ ? ((_a = config.webRequiredVersion) !== null && _a !== void 0 ? _a : 0)
78
+ : ((_b = config.mobileRequiredVersion) !== null && _b !== void 0 ? _b : 0);
79
+ warningVersion = platformNormalized === "web"
80
+ ? ((_c = config.webWarningVersion) !== null && _c !== void 0 ? _c : 0)
81
+ : ((_d = config.mobileWarningVersion) !== null && _d !== void 0 ? _d : 0);
82
+ response = {
83
+ status: "ok",
84
+ };
85
+ if (requiredVersion > 0 && version < requiredVersion) {
86
+ response.status = "required";
87
+ response.message = (_e = config.requiredMessage) !== null && _e !== void 0 ? _e : DEFAULT_REQUIRED_MESSAGE;
88
+ if (config.updateUrl) {
89
+ response.updateUrl = config.updateUrl;
90
+ }
91
+ }
92
+ else if (warningVersion > 0 && version < warningVersion) {
93
+ response.status = "warning";
94
+ response.message = (_f = config.warningMessage) !== null && _f !== void 0 ? _f : DEFAULT_WARNING_MESSAGE;
95
+ if (config.updateUrl) {
96
+ response.updateUrl = config.updateUrl;
97
+ }
98
+ }
99
+ return [2 /*return*/, res.json(response)];
100
+ }
101
+ });
102
+ }); }));
103
+ };
104
+ return VersionCheckPlugin;
105
+ }());
106
+ exports.VersionCheckPlugin = VersionCheckPlugin;
package/package.json CHANGED
@@ -5,13 +5,20 @@
5
5
  },
6
6
  "dependencies": {
7
7
  "@sentry/bun": "^10.25.0",
8
- "better-auth": "^1.2.8",
9
8
  "@sentry/profiling-node": "^10.25.0",
10
9
  "@types/qs": "^6.14.0",
11
- "@wesleytodd/openapi": "^1.1.0",
12
10
  "ajv": "8.18.0",
13
11
  "ajv-formats": "^3.0.1",
12
+ "ajv-keywords": "^5.1.0",
13
+ "http-errors": "^2.0.0",
14
+ "path-to-regexp": "^6.3.0",
15
+ "router": "^2.2.0",
16
+ "serve-static": "^1.15.0",
17
+ "swagger-parser": "^10.0.3",
18
+ "swagger-ui-dist": "^5.11.8",
19
+ "yaml": "^2.4.0",
14
20
  "axios": "^1.13.2",
21
+ "better-auth": "^1.2.8",
15
22
  "cors": "^2.8.5",
16
23
  "cron": "^4.3.4",
17
24
  "expo-server-sdk": "^6.0.0",
@@ -93,5 +100,5 @@
93
100
  "updateSnapshot": "bun test --update-snapshots"
94
101
  },
95
102
  "types": "dist/index.d.ts",
96
- "version": "0.6.0"
103
+ "version": "0.7.1"
97
104
  }