@xemahq/biome-database-nest 0.8.0 → 0.10.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.
Files changed (50) hide show
  1. package/README.md +21 -4
  2. package/dist/index.d.ts +3 -4
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +1 -7
  5. package/dist/index.js.map +1 -1
  6. package/dist/lib/bootstrap.d.ts +3 -15
  7. package/dist/lib/bootstrap.d.ts.map +1 -1
  8. package/dist/lib/bootstrap.js +10 -56
  9. package/dist/lib/bootstrap.js.map +1 -1
  10. package/dist/lib/config.d.ts.map +1 -1
  11. package/dist/lib/config.js +13 -6
  12. package/dist/lib/config.js.map +1 -1
  13. package/dist/lib/control-plane-client.js +3 -3
  14. package/dist/lib/control-plane-client.js.map +1 -1
  15. package/dist/lib/migration-mode.d.ts +1 -57
  16. package/dist/lib/migration-mode.d.ts.map +1 -1
  17. package/dist/lib/migration-mode.js +1 -20
  18. package/dist/lib/migration-mode.js.map +1 -1
  19. package/dist/lib/nest/biome-database.module.d.ts +4 -9
  20. package/dist/lib/nest/biome-database.module.d.ts.map +1 -1
  21. package/dist/lib/nest/biome-database.module.js +4 -11
  22. package/dist/lib/nest/biome-database.module.js.map +1 -1
  23. package/package.json +4 -3
  24. package/src/index.ts +112 -0
  25. package/src/lib/adapter.ts +114 -0
  26. package/src/lib/bootstrap.ts +433 -0
  27. package/src/lib/config.ts +183 -0
  28. package/src/lib/control-plane-client.ts +121 -0
  29. package/src/lib/control-plane-discovery.ts +34 -0
  30. package/src/lib/identifier.ts +177 -0
  31. package/src/lib/migration-mode.ts +25 -0
  32. package/src/lib/nest/biome-database.module.ts +175 -0
  33. package/src/lib/nest/org-erasure.module.ts +124 -0
  34. package/src/lib/nest/prisma-service-factory.ts +376 -0
  35. package/src/lib/role-names.ts +77 -0
  36. package/src/lib/schema-name.ts +62 -0
  37. package/src/lib/tenant-isolation/org-erasure.ts +158 -0
  38. package/src/lib/tenant-isolation/org-scope.ts +305 -0
  39. package/src/lib/tenant-isolation/tenant-isolation-error.ts +79 -0
  40. package/src/lib/tenant-isolation/tenant-isolation-mode.ts +55 -0
  41. package/src/lib/tenant-isolation/tenant-isolation.extension.ts +203 -0
  42. package/src/lib/tenant-isolation/unscoped-models.ts +269 -0
  43. package/dist/lib/external-runtime-verifier.d.ts +0 -3
  44. package/dist/lib/external-runtime-verifier.d.ts.map +0 -1
  45. package/dist/lib/external-runtime-verifier.js +0 -411
  46. package/dist/lib/external-runtime-verifier.js.map +0 -1
  47. package/dist/lib/response-envelope.d.ts +0 -2
  48. package/dist/lib/response-envelope.d.ts.map +0 -1
  49. package/dist/lib/response-envelope.js +0 -6
  50. package/dist/lib/response-envelope.js.map +0 -1
@@ -13,23 +13,16 @@ const identity_client_1 = require("@xemahq/identity-client");
13
13
  const service_registry_nest_1 = require("@xemahq/service-registry-nest");
14
14
  const bootstrap_1 = require("../bootstrap");
15
15
  const migration_mode_1 = require("../migration-mode");
16
- const schema_name_1 = require("../schema-name");
17
16
  exports.BIOME_DATABASE_READY = Symbol.for('@xemahq/biome-database-nest:ready');
