@constructive-io/express-context 0.28.0 → 0.30.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/esm/index.js CHANGED
@@ -45,6 +45,6 @@ export { BoundedCounter, CounterFlusher } from './usage-counter';
45
45
  // Request ID middleware
46
46
  export { requestIdMiddleware } from './request-id';
47
47
  export { buildContext, createContextMiddleware } from './context';
48
- export { agentChatLoader, authSettingsLoader, authSurfaceLoader, billingLoader, computeLoader, corsLoader, createDefaultRegistry, createLoaderRegistry, createModuleLoader, databaseSettingsLoader, identityProvidersLoader, inferenceLogLoader, llmLoader, pubkeyLoader, requestProtectionLoader, requireDatabaseId, requireIdentityProvider, rlsLoader, webauthnLoader, } from './loaders';
48
+ export { agentChatLoader, authSettingsLoader, authSurfaceLoader, billingLoader, computeLoader, corsLoader, createDefaultRegistry, createLoaderRegistry, createModuleLoader, databaseSettingsLoader, eventsLoader, identityProvidersLoader, inferenceLogLoader, llmLoader, pubkeyLoader, requestProtectionLoader, requireDatabaseId, requireIdentityProvider, rlsLoader, webauthnLoader, } from './loaders';
49
49
  // Side-effect: Express type augmentation
50
50
  import './types';
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Events Module Loader
3
+ *
4
+ * Resolves the tenant's app-scoped events module from
5
+ * metaschema_modules_public.events_module: the private schema and the names of
6
+ * its `record_event` and `record_error` functions, so the server can record
7
+ * events without hard-coding the generated schema or function names.
8
+ */
9
+ import { createModuleLoader } from './create-loader';
10
+ // ─── SQL ────────────────────────────────────────────────────────────────────
11
+ const EVENTS_MODULE_SQL = `
12
+ SELECT
13
+ s.schema_name AS private_schema_name,
14
+ em.record_event,
15
+ em.record_error
16
+ FROM metaschema_modules_public.events_module em
17
+ JOIN metaschema_public.schema s ON s.id = em.private_schema_id
18
+ WHERE em.database_id = $1
19
+ AND em.scope = 'app'
20
+ LIMIT 1
21
+ `;
22
+ // ─── Loader ─────────────────────────────────────────────────────────────────
23
+ export const eventsLoader = createModuleLoader({
24
+ name: 'events',
25
+ ttlMs: 60_000,
26
+ async resolve(ctx) {
27
+ const { tenantPool, databaseId } = ctx;
28
+ const result = await tenantPool.query(EVENTS_MODULE_SQL, [databaseId]);
29
+ const row = result.rows[0];
30
+ if (!row?.private_schema_name || !row.record_event)
31
+ return undefined;
32
+ return {
33
+ privateSchemaName: row.private_schema_name,
34
+ recordEvent: row.record_event,
35
+ recordError: row.record_error ?? null
36
+ };
37
+ }
38
+ });
@@ -14,6 +14,7 @@
14
14
  * - webauthnSettings(routing-plane webauthn_settings)
15
15
  * - authSettings (metaschema_modules_public.sessions_module → tenant DB)
16
16
  * - authSurface (identity/connected-accounts/emails modules → tenant DB)
17
+ * - events (metaschema_modules_public.events_module, app scope → tenant DB)
17
18
  *
18
19
  * Opt-in (not in the default registry, register it explicitly):
19
20
  * - identityProviders (three round trips, decrypts client secrets)
@@ -41,6 +42,7 @@ export { billingLoader } from './billing';
41
42
  export { computeLoader } from './compute';
42
43
  export { corsLoader } from './cors';
43
44
  export { databaseSettingsLoader } from './database-settings';
45
+ export { eventsLoader } from './events';
44
46
  export { identityProvidersLoader, requireIdentityProvider } from './identity-providers';
45
47
  export { inferenceLogLoader } from './inference-log';
46
48
  export { llmLoader } from './llm';
@@ -58,6 +60,7 @@ import { billingLoader } from './billing';
58
60
  import { computeLoader } from './compute';
59
61
  import { corsLoader } from './cors';
60
62
  import { databaseSettingsLoader } from './database-settings';
63
+ import { eventsLoader } from './events';
61
64
  import { inferenceLogLoader } from './inference-log';
