@pattern-stack/codegen 0.6.4 → 0.6.5

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 (63) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +2 -0
  3. package/dist/runtime/subsystems/auth/auth-oauth-state.schema.d.ts +81 -0
  4. package/dist/runtime/subsystems/auth/auth-oauth-state.schema.js +12 -0
  5. package/dist/runtime/subsystems/auth/auth-oauth-state.schema.js.map +1 -0
  6. package/dist/runtime/subsystems/auth/auth.module.d.ts +39 -24
  7. package/dist/runtime/subsystems/auth/auth.module.js +246 -13
  8. package/dist/runtime/subsystems/auth/auth.module.js.map +1 -1
  9. package/dist/runtime/subsystems/auth/auth.tokens.d.ts +15 -2
  10. package/dist/runtime/subsystems/auth/auth.tokens.js +9 -1
  11. package/dist/runtime/subsystems/auth/auth.tokens.js.map +1 -1
  12. package/dist/runtime/subsystems/auth/backends/state-store.drizzle-backend.d.ts +23 -0
  13. package/dist/runtime/subsystems/auth/backends/state-store.drizzle-backend.js +68 -0
  14. package/dist/runtime/subsystems/auth/backends/state-store.drizzle-backend.js.map +1 -0
  15. package/dist/runtime/subsystems/auth/backends/state-store.memory-backend.d.ts +21 -0
  16. package/dist/runtime/subsystems/auth/backends/state-store.memory-backend.js +51 -0
  17. package/dist/runtime/subsystems/auth/backends/state-store.memory-backend.js.map +1 -0
  18. package/dist/runtime/subsystems/auth/controllers/auth.controller.d.ts +31 -0
  19. package/dist/runtime/subsystems/auth/controllers/auth.controller.js +137 -0
  20. package/dist/runtime/subsystems/auth/controllers/auth.controller.js.map +1 -0
  21. package/dist/runtime/subsystems/auth/index.d.ts +13 -4
  22. package/dist/runtime/subsystems/auth/index.js +253 -14
  23. package/dist/runtime/subsystems/auth/index.js.map +1 -1
  24. package/dist/runtime/subsystems/auth/protocols/integration-store.d.ts +36 -1
  25. package/dist/runtime/subsystems/auth/protocols/oauth-state-store.d.ts +33 -7
  26. package/dist/runtime/subsystems/auth/protocols/oauth-state-store.js +12 -0
  27. package/dist/runtime/subsystems/auth/protocols/oauth-state-store.js.map +1 -1
  28. package/dist/runtime/subsystems/auth/protocols/provider-strategy.d.ts +47 -0
  29. package/dist/runtime/subsystems/auth/protocols/provider-strategy.js +1 -0
  30. package/dist/runtime/subsystems/auth/protocols/provider-strategy.js.map +1 -0
  31. package/dist/runtime/subsystems/auth/protocols/user-context.d.ts +24 -0
  32. package/dist/runtime/subsystems/auth/protocols/user-context.js +1 -0
  33. package/dist/runtime/subsystems/auth/protocols/user-context.js.map +1 -0
  34. package/dist/runtime/subsystems/index.d.ts +9 -4
  35. package/dist/runtime/subsystems/index.js +247 -14
  36. package/dist/runtime/subsystems/index.js.map +1 -1
  37. package/dist/src/cli/index.js +574 -142
  38. package/dist/src/cli/index.js.map +1 -1
  39. package/package.json +1 -1
  40. package/runtime/subsystems/auth/auth-oauth-state.schema.ts +30 -0
  41. package/runtime/subsystems/auth/auth.module.ts +89 -32
  42. package/runtime/subsystems/auth/auth.tokens.ts +14 -1
  43. package/runtime/subsystems/auth/backends/state-store.drizzle-backend.ts +83 -0
  44. package/runtime/subsystems/auth/backends/state-store.memory-backend.ts +76 -0
  45. package/runtime/subsystems/auth/controllers/auth.controller.ts +155 -0
  46. package/runtime/subsystems/auth/index.ts +43 -4
  47. package/runtime/subsystems/auth/protocols/integration-store.ts +37 -0
  48. package/runtime/subsystems/auth/protocols/oauth-state-store.ts +38 -6
  49. package/runtime/subsystems/auth/protocols/provider-strategy.ts +41 -0
  50. package/runtime/subsystems/auth/protocols/user-context.ts +22 -0
  51. package/runtime/subsystems/index.ts +17 -2
  52. package/templates/subsystem/auth/app-module-hook.ejs.t +21 -0
  53. package/templates/subsystem/auth/auth-oauth-state.schema.ejs.t +35 -0
  54. package/templates/subsystem/auth/env-config.ejs.t +20 -0
  55. package/templates/subsystem/auth/prompt.js +46 -0
  56. package/templates/subsystem/auth-config/codegen-config-auth-block.ejs.t +20 -0
  57. package/templates/subsystem/auth-config/prompt.js +20 -0
  58. package/templates/subsystem/auth-integrations/app-module-hook.ejs.t +16 -0
  59. package/templates/subsystem/auth-integrations/prompt.js +23 -0
  60. package/dist/runtime/subsystems/auth/backends/oauth-state-store/in-memory.d.ts +0 -24
  61. package/dist/runtime/subsystems/auth/backends/oauth-state-store/in-memory.js +0 -24
  62. package/dist/runtime/subsystems/auth/backends/oauth-state-store/in-memory.js.map +0 -1
  63. package/runtime/subsystems/auth/backends/oauth-state-store/in-memory.ts +0 -42