18
17
  let BiomeDatabaseModule = BiomeDatabaseModule_1 = class BiomeDatabaseModule {
19
18
  static forRoot(opts) {
20
- if (opts.migrationMode !== migration_mode_1.BiomeDatabaseMigrationMode.ApplicationManaged &&
21
- opts.migrationMode !== migration_mode_1.BiomeDatabaseMigrationMode.ExternallyManaged) {
19
+ if (opts.migrationMode !== migration_mode_1.BiomeDatabaseMigrationMode.ApplicationManaged) {
22
20
  throw new Error('[biome-database] migrationMode is required and must be a BiomeDatabaseMigrationMode.');
23
21
  }
24
- if (opts.migrationMode === migration_mode_1.BiomeDatabaseMigrationMode.ExternallyManaged &&
25
- opts.databases.length === 0) {
26
- throw new Error('[biome-database] externally-managed mode requires at least one explicit database declaration.');
22
+ if (opts.databases.length === 0) {
23
+ throw new Error('[biome-database] every migration mode requires at least one explicit database declaration.');
27
24
  }
28
- const databases = opts.migrationMode === migration_mode_1.BiomeDatabaseMigrationMode.ApplicationManaged
29
- ? (opts.databases ?? [
30
- { key: schema_name_1.DEFAULT_BIOME_DB_KEY, workspaceDir: process.cwd() },
31
- ])
32
- : opts.databases;
25
+ const databases = opts.databases;
33
26
  if ((0, service_registry_nest_1.isOpenApiExtraction)()) {
34
27
  return {
35
28
  module: BiomeDatabaseModule_1,
@@ -1 +1 @@
1
- {"version":3,"file":"biome-database.module.js","sourceRoot":"","sources":["../../../src/lib/nest/biome-database.module.ts"],"names":[],"mappings":";;;;;;;;;;AACA,2CAAwC;AACxC,6DAAmE;AAEnE,yEAGuC;AAEvC,4CAAuD;AAKvD,sDAA+D;AAC/D,gDAAsD;AAWzC,QAAA,oBAAoB,GAAG,MAAM,CAAC,GAAG,CAC5C,mCAAmC,CACpC,CAAC;AAqFK,IAAM,mBAAmB,2BAAzB,MAAM,mBAAmB;IAC9B,MAAM,CAAC,OAAO,CAAC,IAAgC;QAC7C,IACE,IAAI,CAAC,aAAa,KAAK,2CAA0B,CAAC,kBAAkB;YACpE,IAAI,CAAC,aAAa,KAAK,2CAA0B,CAAC,iBAAiB,EACnE,CAAC;YACD,MAAM,IAAI,KAAK,CACb,sFAAsF,CACvF,CAAC;QACJ,CAAC;QACD,IACE,IAAI,CAAC,aAAa,KAAK,2CAA0B,CAAC,iBAAiB;YACnE,IAAI,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,EAC3B,CAAC;YACD,MAAM,IAAI,KAAK,CACb,+FAA+F,CAChG,CAAC;QACJ,CAAC;QACD,MAAM,SAAS,GAGb,IAAI,CAAC,aAAa,KAAK,2CAA0B,CAAC,kBAAkB;YAClE,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,IAAI;gBACjB,EAAE,GAAG,EAAE,kCAAoB,EAAE,YAAY,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE;aAC3D,CAAC;YACJ,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC;QAQrB,IAAI,IAAA,2CAAmB,GAAE,EAAE,CAAC;YAC1B,OAAO;gBACL,MAAM,EAAE,qBAAmB;gBAC3B,MAAM,EAAE,IAAI;gBACZ,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,4BAAoB,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;gBAC9D,OAAO,EAAE,CAAC,4BAAoB,CAAC;aAChC,CAAC;QACJ,CAAC;QAED,OAAO;YACL,MAAM,EAAE,qBAAmB;YAC3B,MAAM,EAAE,IAAI;YACZ,SAAS,EAAE;gBACT;oBACE,OAAO,EAAE,4BAAoB;oBAC7B,UAAU,EAAE,KAAK,EACf,iBAA2C,EAC3C,WAAwB,EACT,EAAE;wBACjB,IACE,IAAI,CAAC,aAAa;4BAClB,2CAA0B,CAAC,kBAAkB,EAC7C,CAAC;4BACD,MAAM,IAAA,mCAAuB,EAAC;gCAC5B,OAAO,EAAE,IAAI,CAAC,OAAO;gCACrB,aAAa,EAAE,IAAI,CAAC,aAAa;gCACjC,SAAS,EAAE,SAAgD;gCAC3D,GAAG,CAAC,IAAI,CAAC,kBAAkB,KAAK,SAAS;oCACvC,CAAC,CAAC,EAAE,kBAAkB,EAAE,IAAI,CAAC,kBAAkB,EAAE;oCACjD,CAAC,CAAC,EAAE,CAAC;gCACP,YAAY,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,cAAc,EAAE;gCACtD,WAAW;6BACZ,CAAC,CAAC;wBACL,CAAC;6BAAM,CAAC;4BACN,MAAM,IAAA,mCAAuB,EAAC;gCAC5B,OAAO,EAAE,IAAI,CAAC,OAAO;gCACrB,aAAa,EAAE,IAAI,CAAC,aAAa;gCACjC,SAAS,EACP,SAAiE;gCACnE,YAAY,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,cAAc,EAAE;gCACtD,WAAW;6BACZ,CAAC,CAAC;wBACL,CAAC;wBACD,OAAO,IAAI,CAAC;oBACd,CAAC;oBACD,MAAM,EAAE,CAAC,0CAAwB,EAAE,0CAAkB,CAAC;iBACvD;aACF;YACD,OAAO,EAAE,CAAC,4BAAoB,CAAC;SAChC,CAAC;IACJ,CAAC;CACF,CAAA;AApFY,kDAAmB;8BAAnB,mBAAmB;IAD/B,IAAA,eAAM,EAAC,EAAE,CAAC;GACE,mBAAmB,CAoF/B"}
1
+ {"version":3,"file":"biome-database.module.js","sourceRoot":"","sources":["../../../src/lib/nest/biome-database.module.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAAwC;AACxC,6DAAmE;AACnE,yEAGuC;AAEvC,4CAAuD;AACvD,sDAA+D;AAiBlD,QAAA,oBAAoB,GAAG,MAAM,CAAC,GAAG,CAC5C,mCAAmC,CACpC,CAAC;AAwEK,IAAM,mBAAmB,2BAAzB,MAAM,mBAAmB;IAC9B,MAAM,CAAC,OAAO,CAAC,IAAgC;QAC7C,IACE,IAAI,CAAC,aAAa,KAAK,2CAA0B,CAAC,kBAAkB,EACpE,CAAC;YACD,MAAM,IAAI,KAAK,CACb,sFAAsF,CACvF,CAAC;QACJ,CAAC;QACD,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CACb,4FAA4F,CAC7F,CAAC;QACJ,CAAC;QACD,MAAM,SAAS,GAEX,IAAI,CAAC,SAAS,CAAC;QAQnB,IAAI,IAAA,2CAAmB,GAAE,EAAE,CAAC;YAC1B,OAAO;gBACL,MAAM,EAAE,qBAAmB;gBAC3B,MAAM,EAAE,IAAI;gBACZ,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,4BAAoB,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;gBAC9D,OAAO,EAAE,CAAC,4BAAoB,CAAC;aAChC,CAAC;QACJ,CAAC;QAED,OAAO;YACL,MAAM,EAAE,qBAAmB;YAC3B,MAAM,EAAE,IAAI;YACZ,SAAS,EAAE;gBACT;oBACE,OAAO,EAAE,4BAAoB;oBAC7B,UAAU,EAAE,KAAK,EACf,iBAA2C,EAC3C,WAAwB,EACT,EAAE;wBACjB,IACE,IAAI,CAAC,aAAa;4BAClB,2CAA0B,CAAC,kBAAkB,EAC7C,CAAC;4BACD,MAAM,IAAA,mCAAuB,EAAC;gCAC5B,OAAO,EAAE,IAAI,CAAC,OAAO;gCACrB,aAAa,EAAE,IAAI,CAAC,aAAa;gCACjC,SAAS,EAAE,SAAgD;gCAC3D,GAAG,CAAC,IAAI,CAAC,kBAAkB,KAAK,SAAS;oCACvC,CAAC,CAAC,EAAE,kBAAkB,EAAE,IAAI,CAAC,kBAAkB,EAAE;oCACjD,CAAC,CAAC,EAAE,CAAC;gCACP,YAAY,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,cAAc,EAAE;gCACtD,WAAW;6BACZ,CAAC,CAAC;wBACL,CAAC;6BAAM,CAAC;4BACN,MAAM,IAAA,mCAAuB,EAAC;gCAC5B,OAAO,EAAE,IAAI,CAAC,OAAO;gCACrB,aAAa,EAAE,IAAI,CAAC,aAAa;gCACjC,SAAS,EACP,SAAS;gCACX,YAAY,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,cAAc,EAAE;gCACtD,WAAW;6BACZ,CAAC,CAAC;wBACL,CAAC;wBACD,OAAO,IAAI,CAAC;oBACd,CAAC;oBACD,MAAM,EAAE,CAAC,0CAAwB,EAAE,0CAAkB,CAAC;iBACvD;aACF;YACD,OAAO,EAAE,CAAC,4BAAoB,CAAC;SAChC,CAAC;IACJ,CAAC;CACF,CAAA;AA3EY,kDAAmB;8BAAnB,mBAAmB;IAD/B,IAAA,eAAM,EAAC,EAAE,CAAC;GACE,mBAAmB,CA2E/B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xemahq/biome-database-nest",
3
- "version": "0.8.0",
3
+ "version": "0.10.0",
4
4
  "description": "Explicit database migration ownership, least-privilege runtime verification, and schema-qualified Prisma wiring for Xema biome services.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Neuralchowder Inc. <developer@xema.dev> (https://xema.dev)",
@@ -18,7 +18,8 @@
18
18
  "main": "dist/index.js",
19
19
  "types": "dist/index.d.ts",
20
20
  "files": [
21
- "dist"
21
+ "dist",
22
+ "src"
22
23
  ],
23
24
  "devDependencies": {
24
25
  "@nestjs/common": "11.1.13",
@@ -49,7 +50,7 @@
49
50
  },
50
51
  "dependencies": {
51
52
  "@xemahq/migration-runner-prisma": "^0.1.2",
52
- "@xemahq/platform-common": "^0.5.9",
53
+ "@xemahq/platform-common": "^0.6.1",
53
54
  "pg": "8.16.3"
54
55
  },
55
56
  "exports": {
package/src/index.ts ADDED
@@ -0,0 +1,112 @@
1
+ export { DEFAULT_BIOME_DB_KEY, deriveBiomeSchemaName } from './lib/schema-name';
2
+ export {
3
+ composeIdentifier,
4
+ fitIdentifier,
5
+ IDENTIFIER_HASH_LENGTH,
6
+ POSTGRES_MAX_IDENTIFIER_LENGTH,
7
+ sanitizeIdentifierChars,
8
+ sanitizeIdentifierSegment,
9
+ type ComposeIdentifierInput,
10
+ type FitIdentifierInput,
11
+ } from './lib/identifier';
12
+ export {
13
+ rolesForSchema,
14
+ schemaRoleBase,
15
+ schemaRoleName,
16
+ SchemaRoleKind,
17
+ SCHEMA_ROLE_BASE_MAX_LENGTH,
18
+ SCHEMA_ROLE_SUFFIX_LENGTH,
19
+ type SchemaRoleNames,
20
+ } from './lib/role-names';
21
+ export {
22
+ resolveBiomeDatabaseConfigFromEnv,
23
+ type BiomeDatabaseConfig,
24
+ } from './lib/config';
25
+ export {
26
+ createBiomePrismaAdapter,
27
+ createBiomePrismaAdapterFromEnv,
28
+ } from './lib/adapter';
29
+ export {
30
+ fetchSystemDatabaseConfig,
31
+ type SystemDatabaseConfigRequest,
32
+ } from './lib/control-plane-client';
33
+ export {
34
+ resolveControlPlaneBaseUrl,
35
+ ORG_DATABASE_POOL_SERVICE_NAME,
36
+ type ControlPlaneDiscoveryOptions,
37
+ } from './lib/control-plane-discovery';
38
+ export {
39
+ bootstrapBiomeDatabases,
40
+ type BiomeDatabaseDeclaration,
41
+ type BootstrapBiomeDatabasesOptions,
42
+ } from './lib/bootstrap';
43
+ export { BiomeDatabaseMigrationMode } from './lib/migration-mode';
44
+ export {
45
+ BiomeDatabaseModule,
46
+ BIOME_DATABASE_READY,
47
+ type BiomeDatabaseModuleOptions,
48
+ } from './lib/nest/biome-database.module';
49
+ export {
50
+ createBiomePrismaService,
51
+ type BiomePrismaClient,
52
+ type BiomePrismaClientCtor,
53
+ type BiomePrismaServiceInstance,
54
+ type CreateBiomePrismaServiceOptions,
55
+ type TenantIsolationServiceOptions,
56
+ type TenantScopedApi,
57
+ } from './lib/nest/prisma-service-factory';
58
+ export {
59
+ TenantIsolationMode,
60
+ TENANT_ISOLATION_MODE_ENV_VAR,
61
+ resolveTenantIsolationMode,
62
+ } from './lib/tenant-isolation/tenant-isolation-mode';
63
+ export {
64
+ TenantIsolationError,
65
+ TenantIsolationViolationKind,
66
+ formatTenantIsolationViolation,
67
+ type TenantIsolationViolation,
68
+ } from './lib/tenant-isolation/tenant-isolation-error';
69
+ export {
70
+ PrismaModelOperation,
71
+ scopeArgsToOrg,
72
+ type OrgScopeOutcome,
73
+ type OrgScopeRequest,
74
+ } from './lib/tenant-isolation/org-scope';
75
+ export {
76
+ DEFAULT_ORG_FIELD,
77
+ collectOrgScopedModels,
78
+ createTenantIsolationExtension,
79
+ readRuntimeModels,
80
+ type CreateTenantIsolationExtensionOptions,
81
+ type RuntimeDataModelField,
82
+ type RuntimeDataModelModel,
83
+ type TenantIsolationExtensionDefinition,
84
+ type TenantIsolationLogger,
85
+ type TenantIsolationQueryContext,
86
+ } from './lib/tenant-isolation/tenant-isolation.extension';
87
+ export {
88
+ assertUnscopedModelsDeclared,
89
+ collectUnscopableModels,
90
+ formatUnscopedModelReport,
91
+ normalizeUnscopedModelDeclarations,
92
+ UndeclaredUnscopedModelsError,
93
+ type AssertUnscopedModelsOptions,
94
+ type NormalizedUnscopedModelDeclaration,
95
+ type UnscopedModelDeclaration,
96
+ type UnscopedModelDeclarations,
97
+ } from './lib/tenant-isolation/unscoped-models';
98
+ export {
99
+ eraseOrgData,
100
+ OrgErasureBlockedError,
101
+ type EraseOrgDataOptions,
102
+ type OrgErasureReport,
103
+ } from './lib/tenant-isolation/org-erasure';
104
+ export {
105
+ OrgErasureModule,
106
+ OrgErasureController,
107
+ ORG_ERASURE_RUNNER,
108
+ ORG_DATA_ERASURE_CAPABILITY,
109
+ ORG_ERASURE_ROUTE_PATH,
110
+ type OrgErasureModuleOptions,
111
+ type OrgErasureRunner,
112
+ } from './lib/nest/org-erasure.module';
@@ -0,0 +1,114 @@
1
+ import { PrismaPg } from '@prisma/adapter-pg';
2
+ import {
3
+ composeBiomeDatabaseUrl,
4
+ ensureBiomeDbSearchPath,
5
+ } from '@xemahq/platform-common';
6
+
7
+ import type { BiomeDatabaseConfig } from './config';
8
+ import { resolveBiomeDatabaseConfigFromEnv } from './config';
9
+
10
+ const DEFAULT_POOL_MAX = 3;
11
+
12
+ /**
13
+ * Build a connection string from a {@link BiomeDatabaseConfig}, with `?schema=`
14
+ * when a per-biome schema is set and the libpq `search_path` option applied so
15
+ * RAW queries also resolve to the biome schema.
16
+ *
17
+ * @throws if the config is missing a part required to form a URL.
18
+ */
19
+ function buildBiomeConnectionString(config: BiomeDatabaseConfig): string {
20
+ const url = composeBiomeDatabaseUrl({
21
+ user: config.username,
22
+ password: config.password,
23
+ host: config.host,
24
+ port: String(config.port),
25
+ database: config.database,
26
+ ...(config.schema !== undefined ? { schema: config.schema } : {}),
27
+ ...(config.sslParams !== undefined ? { sslParams: config.sslParams } : {}),
28
+ });
29
+ if (url === null) {
30
+ throw new Error(
31
+ 'createBiomePrismaAdapter: incomplete BiomeDatabaseConfig — ' +
32
+ 'host/port/database/username/password are all required.',
33
+ );
34
+ }
35
+ return ensureBiomeDbSearchPath(url);
36
+ }
37
+
38
+ /**
39
+ * Construct a {@link PrismaPg} driver-adapter pool whose Prisma Client qualifies
40
+ * ORM table names with the biome schema.
41
+ *
42
+ * THIS IS THE CENTRALIZED FIX. `@prisma/adapter-pg` (Prisma 7) ignores BOTH the
43
+ * URL `?schema=` and the connection `search_path` when qualifying ORM-emitted
44
+ * SQL — it falls back to `public.<table>` unless the schema is passed as the
45
+ * SECOND constructor argument. Passing `{ schema }` here makes Prisma emit
46
+ * `biome_<id>.<table>`. `ensureBiomeDbSearchPath` separately fixes RAW queries.
47
+ * Constructing the adapter correctly is the ONLY thing this function does, so
48
+ * the correct construction is the only construction a biome can perform.
49
+ */
50
+ export function createBiomePrismaAdapter(config: BiomeDatabaseConfig): PrismaPg {
51
+ const connectionString = buildBiomeConnectionString(config);
52
+ return new PrismaPg(
53
+ {
54
+ connectionString,
55
+ min: 1,
56
+ max: config.poolMax ?? DEFAULT_POOL_MAX,
57
+ idleTimeoutMillis: 30_000,
58
+ },
59
+ config.schema !== undefined ? { schema: config.schema } : undefined,
60
+ );
61
+ }
62
+
63
+ /**
64
+ * Construct the schema-qualified adapter from the environment — the path the
65
+ * unchanged-shape `PrismaService` calls at construction time (post-bootstrap,
66
+ * where `DATABASE_URL`/`DB_*` are guaranteed set).
67
+ *
68
+ * Resolution order:
69
+ * 1. If `DATABASE_URL` (or `DATABASE_URL_<KEY>` for a non-default key) is set,
70
+ * use it directly as the connection string (still applying
71
+ * `ensureBiomeDbSearchPath` + the `{ schema }` second-arg from `DB_SCHEMA`).
72
+ * 2. Otherwise compose from the discrete `DB_*` vars.
73
+ *
74
+ * @throws if neither a `DATABASE_URL` nor a complete `DB_*` set is present.
75
+ */
76
+ export function createBiomePrismaAdapterFromEnv(
77
+ env: NodeJS.ProcessEnv = process.env,
78
+ dbKey?: string,
79
+ ): PrismaPg {
80
+ const isDefault = dbKey === undefined || dbKey === '' || dbKey === 'primary';
81
+ const upperSuffix = isDefault
82
+ ? ''
83
+ : `_${dbKey!.toUpperCase().replace(/[^A-Z0-9]/g, '_')}`;
84
+
85
+ const directUrl = env[`DATABASE_URL${upperSuffix}`];
86
+ const schema = env[`DB_SCHEMA${upperSuffix}`];
87
+ const poolMaxRaw = env[`DB_POOL_MAX${upperSuffix}`] ?? env.DB_POOL_MAX;
88
+ const poolMax =
89
+ poolMaxRaw !== undefined && poolMaxRaw !== ''
90
+ ? Number.parseInt(poolMaxRaw, 10)
91
+ : DEFAULT_POOL_MAX;
92
+
93
+ if (directUrl !== undefined && directUrl !== '') {
94
+ const connectionString = ensureBiomeDbSearchPath(directUrl);
95
+ return new PrismaPg(
96
+ {
97
+ connectionString,
98
+ min: 1,
99
+ max: poolMax,
100
+ idleTimeoutMillis: 30_000,
101
+ },
102
+ schema !== undefined && schema !== '' ? { schema } : undefined,
103
+ );
104
+ }
105
+
106
+ const config = resolveBiomeDatabaseConfigFromEnv(env, dbKey);
107
+ if (config === null) {
108
+ throw new Error(
109
+ `createBiomePrismaAdapterFromEnv: no DATABASE_URL${upperSuffix} and no ` +
110
+ `DB_HOST${upperSuffix}/DB_HOST in the environment — cannot construct an adapter.`,
111
+ );
112
+ }
113
+ return createBiomePrismaAdapter(config);
114
+ }