@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.
Files changed (42) hide show
  1. package/dist/api.js +9 -8
  2. package/dist/betterAuthSetup.js +1 -1
  3. package/dist/configuration.test.d.ts +1 -0
  4. package/dist/configuration.test.js +699 -0
  5. package/dist/configurationApp.d.ts +91 -0
  6. package/dist/configurationApp.js +407 -0
  7. package/dist/configurationPlugin.d.ts +102 -0
  8. package/dist/configurationPlugin.js +285 -0
  9. package/dist/configurationPlugin.test.d.ts +1 -0
  10. package/dist/configurationPlugin.test.js +509 -0
  11. package/dist/example.js +1 -1
  12. package/dist/expressServer.js +5 -1
  13. package/dist/githubAuth.js +2 -2
  14. package/dist/index.d.ts +5 -0
  15. package/dist/index.js +5 -0
  16. package/dist/openApiCompat.d.ts +23 -0
  17. package/dist/openApiCompat.js +198 -0
  18. package/dist/scriptRunner.d.ts +52 -0
  19. package/dist/scriptRunner.js +231 -0
  20. package/dist/secretProviders.d.ts +47 -0
  21. package/dist/secretProviders.js +214 -0
  22. package/dist/terrenoApp.d.ts +25 -0
  23. package/dist/terrenoApp.js +49 -2
  24. package/dist/tests.d.ts +27 -9
  25. package/dist/tests.js +10 -1
  26. package/package.json +13 -13
  27. package/src/api.ts +9 -8
  28. package/src/betterAuthSetup.ts +2 -2
  29. package/src/configuration.test.ts +398 -0
  30. package/src/configurationApp.ts +359 -0
  31. package/src/configurationPlugin.test.ts +299 -0
  32. package/src/configurationPlugin.ts +288 -0
  33. package/src/example.ts +1 -1
  34. package/src/expressServer.ts +6 -1
  35. package/src/githubAuth.ts +4 -4
  36. package/src/index.ts +5 -0
  37. package/src/openApiCompat.ts +147 -0
  38. package/src/permissions.ts +1 -1
  39. package/src/scriptRunner.ts +219 -0
  40. package/src/secretProviders.ts +109 -0
  41. package/src/terrenoApp.ts +44 -2
  42. 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
+ }