@@ -0,0 +1,47 @@
1
+ import { OAuth2RefreshStrategy } from '../runtime/oauth2-refresh.strategy.js';
2
+ import './auth-strategy.js';
3
+ import './integration-store.js';
4
+
5
+ /**
6
+ * Auth subsystem — `ProviderStrategy` contract.
7
+ *
8
+ * Extension of `OAuth2RefreshStrategy` (which already covers the refresh
9
+ * path) that adds the two methods needed by the connect/callback dance:
10
+ *
11
+ * - `buildAuthorizeUrl({ state, redirectUri })` → consent-page URL.
12
+ * - `exchangeCodeForTokens({ code, redirectUri })` → tokens after consent.
13
+ *
14
+ * Concrete per-provider strategies (HubSpot, SFDC, Google, Gong, Fathom, …)
15
+ * stay consumer-side per ADR-031 ("every app has different combinations").
16
+ * They typically subclass `OAuth2RefreshStrategy` for the refresh path and
17
+ * implement these two methods structurally — that satisfies
18
+ * `ProviderStrategy` because TS lets interfaces extend classes by type.
19
+ *
20
+ * AuthController never imports a concrete strategy — it injects the
21
+ * `STRATEGY_REGISTRY` (a `ReadonlyMap<provider-slug, ProviderStrategy>`)
22
+ * and dispatches by slug.
23
+ */
24
+
25
+ interface ExchangedTokens {
26
+ accessToken: string;
27
+ refreshToken?: string;
28
+ expiresAt?: Date;
29
+ scope?: string[];
30
+ externalAccountId?: string;
31
+ /** Provider-specific bag (SFDC `instance_url`, Google `sub`, …). */
32
+ providerMetadata?: Record<string, unknown>;
33
+ }
34
+ interface ProviderStrategy extends OAuth2RefreshStrategy {
35
+ buildAuthorizeUrl(args: {
36
+ state: string;
37
+ redirectUri: string;
38
+ }): string;
39
+ exchangeCodeForTokens(args: {
40
+ code: string;
41
+ redirectUri: string;
42
+ }): Promise<ExchangedTokens>;
43
+ }
44
+ /** The DI value type behind the `STRATEGY_REGISTRY` token. */
45
+ type ProviderStrategyRegistry = ReadonlyMap<string, ProviderStrategy>;
46
+
47
+ export type { ExchangedTokens, ProviderStrategy, ProviderStrategyRegistry };
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=provider-strategy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Auth subsystem — `IUserContext` port.
3
+ *
4
+ * Resolves "who is the current user" from a request. The shape is
5
+ * universal; the implementation is always app-specific:
6
+ *
7
+ * - WorkOS session: `req.session.user.id`
8
+ * - JWT bearer: `decode(req.headers.authorization).sub`
9
+ * - Test fixture: hardcoded UUID
10
+ *
11
+ * The auth subsystem cannot ship a default — every app does auth differently —
12
+ * but the port is universal, so the contract ships here. Consumers bind a
13
+ * concrete implementation under the `AUTH_USER_CONTEXT` token in their app
14
+ * module.
15
+ *
16
+ * `req` is typed as `unknown` deliberately: this protocol must not pull a
17
+ * dependency on `express` / `fastify` / NestJS request types. The concrete
18
+ * adapter narrows it (e.g. via a `Request` import).
19
+ */
20
+ interface IUserContext {
21
+ getCurrentUserId(req: unknown): Promise<string>;
22
+ }
23
+
24
+ export type { IUserContext };
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=user-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -21,15 +21,20 @@ export { ObservabilityModule, ObservabilityModuleOptions } from './observability
21
21
  export { ObservabilityError } from './observability/observability-errors.js';
