@igstack/app-catalog-backend-core 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/LICENSE +21 -0
  2. package/dist/index.d.ts +1934 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +2539 -0
  5. package/dist/index.js.map +1 -0
  6. package/package.json +84 -0
  7. package/prisma/migrations/20250526183023_init/migration.sql +71 -0
  8. package/prisma/migrations/migration_lock.toml +3 -0
  9. package/prisma/schema.prisma +149 -0
  10. package/src/__tests__/dummy.test.ts +7 -0
  11. package/src/db/client.ts +42 -0
  12. package/src/db/index.ts +21 -0
  13. package/src/db/syncAppCatalog.ts +312 -0
  14. package/src/db/tableSyncMagazine.ts +32 -0
  15. package/src/db/tableSyncPrismaAdapter.ts +203 -0
  16. package/src/index.ts +126 -0
  17. package/src/middleware/backendResolver.ts +42 -0
  18. package/src/middleware/createEhMiddleware.ts +171 -0
  19. package/src/middleware/database.ts +62 -0
  20. package/src/middleware/featureRegistry.ts +173 -0
  21. package/src/middleware/index.ts +43 -0
  22. package/src/middleware/types.ts +202 -0
  23. package/src/modules/admin/chat/createAdminChatHandler.ts +152 -0
  24. package/src/modules/admin/chat/createDatabaseTools.ts +261 -0
  25. package/src/modules/appCatalog/service.ts +130 -0
  26. package/src/modules/appCatalogAdmin/appCatalogAdminRouter.ts +187 -0
  27. package/src/modules/appCatalogAdmin/catalogBackupController.ts +213 -0
  28. package/src/modules/approvalMethod/approvalMethodRouter.ts +169 -0
  29. package/src/modules/approvalMethod/slugUtils.ts +17 -0
  30. package/src/modules/approvalMethod/syncApprovalMethods.ts +38 -0
  31. package/src/modules/assets/assetRestController.ts +271 -0
  32. package/src/modules/assets/assetUtils.ts +114 -0
  33. package/src/modules/assets/screenshotRestController.ts +195 -0
  34. package/src/modules/assets/screenshotRouter.ts +112 -0
  35. package/src/modules/assets/syncAssets.ts +277 -0
  36. package/src/modules/assets/upsertAsset.ts +46 -0
  37. package/src/modules/auth/auth.ts +51 -0
  38. package/src/modules/auth/authProviders.ts +40 -0
  39. package/src/modules/auth/authRouter.ts +75 -0
  40. package/src/modules/auth/authorizationUtils.ts +132 -0
  41. package/src/modules/auth/devMockUserUtils.ts +49 -0
  42. package/src/modules/auth/registerAuthRoutes.ts +33 -0
  43. package/src/modules/icons/iconRestController.ts +171 -0
  44. package/src/modules/icons/iconRouter.ts +180 -0
  45. package/src/modules/icons/iconService.ts +73 -0
  46. package/src/modules/icons/iconUtils.ts +46 -0
  47. package/src/prisma-json-types.d.ts +34 -0
  48. package/src/server/controller.ts +47 -0
  49. package/src/server/ehStaticControllerContract.ts +19 -0
  50. package/src/server/ehTrpcContext.ts +26 -0
  51. package/src/server/trpcSetup.ts +89 -0
  52. package/src/types/backend/api.ts +73 -0
  53. package/src/types/backend/common.ts +10 -0
  54. package/src/types/backend/companySpecificBackend.ts +5 -0
  55. package/src/types/backend/dataSources.ts +25 -0
  56. package/src/types/backend/deployments.ts +40 -0
  57. package/src/types/common/app/appTypes.ts +13 -0
  58. package/src/types/common/app/ui/appUiTypes.ts +12 -0
  59. package/src/types/common/appCatalogTypes.ts +65 -0
  60. package/src/types/common/approvalMethodTypes.ts +149 -0
  61. package/src/types/common/env/envTypes.ts +7 -0
  62. package/src/types/common/resourceTypes.ts +8 -0
  63. package/src/types/common/sharedTypes.ts +5 -0
  64. package/src/types/index.ts +21 -0
