@terreno/api 0.3.1 → 0.4.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/dist/api.js +9 -8
- package/dist/betterAuthSetup.js +1 -1
- package/dist/configuration.test.d.ts +1 -0
- package/dist/configuration.test.js +699 -0
- package/dist/configurationApp.d.ts +91 -0
- package/dist/configurationApp.js +407 -0
- package/dist/configurationPlugin.d.ts +102 -0
- package/dist/configurationPlugin.js +285 -0
- package/dist/configurationPlugin.test.d.ts +1 -0
- package/dist/configurationPlugin.test.js +509 -0
- package/dist/example.js +1 -1
- package/dist/expressServer.js +5 -1
- package/dist/githubAuth.js +2 -2
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/openApiCompat.d.ts +23 -0
- package/dist/openApiCompat.js +198 -0
- package/dist/scriptRunner.d.ts +52 -0
- package/dist/scriptRunner.js +231 -0
- package/dist/secretProviders.d.ts +47 -0
- package/dist/secretProviders.js +214 -0
- package/dist/terrenoApp.d.ts +25 -0
- package/dist/terrenoApp.js +49 -2
- package/dist/tests.d.ts +27 -9
- package/dist/tests.js +10 -1
- package/package.json +13 -13
- package/src/api.ts +9 -8
- package/src/betterAuthSetup.ts +2 -2
- package/src/configuration.test.ts +398 -0
- package/src/configurationApp.ts +359 -0
- package/src/configurationPlugin.test.ts +299 -0
- package/src/configurationPlugin.ts +288 -0
- package/src/example.ts +1 -1
- package/src/expressServer.ts +6 -1
- package/src/githubAuth.ts +4 -4
- package/src/index.ts +5 -0
- package/src/openApiCompat.ts +147 -0
- package/src/permissions.ts +1 -1
- package/src/scriptRunner.ts +219 -0
- package/src/secretProviders.ts +109 -0
- package/src/terrenoApp.ts +44 -2
- package/src/tests.ts +12 -1
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Patches the Express router stack to add `.regexp` on layers for
|
|
4
|
+
* compatibility with @wesleytodd/openapi, which expects Express 4-style
|
|
5
|
+
* layers with `.regexp.fast_slash`.
|
|
6
|
+
*
|
|
7
|
+
* In Express 5 (router@2.x), layers use `.slash` (boolean) and `.matchers`
|
|
8
|
+
* (array of functions) instead of `.regexp`.
|
|
9
|
+
*
|
|
10
|
+
* @see https://github.com/wesleytodd/express-openapi/issues/70
|
|
11
|
+
*/
|
|
12
|
+
var __values = (this && this.__values) || function(o) {
|
|
13
|
+
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
|
14
|
+
if (m) return m.call(o);
|
|
15
|
+
if (o && typeof o.length === "number") return {
|
|
16
|
+
next: function () {
|
|
17
|
+
if (o && i >= o.length) o = void 0;
|
|
18
|
+
return { value: o && o[i++], done: !o };
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
|
22
|
+
};
|
|
23
|
+
var __read = (this && this.__read) || function (o, n) {
|
|
24
|
+
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
25
|
+
if (!m) return o;
|
|
26
|
+
var i = m.call(o), r, ar = [], e;
|
|
27
|
+
try {
|
|
28
|
+
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
29
|
+
}
|
|
30
|
+
catch (error) { e = { error: error }; }
|
|
31
|
+
finally {
|
|
32
|
+
try {
|
|
33
|
+
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
34
|
+
}
|
|
35
|
+
finally { if (e) throw e.error; }
|
|
36
|
+
}
|
|
37
|
+
return ar;
|
|
38
|
+
};
|
|
39
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
40
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
41
|
+
if (ar || !(i in from)) {
|
|
42
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
43
|
+
ar[i] = from[i];
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
47
|
+
};
|
|
48
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
49
|
+
exports.openApiCompatMiddleware = exports.patchAppUse = void 0;
|
|
50
|
+
var MOUNT_PATH_KEY = "__openApiMountPath";
|
|
51
|
+
/**
|
|
52
|
+
* Extract Express 4-style keys from a path string.
|
|
53
|
+
* Parses `:paramName` and `*paramName` segments into `{name, optional}` objects
|
|
54
|
+
* that @wesleytodd/openapi expects.
|
|
55
|
+
*/
|
|
56
|
+
var extractKeysFromPath = function (path) {
|
|
57
|
+
var keys = [];
|
|
58
|
+
var paramRegex = /[:*](\w+)\??/g;
|
|
59
|
+
var match;
|
|
60
|
+
// biome-ignore lint/suspicious/noAssignInExpressions: standard regex exec loop
|
|
61
|
+
while ((match = paramRegex.exec(path)) !== null) {
|
|
62
|
+
keys.push({ name: match[1], optional: match[0].endsWith("?") });
|
|
63
|
+
}
|
|
64
|
+
return keys;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Build an Express 4-style regexp from a path string for the openapi parser.
|
|
68
|
+
*
|
|
69
|
+
* For paths without params (e.g., `/food`), produces a simple escaped regexp
|
|
70
|
+
* that the `split()` function in @wesleytodd/openapi can parse directly.
|
|
71
|
+
*
|
|
72
|
+
* For paths with `:params` (e.g., `/food/:id`), replaces each param with the
|
|
73
|
+
* Express 4-style capture group `(?:([^\/]+?))` so that `processComplexMatch()`
|
|
74
|
+
* in the openapi library can map them to `{paramName}` using `layer.keys`.
|
|
75
|
+
*/
|
|
76
|
+
var buildRegexpForPath = function (pathStr, isMount) {
|
|
77
|
+
// Replace :param segments with Express 4-style capture groups, then escape the rest
|
|
78
|
+
var parts = pathStr.split("/").map(function (segment) {
|
|
79
|
+
if (segment.startsWith(":")) {
|
|
80
|
+
return "(?:([^\\/]+?))";
|
|
81
|
+
}
|
|
82
|
+
return segment.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
83
|
+
});
|
|
84
|
+
var pattern = parts.join("\\/");
|
|
85
|
+
if (isMount) {
|
|
86
|
+
return new RegExp("^".concat(pattern, "\\/?(?=\\/|$)"));
|
|
87
|
+
}
|
|
88
|
+
return new RegExp("^".concat(pattern, "\\/?$"));
|
|
89
|
+
};
|
|
90
|
+
var patchRouterStack = function (stack) {
|
|
91
|
+
var e_1, _a;
|
|
92
|
+
var _b, _c, _d, _e;
|
|
93
|
+
try {
|
|
94
|
+
for (var stack_1 = __values(stack), stack_1_1 = stack_1.next(); !stack_1_1.done; stack_1_1 = stack_1.next()) {
|
|
95
|
+
var layer = stack_1_1.value;
|
|
96
|
+
if (layer.regexp !== undefined) {
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
// Determine the path string for this layer
|
|
100
|
+
var pathStr = void 0;
|
|
101
|
+
var isMount = layer.name === "router" || !!((_b = layer.handle) === null || _b === void 0 ? void 0 : _b.stack);
|
|
102
|
+
if (layer.slash) {
|
|
103
|
+
// Express 5 layers use .slash instead of .regexp.fast_slash
|
|
104
|
+
layer.regexp = { fast_slash: true };
|
|
105
|
+
}
|
|
106
|
+
else if (layer[MOUNT_PATH_KEY]) {
|
|
107
|
+
pathStr = layer[MOUNT_PATH_KEY];
|
|
108
|
+
layer.regexp = buildRegexpForPath(pathStr, isMount);
|
|
109
|
+
}
|
|
110
|
+
else if (layer.path && typeof layer.path === "string") {
|
|
111
|
+
pathStr = layer.path;
|
|
112
|
+
layer.regexp = buildRegexpForPath(pathStr, false);
|
|
113
|
+
}
|
|
114
|
+
else if (((_c = layer.route) === null || _c === void 0 ? void 0 : _c.path) && typeof layer.route.path === "string") {
|
|
115
|
+
pathStr = layer.route.path;
|
|
116
|
+
layer.regexp = buildRegexpForPath(pathStr, false);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
layer.regexp = /^\/?$/;
|
|
120
|
+
}
|
|
121
|
+
// Populate keys in Express 4 format: [{name, optional}]
|
|
122
|
+
// @wesleytodd/openapi reads layer.keys[i].name for path parameters
|
|
123
|
+
if (!layer.keys || (Array.isArray(layer.keys) && layer.keys.length === 0)) {
|
|
124
|
+
if (pathStr) {
|
|
125
|
+
layer.keys = extractKeysFromPath(pathStr);
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
layer.keys = [];
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
else if (Array.isArray(layer.keys) && typeof layer.keys[0] === "string") {
|
|
132
|
+
// Express 5 stores keys as plain strings after match() — convert to objects
|
|
133
|
+
layer.keys = layer.keys.map(function (k) { return ({ name: k, optional: false }); });
|
|
134
|
+
}
|
|
135
|
+
// Recursively patch nested stacks
|
|
136
|
+
if ((_d = layer.handle) === null || _d === void 0 ? void 0 : _d.stack) {
|
|
137
|
+
patchRouterStack(layer.handle.stack);
|
|
138
|
+
}
|
|
139
|
+
if ((_e = layer.route) === null || _e === void 0 ? void 0 : _e.stack) {
|
|
140
|
+
patchRouterStack(layer.route.stack);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
145
|
+
finally {
|
|
146
|
+
try {
|
|
147
|
+
if (stack_1_1 && !stack_1_1.done && (_a = stack_1.return)) _a.call(stack_1);
|
|
148
|
+
}
|
|
149
|
+
finally { if (e_1) throw e_1.error; }
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
/**
|
|
153
|
+
* Wraps an Express app's `use` method to record the mount path on each
|
|
154
|
+
* layer added to the router stack. This runs at setup time so that
|
|
155
|
+
* `patchRouterStack` can read the original path later.
|
|
156
|
+
*
|
|
157
|
+
* Must be called before any routes are registered.
|
|
158
|
+
*/
|
|
159
|
+
var patchAppUse = function (app) {
|
|
160
|
+
var originalUse = app.use.bind(app);
|
|
161
|
+
app.use = function patchedUse() {
|
|
162
|
+
var _a, _b;
|
|
163
|
+
var args = [];
|
|
164
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
165
|
+
args[_i] = arguments[_i];
|
|
166
|
+
}
|
|
167
|
+
// Track stack length before the call
|
|
168
|
+
var router = app._router || app.router;
|
|
169
|
+
var stackBefore = (_b = (_a = router === null || router === void 0 ? void 0 : router.stack) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
|
|
170
|
+
var result = originalUse.apply(void 0, __spreadArray([], __read(args), false));
|
|
171
|
+
// After use(), check if new layers were added and annotate them
|
|
172
|
+
var routerAfter = app._router || app.router;
|
|
173
|
+
if (routerAfter === null || routerAfter === void 0 ? void 0 : routerAfter.stack) {
|
|
174
|
+
var stackAfter = routerAfter.stack.length;
|
|
175
|
+
// The first arg is the mount path if it's a string
|
|
176
|
+
var mountPath = typeof args[0] === "string" ? args[0] : undefined;
|
|
177
|
+
if (mountPath && mountPath !== "/") {
|
|
178
|
+
for (var i = stackBefore; i < stackAfter; i++) {
|
|
179
|
+
routerAfter.stack[i][MOUNT_PATH_KEY] = mountPath.replace(/\/+$/, "");
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return result;
|
|
184
|
+
};
|
|
185
|
+
};
|
|
186
|
+
exports.patchAppUse = patchAppUse;
|
|
187
|
+
/**
|
|
188
|
+
* Express middleware that patches the router stack before OpenAPI doc
|
|
189
|
+
* generation. Must be mounted before the openapi middleware.
|
|
190
|
+
*/
|
|
191
|
+
var openApiCompatMiddleware = function (req, _res, next) {
|
|
192
|
+
var router = req.app._router || req.app.router;
|
|
193
|
+
if (router === null || router === void 0 ? void 0 : router.stack) {
|
|
194
|
+
patchRouterStack(router.stack);
|
|
195
|
+
}
|
|
196
|
+
next();
|
|
197
|
+
};
|
|
198
|
+
exports.openApiCompatMiddleware = openApiCompatMiddleware;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import mongoose, { type Document, type Model } from "mongoose";
|
|
2
|
+
export interface ScriptResult {
|
|
3
|
+
success: boolean;
|
|
4
|
+
results: string[];
|
|
5
|
+
}
|
|
6
|
+
export interface ScriptContext {
|
|
7
|
+
/** Check if the task has been cancelled. Throws TaskCancelledError if so. */
|
|
8
|
+
checkCancellation: () => Promise<void>;
|
|
9
|
+
/** Add a log entry to the task. */
|
|
10
|
+
addLog: (level: "info" | "warn" | "error", message: string) => Promise<void>;
|
|
11
|
+
/** Update progress on the task. */
|
|
12
|
+
updateProgress: (percentage: number, stage?: string, message?: string) => Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
export type ScriptRunner = (wetRun: boolean, ctx?: ScriptContext) => Promise<ScriptResult>;
|
|
15
|
+
export declare class TaskCancelledError extends Error {
|
|
16
|
+
constructor(taskId: string);
|
|
17
|
+
}
|
|
18
|
+
interface BackgroundTaskProgress {
|
|
19
|
+
percentage: number;
|
|
20
|
+
stage?: string;
|
|
21
|
+
message?: string;
|
|
22
|
+
}
|
|
23
|
+
interface BackgroundTaskLog {
|
|
24
|
+
timestamp: Date;
|
|
25
|
+
level: "info" | "warn" | "error";
|
|
26
|
+
message: string;
|
|
27
|
+
}
|
|
28
|
+
export type BackgroundTaskMethods = {
|
|
29
|
+
addLog: (this: BackgroundTaskDocument, level: "info" | "warn" | "error", message: string) => Promise<void>;
|
|
30
|
+
updateProgress: (this: BackgroundTaskDocument, percentage: number, stage?: string, message?: string) => Promise<void>;
|
|
31
|
+
};
|
|
32
|
+
export type BackgroundTaskDocument = Document & BackgroundTaskMethods & {
|
|
33
|
+
taskType: string;
|
|
34
|
+
status: "pending" | "running" | "completed" | "failed" | "cancelled";
|
|
35
|
+
progress?: BackgroundTaskProgress;
|
|
36
|
+
createdBy?: mongoose.Types.ObjectId;
|
|
37
|
+
isDryRun: boolean;
|
|
38
|
+
result?: string[];
|
|
39
|
+
error?: string;
|
|
40
|
+
logs: BackgroundTaskLog[];
|
|
41
|
+
startedAt?: Date;
|
|
42
|
+
completedAt?: Date;
|
|
43
|
+
created: Date;
|
|
44
|
+
updated: Date;
|
|
45
|
+
deleted: boolean;
|
|
46
|
+
};
|
|
47
|
+
export type BackgroundTaskStatics = {
|
|
48
|
+
checkCancellation: (taskId: string) => Promise<void>;
|
|
49
|
+
};
|
|
50
|
+
export type BackgroundTaskModel = Model<BackgroundTaskDocument, Record<string, never>, BackgroundTaskMethods> & BackgroundTaskStatics;
|
|
51
|
+
export declare const BackgroundTask: BackgroundTaskModel;
|
|
52
|
+
export {};
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __extends = (this && this.__extends) || (function () {
|
|
3
|
+
var extendStatics = function (d, b) {
|
|
4
|
+
extendStatics = Object.setPrototypeOf ||
|
|
5
|
+
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
6
|
+
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
7
|
+
return extendStatics(d, b);
|
|
8
|
+
};
|
|
9
|
+
return function (d, b) {
|
|
10
|
+
if (typeof b !== "function" && b !== null)
|
|
11
|
+
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
12
|
+
extendStatics(d, b);
|
|
13
|
+
function __() { this.constructor = d; }
|
|
14
|
+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
15
|
+
};
|
|
16
|
+
})();
|
|
17
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
20
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
21
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
22
|
+
}
|
|
23
|
+
Object.defineProperty(o, k2, desc);
|
|
24
|
+
}) : (function(o, m, k, k2) {
|
|
25
|
+
if (k2 === undefined) k2 = k;
|
|
26
|
+
o[k2] = m[k];
|
|
27
|
+
}));
|
|
28
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
29
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
30
|
+
}) : function(o, v) {
|
|
31
|
+
o["default"] = v;
|
|
32
|
+
});
|
|
33
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
34
|
+
var ownKeys = function(o) {
|
|
35
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
36
|
+
var ar = [];
|
|
37
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
38
|
+
return ar;
|
|
39
|
+
};
|
|
40
|
+
return ownKeys(o);
|
|
41
|
+
};
|
|
42
|
+
return function (mod) {
|
|
43
|
+
if (mod && mod.__esModule) return mod;
|
|
44
|
+
var result = {};
|
|
45
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
46
|
+
__setModuleDefault(result, mod);
|
|
47
|
+
return result;
|
|
48
|
+
};
|
|
49
|
+
})();
|
|
50
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
51
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
52
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
53
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
54
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
55
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
56
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
57
|
+
});
|
|
58
|
+
};
|
|
59
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
60
|
+
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);
|
|
61
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
62
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
63
|
+
function step(op) {
|
|
64
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
65
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
66
|
+
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;
|
|
67
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
68
|
+
switch (op[0]) {
|
|
69
|
+
case 0: case 1: t = op; break;
|
|
70
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
71
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
72
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
73
|
+
default:
|
|
74
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
75
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
76
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
77
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
78
|
+
if (t[2]) _.ops.pop();
|
|
79
|
+
_.trys.pop(); continue;
|
|
80
|
+
}
|
|
81
|
+
op = body.call(thisArg, _);
|
|
82
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
83
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
87
|
+
exports.BackgroundTask = exports.TaskCancelledError = void 0;
|
|
88
|
+
var luxon_1 = require("luxon");
|
|
89
|
+
var mongoose_1 = __importStar(require("mongoose"));
|
|
90
|
+
var plugins_1 = require("./plugins");
|
|
91
|
+
var TaskCancelledError = /** @class */ (function (_super) {
|
|
92
|
+
__extends(TaskCancelledError, _super);
|
|
93
|
+
function TaskCancelledError(taskId) {
|
|
94
|
+
var _this = _super.call(this, "Task ".concat(taskId, " was cancelled")) || this;
|
|
95
|
+
_this.name = "TaskCancelledError";
|
|
96
|
+
return _this;
|
|
97
|
+
}
|
|
98
|
+
return TaskCancelledError;
|
|
99
|
+
}(Error));
|
|
100
|
+
exports.TaskCancelledError = TaskCancelledError;
|
|
101
|
+
var progressSchema = new mongoose_1.Schema({
|
|
102
|
+
message: { description: "Human-readable progress message", type: String },
|
|
103
|
+
percentage: { description: "Progress percentage from 0 to 100", max: 100, min: 0, type: Number },
|
|
104
|
+
stage: { description: "Current stage of the task", type: String },
|
|
105
|
+
}, { _id: false });
|
|
106
|
+
var logSchema = new mongoose_1.Schema({
|
|
107
|
+
level: {
|
|
108
|
+
description: "Log level",
|
|
109
|
+
enum: ["info", "warn", "error"],
|
|
110
|
+
required: true,
|
|
111
|
+
type: String,
|
|
112
|
+
},
|
|
113
|
+
message: { description: "Log message", required: true, type: String },
|
|
114
|
+
timestamp: { description: "When this log entry was created", required: true, type: Date },
|
|
115
|
+
}, { _id: false });
|
|
116
|
+
var backgroundTaskSchema = new mongoose_1.Schema({
|
|
117
|
+
completedAt: {
|
|
118
|
+
description: "When the task completed (success or failure)",
|
|
119
|
+
type: Date,
|
|
120
|
+
},
|
|
121
|
+
createdBy: {
|
|
122
|
+
description: "The user who created this task",
|
|
123
|
+
ref: "User",
|
|
124
|
+
type: mongoose_1.default.Schema.Types.ObjectId,
|
|
125
|
+
},
|
|
126
|
+
error: {
|
|
127
|
+
description: "Error message if the task failed",
|
|
128
|
+
type: String,
|
|
129
|
+
},
|
|
130
|
+
isDryRun: {
|
|
131
|
+
default: false,
|
|
132
|
+
description: "Whether this is a dry run that does not make real changes",
|
|
133
|
+
type: Boolean,
|
|
134
|
+
},
|
|
135
|
+
logs: {
|
|
136
|
+
default: [],
|
|
137
|
+
description: "Log entries for the task execution",
|
|
138
|
+
type: [logSchema],
|
|
139
|
+
},
|
|
140
|
+
progress: {
|
|
141
|
+
description: "Progress information for the task",
|
|
142
|
+
type: progressSchema,
|
|
143
|
+
},
|
|
144
|
+
result: {
|
|
145
|
+
description: "Result strings when the task completes",
|
|
146
|
+
type: [String],
|
|
147
|
+
},
|
|
148
|
+
startedAt: {
|
|
149
|
+
description: "When the task started executing",
|
|
150
|
+
type: Date,
|
|
151
|
+
},
|
|
152
|
+
status: {
|
|
153
|
+
default: "pending",
|
|
154
|
+
description: "Current status of the task",
|
|
155
|
+
enum: ["pending", "running", "completed", "failed", "cancelled"],
|
|
156
|
+
type: String,
|
|
157
|
+
},
|
|
158
|
+
taskType: {
|
|
159
|
+
description: "The type or name of the background task",
|
|
160
|
+
required: true,
|
|
161
|
+
type: String,
|
|
162
|
+
},
|
|
163
|
+
}, { strict: "throw", toJSON: { virtuals: true }, toObject: { virtuals: true } });
|
|
164
|
+
backgroundTaskSchema.methods = {
|
|
165
|
+
addLog: function (level, message) {
|
|
166
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
167
|
+
return __generator(this, function (_a) {
|
|
168
|
+
switch (_a.label) {
|
|
169
|
+
case 0:
|
|
170
|
+
if (!this.logs) {
|
|
171
|
+
this.logs = [];
|
|
172
|
+
}
|
|
173
|
+
this.logs.push({
|
|
174
|
+
level: level,
|
|
175
|
+
message: message,
|
|
176
|
+
timestamp: luxon_1.DateTime.now().toJSDate(),
|
|
177
|
+
});
|
|
178
|
+
return [4 /*yield*/, this.save()];
|
|
179
|
+
case 1:
|
|
180
|
+
_a.sent();
|
|
181
|
+
return [2 /*return*/];
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
},
|
|
186
|
+
updateProgress: function (percentage, stage, message) {
|
|
187
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
188
|
+
var _a, _b;
|
|
189
|
+
return __generator(this, function (_c) {
|
|
190
|
+
switch (_c.label) {
|
|
191
|
+
case 0:
|
|
192
|
+
this.progress = {
|
|
193
|
+
message: message !== null && message !== void 0 ? message : (_a = this.progress) === null || _a === void 0 ? void 0 : _a.message,
|
|
194
|
+
percentage: percentage,
|
|
195
|
+
stage: stage !== null && stage !== void 0 ? stage : (_b = this.progress) === null || _b === void 0 ? void 0 : _b.stage,
|
|
196
|
+
};
|
|
197
|
+
return [4 /*yield*/, this.save()];
|
|
198
|
+
case 1:
|
|
199
|
+
_c.sent();
|
|
200
|
+
return [2 /*return*/];
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
},
|
|
205
|
+
};
|
|
206
|
+
backgroundTaskSchema.statics = {
|
|
207
|
+
checkCancellation: function (taskId) {
|
|
208
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
209
|
+
var task;
|
|
210
|
+
return __generator(this, function (_a) {
|
|
211
|
+
switch (_a.label) {
|
|
212
|
+
case 0: return [4 /*yield*/, this.findById(taskId).select("status").lean()];
|
|
213
|
+
case 1:
|
|
214
|
+
task = _a.sent();
|
|
215
|
+
if ((task === null || task === void 0 ? void 0 : task.status) === "cancelled") {
|
|
216
|
+
throw new TaskCancelledError(taskId);
|
|
217
|
+
}
|
|
218
|
+
return [2 /*return*/];
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
},
|
|
223
|
+
};
|
|
224
|
+
backgroundTaskSchema.index({ createdBy: 1, status: 1 });
|
|
225
|
+
backgroundTaskSchema.index({ status: 1 });
|
|
226
|
+
backgroundTaskSchema.index({ status: 1, taskType: 1 });
|
|
227
|
+
backgroundTaskSchema.plugin(plugins_1.createdUpdatedPlugin);
|
|
228
|
+
backgroundTaskSchema.plugin(plugins_1.isDeletedPlugin);
|
|
229
|
+
backgroundTaskSchema.plugin(plugins_1.findOneOrNone);
|
|
230
|
+
backgroundTaskSchema.plugin(plugins_1.findExactlyOne);
|
|
231
|
+
exports.BackgroundTask = mongoose_1.default.model("BackgroundTask", backgroundTaskSchema);
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { SecretProvider } from "./configurationPlugin";
|
|
2
|
+
/**
|
|
3
|
+
* Secret provider that reads secrets from environment variables.
|
|
4
|
+
* Useful for local development and testing.
|
|
5
|
+
*
|
|
6
|
+
* Maps secret names to environment variable names by converting to SCREAMING_SNAKE_CASE.
|
|
7
|
+
* e.g., "openai-api-key" → process.env.OPENAI_API_KEY
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* const provider = new EnvSecretProvider();
|
|
12
|
+
* // reads process.env.OPENAI_API_KEY
|
|
13
|
+
* const key = await provider.getSecret("openai-api-key");
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export declare class EnvSecretProvider implements SecretProvider {
|
|
17
|
+
name: string;
|
|
18
|
+
getSecret(secretName: string): Promise<string | null>;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Options for GcpSecretProvider.
|
|
22
|
+
*/
|
|
23
|
+
export interface GcpSecretProviderOptions {
|
|
24
|
+
/** GCP project ID. Required for short secret names. */
|
|
25
|
+
projectId: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Secret provider that reads secrets from Google Cloud Secret Manager.
|
|
29
|
+
*
|
|
30
|
+
* Requires `@google-cloud/secret-manager` to be installed.
|
|
31
|
+
* Resolves short names like "openai-api-key" to the full resource path
|
|
32
|
+
* `projects/{projectId}/secrets/{secretName}/versions/latest`.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```typescript
|
|
36
|
+
* const provider = new GcpSecretProvider({ projectId: "my-project" });
|
|
37
|
+
* const key = await provider.getSecret("openai-api-key");
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare class GcpSecretProvider implements SecretProvider {
|
|
41
|
+
name: string;
|
|
42
|
+
private projectId;
|
|
43
|
+
private client;
|
|
44
|
+
constructor(options: GcpSecretProviderOptions);
|
|
45
|
+
private getClient;
|
|
46
|
+
getSecret(secretName: string): Promise<string | null>;
|
|
47
|
+
}
|