22
22
  export { AuthCredentials, AuthResolveOptions, IAuthStrategy } from './auth/protocols/auth-strategy.js';
23
23
  export { IEncryptionKey } from './auth/protocols/encryption-key.js';
24
- export { IOAuthStateStore, OAuthStateEntry } from './auth/protocols/oauth-state-store.js';
25
- export { DecryptedIntegration, IIntegrationReader, IIntegrationTokenWriter, IntegrationTokenUpdate } from './auth/protocols/integration-store.js';
26
- export { AUTH_INTEGRATION_READER, AUTH_INTEGRATION_TOKEN_WRITER, ENCRYPTION_KEY, OAUTH_STATE_STORE } from './auth/auth.tokens.js';
24
+ export { IOAuthStateStore, OAuthStateError, OAuthStateRecord } from './auth/protocols/oauth-state-store.js';
25
+ export { DecryptedIntegration, IIntegrationGrantSink, IIntegrationReader, IIntegrationTokenWriter, IntegrationGrantInput, IntegrationTokenUpdate } from './auth/protocols/integration-store.js';
26
+ export { IUserContext } from './auth/protocols/user-context.js';
27
+ export { ExchangedTokens, ProviderStrategy, ProviderStrategyRegistry } from './auth/protocols/provider-strategy.js';
28
+ export { AUTH_INTEGRATION_GRANT_SINK, AUTH_INTEGRATION_READER, AUTH_INTEGRATION_TOKEN_WRITER, AUTH_OPTIONS, AUTH_USER_CONTEXT, ENCRYPTION_KEY, OAUTH_STATE_STORE, STRATEGY_REGISTRY } from './auth/auth.tokens.js';
27
29
  export { OAuth2RefreshStrategy, ParsedRefreshResponse } from './auth/runtime/oauth2-refresh.strategy.js';
28
30
  export { withAuthRetry } from './auth/runtime/with-auth-retry.js';
29
31
  export { IntegrationBrokenError } from './auth/runtime/integration-broken.error.js';
30
32
  export { SessionExpiredError, isSessionExpiredError } from './auth/runtime/session-expired.error.js';
33
+ export { AuthOAuthState, authOAuthState } from './auth/auth-oauth-state.schema.js';
31
34
  export { EnvEncryptionKey } from './auth/backends/encryption-key/env.js';
32
- export { InMemoryOAuthStateStore } from './auth/backends/oauth-state-store/in-memory.js';
35
+ export { MemoryOAuthStateStore } from './auth/backends/state-store.memory-backend.js';
36
+ export { DrizzleOAuthStateStore } from './auth/backends/state-store.drizzle-backend.js';
37
+ export { AuthController } from './auth/controllers/auth.controller.js';
33
38
  export { AuthModule } from './auth/auth.module.js';
34
39
  export { CursorSnapshot } from './sync/sync-cursor-store.protocol.js';
35
40
  export { StatusHistogram } from './bridge/bridge.protocol.js';
@@ -3971,11 +3971,25 @@ var ObservabilityError = class extends Error {
3971
3971
  cause;
3972
3972
  };
3973
3973
 