@@ -0,0 +1,1934 @@
1
+ import * as _prisma_client0 from "@prisma/client";
2
+ import { Prisma, PrismaClient } from "@prisma/client";
3
+ import * as _trpc_server0 from "@trpc/server";
4
+ import { TRPCRootObject } from "@trpc/server";
5
+ import * as better_auth0 from "better-auth";
6
+ import { BetterAuthOptions, BetterAuthPlugin } from "better-auth";
7
+ import { LanguageModel, Tool, tool } from "ai";
8
+ import { Express, Request, Response, Router } from "express";
9
+ import { User } from "better-auth/types";
10
+ import * as _prisma_client_runtime_library0 from "@prisma/client/runtime/library";
11
+
12
+ //#region src/types/common/sharedTypes.d.ts
13
+ interface EhMetaDictionary {
14
+ [key: string]: string | null | Record<string, string | null>;
15
+ }
16
+ type Tag = string;
17
+ //#endregion
18
+ //#region src/types/common/resourceTypes.d.ts
19
+ /**
20
+ * Resources like kafka topics, database tables, etc.
21
+ */
22
+ interface EhResourceIndexed {
23
+ slug: string;
24
+ displayName: string;
25
+ defaultFixedValues?: Array<string>;
26
+ }
27
+ //#endregion
28
+ //#region src/types/common/approvalMethodTypes.d.ts
29
+ /**
30
+ * Approval Method Types
31
+ *
32
+ * Global approval method templates that apps can link to.
33
+ * Each method has a type (service, personTeam, custom) with type-specific config.
34
+ */
35
+ type ApprovalMethodType = 'service' | 'personTeam' | 'custom';
36
+ /**
37
+ * Contact for reaching out (not necessarily the approver)
38
+ */
39
+ interface ReachOutContact {
40
+ displayName: string;
41
+ contact: string;
42
+ }
43
+ /**
44
+ * Service type config - for bots, ticketing systems, self-service portals
45
+ */
46
+ interface ServiceConfig {
47
+ url?: string;
48
+ icon?: string;
49
+ }
50
+ /**
51
+ * Person/Team type config - for human approvers
52
+ */
53
+ interface PersonTeamConfig {
54
+ reachOutContacts?: Array<ReachOutContact>;
55
+ }
56
+ /**
57
+ * Custom type config - generic, no additional fields
58
+ */
59
+ interface CustomConfig {}
60
+ /**
61
+ * Union of all config types
62
+ */
63
+ type ApprovalMethodConfig = ServiceConfig | PersonTeamConfig | CustomConfig;
64
+ /**
65
+ * Approval Method - stored in DbApprovalMethod
66
+ */
67
+ type ApprovalMethod = {
68
+ slug: string;
69
+ displayName: string;
70
+ createdAt?: Date;
71
+ updatedAt?: Date;
72
+ } & ({
73
+ type: 'service';
74
+ config: ServiceConfig;
75
+ } | {
76
+ type: 'personTeam';
77
+ config: PersonTeamConfig;
78
+ } | {
79
+ type: 'custom';
80
+ config: CustomConfig;
81
+ });
82
+ /**
83
+ * Role that can be requested for an app
84
+ */
85
+ interface AppRole {
86
+ displayName: string;
87
+ description?: string;
88
+ adminNotes?: string;
89
+ }
90
+ /**
91
+ * Approver contact (person who approves, may differ from reach-out contact)
92
+ */
93
+ interface ApproverContact {
94
+ displayName: string;
95
+ contact?: string;
96
+ }
97
+ /**
98
+ * URL link with optional label
99
+ */
100
+ interface ApprovalUrl {
101
+ label?: string;
102
+ url: string;
103
+ }
104
+ /**
105
+ * Per-app approval details - stored as JSON in DbAppForCatalog
106
+ * All comment/text-like strings are markdown
107
+ */
108
+ interface AppAccessRequest {
109
+ approvalMethodId: string;
110
+ comments?: string;
111
+ requestPrompt?: string;
112
+ postApprovalInstructions?: string;
113
+ roles?: Array<AppRole>;
114
+ approvers?: Array<ApproverContact>;
115
+ urls?: Array<ApprovalUrl>;
116
+ whoToReachOut?: string;
117
+ }
118
+ interface CreateApprovalMethodInput {
119
+ type: ApprovalMethodType;
120
+ displayName: string;
121
+ config?: ApprovalMethodConfig;
122
+ }
123
+ interface UpdateApprovalMethodInput {
124
+ id: string;
125
+ type?: ApprovalMethodType;
126
+ displayName?: string;
127
+ config?: ApprovalMethodConfig;
128
+ }
129
+ //#endregion
130
+ //#region src/types/common/appCatalogTypes.d.ts
131
+ /**
132
+ * Application entry in the catalog
133
+ */
134
+ interface AppForCatalog {
135
+ id: string;
136
+ slug: string;
137
+ displayName: string;
138
+ description?: string;
139
+ teams?: Array<string>;
140
+ accessRequest?: AppAccessRequest;
141
+ notes?: string;
142
+ tags?: Array<string>;
143
+ appUrl?: string;
144
+ links?: Array<{
145
+ url: string;
146
+ title?: string;
147
+ }>;
148
+ iconName?: string;
149
+ screenshotIds?: Array<string>;
150
+ }
151
+ interface AppCategory {
152
+ id: string;
153
+ name: string;
154
+ }
155
+ interface GroupingTagDefinition {
156
+ prefix: string;
157
+ displayName: string;
158
+ description: string;
159
+ values: Array<GroupingTagValue>;
160
+ }
161
+ type DistributiveOmit<T, TKey extends keyof any> = T extends any ? Omit<T, TKey> : never;
162
+ type AppApprovalMethod = DistributiveOmit<ApprovalMethod, 'createdAt' | 'updatedAt'>;
163
+ interface GroupingTagValue {
164
+ value: string;
165
+ displayName: string;
166
+ description: string;
167
+ }
168
+ interface AppCatalogData {
169
+ apps: Array<AppForCatalog>;
170
+ tagsDefinitions: Array<GroupingTagDefinition>;
171
+ approvalMethods: Array<AppApprovalMethod>;
172
+ }
173
+ //#endregion
174
+ //#region src/types/common/env/envTypes.d.ts
175
+ interface EhEnvIndexed {
176
+ slug: string;
177
+ displayName: string;
178
+ meta?: EhMetaDictionary;
179
+ }
180
+ //#endregion
181
+ //#region src/types/common/app/ui/appUiTypes.d.ts
182
+ interface EhAppPageIndexed {
183
+ slug: string;
184
+ displayName: string;
185
+ url: string;
186
+ tags?: Array<Tag>;
187
+ }
188
+ interface EhAppUiIndexed {
189
+ pages: Array<EhAppPageIndexed>;
190
+ }
191
+ //#endregion
192
+ //#region src/types/common/app/appTypes.d.ts
193
+ interface EhAppIndexed {
194
+ slug: string;
195
+ displayName: string;
196
+ abbr?: string;
197
+ aliases?: Array<string>;
198
+ ui?: EhAppUiIndexed;
199
+ tags?: Array<Tag>;
200
+ iconName?: string;
201
+ meta?: EhMetaDictionary;
202
+ }
203
+ //#endregion
204
+ //#region src/types/backend/common.d.ts
205
+ interface EhBackendUiDefaultsInput {
206
+ credentialsRefs: Array<string>;
207
+ }
208
+ interface EhBackendCredentialInput {
209
+ slug: string;
210
+ desc?: string;
211
+ username: string;
212
+ password: string;
213
+ }
214
+ //#endregion
215
+ //#region src/types/backend/dataSources.d.ts
216
+ interface EhBackendDataSourceInputCommon {
217
+ meta?: EhMetaDictionary;
218
+ }
219
+ interface EhBackendDataSourceInputDb {
220
+ slug?: string;
221
+ type: 'db';
222
+ url: string;
223
+ username: string;
224
+ password: string;
225
+ }
226
+ interface EhBackendDataSourceInputKafka {
227
+ slug?: string;
228
+ type: 'kafka';
229
+ topics: {
230
+ consumer?: Array<string>;
231
+ producer?: Array<string>;
232
+ };
233
+ }
234
+ type EhBackendDataSourceInput = EhBackendDataSourceInputCommon & (EhBackendDataSourceInputDb | EhBackendDataSourceInputKafka);
235
+ //#endregion
236
+ //#region src/types/backend/api.d.ts
237
+ interface EhBackendVersionsRequestParams {
238
+ envNames: Array<string>;
239
+ appNames: Array<string>;
240
+ }
241
+ interface EhBackendVersionsReturn {
242
+ envIds: Array<string>;
243
+ appIds: Array<string>;
244
+ }
245
+ interface EhBackendPageInput extends EhAppPageIndexed {
246
+ slug: string;
247
+ title?: string;
248
+ url: string;
249
+ credentialsRefs?: Array<string>;
250
+ }
251
+ interface EhBackendAppUIBaseInput {
252
+ credentials?: Array<EhBackendCredentialInput>;
253
+ defaults?: EhBackendUiDefaultsInput;
254
+ }
255
+ interface EhBackendAppUIInput extends EhBackendAppUIBaseInput, EhAppUiIndexed {
256
+ pages: Array<EhBackendPageInput>;
257
+ }
258
+ interface EhBackendTagsDescriptionDataIndexed {
259
+ descriptions: Array<EhBackendTagDescriptionDataIndexed>;
260
+ }
261
+ interface EhBackendTagDescriptionDataIndexed {
262
+ tagKey: string;
263
+ displayName?: string;
264
+ fixedTagValues?: Array<EhBackendTagFixedTagValue>;
265
+ }
266
+ interface EhBackendTagFixedTagValue {
267
+ tagValue: string;
268
+ displayName: string;
269
+ }
270
+ interface EhBackendAppInput extends EhAppIndexed {
271
+ ui?: EhBackendAppUIInput;
272
+ dataSources?: Array<EhBackendDataSourceInput>;
273
+ }
274
+ interface EhContextIndexed {
275
+ slug: string;
276
+ displayName: string;
277
+ /**
278
+ * The value is shared across envs (By default: false)
279
+ */
280
+ isSharedAcrossEnvs?: boolean;
281
+ defaultFixedValues?: Array<string>;
282
+ }
283
+ type EhBackendAppDto = EhAppIndexed;
284
+ interface EhAppsMeta {
285
+ defaultIcon?: string;
286
+ tags: EhBackendTagsDescriptionDataIndexed;
287
+ }
288
+ //#endregion
289
+ //#region src/types/backend/companySpecificBackend.d.ts
290
+ interface AppCatalogCompanySpecificBackend {
291
+ getApps?: () => Promise<Array<AppForCatalog>>;
292
+ }
293
+ //#endregion
294
+ //#region src/types/backend/deployments.d.ts
295
+ interface EhBackendEnvironmentInput {
296
+ slug: string;
297
+ displayName?: string;
298
+ description?: string;
299
+ meta?: EhMetaDictionary;
300
+ }
301
+ interface EhBackendDeploymentInput {
302
+ envId: string;
303
+ appId: string;
304
+ displayVersion: string;
305
+ meta?: EhMetaDictionary;
306
+ }
307
+ interface EhBackendDeployableInput {
308
+ slug: string;
309
+ meta?: {
310
+ config: string;
311
+ };
312
+ }
313
+ /**
314
+ * Latest - backend returned latest data.
315
+ * Cached - backend in process of updating data, but returned cached data.
316
+ */
317
+ type EhBackendDataFreshness = 'latest' | 'cached';
318
+ interface EhBackendDataVersion {
319
+ version: string;
320
+ freshness: EhBackendDataFreshness;
321
+ }
322
+ interface EhBackendDeployment {
323
+ appName: string;
324
+ deployableServiceName: string;
325
+ envName: string;
326
+ version: EhBackendDataVersion;
327
+ }
328
+ //#endregion
329
+ //#region src/server/ehTrpcContext.d.ts
330
+ interface EhTrpcContext {
331
+ companySpecificBackend: AppCatalogCompanySpecificBackend;
332
+ user: User | null;
333
+ adminGroups: Array<string>;
334
+ }
335
+ interface EhTrpcContextOptions {
336
+ companySpecificBackend: AppCatalogCompanySpecificBackend;
337
+ user?: User | null;
338
+ adminGroups: Array<string>;
339
+ }
340
+ declare function createEhTrpcContext({
341
+ companySpecificBackend,
342
+ user,
343
+ adminGroups
344
+ }: EhTrpcContextOptions): EhTrpcContext;
345
+ //#endregion
346
+ //#region src/modules/auth/auth.d.ts
347
+ interface AuthConfig {
348
+ appName?: string;
349
+ baseURL: string;
350
+ secret: string;
351
+ providers?: BetterAuthOptions['socialProviders'];
352
+ plugins?: Array<BetterAuthPlugin>;
353
+ /** Session expiration in seconds. Default: 7 days (604800) */
354
+ sessionExpiresIn?: number;
355
+ /** Session update age in seconds. Default: 1 day (86400) */
356
+ sessionUpdateAge?: number;
357
+ }
358
+ declare function createAuth(config: AuthConfig): better_auth0.Auth<{
359
+ appName: string;
360
+ baseURL: string;
361
+ basePath: string;
362
+ secret: string;
363
+ database: (options: BetterAuthOptions) => better_auth0.DBAdapter<BetterAuthOptions>;
364
+ socialProviders: better_auth0.SocialProviders;
365
+ plugins: BetterAuthPlugin[];
366
+ emailAndPassword: {
367
+ enabled: true;
368
+ };
369
+ session: {
370
+ expiresIn: number;
371
+ updateAge: number;
372
+ cookieCache: {
373
+ enabled: true;
374
+ maxAge: number;
375
+ };
376
+ };
377
+ advanced: {
378
+ useSecureCookies: boolean;
379
+ };
380
+ }>;
381
+ type BetterAuth = ReturnType<typeof createAuth>;
382
+ //#endregion
383
+ //#region src/server/controller.d.ts
384
+ /**
385
+ * Create the main tRPC router with optional auth instance
386
+ * @param auth - Optional Better Auth instance for auth-related queries
387
+ */
388
+ declare function createTrpcRouter(auth?: BetterAuth): _trpc_server0.TRPCBuiltRouter<{
389
+ ctx: EhTrpcContext;
390
+ meta: object;
391
+ errorShape: _trpc_server0.TRPCDefaultErrorShape;
392
+ transformer: false;
393
+ }, _trpc_server0.TRPCDecorateCreateRouterOptions<{
394
+ authConfig: _trpc_server0.TRPCQueryProcedure<{
395
+ input: void;
396
+ output: {
397
+ adminGroups: string[];
398
+ };
399
+ meta: object;
400
+ }>;
401
+ appCatalog: _trpc_server0.TRPCQueryProcedure<{
402
+ input: void;
403
+ output: AppCatalogData;
404
+ meta: object;
405
+ }>;
406
+ icon: _trpc_server0.TRPCBuiltRouter<{
407
+ ctx: EhTrpcContext;
408
+ meta: object;
409
+ errorShape: _trpc_server0.TRPCDefaultErrorShape;
410
+ transformer: false;
411
+ }, _trpc_server0.TRPCDecorateCreateRouterOptions<{
412
+ list: _trpc_server0.TRPCQueryProcedure<{
413
+ input: void;
414
+ output: {
415
+ id: string;
416
+ createdAt: Date;
417
+ updatedAt: Date;
418
+ name: string;
419
+ mimeType: string;
420
+ fileSize: number;
421
+ }[];
422
+ meta: object;
423
+ }>;
424
+ getOne: _trpc_server0.TRPCQueryProcedure<{
425
+ input: {
426
+ id: string;
427
+ };
428
+ output: {
429
+ id: string;
430
+ createdAt: Date;
431
+ updatedAt: Date;
432
+ name: string;
433
+ mimeType: string;
434
+ fileSize: number;
435
+ } | null;
436
+ meta: object;
437
+ }>;
438
+ create: _trpc_server0.TRPCMutationProcedure<{
439
+ input: {
440
+ name: string;
441
+ content: string;
442
+ mimeType: string;
443
+ fileSize: number;
444
+ };
445
+ output: {
446
+ id: string;
447
+ createdAt: Date;
448
+ updatedAt: Date;
449
+ name: string;
450
+ content: _prisma_client_runtime_library0.Bytes;
451
+ mimeType: string;
452
+ fileSize: number;
453
+ assetType: _prisma_client0.$Enums.AssetType;
454
+ checksum: string;
455
+ width: number | null;
456
+ height: number | null;
457
+ };
458
+ meta: object;
459
+ }>;
460
+ update: _trpc_server0.TRPCMutationProcedure<{
461
+ input: {
462
+ id: string;
463
+ name?: string | undefined;
464
+ content?: string | undefined;
465
+ mimeType?: string | undefined;
466
+ fileSize?: number | undefined;
467
+ };
468
+ output: {
469
+ id: string;
470
+ createdAt: Date;
471
+ updatedAt: Date;
472
+ name: string;
473
+ content: _prisma_client_runtime_library0.Bytes;
474
+ mimeType: string;
475
+ fileSize: number;
476
+ assetType: _prisma_client0.$Enums.AssetType;
477
+ checksum: string;
478
+ width: number | null;
479
+ height: number | null;
480
+ };
481
+ meta: object;
482
+ }>;
483
+ delete: _trpc_server0.TRPCMutationProcedure<{
484
+ input: {
485
+ id: string;
486
+ };
487
+ output: {
488
+ id: string;
489
+ createdAt: Date;
490
+ updatedAt: Date;
491
+ name: string;
492
+ content: _prisma_client_runtime_library0.Bytes;
493
+ mimeType: string;
494
+ fileSize: number;
495
+ assetType: _prisma_client0.$Enums.AssetType;
496
+ checksum: string;
497
+ width: number | null;
498
+ height: number | null;
499
+ };
500
+ meta: object;
501
+ }>;
502
+ deleteMany: _trpc_server0.TRPCMutationProcedure<{
503
+ input: {
504
+ ids: string[];
505
+ };
506
+ output: _prisma_client0.Prisma.BatchPayload;
507
+ meta: object;
508
+ }>;
509
+ getContent: _trpc_server0.TRPCQueryProcedure<{
510
+ input: {
511
+ id: string;
512
+ };
513
+ output: {
514
+ content: string;
515
+ mimeType: string;
516
+ name: string;
517
+ };
518
+ meta: object;
519
+ }>;
520
+ }>>;
521
+ screenshot: _trpc_server0.TRPCBuiltRouter<{
522
+ ctx: EhTrpcContext;
523
+ meta: object;
524
+ errorShape: _trpc_server0.TRPCDefaultErrorShape;
525
+ transformer: false;
526
+ }, _trpc_server0.TRPCDecorateCreateRouterOptions<{
527
+ list: _trpc_server0.TRPCQueryProcedure<{
528
+ input: void;
529
+ output: {
530
+ id: string;
531
+ createdAt: Date;
532
+ updatedAt: Date;
533
+ name: string;
534
+ mimeType: string;
535
+ fileSize: number;
536
+ width: number | null;
537
+ height: number | null;
538
+ }[];
539
+ meta: object;
540
+ }>;
541
+ getOne: _trpc_server0.TRPCQueryProcedure<{
542
+ input: {
543
+ id: string;
544
+ };
545
+ output: {
546
+ id: string;
547
+ createdAt: Date;
548
+ updatedAt: Date;
549
+ name: string;
550
+ mimeType: string;
551
+ fileSize: number;
552
+ width: number | null;
553
+ height: number | null;
554
+ } | null;
555
+ meta: object;
556
+ }>;
557
+ getByAppSlug: _trpc_server0.TRPCQueryProcedure<{
558
+ input: {
559
+ appSlug: string;
560
+ };
561
+ output: {
562
+ id: string;
563
+ createdAt: Date;
564
+ updatedAt: Date;
565
+ name: string;
566
+ mimeType: string;
567
+ fileSize: number;
568
+ width: number | null;
569
+ height: number | null;
570
+ }[];
571
+ meta: object;
572
+ }>;
573
+ getFirstByAppSlug: _trpc_server0.TRPCQueryProcedure<{
574
+ input: {
575
+ appSlug: string;
576
+ };
577
+ output: {
578
+ id: string;
579
+ createdAt: Date;
580
+ updatedAt: Date;
581
+ name: string;
582
+ mimeType: string;
583
+ fileSize: number;
584
+ width: number | null;
585
+ height: number | null;
586
+ } | null;
587
+ meta: object;
588
+ }>;
589
+ }>>;
590
+ appCatalogAdmin: _trpc_server0.TRPCBuiltRouter<{
591
+ ctx: EhTrpcContext;
592
+ meta: object;
593
+ errorShape: _trpc_server0.TRPCDefaultErrorShape;
594
+ transformer: false;
595
+ }, _trpc_server0.TRPCDecorateCreateRouterOptions<{
596
+ list: _trpc_server0.TRPCQueryProcedure<{
597
+ input: void;
598
+ output: {
599
+ id: string;
600
+ createdAt: Date;
601
+ updatedAt: Date;
602
+ description: string;
603
+ slug: string;
604
+ displayName: string;
605
+ access: PrismaJson.AccessMethod | null;
606
+ teams: string[];
607
+ accessRequest: PrismaJson.AppAccessRequest | null;
608
+ notes: string | null;
609
+ tags: string[];
610
+ appUrl: string | null;
611
+ links: PrismaJson.AppLink[] | null;
612
+ iconName: string | null;
613
+ screenshotIds: string[];
614
+ }[];
615
+ meta: object;
616
+ }>;
617
+ getById: _trpc_server0.TRPCQueryProcedure<{
618
+ input: {
619
+ id: string;
620
+ };
621
+ output: {
622
+ id: string;
623
+ createdAt: Date;
624
+ updatedAt: Date;
625
+ description: string;
626
+ slug: string;
627
+ displayName: string;
628
+ access: PrismaJson.AccessMethod | null;
629
+ teams: string[];
630
+ accessRequest: PrismaJson.AppAccessRequest | null;
631
+ notes: string | null;
632
+ tags: string[];
633
+ appUrl: string | null;
634
+ links: PrismaJson.AppLink[] | null;
635
+ iconName: string | null;
636
+ screenshotIds: string[];
637
+ } | null;
638
+ meta: object;
639
+ }>;
640
+ getBySlug: _trpc_server0.TRPCQueryProcedure<{
641
+ input: {
642
+ slug: string;
643
+ };
644
+ output: {
645
+ id: string;
646
+ createdAt: Date;
647
+ updatedAt: Date;
648
+ description: string;
649
+ slug: string;
650
+ displayName: string;
651
+ access: PrismaJson.AccessMethod | null;
652
+ teams: string[];
653
+ accessRequest: PrismaJson.AppAccessRequest | null;
654
+ notes: string | null;
655
+ tags: string[];
656
+ appUrl: string | null;
657
+ links: PrismaJson.AppLink[] | null;
658
+ iconName: string | null;
659
+ screenshotIds: string[];
660
+ } | null;
661
+ meta: object;
662
+ }>;
663
+ create: _trpc_server0.TRPCMutationProcedure<{
664
+ input: {
665
+ slug: string;
666
+ displayName: string;
667
+ description: string;
668
+ access?: {
669
+ [x: string]: unknown;
670
+ type: "email" | "bot" | "ticketing" | "self-service" | "documentation" | "manual";
671
+ } | undefined;
672
+ teams?: string[] | undefined;
673
+ accessRequest?: {
674
+ approvalMethodId: string;
675
+ comments?: string | undefined;
676
+ requestPrompt?: string | undefined;
677
+ postApprovalInstructions?: string | undefined;
678
+ roles?: {
679
+ name: string;
680
+ description?: string | undefined;
681
+ }[] | undefined;
682
+ approvers?: {
683
+ displayName: string;
684
+ contact?: string | undefined;
685
+ }[] | undefined;
686
+ urls?: {
687
+ url: string;
688
+ label?: string | undefined;
689
+ }[] | undefined;
690
+ whoToReachOut?: string | undefined;
691
+ } | undefined;
692
+ notes?: string | undefined;
693
+ tags?: string[] | undefined;
694
+ appUrl?: string | undefined;
695
+ links?: {
696
+ url: string;
697
+ displayName?: string | undefined;
698
+ }[] | undefined;
699
+ iconName?: string | undefined;
700
+ screenshotIds?: string[] | undefined;
701
+ };
702
+ output: {
703
+ id: string;
704
+ createdAt: Date;
705
+ updatedAt: Date;
706
+ description: string;
707
+ slug: string;
708
+ displayName: string;
709
+ access: PrismaJson.AccessMethod | null;
710
+ teams: string[];
711
+ accessRequest: PrismaJson.AppAccessRequest | null;
712
+ notes: string | null;
713
+ tags: string[];
714
+ appUrl: string | null;
715
+ links: PrismaJson.AppLink[] | null;
716
+ iconName: string | null;
717
+ screenshotIds: string[];
718
+ };
719
+ meta: object;
720
+ }>;
721
+ update: _trpc_server0.TRPCMutationProcedure<{
722
+ input: {
723
+ id: string;
724
+ slug?: string | undefined;
725
+ displayName?: string | undefined;
726
+ description?: string | undefined;
727
+ access?: {
728
+ [x: string]: unknown;
729
+ type: "email" | "bot" | "ticketing" | "self-service" | "documentation" | "manual";
730
+ } | undefined;
731
+ teams?: string[] | undefined;
732
+ accessRequest?: {
733
+ approvalMethodId: string;
734
+ comments?: string | undefined;
735
+ requestPrompt?: string | undefined;
736
+ postApprovalInstructions?: string | undefined;
737
+ roles?: {
738
+ name: string;
739
+ description?: string | undefined;
740
+ }[] | undefined;
741
+ approvers?: {
742
+ displayName: string;
743
+ contact?: string | undefined;
744
+ }[] | undefined;
745
+ urls?: {
746
+ url: string;
747
+ label?: string | undefined;
748
+ }[] | undefined;
749
+ whoToReachOut?: string | undefined;
750
+ } | undefined;
751
+ notes?: string | undefined;
752
+ tags?: string[] | undefined;
753
+ appUrl?: string | undefined;
754
+ links?: {
755
+ url: string;
756
+ displayName?: string | undefined;
757
+ }[] | undefined;
758
+ iconName?: string | undefined;
759
+ screenshotIds?: string[] | undefined;
760
+ };
761
+ output: {
762
+ id: string;
763
+ createdAt: Date;
764
+ updatedAt: Date;
765
+ description: string;
766
+ slug: string;
767
+ displayName: string;
768
+ access: PrismaJson.AccessMethod | null;
769
+ teams: string[];
770
+ accessRequest: PrismaJson.AppAccessRequest | null;
771
+ notes: string | null;
772
+ tags: string[];
773
+ appUrl: string | null;
774
+ links: PrismaJson.AppLink[] | null;
775
+ iconName: string | null;
776
+ screenshotIds: string[];
777
+ };
778
+ meta: object;
779
+ }>;
780
+ updateScreenshots: _trpc_server0.TRPCMutationProcedure<{
781
+ input: {
782
+ id: string;
783
+ screenshotIds: string[];
784
+ };
785
+ output: {
786
+ id: string;
787
+ createdAt: Date;
788
+ updatedAt: Date;
789
+ description: string;
790
+ slug: string;
791
+ displayName: string;
792
+ access: PrismaJson.AccessMethod | null;
793
+ teams: string[];
794
+ accessRequest: PrismaJson.AppAccessRequest | null;
795
+ notes: string | null;
796
+ tags: string[];
797
+ appUrl: string | null;
798
+ links: PrismaJson.AppLink[] | null;
799
+ iconName: string | null;
800
+ screenshotIds: string[];
801
+ };
802
+ meta: object;
803
+ }>;
804
+ delete: _trpc_server0.TRPCMutationProcedure<{
805
+ input: {
806
+ id: string;
807
+ };
808
+ output: {
809
+ id: string;
810
+ createdAt: Date;
811
+ updatedAt: Date;
812
+ description: string;
813
+ slug: string;
814
+ displayName: string;
815
+ access: PrismaJson.AccessMethod | null;
816
+ teams: string[];
817
+ accessRequest: PrismaJson.AppAccessRequest | null;
818
+ notes: string | null;
819
+ tags: string[];
820
+ appUrl: string | null;
821
+ links: PrismaJson.AppLink[] | null;
822
+ iconName: string | null;
823
+ screenshotIds: string[];
824
+ };
825
+ meta: object;
826
+ }>;
827
+ }>>;
828
+ approvalMethod: _trpc_server0.TRPCBuiltRouter<{
829
+ ctx: EhTrpcContext;
830
+ meta: object;
831
+ errorShape: _trpc_server0.TRPCDefaultErrorShape;
832
+ transformer: false;
833
+ }, _trpc_server0.TRPCDecorateCreateRouterOptions<{
834
+ list: _trpc_server0.TRPCQueryProcedure<{
835
+ input: void;
836
+ output: ApprovalMethod[];
837
+ meta: object;
838
+ }>;
839
+ getById: _trpc_server0.TRPCQueryProcedure<{
840
+ input: {
841
+ slug: string;
842
+ };
843
+ output: ApprovalMethod | null;
844
+ meta: object;
845
+ }>;
846
+ create: _trpc_server0.TRPCMutationProcedure<{
847
+ input: {
848
+ type: "custom" | "service" | "personTeam";
849
+ displayName: string;
850
+ config?: Record<string, never> | {
851
+ url?: string | undefined;
852
+ icon?: string | undefined;
853
+ } | {
854
+ reachOutContacts?: {
855
+ displayName: string;
856
+ contact: string;
857
+ }[] | undefined;
858
+ } | undefined;
859
+ };
860
+ output: ApprovalMethod;
861
+ meta: object;
862
+ }>;
863
+ update: _trpc_server0.TRPCMutationProcedure<{
864
+ input: {
865
+ slug: string;
866
+ type?: "custom" | "service" | "personTeam" | undefined;
867
+ displayName?: string | undefined;
868
+ config?: Record<string, never> | {
869
+ url?: string | undefined;
870
+ icon?: string | undefined;
871
+ } | {
872
+ reachOutContacts?: {
873
+ displayName: string;
874
+ contact: string;
875
+ }[] | undefined;
876
+ } | undefined;
877
+ };
878
+ output: ApprovalMethod;
879
+ meta: object;
880
+ }>;
881
+ delete: _trpc_server0.TRPCMutationProcedure<{
882
+ input: {
883
+ slug: string;
884
+ };
885
+ output: ApprovalMethod;
886
+ meta: object;
887
+ }>;
888
+ listByType: _trpc_server0.TRPCQueryProcedure<{
889
+ input: {
890
+ type: "custom" | "service" | "personTeam";
891
+ };
892
+ output: ApprovalMethod[];
893
+ meta: object;
894
+ }>;
895
+ }>>;
896
+ auth: _trpc_server0.TRPCBuiltRouter<{
897
+ ctx: EhTrpcContext;
898
+ meta: {};
899
+ errorShape: _trpc_server0.TRPCDefaultErrorShape;
900
+ transformer: false;
901
+ }, _trpc_server0.TRPCDecorateCreateRouterOptions<{
902
+ getSession: _trpc_server0.TRPCQueryProcedure<{
903
+ input: void;
904
+ output: {
905
+ user: {
906
+ id: string;
907
+ createdAt: Date;
908
+ updatedAt: Date;
909
+ email: string;
910
+ emailVerified: boolean;
911
+ name: string;
912
+ image?: string | null | undefined;
913
+ } | null;
914
+ isAuthenticated: boolean;
915
+ };
916
+ meta: {};
917
+ }>;
918
+ getProviders: _trpc_server0.TRPCQueryProcedure<{
919
+ input: void;
920
+ output: {
921
+ providers: string[];
922
+ };
923
+ meta: {};
924
+ }>;
925
+ }>>;
926
+ }>>;
927
+ type TRPCRouter = ReturnType<typeof createTrpcRouter>;
928
+ //#endregion
929
+ //#region src/server/ehStaticControllerContract.d.ts
930
+ interface EhStaticControllerContract {
931
+ methods: {
932
+ getIcon: {
933
+ method: string;
934
+ url: string;
935
+ };
936
+ getScreenshot: {
937
+ method: string;
938
+ url: string;
939
+ };
940
+ };
941
+ }
942
+ declare const staticControllerContract: EhStaticControllerContract;
943
+ //#endregion
944
+ //#region src/modules/auth/registerAuthRoutes.d.ts
945
+ /**
946
+ * Register Better Auth routes with Express
947
+ * @param app - Express application instance
948
+ * @param auth - Better Auth instance
949
+ */
950
+ declare function registerAuthRoutes(app: Express, auth: BetterAuth): void;
951
+ //#endregion
952
+ //#region src/modules/auth/authRouter.d.ts
953
+ /**
954
+ * Create auth tRPC procedures
955
+ * @param t - tRPC instance
956
+ * @param auth - Better Auth instance (optional, for future extensions)
957
+ * @returns tRPC router with auth procedures
958
+ */
959
+ declare function createAuthRouter(t: TRPCRootObject<EhTrpcContext, {}, {}>, auth?: BetterAuth): _trpc_server0.TRPCBuiltRouter<{
960
+ ctx: EhTrpcContext;
961
+ meta: {};
962
+ errorShape: _trpc_server0.TRPCDefaultErrorShape;
963
+ transformer: false;
964
+ }, _trpc_server0.TRPCDecorateCreateRouterOptions<{
965
+ getSession: _trpc_server0.TRPCQueryProcedure<{
966
+ input: void;
967
+ output: {
968
+ user: {
969
+ id: string;
970
+ createdAt: Date;
971
+ updatedAt: Date;
972
+ email: string;
973
+ emailVerified: boolean;
974
+ name: string;
975
+ image?: string | null | undefined;
976
+ } | null;
977
+ isAuthenticated: boolean;
978
+ };
979
+ meta: {};
980
+ }>;
981
+ getProviders: _trpc_server0.TRPCQueryProcedure<{
982
+ input: void;
983
+ output: {
984
+ providers: string[];
985
+ };
986
+ meta: {};
987
+ }>;
988
+ }>>;
989
+ type AuthRouter = ReturnType<typeof createAuthRouter>;
990
+ //#endregion
991
+ //#region src/modules/auth/authorizationUtils.d.ts
992
+ /**
993
+ * Authorization utilities for checking user permissions based on groups
994
+ *
995
+ * Groups are automatically included in the user session when:
996
+ * 1. Okta auth server has a "groups" claim configured
997
+ * 2. The auth policy rule includes "groups" in scope_whitelist
998
+ *
999
+ * Example usage in tRPC procedures:
1000
+ * ```typescript
1001
+ * myProcedure: protectedProcedure.query(async ({ ctx }) => {
1002
+ * if (requireAdmin(ctx.user)) {
1003
+ * // Admin-only logic
1004
+ * }
1005
+ * // Regular user logic
1006
+ * })
1007
+ * ```
1008
+ */
1009
+ interface UserWithGroups {
1010
+ id: string;
1011
+ email: string;
1012
+ name?: string;
1013
+ [key: string]: any;
1014
+ }
1015
+ /**
1016
+ * Extract groups from user object
1017
+ * Groups can be stored in different locations depending on the OAuth provider
1018
+ */
1019
+ declare function getUserGroups(user: UserWithGroups | null | undefined): Array<string>;
1020
+ /**
1021
+ * Check if user is a member of any of the specified groups
1022
+ */
1023
+ declare function isMemberOfAnyGroup(user: UserWithGroups | null | undefined, allowedGroups: Array<string>): boolean;
1024
+ /**
1025
+ * Check if user is a member of all specified groups
1026
+ */
1027
+ declare function isMemberOfAllGroups(user: UserWithGroups | null | undefined, requiredGroups: Array<string>): boolean;
1028
+ /**
1029
+ * Check if user has admin permissions
1030
+ * @param user User object with groups
1031
+ * @param adminGroups List of admin group names (default: ['env_hopper_ui_super_admins'])
1032
+ */
1033
+ declare function isAdmin(user: UserWithGroups | null | undefined, adminGroups?: Array<string>): boolean;
1034
+ /**
1035
+ * Require admin permissions - throws error if not admin
1036
+ * @param user User object with groups
1037
+ * @param adminGroups List of admin group names (default: ['env_hopper_ui_super_admins'])
1038
+ */
1039
+ declare function requireAdmin(user: UserWithGroups | null | undefined, adminGroups?: Array<string>): void;
1040
+ /**
1041
+ * Require membership in specific groups - throws error if not member
1042
+ */
1043
+ declare function requireGroups(user: UserWithGroups | null | undefined, groups: Array<string>): void;
1044
+ //#endregion
1045
+ //#region src/modules/admin/chat/createAdminChatHandler.d.ts
1046
+ interface AdminChatHandlerOptions {
1047
+ /** The AI model to use (from @ai-sdk/openai, @ai-sdk/anthropic, etc.) */
1048
+ model: LanguageModel;
1049
+ /** System prompt for the AI assistant */
1050
+ systemPrompt?: string;
1051
+ /** Tools available to the AI assistant */
1052
+ tools?: Record<string, Tool>;
1053
+ /**
1054
+ * Optional function to validate configuration before processing requests.
1055
+ * Should throw an error if configuration is invalid (e.g., missing API key).
1056
+ * @example
1057
+ * validateConfig: () => {
1058
+ * if (!process.env.OPENAI_API_KEY) {
1059
+ * throw new Error('OPENAI_API_KEY is not configured')
1060
+ * }
1061
+ * }
1062
+ */
1063
+ validateConfig?: () => void;
1064
+ }
1065
+ /**
1066
+ * Creates an Express handler for the admin chat endpoint.
1067
+ *
1068
+ * Usage in thin wrappers:
1069
+ *
1070
+ * ```typescript
1071
+ * // With OpenAI
1072
+ * import { openai } from '@ai-sdk/openai'
1073
+ * app.post('/api/admin/chat', createAdminChatHandler({
1074
+ * model: openai('gpt-4o-mini'),
1075
+ * }))
1076
+ *
1077
+ * // With Claude
1078
+ * import { anthropic } from '@ai-sdk/anthropic'
1079
+ * app.post('/api/admin/chat', createAdminChatHandler({
1080
+ * model: anthropic('claude-sonnet-4-20250514'),
1081
+ * }))
1082
+ * ```
1083
+ */
1084
+ declare function createAdminChatHandler(options: AdminChatHandlerOptions): (req: Request, res: Response) => Promise<void>;
1085
+ //#endregion
1086
+ //#region src/modules/admin/chat/createDatabaseTools.d.ts
1087
+ /**
1088
+ * Generic interface for executing raw SQL queries.
1089
+ * Can be implemented with Prisma's $queryRawUnsafe or any other SQL client.
1090
+ */
1091
+ interface DatabaseClient {
1092
+ /** Execute a SELECT query and return results */
1093
+ query: <T = unknown>(sql: string) => Promise<Array<T>>;
1094
+ /** Execute an INSERT/UPDATE/DELETE and return affected row count */
1095
+ execute: (sql: string) => Promise<{
1096
+ affectedRows: number;
1097
+ }>;
1098
+ /** Get list of tables in the database */
1099
+ getTables: () => Promise<Array<string>>;
1100
+ /** Get columns for a specific table */
1101
+ getColumns: (tableName: string) => Promise<Array<{
1102
+ name: string;
1103
+ type: string;
1104
+ nullable: boolean;
1105
+ }>>;
1106
+ }
1107
+ /**
1108
+ * Creates a DatabaseClient from a Prisma client.
1109
+ */
1110
+ declare function createPrismaDatabaseClient(prisma: {
1111
+ $queryRawUnsafe: <T>(sql: string) => Promise<T>;
1112
+ $executeRawUnsafe: (sql: string) => Promise<number>;
1113
+ }): DatabaseClient;
1114
+ /**
1115
+ * Creates AI tools for generic database access.
1116
+ *
1117
+ * The AI uses these internally - users interact via natural language.
1118
+ * Results are formatted as tables by the AI based on the system prompt.
1119
+ * Uses the internal backend-core Prisma client automatically.
1120
+ */
1121
+ declare function createDatabaseTools(): Record<string, Tool>;
1122
+ /**
1123
+ * Default system prompt for the database admin assistant.
1124
+ * Can be customized or extended.
1125
+ */
1126
+ declare const DEFAULT_ADMIN_SYSTEM_PROMPT = "You are a helpful database admin assistant. You help users view and manage data in the database.\n\nIMPORTANT RULES:\n1. When showing data, ALWAYS format it as a numbered ASCII table so users can reference rows by number\n2. NEVER show raw SQL to users - just describe what you're doing in plain language\n3. When users ask to modify data (update, delete, create), ALWAYS confirm before executing\n4. For updates, show the current value and ask for confirmation before changing\n5. Keep responses concise and focused on the data\n\nFORMATTING EXAMPLE:\nWhen user asks \"show me all apps\", respond like:\n\"Here are all the apps:\n\n| # | ID | Slug | Display Name | Icon |\n|---|----|---------|-----------------| -------|\n| 1 | 1 | portal | Portal | portal |\n| 2 | 2 | admin | Admin Dashboard | admin |\n| 3 | 3 | api | API Service | null |\n\nFound 3 apps total.\"\n\nWhen user says \"update row 2 display name to 'Admin Panel'\":\n1. First confirm: \"I'll update the app 'Admin Dashboard' (ID: 2) to have display name 'Admin Panel'. Proceed?\"\n2. Only after user confirms, execute the update\n3. Then show the updated row\n\nAVAILABLE TABLES:\nUse getDatabaseSchema tool to discover tables and their columns.\n";
1127
+ //#endregion
1128
+ //#region src/modules/icons/iconRestController.d.ts
1129
+ interface IconRestControllerConfig {
1130
+ /**
1131
+ * Base path for icon endpoints (e.g., '/api/icons')
1132
+ */
1133
+ basePath: string;
1134
+ }
1135
+ /**
1136
+ * Registers REST endpoints for icon upload and retrieval
1137
+ *
1138
+ * Endpoints:
1139
+ * - POST {basePath}/upload - Upload a new icon (multipart/form-data with 'icon' field and 'name' field)
1140
+ * - GET {basePath}/:id - Get icon binary by ID
1141
+ * - GET {basePath}/:id/metadata - Get icon metadata only
1142
+ */
1143
+ declare function registerIconRestController(router: Router, config: IconRestControllerConfig): void;
1144
+ //#endregion
1145
+ //#region src/modules/icons/iconService.d.ts
1146
+ interface UpsertIconInput {
1147
+ name: string;
1148
+ content: Buffer;
1149
+ mimeType: string;
1150
+ fileSize: number;
1151
+ }
1152
+ /**
1153
+ * Upsert an icon to the database.
1154
+ * If an icon with the same name exists, it will be updated.
1155
+ * Otherwise, a new icon will be created.
1156
+ */
1157
+ declare function upsertIcon(input: UpsertIconInput): Promise<{
1158
+ id: string;
1159
+ createdAt: Date;
1160
+ updatedAt: Date;
1161
+ name: string;
1162
+ content: _prisma_client_runtime_library0.Bytes;
1163
+ mimeType: string;
1164
+ fileSize: number;
1165
+ assetType: _prisma_client0.$Enums.AssetType;
1166
+ checksum: string;
1167
+ width: number | null;
1168
+ height: number | null;
1169
+ }>;
1170
+ /**
1171
+ * Upsert multiple icons to the database.
1172
+ * This is more efficient than calling upsertIcon multiple times.
1173
+ */
1174
+ declare function upsertIcons(icons: Array<UpsertIconInput>): Promise<{
1175
+ id: string;
1176
+ createdAt: Date;
1177
+ updatedAt: Date;
1178
+ name: string;
1179
+ content: _prisma_client_runtime_library0.Bytes;
1180
+ mimeType: string;
1181
+ fileSize: number;
1182
+ assetType: _prisma_client0.$Enums.AssetType;
1183
+ checksum: string;
1184
+ width: number | null;
1185
+ height: number | null;
1186
+ }[]>;
1187
+ /**
1188
+ * Get an asset (icon or screenshot) by name from the database.
1189
+ * Returns the asset content, mimeType, and name if found.
1190
+ */
1191
+ declare function getAssetByName(name: string): Promise<{
1192
+ name: string;
1193
+ content: Uint8Array<ArrayBuffer>;
1194
+ mimeType: string;
1195
+ } | null>;
1196
+ //#endregion
1197
+ //#region src/modules/assets/assetRestController.d.ts
1198
+ interface AssetRestControllerConfig {
1199
+ /**
1200
+ * Base path for asset endpoints (e.g., '/api/assets')
1201
+ */
1202
+ basePath: string;
1203
+ }
1204
+ /**
1205
+ * Registers REST endpoints for universal asset upload and retrieval
1206
+ *
1207
+ * Endpoints:
1208
+ * - POST {basePath}/upload - Upload a new asset (multipart/form-data)
1209
+ * - GET {basePath}/:id - Get asset binary by ID
1210
+ * - GET {basePath}/:id/metadata - Get asset metadata only
1211
+ * - GET {basePath}/by-name/:name - Get asset binary by name
1212
+ */
1213
+ declare function registerAssetRestController(router: Router, config: AssetRestControllerConfig): void;
1214
+ //#endregion
1215
+ //#region src/modules/assets/screenshotRestController.d.ts
1216
+ interface ScreenshotRestControllerConfig {
1217
+ /**
1218
+ * Base path for screenshot endpoints (e.g., '/api/screenshots')
1219
+ */
1220
+ basePath: string;
1221
+ }
1222
+ /**
1223
+ * Registers REST endpoints for screenshot retrieval
1224
+ *
1225
+ * Endpoints:
1226
+ * - GET {basePath}/app/:appId - Get all screenshots for an app
1227
+ * - GET {basePath}/:id - Get screenshot binary by ID
1228
+ * - GET {basePath}/:id/metadata - Get screenshot metadata only
1229
+ */
1230
+ declare function registerScreenshotRestController(router: Router, config: ScreenshotRestControllerConfig): void;
1231
+ //#endregion
1232
+ //#region src/modules/assets/screenshotRouter.d.ts
1233
+ declare function createScreenshotRouter(): _trpc_server0.TRPCBuiltRouter<{
1234
+ ctx: EhTrpcContext;
1235
+ meta: object;
1236
+ errorShape: _trpc_server0.TRPCDefaultErrorShape;
1237
+ transformer: false;
1238
+ }, _trpc_server0.TRPCDecorateCreateRouterOptions<{
1239
+ list: _trpc_server0.TRPCQueryProcedure<{
1240
+ input: void;
1241
+ output: {
1242
+ id: string;
1243
+ createdAt: Date;
1244
+ updatedAt: Date;
1245
+ name: string;
1246
+ mimeType: string;
1247
+ fileSize: number;
1248
+ width: number | null;
1249
+ height: number | null;
1250
+ }[];
1251
+ meta: object;
1252
+ }>;
1253
+ getOne: _trpc_server0.TRPCQueryProcedure<{
1254
+ input: {
1255
+ id: string;
1256
+ };
1257
+ output: {
1258
+ id: string;
1259
+ createdAt: Date;
1260
+ updatedAt: Date;
1261
+ name: string;
1262
+ mimeType: string;
1263
+ fileSize: number;
1264
+ width: number | null;
1265
+ height: number | null;
1266
+ } | null;
1267
+ meta: object;
1268
+ }>;
1269
+ getByAppSlug: _trpc_server0.TRPCQueryProcedure<{
1270
+ input: {
1271
+ appSlug: string;
1272
+ };
1273
+ output: {
1274
+ id: string;
1275
+ createdAt: Date;
1276
+ updatedAt: Date;
1277
+ name: string;
1278
+ mimeType: string;
1279
+ fileSize: number;
1280
+ width: number | null;
1281
+ height: number | null;
1282
+ }[];
1283
+ meta: object;
1284
+ }>;
1285
+ getFirstByAppSlug: _trpc_server0.TRPCQueryProcedure<{
1286
+ input: {
1287
+ appSlug: string;
1288
+ };
1289
+ output: {
1290
+ id: string;
1291
+ createdAt: Date;
1292
+ updatedAt: Date;
1293
+ name: string;
1294
+ mimeType: string;
1295
+ fileSize: number;
1296
+ width: number | null;
1297
+ height: number | null;
1298
+ } | null;
1299
+ meta: object;
1300
+ }>;
1301
+ }>>;
1302
+ //#endregion
1303
+ //#region src/modules/assets/syncAssets.d.ts
1304
+ interface SyncAssetsConfig {
1305
+ /**
1306
+ * Directory containing icon files to sync
1307
+ */
1308
+ iconsDir?: string;
1309
+ /**
1310
+ * Directory containing screenshot files to sync
1311
+ */
1312
+ screenshotsDir?: string;
1313
+ }
1314
+ /**
1315
+ * Sync local asset files (icons and screenshots) from directories into the database.
1316
+ *
1317
+ * This function allows consuming applications to sync asset files without directly
1318
+ * exposing the Prisma client. It handles:
1319
+ * - Icon files: Assigned to apps by matching filename to icon name patterns
1320
+ * - Screenshot files: Assigned to apps by matching filename to app ID (format: <app-id>_screenshot_<no>.<ext>)
1321
+ *
1322
+ * @param config Configuration with paths to icon and screenshot directories
1323
+ */
1324
+ declare function syncAssets(config: SyncAssetsConfig): Promise<{
1325
+ iconsUpserted: number;
1326
+ screenshotsUpserted: number;
1327
+ }>;
1328
+ //#endregion
1329
+ //#region src/modules/appCatalogAdmin/appCatalogAdminRouter.d.ts
1330
+ declare function createAppCatalogAdminRouter(): _trpc_server0.TRPCBuiltRouter<{
1331
+ ctx: EhTrpcContext;
1332
+ meta: object;
1333
+ errorShape: _trpc_server0.TRPCDefaultErrorShape;
1334
+ transformer: false;
1335
+ }, _trpc_server0.TRPCDecorateCreateRouterOptions<{
1336
+ list: _trpc_server0.TRPCQueryProcedure<{
1337
+ input: void;
1338
+ output: {
1339
+ id: string;
1340
+ createdAt: Date;
1341
+ updatedAt: Date;
1342
+ description: string;
1343
+ slug: string;
1344
+ displayName: string;
1345
+ access: PrismaJson.AccessMethod | null;
1346
+ teams: string[];
1347
+ accessRequest: PrismaJson.AppAccessRequest | null;
1348
+ notes: string | null;
1349
+ tags: string[];
1350
+ appUrl: string | null;
1351
+ links: PrismaJson.AppLink[] | null;
1352
+ iconName: string | null;
1353
+ screenshotIds: string[];
1354
+ }[];
1355
+ meta: object;
1356
+ }>;
1357
+ getById: _trpc_server0.TRPCQueryProcedure<{
1358
+ input: {
1359
+ id: string;
1360
+ };
1361
+ output: {
1362
+ id: string;
1363
+ createdAt: Date;
1364
+ updatedAt: Date;
1365
+ description: string;
1366
+ slug: string;
1367
+ displayName: string;
1368
+ access: PrismaJson.AccessMethod | null;
1369
+ teams: string[];
1370
+ accessRequest: PrismaJson.AppAccessRequest | null;
1371
+ notes: string | null;
1372
+ tags: string[];
1373
+ appUrl: string | null;
1374
+ links: PrismaJson.AppLink[] | null;
1375
+ iconName: string | null;
1376
+ screenshotIds: string[];
1377
+ } | null;
1378
+ meta: object;
1379
+ }>;
1380
+ getBySlug: _trpc_server0.TRPCQueryProcedure<{
1381
+ input: {
1382
+ slug: string;
1383
+ };
1384
+ output: {
1385
+ id: string;
1386
+ createdAt: Date;
1387
+ updatedAt: Date;
1388
+ description: string;
1389
+ slug: string;
1390
+ displayName: string;
1391
+ access: PrismaJson.AccessMethod | null;
1392
+ teams: string[];
1393
+ accessRequest: PrismaJson.AppAccessRequest | null;
1394
+ notes: string | null;
1395
+ tags: string[];
1396
+ appUrl: string | null;
1397
+ links: PrismaJson.AppLink[] | null;
1398
+ iconName: string | null;
1399
+ screenshotIds: string[];
1400
+ } | null;
1401
+ meta: object;
1402
+ }>;
1403
+ create: _trpc_server0.TRPCMutationProcedure<{
1404
+ input: {
1405
+ slug: string;
1406
+ displayName: string;
1407
+ description: string;
1408
+ access?: {
1409
+ [x: string]: unknown;
1410
+ type: "email" | "bot" | "ticketing" | "self-service" | "documentation" | "manual";
1411
+ } | undefined;
1412
+ teams?: string[] | undefined;
1413
+ accessRequest?: {
1414
+ approvalMethodId: string;
1415
+ comments?: string | undefined;
1416
+ requestPrompt?: string | undefined;
1417
+ postApprovalInstructions?: string | undefined;
1418
+ roles?: {
1419
+ name: string;
1420
+ description?: string | undefined;
1421
+ }[] | undefined;
1422
+ approvers?: {
1423
+ displayName: string;
1424
+ contact?: string | undefined;
1425
+ }[] | undefined;
1426
+ urls?: {
1427
+ url: string;
1428
+ label?: string | undefined;
1429
+ }[] | undefined;
1430
+ whoToReachOut?: string | undefined;
1431
+ } | undefined;
1432
+ notes?: string | undefined;
1433
+ tags?: string[] | undefined;
1434
+ appUrl?: string | undefined;
1435
+ links?: {
1436
+ url: string;
1437
+ displayName?: string | undefined;
1438
+ }[] | undefined;
1439
+ iconName?: string | undefined;
1440
+ screenshotIds?: string[] | undefined;
1441
+ };
1442
+ output: {
1443
+ id: string;
1444
+ createdAt: Date;
1445
+ updatedAt: Date;
1446
+ description: string;
1447
+ slug: string;
1448
+ displayName: string;
1449
+ access: PrismaJson.AccessMethod | null;
1450
+ teams: string[];
1451
+ accessRequest: PrismaJson.AppAccessRequest | null;
1452
+ notes: string | null;
1453
+ tags: string[];
1454
+ appUrl: string | null;
1455
+ links: PrismaJson.AppLink[] | null;
1456
+ iconName: string | null;
1457
+ screenshotIds: string[];
1458
+ };
1459
+ meta: object;
1460
+ }>;
1461
+ update: _trpc_server0.TRPCMutationProcedure<{
1462
+ input: {
1463
+ id: string;
1464
+ slug?: string | undefined;
1465
+ displayName?: string | undefined;
1466
+ description?: string | undefined;
1467
+ access?: {
1468
+ [x: string]: unknown;
1469
+ type: "email" | "bot" | "ticketing" | "self-service" | "documentation" | "manual";
1470
+ } | undefined;
1471
+ teams?: string[] | undefined;
1472
+ accessRequest?: {
1473
+ approvalMethodId: string;
1474
+ comments?: string | undefined;
1475
+ requestPrompt?: string | undefined;
1476
+ postApprovalInstructions?: string | undefined;
1477
+ roles?: {
1478
+ name: string;
1479
+ description?: string | undefined;
1480
+ }[] | undefined;
1481
+ approvers?: {
1482
+ displayName: string;
1483
+ contact?: string | undefined;
1484
+ }[] | undefined;
1485
+ urls?: {
1486
+ url: string;
1487
+ label?: string | undefined;
1488
+ }[] | undefined;
1489
+ whoToReachOut?: string | undefined;
1490
+ } | undefined;
1491
+ notes?: string | undefined;
1492
+ tags?: string[] | undefined;
1493
+ appUrl?: string | undefined;
1494
+ links?: {
1495
+ url: string;
1496
+ displayName?: string | undefined;
1497
+ }[] | undefined;
1498
+ iconName?: string | undefined;
1499
+ screenshotIds?: string[] | undefined;
1500
+ };
1501
+ output: {
1502
+ id: string;
1503
+ createdAt: Date;
1504
+ updatedAt: Date;
1505
+ description: string;
1506
+ slug: string;
1507
+ displayName: string;
1508
+ access: PrismaJson.AccessMethod | null;
1509
+ teams: string[];
1510
+ accessRequest: PrismaJson.AppAccessRequest | null;
1511
+ notes: string | null;
1512
+ tags: string[];
1513
+ appUrl: string | null;
1514
+ links: PrismaJson.AppLink[] | null;
1515
+ iconName: string | null;
1516
+ screenshotIds: string[];
1517
+ };
1518
+ meta: object;
1519
+ }>;
1520
+ updateScreenshots: _trpc_server0.TRPCMutationProcedure<{
1521
+ input: {
1522
+ id: string;
1523
+ screenshotIds: string[];
1524
+ };
1525
+ output: {
1526
+ id: string;
1527
+ createdAt: Date;
1528
+ updatedAt: Date;
1529
+ description: string;
1530
+ slug: string;
1531
+ displayName: string;
1532
+ access: PrismaJson.AccessMethod | null;
1533
+ teams: string[];
1534
+ accessRequest: PrismaJson.AppAccessRequest | null;
1535
+ notes: string | null;
1536
+ tags: string[];
1537
+ appUrl: string | null;
1538
+ links: PrismaJson.AppLink[] | null;
1539
+ iconName: string | null;
1540
+ screenshotIds: string[];
1541
+ };
1542
+ meta: object;
1543
+ }>;
1544
+ delete: _trpc_server0.TRPCMutationProcedure<{
1545
+ input: {
1546
+ id: string;
1547
+ };
1548
+ output: {
1549
+ id: string;
1550
+ createdAt: Date;
1551
+ updatedAt: Date;
1552
+ description: string;
1553
+ slug: string;
1554
+ displayName: string;
1555
+ access: PrismaJson.AccessMethod | null;
1556
+ teams: string[];
1557
+ accessRequest: PrismaJson.AppAccessRequest | null;
1558
+ notes: string | null;
1559
+ tags: string[];
1560
+ appUrl: string | null;
1561
+ links: PrismaJson.AppLink[] | null;
1562
+ iconName: string | null;
1563
+ screenshotIds: string[];
1564
+ };
1565
+ meta: object;
1566
+ }>;
1567
+ }>>;
1568
+ //#endregion
1569
+ //#region src/modules/approvalMethod/approvalMethodRouter.d.ts
1570
+ declare function createApprovalMethodRouter(): _trpc_server0.TRPCBuiltRouter<{
1571
+ ctx: EhTrpcContext;
1572
+ meta: object;
1573
+ errorShape: _trpc_server0.TRPCDefaultErrorShape;
1574
+ transformer: false;
1575
+ }, _trpc_server0.TRPCDecorateCreateRouterOptions<{
1576
+ list: _trpc_server0.TRPCQueryProcedure<{
1577
+ input: void;
1578
+ output: ApprovalMethod[];
1579
+ meta: object;
1580
+ }>;
1581
+ getById: _trpc_server0.TRPCQueryProcedure<{
1582
+ input: {
1583
+ slug: string;
1584
+ };
1585
+ output: ApprovalMethod | null;
1586
+ meta: object;
1587
+ }>;
1588
+ create: _trpc_server0.TRPCMutationProcedure<{
1589
+ input: {
1590
+ type: "custom" | "service" | "personTeam";
1591
+ displayName: string;
1592
+ config?: Record<string, never> | {
1593
+ url?: string | undefined;
1594
+ icon?: string | undefined;
1595
+ } | {
1596
+ reachOutContacts?: {
1597
+ displayName: string;
1598
+ contact: string;
1599
+ }[] | undefined;
1600
+ } | undefined;
1601
+ };
1602
+ output: ApprovalMethod;
1603
+ meta: object;
1604
+ }>;
1605
+ update: _trpc_server0.TRPCMutationProcedure<{
1606
+ input: {
1607
+ slug: string;
1608
+ type?: "custom" | "service" | "personTeam" | undefined;
1609
+ displayName?: string | undefined;
1610
+ config?: Record<string, never> | {
1611
+ url?: string | undefined;
1612
+ icon?: string | undefined;
1613
+ } | {
1614
+ reachOutContacts?: {
1615
+ displayName: string;
1616
+ contact: string;
1617
+ }[] | undefined;
1618
+ } | undefined;
1619
+ };
1620
+ output: ApprovalMethod;
1621
+ meta: object;
1622
+ }>;
1623
+ delete: _trpc_server0.TRPCMutationProcedure<{
1624
+ input: {
1625
+ slug: string;
1626
+ };
1627
+ output: ApprovalMethod;
1628
+ meta: object;
1629
+ }>;
1630
+ listByType: _trpc_server0.TRPCQueryProcedure<{
1631
+ input: {
1632
+ type: "custom" | "service" | "personTeam";
1633
+ };
1634
+ output: ApprovalMethod[];
1635
+ meta: object;
1636
+ }>;
1637
+ }>>;
1638
+ //#endregion
1639
+ //#region src/modules/approvalMethod/syncApprovalMethods.d.ts
1640
+ interface ApprovalMethodSyncInput {
1641
+ slug: string;
1642
+ type: 'service' | 'personTeam' | 'custom';
1643
+ displayName: string;
1644
+ }
1645
+ /**
1646
+ * Syncs approval methods to the database using upsert logic based on type + displayName.
1647
+ *
1648
+ * @param prisma - The PrismaClient instance from the backend-core database
1649
+ * @param methods - Array of approval methods to sync
1650
+ */
1651
+ declare function syncApprovalMethods(prisma: PrismaClient, methods: Array<ApprovalMethodSyncInput>): Promise<void>;
1652
+ //#endregion
1653
+ //#region src/db/client.d.ts
1654
+ /**
1655
+ * Gets the internal Prisma client instance.
1656
+ * Creates one if it doesn't exist.
1657
+ */
1658
+ declare function getDbClient(): PrismaClient;
1659
+ /**
1660
+ * Sets the internal Prisma client instance.
1661
+ * Used by middleware to bridge with existing getDbClient() usage.
1662
+ */
1663
+ declare function setDbClient(client: PrismaClient): void;
1664
+ /**
1665
+ * Connects to the database.
1666
+ * Call this before performing database operations.
1667
+ */
1668
+ declare function connectDb(): Promise<void>;
1669
+ /**
1670
+ * Disconnects from the database.
1671
+ * Call this when done with database operations (e.g., in scripts).
1672
+ */
1673
+ declare function disconnectDb(): Promise<void>;
1674
+ //#endregion
1675
+ //#region src/db/tableSyncPrismaAdapter.d.ts
1676
+ type ScalarKeys<TPrismaModelName extends Prisma.ModelName> = keyof Prisma.TypeMap['model'][TPrismaModelName]['payload']['scalars'];
1677
+ type ObjectKeys<TPrismaModelName extends Prisma.ModelName> = keyof Prisma.TypeMap['model'][TPrismaModelName]['payload']['objects'];
1678
+ type ScalarFilter<TPrismaModelName extends Prisma.ModelName> = Partial<Prisma.TypeMap['model'][TPrismaModelName]['payload']['scalars']>;
1679
+ interface TableSyncParamsPrisma<TPrismaClient extends PrismaClient, TPrismaModelName extends Prisma.ModelName, TUniqColumns extends ReadonlyArray<ScalarKeys<TPrismaModelName>>, TRelationColumns extends ReadonlyArray<ObjectKeys<TPrismaModelName>>> {
1680
+ id?: ScalarKeys<TPrismaModelName>;
1681
+ prisma: TPrismaClient;
1682
+ prismaModelName: TPrismaModelName;
1683
+ uniqColumns: TUniqColumns;
1684
+ relationColumns?: TRelationColumns;
1685
+ where?: ScalarFilter<TPrismaModelName>;
1686
+ upsertOnly?: boolean;
1687
+ }
1688
+ type MakeTFromPrismaModel<TPrismaModelName extends Prisma.ModelName> = NonNullable<Prisma.TypeMap['model'][TPrismaModelName]['operations']['findUnique']['result']>;
1689
+ declare function tableSyncPrisma<TPrismaClient extends PrismaClient, TPrismaModelName extends Prisma.ModelName, TUniqColumns extends ReadonlyArray<ScalarKeys<TPrismaModelName>>, TRelationColumns extends ReadonlyArray<ObjectKeys<TPrismaModelName>>, TId extends ScalarKeys<TPrismaModelName> = ScalarKeys<TPrismaModelName>>(params: TableSyncParamsPrisma<TPrismaClient, TPrismaModelName, TUniqColumns, TRelationColumns>): {
1690
+ sync<TUpsert extends Partial<MakeTFromPrismaModel<TPrismaModelName>> & Pick<MakeTFromPrismaModel<TPrismaModelName>, TUniqColumns[number]>>(upsertRaw: TUpsert[]): Promise<{
1691
+ findIdMaybe: (key: Pick<MakeTFromPrismaModel<TPrismaModelName>, TUniqColumns[number]>) => MakeTFromPrismaModel<TPrismaModelName>[TId] | undefined;
1692
+ findIdOrThrow: (key: Pick<MakeTFromPrismaModel<TPrismaModelName>, TUniqColumns[number]>) => MakeTFromPrismaModel<TPrismaModelName>[TId];
1693
+ getActual(): (Pick<MakeTFromPrismaModel<TPrismaModelName>, TUniqColumns[number]> & MakeTFromPrismaModel<TPrismaModelName>[TId])[];
1694
+ }>;
1695
+ };
1696
+ //#endregion
1697
+ //#region src/db/tableSyncMagazine.d.ts
1698
+ declare const TABLE_SYNC_MAGAZINE: {
1699
+ readonly DbAppForCatalog: {
1700
+ readonly prismaModelName: "DbAppForCatalog";
1701
+ readonly uniqColumns: ["slug"];
1702
+ };
1703
+ readonly DbAppTagDefinition: {
1704
+ readonly prismaModelName: "DbAppTagDefinition";
1705
+ readonly uniqColumns: ["prefix"];
1706
+ };
1707
+ readonly DbApprovalMethod: {
1708
+ readonly id: "slug";
1709
+ readonly prismaModelName: "DbApprovalMethod";
1710
+ readonly uniqColumns: ["slug"];
1711
+ };
1712
+ };
1713
+ type TableSyncMagazine = typeof TABLE_SYNC_MAGAZINE;
1714
+ type TableSyncMagazineModelNameKey = keyof TableSyncMagazine;
1715
+ //#endregion
1716
+ //#region src/db/syncAppCatalog.d.ts
1717
+ interface SyncAppCatalogResult {
1718
+ created: number;
1719
+ updated: number;
1720
+ deleted: number;
1721
+ total: number;
1722
+ }
1723
+ /**
1724
+ * Syncs app catalog data to the database using table sync.
1725
+ * This will create new apps, update existing ones, and delete any that are no longer in the input.
1726
+ *
1727
+ * Note: Call connectDb() before and disconnectDb() after if running in a script.
1728
+ */
1729
+ declare function syncAppCatalog(apps: Array<AppForCatalog>, tagsDefinitions: Array<GroupingTagDefinition>, approvalMethods: Array<ApprovalMethod>, sreenshotsPath?: string): Promise<SyncAppCatalogResult>;
1730
+ //#endregion
1731
+ //#region src/middleware/types.d.ts
1732
+ /**
1733
+ * Database connection configuration.
1734
+ * Supports both connection URL and structured config.
1735
+ */
1736
+ type EhDatabaseConfig = {
1737
+ url: string;
1738
+ } | {
1739
+ host: string;
1740
+ port: number;
1741
+ database: string;
1742
+ username: string;
1743
+ password: string;
1744
+ schema?: string;
1745
+ };
1746
+ /**
1747
+ * Mock user configuration for development/testing.
1748
+ * When provided, bypasses authentication and injects this user into all requests.
1749
+ */
1750
+ interface EhDevMockUser {
1751
+ /** User ID */
1752
+ id: string;
1753
+ /** User email */
1754
+ email: string;
1755
+ /** User display name */
1756
+ name: string;
1757
+ /** User groups (for authorization) */
1758
+ groups: Array<string>;
1759
+ }
1760
+ /**
1761
+ * Auth configuration for Better Auth integration.
1762
+ */
1763
+ interface EhAuthConfig {
1764
+ /** Base URL for auth callbacks (e.g., 'http://localhost:4000') */
1765
+ baseURL: string;
1766
+ /** Secret for signing sessions (min 32 chars in production) */
1767
+ secret: string;
1768
+ /** OAuth providers configuration */
1769
+ providers?: BetterAuthOptions['socialProviders'];
1770
+ /** Additional Better Auth plugins (e.g., Okta) */
1771
+ plugins?: Array<BetterAuthPlugin>;
1772
+ /** Session expiration in seconds (default: 30 days) */
1773
+ sessionExpiresIn?: number;
1774
+ /** Session refresh threshold in seconds (default: 1 day) */
1775
+ sessionUpdateAge?: number;
1776
+ /** Application name shown in auth UI */
1777
+ appName?: string;
1778
+ /** Development mock user - bypasses auth when provided */
1779
+ devMockUser?: EhDevMockUser;
1780
+ /** Admin group names for authorization (default: ['env_hopper_ui_super_admins']) */
1781
+ adminGroups?: Array<string>;
1782
+ /** Okta groups claim name (e.g., 'env_hopper_ui_groups') - used to extract groups from access token JWT */
1783
+ oktaGroupsClaim?: string;
1784
+ }
1785
+ /**
1786
+ * Admin chat (AI) configuration.
1787
+ * When provided, enables the admin/chat endpoint.
1788
+ */
1789
+ interface EhAdminChatConfig {
1790
+ /** AI model instance from @ai-sdk/* packages */
1791
+ model: LanguageModel;
1792
+ /** System prompt for the AI assistant */
1793
+ systemPrompt?: string;
1794
+ /** Custom tools available to the AI */
1795
+ tools?: Record<string, Tool>;
1796
+ /** Validation function called before each request */
1797
+ validateConfig?: () => void;
1798
+ }
1799
+ /**
1800
+ * Feature toggles for enabling/disabling specific functionality.
1801
+ *
1802
+ * Note: Icons, assets, screenshots, and catalog backup are always enabled.
1803
+ * Only these optional features can be toggled:
1804
+ */
1805
+ interface EhFeatureToggles {
1806
+ /** Enable tRPC endpoints (default: true) */
1807
+ trpc?: boolean;
1808
+ /** Enable auth endpoints (default: true) */
1809
+ auth?: boolean;
1810
+ /** Enable admin chat endpoint (default: true if adminChat config provided) */
1811
+ adminChat?: boolean;
1812
+ /** Enable legacy icon endpoint at /static/icon/:icon (default: false) */
1813
+ legacyIconEndpoint?: boolean;
1814
+ }
1815
+ /**
1816
+ * Company-specific backend can be provided as:
1817
+ * 1. Direct object implementing the interface
1818
+ * 2. Factory function called per-request (for DI integration)
1819
+ * 3. Async factory function
1820
+ */
1821
+ type EhBackendProvider = AppCatalogCompanySpecificBackend | (() => AppCatalogCompanySpecificBackend) | (() => Promise<AppCatalogCompanySpecificBackend>);
1822
+ /**
1823
+ * Lifecycle hooks for database and middleware events.
1824
+ */
1825
+ interface EhLifecycleHooks {
1826
+ /** Called after database connection is established */
1827
+ onDatabaseConnected?: () => void | Promise<void>;
1828
+ /** Called before database disconnection (for cleanup) */
1829
+ onDatabaseDisconnecting?: () => void | Promise<void>;
1830
+ /** Called after all routes are registered - use to add custom routes */
1831
+ onRoutesRegistered?: (router: Router) => void | Promise<void>;
1832
+ /** Custom error handler for middleware errors */
1833
+ onError?: (error: Error, context: {
1834
+ path: string;
1835
+ }) => void;
1836
+ }
1837
+ /**
1838
+ * Main configuration options for the app-catalog middleware.
1839
+ */
1840
+ interface EhMiddlewareOptions {
1841
+ /**
1842
+ * Base path prefix for all routes (default: '/api')
1843
+ * - tRPC: {basePath}/trpc
1844
+ * - Auth: {basePath}/auth (note: auth basePath is hardcoded, this affects where router mounts)
1845
+ * - Icons: {basePath}/icons
1846
+ * - Assets: {basePath}/assets
1847
+ * - Screenshots: {basePath}/screenshots
1848
+ * - Admin Chat: {basePath}/admin/chat
1849
+ */
1850
+ basePath?: string;
1851
+ /**
1852
+ * Database connection configuration (required).
1853
+ * Backend-core manages the database for all features.
1854
+ */
1855
+ database: EhDatabaseConfig;
1856
+ /** Auth configuration (required) */
1857
+ auth: EhAuthConfig;
1858
+ /** Company-specific backend implementation (required) */
1859
+ backend: EhBackendProvider;
1860
+ /** AI admin chat configuration (optional) */
1861
+ adminChat?: EhAdminChatConfig;
1862
+ /** Feature toggles (all enabled by default) */
1863
+ features?: EhFeatureToggles;
1864
+ /** Lifecycle hooks */
1865
+ hooks?: EhLifecycleHooks;
1866
+ }
1867
+ /**
1868
+ * Result of middleware initialization.
1869
+ *
1870
+ * @example
1871
+ * ```typescript
1872
+ * const eh = await createEhMiddleware({ ... })
1873
+ *
1874
+ * // Mount routes
1875
+ * app.use(eh.router)
1876
+ *
1877
+ * // Connect to database
1878
+ * await eh.connect()
1879
+ *
1880
+ * // Cleanup on shutdown
1881
+ * process.on('SIGTERM', async () => {
1882
+ * await eh.disconnect()
1883
+ * })
1884
+ * ```
1885
+ */
1886
+ interface EhMiddlewareResult {
1887
+ /** Express router with all app-catalog routes */
1888
+ router: Router;
1889
+ /** Better Auth instance (for extending auth functionality) */
1890
+ auth: BetterAuth;
1891
+ /** tRPC router (for extending with custom procedures) */
1892
+ trpcRouter: TRPCRouter;
1893
+ /** Connect to database (call during app startup) */
1894
+ connect: () => Promise<void>;
1895
+ /** Disconnect from database (call during app shutdown) */
1896
+ disconnect: () => Promise<void>;
1897
+ /** Add custom routes to the middleware router */
1898
+ addRoutes: (callback: (router: Router) => void) => void;
1899
+ }
1900
+ /**
1901
+ * Internal context passed to feature registration functions.
1902
+ */
1903
+ interface MiddlewareContext {
1904
+ auth: BetterAuth;
1905
+ trpcRouter: TRPCRouter;
1906
+ createContext: () => Promise<{
1907
+ companySpecificBackend: AppCatalogCompanySpecificBackend;
1908
+ }>;
1909
+ authConfig: EhAuthConfig;
1910
+ }
1911
+ //#endregion
1912
+ //#region src/middleware/createEhMiddleware.d.ts
1913
+ declare function createEhMiddleware(options: EhMiddlewareOptions): Promise<EhMiddlewareResult>;
1914
+ //#endregion
1915
+ //#region src/middleware/database.d.ts
1916
+ /**
1917
+ * Internal database manager used by the middleware.
1918
+ * Handles connection URL formatting and lifecycle.
1919
+ */
1920
+ declare class EhDatabaseManager {
1921
+ private client;
1922
+ private config;
1923
+ constructor(config: EhDatabaseConfig);
1924
+ /**
1925
+ * Get or create the Prisma client instance.
1926
+ * Uses lazy initialization for flexibility.
1927
+ */
1928
+ getClient(): PrismaClient;
1929
+ connect(): Promise<void>;
1930
+ disconnect(): Promise<void>;
1931
+ }
1932
+ //#endregion
1933
+ export { type AdminChatHandlerOptions, AppAccessRequest, AppApprovalMethod, AppCatalogCompanySpecificBackend, AppCatalogData, AppCategory, type AppForCatalog, AppRole, ApprovalMethod, ApprovalMethodConfig, type ApprovalMethodSyncInput, ApprovalMethodType, ApprovalUrl, ApproverContact, type AssetRestControllerConfig, type AuthConfig, type AuthRouter, type BetterAuth, CreateApprovalMethodInput, CustomConfig, DEFAULT_ADMIN_SYSTEM_PROMPT, type DatabaseClient, type EhAdminChatConfig, EhAppIndexed, EhAppPageIndexed, EhAppUiIndexed, EhAppsMeta, type EhAuthConfig, EhBackendAppDto, EhBackendAppInput, EhBackendAppUIBaseInput, EhBackendAppUIInput, EhBackendCredentialInput, EhBackendDataFreshness, EhBackendDataSourceInput, EhBackendDataSourceInputCommon, EhBackendDataSourceInputDb, EhBackendDataSourceInputKafka, EhBackendDataVersion, EhBackendDeployableInput, EhBackendDeployment, EhBackendDeploymentInput, EhBackendEnvironmentInput, EhBackendPageInput, type EhBackendProvider, EhBackendTagDescriptionDataIndexed, EhBackendTagFixedTagValue, EhBackendTagsDescriptionDataIndexed, EhBackendUiDefaultsInput, EhBackendVersionsRequestParams, EhBackendVersionsReturn, EhContextIndexed, type EhDatabaseConfig, EhDatabaseManager, EhEnvIndexed, type EhFeatureToggles, type EhLifecycleHooks, EhMetaDictionary, type EhMiddlewareOptions, type EhMiddlewareResult, EhResourceIndexed, type EhStaticControllerContract, type EhTrpcContext, type EhTrpcContextOptions, GroupingTagDefinition, GroupingTagValue, type IconRestControllerConfig, type MakeTFromPrismaModel, type MiddlewareContext, type ObjectKeys, PersonTeamConfig, ReachOutContact, type ScalarFilter, type ScalarKeys, type ScreenshotRestControllerConfig, ServiceConfig, type SyncAppCatalogResult, type SyncAssetsConfig, TABLE_SYNC_MAGAZINE, type TRPCRouter, type TableSyncMagazine, type TableSyncMagazineModelNameKey, type TableSyncParamsPrisma, Tag, UpdateApprovalMethodInput, type UpsertIconInput, type UserWithGroups, connectDb, createAdminChatHandler, createAppCatalogAdminRouter, createApprovalMethodRouter, createAuth, createAuthRouter, createDatabaseTools, createEhMiddleware, createEhTrpcContext, createPrismaDatabaseClient, createScreenshotRouter, createTrpcRouter, disconnectDb, getAssetByName, getDbClient, getUserGroups, isAdmin, isMemberOfAllGroups, isMemberOfAnyGroup, registerAssetRestController, registerAuthRoutes, registerIconRestController, registerScreenshotRestController, requireAdmin, requireGroups, setDbClient, staticControllerContract, syncAppCatalog, syncApprovalMethods, syncAssets, tableSyncPrisma, tool, upsertIcon, upsertIcons };
1934
+ //# sourceMappingURL=index.d.ts.map