62
65
  import { llmLoader } from './llm';
63
66
  import { pubkeyLoader } from './pubkey';
@@ -79,6 +82,7 @@ export function createDefaultRegistry() {
79
82
  registry.register(agentChatLoader);
80
83
  registry.register(llmLoader);
81
84
  registry.register(computeLoader);
85
+ registry.register(eventsLoader);
82
86
  registry.register(requestProtectionLoader);
83
87
  return registry;
84
88
  }
package/index.d.ts CHANGED
@@ -34,7 +34,7 @@
34
34
  * });
35
35
  * ```
36
36
  */
37
- export type { AgentChatConfig, ApiConfigResult, ApiError, ApiStructure, AuthSettings, AuthSurface, BillingConfig, BuiltinModuleMap, ComputeConfig, ComputeModuleConfig, ConstructiveAPIToken, ConstructiveContext, DatabaseSettings, IdentityProviderConfig, IdentityProvidersModule, InferenceLogConfig, LlmConfig, PubkeyChallengeSettings, RlsModule, WebauthnSettings, WithPgClient, } from './types';
37
+ export type { AgentChatConfig, ApiConfigResult, ApiError, ApiStructure, AuthSettings, AuthSurface, BillingConfig, BuiltinModuleMap, ComputeConfig, ComputeModuleConfig, ConstructiveAPIToken, ConstructiveContext, DatabaseSettings, EventsConfig, IdentityProviderConfig, IdentityProvidersModule, InferenceLogConfig, LlmConfig, PubkeyChallengeSettings, RlsModule, WebauthnSettings, WithPgClient, } from './types';
38
38
  export type { BillingClient, InferenceLogEntry } from './billing-client';
39
39
  export { createBillingClient } from './billing-client';
40
40
  export type { PgSettingsInput } from './pg-settings';
@@ -52,5 +52,5 @@ export { requestIdMiddleware } from './request-id';
52
52
  export type { ContextMiddlewareOptions } from './context';
53
53
  export { buildContext, createContextMiddleware } from './context';
54
54
  export type { CreateLoaderOptions, LoaderContext, LoaderRegistry, ModuleLoader, } from './loaders';
55
- export { agentChatLoader, authSettingsLoader, authSurfaceLoader, billingLoader, computeLoader, corsLoader, createDefaultRegistry, createLoaderRegistry, createModuleLoader, databaseSettingsLoader, identityProvidersLoader, inferenceLogLoader, llmLoader, pubkeyLoader, requestProtectionLoader, requireDatabaseId, requireIdentityProvider, rlsLoader, webauthnLoader, } from './loaders';
55
+ export { agentChatLoader, authSettingsLoader, authSurfaceLoader, billingLoader, computeLoader, corsLoader, createDefaultRegistry, createLoaderRegistry, createModuleLoader, databaseSettingsLoader, eventsLoader, identityProvidersLoader, inferenceLogLoader, llmLoader, pubkeyLoader, requestProtectionLoader, requireDatabaseId, requireIdentityProvider, rlsLoader, webauthnLoader, } from './loaders';
56
56
  import './types';
package/index.js CHANGED
@@ -36,7 +36,8 @@
36
36
  * ```