3974
+ // runtime/subsystems/auth/protocols/oauth-state-store.ts
3975
+ var OAuthStateError = class extends Error {
3976
+ constructor(message, reason) {
3977
+ super(message);
3978
+ this.reason = reason;
3979
+ this.name = "OAuthStateError";
3980
+ }
3981
+ reason;
3982
+ };
3983
+
3974
3984
  // runtime/subsystems/auth/auth.tokens.ts
3975
3985
  var ENCRYPTION_KEY = /* @__PURE__ */ Symbol("ENCRYPTION_KEY");
3976
3986
  var OAUTH_STATE_STORE = /* @__PURE__ */ Symbol("OAUTH_STATE_STORE");
3977
3987
  var AUTH_INTEGRATION_READER = /* @__PURE__ */ Symbol("AUTH_INTEGRATION_READER");
3978
3988
  var AUTH_INTEGRATION_TOKEN_WRITER = /* @__PURE__ */ Symbol("AUTH_INTEGRATION_TOKEN_WRITER");
3989
+ var AUTH_INTEGRATION_GRANT_SINK = /* @__PURE__ */ Symbol("AUTH_INTEGRATION_GRANT_SINK");
3990
+ var AUTH_USER_CONTEXT = /* @__PURE__ */ Symbol("AUTH_USER_CONTEXT");
3991
+ var STRATEGY_REGISTRY = /* @__PURE__ */ Symbol("STRATEGY_REGISTRY");
3992
+ var AUTH_OPTIONS = /* @__PURE__ */ Symbol("AUTH_OPTIONS");
3979
3993
 
3980
3994
  // runtime/subsystems/auth/runtime/integration-broken.error.ts
3981
3995
  var IntegrationBrokenError = class extends Error {
@@ -4112,6 +4126,15 @@ async function withAuthRetry(authStrategy, integrationId, op, options = {}) {
4112
4126
  }
4113
4127
  }
4114
4128
 
4129
+ // runtime/subsystems/auth/auth-oauth-state.schema.ts
4130
+ import { pgTable as pgTable4, text as text4, timestamp as timestamp4 } from "drizzle-orm/pg-core";
4131
+ var authOAuthState = pgTable4("auth_oauth_state", {
4132
+ state: text4("state").primaryKey(),
4133
+ userId: text4("user_id").notNull(),
4134
+ redirect: text4("redirect"),
4135
+ expiresAt: timestamp4("expires_at", { withTimezone: true }).notNull()
4136
+ });
4137
+
4115
4138
  // runtime/subsystems/auth/backends/encryption-key/env.ts
4116
4139
  import { createCipheriv, createDecipheriv, randomBytes } from "crypto";
4117
4140
  var ALGO = "aes-256-gcm";
@@ -4162,26 +4185,198 @@ var EnvEncryptionKey = class {
4162
4185
  }
4163
4186
  };
4164
4187
 
