@igstack/app-catalog-backend-core 0.2.0 → 0.3.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/index.d.ts +239 -1235
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +441 -2367
- package/dist/index.js.map +1 -1
- package/package.json +7 -4
- package/prisma.config.ts +13 -0
- package/src/index.ts +0 -30
- package/src/middleware/featureRegistry.ts +0 -38
- package/src/server/controller.ts +0 -16
- package/src/modules/appCatalogAdmin/appCatalogAdminRouter.ts +0 -187
- package/src/modules/appCatalogAdmin/catalogBackupController.ts +0 -213
- package/src/modules/approvalMethod/approvalMethodRouter.ts +0 -169
- package/src/modules/approvalMethod/slugUtils.ts +0 -17
- package/src/modules/approvalMethod/syncApprovalMethods.ts +0 -38
package/dist/index.js
CHANGED
|
@@ -3,17 +3,16 @@ import * as path$1 from "node:path";
|
|
|
3
3
|
import { extname, join } from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
import * as runtime from "@prisma/client/runtime/client";
|
|
6
|
+
import { PrismaPg } from "@prisma/adapter-pg";
|
|
6
7
|
import { group, mapValues, omit, pick } from "radashi";
|
|
7
|
-
import {
|
|
8
|
+
import { TRPCError, initTRPC } from "@trpc/server";
|
|
9
|
+
import { betterAuth } from "better-auth";
|
|
10
|
+
import { prismaAdapter } from "better-auth/adapters/prisma";
|
|
8
11
|
import { tableSync } from "@igstack/app-catalog-table-sync";
|
|
9
12
|
import { readFile, readdir, stat } from "node:fs/promises";
|
|
10
13
|
import { createHash } from "node:crypto";
|
|
11
14
|
import sharp from "sharp";
|
|
12
|
-
import { TRPCError, initTRPC } from "@trpc/server";
|
|
13
|
-
import { betterAuth } from "better-auth";
|
|
14
|
-
import { prismaAdapter } from "better-auth/adapters/prisma";
|
|
15
15
|
import { toNodeHandler } from "better-auth/node";
|
|
16
|
-
import { stepCountIs, streamText, tool } from "ai";
|
|
17
16
|
import multer from "multer";
|
|
18
17
|
import { readFileSync, readdirSync } from "node:fs";
|
|
19
18
|
import express, { Router } from "express";
|
|
@@ -21,7 +20,7 @@ import * as trpcExpress from "@trpc/server/adapters/express";
|
|
|
21
20
|
|
|
22
21
|
//#region rolldown:runtime
|
|
23
22
|
var __create = Object.create;
|
|
24
|
-
var __defProp
|
|
23
|
+
var __defProp = Object.defineProperty;
|
|
25
24
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
26
25
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
27
26
|
var __getProtoOf = Object.getPrototypeOf;
|
|
@@ -32,14 +31,14 @@ var __commonJS = (cb, mod) => function() {
|
|
|
32
31
|
var __copyProps = (to, from, except, desc) => {
|
|
33
32
|
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
34
33
|
key = keys[i];
|
|
35
|
-
if (!__hasOwnProp.call(to, key) && key !== except) __defProp
|
|
34
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
36
35
|
get: ((k) => from[k]).bind(null, key),
|
|
37
36
|
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
38
37
|
});
|
|
39
38
|
}
|
|
40
39
|
return to;
|
|
41
40
|
};
|
|
42
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp
|
|
41
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
43
42
|
value: mod,
|
|
44
43
|
enumerable: true
|
|
45
44
|
}) : target, mod));
|
|
@@ -85,63 +84,6 @@ function getPrismaClientClass() {
|
|
|
85
84
|
return runtime.getPrismaClient(config);
|
|
86
85
|
}
|
|
87
86
|
|
|
88
|
-
//#endregion
|
|
89
|
-
//#region src/generated/prisma/internal/prismaNamespace.ts
|
|
90
|
-
/**
|
|
91
|
-
* Prisma Errors
|
|
92
|
-
*/
|
|
93
|
-
const PrismaClientKnownRequestError = runtime.PrismaClientKnownRequestError;
|
|
94
|
-
const PrismaClientUnknownRequestError = runtime.PrismaClientUnknownRequestError;
|
|
95
|
-
const PrismaClientRustPanicError = runtime.PrismaClientRustPanicError;
|
|
96
|
-
const PrismaClientInitializationError = runtime.PrismaClientInitializationError;
|
|
97
|
-
const PrismaClientValidationError = runtime.PrismaClientValidationError;
|
|
98
|
-
/**
|
|
99
|
-
* Re-export of sql-template-tag
|
|
100
|
-
*/
|
|
101
|
-
const sql = runtime.sqltag;
|
|
102
|
-
const empty = runtime.empty;
|
|
103
|
-
const join$1 = runtime.join;
|
|
104
|
-
const raw = runtime.raw;
|
|
105
|
-
const Sql = runtime.Sql;
|
|
106
|
-
/**
|
|
107
|
-
* Decimal.js
|
|
108
|
-
*/
|
|
109
|
-
const Decimal = runtime.Decimal;
|
|
110
|
-
const getExtensionContext = runtime.Extensions.getExtensionContext;
|
|
111
|
-
const NullTypes = {
|
|
112
|
-
DbNull: runtime.NullTypes.DbNull,
|
|
113
|
-
JsonNull: runtime.NullTypes.JsonNull,
|
|
114
|
-
AnyNull: runtime.NullTypes.AnyNull
|
|
115
|
-
};
|
|
116
|
-
/**
|
|
117
|
-
* Helper for filtering JSON entries that have `null` on the database (empty on the db)
|
|
118
|
-
*
|
|
119
|
-
* @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field
|
|
120
|
-
*/
|
|
121
|
-
const DbNull = runtime.DbNull;
|
|
122
|
-
/**
|
|
123
|
-
* Helper for filtering JSON entries that have JSON `null` values (not empty on the db)
|
|
124
|
-
*
|
|
125
|
-
* @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field
|
|
126
|
-
*/
|
|
127
|
-
const JsonNull = runtime.JsonNull;
|
|
128
|
-
/**
|
|
129
|
-
* Helper for filtering JSON entries that are `Prisma.DbNull` or `Prisma.JsonNull`
|
|
130
|
-
*
|
|
131
|
-
* @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field
|
|
132
|
-
*/
|
|
133
|
-
const AnyNull = runtime.AnyNull;
|
|
134
|
-
/**
|
|
135
|
-
* Enums
|
|
136
|
-
*/
|
|
137
|
-
const TransactionIsolationLevel = runtime.makeStrictEnum({
|
|
138
|
-
ReadUncommitted: "ReadUncommitted",
|
|
139
|
-
ReadCommitted: "ReadCommitted",
|
|
140
|
-
RepeatableRead: "RepeatableRead",
|
|
141
|
-
Serializable: "Serializable"
|
|
142
|
-
});
|
|
143
|
-
const defineExtension = runtime.Extensions.defineExtension;
|
|
144
|
-
|
|
145
87
|
//#endregion
|
|
146
88
|
//#region src/generated/prisma/client.ts
|
|
147
89
|
globalThis["__dirname"] = path$1.dirname(fileURLToPath(import.meta.url));
|
|
@@ -162,225 +104,9 @@ globalThis["__dirname"] = path$1.dirname(fileURLToPath(import.meta.url));
|
|
|
162
104
|
*/
|
|
163
105
|
const PrismaClient = getPrismaClientClass();
|
|
164
106
|
|
|
165
|
-
//#endregion
|
|
166
|
-
//#region ../../node_modules/.pnpm/@prisma+debug@7.4.2/node_modules/@prisma/debug/dist/index.mjs
|
|
167
|
-
var __defProp = Object.defineProperty;
|
|
168
|
-
var __export = (target, all) => {
|
|
169
|
-
for (var name$1 in all) __defProp(target, name$1, {
|
|
170
|
-
get: all[name$1],
|
|
171
|
-
enumerable: true
|
|
172
|
-
});
|
|
173
|
-
};
|
|
174
|
-
var colors_exports = {};
|
|
175
|
-
__export(colors_exports, {
|
|
176
|
-
$: () => $,
|
|
177
|
-
bgBlack: () => bgBlack,
|
|
178
|
-
bgBlue: () => bgBlue,
|
|
179
|
-
bgCyan: () => bgCyan,
|
|
180
|
-
bgGreen: () => bgGreen,
|
|
181
|
-
bgMagenta: () => bgMagenta,
|
|
182
|
-
bgRed: () => bgRed,
|
|
183
|
-
bgWhite: () => bgWhite,
|
|
184
|
-
bgYellow: () => bgYellow,
|
|
185
|
-
black: () => black,
|
|
186
|
-
blue: () => blue,
|
|
187
|
-
bold: () => bold,
|
|
188
|
-
cyan: () => cyan,
|
|
189
|
-
dim: () => dim,
|
|
190
|
-
gray: () => gray,
|
|
191
|
-
green: () => green,
|
|
192
|
-
grey: () => grey,
|
|
193
|
-
hidden: () => hidden,
|
|
194
|
-
inverse: () => inverse,
|
|
195
|
-
italic: () => italic,
|
|
196
|
-
magenta: () => magenta,
|
|
197
|
-
red: () => red,
|
|
198
|
-
reset: () => reset,
|
|
199
|
-
strikethrough: () => strikethrough,
|
|
200
|
-
underline: () => underline,
|
|
201
|
-
white: () => white,
|
|
202
|
-
yellow: () => yellow
|
|
203
|
-
});
|
|
204
|
-
var FORCE_COLOR;
|
|
205
|
-
var NODE_DISABLE_COLORS;
|
|
206
|
-
var NO_COLOR;
|
|
207
|
-
var TERM;
|
|
208
|
-
var isTTY = true;
|
|
209
|
-
if (typeof process !== "undefined") {
|
|
210
|
-
({FORCE_COLOR, NODE_DISABLE_COLORS, NO_COLOR, TERM} = process.env || {});
|
|
211
|
-
isTTY = process.stdout && process.stdout.isTTY;
|
|
212
|
-
}
|
|
213
|
-
var $ = { enabled: !NODE_DISABLE_COLORS && NO_COLOR == null && TERM !== "dumb" && (FORCE_COLOR != null && FORCE_COLOR !== "0" || isTTY) };
|
|
214
|
-
function init$2(x, y) {
|
|
215
|
-
let rgx = new RegExp(`\\x1b\\[${y}m`, "g");
|
|
216
|
-
let open = `\x1B[${x}m`, close$1 = `\x1B[${y}m`;
|
|
217
|
-
return function(txt) {
|
|
218
|
-
if (!$.enabled || txt == null) return txt;
|
|
219
|
-
return open + (!!~("" + txt).indexOf(close$1) ? txt.replace(rgx, close$1 + open) : txt) + close$1;
|
|
220
|
-
};
|
|
221
|
-
}
|
|
222
|
-
var reset = init$2(0, 0);
|
|
223
|
-
var bold = init$2(1, 22);
|
|
224
|
-
var dim = init$2(2, 22);
|
|
225
|
-
var italic = init$2(3, 23);
|
|
226
|
-
var underline = init$2(4, 24);
|
|
227
|
-
var inverse = init$2(7, 27);
|
|
228
|
-
var hidden = init$2(8, 28);
|
|
229
|
-
var strikethrough = init$2(9, 29);
|
|
230
|
-
var black = init$2(30, 39);
|
|
231
|
-
var red = init$2(31, 39);
|
|
232
|
-
var green = init$2(32, 39);
|
|
233
|
-
var yellow = init$2(33, 39);
|
|
234
|
-
var blue = init$2(34, 39);
|
|
235
|
-
var magenta = init$2(35, 39);
|
|
236
|
-
var cyan = init$2(36, 39);
|
|
237
|
-
var white = init$2(37, 39);
|
|
238
|
-
var gray = init$2(90, 39);
|
|
239
|
-
var grey = init$2(90, 39);
|
|
240
|
-
var bgBlack = init$2(40, 49);
|
|
241
|
-
var bgRed = init$2(41, 49);
|
|
242
|
-
var bgGreen = init$2(42, 49);
|
|
243
|
-
var bgYellow = init$2(43, 49);
|
|
244
|
-
var bgBlue = init$2(44, 49);
|
|
245
|
-
var bgMagenta = init$2(45, 49);
|
|
246
|
-
var bgCyan = init$2(46, 49);
|
|
247
|
-
var bgWhite = init$2(47, 49);
|
|
248
|
-
var MAX_ARGS_HISTORY = 100;
|
|
249
|
-
var COLORS = [
|
|
250
|
-
"green",
|
|
251
|
-
"yellow",
|
|
252
|
-
"blue",
|
|
253
|
-
"magenta",
|
|
254
|
-
"cyan",
|
|
255
|
-
"red"
|
|
256
|
-
];
|
|
257
|
-
var argsHistory = [];
|
|
258
|
-
var lastTimestamp = Date.now();
|
|
259
|
-
var lastColor = 0;
|
|
260
|
-
var processEnv = typeof process !== "undefined" ? process.env : {};
|
|
261
|
-
globalThis.DEBUG ??= processEnv.DEBUG ?? "";
|
|
262
|
-
globalThis.DEBUG_COLORS ??= processEnv.DEBUG_COLORS ? processEnv.DEBUG_COLORS === "true" : true;
|
|
263
|
-
var topProps = {
|
|
264
|
-
enable(namespace) {
|
|
265
|
-
if (typeof namespace === "string") globalThis.DEBUG = namespace;
|
|
266
|
-
},
|
|
267
|
-
disable() {
|
|
268
|
-
const prev = globalThis.DEBUG;
|
|
269
|
-
globalThis.DEBUG = "";
|
|
270
|
-
return prev;
|
|
271
|
-
},
|
|
272
|
-
enabled(namespace) {
|
|
273
|
-
const listenedNamespaces = globalThis.DEBUG.split(",").map((s) => {
|
|
274
|
-
return s.replace(/[.+?^${}()|[\]\\]/g, "\\$&");
|
|
275
|
-
});
|
|
276
|
-
const isListened = listenedNamespaces.some((listenedNamespace) => {
|
|
277
|
-
if (listenedNamespace === "" || listenedNamespace[0] === "-") return false;
|
|
278
|
-
return namespace.match(RegExp(listenedNamespace.split("*").join(".*") + "$"));
|
|
279
|
-
});
|
|
280
|
-
const isExcluded = listenedNamespaces.some((listenedNamespace) => {
|
|
281
|
-
if (listenedNamespace === "" || listenedNamespace[0] !== "-") return false;
|
|
282
|
-
return namespace.match(RegExp(listenedNamespace.slice(1).split("*").join(".*") + "$"));
|
|
283
|
-
});
|
|
284
|
-
return isListened && !isExcluded;
|
|
285
|
-
},
|
|
286
|
-
log: (...args) => {
|
|
287
|
-
const [namespace, format, ...rest] = args;
|
|
288
|
-
(console.warn ?? console.log)(`${namespace} ${format}`, ...rest);
|
|
289
|
-
},
|
|
290
|
-
formatters: {}
|
|
291
|
-
};
|
|
292
|
-
function debugCreate(namespace) {
|
|
293
|
-
const instanceProps = {
|
|
294
|
-
color: COLORS[lastColor++ % COLORS.length],
|
|
295
|
-
enabled: topProps.enabled(namespace),
|
|
296
|
-
namespace,
|
|
297
|
-
log: topProps.log,
|
|
298
|
-
extend: () => {}
|
|
299
|
-
};
|
|
300
|
-
const debugCall = (...args) => {
|
|
301
|
-
const { enabled, namespace: namespace2, color, log } = instanceProps;
|
|
302
|
-
if (args.length !== 0) argsHistory.push([namespace2, ...args]);
|
|
303
|
-
if (argsHistory.length > MAX_ARGS_HISTORY) argsHistory.shift();
|
|
304
|
-
if (topProps.enabled(namespace2) || enabled) {
|
|
305
|
-
const stringArgs = args.map((arg) => {
|
|
306
|
-
if (typeof arg === "string") return arg;
|
|
307
|
-
return safeStringify(arg);
|
|
308
|
-
});
|
|
309
|
-
const ms = `+${Date.now() - lastTimestamp}ms`;
|
|
310
|
-
lastTimestamp = Date.now();
|
|
311
|
-
if (globalThis.DEBUG_COLORS) log(colors_exports[color](bold(namespace2)), ...stringArgs, colors_exports[color](ms));
|
|
312
|
-
else log(namespace2, ...stringArgs, ms);
|
|
313
|
-
}
|
|
314
|
-
};
|
|
315
|
-
return new Proxy(debugCall, {
|
|
316
|
-
get: (_, prop) => instanceProps[prop],
|
|
317
|
-
set: (_, prop, value) => instanceProps[prop] = value
|
|
318
|
-
});
|
|
319
|
-
}
|
|
320
|
-
var Debug = new Proxy(debugCreate, {
|
|
321
|
-
get: (_, prop) => topProps[prop],
|
|
322
|
-
set: (_, prop, value) => topProps[prop] = value
|
|
323
|
-
});
|
|
324
|
-
function safeStringify(value, indent = 2) {
|
|
325
|
-
const cache = /* @__PURE__ */ new Set();
|
|
326
|
-
return JSON.stringify(value, (key, value2) => {
|
|
327
|
-
if (typeof value2 === "object" && value2 !== null) {
|
|
328
|
-
if (cache.has(value2)) return `[Circular *]`;
|
|
329
|
-
cache.add(value2);
|
|
330
|
-
} else if (typeof value2 === "bigint") return value2.toString();
|
|
331
|
-
return value2;
|
|
332
|
-
}, indent);
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
//#endregion
|
|
336
|
-
//#region ../../node_modules/.pnpm/@prisma+driver-adapter-utils@7.4.2/node_modules/@prisma/driver-adapter-utils/dist/index.mjs
|
|
337
|
-
var DriverAdapterError = class extends Error {
|
|
338
|
-
name = "DriverAdapterError";
|
|
339
|
-
cause;
|
|
340
|
-
constructor(payload) {
|
|
341
|
-
super(typeof payload["message"] === "string" ? payload["message"] : payload.kind);
|
|
342
|
-
this.cause = payload;
|
|
343
|
-
}
|
|
344
|
-
};
|
|
345
|
-
var debug$1 = Debug("driver-adapter-utils");
|
|
346
|
-
var ColumnTypeEnum = {
|
|
347
|
-
Int32: 0,
|
|
348
|
-
Int64: 1,
|
|
349
|
-
Float: 2,
|
|
350
|
-
Double: 3,
|
|
351
|
-
Numeric: 4,
|
|
352
|
-
Boolean: 5,
|
|
353
|
-
Character: 6,
|
|
354
|
-
Text: 7,
|
|
355
|
-
Date: 8,
|
|
356
|
-
Time: 9,
|
|
357
|
-
DateTime: 10,
|
|
358
|
-
Json: 11,
|
|
359
|
-
Enum: 12,
|
|
360
|
-
Bytes: 13,
|
|
361
|
-
Set: 14,
|
|
362
|
-
Uuid: 15,
|
|
363
|
-
Int32Array: 64,
|
|
364
|
-
Int64Array: 65,
|
|
365
|
-
FloatArray: 66,
|
|
366
|
-
DoubleArray: 67,
|
|
367
|
-
NumericArray: 68,
|
|
368
|
-
BooleanArray: 69,
|
|
369
|
-
CharacterArray: 70,
|
|
370
|
-
TextArray: 71,
|
|
371
|
-
DateArray: 72,
|
|
372
|
-
TimeArray: 73,
|
|
373
|
-
DateTimeArray: 74,
|
|
374
|
-
JsonArray: 75,
|
|
375
|
-
EnumArray: 76,
|
|
376
|
-
BytesArray: 77,
|
|
377
|
-
UuidArray: 78,
|
|
378
|
-
UnknownNumber: 128
|
|
379
|
-
};
|
|
380
|
-
|
|
381
107
|
//#endregion
|
|
382
108
|
//#region ../../node_modules/.pnpm/postgres-array@2.0.0/node_modules/postgres-array/index.js
|
|
383
|
-
var require_postgres_array
|
|
109
|
+
var require_postgres_array = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm/postgres-array@2.0.0/node_modules/postgres-array/index.js": ((exports) => {
|
|
384
110
|
exports.parse = function(source, transform$1) {
|
|
385
111
|
return new ArrayParser(source, transform$1).parse();
|
|
386
112
|
};
|
|
@@ -461,7 +187,7 @@ var require_postgres_array$1 = /* @__PURE__ */ __commonJS({ "../../node_modules/
|
|
|
461
187
|
//#endregion
|
|
462
188
|
//#region ../../node_modules/.pnpm/pg-types@2.2.0/node_modules/pg-types/lib/arrayParser.js
|
|
463
189
|
var require_arrayParser = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm/pg-types@2.2.0/node_modules/pg-types/lib/arrayParser.js": ((exports, module) => {
|
|
464
|
-
var array$1 = require_postgres_array
|
|
190
|
+
var array$1 = require_postgres_array();
|
|
465
191
|
module.exports = { create: function(source, transform$1) {
|
|
466
192
|
return { parse: function() {
|
|
467
193
|
return array$1.parse(source, transform$1);
|
|
@@ -549,9 +275,9 @@ var require_mutable = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm/xte
|
|
|
549
275
|
var require_postgres_interval = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm/postgres-interval@1.2.0/node_modules/postgres-interval/index.js": ((exports, module) => {
|
|
550
276
|
var extend = require_mutable();
|
|
551
277
|
module.exports = PostgresInterval;
|
|
552
|
-
function PostgresInterval(raw
|
|
553
|
-
if (!(this instanceof PostgresInterval)) return new PostgresInterval(raw
|
|
554
|
-
extend(this, parse$5(raw
|
|
278
|
+
function PostgresInterval(raw) {
|
|
279
|
+
if (!(this instanceof PostgresInterval)) return new PostgresInterval(raw);
|
|
280
|
+
extend(this, parse$5(raw));
|
|
555
281
|
}
|
|
556
282
|
var properties = [
|
|
557
283
|
"seconds",
|
|
@@ -673,7 +399,7 @@ var require_postgres_bytea = /* @__PURE__ */ __commonJS({ "../../node_modules/.p
|
|
|
673
399
|
//#endregion
|
|
674
400
|
//#region ../../node_modules/.pnpm/pg-types@2.2.0/node_modules/pg-types/lib/textParsers.js
|
|
675
401
|
var require_textParsers = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm/pg-types@2.2.0/node_modules/pg-types/lib/textParsers.js": ((exports, module) => {
|
|
676
|
-
var array = require_postgres_array
|
|
402
|
+
var array = require_postgres_array();
|
|
677
403
|
var arrayParser$1 = require_arrayParser();
|
|
678
404
|
var parseDate$1 = require_postgres_date();
|
|
679
405
|
var parseInterval = require_postgres_interval();
|
|
@@ -981,13 +707,13 @@ var require_binaryParsers = /* @__PURE__ */ __commonJS({ "../../node_modules/.pn
|
|
|
981
707
|
};
|
|
982
708
|
return result;
|
|
983
709
|
};
|
|
984
|
-
var parseArray
|
|
985
|
-
var dim
|
|
710
|
+
var parseArray = function(value) {
|
|
711
|
+
var dim = parseBits(value, 32);
|
|
986
712
|
parseBits(value, 32, 32);
|
|
987
713
|
var elementType = parseBits(value, 32, 64);
|
|
988
714
|
var offset = 96;
|
|
989
715
|
var dims = [];
|
|
990
|
-
for (var i = 0; i < dim
|
|
716
|
+
for (var i = 0; i < dim; i++) {
|
|
991
717
|
dims[i] = parseBits(value, 32, offset);
|
|
992
718
|
offset += 32;
|
|
993
719
|
offset += 32;
|
|
@@ -1036,11 +762,11 @@ var require_binaryParsers = /* @__PURE__ */ __commonJS({ "../../node_modules/.pn
|
|
|
1036
762
|
register(16, parseBool);
|
|
1037
763
|
register(1114, parseDate.bind(null, false));
|
|
1038
764
|
register(1184, parseDate.bind(null, true));
|
|
1039
|
-
register(1e3, parseArray
|
|
1040
|
-
register(1007, parseArray
|
|
1041
|
-
register(1016, parseArray
|
|
1042
|
-
register(1008, parseArray
|
|
1043
|
-
register(1009, parseArray
|
|
765
|
+
register(1e3, parseArray);
|
|
766
|
+
register(1007, parseArray);
|
|
767
|
+
register(1016, parseArray);
|
|
768
|
+
register(1008, parseArray);
|
|
769
|
+
register(1009, parseArray);
|
|
1044
770
|
register(25, parseText);
|
|
1045
771
|
};
|
|
1046
772
|
module.exports = { init };
|
|
@@ -1130,7 +856,7 @@ var require_pg_types = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm/pg
|
|
|
1130
856
|
var binaryParsers = require_binaryParsers();
|
|
1131
857
|
var arrayParser = require_arrayParser();
|
|
1132
858
|
var builtinTypes = require_builtins();
|
|
1133
|
-
exports.getTypeParser = getTypeParser
|
|
859
|
+
exports.getTypeParser = getTypeParser;
|
|
1134
860
|
exports.setTypeParser = setTypeParser;
|
|
1135
861
|
exports.arrayParser = arrayParser;
|
|
1136
862
|
exports.builtins = builtinTypes;
|
|
@@ -1141,7 +867,7 @@ var require_pg_types = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm/pg
|
|
|
1141
867
|
function noParse(val$1) {
|
|
1142
868
|
return String(val$1);
|
|
1143
869
|
}
|
|
1144
|
-
function getTypeParser
|
|
870
|
+
function getTypeParser(oid, format) {
|
|
1145
871
|
format = format || "text";
|
|
1146
872
|
if (!typeParsers[format]) return noParse;
|
|
1147
873
|
return typeParsers[format][oid] || noParse;
|
|
@@ -1663,9 +1389,9 @@ var require_sasl = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm/pg@8.2
|
|
|
1663
1389
|
//#endregion
|
|
1664
1390
|
//#region ../../node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/type-overrides.js
|
|
1665
1391
|
var require_type_overrides = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/type-overrides.js": ((exports, module) => {
|
|
1666
|
-
const types$
|
|
1392
|
+
const types$2 = require_pg_types();
|
|
1667
1393
|
function TypeOverrides$4(userTypes) {
|
|
1668
|
-
this._types = userTypes || types$
|
|
1394
|
+
this._types = userTypes || types$2;
|
|
1669
1395
|
this.text = {};
|
|
1670
1396
|
this.binary = {};
|
|
1671
1397
|
}
|
|
@@ -1917,17 +1643,17 @@ var require_connection_parameters = /* @__PURE__ */ __commonJS({ "../../node_mod
|
|
|
1917
1643
|
//#endregion
|
|
1918
1644
|
//#region ../../node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/result.js
|
|
1919
1645
|
var require_result = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/result.js": ((exports, module) => {
|
|
1920
|
-
const types$
|
|
1646
|
+
const types$1 = require_pg_types();
|
|
1921
1647
|
const matchRegexp = /^([A-Za-z]+)(?: (\d+))?(?: (\d+))?/;
|
|
1922
1648
|
var Result$3 = class {
|
|
1923
|
-
constructor(rowMode, types$
|
|
1649
|
+
constructor(rowMode, types$3) {
|
|
1924
1650
|
this.command = null;
|
|
1925
1651
|
this.rowCount = null;
|
|
1926
1652
|
this.oid = null;
|
|
1927
1653
|
this.rows = [];
|
|
1928
1654
|
this.fields = [];
|
|
1929
1655
|
this._parsers = void 0;
|
|
1930
|
-
this._types = types$
|
|
1656
|
+
this._types = types$3;
|
|
1931
1657
|
this.RowCtor = null;
|
|
1932
1658
|
this.rowAsArray = rowMode === "array";
|
|
1933
1659
|
if (this.rowAsArray) this.parseRow = this._parseRowAsArray;
|
|
@@ -1977,7 +1703,7 @@ var require_result = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm/pg@8
|
|
|
1977
1703
|
const desc = fieldDescriptions[i];
|
|
1978
1704
|
row[desc.name] = null;
|
|
1979
1705
|
if (this._types) this._parsers[i] = this._types.getTypeParser(desc.dataTypeID, desc.format || "text");
|
|
1980
|
-
else this._parsers[i] = types$
|
|
1706
|
+
else this._parsers[i] = types$1.getTypeParser(desc.dataTypeID, desc.format || "text");
|
|
1981
1707
|
}
|
|
1982
1708
|
this._prebuiltEmptyResultObject = { ...row };
|
|
1983
1709
|
}
|
|
@@ -2168,10 +1894,10 @@ var require_messages = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm/pg
|
|
|
2168
1894
|
length: 4
|
|
2169
1895
|
};
|
|
2170
1896
|
var DatabaseError$2 = class extends Error {
|
|
2171
|
-
constructor(message, length, name
|
|
1897
|
+
constructor(message, length, name) {
|
|
2172
1898
|
super(message);
|
|
2173
1899
|
this.length = length;
|
|
2174
|
-
this.name = name
|
|
1900
|
+
this.name = name;
|
|
2175
1901
|
}
|
|
2176
1902
|
};
|
|
2177
1903
|
exports.DatabaseError = DatabaseError$2;
|
|
@@ -2184,17 +1910,17 @@ var require_messages = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm/pg
|
|
|
2184
1910
|
};
|
|
2185
1911
|
exports.CopyDataMessage = CopyDataMessage;
|
|
2186
1912
|
var CopyResponse = class {
|
|
2187
|
-
constructor(length, name
|
|
1913
|
+
constructor(length, name, binary, columnCount) {
|
|
2188
1914
|
this.length = length;
|
|
2189
|
-
this.name = name
|
|
1915
|
+
this.name = name;
|
|
2190
1916
|
this.binary = binary;
|
|
2191
1917
|
this.columnTypes = new Array(columnCount);
|
|
2192
1918
|
}
|
|
2193
1919
|
};
|
|
2194
1920
|
exports.CopyResponse = CopyResponse;
|
|
2195
1921
|
var Field = class {
|
|
2196
|
-
constructor(name
|
|
2197
|
-
this.name = name
|
|
1922
|
+
constructor(name, tableID, columnID, dataTypeID, dataTypeSize, dataTypeModifier, format) {
|
|
1923
|
+
this.name = name;
|
|
2198
1924
|
this.tableID = tableID;
|
|
2199
1925
|
this.columnID = columnID;
|
|
2200
1926
|
this.dataTypeID = dataTypeID;
|
|
@@ -2406,16 +2132,16 @@ var require_serializer = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm/
|
|
|
2406
2132
|
};
|
|
2407
2133
|
const emptyArray = [];
|
|
2408
2134
|
const parse$2 = (query$1) => {
|
|
2409
|
-
const name
|
|
2410
|
-
if (name
|
|
2135
|
+
const name = query$1.name || "";
|
|
2136
|
+
if (name.length > 63) {
|
|
2411
2137
|
console.error("Warning! Postgres only supports 63 characters for query names.");
|
|
2412
|
-
console.error("You supplied %s (%s)", name
|
|
2138
|
+
console.error("You supplied %s (%s)", name, name.length);
|
|
2413
2139
|
console.error("This can cause conflicts and silent errors executing queries");
|
|
2414
2140
|
}
|
|
2415
|
-
const types$
|
|
2416
|
-
const len = types$
|
|
2417
|
-
const buffer = writer.addCString(name
|
|
2418
|
-
for (let i = 0; i < len; i++) buffer.addInt32(types$
|
|
2141
|
+
const types$3 = query$1.types || emptyArray;
|
|
2142
|
+
const len = types$3.length;
|
|
2143
|
+
const buffer = writer.addCString(name).addCString(query$1.text).addInt16(len);
|
|
2144
|
+
for (let i = 0; i < len; i++) buffer.addInt32(types$3[i]);
|
|
2419
2145
|
return writer.flush(80);
|
|
2420
2146
|
};
|
|
2421
2147
|
const paramWriter = new buffer_writer_1.Writer();
|
|
@@ -2777,14 +2503,14 @@ var require_parser = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm/pg-p
|
|
|
2777
2503
|
return message;
|
|
2778
2504
|
};
|
|
2779
2505
|
const parseField = (reader) => {
|
|
2780
|
-
const name
|
|
2506
|
+
const name = reader.cstring();
|
|
2781
2507
|
const tableID = reader.uint32();
|
|
2782
2508
|
const columnID = reader.int16();
|
|
2783
2509
|
const dataTypeID = reader.uint32();
|
|
2784
2510
|
const dataTypeSize = reader.int16();
|
|
2785
2511
|
const dataTypeModifier = reader.int32();
|
|
2786
2512
|
const mode = reader.int16() === 0 ? "text" : "binary";
|
|
2787
|
-
return new messages_1$1.Field(name
|
|
2513
|
+
return new messages_1$1.Field(name, tableID, columnID, dataTypeID, dataTypeSize, dataTypeModifier, mode);
|
|
2788
2514
|
};
|
|
2789
2515
|
const parseParameterDescriptionMessage = (reader) => {
|
|
2790
2516
|
const parameterCount = reader.int16();
|
|
@@ -2802,9 +2528,9 @@ var require_parser = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm/pg-p
|
|
|
2802
2528
|
return new messages_1$1.DataRowMessage(LATEINIT_LENGTH, fields);
|
|
2803
2529
|
};
|
|
2804
2530
|
const parseParameterStatusMessage = (reader) => {
|
|
2805
|
-
const name
|
|
2531
|
+
const name = reader.cstring();
|
|
2806
2532
|
const value = reader.cstring();
|
|
2807
|
-
return new messages_1$1.ParameterStatusMessage(LATEINIT_LENGTH, name
|
|
2533
|
+
return new messages_1$1.ParameterStatusMessage(LATEINIT_LENGTH, name, value);
|
|
2808
2534
|
};
|
|
2809
2535
|
const parseBackendKeyData = (reader) => {
|
|
2810
2536
|
const processID = reader.int32();
|
|
@@ -2852,7 +2578,7 @@ var require_parser = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm/pg-p
|
|
|
2852
2578
|
}
|
|
2853
2579
|
return message;
|
|
2854
2580
|
};
|
|
2855
|
-
const parseErrorMessage = (reader, name
|
|
2581
|
+
const parseErrorMessage = (reader, name) => {
|
|
2856
2582
|
const fields = {};
|
|
2857
2583
|
let fieldType = reader.string(1);
|
|
2858
2584
|
while (fieldType !== "\0") {
|
|
@@ -2860,7 +2586,7 @@ var require_parser = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm/pg-p
|
|
|
2860
2586
|
fieldType = reader.string(1);
|
|
2861
2587
|
}
|
|
2862
2588
|
const messageValue = fields.M;
|
|
2863
|
-
const message = name
|
|
2589
|
+
const message = name === "notice" ? new messages_1$1.NoticeMessage(LATEINIT_LENGTH, messageValue) : new messages_1$1.DatabaseError(messageValue, LATEINIT_LENGTH, name);
|
|
2864
2590
|
message.severity = fields.S;
|
|
2865
2591
|
message.code = fields.C;
|
|
2866
2592
|
message.detail = fields.D;
|
|
@@ -4620,7 +4346,7 @@ var import_lib = /* @__PURE__ */ __toESM(require_lib(), 1);
|
|
|
4620
4346
|
const Client = import_lib.default.Client;
|
|
4621
4347
|
const Pool = import_lib.default.Pool;
|
|
4622
4348
|
const Connection = import_lib.default.Connection;
|
|
4623
|
-
const types
|
|
4349
|
+
const types = import_lib.default.types;
|
|
4624
4350
|
const Query = import_lib.default.Query;
|
|
4625
4351
|
const DatabaseError = import_lib.default.DatabaseError;
|
|
4626
4352
|
const escapeIdentifier = import_lib.default.escapeIdentifier;
|
|
@@ -4630,764 +4356,6 @@ const TypeOverrides = import_lib.default.TypeOverrides;
|
|
|
4630
4356
|
const defaults = import_lib.default.defaults;
|
|
4631
4357
|
var esm_default = import_lib.default;
|
|
4632
4358
|
|
|
4633
|
-
//#endregion
|
|
4634
|
-
//#region ../../node_modules/.pnpm/postgres-array@3.0.4/node_modules/postgres-array/index.js
|
|
4635
|
-
var require_postgres_array = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm/postgres-array@3.0.4/node_modules/postgres-array/index.js": ((exports) => {
|
|
4636
|
-
const BACKSLASH = "\\";
|
|
4637
|
-
const DQUOT = "\"";
|
|
4638
|
-
const LBRACE = "{";
|
|
4639
|
-
const RBRACE = "}";
|
|
4640
|
-
const LBRACKET = "[";
|
|
4641
|
-
const EQUALS = "=";
|
|
4642
|
-
const COMMA = ",";
|
|
4643
|
-
/** When the raw value is this, it means a literal `null` */
|
|
4644
|
-
const NULL_STRING = "NULL";
|
|
4645
|
-
/**
|
|
4646
|
-
* Parses an array according to
|
|
4647
|
-
* https://www.postgresql.org/docs/17/arrays.html#ARRAYS-IO
|
|
4648
|
-
*
|
|
4649
|
-
* Trusts the data (mostly), so only hook up to trusted Postgres servers.
|
|
4650
|
-
*/
|
|
4651
|
-
function makeParseArrayWithTransform(transform$1) {
|
|
4652
|
-
const haveTransform = transform$1 != null;
|
|
4653
|
-
return function parseArray$3(str) {
|
|
4654
|
-
const rbraceIndex = str.length - 1;
|
|
4655
|
-
if (rbraceIndex === 1) return [];
|
|
4656
|
-
if (str[rbraceIndex] !== RBRACE) throw new Error("Invalid array text - must end with }");
|
|
4657
|
-
let position = 0;
|
|
4658
|
-
if (str[position] === LBRACKET) position = str.indexOf(EQUALS) + 1;
|
|
4659
|
-
if (str[position++] !== LBRACE) throw new Error("Invalid array text - must start with {");
|
|
4660
|
-
const output = [];
|
|
4661
|
-
let current = output;
|
|
4662
|
-
const stack = [];
|
|
4663
|
-
let currentStringStart = position;
|
|
4664
|
-
let currentString = "";
|
|
4665
|
-
let expectValue = true;
|
|
4666
|
-
for (; position < rbraceIndex; ++position) {
|
|
4667
|
-
let char = str[position];
|
|
4668
|
-
if (char === DQUOT) {
|
|
4669
|
-
currentStringStart = ++position;
|
|
4670
|
-
let dquot = str.indexOf(DQUOT, currentStringStart);
|
|
4671
|
-
let backSlash = str.indexOf(BACKSLASH, currentStringStart);
|
|
4672
|
-
while (backSlash !== -1 && backSlash < dquot) {
|
|
4673
|
-
position = backSlash;
|
|
4674
|
-
const part$1 = str.slice(currentStringStart, position);
|
|
4675
|
-
currentString += part$1;
|
|
4676
|
-
currentStringStart = ++position;
|
|
4677
|
-
if (dquot === position++) dquot = str.indexOf(DQUOT, position);
|
|
4678
|
-
backSlash = str.indexOf(BACKSLASH, position);
|
|
4679
|
-
}
|
|
4680
|
-
position = dquot;
|
|
4681
|
-
const part = str.slice(currentStringStart, position);
|
|
4682
|
-
currentString += part;
|
|
4683
|
-
current.push(haveTransform ? transform$1(currentString) : currentString);
|
|
4684
|
-
currentString = "";
|
|
4685
|
-
expectValue = false;
|
|
4686
|
-
} else if (char === LBRACE) {
|
|
4687
|
-
const newArray = [];
|
|
4688
|
-
current.push(newArray);
|
|
4689
|
-
stack.push(current);
|
|
4690
|
-
current = newArray;
|
|
4691
|
-
currentStringStart = position + 1;
|
|
4692
|
-
expectValue = true;
|
|
4693
|
-
} else if (char === COMMA) expectValue = true;
|
|
4694
|
-
else if (char === RBRACE) {
|
|
4695
|
-
expectValue = false;
|
|
4696
|
-
const arr = stack.pop();
|
|
4697
|
-
if (arr === void 0) throw new Error("Invalid array text - too many '}'");
|
|
4698
|
-
current = arr;
|
|
4699
|
-
} else if (expectValue) {
|
|
4700
|
-
currentStringStart = position;
|
|
4701
|
-
while ((char = str[position]) !== COMMA && char !== RBRACE && position < rbraceIndex) ++position;
|
|
4702
|
-
const part = str.slice(currentStringStart, position--);
|
|
4703
|
-
current.push(part === NULL_STRING ? null : haveTransform ? transform$1(part) : part);
|
|
4704
|
-
expectValue = false;
|
|
4705
|
-
} else throw new Error("Was expecting delimeter");
|
|
4706
|
-
}
|
|
4707
|
-
return output;
|
|
4708
|
-
};
|
|
4709
|
-
}
|
|
4710
|
-
const parseArray$1 = makeParseArrayWithTransform();
|
|
4711
|
-
exports.parse = (source, transform$1) => transform$1 != null ? makeParseArrayWithTransform(transform$1)(source) : parseArray$1(source);
|
|
4712
|
-
}) });
|
|
4713
|
-
|
|
4714
|
-
//#endregion
|
|
4715
|
-
//#region ../../node_modules/.pnpm/@prisma+adapter-pg@7.4.2/node_modules/@prisma/adapter-pg/dist/index.mjs
|
|
4716
|
-
var import_postgres_array = /* @__PURE__ */ __toESM(require_postgres_array(), 1);
|
|
4717
|
-
var name = "@prisma/adapter-pg";
|
|
4718
|
-
var FIRST_NORMAL_OBJECT_ID = 16384;
|
|
4719
|
-
var { types } = esm_default;
|
|
4720
|
-
var { builtins: ScalarColumnType, getTypeParser } = types;
|
|
4721
|
-
var AdditionalScalarColumnType = { NAME: 19 };
|
|
4722
|
-
var ArrayColumnType = {
|
|
4723
|
-
BIT_ARRAY: 1561,
|
|
4724
|
-
BOOL_ARRAY: 1e3,
|
|
4725
|
-
BYTEA_ARRAY: 1001,
|
|
4726
|
-
BPCHAR_ARRAY: 1014,
|
|
4727
|
-
CHAR_ARRAY: 1002,
|
|
4728
|
-
CIDR_ARRAY: 651,
|
|
4729
|
-
DATE_ARRAY: 1182,
|
|
4730
|
-
FLOAT4_ARRAY: 1021,
|
|
4731
|
-
FLOAT8_ARRAY: 1022,
|
|
4732
|
-
INET_ARRAY: 1041,
|
|
4733
|
-
INT2_ARRAY: 1005,
|
|
4734
|
-
INT4_ARRAY: 1007,
|
|
4735
|
-
INT8_ARRAY: 1016,
|
|
4736
|
-
JSONB_ARRAY: 3807,
|
|
4737
|
-
JSON_ARRAY: 199,
|
|
4738
|
-
MONEY_ARRAY: 791,
|
|
4739
|
-
NUMERIC_ARRAY: 1231,
|
|
4740
|
-
OID_ARRAY: 1028,
|
|
4741
|
-
TEXT_ARRAY: 1009,
|
|
4742
|
-
TIMESTAMP_ARRAY: 1115,
|
|
4743
|
-
TIMESTAMPTZ_ARRAY: 1185,
|
|
4744
|
-
TIME_ARRAY: 1183,
|
|
4745
|
-
UUID_ARRAY: 2951,
|
|
4746
|
-
VARBIT_ARRAY: 1563,
|
|
4747
|
-
VARCHAR_ARRAY: 1015,
|
|
4748
|
-
XML_ARRAY: 143
|
|
4749
|
-
};
|
|
4750
|
-
var UnsupportedNativeDataType = class _UnsupportedNativeDataType extends Error {
|
|
4751
|
-
static typeNames = {
|
|
4752
|
-
16: "bool",
|
|
4753
|
-
17: "bytea",
|
|
4754
|
-
18: "char",
|
|
4755
|
-
19: "name",
|
|
4756
|
-
20: "int8",
|
|
4757
|
-
21: "int2",
|
|
4758
|
-
22: "int2vector",
|
|
4759
|
-
23: "int4",
|
|
4760
|
-
24: "regproc",
|
|
4761
|
-
25: "text",
|
|
4762
|
-
26: "oid",
|
|
4763
|
-
27: "tid",
|
|
4764
|
-
28: "xid",
|
|
4765
|
-
29: "cid",
|
|
4766
|
-
30: "oidvector",
|
|
4767
|
-
32: "pg_ddl_command",
|
|
4768
|
-
71: "pg_type",
|
|
4769
|
-
75: "pg_attribute",
|
|
4770
|
-
81: "pg_proc",
|
|
4771
|
-
83: "pg_class",
|
|
4772
|
-
114: "json",
|
|
4773
|
-
142: "xml",
|
|
4774
|
-
194: "pg_node_tree",
|
|
4775
|
-
269: "table_am_handler",
|
|
4776
|
-
325: "index_am_handler",
|
|
4777
|
-
600: "point",
|
|
4778
|
-
601: "lseg",
|
|
4779
|
-
602: "path",
|
|
4780
|
-
603: "box",
|
|
4781
|
-
604: "polygon",
|
|
4782
|
-
628: "line",
|
|
4783
|
-
650: "cidr",
|
|
4784
|
-
700: "float4",
|
|
4785
|
-
701: "float8",
|
|
4786
|
-
705: "unknown",
|
|
4787
|
-
718: "circle",
|
|
4788
|
-
774: "macaddr8",
|
|
4789
|
-
790: "money",
|
|
4790
|
-
829: "macaddr",
|
|
4791
|
-
869: "inet",
|
|
4792
|
-
1033: "aclitem",
|
|
4793
|
-
1042: "bpchar",
|
|
4794
|
-
1043: "varchar",
|
|
4795
|
-
1082: "date",
|
|
4796
|
-
1083: "time",
|
|
4797
|
-
1114: "timestamp",
|
|
4798
|
-
1184: "timestamptz",
|
|
4799
|
-
1186: "interval",
|
|
4800
|
-
1266: "timetz",
|
|
4801
|
-
1560: "bit",
|
|
4802
|
-
1562: "varbit",
|
|
4803
|
-
1700: "numeric",
|
|
4804
|
-
1790: "refcursor",
|
|
4805
|
-
2202: "regprocedure",
|
|
4806
|
-
2203: "regoper",
|
|
4807
|
-
2204: "regoperator",
|
|
4808
|
-
2205: "regclass",
|
|
4809
|
-
2206: "regtype",
|
|
4810
|
-
2249: "record",
|
|
4811
|
-
2275: "cstring",
|
|
4812
|
-
2276: "any",
|
|
4813
|
-
2277: "anyarray",
|
|
4814
|
-
2278: "void",
|
|
4815
|
-
2279: "trigger",
|
|
4816
|
-
2280: "language_handler",
|
|
4817
|
-
2281: "internal",
|
|
4818
|
-
2283: "anyelement",
|
|
4819
|
-
2287: "_record",
|
|
4820
|
-
2776: "anynonarray",
|
|
4821
|
-
2950: "uuid",
|
|
4822
|
-
2970: "txid_snapshot",
|
|
4823
|
-
3115: "fdw_handler",
|
|
4824
|
-
3220: "pg_lsn",
|
|
4825
|
-
3310: "tsm_handler",
|
|
4826
|
-
3361: "pg_ndistinct",
|
|
4827
|
-
3402: "pg_dependencies",
|
|
4828
|
-
3500: "anyenum",
|
|
4829
|
-
3614: "tsvector",
|
|
4830
|
-
3615: "tsquery",
|
|
4831
|
-
3642: "gtsvector",
|
|
4832
|
-
3734: "regconfig",
|
|
4833
|
-
3769: "regdictionary",
|
|
4834
|
-
3802: "jsonb",
|
|
4835
|
-
3831: "anyrange",
|
|
4836
|
-
3838: "event_trigger",
|
|
4837
|
-
3904: "int4range",
|
|
4838
|
-
3906: "numrange",
|
|
4839
|
-
3908: "tsrange",
|
|
4840
|
-
3910: "tstzrange",
|
|
4841
|
-
3912: "daterange",
|
|
4842
|
-
3926: "int8range",
|
|
4843
|
-
4072: "jsonpath",
|
|
4844
|
-
4089: "regnamespace",
|
|
4845
|
-
4096: "regrole",
|
|
4846
|
-
4191: "regcollation",
|
|
4847
|
-
4451: "int4multirange",
|
|
4848
|
-
4532: "nummultirange",
|
|
4849
|
-
4533: "tsmultirange",
|
|
4850
|
-
4534: "tstzmultirange",
|
|
4851
|
-
4535: "datemultirange",
|
|
4852
|
-
4536: "int8multirange",
|
|
4853
|
-
4537: "anymultirange",
|
|
4854
|
-
4538: "anycompatiblemultirange",
|
|
4855
|
-
4600: "pg_brin_bloom_summary",
|
|
4856
|
-
4601: "pg_brin_minmax_multi_summary",
|
|
4857
|
-
5017: "pg_mcv_list",
|
|
4858
|
-
5038: "pg_snapshot",
|
|
4859
|
-
5069: "xid8",
|
|
4860
|
-
5077: "anycompatible",
|
|
4861
|
-
5078: "anycompatiblearray",
|
|
4862
|
-
5079: "anycompatiblenonarray",
|
|
4863
|
-
5080: "anycompatiblerange"
|
|
4864
|
-
};
|
|
4865
|
-
type;
|
|
4866
|
-
constructor(code) {
|
|
4867
|
-
super();
|
|
4868
|
-
this.type = _UnsupportedNativeDataType.typeNames[code] || "Unknown";
|
|
4869
|
-
this.message = `Unsupported column type ${this.type}`;
|
|
4870
|
-
}
|
|
4871
|
-
};
|
|
4872
|
-
function fieldToColumnType(fieldTypeId) {
|
|
4873
|
-
switch (fieldTypeId) {
|
|
4874
|
-
case ScalarColumnType.INT2:
|
|
4875
|
-
case ScalarColumnType.INT4: return ColumnTypeEnum.Int32;
|
|
4876
|
-
case ScalarColumnType.INT8: return ColumnTypeEnum.Int64;
|
|
4877
|
-
case ScalarColumnType.FLOAT4: return ColumnTypeEnum.Float;
|
|
4878
|
-
case ScalarColumnType.FLOAT8: return ColumnTypeEnum.Double;
|
|
4879
|
-
case ScalarColumnType.BOOL: return ColumnTypeEnum.Boolean;
|
|
4880
|
-
case ScalarColumnType.DATE: return ColumnTypeEnum.Date;
|
|
4881
|
-
case ScalarColumnType.TIME:
|
|
4882
|
-
case ScalarColumnType.TIMETZ: return ColumnTypeEnum.Time;
|
|
4883
|
-
case ScalarColumnType.TIMESTAMP:
|
|
4884
|
-
case ScalarColumnType.TIMESTAMPTZ: return ColumnTypeEnum.DateTime;
|
|
4885
|
-
case ScalarColumnType.NUMERIC:
|
|
4886
|
-
case ScalarColumnType.MONEY: return ColumnTypeEnum.Numeric;
|
|
4887
|
-
case ScalarColumnType.JSON:
|
|
4888
|
-
case ScalarColumnType.JSONB: return ColumnTypeEnum.Json;
|
|
4889
|
-
case ScalarColumnType.UUID: return ColumnTypeEnum.Uuid;
|
|
4890
|
-
case ScalarColumnType.OID: return ColumnTypeEnum.Int64;
|
|
4891
|
-
case ScalarColumnType.BPCHAR:
|
|
4892
|
-
case ScalarColumnType.TEXT:
|
|
4893
|
-
case ScalarColumnType.VARCHAR:
|
|
4894
|
-
case ScalarColumnType.BIT:
|
|
4895
|
-
case ScalarColumnType.VARBIT:
|
|
4896
|
-
case ScalarColumnType.INET:
|
|
4897
|
-
case ScalarColumnType.CIDR:
|
|
4898
|
-
case ScalarColumnType.XML:
|
|
4899
|
-
case AdditionalScalarColumnType.NAME: return ColumnTypeEnum.Text;
|
|
4900
|
-
case ScalarColumnType.BYTEA: return ColumnTypeEnum.Bytes;
|
|
4901
|
-
case ArrayColumnType.INT2_ARRAY:
|
|
4902
|
-
case ArrayColumnType.INT4_ARRAY: return ColumnTypeEnum.Int32Array;
|
|
4903
|
-
case ArrayColumnType.FLOAT4_ARRAY: return ColumnTypeEnum.FloatArray;
|
|
4904
|
-
case ArrayColumnType.FLOAT8_ARRAY: return ColumnTypeEnum.DoubleArray;
|
|
4905
|
-
case ArrayColumnType.NUMERIC_ARRAY:
|
|
4906
|
-
case ArrayColumnType.MONEY_ARRAY: return ColumnTypeEnum.NumericArray;
|
|
4907
|
-
case ArrayColumnType.BOOL_ARRAY: return ColumnTypeEnum.BooleanArray;
|
|
4908
|
-
case ArrayColumnType.CHAR_ARRAY: return ColumnTypeEnum.CharacterArray;
|
|
4909
|
-
case ArrayColumnType.BPCHAR_ARRAY:
|
|
4910
|
-
case ArrayColumnType.TEXT_ARRAY:
|
|
4911
|
-
case ArrayColumnType.VARCHAR_ARRAY:
|
|
4912
|
-
case ArrayColumnType.VARBIT_ARRAY:
|
|
4913
|
-
case ArrayColumnType.BIT_ARRAY:
|
|
4914
|
-
case ArrayColumnType.INET_ARRAY:
|
|
4915
|
-
case ArrayColumnType.CIDR_ARRAY:
|
|
4916
|
-
case ArrayColumnType.XML_ARRAY: return ColumnTypeEnum.TextArray;
|
|
4917
|
-
case ArrayColumnType.DATE_ARRAY: return ColumnTypeEnum.DateArray;
|
|
4918
|
-
case ArrayColumnType.TIME_ARRAY: return ColumnTypeEnum.TimeArray;
|
|
4919
|
-
case ArrayColumnType.TIMESTAMP_ARRAY: return ColumnTypeEnum.DateTimeArray;
|
|
4920
|
-
case ArrayColumnType.TIMESTAMPTZ_ARRAY: return ColumnTypeEnum.DateTimeArray;
|
|
4921
|
-
case ArrayColumnType.JSON_ARRAY:
|
|
4922
|
-
case ArrayColumnType.JSONB_ARRAY: return ColumnTypeEnum.JsonArray;
|
|
4923
|
-
case ArrayColumnType.BYTEA_ARRAY: return ColumnTypeEnum.BytesArray;
|
|
4924
|
-
case ArrayColumnType.UUID_ARRAY: return ColumnTypeEnum.UuidArray;
|
|
4925
|
-
case ArrayColumnType.INT8_ARRAY:
|
|
4926
|
-
case ArrayColumnType.OID_ARRAY: return ColumnTypeEnum.Int64Array;
|
|
4927
|
-
default:
|
|
4928
|
-
if (fieldTypeId >= FIRST_NORMAL_OBJECT_ID) return ColumnTypeEnum.Text;
|
|
4929
|
-
throw new UnsupportedNativeDataType(fieldTypeId);
|
|
4930
|
-
}
|
|
4931
|
-
}
|
|
4932
|
-
function normalize_array(element_normalizer) {
|
|
4933
|
-
return (str) => (0, import_postgres_array.parse)(str, element_normalizer);
|
|
4934
|
-
}
|
|
4935
|
-
function normalize_numeric(numeric) {
|
|
4936
|
-
return numeric;
|
|
4937
|
-
}
|
|
4938
|
-
function normalize_date(date) {
|
|
4939
|
-
return date;
|
|
4940
|
-
}
|
|
4941
|
-
function normalize_timestamp(time) {
|
|
4942
|
-
return `${time.replace(" ", "T")}+00:00`;
|
|
4943
|
-
}
|
|
4944
|
-
function normalize_timestamptz(time) {
|
|
4945
|
-
return time.replace(" ", "T").replace(/[+-]\d{2}(:\d{2})?$/, "+00:00");
|
|
4946
|
-
}
|
|
4947
|
-
function normalize_time(time) {
|
|
4948
|
-
return time;
|
|
4949
|
-
}
|
|
4950
|
-
function normalize_timez(time) {
|
|
4951
|
-
return time.replace(/[+-]\d{2}(:\d{2})?$/, "");
|
|
4952
|
-
}
|
|
4953
|
-
function normalize_money(money) {
|
|
4954
|
-
return money.slice(1);
|
|
4955
|
-
}
|
|
4956
|
-
function normalize_xml(xml) {
|
|
4957
|
-
return xml;
|
|
4958
|
-
}
|
|
4959
|
-
function toJson(json) {
|
|
4960
|
-
return json;
|
|
4961
|
-
}
|
|
4962
|
-
var parsePgBytes = getTypeParser(ScalarColumnType.BYTEA);
|
|
4963
|
-
var normalizeByteaArray = getTypeParser(ArrayColumnType.BYTEA_ARRAY);
|
|
4964
|
-
function convertBytes(serializedBytes) {
|
|
4965
|
-
return parsePgBytes(serializedBytes);
|
|
4966
|
-
}
|
|
4967
|
-
function normalizeBit(bit) {
|
|
4968
|
-
return bit;
|
|
4969
|
-
}
|
|
4970
|
-
var customParsers = {
|
|
4971
|
-
[ScalarColumnType.NUMERIC]: normalize_numeric,
|
|
4972
|
-
[ArrayColumnType.NUMERIC_ARRAY]: normalize_array(normalize_numeric),
|
|
4973
|
-
[ScalarColumnType.TIME]: normalize_time,
|
|
4974
|
-
[ArrayColumnType.TIME_ARRAY]: normalize_array(normalize_time),
|
|
4975
|
-
[ScalarColumnType.TIMETZ]: normalize_timez,
|
|
4976
|
-
[ScalarColumnType.DATE]: normalize_date,
|
|
4977
|
-
[ArrayColumnType.DATE_ARRAY]: normalize_array(normalize_date),
|
|
4978
|
-
[ScalarColumnType.TIMESTAMP]: normalize_timestamp,
|
|
4979
|
-
[ArrayColumnType.TIMESTAMP_ARRAY]: normalize_array(normalize_timestamp),
|
|
4980
|
-
[ScalarColumnType.TIMESTAMPTZ]: normalize_timestamptz,
|
|
4981
|
-
[ArrayColumnType.TIMESTAMPTZ_ARRAY]: normalize_array(normalize_timestamptz),
|
|
4982
|
-
[ScalarColumnType.MONEY]: normalize_money,
|
|
4983
|
-
[ArrayColumnType.MONEY_ARRAY]: normalize_array(normalize_money),
|
|
4984
|
-
[ScalarColumnType.JSON]: toJson,
|
|
4985
|
-
[ArrayColumnType.JSON_ARRAY]: normalize_array(toJson),
|
|
4986
|
-
[ScalarColumnType.JSONB]: toJson,
|
|
4987
|
-
[ArrayColumnType.JSONB_ARRAY]: normalize_array(toJson),
|
|
4988
|
-
[ScalarColumnType.BYTEA]: convertBytes,
|
|
4989
|
-
[ArrayColumnType.BYTEA_ARRAY]: normalizeByteaArray,
|
|
4990
|
-
[ArrayColumnType.BIT_ARRAY]: normalize_array(normalizeBit),
|
|
4991
|
-
[ArrayColumnType.VARBIT_ARRAY]: normalize_array(normalizeBit),
|
|
4992
|
-
[ArrayColumnType.XML_ARRAY]: normalize_array(normalize_xml)
|
|
4993
|
-
};
|
|
4994
|
-
function mapArg(arg, argType) {
|
|
4995
|
-
if (arg === null) return null;
|
|
4996
|
-
if (Array.isArray(arg) && argType.arity === "list") return arg.map((value) => mapArg(value, argType));
|
|
4997
|
-
if (typeof arg === "string" && argType.scalarType === "datetime") arg = new Date(arg);
|
|
4998
|
-
if (arg instanceof Date) switch (argType.dbType) {
|
|
4999
|
-
case "TIME":
|
|
5000
|
-
case "TIMETZ": return formatTime(arg);
|
|
5001
|
-
case "DATE": return formatDate(arg);
|
|
5002
|
-
default: return formatDateTime(arg);
|
|
5003
|
-
}
|
|
5004
|
-
if (typeof arg === "string" && argType.scalarType === "bytes") return Buffer.from(arg, "base64");
|
|
5005
|
-
if (ArrayBuffer.isView(arg)) return new Uint8Array(arg.buffer, arg.byteOffset, arg.byteLength);
|
|
5006
|
-
return arg;
|
|
5007
|
-
}
|
|
5008
|
-
function formatDateTime(date) {
|
|
5009
|
-
const pad = (n, z$1 = 2) => String(n).padStart(z$1, "0");
|
|
5010
|
-
const ms = date.getUTCMilliseconds();
|
|
5011
|
-
return pad(date.getUTCFullYear(), 4) + "-" + pad(date.getUTCMonth() + 1) + "-" + pad(date.getUTCDate()) + " " + pad(date.getUTCHours()) + ":" + pad(date.getUTCMinutes()) + ":" + pad(date.getUTCSeconds()) + (ms ? "." + String(ms).padStart(3, "0") : "");
|
|
5012
|
-
}
|
|
5013
|
-
function formatDate(date) {
|
|
5014
|
-
const pad = (n, z$1 = 2) => String(n).padStart(z$1, "0");
|
|
5015
|
-
return pad(date.getUTCFullYear(), 4) + "-" + pad(date.getUTCMonth() + 1) + "-" + pad(date.getUTCDate());
|
|
5016
|
-
}
|
|
5017
|
-
function formatTime(date) {
|
|
5018
|
-
const pad = (n, z$1 = 2) => String(n).padStart(z$1, "0");
|
|
5019
|
-
const ms = date.getUTCMilliseconds();
|
|
5020
|
-
return pad(date.getUTCHours()) + ":" + pad(date.getUTCMinutes()) + ":" + pad(date.getUTCSeconds()) + (ms ? "." + String(ms).padStart(3, "0") : "");
|
|
5021
|
-
}
|
|
5022
|
-
var TLS_ERRORS = /* @__PURE__ */ new Set([
|
|
5023
|
-
"UNABLE_TO_GET_ISSUER_CERT",
|
|
5024
|
-
"UNABLE_TO_GET_CRL",
|
|
5025
|
-
"UNABLE_TO_DECRYPT_CERT_SIGNATURE",
|
|
5026
|
-
"UNABLE_TO_DECRYPT_CRL_SIGNATURE",
|
|
5027
|
-
"UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY",
|
|
5028
|
-
"CERT_SIGNATURE_FAILURE",
|
|
5029
|
-
"CRL_SIGNATURE_FAILURE",
|
|
5030
|
-
"CERT_NOT_YET_VALID",
|
|
5031
|
-
"CERT_HAS_EXPIRED",
|
|
5032
|
-
"CRL_NOT_YET_VALID",
|
|
5033
|
-
"CRL_HAS_EXPIRED",
|
|
5034
|
-
"ERROR_IN_CERT_NOT_BEFORE_FIELD",
|
|
5035
|
-
"ERROR_IN_CERT_NOT_AFTER_FIELD",
|
|
5036
|
-
"ERROR_IN_CRL_LAST_UPDATE_FIELD",
|
|
5037
|
-
"ERROR_IN_CRL_NEXT_UPDATE_FIELD",
|
|
5038
|
-
"DEPTH_ZERO_SELF_SIGNED_CERT",
|
|
5039
|
-
"SELF_SIGNED_CERT_IN_CHAIN",
|
|
5040
|
-
"UNABLE_TO_GET_ISSUER_CERT_LOCALLY",
|
|
5041
|
-
"UNABLE_TO_VERIFY_LEAF_SIGNATURE",
|
|
5042
|
-
"CERT_CHAIN_TOO_LONG",
|
|
5043
|
-
"CERT_REVOKED",
|
|
5044
|
-
"INVALID_CA",
|
|
5045
|
-
"INVALID_PURPOSE",
|
|
5046
|
-
"CERT_UNTRUSTED",
|
|
5047
|
-
"CERT_REJECTED",
|
|
5048
|
-
"HOSTNAME_MISMATCH",
|
|
5049
|
-
"ERR_TLS_CERT_ALTNAME_FORMAT",
|
|
5050
|
-
"ERR_TLS_CERT_ALTNAME_INVALID"
|
|
5051
|
-
]);
|
|
5052
|
-
var SOCKET_ERRORS = /* @__PURE__ */ new Set([
|
|
5053
|
-
"ENOTFOUND",
|
|
5054
|
-
"ECONNREFUSED",
|
|
5055
|
-
"ECONNRESET",
|
|
5056
|
-
"ETIMEDOUT"
|
|
5057
|
-
]);
|
|
5058
|
-
function convertDriverError(error) {
|
|
5059
|
-
if (isSocketError(error)) return mapSocketError(error);
|
|
5060
|
-
if (isTlsError(error)) return {
|
|
5061
|
-
kind: "TlsConnectionError",
|
|
5062
|
-
reason: error.message
|
|
5063
|
-
};
|
|
5064
|
-
if (isDriverError(error)) return {
|
|
5065
|
-
originalCode: error.code,
|
|
5066
|
-
originalMessage: error.message,
|
|
5067
|
-
...mapDriverError(error)
|
|
5068
|
-
};
|
|
5069
|
-
throw error;
|
|
5070
|
-
}
|
|
5071
|
-
function mapDriverError(error) {
|
|
5072
|
-
switch (error.code) {
|
|
5073
|
-
case "22001": return {
|
|
5074
|
-
kind: "LengthMismatch",
|
|
5075
|
-
column: error.column
|
|
5076
|
-
};
|
|
5077
|
-
case "22003": return {
|
|
5078
|
-
kind: "ValueOutOfRange",
|
|
5079
|
-
cause: error.message
|
|
5080
|
-
};
|
|
5081
|
-
case "22P02": return {
|
|
5082
|
-
kind: "InvalidInputValue",
|
|
5083
|
-
message: error.message
|
|
5084
|
-
};
|
|
5085
|
-
case "23505": {
|
|
5086
|
-
var _error$detail;
|
|
5087
|
-
const fields = (_error$detail = error.detail) === null || _error$detail === void 0 || (_error$detail = _error$detail.match(/Key \(([^)]+)\)/)) === null || _error$detail === void 0 || (_error$detail = _error$detail.at(1)) === null || _error$detail === void 0 ? void 0 : _error$detail.split(", ");
|
|
5088
|
-
return {
|
|
5089
|
-
kind: "UniqueConstraintViolation",
|
|
5090
|
-
constraint: fields !== void 0 ? { fields } : void 0
|
|
5091
|
-
};
|
|
5092
|
-
}
|
|
5093
|
-
case "23502": {
|
|
5094
|
-
var _error$detail2;
|
|
5095
|
-
const fields = (_error$detail2 = error.detail) === null || _error$detail2 === void 0 || (_error$detail2 = _error$detail2.match(/Key \(([^)]+)\)/)) === null || _error$detail2 === void 0 || (_error$detail2 = _error$detail2.at(1)) === null || _error$detail2 === void 0 ? void 0 : _error$detail2.split(", ");
|
|
5096
|
-
return {
|
|
5097
|
-
kind: "NullConstraintViolation",
|
|
5098
|
-
constraint: fields !== void 0 ? { fields } : void 0
|
|
5099
|
-
};
|
|
5100
|
-
}
|
|
5101
|
-
case "23503": {
|
|
5102
|
-
let constraint;
|
|
5103
|
-
if (error.column) constraint = { fields: [error.column] };
|
|
5104
|
-
else if (error.constraint) constraint = { index: error.constraint };
|
|
5105
|
-
return {
|
|
5106
|
-
kind: "ForeignKeyConstraintViolation",
|
|
5107
|
-
constraint
|
|
5108
|
-
};
|
|
5109
|
-
}
|
|
5110
|
-
case "3D000":
|
|
5111
|
-
var _error$message$split$;
|
|
5112
|
-
return {
|
|
5113
|
-
kind: "DatabaseDoesNotExist",
|
|
5114
|
-
db: (_error$message$split$ = error.message.split(" ").at(1)) === null || _error$message$split$ === void 0 ? void 0 : _error$message$split$.split("\"").at(1)
|
|
5115
|
-
};
|
|
5116
|
-
case "28000":
|
|
5117
|
-
var _error$message$split$2;
|
|
5118
|
-
return {
|
|
5119
|
-
kind: "DatabaseAccessDenied",
|
|
5120
|
-
db: (_error$message$split$2 = error.message.split(",").find((s) => s.startsWith(" database"))) === null || _error$message$split$2 === void 0 ? void 0 : _error$message$split$2.split("\"").at(1)
|
|
5121
|
-
};
|
|
5122
|
-
case "28P01":
|
|
5123
|
-
var _error$message$split$3;
|
|
5124
|
-
return {
|
|
5125
|
-
kind: "AuthenticationFailed",
|
|
5126
|
-
user: (_error$message$split$3 = error.message.split(" ").pop()) === null || _error$message$split$3 === void 0 ? void 0 : _error$message$split$3.split("\"").at(1)
|
|
5127
|
-
};
|
|
5128
|
-
case "40001": return { kind: "TransactionWriteConflict" };
|
|
5129
|
-
case "42P01":
|
|
5130
|
-
var _error$message$split$4;
|
|
5131
|
-
return {
|
|
5132
|
-
kind: "TableDoesNotExist",
|
|
5133
|
-
table: (_error$message$split$4 = error.message.split(" ").at(1)) === null || _error$message$split$4 === void 0 ? void 0 : _error$message$split$4.split("\"").at(1)
|
|
5134
|
-
};
|
|
5135
|
-
case "42703":
|
|
5136
|
-
var _error$message$split$5;
|
|
5137
|
-
return {
|
|
5138
|
-
kind: "ColumnNotFound",
|
|
5139
|
-
column: (_error$message$split$5 = error.message.split(" ").at(1)) === null || _error$message$split$5 === void 0 ? void 0 : _error$message$split$5.split("\"").at(1)
|
|
5140
|
-
};
|
|
5141
|
-
case "42P04":
|
|
5142
|
-
var _error$message$split$6;
|
|
5143
|
-
return {
|
|
5144
|
-
kind: "DatabaseAlreadyExists",
|
|
5145
|
-
db: (_error$message$split$6 = error.message.split(" ").at(1)) === null || _error$message$split$6 === void 0 ? void 0 : _error$message$split$6.split("\"").at(1)
|
|
5146
|
-
};
|
|
5147
|
-
case "53300": return {
|
|
5148
|
-
kind: "TooManyConnections",
|
|
5149
|
-
cause: error.message
|
|
5150
|
-
};
|
|
5151
|
-
default: return {
|
|
5152
|
-
kind: "postgres",
|
|
5153
|
-
code: error.code ?? "N/A",
|
|
5154
|
-
severity: error.severity ?? "N/A",
|
|
5155
|
-
message: error.message,
|
|
5156
|
-
detail: error.detail,
|
|
5157
|
-
column: error.column,
|
|
5158
|
-
hint: error.hint
|
|
5159
|
-
};
|
|
5160
|
-
}
|
|
5161
|
-
}
|
|
5162
|
-
function isDriverError(error) {
|
|
5163
|
-
return typeof error.code === "string" && typeof error.message === "string" && typeof error.severity === "string" && (typeof error.detail === "string" || error.detail === void 0) && (typeof error.column === "string" || error.column === void 0) && (typeof error.hint === "string" || error.hint === void 0);
|
|
5164
|
-
}
|
|
5165
|
-
function mapSocketError(error) {
|
|
5166
|
-
switch (error.code) {
|
|
5167
|
-
case "ENOTFOUND":
|
|
5168
|
-
case "ECONNREFUSED": return {
|
|
5169
|
-
kind: "DatabaseNotReachable",
|
|
5170
|
-
host: error.address ?? error.hostname,
|
|
5171
|
-
port: error.port
|
|
5172
|
-
};
|
|
5173
|
-
case "ECONNRESET": return { kind: "ConnectionClosed" };
|
|
5174
|
-
case "ETIMEDOUT": return { kind: "SocketTimeout" };
|
|
5175
|
-
}
|
|
5176
|
-
}
|
|
5177
|
-
function isSocketError(error) {
|
|
5178
|
-
return typeof error.code === "string" && typeof error.syscall === "string" && typeof error.errno === "number" && SOCKET_ERRORS.has(error.code);
|
|
5179
|
-
}
|
|
5180
|
-
function isTlsError(error) {
|
|
5181
|
-
if (typeof error.code === "string") return TLS_ERRORS.has(error.code);
|
|
5182
|
-
switch (error.message) {
|
|
5183
|
-
case "The server does not support SSL connections":
|
|
5184
|
-
case "There was an error establishing an SSL connection": return true;
|
|
5185
|
-
}
|
|
5186
|
-
return false;
|
|
5187
|
-
}
|
|
5188
|
-
var types2 = esm_default.types;
|
|
5189
|
-
var debug = Debug("prisma:driver-adapter:pg");
|
|
5190
|
-
var PgQueryable = class {
|
|
5191
|
-
constructor(client, pgOptions) {
|
|
5192
|
-
this.client = client;
|
|
5193
|
-
this.pgOptions = pgOptions;
|
|
5194
|
-
}
|
|
5195
|
-
provider = "postgres";
|
|
5196
|
-
adapterName = name;
|
|
5197
|
-
/**
|
|
5198
|
-
* Execute a query given as SQL, interpolating the given parameters.
|
|
5199
|
-
*/
|
|
5200
|
-
async queryRaw(query$1) {
|
|
5201
|
-
var _this$pgOptions;
|
|
5202
|
-
debug(`[js::query_raw] %O`, query$1);
|
|
5203
|
-
const { fields, rows } = await this.performIO(query$1);
|
|
5204
|
-
const columnNames = fields.map((field) => field.name);
|
|
5205
|
-
let columnTypes = [];
|
|
5206
|
-
try {
|
|
5207
|
-
columnTypes = fields.map((field) => fieldToColumnType(field.dataTypeID));
|
|
5208
|
-
} catch (e) {
|
|
5209
|
-
if (e instanceof UnsupportedNativeDataType) throw new DriverAdapterError({
|
|
5210
|
-
kind: "UnsupportedNativeDataType",
|
|
5211
|
-
type: e.type
|
|
5212
|
-
});
|
|
5213
|
-
throw e;
|
|
5214
|
-
}
|
|
5215
|
-
const udtParser = (_this$pgOptions = this.pgOptions) === null || _this$pgOptions === void 0 ? void 0 : _this$pgOptions.userDefinedTypeParser;
|
|
5216
|
-
if (udtParser) for (let i = 0; i < fields.length; i++) {
|
|
5217
|
-
const field = fields[i];
|
|
5218
|
-
if (field.dataTypeID >= FIRST_NORMAL_OBJECT_ID && !Object.hasOwn(customParsers, field.dataTypeID)) for (let j = 0; j < rows.length; j++) rows[j][i] = await udtParser(field.dataTypeID, rows[j][i], this);
|
|
5219
|
-
}
|
|
5220
|
-
return {
|
|
5221
|
-
columnNames,
|
|
5222
|
-
columnTypes,
|
|
5223
|
-
rows
|
|
5224
|
-
};
|
|
5225
|
-
}
|
|
5226
|
-
/**
|
|
5227
|
-
* Execute a query given as SQL, interpolating the given parameters and
|
|
5228
|
-
* returning the number of affected rows.
|
|
5229
|
-
* Note: Queryable expects a u64, but napi.rs only supports u32.
|
|
5230
|
-
*/
|
|
5231
|
-
async executeRaw(query$1) {
|
|
5232
|
-
debug(`[js::execute_raw] %O`, query$1);
|
|
5233
|
-
return (await this.performIO(query$1)).rowCount ?? 0;
|
|
5234
|
-
}
|
|
5235
|
-
/**
|
|
5236
|
-
* Run a query against the database, returning the result set.
|
|
5237
|
-
* Should the query fail due to a connection error, the connection is
|
|
5238
|
-
* marked as unhealthy.
|
|
5239
|
-
*/
|
|
5240
|
-
async performIO(query$1) {
|
|
5241
|
-
const { sql: sql$1, args } = query$1;
|
|
5242
|
-
const values = args.map((arg, i) => mapArg(arg, query$1.argTypes[i]));
|
|
5243
|
-
try {
|
|
5244
|
-
return await this.client.query({
|
|
5245
|
-
text: sql$1,
|
|
5246
|
-
values,
|
|
5247
|
-
rowMode: "array",
|
|
5248
|
-
types: { getTypeParser: (oid, format) => {
|
|
5249
|
-
if (format === "text" && customParsers[oid]) return customParsers[oid];
|
|
5250
|
-
return types2.getTypeParser(oid, format);
|
|
5251
|
-
} }
|
|
5252
|
-
}, values);
|
|
5253
|
-
} catch (e) {
|
|
5254
|
-
this.onError(e);
|
|
5255
|
-
}
|
|
5256
|
-
}
|
|
5257
|
-
onError(error) {
|
|
5258
|
-
debug("Error in performIO: %O", error);
|
|
5259
|
-
throw new DriverAdapterError(convertDriverError(error));
|
|
5260
|
-
}
|
|
5261
|
-
};
|
|
5262
|
-
var PgTransaction = class extends PgQueryable {
|
|
5263
|
-
constructor(client, options, pgOptions, cleanup) {
|
|
5264
|
-
super(client, pgOptions);
|
|
5265
|
-
this.options = options;
|
|
5266
|
-
this.pgOptions = pgOptions;
|
|
5267
|
-
this.cleanup = cleanup;
|
|
5268
|
-
}
|
|
5269
|
-
async commit() {
|
|
5270
|
-
var _this$cleanup;
|
|
5271
|
-
debug(`[js::commit]`);
|
|
5272
|
-
(_this$cleanup = this.cleanup) === null || _this$cleanup === void 0 || _this$cleanup.call(this);
|
|
5273
|
-
this.client.release();
|
|
5274
|
-
}
|
|
5275
|
-
async rollback() {
|
|
5276
|
-
var _this$cleanup2;
|
|
5277
|
-
debug(`[js::rollback]`);
|
|
5278
|
-
(_this$cleanup2 = this.cleanup) === null || _this$cleanup2 === void 0 || _this$cleanup2.call(this);
|
|
5279
|
-
this.client.release();
|
|
5280
|
-
}
|
|
5281
|
-
};
|
|
5282
|
-
var PrismaPgAdapter = class extends PgQueryable {
|
|
5283
|
-
constructor(client, pgOptions, release) {
|
|
5284
|
-
super(client);
|
|
5285
|
-
this.pgOptions = pgOptions;
|
|
5286
|
-
this.release = release;
|
|
5287
|
-
}
|
|
5288
|
-
async startTransaction(isolationLevel) {
|
|
5289
|
-
const options = { usePhantomQuery: false };
|
|
5290
|
-
debug("%s options: %O", "[js::startTransaction]", options);
|
|
5291
|
-
const conn = await this.client.connect().catch((error) => this.onError(error));
|
|
5292
|
-
const onError = (err) => {
|
|
5293
|
-
var _this$pgOptions2, _this$pgOptions2$onCo;
|
|
5294
|
-
debug(`Error from pool connection: ${err.message} %O`, err);
|
|
5295
|
-
(_this$pgOptions2 = this.pgOptions) === null || _this$pgOptions2 === void 0 || (_this$pgOptions2$onCo = _this$pgOptions2.onConnectionError) === null || _this$pgOptions2$onCo === void 0 || _this$pgOptions2$onCo.call(_this$pgOptions2, err);
|
|
5296
|
-
};
|
|
5297
|
-
conn.on("error", onError);
|
|
5298
|
-
const cleanup = () => {
|
|
5299
|
-
conn.removeListener("error", onError);
|
|
5300
|
-
};
|
|
5301
|
-
try {
|
|
5302
|
-
const tx = new PgTransaction(conn, options, this.pgOptions, cleanup);
|
|
5303
|
-
await tx.executeRaw({
|
|
5304
|
-
sql: "BEGIN",
|
|
5305
|
-
args: [],
|
|
5306
|
-
argTypes: []
|
|
5307
|
-
});
|
|
5308
|
-
if (isolationLevel) await tx.executeRaw({
|
|
5309
|
-
sql: `SET TRANSACTION ISOLATION LEVEL ${isolationLevel}`,
|
|
5310
|
-
args: [],
|
|
5311
|
-
argTypes: []
|
|
5312
|
-
});
|
|
5313
|
-
return tx;
|
|
5314
|
-
} catch (error) {
|
|
5315
|
-
cleanup();
|
|
5316
|
-
conn.release(error);
|
|
5317
|
-
this.onError(error);
|
|
5318
|
-
}
|
|
5319
|
-
}
|
|
5320
|
-
async executeScript(script) {
|
|
5321
|
-
const statements = script.split(";").map((stmt) => stmt.trim()).filter((stmt) => stmt.length > 0);
|
|
5322
|
-
for (const stmt of statements) try {
|
|
5323
|
-
await this.client.query(stmt);
|
|
5324
|
-
} catch (error) {
|
|
5325
|
-
this.onError(error);
|
|
5326
|
-
}
|
|
5327
|
-
}
|
|
5328
|
-
getConnectionInfo() {
|
|
5329
|
-
var _this$pgOptions3;
|
|
5330
|
-
return {
|
|
5331
|
-
schemaName: (_this$pgOptions3 = this.pgOptions) === null || _this$pgOptions3 === void 0 ? void 0 : _this$pgOptions3.schema,
|
|
5332
|
-
supportsRelationJoins: true
|
|
5333
|
-
};
|
|
5334
|
-
}
|
|
5335
|
-
async dispose() {
|
|
5336
|
-
var _this$release;
|
|
5337
|
-
return (_this$release = this.release) === null || _this$release === void 0 ? void 0 : _this$release.call(this);
|
|
5338
|
-
}
|
|
5339
|
-
underlyingDriver() {
|
|
5340
|
-
return this.client;
|
|
5341
|
-
}
|
|
5342
|
-
};
|
|
5343
|
-
var PrismaPgAdapterFactory = class {
|
|
5344
|
-
constructor(poolOrConfig, options) {
|
|
5345
|
-
this.options = options;
|
|
5346
|
-
if (poolOrConfig instanceof esm_default.Pool) {
|
|
5347
|
-
this.externalPool = poolOrConfig;
|
|
5348
|
-
this.config = poolOrConfig.options;
|
|
5349
|
-
} else {
|
|
5350
|
-
this.externalPool = null;
|
|
5351
|
-
this.config = poolOrConfig;
|
|
5352
|
-
}
|
|
5353
|
-
}
|
|
5354
|
-
provider = "postgres";
|
|
5355
|
-
adapterName = name;
|
|
5356
|
-
config;
|
|
5357
|
-
externalPool;
|
|
5358
|
-
async connect() {
|
|
5359
|
-
const client = this.externalPool ?? new esm_default.Pool(this.config);
|
|
5360
|
-
const onIdleClientError = (err) => {
|
|
5361
|
-
var _this$options, _this$options$onPoolE;
|
|
5362
|
-
debug(`Error from idle pool client: ${err.message} %O`, err);
|
|
5363
|
-
(_this$options = this.options) === null || _this$options === void 0 || (_this$options$onPoolE = _this$options.onPoolError) === null || _this$options$onPoolE === void 0 || _this$options$onPoolE.call(_this$options, err);
|
|
5364
|
-
};
|
|
5365
|
-
client.on("error", onIdleClientError);
|
|
5366
|
-
return new PrismaPgAdapter(client, this.options, async () => {
|
|
5367
|
-
if (this.externalPool) {
|
|
5368
|
-
var _this$options2;
|
|
5369
|
-
if ((_this$options2 = this.options) === null || _this$options2 === void 0 ? void 0 : _this$options2.disposeExternalPool) {
|
|
5370
|
-
await this.externalPool.end();
|
|
5371
|
-
this.externalPool = null;
|
|
5372
|
-
} else this.externalPool.removeListener("error", onIdleClientError);
|
|
5373
|
-
} else await client.end();
|
|
5374
|
-
});
|
|
5375
|
-
}
|
|
5376
|
-
async connectToShadowDb() {
|
|
5377
|
-
const conn = await this.connect();
|
|
5378
|
-
const database = `prisma_migrate_shadow_db_${globalThis.crypto.randomUUID()}`;
|
|
5379
|
-
await conn.executeScript(`CREATE DATABASE "${database}"`);
|
|
5380
|
-
const client = new esm_default.Pool({
|
|
5381
|
-
...this.config,
|
|
5382
|
-
database
|
|
5383
|
-
});
|
|
5384
|
-
return new PrismaPgAdapter(client, void 0, async () => {
|
|
5385
|
-
await conn.executeScript(`DROP DATABASE "${database}"`);
|
|
5386
|
-
await client.end();
|
|
5387
|
-
});
|
|
5388
|
-
}
|
|
5389
|
-
};
|
|
5390
|
-
|
|
5391
4359
|
//#endregion
|
|
5392
4360
|
//#region src/db/client.ts
|
|
5393
4361
|
let prismaClient = null;
|
|
@@ -5401,7 +4369,7 @@ function getDbClient() {
|
|
|
5401
4369
|
const databaseUrl = process.env.AC_CORE_DATABASE_URL;
|
|
5402
4370
|
if (!databaseUrl) throw new Error("AC_CORE_DATABASE_URL environment variable is required for PrismaClient initialization");
|
|
5403
4371
|
pool = new esm_default.Pool({ connectionString: databaseUrl });
|
|
5404
|
-
prismaClient = new PrismaClient({ adapter: new
|
|
4372
|
+
prismaClient = new PrismaClient({ adapter: new PrismaPg(pool) });
|
|
5405
4373
|
}
|
|
5406
4374
|
return prismaClient;
|
|
5407
4375
|
}
|
|
@@ -5532,52 +4500,267 @@ async function getAppCatalogData(getAppsOptional) {
|
|
|
5532
4500
|
}
|
|
5533
4501
|
|
|
5534
4502
|
//#endregion
|
|
5535
|
-
//#region src/
|
|
5536
|
-
|
|
5537
|
-
|
|
5538
|
-
|
|
5539
|
-
|
|
5540
|
-
|
|
5541
|
-
|
|
5542
|
-
|
|
5543
|
-
|
|
5544
|
-
|
|
5545
|
-
|
|
5546
|
-
|
|
5547
|
-
|
|
5548
|
-
|
|
5549
|
-
|
|
5550
|
-
|
|
5551
|
-
|
|
5552
|
-
|
|
5553
|
-
|
|
5554
|
-
|
|
5555
|
-
|
|
5556
|
-
|
|
5557
|
-
|
|
5558
|
-
|
|
5559
|
-
return { set: value };
|
|
5560
|
-
});
|
|
5561
|
-
await txOps.update({
|
|
5562
|
-
data: {
|
|
5563
|
-
...dataScalar,
|
|
5564
|
-
...dataRelations
|
|
5565
|
-
},
|
|
5566
|
-
where: { ...uniqKeyWhere }
|
|
5567
|
-
});
|
|
5568
|
-
}
|
|
5569
|
-
if (upsertOnly !== true) await txOps.deleteMany({ where: { [idColumn]: { in: deleteIds } } });
|
|
5570
|
-
const createDataMapped = createData.map((data) => {
|
|
5571
|
-
const dataScalar = omit(data, relationColumnList);
|
|
5572
|
-
const dataRelations = mapValues(pick(data, relationColumnList), (value) => {
|
|
5573
|
-
return { connect: value };
|
|
5574
|
-
});
|
|
5575
|
-
return {
|
|
5576
|
-
...dataScalar,
|
|
5577
|
-
...dataRelations
|
|
5578
|
-
};
|
|
4503
|
+
//#region src/modules/auth/authRouter.ts
|
|
4504
|
+
/**
|
|
4505
|
+
* Create auth tRPC procedures
|
|
4506
|
+
* @param t - tRPC instance
|
|
4507
|
+
* @param auth - Better Auth instance (optional, for future extensions)
|
|
4508
|
+
* @returns tRPC router with auth procedures
|
|
4509
|
+
*/
|
|
4510
|
+
function createAuthRouter(t$1, auth) {
|
|
4511
|
+
const router$1 = t$1.router;
|
|
4512
|
+
const publicProcedure$1 = t$1.procedure;
|
|
4513
|
+
return router$1({
|
|
4514
|
+
getSession: publicProcedure$1.query(async ({ ctx }) => {
|
|
4515
|
+
return {
|
|
4516
|
+
user: ctx.user ?? null,
|
|
4517
|
+
isAuthenticated: !!ctx.user
|
|
4518
|
+
};
|
|
4519
|
+
}),
|
|
4520
|
+
getProviders: publicProcedure$1.query(() => {
|
|
4521
|
+
const providers = [];
|
|
4522
|
+
const authOptions = auth === null || auth === void 0 ? void 0 : auth.options;
|
|
4523
|
+
if (authOptions === null || authOptions === void 0 ? void 0 : authOptions.socialProviders) {
|
|
4524
|
+
const socialProviders = authOptions.socialProviders;
|
|
4525
|
+
Object.keys(socialProviders).forEach((key) => {
|
|
4526
|
+
if (socialProviders[key]) providers.push(key);
|
|
5579
4527
|
});
|
|
5580
|
-
|
|
4528
|
+
}
|
|
4529
|
+
if (authOptions === null || authOptions === void 0 ? void 0 : authOptions.plugins) authOptions.plugins.forEach((plugin) => {
|
|
4530
|
+
var _pluginWithConfig$opt;
|
|
4531
|
+
const pluginWithConfig = plugin;
|
|
4532
|
+
if (pluginWithConfig.id === "generic-oauth" && ((_pluginWithConfig$opt = pluginWithConfig.options) === null || _pluginWithConfig$opt === void 0 ? void 0 : _pluginWithConfig$opt.config)) (Array.isArray(pluginWithConfig.options.config) ? pluginWithConfig.options.config : [pluginWithConfig.options.config]).forEach((config$1) => {
|
|
4533
|
+
if (config$1.providerId) providers.push(config$1.providerId);
|
|
4534
|
+
});
|
|
4535
|
+
});
|
|
4536
|
+
return { providers };
|
|
4537
|
+
})
|
|
4538
|
+
});
|
|
4539
|
+
}
|
|
4540
|
+
|
|
4541
|
+
//#endregion
|
|
4542
|
+
//#region src/modules/auth/authorizationUtils.ts
|
|
4543
|
+
/**
|
|
4544
|
+
* Extract groups from user object
|
|
4545
|
+
* Groups can be stored in different locations depending on the OAuth provider
|
|
4546
|
+
*/
|
|
4547
|
+
function getUserGroups(user$1) {
|
|
4548
|
+
if (!user$1) {
|
|
4549
|
+
console.log("[getUserGroups] No user provided");
|
|
4550
|
+
return [];
|
|
4551
|
+
}
|
|
4552
|
+
console.log("[getUserGroups] === USER OBJECT DEBUG ===");
|
|
4553
|
+
console.log("[getUserGroups] User ID:", user$1.id);
|
|
4554
|
+
console.log("[getUserGroups] User email:", user$1.email);
|
|
4555
|
+
console.log("[getUserGroups] User.env_hopper_groups:", user$1.env_hopper_groups);
|
|
4556
|
+
console.log("[getUserGroups] User.groups:", user$1.groups);
|
|
4557
|
+
console.log("[getUserGroups] User.oktaGroups:", user$1.oktaGroups);
|
|
4558
|
+
console.log("[getUserGroups] User.roles:", user$1.roles);
|
|
4559
|
+
console.log("[getUserGroups] All user keys:", Object.keys(user$1));
|
|
4560
|
+
console.log("[getUserGroups] Full user object:", JSON.stringify(user$1, null, 2));
|
|
4561
|
+
const groups = user$1.env_hopper_groups || user$1.groups || user$1.oktaGroups || user$1.roles || [];
|
|
4562
|
+
const result = Array.isArray(groups) ? groups : [];
|
|
4563
|
+
console.log("[getUserGroups] Final groups result:", result);
|
|
4564
|
+
return result;
|
|
4565
|
+
}
|
|
4566
|
+
/**
|
|
4567
|
+
* Check if user is a member of any of the specified groups
|
|
4568
|
+
*/
|
|
4569
|
+
function isMemberOfAnyGroup(user$1, allowedGroups) {
|
|
4570
|
+
const userGroups = getUserGroups(user$1);
|
|
4571
|
+
return allowedGroups.some((group$1) => userGroups.includes(group$1));
|
|
4572
|
+
}
|
|
4573
|
+
/**
|
|
4574
|
+
* Check if user is a member of all specified groups
|
|
4575
|
+
*/
|
|
4576
|
+
function isMemberOfAllGroups(user$1, requiredGroups) {
|
|
4577
|
+
const userGroups = getUserGroups(user$1);
|
|
4578
|
+
return requiredGroups.every((group$1) => userGroups.includes(group$1));
|
|
4579
|
+
}
|
|
4580
|
+
/**
|
|
4581
|
+
* Check if user has admin permissions
|
|
4582
|
+
* @param user User object with groups
|
|
4583
|
+
* @param adminGroups List of admin group names (default: ['env_hopper_ui_super_admins'])
|
|
4584
|
+
*/
|
|
4585
|
+
function isAdmin(user$1, adminGroups = ["env_hopper_ui_super_admins"]) {
|
|
4586
|
+
return isMemberOfAnyGroup(user$1, adminGroups);
|
|
4587
|
+
}
|
|
4588
|
+
/**
|
|
4589
|
+
* Require admin permissions - throws error if not admin
|
|
4590
|
+
* @param user User object with groups
|
|
4591
|
+
* @param adminGroups List of admin group names (default: ['env_hopper_ui_super_admins'])
|
|
4592
|
+
*/
|
|
4593
|
+
function requireAdmin(user$1, adminGroups = ["env_hopper_ui_super_admins"]) {
|
|
4594
|
+
if (!isAdmin(user$1, adminGroups)) throw new Error("Forbidden: Admin access required");
|
|
4595
|
+
}
|
|
4596
|
+
/**
|
|
4597
|
+
* Require membership in specific groups - throws error if not member
|
|
4598
|
+
*/
|
|
4599
|
+
function requireGroups(user$1, groups) {
|
|
4600
|
+
if (!isMemberOfAnyGroup(user$1, groups)) throw new Error(`Forbidden: Membership in one of these groups required: ${groups.join(", ")}`);
|
|
4601
|
+
}
|
|
4602
|
+
|
|
4603
|
+
//#endregion
|
|
4604
|
+
//#region src/server/trpcSetup.ts
|
|
4605
|
+
/**
|
|
4606
|
+
* Initialization of tRPC backend
|
|
4607
|
+
* Should be done only once per backend!
|
|
4608
|
+
*/
|
|
4609
|
+
const t = initTRPC.context().create({ errorFormatter({ error, shape }) {
|
|
4610
|
+
var _data;
|
|
4611
|
+
console.error("[tRPC Error]", {
|
|
4612
|
+
path: (_data = shape.data) === null || _data === void 0 ? void 0 : _data.path,
|
|
4613
|
+
code: error.code,
|
|
4614
|
+
message: error.message,
|
|
4615
|
+
cause: error.cause,
|
|
4616
|
+
stack: error.stack
|
|
4617
|
+
});
|
|
4618
|
+
return shape;
|
|
4619
|
+
} });
|
|
4620
|
+
/**
|
|
4621
|
+
* Export reusable router and procedure helpers
|
|
4622
|
+
*/
|
|
4623
|
+
const router = t.router;
|
|
4624
|
+
const publicProcedure = t.procedure;
|
|
4625
|
+
/**
|
|
4626
|
+
* Middleware to check if user is authenticated
|
|
4627
|
+
*/
|
|
4628
|
+
const isAuthenticated = t.middleware(({ ctx, next }) => {
|
|
4629
|
+
if (!ctx.user) throw new TRPCError({
|
|
4630
|
+
code: "UNAUTHORIZED",
|
|
4631
|
+
message: "You must be logged in to access this resource"
|
|
4632
|
+
});
|
|
4633
|
+
return next({ ctx: {
|
|
4634
|
+
...ctx,
|
|
4635
|
+
user: ctx.user
|
|
4636
|
+
} });
|
|
4637
|
+
});
|
|
4638
|
+
/**
|
|
4639
|
+
* Middleware to check if user is an admin
|
|
4640
|
+
*/
|
|
4641
|
+
const isAdminMiddleware = t.middleware(({ ctx, next }) => {
|
|
4642
|
+
if (!ctx.user) throw new TRPCError({
|
|
4643
|
+
code: "UNAUTHORIZED",
|
|
4644
|
+
message: "You must be logged in to access this resource"
|
|
4645
|
+
});
|
|
4646
|
+
console.log("[isAdminMiddleware] === ADMIN CHECK DEBUG ===");
|
|
4647
|
+
console.log("[isAdminMiddleware] User:", ctx.user.email);
|
|
4648
|
+
console.log("[isAdminMiddleware] Required admin groups:", ctx.adminGroups);
|
|
4649
|
+
console.log("[isAdminMiddleware] Calling isAdmin()...");
|
|
4650
|
+
const hasAdminAccess = isAdmin(ctx.user, ctx.adminGroups);
|
|
4651
|
+
console.log("[isAdminMiddleware] Has admin access:", hasAdminAccess);
|
|
4652
|
+
if (!hasAdminAccess) throw new TRPCError({
|
|
4653
|
+
code: "FORBIDDEN",
|
|
4654
|
+
message: `You must be an admin to access this resource. Required groups: ${ctx.adminGroups.join(", ") || "env_hopper_ui_super_admins"}`
|
|
4655
|
+
});
|
|
4656
|
+
return next({ ctx: {
|
|
4657
|
+
...ctx,
|
|
4658
|
+
user: ctx.user
|
|
4659
|
+
} });
|
|
4660
|
+
});
|
|
4661
|
+
/**
|
|
4662
|
+
* Admin procedure that requires admin permissions
|
|
4663
|
+
*/
|
|
4664
|
+
const adminProcedure = t.procedure.use(isAdminMiddleware);
|
|
4665
|
+
/**
|
|
4666
|
+
* Protected procedure that requires authentication (but not admin)
|
|
4667
|
+
*/
|
|
4668
|
+
const protectedProcedure = t.procedure.use(isAuthenticated);
|
|
4669
|
+
|
|
4670
|
+
//#endregion
|
|
4671
|
+
//#region src/server/controller.ts
|
|
4672
|
+
/**
|
|
4673
|
+
* Create the main tRPC router with optional auth instance
|
|
4674
|
+
* @param auth - Optional Better Auth instance for auth-related queries
|
|
4675
|
+
*/
|
|
4676
|
+
function createTrpcRouter(auth) {
|
|
4677
|
+
return router({
|
|
4678
|
+
authConfig: publicProcedure.query(async ({ ctx }) => {
|
|
4679
|
+
return { adminGroups: ctx.adminGroups };
|
|
4680
|
+
}),
|
|
4681
|
+
appCatalog: publicProcedure.query(async ({ ctx }) => {
|
|
4682
|
+
var _ctx$companySpecificB, _ctx$companySpecificB2;
|
|
4683
|
+
const baseData = await getAppCatalogData();
|
|
4684
|
+
const appVersion = (_ctx$companySpecificB = (_ctx$companySpecificB2 = ctx.companySpecificBackend).getAppVersion) === null || _ctx$companySpecificB === void 0 ? void 0 : _ctx$companySpecificB.call(_ctx$companySpecificB2);
|
|
4685
|
+
return {
|
|
4686
|
+
...baseData,
|
|
4687
|
+
...appVersion && { appVersion }
|
|
4688
|
+
};
|
|
4689
|
+
}),
|
|
4690
|
+
auth: createAuthRouter(t, auth)
|
|
4691
|
+
});
|
|
4692
|
+
}
|
|
4693
|
+
|
|
4694
|
+
//#endregion
|
|
4695
|
+
//#region src/server/ehTrpcContext.ts
|
|
4696
|
+
function createEhTrpcContext({ companySpecificBackend, user: user$1 = null, adminGroups }) {
|
|
4697
|
+
return {
|
|
4698
|
+
companySpecificBackend,
|
|
4699
|
+
user: user$1,
|
|
4700
|
+
adminGroups
|
|
4701
|
+
};
|
|
4702
|
+
}
|
|
4703
|
+
|
|
4704
|
+
//#endregion
|
|
4705
|
+
//#region src/server/ehStaticControllerContract.ts
|
|
4706
|
+
const staticControllerContract = { methods: {
|
|
4707
|
+
getIcon: {
|
|
4708
|
+
method: "get",
|
|
4709
|
+
url: "icon/:icon"
|
|
4710
|
+
},
|
|
4711
|
+
getScreenshot: {
|
|
4712
|
+
method: "get",
|
|
4713
|
+
url: "screenshot/:id"
|
|
4714
|
+
}
|
|
4715
|
+
} };
|
|
4716
|
+
|
|
4717
|
+
//#endregion
|
|
4718
|
+
//#region src/db/tableSyncPrismaAdapter.ts
|
|
4719
|
+
function getPrismaModelOperations(prisma, prismaModelName) {
|
|
4720
|
+
return prisma[prismaModelName.slice(0, 1).toLowerCase() + prismaModelName.slice(1)];
|
|
4721
|
+
}
|
|
4722
|
+
function tableSyncPrisma(params) {
|
|
4723
|
+
const { prisma, prismaModelName, uniqColumns, where: whereGlobal, upsertOnly } = params;
|
|
4724
|
+
const prismOperations = getPrismaModelOperations(prisma, prismaModelName);
|
|
4725
|
+
const idColumn = params.id ?? "id";
|
|
4726
|
+
return tableSync({
|
|
4727
|
+
id: idColumn,
|
|
4728
|
+
uniqColumns,
|
|
4729
|
+
readAll: async () => {
|
|
4730
|
+
const findManyArgs = whereGlobal ? { where: whereGlobal } : {};
|
|
4731
|
+
return await prismOperations.findMany(findManyArgs);
|
|
4732
|
+
},
|
|
4733
|
+
writeAll: async (createData, update, deleteIds) => {
|
|
4734
|
+
const prismaUniqKey = params.uniqColumns.join("_");
|
|
4735
|
+
const relationColumnList = params.relationColumns ?? [];
|
|
4736
|
+
return prisma.$transaction(async (tx) => {
|
|
4737
|
+
const txOps = getPrismaModelOperations(tx, prismaModelName);
|
|
4738
|
+
for (const { data, where } of update) {
|
|
4739
|
+
const uniqKeyWhere = Object.keys(where).length > 1 ? { [prismaUniqKey]: where } : where;
|
|
4740
|
+
const dataScalar = omit(data, relationColumnList);
|
|
4741
|
+
const dataRelations = mapValues(pick(data, relationColumnList), (value) => {
|
|
4742
|
+
return { set: value };
|
|
4743
|
+
});
|
|
4744
|
+
await txOps.update({
|
|
4745
|
+
data: {
|
|
4746
|
+
...dataScalar,
|
|
4747
|
+
...dataRelations
|
|
4748
|
+
},
|
|
4749
|
+
where: { ...uniqKeyWhere }
|
|
4750
|
+
});
|
|
4751
|
+
}
|
|
4752
|
+
if (upsertOnly !== true) await txOps.deleteMany({ where: { [idColumn]: { in: deleteIds } } });
|
|
4753
|
+
const createDataMapped = createData.map((data) => {
|
|
4754
|
+
const dataScalar = omit(data, relationColumnList);
|
|
4755
|
+
const dataRelations = mapValues(pick(data, relationColumnList), (value) => {
|
|
4756
|
+
return { connect: value };
|
|
4757
|
+
});
|
|
4758
|
+
return {
|
|
4759
|
+
...dataScalar,
|
|
4760
|
+
...dataRelations
|
|
4761
|
+
};
|
|
4762
|
+
});
|
|
4763
|
+
if (createDataMapped.length > 0) {
|
|
5581
4764
|
const uniqKeysInCreate = /* @__PURE__ */ new Set();
|
|
5582
4765
|
const duplicateKeys = [];
|
|
5583
4766
|
for (const data of createDataMapped) {
|
|
@@ -5709,15 +4892,15 @@ async function parseAssetMeta(p) {
|
|
|
5709
4892
|
|
|
5710
4893
|
//#endregion
|
|
5711
4894
|
//#region src/modules/assets/upsertAsset.ts
|
|
5712
|
-
async function upsertAsset({ prisma, buffer, name
|
|
4895
|
+
async function upsertAsset({ prisma, buffer, name, originalFilename, assetType }) {
|
|
5713
4896
|
const { checksum, fileSize, width, height, mimeType } = await parseAssetMeta({
|
|
5714
4897
|
buffer,
|
|
5715
4898
|
originalFilename
|
|
5716
4899
|
});
|
|
5717
|
-
const existing = await prisma.dbAsset.findUnique({ where: { name
|
|
4900
|
+
const existing = await prisma.dbAsset.findUnique({ where: { name } });
|
|
5718
4901
|
if (existing) return existing.id;
|
|
5719
4902
|
return (await prisma.dbAsset.create({ data: {
|
|
5720
|
-
name
|
|
4903
|
+
name,
|
|
5721
4904
|
checksum,
|
|
5722
4905
|
assetType,
|
|
5723
4906
|
content: new Uint8Array(buffer),
|
|
@@ -5793,751 +4976,57 @@ async function syncAssetsFromFileSystem(apps, allAppsAssetsPath) {
|
|
|
5793
4976
|
}
|
|
5794
4977
|
/**
|
|
5795
4978
|
* Syncs app catalog data to the database using table sync.
|
|
5796
|
-
* This will create new apps, update existing ones, and delete any that are no longer in the input.
|
|
5797
|
-
*
|
|
5798
|
-
* Note: Call connectDb() before and disconnectDb() after if running in a script.
|
|
5799
|
-
*/
|
|
5800
|
-
async function syncAppCatalog(apps, tagsDefinitions, approvalMethods, sreenshotsPath) {
|
|
5801
|
-
try {
|
|
5802
|
-
const prisma = getDbClient();
|
|
5803
|
-
await tableSyncPrisma({
|
|
5804
|
-
prisma,
|
|
5805
|
-
...TABLE_SYNC_MAGAZINE.DbApprovalMethod
|
|
5806
|
-
}).sync(approvalMethods);
|
|
5807
|
-
const sync = tableSyncPrisma({
|
|
5808
|
-
prisma,
|
|
5809
|
-
...TABLE_SYNC_MAGAZINE.DbAppForCatalog
|
|
5810
|
-
});
|
|
5811
|
-
await tableSyncPrisma({
|
|
5812
|
-
prisma,
|
|
5813
|
-
...TABLE_SYNC_MAGAZINE.DbAppTagDefinition
|
|
5814
|
-
}).sync(tagsDefinitions);
|
|
5815
|
-
const dbApps = apps.map((app) => {
|
|
5816
|
-
return {
|
|
5817
|
-
slug: app.slug || app.displayName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, ""),
|
|
5818
|
-
displayName: app.displayName,
|
|
5819
|
-
description: app.description,
|
|
5820
|
-
teams: app.teams ?? [],
|
|
5821
|
-
accessRequest: app.accessRequest ?? null,
|
|
5822
|
-
notes: app.notes ?? null,
|
|
5823
|
-
tags: app.tags ?? [],
|
|
5824
|
-
appUrl: app.appUrl ?? null,
|
|
5825
|
-
links: app.links ?? null,
|
|
5826
|
-
iconName: app.iconName ?? null,
|
|
5827
|
-
screenshotIds: app.screenshotIds ?? [],
|
|
5828
|
-
sources: app.sources ?? [],
|
|
5829
|
-
deprecated: app.deprecated ?? null
|
|
5830
|
-
};
|
|
5831
|
-
});
|
|
5832
|
-
const actual = (await sync.sync(dbApps)).getActual();
|
|
5833
|
-
if (sreenshotsPath) await syncAssetsFromFileSystem(apps, sreenshotsPath);
|
|
5834
|
-
else console.warn("Do not sync screenhots");
|
|
5835
|
-
return {
|
|
5836
|
-
created: actual.length - apps.length + (apps.length - actual.length),
|
|
5837
|
-
updated: 0,
|
|
5838
|
-
deleted: 0,
|
|
5839
|
-
total: actual.length
|
|
5840
|
-
};
|
|
5841
|
-
} catch (error) {
|
|
5842
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
5843
|
-
const errorStack = error instanceof Error ? error.stack : void 0;
|
|
5844
|
-
throw new Error(`Error syncing app catalog: ${errorMessage}\n\nDetails:\n${errorStack || "No stack trace available"}`);
|
|
5845
|
-
}
|
|
5846
|
-
}
|
|
5847
|
-
|
|
5848
|
-
//#endregion
|
|
5849
|
-
//#region src/modules/auth/authorizationUtils.ts
|
|
5850
|
-
/**
|
|
5851
|
-
* Extract groups from user object
|
|
5852
|
-
* Groups can be stored in different locations depending on the OAuth provider
|
|
5853
|
-
*/
|
|
5854
|
-
function getUserGroups(user$1) {
|
|
5855
|
-
if (!user$1) {
|
|
5856
|
-
console.log("[getUserGroups] No user provided");
|
|
5857
|
-
return [];
|
|
5858
|
-
}
|
|
5859
|
-
console.log("[getUserGroups] === USER OBJECT DEBUG ===");
|
|
5860
|
-
console.log("[getUserGroups] User ID:", user$1.id);
|
|
5861
|
-
console.log("[getUserGroups] User email:", user$1.email);
|
|
5862
|
-
console.log("[getUserGroups] User.env_hopper_groups:", user$1.env_hopper_groups);
|
|
5863
|
-
console.log("[getUserGroups] User.groups:", user$1.groups);
|
|
5864
|
-
console.log("[getUserGroups] User.oktaGroups:", user$1.oktaGroups);
|
|
5865
|
-
console.log("[getUserGroups] User.roles:", user$1.roles);
|
|
5866
|
-
console.log("[getUserGroups] All user keys:", Object.keys(user$1));
|
|
5867
|
-
console.log("[getUserGroups] Full user object:", JSON.stringify(user$1, null, 2));
|
|
5868
|
-
const groups = user$1.env_hopper_groups || user$1.groups || user$1.oktaGroups || user$1.roles || [];
|
|
5869
|
-
const result = Array.isArray(groups) ? groups : [];
|
|
5870
|
-
console.log("[getUserGroups] Final groups result:", result);
|
|
5871
|
-
return result;
|
|
5872
|
-
}
|
|
5873
|
-
/**
|
|
5874
|
-
* Check if user is a member of any of the specified groups
|
|
5875
|
-
*/
|
|
5876
|
-
function isMemberOfAnyGroup(user$1, allowedGroups) {
|
|
5877
|
-
const userGroups = getUserGroups(user$1);
|
|
5878
|
-
return allowedGroups.some((group$1) => userGroups.includes(group$1));
|
|
5879
|
-
}
|
|
5880
|
-
/**
|
|
5881
|
-
* Check if user is a member of all specified groups
|
|
5882
|
-
*/
|
|
5883
|
-
function isMemberOfAllGroups(user$1, requiredGroups) {
|
|
5884
|
-
const userGroups = getUserGroups(user$1);
|
|
5885
|
-
return requiredGroups.every((group$1) => userGroups.includes(group$1));
|
|
5886
|
-
}
|
|
5887
|
-
/**
|
|
5888
|
-
* Check if user has admin permissions
|
|
5889
|
-
* @param user User object with groups
|
|
5890
|
-
* @param adminGroups List of admin group names (default: ['env_hopper_ui_super_admins'])
|
|
5891
|
-
*/
|
|
5892
|
-
function isAdmin(user$1, adminGroups = ["env_hopper_ui_super_admins"]) {
|
|
5893
|
-
return isMemberOfAnyGroup(user$1, adminGroups);
|
|
5894
|
-
}
|
|
5895
|
-
/**
|
|
5896
|
-
* Require admin permissions - throws error if not admin
|
|
5897
|
-
* @param user User object with groups
|
|
5898
|
-
* @param adminGroups List of admin group names (default: ['env_hopper_ui_super_admins'])
|
|
5899
|
-
*/
|
|
5900
|
-
function requireAdmin(user$1, adminGroups = ["env_hopper_ui_super_admins"]) {
|
|
5901
|
-
if (!isAdmin(user$1, adminGroups)) throw new Error("Forbidden: Admin access required");
|
|
5902
|
-
}
|
|
5903
|
-
/**
|
|
5904
|
-
* Require membership in specific groups - throws error if not member
|
|
5905
|
-
*/
|
|
5906
|
-
function requireGroups(user$1, groups) {
|
|
5907
|
-
if (!isMemberOfAnyGroup(user$1, groups)) throw new Error(`Forbidden: Membership in one of these groups required: ${groups.join(", ")}`);
|
|
5908
|
-
}
|
|
5909
|
-
|
|
5910
|
-
//#endregion
|
|
5911
|
-
//#region src/server/trpcSetup.ts
|
|
5912
|
-
/**
|
|
5913
|
-
* Initialization of tRPC backend
|
|
5914
|
-
* Should be done only once per backend!
|
|
5915
|
-
*/
|
|
5916
|
-
const t = initTRPC.context().create({ errorFormatter({ error, shape }) {
|
|
5917
|
-
var _data;
|
|
5918
|
-
console.error("[tRPC Error]", {
|
|
5919
|
-
path: (_data = shape.data) === null || _data === void 0 ? void 0 : _data.path,
|
|
5920
|
-
code: error.code,
|
|
5921
|
-
message: error.message,
|
|
5922
|
-
cause: error.cause,
|
|
5923
|
-
stack: error.stack
|
|
5924
|
-
});
|
|
5925
|
-
return shape;
|
|
5926
|
-
} });
|
|
5927
|
-
/**
|
|
5928
|
-
* Export reusable router and procedure helpers
|
|
5929
|
-
*/
|
|
5930
|
-
const router = t.router;
|
|
5931
|
-
const publicProcedure = t.procedure;
|
|
5932
|
-
/**
|
|
5933
|
-
* Middleware to check if user is authenticated
|
|
5934
|
-
*/
|
|
5935
|
-
const isAuthenticated = t.middleware(({ ctx, next }) => {
|
|
5936
|
-
if (!ctx.user) throw new TRPCError({
|
|
5937
|
-
code: "UNAUTHORIZED",
|
|
5938
|
-
message: "You must be logged in to access this resource"
|
|
5939
|
-
});
|
|
5940
|
-
return next({ ctx: {
|
|
5941
|
-
...ctx,
|
|
5942
|
-
user: ctx.user
|
|
5943
|
-
} });
|
|
5944
|
-
});
|
|
5945
|
-
/**
|
|
5946
|
-
* Middleware to check if user is an admin
|
|
5947
|
-
*/
|
|
5948
|
-
const isAdminMiddleware = t.middleware(({ ctx, next }) => {
|
|
5949
|
-
if (!ctx.user) throw new TRPCError({
|
|
5950
|
-
code: "UNAUTHORIZED",
|
|
5951
|
-
message: "You must be logged in to access this resource"
|
|
5952
|
-
});
|
|
5953
|
-
console.log("[isAdminMiddleware] === ADMIN CHECK DEBUG ===");
|
|
5954
|
-
console.log("[isAdminMiddleware] User:", ctx.user.email);
|
|
5955
|
-
console.log("[isAdminMiddleware] Required admin groups:", ctx.adminGroups);
|
|
5956
|
-
console.log("[isAdminMiddleware] Calling isAdmin()...");
|
|
5957
|
-
const hasAdminAccess = isAdmin(ctx.user, ctx.adminGroups);
|
|
5958
|
-
console.log("[isAdminMiddleware] Has admin access:", hasAdminAccess);
|
|
5959
|
-
if (!hasAdminAccess) throw new TRPCError({
|
|
5960
|
-
code: "FORBIDDEN",
|
|
5961
|
-
message: `You must be an admin to access this resource. Required groups: ${ctx.adminGroups.join(", ") || "env_hopper_ui_super_admins"}`
|
|
5962
|
-
});
|
|
5963
|
-
return next({ ctx: {
|
|
5964
|
-
...ctx,
|
|
5965
|
-
user: ctx.user
|
|
5966
|
-
} });
|
|
5967
|
-
});
|
|
5968
|
-
/**
|
|
5969
|
-
* Admin procedure that requires admin permissions
|
|
5970
|
-
*/
|
|
5971
|
-
const adminProcedure = t.procedure.use(isAdminMiddleware);
|
|
5972
|
-
/**
|
|
5973
|
-
* Protected procedure that requires authentication (but not admin)
|
|
5974
|
-
*/
|
|
5975
|
-
const protectedProcedure = t.procedure.use(isAuthenticated);
|
|
5976
|
-
|
|
5977
|
-
//#endregion
|
|
5978
|
-
//#region src/modules/appCatalogAdmin/appCatalogAdminRouter.ts
|
|
5979
|
-
const AccessMethodSchema = z.object({ type: z.enum([
|
|
5980
|
-
"bot",
|
|
5981
|
-
"ticketing",
|
|
5982
|
-
"email",
|
|
5983
|
-
"self-service",
|
|
5984
|
-
"documentation",
|
|
5985
|
-
"manual"
|
|
5986
|
-
]) }).loose();
|
|
5987
|
-
const AppLinkSchema = z.object({
|
|
5988
|
-
displayName: z.string().optional(),
|
|
5989
|
-
url: z.url()
|
|
5990
|
-
});
|
|
5991
|
-
const AppRoleSchema = z.object({
|
|
5992
|
-
name: z.string(),
|
|
5993
|
-
description: z.string().optional()
|
|
5994
|
-
});
|
|
5995
|
-
const ApproverContactSchema = z.object({
|
|
5996
|
-
displayName: z.string(),
|
|
5997
|
-
contact: z.string().optional()
|
|
5998
|
-
});
|
|
5999
|
-
const ApprovalUrlSchema = z.object({
|
|
6000
|
-
label: z.string().optional(),
|
|
6001
|
-
url: z.url()
|
|
6002
|
-
});
|
|
6003
|
-
const AppAccessRequestSchema = z.object({
|
|
6004
|
-
approvalMethodId: z.string(),
|
|
6005
|
-
comments: z.string().optional(),
|
|
6006
|
-
requestPrompt: z.string().optional(),
|
|
6007
|
-
postApprovalInstructions: z.string().optional(),
|
|
6008
|
-
roles: z.array(AppRoleSchema).optional(),
|
|
6009
|
-
approvers: z.array(ApproverContactSchema).optional(),
|
|
6010
|
-
urls: z.array(ApprovalUrlSchema).optional(),
|
|
6011
|
-
whoToReachOut: z.string().optional()
|
|
6012
|
-
});
|
|
6013
|
-
const CreateAppForCatalogSchema = z.object({
|
|
6014
|
-
slug: z.string().min(1).regex(/^[a-z0-9-]+$/, "Slug must be lowercase alphanumeric with hyphens"),
|
|
6015
|
-
displayName: z.string().min(1),
|
|
6016
|
-
description: z.string(),
|
|
6017
|
-
access: AccessMethodSchema.optional(),
|
|
6018
|
-
teams: z.array(z.string()).optional(),
|
|
6019
|
-
accessRequest: AppAccessRequestSchema.optional(),
|
|
6020
|
-
notes: z.string().optional(),
|
|
6021
|
-
tags: z.array(z.string()).optional(),
|
|
6022
|
-
appUrl: z.url().optional(),
|
|
6023
|
-
links: z.array(AppLinkSchema).optional(),
|
|
6024
|
-
iconName: z.string().optional(),
|
|
6025
|
-
screenshotIds: z.array(z.string()).optional()
|
|
6026
|
-
});
|
|
6027
|
-
const UpdateAppForCatalogSchema = CreateAppForCatalogSchema.partial().extend({ id: z.string() });
|
|
6028
|
-
function createAppCatalogAdminRouter() {
|
|
6029
|
-
const prisma = getDbClient();
|
|
6030
|
-
return router({
|
|
6031
|
-
list: adminProcedure.query(async () => {
|
|
6032
|
-
return prisma.dbAppForCatalog.findMany({ orderBy: { displayName: "asc" } });
|
|
6033
|
-
}),
|
|
6034
|
-
getById: adminProcedure.input(z.object({ id: z.string() })).query(async ({ input }) => {
|
|
6035
|
-
return prisma.dbAppForCatalog.findUnique({ where: { id: input.id } });
|
|
6036
|
-
}),
|
|
6037
|
-
getBySlug: adminProcedure.input(z.object({ slug: z.string() })).query(async ({ input }) => {
|
|
6038
|
-
return prisma.dbAppForCatalog.findUnique({ where: { slug: input.slug } });
|
|
6039
|
-
}),
|
|
6040
|
-
create: adminProcedure.input(CreateAppForCatalogSchema).mutation(async ({ input }) => {
|
|
6041
|
-
return prisma.dbAppForCatalog.create({ data: {
|
|
6042
|
-
slug: input.slug,
|
|
6043
|
-
displayName: input.displayName,
|
|
6044
|
-
description: input.description,
|
|
6045
|
-
teams: input.teams ?? [],
|
|
6046
|
-
accessRequest: input.accessRequest,
|
|
6047
|
-
notes: input.notes,
|
|
6048
|
-
tags: input.tags ?? [],
|
|
6049
|
-
appUrl: input.appUrl,
|
|
6050
|
-
links: input.links,
|
|
6051
|
-
iconName: input.iconName,
|
|
6052
|
-
screenshotIds: input.screenshotIds ?? []
|
|
6053
|
-
} });
|
|
6054
|
-
}),
|
|
6055
|
-
update: adminProcedure.input(UpdateAppForCatalogSchema).mutation(async ({ input }) => {
|
|
6056
|
-
const { id,...updateData } = input;
|
|
6057
|
-
return prisma.dbAppForCatalog.update({
|
|
6058
|
-
where: { id },
|
|
6059
|
-
data: {
|
|
6060
|
-
...updateData.slug !== void 0 && { slug: updateData.slug },
|
|
6061
|
-
...updateData.displayName !== void 0 && { displayName: updateData.displayName },
|
|
6062
|
-
...updateData.description !== void 0 && { description: updateData.description },
|
|
6063
|
-
...updateData.teams !== void 0 && { teams: updateData.teams },
|
|
6064
|
-
...updateData.accessRequest !== void 0 && { accessRequest: updateData.accessRequest },
|
|
6065
|
-
...updateData.notes !== void 0 && { notes: updateData.notes },
|
|
6066
|
-
...updateData.tags !== void 0 && { tags: updateData.tags },
|
|
6067
|
-
...updateData.appUrl !== void 0 && { appUrl: updateData.appUrl },
|
|
6068
|
-
...updateData.links !== void 0 && { links: updateData.links },
|
|
6069
|
-
...updateData.iconName !== void 0 && { iconName: updateData.iconName },
|
|
6070
|
-
...updateData.screenshotIds !== void 0 && { screenshotIds: updateData.screenshotIds }
|
|
6071
|
-
}
|
|
6072
|
-
});
|
|
6073
|
-
}),
|
|
6074
|
-
updateScreenshots: adminProcedure.input(z.object({
|
|
6075
|
-
id: z.string(),
|
|
6076
|
-
screenshotIds: z.array(z.string())
|
|
6077
|
-
})).mutation(async ({ input }) => {
|
|
6078
|
-
return prisma.dbAppForCatalog.update({
|
|
6079
|
-
where: { id: input.id },
|
|
6080
|
-
data: { screenshotIds: input.screenshotIds }
|
|
6081
|
-
});
|
|
6082
|
-
}),
|
|
6083
|
-
delete: adminProcedure.input(z.object({ id: z.string() })).mutation(async ({ input }) => {
|
|
6084
|
-
return prisma.dbAppForCatalog.delete({ where: { id: input.id } });
|
|
6085
|
-
})
|
|
6086
|
-
});
|
|
6087
|
-
}
|
|
6088
|
-
|
|
6089
|
-
//#endregion
|
|
6090
|
-
//#region src/modules/approvalMethod/slugUtils.ts
|
|
6091
|
-
/**
|
|
6092
|
-
* Generates a URL-friendly slug from a display name.
|
|
6093
|
-
* Converts to lowercase and replaces non-alphanumeric characters with hyphens.
|
|
6094
|
-
*
|
|
6095
|
-
* @param displayName - The display name to convert
|
|
6096
|
-
* @returns A slug suitable for use as a primary key
|
|
6097
|
-
*
|
|
6098
|
-
* @example
|
|
6099
|
-
* generateSlugFromDisplayName("My Service") // "my-service"
|
|
6100
|
-
* generateSlugFromDisplayName("John's Team") // "john-s-team"
|
|
6101
|
-
*/
|
|
6102
|
-
function generateSlugFromDisplayName(displayName) {
|
|
6103
|
-
return displayName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
6104
|
-
}
|
|
6105
|
-
|
|
6106
|
-
//#endregion
|
|
6107
|
-
//#region src/modules/approvalMethod/approvalMethodRouter.ts
|
|
6108
|
-
const ReachOutContactSchema = z.object({
|
|
6109
|
-
displayName: z.string(),
|
|
6110
|
-
contact: z.string()
|
|
6111
|
-
});
|
|
6112
|
-
const ServiceConfigSchema = z.object({
|
|
6113
|
-
url: z.url().optional(),
|
|
6114
|
-
icon: z.string().optional()
|
|
6115
|
-
});
|
|
6116
|
-
const PersonTeamConfigSchema = z.object({ reachOutContacts: z.array(ReachOutContactSchema).optional() });
|
|
6117
|
-
const CustomConfigSchema = z.object({});
|
|
6118
|
-
const ApprovalMethodConfigSchema = z.union([
|
|
6119
|
-
ServiceConfigSchema,
|
|
6120
|
-
PersonTeamConfigSchema,
|
|
6121
|
-
CustomConfigSchema
|
|
6122
|
-
]);
|
|
6123
|
-
const CreateApprovalMethodSchema = z.object({
|
|
6124
|
-
type: z.enum([
|
|
6125
|
-
"service",
|
|
6126
|
-
"personTeam",
|
|
6127
|
-
"custom"
|
|
6128
|
-
]),
|
|
6129
|
-
displayName: z.string().min(1),
|
|
6130
|
-
config: ApprovalMethodConfigSchema.optional()
|
|
6131
|
-
});
|
|
6132
|
-
const UpdateApprovalMethodSchema = z.object({
|
|
6133
|
-
slug: z.string(),
|
|
6134
|
-
type: z.enum([
|
|
6135
|
-
"service",
|
|
6136
|
-
"personTeam",
|
|
6137
|
-
"custom"
|
|
6138
|
-
]).optional(),
|
|
6139
|
-
displayName: z.string().min(1).optional(),
|
|
6140
|
-
config: ApprovalMethodConfigSchema.optional()
|
|
6141
|
-
});
|
|
6142
|
-
/**
|
|
6143
|
-
* Convert Prisma DbApprovalMethod to our ApprovalMethod type.
|
|
6144
|
-
* This ensures tRPC infers proper types for frontend consumers.
|
|
6145
|
-
*/
|
|
6146
|
-
function toApprovalMethod(db) {
|
|
6147
|
-
const baseFields = {
|
|
6148
|
-
slug: db.slug,
|
|
6149
|
-
displayName: db.displayName,
|
|
6150
|
-
createdAt: db.createdAt,
|
|
6151
|
-
updatedAt: db.updatedAt
|
|
6152
|
-
};
|
|
6153
|
-
const config$1 = db.config ?? {};
|
|
6154
|
-
switch (db.type) {
|
|
6155
|
-
case "service": return {
|
|
6156
|
-
...baseFields,
|
|
6157
|
-
type: "service",
|
|
6158
|
-
config: config$1
|
|
6159
|
-
};
|
|
6160
|
-
case "personTeam": return {
|
|
6161
|
-
...baseFields,
|
|
6162
|
-
type: "personTeam",
|
|
6163
|
-
config: config$1
|
|
6164
|
-
};
|
|
6165
|
-
case "custom": return {
|
|
6166
|
-
...baseFields,
|
|
6167
|
-
type: "custom",
|
|
6168
|
-
config: config$1
|
|
6169
|
-
};
|
|
6170
|
-
}
|
|
6171
|
-
}
|
|
6172
|
-
function createApprovalMethodRouter() {
|
|
6173
|
-
return router({
|
|
6174
|
-
list: publicProcedure.query(async () => {
|
|
6175
|
-
return (await getDbClient().dbApprovalMethod.findMany({ orderBy: { displayName: "asc" } })).map(toApprovalMethod);
|
|
6176
|
-
}),
|
|
6177
|
-
getById: publicProcedure.input(z.object({ slug: z.string() })).query(async ({ input }) => {
|
|
6178
|
-
const result = await getDbClient().dbApprovalMethod.findUnique({ where: { slug: input.slug } });
|
|
6179
|
-
return result ? toApprovalMethod(result) : null;
|
|
6180
|
-
}),
|
|
6181
|
-
create: adminProcedure.input(CreateApprovalMethodSchema).mutation(async ({ input }) => {
|
|
6182
|
-
return toApprovalMethod(await getDbClient().dbApprovalMethod.create({ data: {
|
|
6183
|
-
slug: generateSlugFromDisplayName(input.displayName),
|
|
6184
|
-
type: input.type,
|
|
6185
|
-
displayName: input.displayName,
|
|
6186
|
-
config: input.config ?? JsonNull
|
|
6187
|
-
} }));
|
|
6188
|
-
}),
|
|
6189
|
-
update: adminProcedure.input(UpdateApprovalMethodSchema).mutation(async ({ input }) => {
|
|
6190
|
-
const prisma = getDbClient();
|
|
6191
|
-
const { slug,...updateData } = input;
|
|
6192
|
-
return toApprovalMethod(await prisma.dbApprovalMethod.update({
|
|
6193
|
-
where: { slug },
|
|
6194
|
-
data: {
|
|
6195
|
-
...updateData.type !== void 0 && { type: updateData.type },
|
|
6196
|
-
...updateData.displayName !== void 0 && { displayName: updateData.displayName },
|
|
6197
|
-
...updateData.config !== void 0 && { config: updateData.config ?? JsonNull }
|
|
6198
|
-
}
|
|
6199
|
-
}));
|
|
6200
|
-
}),
|
|
6201
|
-
delete: adminProcedure.input(z.object({ slug: z.string() })).mutation(async ({ input }) => {
|
|
6202
|
-
return toApprovalMethod(await getDbClient().dbApprovalMethod.delete({ where: { slug: input.slug } }));
|
|
6203
|
-
}),
|
|
6204
|
-
listByType: publicProcedure.input(z.object({ type: z.enum([
|
|
6205
|
-
"service",
|
|
6206
|
-
"personTeam",
|
|
6207
|
-
"custom"
|
|
6208
|
-
]) })).query(async ({ input }) => {
|
|
6209
|
-
return (await getDbClient().dbApprovalMethod.findMany({
|
|
6210
|
-
where: { type: input.type },
|
|
6211
|
-
orderBy: { displayName: "asc" }
|
|
6212
|
-
})).map(toApprovalMethod);
|
|
6213
|
-
})
|
|
6214
|
-
});
|
|
6215
|
-
}
|
|
6216
|
-
|
|
6217
|
-
//#endregion
|
|
6218
|
-
//#region src/modules/assets/screenshotRouter.ts
|
|
6219
|
-
function createScreenshotRouter() {
|
|
6220
|
-
return router({
|
|
6221
|
-
list: publicProcedure.query(async () => {
|
|
6222
|
-
return getDbClient().dbAsset.findMany({
|
|
6223
|
-
where: { assetType: "screenshot" },
|
|
6224
|
-
select: {
|
|
6225
|
-
id: true,
|
|
6226
|
-
name: true,
|
|
6227
|
-
mimeType: true,
|
|
6228
|
-
fileSize: true,
|
|
6229
|
-
width: true,
|
|
6230
|
-
height: true,
|
|
6231
|
-
createdAt: true,
|
|
6232
|
-
updatedAt: true
|
|
6233
|
-
},
|
|
6234
|
-
orderBy: { createdAt: "desc" }
|
|
6235
|
-
});
|
|
6236
|
-
}),
|
|
6237
|
-
getOne: publicProcedure.input(z.object({ id: z.string() })).query(async ({ input }) => {
|
|
6238
|
-
return getDbClient().dbAsset.findFirst({
|
|
6239
|
-
where: {
|
|
6240
|
-
id: input.id,
|
|
6241
|
-
assetType: "screenshot"
|
|
6242
|
-
},
|
|
6243
|
-
select: {
|
|
6244
|
-
id: true,
|
|
6245
|
-
name: true,
|
|
6246
|
-
mimeType: true,
|
|
6247
|
-
fileSize: true,
|
|
6248
|
-
width: true,
|
|
6249
|
-
height: true,
|
|
6250
|
-
createdAt: true,
|
|
6251
|
-
updatedAt: true
|
|
6252
|
-
}
|
|
6253
|
-
});
|
|
6254
|
-
}),
|
|
6255
|
-
getByAppSlug: publicProcedure.input(z.object({ appSlug: z.string() })).query(async ({ input }) => {
|
|
6256
|
-
const prisma = getDbClient();
|
|
6257
|
-
const app = await prisma.dbAppForCatalog.findUnique({
|
|
6258
|
-
where: { slug: input.appSlug },
|
|
6259
|
-
select: { screenshotIds: true }
|
|
6260
|
-
});
|
|
6261
|
-
if (!app) return [];
|
|
6262
|
-
return prisma.dbAsset.findMany({
|
|
6263
|
-
where: {
|
|
6264
|
-
id: { in: app.screenshotIds },
|
|
6265
|
-
assetType: "screenshot"
|
|
6266
|
-
},
|
|
6267
|
-
select: {
|
|
6268
|
-
id: true,
|
|
6269
|
-
name: true,
|
|
6270
|
-
mimeType: true,
|
|
6271
|
-
fileSize: true,
|
|
6272
|
-
width: true,
|
|
6273
|
-
height: true,
|
|
6274
|
-
createdAt: true,
|
|
6275
|
-
updatedAt: true
|
|
6276
|
-
}
|
|
6277
|
-
});
|
|
6278
|
-
}),
|
|
6279
|
-
getFirstByAppSlug: publicProcedure.input(z.object({ appSlug: z.string() })).query(async ({ input }) => {
|
|
6280
|
-
const prisma = getDbClient();
|
|
6281
|
-
const app = await prisma.dbAppForCatalog.findUnique({
|
|
6282
|
-
where: { slug: input.appSlug },
|
|
6283
|
-
select: { screenshotIds: true }
|
|
6284
|
-
});
|
|
6285
|
-
if (!app || app.screenshotIds.length === 0) return null;
|
|
6286
|
-
return prisma.dbAsset.findUnique({
|
|
6287
|
-
where: { id: app.screenshotIds[0] },
|
|
6288
|
-
select: {
|
|
6289
|
-
id: true,
|
|
6290
|
-
name: true,
|
|
6291
|
-
mimeType: true,
|
|
6292
|
-
fileSize: true,
|
|
6293
|
-
width: true,
|
|
6294
|
-
height: true,
|
|
6295
|
-
createdAt: true,
|
|
6296
|
-
updatedAt: true
|
|
6297
|
-
}
|
|
6298
|
-
});
|
|
6299
|
-
})
|
|
6300
|
-
});
|
|
6301
|
-
}
|
|
6302
|
-
|
|
6303
|
-
//#endregion
|
|
6304
|
-
//#region src/modules/auth/authRouter.ts
|
|
6305
|
-
/**
|
|
6306
|
-
* Create auth tRPC procedures
|
|
6307
|
-
* @param t - tRPC instance
|
|
6308
|
-
* @param auth - Better Auth instance (optional, for future extensions)
|
|
6309
|
-
* @returns tRPC router with auth procedures
|
|
6310
|
-
*/
|
|
6311
|
-
function createAuthRouter(t$1, auth) {
|
|
6312
|
-
const router$1 = t$1.router;
|
|
6313
|
-
const publicProcedure$1 = t$1.procedure;
|
|
6314
|
-
return router$1({
|
|
6315
|
-
getSession: publicProcedure$1.query(async ({ ctx }) => {
|
|
6316
|
-
return {
|
|
6317
|
-
user: ctx.user ?? null,
|
|
6318
|
-
isAuthenticated: !!ctx.user
|
|
6319
|
-
};
|
|
6320
|
-
}),
|
|
6321
|
-
getProviders: publicProcedure$1.query(() => {
|
|
6322
|
-
const providers = [];
|
|
6323
|
-
const authOptions = auth === null || auth === void 0 ? void 0 : auth.options;
|
|
6324
|
-
if (authOptions === null || authOptions === void 0 ? void 0 : authOptions.socialProviders) {
|
|
6325
|
-
const socialProviders = authOptions.socialProviders;
|
|
6326
|
-
Object.keys(socialProviders).forEach((key) => {
|
|
6327
|
-
if (socialProviders[key]) providers.push(key);
|
|
6328
|
-
});
|
|
6329
|
-
}
|
|
6330
|
-
if (authOptions === null || authOptions === void 0 ? void 0 : authOptions.plugins) authOptions.plugins.forEach((plugin) => {
|
|
6331
|
-
var _pluginWithConfig$opt;
|
|
6332
|
-
const pluginWithConfig = plugin;
|
|
6333
|
-
if (pluginWithConfig.id === "generic-oauth" && ((_pluginWithConfig$opt = pluginWithConfig.options) === null || _pluginWithConfig$opt === void 0 ? void 0 : _pluginWithConfig$opt.config)) (Array.isArray(pluginWithConfig.options.config) ? pluginWithConfig.options.config : [pluginWithConfig.options.config]).forEach((config$1) => {
|
|
6334
|
-
if (config$1.providerId) providers.push(config$1.providerId);
|
|
6335
|
-
});
|
|
6336
|
-
});
|
|
6337
|
-
return { providers };
|
|
6338
|
-
})
|
|
6339
|
-
});
|
|
6340
|
-
}
|
|
6341
|
-
|
|
6342
|
-
//#endregion
|
|
6343
|
-
//#region src/modules/icons/iconUtils.ts
|
|
6344
|
-
/**
|
|
6345
|
-
* Get file extension from MIME type
|
|
6346
|
-
*/
|
|
6347
|
-
function getExtensionFromMimeType(mimeType) {
|
|
6348
|
-
return {
|
|
6349
|
-
"image/svg+xml": "svg",
|
|
6350
|
-
"image/png": "png",
|
|
6351
|
-
"image/jpeg": "jpg",
|
|
6352
|
-
"image/jpg": "jpg",
|
|
6353
|
-
"image/webp": "webp",
|
|
6354
|
-
"image/gif": "gif",
|
|
6355
|
-
"image/bmp": "bmp",
|
|
6356
|
-
"image/tiff": "tiff",
|
|
6357
|
-
"image/x-icon": "ico",
|
|
6358
|
-
"image/vnd.microsoft.icon": "ico"
|
|
6359
|
-
}[mimeType.toLowerCase()] || "bin";
|
|
6360
|
-
}
|
|
6361
|
-
/**
|
|
6362
|
-
* Get file extension from filename
|
|
6363
|
-
*/
|
|
6364
|
-
function getExtensionFromFilename(filename) {
|
|
6365
|
-
var _match$;
|
|
6366
|
-
const match = filename.match(/\.([^.]+)$/);
|
|
6367
|
-
return (match === null || match === void 0 || (_match$ = match[1]) === null || _match$ === void 0 ? void 0 : _match$.toLowerCase()) || "";
|
|
6368
|
-
}
|
|
6369
|
-
|
|
6370
|
-
//#endregion
|
|
6371
|
-
//#region src/modules/icons/iconRouter.ts
|
|
6372
|
-
function createIconRouter() {
|
|
6373
|
-
return router({
|
|
6374
|
-
list: publicProcedure.query(async () => {
|
|
6375
|
-
return getDbClient().dbAsset.findMany({
|
|
6376
|
-
where: { assetType: "icon" },
|
|
6377
|
-
select: {
|
|
6378
|
-
id: true,
|
|
6379
|
-
name: true,
|
|
6380
|
-
mimeType: true,
|
|
6381
|
-
fileSize: true,
|
|
6382
|
-
createdAt: true,
|
|
6383
|
-
updatedAt: true
|
|
6384
|
-
},
|
|
6385
|
-
orderBy: { name: "asc" }
|
|
6386
|
-
});
|
|
6387
|
-
}),
|
|
6388
|
-
getOne: publicProcedure.input(z.object({ id: z.string() })).query(async ({ input }) => {
|
|
6389
|
-
return getDbClient().dbAsset.findFirst({
|
|
6390
|
-
where: {
|
|
6391
|
-
id: input.id,
|
|
6392
|
-
assetType: "icon"
|
|
6393
|
-
},
|
|
6394
|
-
select: {
|
|
6395
|
-
id: true,
|
|
6396
|
-
name: true,
|
|
6397
|
-
mimeType: true,
|
|
6398
|
-
fileSize: true,
|
|
6399
|
-
createdAt: true,
|
|
6400
|
-
updatedAt: true
|
|
6401
|
-
}
|
|
6402
|
-
});
|
|
6403
|
-
}),
|
|
6404
|
-
create: adminProcedure.input(z.object({
|
|
6405
|
-
name: z.string().min(1),
|
|
6406
|
-
content: z.string(),
|
|
6407
|
-
mimeType: z.string(),
|
|
6408
|
-
fileSize: z.number().int().positive()
|
|
6409
|
-
})).mutation(async ({ input }) => {
|
|
6410
|
-
const prisma = getDbClient();
|
|
6411
|
-
const buffer = Buffer.from(input.content, "base64");
|
|
6412
|
-
const checksum = generateChecksum(buffer);
|
|
6413
|
-
const { width, height } = await getImageDimensions(buffer);
|
|
6414
|
-
let name$1 = input.name;
|
|
6415
|
-
if (!name$1.includes(".")) {
|
|
6416
|
-
const extension = getExtensionFromMimeType(input.mimeType);
|
|
6417
|
-
name$1 = `${name$1}.${extension}`;
|
|
6418
|
-
}
|
|
6419
|
-
const existing = await prisma.dbAsset.findFirst({ where: {
|
|
6420
|
-
checksum,
|
|
6421
|
-
assetType: "icon"
|
|
6422
|
-
} });
|
|
6423
|
-
if (existing) return existing;
|
|
6424
|
-
return prisma.dbAsset.create({ data: {
|
|
6425
|
-
name: name$1,
|
|
6426
|
-
assetType: "icon",
|
|
6427
|
-
content: new Uint8Array(buffer),
|
|
6428
|
-
checksum,
|
|
6429
|
-
mimeType: input.mimeType,
|
|
6430
|
-
fileSize: input.fileSize,
|
|
6431
|
-
width,
|
|
6432
|
-
height
|
|
6433
|
-
} });
|
|
6434
|
-
}),
|
|
6435
|
-
update: adminProcedure.input(z.object({
|
|
6436
|
-
id: z.string(),
|
|
6437
|
-
name: z.string().min(1).optional(),
|
|
6438
|
-
content: z.string().optional(),
|
|
6439
|
-
mimeType: z.string().optional(),
|
|
6440
|
-
fileSize: z.number().int().positive().optional()
|
|
6441
|
-
})).mutation(async ({ input }) => {
|
|
6442
|
-
const prisma = getDbClient();
|
|
6443
|
-
const { id, content, name: name$1,...rest } = input;
|
|
6444
|
-
const data = { ...rest };
|
|
6445
|
-
if (content) {
|
|
6446
|
-
const buffer = Buffer.from(content, "base64");
|
|
6447
|
-
data.content = new Uint8Array(buffer);
|
|
6448
|
-
data.checksum = generateChecksum(buffer);
|
|
6449
|
-
const { width, height } = await getImageDimensions(buffer);
|
|
6450
|
-
data.width = width;
|
|
6451
|
-
data.height = height;
|
|
6452
|
-
}
|
|
6453
|
-
if (name$1) if (!name$1.includes(".") && input.mimeType) data.name = `${name$1}.${getExtensionFromMimeType(input.mimeType)}`;
|
|
6454
|
-
else data.name = name$1;
|
|
6455
|
-
return prisma.dbAsset.update({
|
|
6456
|
-
where: { id },
|
|
6457
|
-
data
|
|
6458
|
-
});
|
|
6459
|
-
}),
|
|
6460
|
-
delete: adminProcedure.input(z.object({ id: z.string() })).mutation(async ({ input }) => {
|
|
6461
|
-
return getDbClient().dbAsset.delete({ where: { id: input.id } });
|
|
6462
|
-
}),
|
|
6463
|
-
deleteMany: adminProcedure.input(z.object({ ids: z.array(z.string()) })).mutation(async ({ input }) => {
|
|
6464
|
-
return getDbClient().dbAsset.deleteMany({ where: {
|
|
6465
|
-
id: { in: input.ids },
|
|
6466
|
-
assetType: "icon"
|
|
6467
|
-
} });
|
|
6468
|
-
}),
|
|
6469
|
-
getContent: publicProcedure.input(z.object({ id: z.string() })).query(async ({ input }) => {
|
|
6470
|
-
const asset = await getDbClient().dbAsset.findFirst({
|
|
6471
|
-
where: {
|
|
6472
|
-
id: input.id,
|
|
6473
|
-
assetType: "icon"
|
|
6474
|
-
},
|
|
6475
|
-
select: {
|
|
6476
|
-
content: true,
|
|
6477
|
-
mimeType: true,
|
|
6478
|
-
name: true
|
|
6479
|
-
}
|
|
6480
|
-
});
|
|
6481
|
-
if (!asset) throw new Error("Icon not found");
|
|
6482
|
-
return {
|
|
6483
|
-
content: Buffer.from(asset.content).toString("base64"),
|
|
6484
|
-
mimeType: asset.mimeType,
|
|
6485
|
-
name: asset.name
|
|
6486
|
-
};
|
|
6487
|
-
})
|
|
6488
|
-
});
|
|
6489
|
-
}
|
|
6490
|
-
|
|
6491
|
-
//#endregion
|
|
6492
|
-
//#region src/server/controller.ts
|
|
6493
|
-
/**
|
|
6494
|
-
* Create the main tRPC router with optional auth instance
|
|
6495
|
-
* @param auth - Optional Better Auth instance for auth-related queries
|
|
6496
|
-
*/
|
|
6497
|
-
function createTrpcRouter(auth) {
|
|
6498
|
-
return router({
|
|
6499
|
-
authConfig: publicProcedure.query(async ({ ctx }) => {
|
|
6500
|
-
return { adminGroups: ctx.adminGroups };
|
|
6501
|
-
}),
|
|
6502
|
-
appCatalog: publicProcedure.query(async ({ ctx }) => {
|
|
6503
|
-
var _ctx$companySpecificB, _ctx$companySpecificB2;
|
|
6504
|
-
const baseData = await getAppCatalogData();
|
|
6505
|
-
const appVersion = (_ctx$companySpecificB = (_ctx$companySpecificB2 = ctx.companySpecificBackend).getAppVersion) === null || _ctx$companySpecificB === void 0 ? void 0 : _ctx$companySpecificB.call(_ctx$companySpecificB2);
|
|
4979
|
+
* This will create new apps, update existing ones, and delete any that are no longer in the input.
|
|
4980
|
+
*
|
|
4981
|
+
* Note: Call connectDb() before and disconnectDb() after if running in a script.
|
|
4982
|
+
*/
|
|
4983
|
+
async function syncAppCatalog(apps, tagsDefinitions, approvalMethods, sreenshotsPath) {
|
|
4984
|
+
try {
|
|
4985
|
+
const prisma = getDbClient();
|
|
4986
|
+
await tableSyncPrisma({
|
|
4987
|
+
prisma,
|
|
4988
|
+
...TABLE_SYNC_MAGAZINE.DbApprovalMethod
|
|
4989
|
+
}).sync(approvalMethods);
|
|
4990
|
+
const sync = tableSyncPrisma({
|
|
4991
|
+
prisma,
|
|
4992
|
+
...TABLE_SYNC_MAGAZINE.DbAppForCatalog
|
|
4993
|
+
});
|
|
4994
|
+
await tableSyncPrisma({
|
|
4995
|
+
prisma,
|
|
4996
|
+
...TABLE_SYNC_MAGAZINE.DbAppTagDefinition
|
|
4997
|
+
}).sync(tagsDefinitions);
|
|
4998
|
+
const dbApps = apps.map((app) => {
|
|
6506
4999
|
return {
|
|
6507
|
-
|
|
6508
|
-
|
|
5000
|
+
slug: app.slug || app.displayName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, ""),
|
|
5001
|
+
displayName: app.displayName,
|
|
5002
|
+
description: app.description,
|
|
5003
|
+
teams: app.teams ?? [],
|
|
5004
|
+
accessRequest: app.accessRequest ?? null,
|
|
5005
|
+
notes: app.notes ?? null,
|
|
5006
|
+
tags: app.tags ?? [],
|
|
5007
|
+
appUrl: app.appUrl ?? null,
|
|
5008
|
+
links: app.links ?? null,
|
|
5009
|
+
iconName: app.iconName ?? null,
|
|
5010
|
+
screenshotIds: app.screenshotIds ?? [],
|
|
5011
|
+
sources: app.sources ?? [],
|
|
5012
|
+
deprecated: app.deprecated ?? null
|
|
6509
5013
|
};
|
|
6510
|
-
})
|
|
6511
|
-
|
|
6512
|
-
|
|
6513
|
-
|
|
6514
|
-
|
|
6515
|
-
|
|
6516
|
-
|
|
6517
|
-
|
|
6518
|
-
|
|
6519
|
-
|
|
6520
|
-
|
|
6521
|
-
|
|
6522
|
-
|
|
6523
|
-
|
|
6524
|
-
user: user$1,
|
|
6525
|
-
adminGroups
|
|
6526
|
-
};
|
|
6527
|
-
}
|
|
6528
|
-
|
|
6529
|
-
//#endregion
|
|
6530
|
-
//#region src/server/ehStaticControllerContract.ts
|
|
6531
|
-
const staticControllerContract = { methods: {
|
|
6532
|
-
getIcon: {
|
|
6533
|
-
method: "get",
|
|
6534
|
-
url: "icon/:icon"
|
|
6535
|
-
},
|
|
6536
|
-
getScreenshot: {
|
|
6537
|
-
method: "get",
|
|
6538
|
-
url: "screenshot/:id"
|
|
5014
|
+
});
|
|
5015
|
+
const actual = (await sync.sync(dbApps)).getActual();
|
|
5016
|
+
if (sreenshotsPath) await syncAssetsFromFileSystem(apps, sreenshotsPath);
|
|
5017
|
+
else console.warn("Do not sync screenhots");
|
|
5018
|
+
return {
|
|
5019
|
+
created: actual.length - apps.length + (apps.length - actual.length),
|
|
5020
|
+
updated: 0,
|
|
5021
|
+
deleted: 0,
|
|
5022
|
+
total: actual.length
|
|
5023
|
+
};
|
|
5024
|
+
} catch (error) {
|
|
5025
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
5026
|
+
const errorStack = error instanceof Error ? error.stack : void 0;
|
|
5027
|
+
throw new Error(`Error syncing app catalog: ${errorMessage}\n\nDetails:\n${errorStack || "No stack trace available"}`);
|
|
6539
5028
|
}
|
|
6540
|
-
}
|
|
5029
|
+
}
|
|
6541
5030
|
|
|
6542
5031
|
//#endregion
|
|
6543
5032
|
//#region src/modules/auth/auth.ts
|
|
@@ -6588,256 +5077,32 @@ function registerAuthRoutes(app, auth) {
|
|
|
6588
5077
|
}
|
|
6589
5078
|
|
|
6590
5079
|
//#endregion
|
|
6591
|
-
//#region src/modules/
|
|
6592
|
-
function convertToCoreMessages(messages) {
|
|
6593
|
-
return messages.map((msg) => {
|
|
6594
|
-
var _msg$parts;
|
|
6595
|
-
if (msg.content) return {
|
|
6596
|
-
role: msg.role,
|
|
6597
|
-
content: msg.content
|
|
6598
|
-
};
|
|
6599
|
-
const textContent = ((_msg$parts = msg.parts) === null || _msg$parts === void 0 ? void 0 : _msg$parts.filter((part) => part.type === "text").map((part) => part.text).join("")) ?? "";
|
|
6600
|
-
return {
|
|
6601
|
-
role: msg.role,
|
|
6602
|
-
content: textContent
|
|
6603
|
-
};
|
|
6604
|
-
});
|
|
6605
|
-
}
|
|
6606
|
-
/**
|
|
6607
|
-
* Creates an Express handler for the admin chat endpoint.
|
|
6608
|
-
*
|
|
6609
|
-
* Usage in thin wrappers:
|
|
6610
|
-
*
|
|
6611
|
-
* ```typescript
|
|
6612
|
-
* // With OpenAI
|
|
6613
|
-
* import { openai } from '@ai-sdk/openai'
|
|
6614
|
-
* app.post('/api/admin/chat', createAdminChatHandler({
|
|
6615
|
-
* model: openai('gpt-4o-mini'),
|
|
6616
|
-
* }))
|
|
6617
|
-
*
|
|
6618
|
-
* // With Claude
|
|
6619
|
-
* import { anthropic } from '@ai-sdk/anthropic'
|
|
6620
|
-
* app.post('/api/admin/chat', createAdminChatHandler({
|
|
6621
|
-
* model: anthropic('claude-sonnet-4-20250514'),
|
|
6622
|
-
* }))
|
|
6623
|
-
* ```
|
|
6624
|
-
*/
|
|
6625
|
-
function createAdminChatHandler(options) {
|
|
6626
|
-
const { model, systemPrompt = "You are a helpful admin assistant for the App Catalog application. Help users manage apps, data sources, and MCP server configurations.", tools = {}, validateConfig } = options;
|
|
6627
|
-
return async (req, res) => {
|
|
6628
|
-
try {
|
|
6629
|
-
if (validateConfig) validateConfig();
|
|
6630
|
-
const { messages } = req.body;
|
|
6631
|
-
const coreMessages = convertToCoreMessages(messages);
|
|
6632
|
-
console.log("[Admin Chat] Received messages:", JSON.stringify(coreMessages, null, 2));
|
|
6633
|
-
console.log("[Admin Chat] Available tools:", Object.keys(tools));
|
|
6634
|
-
const response = streamText({
|
|
6635
|
-
model,
|
|
6636
|
-
system: systemPrompt,
|
|
6637
|
-
messages: coreMessages,
|
|
6638
|
-
tools,
|
|
6639
|
-
stopWhen: stepCountIs(5),
|
|
6640
|
-
onFinish: (event) => {
|
|
6641
|
-
console.log("[Admin Chat] Finished:", {
|
|
6642
|
-
finishReason: event.finishReason,
|
|
6643
|
-
usage: event.usage,
|
|
6644
|
-
hasText: !!event.text,
|
|
6645
|
-
textLength: event.text.length
|
|
6646
|
-
});
|
|
6647
|
-
}
|
|
6648
|
-
}).toUIMessageStreamResponse();
|
|
6649
|
-
response.headers.forEach((value, key) => {
|
|
6650
|
-
res.setHeader(key, value);
|
|
6651
|
-
});
|
|
6652
|
-
if (response.body) {
|
|
6653
|
-
const reader = response.body.getReader();
|
|
6654
|
-
const pump = async () => {
|
|
6655
|
-
const { done, value } = await reader.read();
|
|
6656
|
-
if (done) {
|
|
6657
|
-
res.end();
|
|
6658
|
-
return;
|
|
6659
|
-
}
|
|
6660
|
-
res.write(value);
|
|
6661
|
-
return pump();
|
|
6662
|
-
};
|
|
6663
|
-
await pump();
|
|
6664
|
-
} else {
|
|
6665
|
-
console.error("[Admin Chat] No response body");
|
|
6666
|
-
res.status(500).json({ error: "No response from AI model" });
|
|
6667
|
-
}
|
|
6668
|
-
} catch (error) {
|
|
6669
|
-
console.error("[Admin Chat] Error:", error);
|
|
6670
|
-
res.status(500).json({ error: "Failed to process chat request" });
|
|
6671
|
-
}
|
|
6672
|
-
};
|
|
6673
|
-
}
|
|
6674
|
-
|
|
6675
|
-
//#endregion
|
|
6676
|
-
//#region src/modules/admin/chat/createDatabaseTools.ts
|
|
5080
|
+
//#region src/modules/icons/iconUtils.ts
|
|
6677
5081
|
/**
|
|
6678
|
-
*
|
|
5082
|
+
* Get file extension from MIME type
|
|
6679
5083
|
*/
|
|
6680
|
-
function
|
|
5084
|
+
function getExtensionFromMimeType(mimeType) {
|
|
6681
5085
|
return {
|
|
6682
|
-
|
|
6683
|
-
|
|
6684
|
-
|
|
6685
|
-
|
|
6686
|
-
|
|
6687
|
-
|
|
6688
|
-
|
|
6689
|
-
|
|
6690
|
-
|
|
6691
|
-
|
|
6692
|
-
|
|
6693
|
-
FROM information_schema.columns
|
|
6694
|
-
WHERE table_name = '${tableName}' AND table_schema = 'public'`)).map((c) => ({
|
|
6695
|
-
name: c.column_name,
|
|
6696
|
-
type: c.data_type,
|
|
6697
|
-
nullable: c.is_nullable === "YES"
|
|
6698
|
-
}));
|
|
6699
|
-
}
|
|
6700
|
-
};
|
|
6701
|
-
}
|
|
6702
|
-
const querySchema = z.object({ sql: z.string().describe("The SELECT SQL query to execute") });
|
|
6703
|
-
const modifySchema = z.object({
|
|
6704
|
-
sql: z.string().describe("The INSERT, UPDATE, or DELETE SQL query to execute"),
|
|
6705
|
-
confirmed: z.boolean().describe("Must be true to execute destructive operations")
|
|
6706
|
-
});
|
|
6707
|
-
const schemaParamsSchema = z.object({ tableName: z.string().optional().describe("Specific table name to get columns for. If not provided, returns list of all tables.") });
|
|
6708
|
-
/**
|
|
6709
|
-
* Creates a DatabaseClient using the internal backend-core Prisma client.
|
|
6710
|
-
* This is a convenience function for apps that don't need to pass their own Prisma client.
|
|
6711
|
-
*/
|
|
6712
|
-
function createInternalDatabaseClient() {
|
|
6713
|
-
return createPrismaDatabaseClient(getDbClient());
|
|
5086
|
+
"image/svg+xml": "svg",
|
|
5087
|
+
"image/png": "png",
|
|
5088
|
+
"image/jpeg": "jpg",
|
|
5089
|
+
"image/jpg": "jpg",
|
|
5090
|
+
"image/webp": "webp",
|
|
5091
|
+
"image/gif": "gif",
|
|
5092
|
+
"image/bmp": "bmp",
|
|
5093
|
+
"image/tiff": "tiff",
|
|
5094
|
+
"image/x-icon": "ico",
|
|
5095
|
+
"image/vnd.microsoft.icon": "ico"
|
|
5096
|
+
}[mimeType.toLowerCase()] || "bin";
|
|
6714
5097
|
}
|
|
6715
5098
|
/**
|
|
6716
|
-
*
|
|
6717
|
-
*
|
|
6718
|
-
* The AI uses these internally - users interact via natural language.
|
|
6719
|
-
* Results are formatted as tables by the AI based on the system prompt.
|
|
6720
|
-
* Uses the internal backend-core Prisma client automatically.
|
|
5099
|
+
* Get file extension from filename
|
|
6721
5100
|
*/
|
|
6722
|
-
function
|
|
6723
|
-
|
|
6724
|
-
|
|
6725
|
-
|
|
6726
|
-
description: `Execute a SELECT query to read data from the database.
|
|
6727
|
-
Use this to list, search, or filter records from any table.
|
|
6728
|
-
Always use double quotes around table and column names for PostgreSQL (e.g., SELECT * FROM "App").
|
|
6729
|
-
Return results will be formatted as a table for the user.`,
|
|
6730
|
-
inputSchema: querySchema,
|
|
6731
|
-
execute: async ({ sql: sql$1 }) => {
|
|
6732
|
-
console.log(`Executing ${sql$1}`);
|
|
6733
|
-
if (!sql$1.trim().toUpperCase().startsWith("SELECT")) return { error: "Only SELECT queries are allowed with queryDatabase. Use modifyDatabase for changes." };
|
|
6734
|
-
try {
|
|
6735
|
-
const results = await db.query(sql$1);
|
|
6736
|
-
return {
|
|
6737
|
-
success: true,
|
|
6738
|
-
rowCount: Array.isArray(results) ? results.length : 0,
|
|
6739
|
-
data: results
|
|
6740
|
-
};
|
|
6741
|
-
} catch (error) {
|
|
6742
|
-
return {
|
|
6743
|
-
success: false,
|
|
6744
|
-
error: error instanceof Error ? error.message : "Query failed"
|
|
6745
|
-
};
|
|
6746
|
-
}
|
|
6747
|
-
}
|
|
6748
|
-
},
|
|
6749
|
-
modifyDatabase: {
|
|
6750
|
-
description: `Execute an INSERT, UPDATE, or DELETE query to modify data.
|
|
6751
|
-
Use double quotes around table and column names for PostgreSQL.
|
|
6752
|
-
IMPORTANT: Always ask for user confirmation before executing. Set confirmed=true only after user confirms.
|
|
6753
|
-
For UPDATE/DELETE, always include a WHERE clause to avoid affecting all rows.`,
|
|
6754
|
-
inputSchema: modifySchema,
|
|
6755
|
-
execute: async ({ sql: sql$1, confirmed }) => {
|
|
6756
|
-
if (!confirmed) return {
|
|
6757
|
-
needsConfirmation: true,
|
|
6758
|
-
message: "Please confirm you want to execute this operation.",
|
|
6759
|
-
sql: sql$1
|
|
6760
|
-
};
|
|
6761
|
-
const normalizedSql = sql$1.trim().toUpperCase();
|
|
6762
|
-
if (normalizedSql.startsWith("SELECT")) return { error: "Use queryDatabase for SELECT queries." };
|
|
6763
|
-
if ((normalizedSql.startsWith("UPDATE") || normalizedSql.startsWith("DELETE")) && !normalizedSql.includes("WHERE")) return {
|
|
6764
|
-
error: "UPDATE and DELETE queries must include a WHERE clause for safety.",
|
|
6765
|
-
sql: sql$1
|
|
6766
|
-
};
|
|
6767
|
-
try {
|
|
6768
|
-
const result = await db.execute(sql$1);
|
|
6769
|
-
return {
|
|
6770
|
-
success: true,
|
|
6771
|
-
affectedRows: result.affectedRows,
|
|
6772
|
-
message: `Operation completed. ${result.affectedRows} row(s) affected.`
|
|
6773
|
-
};
|
|
6774
|
-
} catch (error) {
|
|
6775
|
-
return {
|
|
6776
|
-
success: false,
|
|
6777
|
-
error: error instanceof Error ? error.message : "Operation failed"
|
|
6778
|
-
};
|
|
6779
|
-
}
|
|
6780
|
-
}
|
|
6781
|
-
},
|
|
6782
|
-
getDatabaseSchema: {
|
|
6783
|
-
description: `Get information about database tables and their columns.
|
|
6784
|
-
Use this to understand the database structure before writing queries.
|
|
6785
|
-
Call without tableName to list all tables, or with tableName to get columns for a specific table.`,
|
|
6786
|
-
inputSchema: schemaParamsSchema,
|
|
6787
|
-
execute: async ({ tableName }) => {
|
|
6788
|
-
try {
|
|
6789
|
-
if (tableName) return {
|
|
6790
|
-
success: true,
|
|
6791
|
-
table: tableName,
|
|
6792
|
-
columns: await db.getColumns(tableName)
|
|
6793
|
-
};
|
|
6794
|
-
else return {
|
|
6795
|
-
success: true,
|
|
6796
|
-
tables: await db.getTables()
|
|
6797
|
-
};
|
|
6798
|
-
} catch (error) {
|
|
6799
|
-
return {
|
|
6800
|
-
success: false,
|
|
6801
|
-
error: error instanceof Error ? error.message : "Failed to get schema"
|
|
6802
|
-
};
|
|
6803
|
-
}
|
|
6804
|
-
}
|
|
6805
|
-
}
|
|
6806
|
-
};
|
|
5101
|
+
function getExtensionFromFilename(filename) {
|
|
5102
|
+
var _match$;
|
|
5103
|
+
const match = filename.match(/\.([^.]+)$/);
|
|
5104
|
+
return (match === null || match === void 0 || (_match$ = match[1]) === null || _match$ === void 0 ? void 0 : _match$.toLowerCase()) || "";
|
|
6807
5105
|
}
|
|
6808
|
-
/**
|
|
6809
|
-
* Default system prompt for the database admin assistant.
|
|
6810
|
-
* Can be customized or extended.
|
|
6811
|
-
*/
|
|
6812
|
-
const DEFAULT_ADMIN_SYSTEM_PROMPT = `You are a helpful database admin assistant. You help users view and manage data in the database.
|
|
6813
|
-
|
|
6814
|
-
IMPORTANT RULES:
|
|
6815
|
-
1. When showing data, ALWAYS format it as a numbered ASCII table so users can reference rows by number
|
|
6816
|
-
2. NEVER show raw SQL to users - just describe what you're doing in plain language
|
|
6817
|
-
3. When users ask to modify data (update, delete, create), ALWAYS confirm before executing
|
|
6818
|
-
4. For updates, show the current value and ask for confirmation before changing
|
|
6819
|
-
5. Keep responses concise and focused on the data
|
|
6820
|
-
|
|
6821
|
-
FORMATTING EXAMPLE:
|
|
6822
|
-
When user asks "show me all apps", respond like:
|
|
6823
|
-
"Here are all the apps:
|
|
6824
|
-
|
|
6825
|
-
| # | ID | Slug | Display Name | Icon |
|
|
6826
|
-
|---|----|---------|-----------------| -------|
|
|
6827
|
-
| 1 | 1 | portal | Portal | portal |
|
|
6828
|
-
| 2 | 2 | admin | Admin Dashboard | admin |
|
|
6829
|
-
| 3 | 3 | api | API Service | null |
|
|
6830
|
-
|
|
6831
|
-
Found 3 apps total."
|
|
6832
|
-
|
|
6833
|
-
When user says "update row 2 display name to 'Admin Panel'":
|
|
6834
|
-
1. First confirm: "I'll update the app 'Admin Dashboard' (ID: 2) to have display name 'Admin Panel'. Proceed?"
|
|
6835
|
-
2. Only after user confirms, execute the update
|
|
6836
|
-
3. Then show the updated row
|
|
6837
|
-
|
|
6838
|
-
AVAILABLE TABLES:
|
|
6839
|
-
Use getDatabaseSchema tool to discover tables and their columns.
|
|
6840
|
-
`;
|
|
6841
5106
|
|
|
6842
5107
|
//#endregion
|
|
6843
5108
|
//#region src/modules/icons/iconRestController.ts
|
|
@@ -6868,17 +5133,17 @@ function registerIconRestController(router$1, config$1) {
|
|
|
6868
5133
|
res.status(400).json({ error: "No file uploaded" });
|
|
6869
5134
|
return;
|
|
6870
5135
|
}
|
|
6871
|
-
let name
|
|
6872
|
-
if (!name
|
|
5136
|
+
let name = req.body["name"];
|
|
5137
|
+
if (!name) {
|
|
6873
5138
|
res.status(400).json({ error: "Name is required" });
|
|
6874
5139
|
return;
|
|
6875
5140
|
}
|
|
6876
5141
|
const extension = getExtensionFromFilename(req.file.originalname) || getExtensionFromMimeType(req.file.mimetype);
|
|
6877
|
-
if (!name
|
|
5142
|
+
if (!name.includes(".")) name = `${name}.${extension}`;
|
|
6878
5143
|
const prisma = getDbClient();
|
|
6879
5144
|
const checksum = createHash("sha256").update(req.file.buffer).digest("hex");
|
|
6880
5145
|
const icon = await prisma.dbAsset.create({ data: {
|
|
6881
|
-
name
|
|
5146
|
+
name,
|
|
6882
5147
|
assetType: "icon",
|
|
6883
5148
|
content: new Uint8Array(req.file.buffer),
|
|
6884
5149
|
mimeType: req.file.mimetype,
|
|
@@ -6899,10 +5164,10 @@ function registerIconRestController(router$1, config$1) {
|
|
|
6899
5164
|
});
|
|
6900
5165
|
router$1.get(`${basePath}/:name`, async (req, res) => {
|
|
6901
5166
|
try {
|
|
6902
|
-
const { name
|
|
5167
|
+
const { name } = req.params;
|
|
6903
5168
|
const icon = await getDbClient().dbAsset.findFirst({
|
|
6904
5169
|
where: {
|
|
6905
|
-
name
|
|
5170
|
+
name,
|
|
6906
5171
|
assetType: "icon"
|
|
6907
5172
|
},
|
|
6908
5173
|
select: {
|
|
@@ -6926,10 +5191,10 @@ function registerIconRestController(router$1, config$1) {
|
|
|
6926
5191
|
});
|
|
6927
5192
|
router$1.get(`${basePath}/:name/metadata`, async (req, res) => {
|
|
6928
5193
|
try {
|
|
6929
|
-
const { name
|
|
5194
|
+
const { name } = req.params;
|
|
6930
5195
|
const icon = await getDbClient().dbAsset.findFirst({
|
|
6931
5196
|
where: {
|
|
6932
|
-
name
|
|
5197
|
+
name,
|
|
6933
5198
|
assetType: "icon"
|
|
6934
5199
|
},
|
|
6935
5200
|
select: {
|
|
@@ -7002,9 +5267,9 @@ async function upsertIcons(icons) {
|
|
|
7002
5267
|
* Get an asset (icon or screenshot) by name from the database.
|
|
7003
5268
|
* Returns the asset content, mimeType, and name if found.
|
|
7004
5269
|
*/
|
|
7005
|
-
async function getAssetByName(name
|
|
5270
|
+
async function getAssetByName(name) {
|
|
7006
5271
|
return getDbClient().dbAsset.findUnique({
|
|
7007
|
-
where: { name
|
|
5272
|
+
where: { name },
|
|
7008
5273
|
select: {
|
|
7009
5274
|
content: true,
|
|
7010
5275
|
mimeType: true,
|
|
@@ -7044,16 +5309,16 @@ function registerAssetRestController(router$1, config$1) {
|
|
|
7044
5309
|
res.status(400).json({ error: "No file uploaded" });
|
|
7045
5310
|
return;
|
|
7046
5311
|
}
|
|
7047
|
-
const name
|
|
5312
|
+
const name = req.body["name"];
|
|
7048
5313
|
const assetType = req.body["assetType"];
|
|
7049
|
-
if (!name
|
|
5314
|
+
if (!name) {
|
|
7050
5315
|
res.status(400).json({ error: "Name is required" });
|
|
7051
5316
|
return;
|
|
7052
5317
|
}
|
|
7053
5318
|
const id = await upsertAsset({
|
|
7054
5319
|
prisma,
|
|
7055
5320
|
buffer: req.file.buffer,
|
|
7056
|
-
name
|
|
5321
|
+
name,
|
|
7057
5322
|
originalFilename: req.file.filename,
|
|
7058
5323
|
assetType
|
|
7059
5324
|
});
|
|
@@ -7129,9 +5394,9 @@ function registerAssetRestController(router$1, config$1) {
|
|
|
7129
5394
|
});
|
|
7130
5395
|
router$1.get(`${basePath}/by-name/:name`, async (req, res) => {
|
|
7131
5396
|
try {
|
|
7132
|
-
const { name
|
|
5397
|
+
const { name } = req.params;
|
|
7133
5398
|
const asset = await prisma.dbAsset.findUnique({
|
|
7134
|
-
where: { name
|
|
5399
|
+
where: { name },
|
|
7135
5400
|
select: {
|
|
7136
5401
|
content: true,
|
|
7137
5402
|
mimeType: true,
|
|
@@ -7685,29 +5950,6 @@ function printLinkCheckReport(report) {
|
|
|
7685
5950
|
else console.log("\n✅ All links are working!");
|
|
7686
5951
|
}
|
|
7687
5952
|
|
|
7688
|
-
//#endregion
|
|
7689
|
-
//#region src/modules/approvalMethod/syncApprovalMethods.ts
|
|
7690
|
-
/**
|
|
7691
|
-
* Syncs approval methods to the database using upsert logic based on type + displayName.
|
|
7692
|
-
*
|
|
7693
|
-
* @param prisma - The PrismaClient instance from the backend-core database
|
|
7694
|
-
* @param methods - Array of approval methods to sync
|
|
7695
|
-
*/
|
|
7696
|
-
async function syncApprovalMethods(prisma, methods) {
|
|
7697
|
-
await prisma.$transaction(methods.map((method) => prisma.dbApprovalMethod.upsert({
|
|
7698
|
-
where: { slug: method.slug },
|
|
7699
|
-
update: {
|
|
7700
|
-
displayName: method.displayName,
|
|
7701
|
-
type: method.type
|
|
7702
|
-
},
|
|
7703
|
-
create: {
|
|
7704
|
-
slug: method.slug,
|
|
7705
|
-
type: method.type,
|
|
7706
|
-
displayName: method.displayName
|
|
7707
|
-
}
|
|
7708
|
-
})));
|
|
7709
|
-
}
|
|
7710
|
-
|
|
7711
5953
|
//#endregion
|
|
7712
5954
|
//#region src/middleware/database.ts
|
|
7713
5955
|
/**
|
|
@@ -7737,7 +5979,7 @@ var EhDatabaseManager = class {
|
|
|
7737
5979
|
const datasourceUrl = formatConnectionUrl(this.config);
|
|
7738
5980
|
this.pool = new esm_default.Pool({ connectionString: datasourceUrl });
|
|
7739
5981
|
this.client = new PrismaClient({
|
|
7740
|
-
adapter: new
|
|
5982
|
+
adapter: new PrismaPg(this.pool),
|
|
7741
5983
|
log: process.env.NODE_ENV === "development" ? ["warn", "error"] : ["warn", "error"]
|
|
7742
5984
|
});
|
|
7743
5985
|
setDbClient(this.client);
|
|
@@ -7783,154 +6025,6 @@ function createBackendResolver(provider) {
|
|
|
7783
6025
|
throw new Error("Invalid backend provider: must be an object implementing AppCatalogCompanySpecificBackend or a factory function");
|
|
7784
6026
|
}
|
|
7785
6027
|
|
|
7786
|
-
//#endregion
|
|
7787
|
-
//#region src/modules/appCatalogAdmin/catalogBackupController.ts
|
|
7788
|
-
/**
|
|
7789
|
-
* Export the complete app catalog as JSON
|
|
7790
|
-
* Includes all fields from DbAppForCatalog and DbApprovalMethod
|
|
7791
|
-
*/
|
|
7792
|
-
async function exportCatalog(_req, res) {
|
|
7793
|
-
try {
|
|
7794
|
-
const prisma = getDbClient();
|
|
7795
|
-
const apps = await prisma.dbAppForCatalog.findMany({ orderBy: { slug: "asc" } });
|
|
7796
|
-
const approvalMethods = await prisma.dbApprovalMethod.findMany({ orderBy: { displayName: "asc" } });
|
|
7797
|
-
res.json({
|
|
7798
|
-
version: "2.0",
|
|
7799
|
-
exportDate: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7800
|
-
apps,
|
|
7801
|
-
approvalMethods
|
|
7802
|
-
});
|
|
7803
|
-
} catch (error) {
|
|
7804
|
-
console.error("Error exporting catalog:", error);
|
|
7805
|
-
res.status(500).json({ error: "Failed to export catalog" });
|
|
7806
|
-
}
|
|
7807
|
-
}
|
|
7808
|
-
/**
|
|
7809
|
-
* Import/restore the complete app catalog from JSON
|
|
7810
|
-
* Overwrites existing data
|
|
7811
|
-
*/
|
|
7812
|
-
async function importCatalog(req, res) {
|
|
7813
|
-
try {
|
|
7814
|
-
const prisma = getDbClient();
|
|
7815
|
-
const { apps, approvalMethods } = req.body;
|
|
7816
|
-
if (!Array.isArray(apps)) {
|
|
7817
|
-
res.status(400).json({ error: "Invalid data format: apps must be an array" });
|
|
7818
|
-
return;
|
|
7819
|
-
}
|
|
7820
|
-
await prisma.$transaction(async (tx) => {
|
|
7821
|
-
if (Array.isArray(approvalMethods)) await tx.dbApprovalMethod.deleteMany({});
|
|
7822
|
-
await tx.dbAppForCatalog.deleteMany({});
|
|
7823
|
-
if (Array.isArray(approvalMethods)) for (const method of approvalMethods) {
|
|
7824
|
-
const { id, createdAt, updatedAt,...methodData } = method;
|
|
7825
|
-
await tx.dbApprovalMethod.create({ data: methodData });
|
|
7826
|
-
}
|
|
7827
|
-
for (const app of apps) {
|
|
7828
|
-
const { id, createdAt, updatedAt,...appData } = app;
|
|
7829
|
-
await tx.dbAppForCatalog.create({ data: appData });
|
|
7830
|
-
}
|
|
7831
|
-
});
|
|
7832
|
-
res.json({
|
|
7833
|
-
success: true,
|
|
7834
|
-
imported: {
|
|
7835
|
-
apps: apps.length,
|
|
7836
|
-
approvalMethods: Array.isArray(approvalMethods) ? approvalMethods.length : 0
|
|
7837
|
-
}
|
|
7838
|
-
});
|
|
7839
|
-
} catch (error) {
|
|
7840
|
-
console.error("Error importing catalog:", error);
|
|
7841
|
-
res.status(500).json({ error: "Failed to import catalog" });
|
|
7842
|
-
}
|
|
7843
|
-
}
|
|
7844
|
-
/**
|
|
7845
|
-
* Export an asset (icon or screenshot) by name
|
|
7846
|
-
*/
|
|
7847
|
-
async function exportAsset(req, res) {
|
|
7848
|
-
try {
|
|
7849
|
-
const { name: name$1 } = req.params;
|
|
7850
|
-
const asset = await getDbClient().dbAsset.findUnique({ where: { name: name$1 } });
|
|
7851
|
-
if (!asset) {
|
|
7852
|
-
res.status(404).json({ error: "Asset not found" });
|
|
7853
|
-
return;
|
|
7854
|
-
}
|
|
7855
|
-
res.set("Content-Type", asset.mimeType);
|
|
7856
|
-
res.set("Content-Disposition", `attachment; filename="${name$1}"`);
|
|
7857
|
-
res.send(Buffer.from(asset.content));
|
|
7858
|
-
} catch (error) {
|
|
7859
|
-
console.error("Error exporting asset:", error);
|
|
7860
|
-
res.status(500).json({ error: "Failed to export asset" });
|
|
7861
|
-
}
|
|
7862
|
-
}
|
|
7863
|
-
/**
|
|
7864
|
-
* List all assets with metadata
|
|
7865
|
-
*/
|
|
7866
|
-
async function listAssets(_req, res) {
|
|
7867
|
-
try {
|
|
7868
|
-
const assets = await getDbClient().dbAsset.findMany({
|
|
7869
|
-
select: {
|
|
7870
|
-
id: true,
|
|
7871
|
-
name: true,
|
|
7872
|
-
assetType: true,
|
|
7873
|
-
mimeType: true,
|
|
7874
|
-
fileSize: true,
|
|
7875
|
-
width: true,
|
|
7876
|
-
height: true,
|
|
7877
|
-
checksum: true
|
|
7878
|
-
},
|
|
7879
|
-
orderBy: { name: "asc" }
|
|
7880
|
-
});
|
|
7881
|
-
res.json({ assets });
|
|
7882
|
-
} catch (error) {
|
|
7883
|
-
console.error("Error listing assets:", error);
|
|
7884
|
-
res.status(500).json({ error: "Failed to list assets" });
|
|
7885
|
-
}
|
|
7886
|
-
}
|
|
7887
|
-
/**
|
|
7888
|
-
* Import an asset (icon or screenshot)
|
|
7889
|
-
*/
|
|
7890
|
-
async function importAsset(req, res) {
|
|
7891
|
-
try {
|
|
7892
|
-
const file = req.file;
|
|
7893
|
-
const { name: name$1, assetType, mimeType, width, height } = req.body;
|
|
7894
|
-
if (!file) {
|
|
7895
|
-
res.status(400).json({ error: "No file uploaded" });
|
|
7896
|
-
return;
|
|
7897
|
-
}
|
|
7898
|
-
const prisma = getDbClient();
|
|
7899
|
-
const checksum = (await import("node:crypto")).createHash("sha256").update(file.buffer).digest("hex");
|
|
7900
|
-
const content = new Uint8Array(file.buffer);
|
|
7901
|
-
await prisma.dbAsset.upsert({
|
|
7902
|
-
where: { name: name$1 },
|
|
7903
|
-
update: {
|
|
7904
|
-
content,
|
|
7905
|
-
checksum,
|
|
7906
|
-
mimeType: mimeType || file.mimetype,
|
|
7907
|
-
fileSize: file.size,
|
|
7908
|
-
width: width ? parseInt(width) : null,
|
|
7909
|
-
height: height ? parseInt(height) : null,
|
|
7910
|
-
assetType: assetType || "icon"
|
|
7911
|
-
},
|
|
7912
|
-
create: {
|
|
7913
|
-
name: name$1,
|
|
7914
|
-
content,
|
|
7915
|
-
checksum,
|
|
7916
|
-
mimeType: mimeType || file.mimetype,
|
|
7917
|
-
fileSize: file.size,
|
|
7918
|
-
width: width ? parseInt(width) : null,
|
|
7919
|
-
height: height ? parseInt(height) : null,
|
|
7920
|
-
assetType: assetType || "icon"
|
|
7921
|
-
}
|
|
7922
|
-
});
|
|
7923
|
-
res.json({
|
|
7924
|
-
success: true,
|
|
7925
|
-
name: name$1,
|
|
7926
|
-
size: file.size
|
|
7927
|
-
});
|
|
7928
|
-
} catch (error) {
|
|
7929
|
-
console.error("Error importing asset:", error);
|
|
7930
|
-
res.status(500).json({ error: "Failed to import asset" });
|
|
7931
|
-
}
|
|
7932
|
-
}
|
|
7933
|
-
|
|
7934
6028
|
//#endregion
|
|
7935
6029
|
//#region src/modules/auth/devMockUserUtils.ts
|
|
7936
6030
|
/**
|
|
@@ -7974,64 +6068,54 @@ function createMockSessionResponse(devUser) {
|
|
|
7974
6068
|
|
|
7975
6069
|
//#endregion
|
|
7976
6070
|
//#region src/middleware/featureRegistry.ts
|
|
7977
|
-
const FEATURES = [
|
|
7978
|
-
|
|
7979
|
-
|
|
7980
|
-
|
|
7981
|
-
|
|
7982
|
-
|
|
7983
|
-
|
|
7984
|
-
|
|
7985
|
-
|
|
7986
|
-
res.json(createMockSessionResponse(ctx.authConfig.devMockUser));
|
|
7987
|
-
return;
|
|
7988
|
-
}
|
|
7989
|
-
const session = await ctx.auth.api.getSession({ headers: req.headers });
|
|
7990
|
-
if (session) res.json(session);
|
|
7991
|
-
else res.status(401).json({ error: "Not authenticated" });
|
|
7992
|
-
} catch (error) {
|
|
7993
|
-
console.error("[Auth Session Error]", error);
|
|
7994
|
-
res.status(500).json({ error: "Internal server error" });
|
|
7995
|
-
}
|
|
7996
|
-
});
|
|
7997
|
-
const authHandler = toNodeHandler(ctx.auth);
|
|
7998
|
-
router$1.all(`${basePath}/auth/{*any}`, authHandler);
|
|
7999
|
-
}
|
|
8000
|
-
},
|
|
8001
|
-
{
|
|
8002
|
-
name: "adminChat",
|
|
8003
|
-
defaultEnabled: false,
|
|
8004
|
-
register: (router$1, options) => {
|
|
8005
|
-
if (options.adminChat) router$1.post(`${options.basePath}/admin/chat`, createAdminChatHandler(options.adminChat));
|
|
8006
|
-
}
|
|
8007
|
-
},
|
|
8008
|
-
{
|
|
8009
|
-
name: "legacyIconEndpoint",
|
|
8010
|
-
defaultEnabled: false,
|
|
8011
|
-
register: (router$1) => {
|
|
8012
|
-
router$1.get("/static/icon/:icon", async (req, res) => {
|
|
8013
|
-
const { icon } = req.params;
|
|
8014
|
-
if (!icon || !/^[a-z0-9-]+$/i.test(icon)) {
|
|
8015
|
-
res.status(400).send("Invalid icon name");
|
|
6071
|
+
const FEATURES = [{
|
|
6072
|
+
name: "auth",
|
|
6073
|
+
defaultEnabled: true,
|
|
6074
|
+
register: (router$1, options, ctx) => {
|
|
6075
|
+
const basePath = options.basePath;
|
|
6076
|
+
router$1.get(`${basePath}/auth/session`, async (req, res) => {
|
|
6077
|
+
try {
|
|
6078
|
+
if (ctx.authConfig.devMockUser) {
|
|
6079
|
+
res.json(createMockSessionResponse(ctx.authConfig.devMockUser));
|
|
8016
6080
|
return;
|
|
8017
6081
|
}
|
|
8018
|
-
|
|
8019
|
-
|
|
8020
|
-
|
|
8021
|
-
|
|
8022
|
-
|
|
8023
|
-
|
|
8024
|
-
|
|
8025
|
-
|
|
8026
|
-
|
|
8027
|
-
|
|
8028
|
-
|
|
6082
|
+
const session = await ctx.auth.api.getSession({ headers: req.headers });
|
|
6083
|
+
if (session) res.json(session);
|
|
6084
|
+
else res.status(401).json({ error: "Not authenticated" });
|
|
6085
|
+
} catch (error) {
|
|
6086
|
+
console.error("[Auth Session Error]", error);
|
|
6087
|
+
res.status(500).json({ error: "Internal server error" });
|
|
6088
|
+
}
|
|
6089
|
+
});
|
|
6090
|
+
const authHandler = toNodeHandler(ctx.auth);
|
|
6091
|
+
router$1.all(`${basePath}/auth/{*any}`, authHandler);
|
|
6092
|
+
}
|
|
6093
|
+
}, {
|
|
6094
|
+
name: "legacyIconEndpoint",
|
|
6095
|
+
defaultEnabled: false,
|
|
6096
|
+
register: (router$1) => {
|
|
6097
|
+
router$1.get("/static/icon/:icon", async (req, res) => {
|
|
6098
|
+
const { icon } = req.params;
|
|
6099
|
+
if (!icon || !/^[a-z0-9-]+$/i.test(icon)) {
|
|
6100
|
+
res.status(400).send("Invalid icon name");
|
|
6101
|
+
return;
|
|
6102
|
+
}
|
|
6103
|
+
try {
|
|
6104
|
+
const dbIcon = await getAssetByName(icon);
|
|
6105
|
+
if (!dbIcon) {
|
|
8029
6106
|
res.status(404).send("Icon not found");
|
|
6107
|
+
return;
|
|
8030
6108
|
}
|
|
8031
|
-
|
|
8032
|
-
|
|
6109
|
+
res.setHeader("Content-Type", dbIcon.mimeType);
|
|
6110
|
+
res.setHeader("Cache-Control", "public, max-age=86400");
|
|
6111
|
+
res.send(dbIcon.content);
|
|
6112
|
+
} catch (error) {
|
|
6113
|
+
console.error("Error fetching icon:", error);
|
|
6114
|
+
res.status(404).send("Icon not found");
|
|
6115
|
+
}
|
|
6116
|
+
});
|
|
8033
6117
|
}
|
|
8034
|
-
];
|
|
6118
|
+
}];
|
|
8035
6119
|
/**
|
|
8036
6120
|
* Registers all enabled features on the router.
|
|
8037
6121
|
*/
|
|
@@ -8040,18 +6124,8 @@ function registerFeatures(router$1, options, context) {
|
|
|
8040
6124
|
registerIconRestController(router$1, { basePath: `${basePath}/icons` });
|
|
8041
6125
|
registerAssetRestController(router$1, { basePath: `${basePath}/assets` });
|
|
8042
6126
|
registerScreenshotRestController(router$1, { basePath: `${basePath}/screenshots` });
|
|
8043
|
-
const upload$2 = multer({ storage: multer.memoryStorage() });
|
|
8044
|
-
router$1.get(`${basePath}/catalog/backup/export`, exportCatalog);
|
|
8045
|
-
router$1.post(`${basePath}/catalog/backup/import`, importCatalog);
|
|
8046
|
-
router$1.get(`${basePath}/catalog/backup/assets`, listAssets);
|
|
8047
|
-
router$1.get(`${basePath}/catalog/backup/assets/:name`, exportAsset);
|
|
8048
|
-
router$1.post(`${basePath}/catalog/backup/assets`, upload$2.single("file"), importAsset);
|
|
8049
6127
|
const toggles = options.features || {};
|
|
8050
|
-
for (const feature of FEATURES)
|
|
8051
|
-
const isEnabled = toggles[feature.name] ?? feature.defaultEnabled;
|
|
8052
|
-
if (feature.name === "adminChat" && !options.adminChat) continue;
|
|
8053
|
-
if (isEnabled) feature.register(router$1, options, context);
|
|
8054
|
-
}
|
|
6128
|
+
for (const feature of FEATURES) if (toggles[feature.name] ?? feature.defaultEnabled) feature.register(router$1, options, context);
|
|
8055
6129
|
}
|
|
8056
6130
|
|
|
8057
6131
|
//#endregion
|
|
@@ -8172,5 +6246,5 @@ function injectCustomScripts(html, scriptUrls) {
|
|
|
8172
6246
|
}
|
|
8173
6247
|
|
|
8174
6248
|
//#endregion
|
|
8175
|
-
export {
|
|
6249
|
+
export { EhDatabaseManager, TABLE_SYNC_MAGAZINE, checkAllLinks, connectDb, createAuth, createAuthRouter, createEhMiddleware, createEhTrpcContext, createTrpcRouter, disconnectDb, getAssetByName, getDbClient, getUserGroups, injectCustomScripts, isAdmin, isMemberOfAllGroups, isMemberOfAnyGroup, printLinkCheckReport, registerAssetRestController, registerAuthRoutes, registerIconRestController, registerScreenshotRestController, requireAdmin, requireGroups, setDbClient, staticControllerContract, syncAppCatalog, syncAssets, tableSyncPrisma, upsertIcon, upsertIcons };
|
|
8176
6250
|
//# sourceMappingURL=index.js.map
|