@pattern-stack/codegen 0.6.5 → 0.6.6

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 (56) hide show
  1. package/CHANGELOG.md +11 -1
  2. package/dist/runtime/subsystems/auth/auth.module.js +1 -1
  3. package/dist/runtime/subsystems/auth/auth.module.js.map +1 -1
  4. package/dist/runtime/subsystems/auth/auth.tokens.d.ts +1 -1
  5. package/dist/runtime/subsystems/auth/auth.tokens.js.map +1 -1
  6. package/dist/runtime/subsystems/auth/backends/encryption-key/env.d.ts +1 -1
  7. package/dist/runtime/subsystems/auth/backends/encryption-key/env.js +1 -1
  8. package/dist/runtime/subsystems/auth/backends/encryption-key/env.js.map +1 -1
  9. package/dist/runtime/subsystems/auth/controllers/auth.controller.js.map +1 -1
  10. package/dist/runtime/subsystems/auth/index.d.ts +1 -1
  11. package/dist/runtime/subsystems/auth/index.js +1 -1
  12. package/dist/runtime/subsystems/auth/index.js.map +1 -1
  13. package/dist/runtime/subsystems/auth/protocols/auth-strategy.d.ts +1 -1
  14. package/dist/runtime/subsystems/auth/protocols/integration-store.d.ts +2 -2
  15. package/dist/runtime/subsystems/auth/protocols/provider-strategy.d.ts +13 -6
  16. package/dist/runtime/subsystems/auth/runtime/oauth2-refresh.strategy.d.ts +2 -2
  17. package/dist/runtime/subsystems/auth/runtime/oauth2-refresh.strategy.js.map +1 -1
  18. package/dist/runtime/subsystems/auth/runtime/session-expired.error.d.ts +2 -2
  19. package/dist/runtime/subsystems/auth/runtime/session-expired.error.js.map +1 -1
  20. package/dist/runtime/subsystems/auth/runtime/with-auth-retry.d.ts +1 -1
  21. package/dist/runtime/subsystems/auth/runtime/with-auth-retry.js.map +1 -1
  22. package/dist/runtime/subsystems/index.d.ts +1 -1
  23. package/dist/runtime/subsystems/index.js +1 -1
  24. package/dist/runtime/subsystems/index.js.map +1 -1
  25. package/dist/runtime/subsystems/sync/deep-equal.differ.js.map +1 -1
  26. package/dist/runtime/subsystems/sync/execute-sync.use-case.js.map +1 -1
  27. package/dist/runtime/subsystems/sync/index.js.map +1 -1
  28. package/dist/runtime/subsystems/sync/sync-change-source.protocol.d.ts +1 -1
  29. package/dist/runtime/subsystems/sync/sync-cursor-store.memory-backend.js.map +1 -1
  30. package/dist/runtime/subsystems/sync/sync-loopback.protocol.d.ts +3 -4
  31. package/dist/runtime/subsystems/sync/sync-run-recorder.drizzle-backend.js.map +1 -1
  32. package/dist/runtime/subsystems/sync/sync.module.js.map +1 -1
  33. package/dist/src/cli/index.js.map +1 -1
  34. package/dist/src/index.js.map +1 -1
  35. package/package.json +1 -1
  36. package/runtime/subsystems/auth/auth.tokens.ts +1 -1
  37. package/runtime/subsystems/auth/backends/encryption-key/env.ts +3 -3
  38. package/runtime/subsystems/auth/controllers/auth.controller.ts +3 -3
  39. package/runtime/subsystems/auth/index.ts +2 -2
  40. package/runtime/subsystems/auth/protocols/auth-strategy.ts +1 -1
  41. package/runtime/subsystems/auth/protocols/integration-store.ts +2 -2
  42. package/runtime/subsystems/auth/protocols/provider-strategy.ts +12 -5
  43. package/runtime/subsystems/auth/runtime/oauth2-refresh.strategy.ts +2 -2
  44. package/runtime/subsystems/auth/runtime/session-expired.error.ts +2 -2
  45. package/runtime/subsystems/auth/runtime/with-auth-retry.ts +1 -1
  46. package/runtime/subsystems/index.ts +1 -1
  47. package/runtime/subsystems/sync/deep-equal.differ.ts +1 -1
  48. package/runtime/subsystems/sync/execute-sync.use-case.ts +1 -1
  49. package/runtime/subsystems/sync/sync-change-source.protocol.ts +1 -1
  50. package/runtime/subsystems/sync/sync-cursor-store.memory-backend.ts +1 -1
  51. package/runtime/subsystems/sync/sync-loopback.protocol.ts +3 -4
  52. package/runtime/subsystems/sync/sync-run-recorder.drizzle-backend.ts +1 -1
  53. package/templates/subsystem/auth/app-module-hook.ejs.t +1 -1
  54. package/templates/subsystem/auth/env-config.ejs.t +5 -5
  55. package/templates/subsystem/auth/prompt.js +3 -3
  56. package/templates/subsystem/auth-config/codegen-config-auth-block.ejs.t +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pattern-stack/codegen",