37
37
  */
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.webauthnLoader = exports.rlsLoader = exports.requireIdentityProvider = exports.requireDatabaseId = exports.requestProtectionLoader = exports.pubkeyLoader = exports.llmLoader = exports.inferenceLogLoader = exports.identityProvidersLoader = exports.databaseSettingsLoader = exports.createModuleLoader = exports.createLoaderRegistry = exports.createDefaultRegistry = exports.corsLoader = exports.computeLoader = exports.billingLoader = exports.authSurfaceLoader = exports.authSettingsLoader = exports.agentChatLoader = exports.createContextMiddleware = exports.buildContext = exports.requestIdMiddleware = exports.CounterFlusher = exports.BoundedCounter = exports.UNKNOWN_SOURCE = exports.sourceBucket = exports.refusalRows = exports.RefusalRecorder = exports.refusalOverflowKey = exports.refusalKeyOf = exports.REFUSAL_REASONS = exports.OVERFLOW_SOURCE = exports.OVERFLOW_ROUTE = exports.DEFAULT_REFUSAL_MAX_KEYS = exports.DEFAULT_REFUSAL_FLUSH_JITTER_MS = exports.DEFAULT_REFUSAL_FLUSH_INTERVAL_MS = exports.createRecordRefusalsSink = exports.trustedProxyHops = exports.RateWindow = exports.ConcurrencyLimiter = exports.clientIpFrom = exports.resolveRequestProtection = exports.protectionPgSettings = exports.PROTECTION_BOUNDS = exports.INTROSPECTION_BOUND = exports.DEFAULT_REQUEST_PROTECTION = exports.ASSUMED_PAGE_SIZE = exports.withPgClient = exports.buildPgSettings = exports.createBillingClient = void 0;
39
+ exports.rlsLoader = exports.requireIdentityProvider = exports.requireDatabaseId = exports.requestProtectionLoader = exports.pubkeyLoader = exports.llmLoader = exports.inferenceLogLoader = exports.identityProvidersLoader = exports.eventsLoader = exports.databaseSettingsLoader = exports.createModuleLoader = exports.createLoaderRegistry = exports.createDefaultRegistry = exports.corsLoader = exports.computeLoader = exports.billingLoader = exports.authSurfaceLoader = exports.authSettingsLoader = exports.agentChatLoader = exports.createContextMiddleware = exports.buildContext = exports.requestIdMiddleware = exports.CounterFlusher = exports.BoundedCounter = exports.UNKNOWN_SOURCE = exports.sourceBucket = exports.refusalRows = exports.RefusalRecorder = exports.refusalOverflowKey = exports.refusalKeyOf = exports.REFUSAL_REASONS = exports.OVERFLOW_SOURCE = exports.OVERFLOW_ROUTE = exports.DEFAULT_REFUSAL_MAX_KEYS = exports.DEFAULT_REFUSAL_FLUSH_JITTER_MS = exports.DEFAULT_REFUSAL_FLUSH_INTERVAL_MS = exports.createRecordRefusalsSink = exports.trustedProxyHops = exports.RateWindow = exports.ConcurrencyLimiter = exports.clientIpFrom = exports.resolveRequestProtection = exports.protectionPgSettings = exports.PROTECTION_BOUNDS = exports.INTROSPECTION_BOUND = exports.DEFAULT_REQUEST_PROTECTION = exports.ASSUMED_PAGE_SIZE = exports.withPgClient = exports.buildPgSettings = exports.createBillingClient = void 0;
40
+ exports.webauthnLoader = void 0;
40
41
  var billing_client_1 = require("./billing-client");
41
42
  Object.defineProperty(exports, "createBillingClient", { enumerable: true, get: function () { return billing_client_1.createBillingClient; } });
42
43
  var pg_settings_1 = require("./pg-settings");