4165
- // runtime/subsystems/auth/backends/oauth-state-store/in-memory.ts
4166
- var InMemoryOAuthStateStore = class {
4188
+ // runtime/subsystems/auth/backends/state-store.memory-backend.ts
4189
+ import { randomBytes as randomBytes2 } from "crypto";
4190
+ var MemoryOAuthStateStore = class {
4167
4191
  store = /* @__PURE__ */ new Map();
4168
4192
  ttlMs;
4169
4193
  now;
4194
+ generateToken;
4170
4195
  constructor(opts = {}) {
4171
4196
  this.ttlMs = opts.ttlMs ?? 10 * 60 * 1e3;
4172
4197
  this.now = opts.now ?? (() => Date.now());
4198
+ this.generateToken = opts.generateToken ?? (() => randomBytes2(32).toString("base64url"));
4173
4199
  }
4174
- async put(state, entry) {
4175
- this.store.set(state, { entry, expiresAt: this.now() + this.ttlMs });
4200
+ async generate(record) {
4201
+ const state = this.generateToken();
4202
+ this.store.set(state, {
4203
+ record: { ...record },
4204
+ expiresAt: this.now() + this.ttlMs
4205
+ });
4206
+ return state;
4176
4207
  }
4177
4208
  async consume(state) {
4178
4209
  const slot = this.store.get(state);
4179
- if (!slot) return null;
4210
+ if (!slot) {
4211
+ throw new OAuthStateError(
4212
+ `OAuth state token unknown or already consumed`,
4213
+ "missing"
4214
+ );
4215
+ }
4180
4216
  this.store.delete(state);
4181
- if (slot.expiresAt <= this.now()) return null;
4182
- return slot.entry;
4217
+ if (slot.expiresAt <= this.now()) {
4218
+ throw new OAuthStateError(`OAuth state token expired`, "expired");
4219
+ }
4220
+ return slot.record;
4221
+ }
4222
+ };
4223
+
4224
+ // runtime/subsystems/auth/backends/state-store.drizzle-backend.ts
4225
+ import { randomBytes as randomBytes3 } from "crypto";
4226
+ import { eq as eq7 } from "drizzle-orm";
4227
+ var DrizzleOAuthStateStore = class {
4228
+ constructor(db, opts = {}) {
4229
+ this.db = db;
4230
+ this.ttlMs = opts.ttlMs ?? 10 * 60 * 1e3;
4231
+ this.now = opts.now ?? (() => Date.now());
4232
+ this.generateToken = opts.generateToken ?? (() => randomBytes3(32).toString("base64url"));
4233
+ }
4234
+ db;
4235
+ ttlMs;
4236
+ now;
4237
+ generateToken;
4238
+ async generate(record) {
4239
+ const state = this.generateToken();
4240
+ const expiresAt = new Date(this.now() + this.ttlMs);
4241
+ await this.db.insert(authOAuthState).values({
4242
+ state,
4243
+ userId: record.userId,
4244
+ redirect: record.redirect ?? null,
4245
+ expiresAt
4246
+ });
4247
+ return state;
4248
+ }
4249
+ async consume(state) {
4250
+ const rows = await this.db.delete(authOAuthState).where(eq7(authOAuthState.state, state)).returning();
4251
+ const row = rows[0];
4252
+ if (!row) {
4253
+ throw new OAuthStateError(
4254
+ `OAuth state token unknown or already consumed`,
4255
+ "missing"
4256
+ );
4257
+ }
4258
+ if (row.expiresAt.getTime() <= this.now()) {
4259
+ throw new OAuthStateError(`OAuth state token expired`, "expired");
4260
+ }
4261
+ return {
4262
+ userId: row.userId,
4263
+ redirect: row.redirect ?? void 0
4264
+ };
4265
+ }
4266
+ };
4267
+
4268
+ // runtime/subsystems/auth/controllers/auth.controller.ts
4269
+ import {
4270
+ Controller,
4271
+ Get,
4272
+ Inject as Inject16,
4273
+ Param,
4274
+ Query,
4275
+ Req,
4276
+ Res,
4277
+ HttpException,
4278
+ HttpStatus
4279
+ } from "@nestjs/common";
4280
+ var AuthController = class {
4281
+ constructor(registry, userContext, stateStore, grantSink, options) {
4282
+ this.registry = registry;
4283
+ this.userContext = userContext;
4284
+ this.stateStore = stateStore;
4285
+ this.grantSink = grantSink;
4286
+ this.options = options;
4287
+ }
4288
+ registry;
4289
+ userContext;
4290
+ stateStore;
4291
+ grantSink;
4292
+ options;
4293
+ async connect(slug, redirect, req, res) {
4294
+ const strategy = this.requireStrategy(slug);
4295
+ const userId = await this.userContext.getCurrentUserId(req);
4296
+ const state = await this.stateStore.generate({ userId, redirect });
4297
+ const url = strategy.buildAuthorizeUrl({
4298
+ state,
4299
+ redirectUri: this.redirectUriFor(slug)
4300
+ });
4301
+ return res.redirect(HttpStatus.FOUND, url);
4302
+ }
4303
+ async callback(slug, code, state, res) {
4304
+ const strategy = this.requireStrategy(slug);
4305
+ if (!code) {
4306
+ throw new HttpException(
4307
+ `Missing 'code' query param`,
4308
+ HttpStatus.BAD_REQUEST
4309
+ );
4310
+ }
4311
+ if (!state) {
4312
+ throw new HttpException(
4313
+ `Missing 'state' query param`,
4314
+ HttpStatus.BAD_REQUEST
4315
+ );
4316
+ }
4317
+ const { userId, redirect } = await this.stateStore.consume(state);
4318
+ const tokens = await strategy.exchangeCodeForTokens({
4319
+ code,
4320
+ redirectUri: this.redirectUriFor(slug)
4321
+ });
4322
+ await this.grantSink.createOrUpdateFromOAuthGrant({
4323
+ userId,
4324
+ provider: slug,
4325
+ accessToken: tokens.accessToken,
4326
+ refreshToken: tokens.refreshToken,
4327
+ expiresAt: tokens.expiresAt,
4328
+ scope: tokens.scope,
4329
+ externalAccountId: tokens.externalAccountId,
4330
+ providerMetadata: tokens.providerMetadata
4331
+ });
4332
+ return res.redirect(
4333
+ HttpStatus.FOUND,
4334
+ redirect ?? `/settings/integrations?connected=${encodeURIComponent(slug)}`
4335
+ );
4336
+ }
4337
+ requireStrategy(slug) {
4338
+ const strategy = this.registry.get(slug);
4339
+ if (!strategy) {
4340
+ throw new HttpException(
4341
+ `Unknown provider '${slug}'`,
4342
+ HttpStatus.NOT_FOUND
4343
+ );
4344
+ }
4345
+ return strategy;
4346
+ }
4347
+ redirectUriFor(slug) {
4348
+ const base = this.options.redirectUriBase;
4349
+ if (!base) {
4350
+ throw new Error(
4351
+ `AuthModule.forRoot: redirectUriBase is required when AuthController is enabled`
4352
+ );
4353
+ }
4354
+ const trimmed = base.replace(/\/+$/, "");
4355
+ return `${trimmed}/auth/${encodeURIComponent(slug)}/callback`;
4183
4356
  }
4184
4357
  };
4358
+ __decorateClass([
4359
+ Get(":provider/connect"),
4360
+ __decorateParam(0, Param("provider")),
4361
+ __decorateParam(1, Query("redirect")),
4362
+ __decorateParam(2, Req()),
4363
+ __decorateParam(3, Res())
4364
+ ], AuthController.prototype, "connect", 1);
4365
+ __decorateClass([
4366
+ Get(":provider/callback"),
4367
+ __decorateParam(0, Param("provider")),
4368
+ __decorateParam(1, Query("code")),
4369
+ __decorateParam(2, Query("state")),
4370
+ __decorateParam(3, Res())
4371
+ ], AuthController.prototype, "callback", 1);
4372
+ AuthController = __decorateClass([
4373
+ Controller("auth"),
4374
+ __decorateParam(0, Inject16(STRATEGY_REGISTRY)),
4375
+ __decorateParam(1, Inject16(AUTH_USER_CONTEXT)),
4376
+ __decorateParam(2, Inject16(OAUTH_STATE_STORE)),
4377
+ __decorateParam(3, Inject16(AUTH_INTEGRATION_GRANT_SINK)),
4378
+ __decorateParam(4, Inject16(AUTH_OPTIONS))
4379
+ ], AuthController);
4185
4380
 
4186
4381
  // runtime/subsystems/auth/auth.module.ts
4187
4382
  import { Module as Module7 } from "@nestjs/common";
@@ -4192,24 +4387,54 @@ function resolveEncryptionKeyProvider(choice) {
4192
4387
  return { provide: ENCRYPTION_KEY, ...choice };
4193
4388
  }
4194
4389
  function resolveOAuthStateStoreProvider(choice) {
4195
- if (choice === "in-memory") {
4196
- return { provide: OAUTH_STATE_STORE, useClass: InMemoryOAuthStateStore };
4390
+ if (choice === "memory") {
4391
+ return { provide: OAUTH_STATE_STORE, useClass: MemoryOAuthStateStore };
4392
+ }
4393
+ if (choice === "drizzle") {
4394
+ return {
4395
+ provide: OAUTH_STATE_STORE,
4396
+ useFactory: (db) => {
4397
+ if (!db) {
4398
+ throw new Error(
4399
+ "AuthModule.forRoot: oauthStateStore: 'drizzle' selected but DRIZZLE provider is not available. Ensure DatabaseModule (or another provider exposing DRIZZLE) is imported before AuthModule.forRoot."
4400
+ );
4401
+ }
4402
+ return new DrizzleOAuthStateStore(db);
4403
+ },
4404
+ inject: [{ token: DRIZZLE, optional: true }]
4405
+ };
4197
4406
  }
4198
4407
  return { provide: OAUTH_STATE_STORE, ...choice };
4199
4408
  }
4200
4409
  var AuthModule = class {
4201
4410
  static forRoot(options = {}) {
4411
+ const resolved = {
4412
+ encryptionKey: options.encryptionKey ?? "env",
4413
+ oauthStateStore: options.oauthStateStore ?? "memory",
4414
+ enableController: options.enableController ?? false,
4415
+ redirectUriBase: options.redirectUriBase
4416
+ };
4417
+ if (resolved.enableController && !resolved.redirectUriBase) {
4418
+ throw new Error(
4419
+ "AuthModule.forRoot: redirectUriBase is required when enableController: true"
4420
+ );
4421
+ }
4202
4422
  const encryptionKeyProvider = resolveEncryptionKeyProvider(
4203
- options.encryptionKey ?? "env"
4423
+ resolved.encryptionKey
4204
4424
  );
4205
4425
  const oauthStateStoreProvider = resolveOAuthStateStoreProvider(
4206
- options.oauthStateStore ?? "in-memory"
4426
+ resolved.oauthStateStore
4207
4427
  );
4428
+ const optionsProvider = {
4429
+ provide: AUTH_OPTIONS,
4430
+ useValue: resolved
4431
+ };
4208
4432
  return {
4209
4433
  module: AuthModule,
4210
4434
  global: true,
4211
- providers: [encryptionKeyProvider, oauthStateStoreProvider],
4212
- exports: [ENCRYPTION_KEY, OAUTH_STATE_STORE]
4435
+ providers: [encryptionKeyProvider, oauthStateStoreProvider, optionsProvider],
4436
+ controllers: resolved.enableController ? [AuthController] : [],
4437
+ exports: [ENCRYPTION_KEY, OAUTH_STATE_STORE, AUTH_OPTIONS]
4213
4438
  };
4214
4439
  }
4215
4440
  };
@@ -4217,32 +4442,40 @@ AuthModule = __decorateClass([
4217
4442
  Module7({})
4218
4443
  ], AuthModule);
4219
4444
  export {
4445
+ AUTH_INTEGRATION_GRANT_SINK,
4220
4446
  AUTH_INTEGRATION_READER,
4221
4447
  AUTH_INTEGRATION_TOKEN_WRITER,
4448
+ AUTH_OPTIONS,
4449
+ AUTH_USER_CONTEXT,
4450
+ AuthController,
4222
4451
  AuthModule,
4223
4452
  CACHE,
4224
4453
  CacheModule,
4225
4454
  DrizzleCacheService,
4226
4455
  DrizzleEventBus,
4456
+ DrizzleOAuthStateStore,
4227
4457
  ENCRYPTION_KEY,
4228
4458
  EVENT_BUS,
4229
4459
  EnvEncryptionKey,
4230
4460
  EventsModule,
4231
- InMemoryOAuthStateStore,
4232
4461
  IntegrationBrokenError,
4233
4462
  LocalStorageBackend,
4234
4463
  MemoryCacheService,
4235
4464
  MemoryEventBus,
4465
+ MemoryOAuthStateStore,
4236
4466
  MemoryStorageBackend,
4237
4467
  OAUTH_STATE_STORE,
4238
4468
  OAuth2RefreshStrategy,
4469
+ OAuthStateError,
4239
4470
  OBSERVABILITY,
4240
4471
  OBSERVABILITY_MODULE_OPTIONS,
4241
4472
  ObservabilityError,
4242
4473
  ObservabilityModule,
4243
4474
  STORAGE,
4475
+ STRATEGY_REGISTRY,
4244
4476
  SessionExpiredError,
4245
4477
  StorageModule,
4478
+ authOAuthState,
4246
4479
  collisionModeEnum,
4247
4480
  isSessionExpiredError,
4248
4481
  jobRunStatusEnum,