3
- "version": "0.6.5",
3
+ "version": "0.6.6",
4
4
  "description": "Entity-driven code generation for full-stack TypeScript applications",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -23,7 +23,7 @@
23
23
  * `HUBSPOT_AUTH_STRATEGY`) by each integration module — this subsystem does
24
24
  * not mandate a single `AUTH_STRATEGY` token because an app typically has
25
25
  * many concurrent strategies, one per provider. They are dispatched through
26
- * `STRATEGY_REGISTRY` (a `ReadonlyMap<slug, ProviderStrategy>`), populated
26
+ * `STRATEGY_REGISTRY` (a `ReadonlyMap<slug, IProviderStrategy>`), populated
27
27
  * by per-provider modules via a `useFactory` provider.
28
28
  */
29
29
  export const ENCRYPTION_KEY = Symbol('ENCRYPTION_KEY');
@@ -6,7 +6,7 @@
6
6
  * ciphertexts — prevents replay-style inference. Auth tag enforces integrity;
7
7
  * any tampering throws on decrypt.
8
8
  *
9
- * Key source: `TOKEN_ENCRYPTION_KEY` env var, 32 bytes base64-encoded.
9
+ * Key source: `INTEGRATION_TOKEN_ENCRYPTION_KEY` env var, 32 bytes base64-encoded.
10
10
  * Generate via `openssl rand -base64 32`.
11
11
  *
12
12
  * Future backend: `kms.ts` (AWS/GCP KMS) for production deployments that
@@ -18,7 +18,7 @@ import type { IEncryptionKey } from '../../protocols/encryption-key';
18
18
  export interface EnvEncryptionKeyOptions {
19
19
  /** Defaults to `process.env`. Tests inject a fixture. */
20
20
  env?: NodeJS.ProcessEnv;
21
- /** Defaults to `'TOKEN_ENCRYPTION_KEY'`. */
21
+ /** Defaults to `'INTEGRATION_TOKEN_ENCRYPTION_KEY'`. */
22
22
  envVar?: string;
23
23
  }
24
24
 