@@ -90,6 +91,7 @@ Object.defineProperty(exports, "createDefaultRegistry", { enumerable: true, get:
90
91
  Object.defineProperty(exports, "createLoaderRegistry", { enumerable: true, get: function () { return loaders_1.createLoaderRegistry; } });
91
92
  Object.defineProperty(exports, "createModuleLoader", { enumerable: true, get: function () { return loaders_1.createModuleLoader; } });
92
93
  Object.defineProperty(exports, "databaseSettingsLoader", { enumerable: true, get: function () { return loaders_1.databaseSettingsLoader; } });
94
+ Object.defineProperty(exports, "eventsLoader", { enumerable: true, get: function () { return loaders_1.eventsLoader; } });
93
95
  Object.defineProperty(exports, "identityProvidersLoader", { enumerable: true, get: function () { return loaders_1.identityProvidersLoader; } });
94
96
  Object.defineProperty(exports, "inferenceLogLoader", { enumerable: true, get: function () { return loaders_1.inferenceLogLoader; } });
95
97
  Object.defineProperty(exports, "llmLoader", { enumerable: true, get: function () { return loaders_1.llmLoader; } });
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Events Module Loader
3
+ *
4
+ * Resolves the tenant's app-scoped events module from
5
+ * metaschema_modules_public.events_module: the private schema and the names of
6
+ * its `record_event` and `record_error` functions, so the server can record
7
+ * events without hard-coding the generated schema or function names.
8
+ */
9
+ import type { EventsConfig } from '../types';
10
+ import type { ModuleLoader } from './types';
11
+ export declare const eventsLoader: ModuleLoader<EventsConfig>;
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ /**
3
+ * Events Module Loader
4
+ *
5
+ * Resolves the tenant's app-scoped events module from
6
+ * metaschema_modules_public.events_module: the private schema and the names of
7
+ * its `record_event` and `record_error` functions, so the server can record
8
+ * events without hard-coding the generated schema or function names.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.eventsLoader = void 0;
12
+ const create_loader_1 = require("./create-loader");
13
+ // ─── SQL ────────────────────────────────────────────────────────────────────
14
+ const EVENTS_MODULE_SQL = `
15
+ SELECT
16
+ s.schema_name AS private_schema_name,
17
+ em.record_event,
18
+ em.record_error
19
+ FROM metaschema_modules_public.events_module em
20
+ JOIN metaschema_public.schema s ON s.id = em.private_schema_id
21
+ WHERE em.database_id = $1
22
+ AND em.scope = 'app'
23
+ LIMIT 1
24
+ `;
25
+ // ─── Loader ─────────────────────────────────────────────────────────────────
26
+ exports.eventsLoader = (0, create_loader_1.createModuleLoader)({
27
+ name: 'events',
28
+ ttlMs: 60_000,
29
+ async resolve(ctx) {
30
+ const { tenantPool, databaseId } = ctx;
31
+ const result = await tenantPool.query(EVENTS_MODULE_SQL, [databaseId]);
32
+ const row = result.rows[0];
33
+ if (!row?.private_schema_name || !row.record_event)
34
+ return undefined;
35
+ return {
36
+ privateSchemaName: row.private_schema_name,
37
+ recordEvent: row.record_event,
38
+ recordError: row.record_error ?? null
39
+ };
40
+ }
41
+ });
@@ -14,6 +14,7 @@
14
14
  * - webauthnSettings(routing-plane webauthn_settings)
15
15
  * - authSettings (metaschema_modules_public.sessions_module → tenant DB)
16
16
  * - authSurface (identity/connected-accounts/emails modules → tenant DB)
17
+ * - events (metaschema_modules_public.events_module, app scope → tenant DB)
17
18
  *
18
19
  * Opt-in (not in the default registry, register it explicitly):
19
20
  * - identityProviders (three round trips, decrypts client secrets)
@@ -43,6 +44,7 @@ export { billingLoader } from './billing';
43
44
  export { computeLoader } from './compute';
44
45
  export { corsLoader } from './cors';
45
46
  export { databaseSettingsLoader } from './database-settings';
47
+ export { eventsLoader } from './events';
46
48
  export { identityProvidersLoader, requireIdentityProvider } from './identity-providers';
47
49
  export { inferenceLogLoader } from './inference-log';
48
50
  export { llmLoader } from './llm';
package/loaders/index.js CHANGED
@@ -15,6 +15,7 @@
15
15
  * - webauthnSettings(routing-plane webauthn_settings)
16
16
  * - authSettings (metaschema_modules_public.sessions_module → tenant DB)
17
17
  * - authSurface (identity/connected-accounts/emails modules → tenant DB)
18
+ * - events (metaschema_modules_public.events_module, app scope → tenant DB)
18
19
  *
19
20
  * Opt-in (not in the default registry, register it explicitly):
20
21
  * - identityProviders (three round trips, decrypts client secrets)
@@ -32,7 +33,7 @@
32
33
  * registry.register(myLoader);
33
34
  */
34
35
  Object.defineProperty(exports, "__esModule", { value: true });
35
- exports.webauthnLoader = exports.rlsLoader = exports.requestProtectionLoader = exports.pubkeyLoader = exports.llmLoader = exports.inferenceLogLoader = exports.requireIdentityProvider = exports.identityProvidersLoader = exports.databaseSettingsLoader = exports.corsLoader = exports.computeLoader = exports.billingLoader = exports.authSurfaceLoader = exports.authSettingsLoader = exports.agentChatLoader = exports.createLoaderRegistry = exports.createModuleLoader = exports.requireDatabaseId = void 0;
36
+ exports.webauthnLoader = exports.rlsLoader = exports.requestProtectionLoader = exports.pubkeyLoader = exports.llmLoader = exports.inferenceLogLoader = exports.requireIdentityProvider = exports.identityProvidersLoader = exports.eventsLoader = exports.databaseSettingsLoader = exports.corsLoader = exports.computeLoader = exports.billingLoader = exports.authSurfaceLoader = exports.authSettingsLoader = exports.agentChatLoader = exports.createLoaderRegistry = exports.createModuleLoader = exports.requireDatabaseId = void 0;
36
37
  exports.createDefaultRegistry = createDefaultRegistry;
37
38
  var types_1 = require("./types");
38
39
  Object.defineProperty(exports, "requireDatabaseId", { enumerable: true, get: function () { return types_1.requireDatabaseId; } });
@@ -55,6 +56,8 @@ var cors_1 = require("./cors");
55
56
  Object.defineProperty(exports, "corsLoader", { enumerable: true, get: function () { return cors_1.corsLoader; } });
56
57
  var database_settings_1 = require("./database-settings");
57
58
  Object.defineProperty(exports, "databaseSettingsLoader", { enumerable: true, get: function () { return database_settings_1.databaseSettingsLoader; } });
59
+ var events_1 = require("./events");
60
+ Object.defineProperty(exports, "eventsLoader", { enumerable: true, get: function () { return events_1.eventsLoader; } });
58
61
  var identity_providers_1 = require("./identity-providers");
59
62
  Object.defineProperty(exports, "identityProvidersLoader", { enumerable: true, get: function () { return identity_providers_1.identityProvidersLoader; } });
60
63
  Object.defineProperty(exports, "requireIdentityProvider", { enumerable: true, get: function () { return identity_providers_1.requireIdentityProvider; } });
@@ -80,6 +83,7 @@ const billing_2 = require("./billing");
80
83
  const compute_2 = require("./compute");
81
84
  const cors_2 = require("./cors");
82
85
  const database_settings_2 = require("./database-settings");
86
+ const events_2 = require("./events");
83
87
  const inference_log_2 = require("./inference-log");
84
88
  const llm_2 = require("./llm");
85
89
  const pubkey_2 = require("./pubkey");
@@ -101,6 +105,7 @@ function createDefaultRegistry() {
101
105
  registry.register(agent_chat_2.agentChatLoader);
102
106
  registry.register(llm_2.llmLoader);
103
107
  registry.register(compute_2.computeLoader);
108
+ registry.register(events_2.eventsLoader);
104
109
  registry.register(request_protection_2.requestProtectionLoader);
105
110
  return registry;
106
111
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@constructive-io/express-context",
3
- "version": "0.28.0",
3
+ "version": "0.30.0",
4
4
  "description": "Extractable Express middleware for Constructive tenant context — domain resolution, JWT auth, pgSettings, and withPgClient",
5
5
  "author": "Constructive <developers@constructive.io>",
6
6
  "homepage": "https://github.com/constructive-io/constructive",
@@ -59,5 +59,5 @@
59
59
  "jwt",
60
60
  "pgSettings"
61
61
  ],
62
- "gitHead": "01e073830677c0587bab564b7d575a06b5156f0c"
62
+ "gitHead": "10d3a11478d17a20c80da5a827f8e8da4facfc80"
63
63
  }
package/types.d.ts CHANGED
@@ -199,6 +199,16 @@ export interface ComputeModuleConfig {
199
199
  export interface ComputeConfig {
200
200
  modules: ComputeModuleConfig[];
201
201
  }
202
+ /**
203
+ * The tenant's app-scoped events module: where `record_event` and
204
+ * `record_error` live. `recordError` is null on a tenant whose events module
205
+ * predates the function; callers must report that rather than skip silently.
206
+ */
207
+ export interface EventsConfig {
208
+ privateSchemaName: string;
209
+ recordEvent: string;
210
+ recordError: string | null;
211
+ }
202
212
  export interface LlmConfig {
203
213
  embeddingProvider: string;
204
214
  embeddingModel: string;
@@ -233,6 +243,7 @@ export interface BuiltinModuleMap {
233
243
  agentChat: AgentChatConfig;
234
244
  llm: LlmConfig;
235
245
  compute: ComputeConfig;
246
+ events: EventsConfig;
236
247
  requestProtection: RequestProtection;
237
248
  }
238
249
  /**