@constructive-io/graphql-server 4.33.0 → 4.34.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.
@@ -20,6 +20,9 @@
20
20
  *
21
21
  * Auth: JWT from the auth middleware (req.token) → pg SET LOCAL context for RLS
22
22
  * Metering: check_billing_quota → LLM call → record_usage with real token counts
23
+ *
24
+ * Context: Uses `req.constructive` from @constructive-io/express-context
25
+ * for tenant-scoped database access, pgSettings, and withPgClient.
23
26
  */
24
27
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
25
28
  if (k2 === undefined) k2 = k;
@@ -58,45 +61,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
58
61
  exports.createLlmApiRouter = createLlmApiRouter;
59
62
  const express_1 = __importStar(require("express"));
60
63
  const logger_1 = require("@pgpmjs/logger");
61
- const pg_cache_1 = require("pg-cache");
62
64
  const ollama_1 = require("@agentic-kit/ollama");
63
65
  const graphile_cache_1 = require("graphile-cache");
64
66
  const graphile_llm_1 = require("graphile-llm");
65
67
  const log = new logger_1.Logger('llm-api');
66
68
  // ─── Helpers ────────────────────────────────────────────────────────────────
67
- function getPgSettings(req) {
68
- const settings = {};
69
- if (req.token?.user_id) {
70
- settings['jwt.claims.user_id'] = req.token.user_id;
71
- settings['role'] = 'authenticated';
72
- }
73
- if (req.databaseId) {
74
- settings['jwt.claims.database_id'] = req.databaseId;
75
- }
76
- if (req.requestId) {
77
- settings['request.id'] = req.requestId;
78
- }
79
- return settings;
80
- }
81
- async function withRlsClient(pool, pgSettings, fn) {
82
- const client = await pool.connect();
83
- try {
84
- await client.query('BEGIN');
85
- for (const [key, value] of Object.entries(pgSettings)) {
86
- await client.query('SELECT set_config($1, $2, true)', [key, value]);
87
- }
88
- const result = await fn(client);
89
- await client.query('COMMIT');
90
- return result;
91
- }
92
- catch (err) {
93
- await client.query('ROLLBACK').catch(() => { });
94
- throw err;
95
- }
96
- finally {
97
- client.release();
98
- }
99
- }
100
69
  function resolveOllamaAdapter() {
101
70
  const { chat } = (0, graphile_llm_1.getLlmEnvOptions)();
102
71
  if (chat.provider === 'ollama') {
@@ -109,9 +78,9 @@ function resolveOllamaAdapter() {
109
78
  return null;
110
79
  }
111
80
  // ─── Billing Helpers ────────────────────────────────────────────────────────
112
- async function checkQuota(pool, pgSettings, billing, entityId, meterSlug) {
81
+ async function checkQuota(ctx, billing, entityId, meterSlug) {
113
82
  try {
114
- return await withRlsClient(pool, pgSettings, async (client) => {
83
+ return await ctx.withPgClient(async (client) => {
115
84
  const sql = `SELECT "${billing.privateSchema}"."${billing.checkBillingQuotaFunction}"($1, $2::uuid, $3) AS allowed`;
116
85
  const result = await client.query(sql, [meterSlug, entityId, 1]);
117
86
  return result.rows[0]?.allowed !== false;
@@ -123,9 +92,9 @@ async function checkQuota(pool, pgSettings, billing, entityId, meterSlug) {
123
92
  return true;
124
93
  }
125
94
  }
126
- async function recordUsage(pool, pgSettings, billing, entityId, meterSlug, amount, metadata) {
95
+ async function recordUsage(ctx, billing, entityId, meterSlug, amount, metadata) {
127
96
  try {
128
- await withRlsClient(pool, pgSettings, async (client) => {
97
+ await ctx.withPgClient(async (client) => {
129
98
  const sql = `SELECT "${billing.privateSchema}"."${billing.recordUsageFunction}"($1, $2::uuid, $3, $4::jsonb)`;
130
99
  await client.query(sql, [meterSlug, entityId, amount, JSON.stringify(metadata)]);
131
100
  });
@@ -135,11 +104,13 @@ async function recordUsage(pool, pgSettings, billing, entityId, meterSlug, amoun
135
104
  log.warn(`[llm-api] record_usage failed (non-fatal): ${message}`);
136
105
  }
137
106
  }
138
- async function resolveBilling(pool, pgSettings, databaseId) {
107
+ async function resolveBilling(ctx) {
108
+ if (!ctx.databaseId)
109
+ return null;
139
110
  try {
140
111
  let billing = null;
141
- await withRlsClient(pool, pgSettings, async (client) => {
142
- const entry = await (0, graphile_llm_1.getLlmBillingConfig)(client, databaseId);
112
+ await ctx.withPgClient(async (client) => {
113
+ const entry = await (0, graphile_llm_1.getLlmBillingConfig)(client, ctx.databaseId);
143
114
  billing = entry.billing;
144
115
  });
145
116
  return billing;
@@ -178,9 +149,9 @@ async function getInferenceLogInfo(pool, dbname) {
178
149
  inferenceLogCache.set(dbname, info);
179
150
  return info;
180
151
  }
181
- async function logInference(pool, pgSettings, logInfo, data) {
152
+ async function logInference(ctx, logInfo, data) {
182
153
  try {
183
- await withRlsClient(pool, pgSettings, async (client) => {
154
+ await ctx.withPgClient(async (client) => {
184
155
  await client.query(`INSERT INTO "${logInfo.schemaName}"."${logInfo.tableName}"
185
156
  (entity_id, actor_id, model, provider, service, operation, input_tokens, output_tokens, total_tokens, latency_ms, status)
186
157
  VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)`, [
@@ -205,31 +176,29 @@ async function logInference(pool, pgSettings, logInfo, data) {
205
176
  }
206
177
  // ─── Route Handlers ─────────────────────────────────────────────────────────
207
178
  async function handleCreateThread(req, res, entityId) {
208
- if (!req.token?.user_id) {
179
+ const ctx = req.constructive;
180
+ if (!ctx?.userId) {
209
181
  res.status(401).json({ error: 'Authentication required' });
210
182
  return;
211
183
  }
212
- const dbname = req.api?.dbname;
213
- if (!dbname) {
184
+ if (!ctx.api.dbname) {
214
185
  res.status(400).json({ error: 'Database not resolved' });
215
186
  return;
216
187
  }
217
- const pool = (0, pg_cache_1.getPgPool)({ database: dbname });
218
- const discovery = await (0, graphile_llm_1.getAgentDiscovery)(pool, dbname);
188
+ const discovery = await (0, graphile_llm_1.getAgentDiscovery)(ctx.pool, ctx.api.dbname);
219
189
  if (!discovery?.thread) {
220
190
  res.status(404).json({ error: 'Agent module not provisioned for this database' });
221
191
  return;
222
192
  }
223
193
  const body = req.body || {};
224
194
  const { thread } = discovery;
225
- const pgSettings = getPgSettings(req);
226
- const result = await withRlsClient(pool, pgSettings, async (client) => {
195
+ const result = await ctx.withPgClient(async (client) => {
227
196
  const { rows } = await client.query(`INSERT INTO "${thread.schemaName}"."${thread.tableName}"
228
197
  (entity_id, owner_id, mode, model, system_prompt, title)
229
198
  VALUES ($1, $2, $3, $4, $5, $6)
230
199
  RETURNING id, mode, model, system_prompt, status, created_at`, [
231
200
  entityId,
232
- req.token.user_id,
201
+ ctx.userId,
233
202
  body.mode ?? 'ask',
234
203
  body.model ?? null,
235
204
  body.system_prompt ?? null,
@@ -247,17 +216,16 @@ async function handleCreateThread(req, res, entityId) {
247
216
  });
248
217
  }
249
218
  async function handleSendMessage(req, res, entityId) {
250
- if (!req.token?.user_id) {
219
+ const ctx = req.constructive;
220
+ if (!ctx?.userId) {
251
221
  res.status(401).json({ error: 'Authentication required' });
252
222
  return;
253
223
  }
254
- const dbname = req.api?.dbname;
255
- if (!dbname) {
224
+ if (!ctx.api.dbname) {
256
225
  res.status(400).json({ error: 'Database not resolved' });
257
226
  return;
258
227
  }
259
- const pool = (0, pg_cache_1.getPgPool)({ database: dbname });
260
- const discovery = await (0, graphile_llm_1.getAgentDiscovery)(pool, dbname);
228
+ const discovery = await (0, graphile_llm_1.getAgentDiscovery)(ctx.pool, ctx.api.dbname);
261
229
  if (!discovery?.thread || !discovery?.message) {
262
230
  res.status(404).json({ error: 'Agent module not provisioned for this database' });
263
231
  return;
@@ -268,12 +236,10 @@ async function handleSendMessage(req, res, entityId) {
268
236
  return;
269
237
  }
270
238
  const { thread, message: msgTable } = discovery;
271
- const pgSettings = getPgSettings(req);
272
239
  const threadId = req.params.thread_id;
273
- const userId = req.token.user_id;
274
- const databaseId = req.databaseId;
240
+ const userId = ctx.userId;
275
241
  // 1. Verify thread exists and user owns it (RLS enforced)
276
- const threadRow = await withRlsClient(pool, pgSettings, async (client) => {
242
+ const threadRow = await ctx.withPgClient(async (client) => {
277
243
  const { rows } = await client.query(`SELECT id, mode, model, system_prompt, status
278
244
  FROM "${thread.schemaName}"."${thread.tableName}"
279
245
  WHERE id = $1`, [threadId]);
@@ -284,10 +250,8 @@ async function handleSendMessage(req, res, entityId) {
284
250
  return;
285
251
  }
286
252
  // 2. Resolve billing config + inference log discovery
287
- const billing = databaseId
288
- ? await resolveBilling(pool, pgSettings, databaseId)
289
- : null;
290
- const inferenceLog = await getInferenceLogInfo(pool, dbname);
253
+ const billing = await resolveBilling(ctx);
254
+ const inferenceLog = await getInferenceLogInfo(ctx.pool, ctx.api.dbname);
291
255
  const ollama = resolveOllamaAdapter();
292
256
  if (!ollama) {
293
257
  res.status(503).json({ error: 'No LLM provider configured' });
@@ -296,7 +260,7 @@ async function handleSendMessage(req, res, entityId) {
296
260
  const model = body.model ?? threadRow.model ?? ollama.model;
297
261
  const meterSlug = model;
298
262
  if (billing) {
299
- const allowed = await checkQuota(pool, pgSettings, billing, entityId, meterSlug);
263
+ const allowed = await checkQuota(ctx, billing, entityId, meterSlug);
300
264
  if (!allowed) {
301
265
  res.status(429).json({
302
266
  error: 'Token quota exceeded',
@@ -307,7 +271,7 @@ async function handleSendMessage(req, res, entityId) {
307
271
  }
308
272
  }
309
273
  // 3. Persist user message(s)
310
- await withRlsClient(pool, pgSettings, async (client) => {
274
+ await ctx.withPgClient(async (client) => {
311
275
  for (const msg of body.messages) {
312
276
  if (msg.role === 'user') {
313
277
  await client.query(`INSERT INTO "${msgTable.schemaName}"."${msgTable.tableName}"
@@ -322,7 +286,7 @@ async function handleSendMessage(req, res, entityId) {
322
286
  }
323
287
  });
324
288
  // 4. Load full thread history for context
325
- const history = await withRlsClient(pool, pgSettings, async (client) => {
289
+ const history = await ctx.withPgClient(async (client) => {
326
290
  const { rows } = await client.query(`SELECT author_role, parts, created_at
327
291
  FROM "${msgTable.schemaName}"."${msgTable.tableName}"
328
292
  WHERE thread_id = $1
@@ -408,7 +372,7 @@ async function handleSendMessage(req, res, entityId) {
408
372
  res.end();
409
373
  // 6. Persist assistant message with model (fire-and-forget)
410
374
  if (content) {
411
- withRlsClient(pool, pgSettings, async (client) => {
375
+ ctx.withPgClient(async (client) => {
412
376
  await client.query(`INSERT INTO "${msgTable.schemaName}"."${msgTable.tableName}"
413
377
  (thread_id, owner_id, entity_id, author_role, parts, model)
414
378
  VALUES ($1, $2, (SELECT entity_id FROM "${thread.schemaName}"."${thread.tableName}" WHERE id = $1), $3, $4, $5)`, [
@@ -424,7 +388,7 @@ async function handleSendMessage(req, res, entityId) {
424
388
  }
425
389
  // 7. Record billing usage (fire-and-forget)
426
390
  if (billing && usage.totalTokens > 0) {
427
- recordUsage(pool, pgSettings, billing, entityId, meterSlug, usage.totalTokens, {
391
+ recordUsage(ctx, billing, entityId, meterSlug, usage.totalTokens, {
428
392
  input_tokens: usage.input,
429
393
  output_tokens: usage.output,
430
394
  cache_read_tokens: usage.cacheRead,
@@ -436,7 +400,7 @@ async function handleSendMessage(req, res, entityId) {
436
400
  }
437
401
  // 8. Inference log (fire-and-forget)
438
402
  if (inferenceLog) {
439
- logInference(pool, pgSettings, inferenceLog, {
403
+ logInference(ctx, inferenceLog, {
440
404
  entityId,
441
405
  actorId: userId,
442
406
  model,
@@ -492,7 +456,7 @@ async function handleSendMessage(req, res, entityId) {
492
456
  totalTokens: result.usage.totalTokens,
493
457
  };
494
458
  // Persist assistant message with model
495
- await withRlsClient(pool, pgSettings, async (client) => {
459
+ await ctx.withPgClient(async (client) => {
496
460
  await client.query(`INSERT INTO "${msgTable.schemaName}"."${msgTable.tableName}"
497
461
  (thread_id, owner_id, entity_id, author_role, parts, model)
498
462
  VALUES ($1, $2, (SELECT entity_id FROM "${thread.schemaName}"."${thread.tableName}" WHERE id = $1), $3, $4, $5)`, [
@@ -505,7 +469,7 @@ async function handleSendMessage(req, res, entityId) {
505
469
  });
506
470
  // Record billing usage
507
471
  if (billing && usage.totalTokens > 0) {
508
- recordUsage(pool, pgSettings, billing, entityId, meterSlug, usage.totalTokens, {
472
+ recordUsage(ctx, billing, entityId, meterSlug, usage.totalTokens, {
509
473
  input_tokens: usage.input,
510
474
  output_tokens: usage.output,
511
475
  cache_read_tokens: usage.cacheRead,
@@ -517,7 +481,7 @@ async function handleSendMessage(req, res, entityId) {
517
481
  }
518
482
  // Inference log
519
483
  if (inferenceLog) {
520
- logInference(pool, pgSettings, inferenceLog, {
484
+ logInference(ctx, inferenceLog, {
521
485
  entityId,
522
486
  actorId: userId,
523
487
  model,
@@ -577,7 +541,7 @@ function createLlmApiRouter() {
577
541
  // ── Global routes (no entity_id — bills to actor_id from JWT) ────────────
578
542
  router.post('/v1/threads', async (req, res) => {
579
543
  try {
580
- const userId = req.token?.user_id;
544
+ const userId = req.constructive?.userId;
581
545
  if (!userId) {
582
546
  res.status(401).json({ error: 'Authentication required' });
583
547
  return;
@@ -593,7 +557,7 @@ function createLlmApiRouter() {
593
557
  });
594
558
  router.post('/v1/threads/:thread_id/messages', async (req, res) => {
595
559
  try {
596
- const userId = req.token?.user_id;
560
+ const userId = req.constructive?.userId;
597
561
  if (!userId) {
598
562
  res.status(401).json({ error: 'Authentication required' });
599
563
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@constructive-io/graphql-server",
3
- "version": "4.33.0",
3
+ "version": "4.34.1",
4
4
  "author": "Constructive <developers@constructive.io>",
5
5
  "description": "Constructive GraphQL Server",
6
6
  "main": "index.js",
@@ -43,16 +43,17 @@
43
43
  "dependencies": {
44
44
  "@agentic-kit/ollama": "^2.0.0",
45
45
  "@constructive-io/csrf": "^0.14.0",
46
- "@constructive-io/graphql-env": "^3.11.1",
47
- "@constructive-io/graphql-types": "^3.10.1",
46
+ "@constructive-io/express-context": "^0.2.1",
47
+ "@constructive-io/graphql-env": "^3.12.0",
48
+ "@constructive-io/graphql-types": "^3.11.0",
48
49
  "@constructive-io/s3-utils": "^2.17.1",
49
50
  "@constructive-io/upload-names": "^2.16.0",
50
51
  "@constructive-io/url-domains": "^2.16.0",
51
52
  "@graphile-contrib/pg-many-to-many": "2.0.0-rc.2",
52
- "@pgpmjs/env": "^2.23.0",
53
+ "@pgpmjs/env": "^2.24.0",
53
54
  "@pgpmjs/logger": "^2.11.0",
54
- "@pgpmjs/server-utils": "^3.11.0",
55
- "@pgpmjs/types": "^2.27.0",
55
+ "@pgpmjs/server-utils": "^3.12.0",
56
+ "@pgpmjs/types": "^2.28.0",
56
57
  "@pgsql/quotes": "^17.1.0",
57
58
  "cors": "^2.8.6",
58
59
  "deepmerge": "^4.3.1",
@@ -62,19 +63,19 @@
62
63
  "grafserv": "1.0.0",
63
64
  "graphile-build": "5.0.2",
64
65
  "graphile-build-pg": "5.0.2",
65
- "graphile-cache": "^3.11.2",
66
+ "graphile-cache": "^3.12.0",
66
67
  "graphile-config": "1.0.1",
67
- "graphile-llm": "^0.9.0",
68
- "graphile-settings": "^5.2.4",
68
+ "graphile-llm": "^0.10.0",
69
+ "graphile-settings": "^5.3.0",
69
70
  "graphile-utils": "5.0.1",
70
71
  "graphql": "16.13.0",
71
72
  "graphql-upload": "^13.0.0",
72
73
  "lru-cache": "^11.2.7",
73
74
  "multer": "^2.1.1",
74
75
  "pg": "^8.21.0",
75
- "pg-cache": "^3.10.1",
76
- "pg-env": "^1.14.0",
77
- "pg-query-context": "^2.15.1",
76
+ "pg-cache": "^3.11.0",
77
+ "pg-env": "^1.15.0",
78
+ "pg-query-context": "^2.16.0",
78
79
  "pg-sql2": "5.0.1",
79
80
  "postgraphile": "5.0.3",
80
81
  "request-ip": "^3.3.0"
@@ -89,10 +90,10 @@
89
90
  "@types/pg": "^8.20.0",
90
91
  "@types/request-ip": "^0.0.41",
91
92
  "cookie-parser": "^1.4.7",
92
- "graphile-test": "4.15.3",
93
+ "graphile-test": "4.16.0",
93
94
  "makage": "^0.3.0",
94
95
  "nodemon": "^3.1.14",
95
96
  "ts-node": "^10.9.2"
96
97
  },
97
- "gitHead": "f3ea414974306e3c0d1d68edc93b4cdd8fa6e806"
98
+ "gitHead": "ccc303b2a2d1d9701648efc124ea1d9f2714711f"
98
99
  }
package/server.js CHANGED
@@ -34,6 +34,7 @@ const captcha_1 = require("./middleware/captcha");
34
34
  const cookie_1 = require("./middleware/cookie");
35
35
  const upload_1 = require("./middleware/upload");
36
36
  const llm_api_1 = require("./middleware/llm-api");
37
+ const express_context_1 = require("@constructive-io/express-context");
37
38
  const debug_sampler_1 = require("./diagnostics/debug-sampler");
38
39
  const log = new logger_1.Logger('server');
39
40
  /**
@@ -142,10 +143,12 @@ class Server {
142
143
  app.use('/graphql', multipart_bridge_1.multipartBridge);
143
144
  app.use((0, url_domains_1.middleware)());
144
145
  app.use(request_ip_1.default.mw());
146
+ app.use((0, express_context_1.requestIdMiddleware)());
145
147
  app.use(requestLogger);
146
148
  app.use(api);
147
149
  app.post('/upload', uploadAuthenticate, ...upload_1.uploadRoute);
148
150
  app.use(authenticate);
151
+ app.use((0, express_context_1.createContextMiddleware)({ pg: effectiveOpts.pg }));
149
152
  app.use((0, captcha_1.createCaptchaMiddleware)());
150
153
  // CSRF protection for cookie-authenticated requests
151
154
  // Skip CSRF for Bearer token auth (not vulnerable to CSRF) and anonymous requests
package/types.d.ts CHANGED
@@ -1,129 +1,6 @@
1
1
  import type { PgpmOptions } from '@pgpmjs/types';
2
2
  import type { ApiOptions as ApiConfig } from '@constructive-io/graphql-types';
3
- export interface CorsModuleData {
4
- urls: string[];
5
- }
6
- export interface PublicKeyChallengeData {
7
- schema: string;
8
- crypto_network: string;
9
- sign_up_with_key: string;
10
- sign_in_request_challenge: string;
11
- sign_in_record_failure: string;
12
- sign_in_with_challenge: string;
13
- }
14
- export interface GenericModuleData {
15
- [key: string]: unknown;
16
- }
17
- /**
18
- * Resolved feature flags from database_settings + api_settings cascade.
19
- * api_settings values (when non-null) override database_settings defaults.
20
- */
21
- export interface DatabaseSettings {
22
- enableAggregates: boolean;
23
- enablePostgis: boolean;
24
- enableSearch: boolean;
25
- enableDirectUploads: boolean;
26
- enablePresignedUploads: boolean;
27
- enableManyToMany: boolean;
28
- enableConnectionFilter: boolean;
29
- enableLtree: boolean;
30
- enableLlm: boolean;
31
- enableRealtime: boolean;
32
- enableBulk: boolean;
33
- }
34
- /**
35
- * Resolved pubkey challenge config from pubkey_settings typed table.
36
- * Matches the shape expected by the PublicKeySignature Graphile plugin.
37
- */
38
- export interface PubkeyChallengeSettings {
39
- schema: string;
40
- cryptoNetwork: string;
41
- signUpWithKey: string;
42
- signInRequestChallenge: string;
43
- signInRecordFailure: string;
44
- signInWithChallenge: string;
45
- }
46
- /**
47
- * Resolved WebAuthn config from webauthn_settings typed table.
48
- * Stored on ApiStructure for future server-side WebAuthn wiring.
49
- */
50
- export interface WebauthnSettings {
51
- schema: string;
52
- credentialsSchema: string;
53
- sessionsSchema: string;
54
- sessionSecretsSchema: string;
55
- rpId: string;
56
- rpName: string;
57
- originAllowlist: string[];
58
- attestationType: string;
59
- requireUserVerification: boolean;
60
- residentKey: string;
61
- challengeExpirySeconds: number;
62
- }
63
- export type ApiModule = {
64
- name: 'cors';
65
- data: CorsModuleData;
66
- } | {
67
- name: 'pubkey_challenge';
68
- data: PublicKeyChallengeData;
69
- } | {
70
- name: string;
71
- data?: GenericModuleData;
72
- };
73
- export interface RlsModule {
74
- authenticate: string;
75
- authenticateStrict: string;
76
- privateSchema: {
77
- schemaName: string;
78
- };
79
- publicSchema: {
80
- schemaName: string;
81
- };
82
- currentRole: string;
83
- currentRoleId: string;
84
- currentIpAddress: string;
85
- currentUserAgent: string;
86
- }
87
- /**
88
- * Server-visible subset of app_auth_settings (lives in the tenant DB private schema).
89
- * Discovered dynamically via metaschema_modules_public.sessions_module.
90
- * Loaded once per API resolution and cached alongside the ApiStructure.
91
- */
92
- export interface AuthSettings {
93
- /** Cookie configuration */
94
- cookieSecure?: boolean;
95
- cookieSamesite?: string;
96
- cookieDomain?: string | null;
97
- cookieHttponly?: boolean;
98
- cookieMaxAge?: string | null;
99
- cookiePath?: string;
100
- /** Remember me duration (seconds) for extended session cookies */
101
- rememberMeDuration?: string | null;
102
- /** reCAPTCHA / CAPTCHA */
103
- enableCaptcha?: boolean;
104
- captchaSiteKey?: string | null;
105
- }
106
- export interface ApiStructure {
107
- apiId?: string;
108
- dbname: string;
109
- anonRole: string;
110
- roleName: string;
111
- schema: string[];
112
- apiModules: ApiModule[];
113
- rlsModule?: RlsModule;
114
- domains?: string[];
115
- databaseId?: string;
116
- isPublic?: boolean;
117
- authSettings?: AuthSettings;
118
- corsOrigins?: string[];
119
- databaseSettings?: DatabaseSettings;
120
- pubkeyChallengeSettings?: PubkeyChallengeSettings;
121
- webauthnSettings?: WebauthnSettings;
122
- }
123
- export type ApiError = {
124
- errorHtml: string;
125
- };
126
- export type ApiConfigResult = ApiStructure | ApiError | null;
3
+ export type { ApiConfigResult, ApiError, ApiModule, ApiStructure, AuthSettings, CorsModuleData, DatabaseSettings, GenericModuleData, PubkeyChallengeSettings, PublicKeyChallengeData, RlsModule, WebauthnSettings, } from '@constructive-io/express-context';
127
4
  export type ApiOptions = PgpmOptions & {
128
5
  api?: ApiConfig;
129
6
  };