@@ -32,7 +32,7 @@ export class EnvEncryptionKey implements IEncryptionKey {
32
32
 
33
33
  constructor(opts: EnvEncryptionKeyOptions = {}) {
34
34
  const env = opts.env ?? process.env;
35
- const envVar = opts.envVar ?? 'TOKEN_ENCRYPTION_KEY';
35
+ const envVar = opts.envVar ?? 'INTEGRATION_TOKEN_ENCRYPTION_KEY';
36
36
  const raw = env[envVar];
37
37
  if (!raw) {
38
38
  throw new Error(
@@ -9,7 +9,7 @@
9
9
  * 302-redirects to the post-connect path.
10
10
  *
11
11
  * Hexagonal seams:
12
- * - `STRATEGY_REGISTRY` (ReadonlyMap<slug, ProviderStrategy>) — dispatch.
12
+ * - `STRATEGY_REGISTRY` (ReadonlyMap<slug, IProviderStrategy>) — dispatch.
13
13
  * Concrete per-provider strategies live consumer-side and contribute
14
14
  * entries via a `useFactory` in the consumer's app module.
15
15
  * - `AUTH_USER_CONTEXT` (IUserContext) — resolves "who is this request"
@@ -44,7 +44,7 @@ import type { AuthModuleOptions } from '../auth.module';
44
44
  import type { IOAuthStateStore } from '../protocols/oauth-state-store';
45
45
  import type { IUserContext } from '../protocols/user-context';
46
46
  import type {
47
- ProviderStrategy,
47
+ IProviderStrategy,
48
48
  ProviderStrategyRegistry,
49
49
  } from '../protocols/provider-strategy';
50
50
  import type { IIntegrationGrantSink } from '../protocols/integration-store';
@@ -131,7 +131,7 @@ export class AuthController {
131
131
  );
132
132
  }
133
133
 
134
- private requireStrategy(slug: string): ProviderStrategy {
134
+ private requireStrategy(slug: string): IProviderStrategy {
135
135
  const strategy = this.registry.get(slug);
136
136
  if (!strategy) {
137
137
  throw new HttpException(
@@ -29,7 +29,7 @@
29
29
  * type IIntegrationGrantSink,
30
30
  * type IntegrationGrantInput,
31
31
  * type IUserContext,
32
- * type ProviderStrategy,
32
+ * type IProviderStrategy,
33
33
  * type ProviderStrategyRegistry,
34
34
  * type ExchangedTokens,
35
35
  * } from '@pattern-stack/codegen/runtime/subsystems/auth';
@@ -58,7 +58,7 @@ export type {
58
58
  } from './protocols/integration-store';
59
59
  export type { IUserContext } from './protocols/user-context';
60
60
  export type {
61
- ProviderStrategy,
61
+ IProviderStrategy,
62
62
  ProviderStrategyRegistry,
63
63
  ExchangedTokens,
64
64
  } from './protocols/provider-strategy';
@@ -7,7 +7,7 @@
7
7
  * `OAuth2RefreshStrategy` template-method base in `../runtime/`.
8
8
  *
9
9
  * See `docs/adrs/ADR-031-auth-subsystem.md` and
10
- * `docs/gate-1-auth-extraction-findings.md` (inbound from dealbrain-v2) for
10
+ * `docs/gate-1-auth-extraction-findings.md` (extraction-source findings) for
11
11
  * the rationale.
12
12
  */
13
13
 
@@ -6,7 +6,7 @@
6
6
  * those rows — consumers implement these narrow ports against whatever
7
7
  * `integrations` table their app uses.
8
8
  *
9
- * In dealbrain-v2 (the extraction source) both ports are satisfied by a
9
+ * In the extraction-source app both ports are satisfied by a
10
10
  * pair of thin adapters over `IntegrationService` + `RefreshIntegrationUseCase`.
11
11
  * The codegen-patterns `examples/auth-integrations/` starter (separate PR)
12
12
  * ships a canonical `integration.yaml` whose generated service + use case
@@ -70,7 +70,7 @@ export interface IIntegrationTokenWriter {
70
70
  * authorize-code callback (i.e. the user just connected a new provider, or
71
71
  * re-connected an existing one).
72
72
  *
73
- * `AuthController.callback` invokes this after `ProviderStrategy.exchangeCodeForTokens`.
73
+ * `AuthController.callback` invokes this after `IProviderStrategy.exchangeCodeForTokens`.
74
74
  * The subsystem itself never imports a concrete `IntegrationsService` — the
75
75
  * consumer's `auth-integrations` starter (or any equivalent) adapts this
76
76
  * port. Keeps the auth subsystem standalone: a non-codegen consumer can
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Auth subsystem — `ProviderStrategy` contract.
2
+ * Auth subsystem — `IProviderStrategy` contract.
3
3
  *
4
4
  * Extension of `OAuth2RefreshStrategy` (which already covers the refresh
5
5
  * path) that adds the two methods needed by the connect/callback dance:
@@ -11,11 +11,18 @@
11
11
  * stay consumer-side per ADR-031 ("every app has different combinations").
12
12
  * They typically subclass `OAuth2RefreshStrategy` for the refresh path and
13
13
  * implement these two methods structurally — that satisfies
14
- * `ProviderStrategy` because TS lets interfaces extend classes by type.
14
+ * `IProviderStrategy` because TS lets interfaces extend classes by type.
15
15
  *
16
16
  * AuthController never imports a concrete strategy — it injects the
17
- * `STRATEGY_REGISTRY` (a `ReadonlyMap<provider-slug, ProviderStrategy>`)
17
+ * `STRATEGY_REGISTRY` (a `ReadonlyMap<provider-slug, IProviderStrategy>`)
18
18
  * and dispatches by slug.
19
+ *
20
+ * **Naming convention:** interfaces that describe behavioral ports use the
21
+ * `I` prefix (`IProviderStrategy`, `IIntegrationReader`, `IUserContext`,
22
+ * `IOAuthStateStore`, `IEncryptionKey`). Plain data types / DTOs (e.g.
23
+ * `ExchangedTokens`, `DecryptedIntegration`, `IntegrationGrantInput`) do
24
+ * not. Abstract template-method classes (e.g. `OAuth2RefreshStrategy`) also
25
+ * do not — the `I` is for interfaces only.
19
26
  */
20
27
  import type { OAuth2RefreshStrategy } from '../runtime/oauth2-refresh.strategy';
21
28
 
@@ -29,7 +36,7 @@ export interface ExchangedTokens {
29
36
  providerMetadata?: Record<string, unknown>;
30
37
  }
31
38
 
32
- export interface ProviderStrategy extends OAuth2RefreshStrategy {
39
+ export interface IProviderStrategy extends OAuth2RefreshStrategy {
33
40
  buildAuthorizeUrl(args: { state: string; redirectUri: string }): string;
34
41
  exchangeCodeForTokens(args: {
35
42
  code: string;
@@ -38,4 +45,4 @@ export interface ProviderStrategy extends OAuth2RefreshStrategy {
38
45
  }
39
46
 
40
47
  /** The DI value type behind the `STRATEGY_REGISTRY` token. */
41
- export type ProviderStrategyRegistry = ReadonlyMap<string, ProviderStrategy>;
48
+ export type ProviderStrategyRegistry = ReadonlyMap<string, IProviderStrategy>;
@@ -2,8 +2,8 @@
2
2
  * Abstract base class for OAuth2 refresh-token strategies.
3
3
  *
4
4
  * Template-method pattern: `resolve()` is concrete; four small hooks inject
5
- * provider specifics. Validated across two providers in dealbrain-v2
6
- * (SalesforceAuthStrategy, HubSpotAuthStrategy) before extraction here — see
5
+ * provider specifics. Validated across two providers (Salesforce, HubSpot)
6
+ * in the extraction-source app before being extracted here — see
7
7
  * `docs/gate-1-auth-extraction-findings.md` for the "build first, extract
8
8
  * later" evidence.
9
9
  *
@@ -8,8 +8,8 @@
8
8
  * the `isSessionExpiredError` predicate to decide whether to force-refresh
9
9
  * and retry once.
10
10
  *
11
- * This discriminator replaces the SFDC-only `instanceof` check from
12
- * dealbrain-v2's original `withAuthRetry`. See
11
+ * This discriminator replaces the SFDC-only `instanceof` check from the
12
+ * extraction-source app's original `withAuthRetry`. See
13
13
  * `docs/gate-1-auth-extraction-findings.md` (recommendation 4).
14
14
  */
15
15
  export class SessionExpiredError extends Error {
@@ -6,7 +6,7 @@
6
6
  * on the refreshed token propagates rather than looping, so transient
7
7
  * adapter bugs can't hang the caller.
8
8
  *
9
- * Generalisation over dealbrain's original SFDC-specific version: the
9
+ * Generalisation over the extraction source's SFDC-specific original: the
10
10
  * session-expired classifier is injected. Providers mark their session-
11
11
  * expired errors (via `instanceof` of a marker class, or by setting a known
12
12
  * property) and pass a classifier matching that shape.
@@ -82,7 +82,7 @@ export type {
82
82
  IIntegrationGrantSink,
83
83
  IntegrationGrantInput,
84
84
  IUserContext,
85
- ProviderStrategy,
85
+ IProviderStrategy,
86
86
  ProviderStrategyRegistry,
87
87
  ExchangedTokens,
88
88
  AuthCredentials,
@@ -5,7 +5,7 @@
5
5
  * per-field diff (`{ from, to }`) for every field whose value changed.
6
6
  * Returns `'noop'` when the record is unchanged.
7
7
  *
8
- * Design decisions (extracted from dealbrain-v2 + HS-9 findings):
8
+ * Design decisions (extracted from the upstream consumer + HS-9 findings):
9
9
  *
10
10
  * 1. **Ignore list** — row metadata that sinks/services stamp unconditionally
11
11
  * so upstream cannot reasonably disagree:
@@ -41,7 +41,7 @@
41
41
  * is strictly provider-agnostic:
42
42
  * - `entityType` is `string` throughout; no `'opportunity' | 'account' | ...`
43
43
  * narrowing leaks into the use case
44
- * - dealbrain's `SyncRunRecorderService` class injection replaced with the
44
+ * - the upstream consumer's `SyncRunRecorderService` class injection replaced with the
45
45
  * `ISyncRunRecorder` protocol (backend lands in SYNC-4)
46
46
  */
47
47
  import { Inject, Injectable, Logger, Optional } from '@nestjs/common';
@@ -6,7 +6,7 @@
6
6
  * depend on a specific backend implementation.
7
7
  *
8
8
  * Three detection modes (poll / cdc / webhook) converge on this single port
9
- * per ADR-0002 (dealbrain-v2). Per-mode differences live in the
9
+ * per ADR-0002 (the upstream consumer). Per-mode differences live in the
10
10
  * `Change.source` / `dedupKey` / `providerChangedFields` metadata fields,
11
11
  * not in separate ports.
12
12
  *
@@ -21,7 +21,7 @@
21
21
  * could occur. Tests that want to assert per-tenant isolation should
22
22
  * target the Drizzle backend.
23
23
  *
24
- * Not shipped in dealbrain-v2; this is a subsystem-first addition for the
24
+ * Not shipped in the upstream consumer; this is a subsystem-first addition for the
25
25
  * test surface. Consumed by:
26
26
  * - SYNC-5 unit tests (`ExecuteSyncUseCase` against synthetic sources)
27
27
  * - SYNC-6 module tests (`SyncModule.forRoot({ backend: 'memory' })`)
@@ -14,10 +14,9 @@
14
14
  * a backend in Phase 1; consumers that need loopback suppression provide
15
15
  * their own (redis-hashed, memory TTL, etc.).
16
16
  *
17
- * `entityType` is `string` (not a union) — per dealbrain-v2's HS-9 findings
18
- * the CRM-specific narrowing `'opportunity' | 'account' | 'contact'` bled
19
- * into the port and had to be removed. Consumers narrow internally if they
20
- * want.
17
+ * `entityType` is `string` (not a union) — per HS-9 findings the
18
+ * CRM-specific narrowing `'opportunity' | 'account' | 'contact'` bled into
19
+ * the port and had to be removed. Consumers narrow internally if they want.
21
20
  */
22
21
 
23
22
  export interface ILoopbackFingerprintStore<T = unknown> {
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * DrizzleSyncRunRecorder — Drizzle-backed `ISyncRunRecorder` (SYNC-4).
3
3
  *
4
- * Generic write path only — extracted from dealbrain-v2's
4
+ * Generic write path only — extracted from the source app's
5
5
  * `SyncRunRecorderService`, minus CRM-specific convenience methods. Those
6
6
  * stay consumer-owned; the subsystem ships the substrate.
7
7
  *
@@ -17,5 +17,5 @@ skip_if: "AuthModule"
17
17
  // redirectUriBase: process.env.AUTH_REDIRECT_URI_BASE ?? '<%= redirectUriBase %>',
18
18
  // }),
19
19
  //
20
- // Requires TOKEN_ENCRYPTION_KEY in your environment (see .env.config).
20
+ // Requires INTEGRATION_TOKEN_ENCRYPTION_KEY in your environment (see .env.config).
21
21
  // Provide an IUserContext adapter (your app's session/JWT scheme).
@@ -2,19 +2,19 @@
2
2
  to: "<%= envConfigPath %>"
3
3
  inject: true
4
4
  append: true
5
- skip_if: "TOKEN_ENCRYPTION_KEY"
5
+ skip_if: "INTEGRATION_TOKEN_ENCRYPTION_KEY"
6
6
  ---
7
7
 
8
8
  # OAuth integration token encryption key — 32 bytes base64 (AES-256-GCM).
9
9
  # DO NOT REUSE this dev value in prod. To regenerate locally:
10
10
  # node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"
11
11
  # Re-running `codegen subsystem install auth` does NOT rotate this key —
12
- # `skip_if: "TOKEN_ENCRYPTION_KEY"` blocks the inject intentionally, because
13
- # silently rotating would invalidate every encrypted token already in the
14
- # consumer's `integrations` table. Rotation is a separate, auditable op.
12
+ # `skip_if: "INTEGRATION_TOKEN_ENCRYPTION_KEY"` blocks the inject intentionally,
13
+ # because silently rotating would invalidate every encrypted token already in
14
+ # the consumer's `integrations` table. Rotation is a separate, auditable op.
15
15
  # In production: store the key in `secrets/secrets.yaml` (or your secret
16
16
  # manager) and have your deploy pipeline materialise it into the env at
17
17
  # boot — this `.env.config` line should be a placeholder, not the source.
18
- TOKEN_ENCRYPTION_KEY=<%= tokenEncryptionKey %>
18
+ INTEGRATION_TOKEN_ENCRYPTION_KEY=<%= tokenEncryptionKey %>
19
19
  # Public base URL where OAuth providers redirect back. Override in staging/prod.
20
20
  AUTH_REDIRECT_URI_BASE=<%= redirectUriBase %>
@@ -21,9 +21,9 @@
21
21
  * - `app-module-hook.ejs.t` — appends a TODO comment block to
22
22
  * app.module.ts directing the human to register
23
23
  * `AuthModule.forRoot({ ... })`. Same convention as observability.
24
- * - `env-config.ejs.t` — appends `TOKEN_ENCRYPTION_KEY=<b64>` and
25
- * `AUTH_REDIRECT_URI_BASE=<url>` to `.env.config`. Idempotent via
26
- * `skip_if: "TOKEN_ENCRYPTION_KEY"` — re-running install does NOT
24
+ * - `env-config.ejs.t` — appends `INTEGRATION_TOKEN_ENCRYPTION_KEY=<b64>`
25
+ * and `AUTH_REDIRECT_URI_BASE=<url>` to `.env.config`. Idempotent via
26
+ * `skip_if: "INTEGRATION_TOKEN_ENCRYPTION_KEY"` — re-running install does NOT
27
27
  * regenerate the key (rotation is a separate operation).
28
28
  *
29
29
  * Auth has NO `multi_tenant` knob (see auth-scaffold-locals.ts docstring).
@@ -6,7 +6,7 @@ skip_if: "auth:"
6
6
  ---
7
7
 
8
8
  auth:
9
- # ── Encryption key (TOKEN_ENCRYPTION_KEY from .env.config) ──
9
+ # ── Encryption key (INTEGRATION_TOKEN_ENCRYPTION_KEY from .env.config) ──
10
10
  encryption_key: env
11
11
 
12
12
  # ── OAuth state store (drizzle for prod, memory for tests) ──