@arki/db 0.1.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 (67) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +113 -0
  3. package/dist/builder.d.ts +119 -0
  4. package/dist/builder.d.ts.map +1 -0
  5. package/dist/builder.js +165 -0
  6. package/dist/builder.js.map +1 -0
  7. package/dist/bun.d.ts +22 -0
  8. package/dist/bun.d.ts.map +1 -0
  9. package/dist/bun.js +37 -0
  10. package/dist/bun.js.map +1 -0
  11. package/dist/client/ids.d.ts +12 -0
  12. package/dist/client/ids.d.ts.map +1 -0
  13. package/dist/client/ids.js +2 -0
  14. package/dist/client/ids.js.map +1 -0
  15. package/dist/client/index.d.ts +12 -0
  16. package/dist/client/index.d.ts.map +1 -0
  17. package/dist/client/index.js +2 -0
  18. package/dist/client/index.js.map +1 -0
  19. package/dist/connection-options.d.ts +30 -0
  20. package/dist/connection-options.d.ts.map +1 -0
  21. package/dist/connection-options.js +41 -0
  22. package/dist/connection-options.js.map +1 -0
  23. package/dist/debug.d.ts +21 -0
  24. package/dist/debug.d.ts.map +1 -0
  25. package/dist/debug.js +21 -0
  26. package/dist/debug.js.map +1 -0
  27. package/dist/dot.d.ts +87 -0
  28. package/dist/dot.d.ts.map +1 -0
  29. package/dist/dot.js +104 -0
  30. package/dist/dot.js.map +1 -0
  31. package/dist/env.d.ts +23 -0
  32. package/dist/env.d.ts.map +1 -0
  33. package/dist/env.js +77 -0
  34. package/dist/env.js.map +1 -0
  35. package/dist/factory.d.ts +18 -0
  36. package/dist/factory.d.ts.map +1 -0
  37. package/dist/factory.js +31 -0
  38. package/dist/factory.js.map +1 -0
  39. package/dist/id-factory.d.ts +85 -0
  40. package/dist/id-factory.d.ts.map +1 -0
  41. package/dist/id-factory.js +119 -0
  42. package/dist/id-factory.js.map +1 -0
  43. package/dist/id.d.ts +4 -0
  44. package/dist/id.d.ts.map +1 -0
  45. package/dist/id.js +10 -0
  46. package/dist/id.js.map +1 -0
  47. package/dist/init.bun.d.ts +25 -0
  48. package/dist/init.bun.d.ts.map +1 -0
  49. package/dist/init.bun.js +29 -0
  50. package/dist/init.bun.js.map +1 -0
  51. package/dist/init.d.ts +16 -0
  52. package/dist/init.d.ts.map +1 -0
  53. package/dist/init.js +24 -0
  54. package/dist/init.js.map +1 -0
  55. package/dist/orm.d.ts +3 -0
  56. package/dist/orm.d.ts.map +1 -0
  57. package/dist/orm.js +5 -0
  58. package/dist/orm.js.map +1 -0
  59. package/dist/pg.d.ts +2 -0
  60. package/dist/pg.d.ts.map +1 -0
  61. package/dist/pg.js +2 -0
  62. package/dist/pg.js.map +1 -0
  63. package/dist/runtime-local.d.ts +30 -0
  64. package/dist/runtime-local.d.ts.map +1 -0
  65. package/dist/runtime-local.js +31 -0
  66. package/dist/runtime-local.js.map +1 -0
  67. package/package.json +128 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../src/debug.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEpD;;;GAGG;AACH,eAAO,MAAM,SAAS,4BAA+B,CAAC;AAEtD;;;GAGG;AACH,eAAO,MAAM,YAAY,4BAAkC,CAAC;AAE5D;;;GAGG;AACH,eAAO,MAAM,eAAe,4BAAqC,CAAC;AAElE;;;GAGG"}
package/dist/debug.js ADDED
@@ -0,0 +1,21 @@
1
+ import { createDebugLogger } from '@arki/log/debug';
2
+ /**
3
+ * Debug logger for database initialization and connection operations
4
+ * Enable with: DEBUG=db:init
5
+ */
6
+ export const debugInit = createDebugLogger('db:init');
7
+ /**
8
+ * Debug logger for database factory operations
9
+ * Enable with: DEBUG=db:factory
10
+ */
11
+ export const debugFactory = createDebugLogger('db:factory');
12
+ /**
13
+ * Debug logger for projection builder operations
14
+ * Enable with: DEBUG=db:projection
15
+ */
16
+ export const debugProjection = createDebugLogger('db:projection');
17
+ /**
18
+ * Enable all database debug logs
19
+ * Enable with: DEBUG=db:*
20
+ */
21
+ //# sourceMappingURL=debug.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debug.js","sourceRoot":"","sources":["../src/debug.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEpD;;;GAGG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;AAEtD;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,iBAAiB,CAAC,YAAY,CAAC,CAAC;AAE5D;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,iBAAiB,CAAC,eAAe,CAAC,CAAC;AAElE;;;GAGG"}
package/dist/dot.d.ts ADDED
@@ -0,0 +1,87 @@
1
+ /**
2
+ * DOT adapter for `@arki/db`.
3
+ *
4
+ * Wraps the Drizzle database initialization as a `DotPip`. The pip
5
+ * opens a database connection in `boot`, publishes the Drizzle handle as
6
+ * `services.db`, and tears down the underlying client in `dispose`
7
+ * (reverse-topological order).
8
+ *
9
+ * Two drivers are supported:
10
+ * - `'pg'` (default) — `node-postgres` pool. Reads `DB_URL` and the
11
+ * `DB_POOL_*` env vars via `@arki/db`'s built-in env loader.
12
+ * - `'pglite'` — embedded PGlite. Pass `dataDir`, or `memory: true` for
13
+ * an in-memory instance. Use for tests, single-binary apps, or local
14
+ * development without a real Postgres server.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * import { defineApp } from '@arki/dot';
19
+ * import { db } from '@arki/db/dot';
20
+ * import { defineRelations } from '@arki/db/orm';
21
+ * import { schema } from './schema';
22
+ *
23
+ * const relations = defineRelations(schema, (b) => ({ ... }));
24
+ *
25
+ * // Node-postgres (default), reads DB_URL from env:
26
+ * const app = await defineApp('my-app')
27
+ * .use(db({ relations }))
28
+ * .boot();
29
+ *
30
+ * // PGlite in-memory (great for tests):
31
+ * const testApp = await defineApp('test')
32
+ * .use(db({ driver: 'pglite', memory: true, relations }))
33
+ * .boot();
34
+ * ```
35
+ *
36
+ * The `@arki/dot` package is an OPTIONAL peer of `@arki/db`. Importing
37
+ * this adapter without `@arki/dot` installed will fail at module load —
38
+ * that is intentional: the adapter only makes sense in a DOT app.
39
+ */
40
+ import type { AnyRelations, Logger } from 'drizzle-orm';
41
+ import type { NodePgDatabase } from 'drizzle-orm/node-postgres';
42
+ import type { PgliteDatabase } from 'drizzle-orm/pglite';
43
+ import { type DotPip } from '@arki/dot/pip';
44
+ import { type PgliteInitOptions } from './runtime-local.js';
45
+ /**
46
+ * Common options shared by all DB driver variants.
47
+ */
48
+ type BaseDbDotOptions<TRelations extends AnyRelations> = {
49
+ /** Drizzle 1.0 relations config (build via `defineRelations`). */
50
+ readonly relations: TRelations;
51
+ /** Drizzle logger override — `true`/`false` or a custom `Logger` instance. */
52
+ readonly logger?: boolean | Logger;
53
+ /**
54
+ * Pip name override. Defaults to `'db'`. Use this only when composing
55
+ * multiple database scopes inside the same app (e.g. primary + reporting).
56
+ */
57
+ readonly name?: string;
58
+ };
59
+ /** Options for the node-postgres driver (the default). */
60
+ export type PgDbDotOptions<TRelations extends AnyRelations> = BaseDbDotOptions<TRelations> & {
61
+ /** Driver discriminant. Defaults to `'pg'` when omitted. */
62
+ readonly driver?: 'pg';
63
+ };
64
+ /** Options for the embedded-PGlite driver. */
65
+ export type PgliteDbDotOptions<TRelations extends AnyRelations> = BaseDbDotOptions<TRelations> & PgliteInitOptions & {
66
+ /** Driver discriminant. */
67
+ readonly driver: 'pglite';
68
+ };
69
+ /** Discriminated union of all supported driver option shapes. */
70
+ export type DbDotOptions<TRelations extends AnyRelations> = PgDbDotOptions<TRelations> | PgliteDbDotOptions<TRelations>;
71
+ /**
72
+ * Services published by the db adapter. Keyed by the driver — for the
73
+ * default `'pg'` driver, `services.db` is a `NodePgDatabase<TRelations>`;
74
+ * for `'pglite'` it is a `PgliteDatabase<TRelations>`.
75
+ */
76
+ export type DbServices<TRelations extends AnyRelations, TDriver extends 'pg' | 'pglite' = 'pg'> = {
77
+ readonly db: TDriver extends 'pglite' ? PgliteDatabase<TRelations> : NodePgDatabase<TRelations>;
78
+ };
79
+ /**
80
+ * Build a DOT pip that opens a Drizzle database and publishes it as
81
+ * a service. The kernel calls `dispose` in reverse-topological order to
82
+ * close the underlying pool / PGlite instance.
83
+ */
84
+ export declare function db<TRelations extends AnyRelations>(options: PgDbDotOptions<TRelations>): DotPip<DbServices<TRelations, 'pg'>>;
85
+ export declare function db<TRelations extends AnyRelations>(options: PgliteDbDotOptions<TRelations>): DotPip<DbServices<TRelations, 'pglite'>>;
86
+ export {};
87
+ //# sourceMappingURL=dot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dot.d.ts","sourceRoot":"","sources":["../src/dot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,eAAe,CAAC;AAG1D,OAAO,EAAsB,KAAK,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAEhF;;GAEG;AACH,KAAK,gBAAgB,CAAC,UAAU,SAAS,YAAY,IAAI;IACvD,kEAAkE;IAClE,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAC;IAC/B,8EAA8E;IAC9E,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACnC;;;OAGG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,0DAA0D;AAC1D,MAAM,MAAM,cAAc,CAAC,UAAU,SAAS,YAAY,IACtD,gBAAgB,CAAC,UAAU,CAAC,GAC5B;IACA,4DAA4D;IAC5D,QAAQ,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC;CACxB,CAAC;AAEJ,8CAA8C;AAC9C,MAAM,MAAM,kBAAkB,CAAC,UAAU,SAAS,YAAY,IAC1D,gBAAgB,CAAC,UAAU,CAAC,GAC5B,iBAAiB,GACjB;IACA,2BAA2B;IAC3B,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;CAC3B,CAAC;AAEJ,iEAAiE;AACjE,MAAM,MAAM,YAAY,CAAC,UAAU,SAAS,YAAY,IACpD,cAAc,CAAC,UAAU,CAAC,GAC1B,kBAAkB,CAAC,UAAU,CAAC,CAAC;AAEnC;;;;GAIG;AACH,MAAM,MAAM,UAAU,CACpB,UAAU,SAAS,YAAY,EAC/B,OAAO,SAAS,IAAI,GAAG,QAAQ,GAAG,IAAI,IACpC;IACF,QAAQ,CAAC,EAAE,EAAE,OAAO,SAAS,QAAQ,GAAG,cAAc,CAAC,UAAU,CAAC,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;CACjG,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,EAAE,CAAC,UAAU,SAAS,YAAY,EAChD,OAAO,EAAE,cAAc,CAAC,UAAU,CAAC,GAClC,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,CAAC;AACxC,wBAAgB,EAAE,CAAC,UAAU,SAAS,YAAY,EAChD,OAAO,EAAE,kBAAkB,CAAC,UAAU,CAAC,GACtC,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC"}
package/dist/dot.js ADDED
@@ -0,0 +1,104 @@
1
+ /**
2
+ * DOT adapter for `@arki/db`.
3
+ *
4
+ * Wraps the Drizzle database initialization as a `DotPip`. The pip
5
+ * opens a database connection in `boot`, publishes the Drizzle handle as
6
+ * `services.db`, and tears down the underlying client in `dispose`
7
+ * (reverse-topological order).
8
+ *
9
+ * Two drivers are supported:
10
+ * - `'pg'` (default) — `node-postgres` pool. Reads `DB_URL` and the
11
+ * `DB_POOL_*` env vars via `@arki/db`'s built-in env loader.
12
+ * - `'pglite'` — embedded PGlite. Pass `dataDir`, or `memory: true` for
13
+ * an in-memory instance. Use for tests, single-binary apps, or local
14
+ * development without a real Postgres server.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * import { defineApp } from '@arki/dot';
19
+ * import { db } from '@arki/db/dot';
20
+ * import { defineRelations } from '@arki/db/orm';
21
+ * import { schema } from './schema';
22
+ *
23
+ * const relations = defineRelations(schema, (b) => ({ ... }));
24
+ *
25
+ * // Node-postgres (default), reads DB_URL from env:
26
+ * const app = await defineApp('my-app')
27
+ * .use(db({ relations }))
28
+ * .boot();
29
+ *
30
+ * // PGlite in-memory (great for tests):
31
+ * const testApp = await defineApp('test')
32
+ * .use(db({ driver: 'pglite', memory: true, relations }))
33
+ * .boot();
34
+ * ```
35
+ *
36
+ * The `@arki/dot` package is an OPTIONAL peer of `@arki/db`. Importing
37
+ * this adapter without `@arki/dot` installed will fail at module load —
38
+ * that is intentional: the adapter only makes sense in a DOT app.
39
+ */
40
+ import { defineDotPip } from '@arki/dot/pip';
41
+ import { createDb } from './factory.js';
42
+ import { initDbRuntimeLocal } from './runtime-local.js';
43
+ export function db(options) {
44
+ const name = options.name ?? 'db';
45
+ const driver = options.driver ?? 'pg';
46
+ if (driver === 'pglite') {
47
+ const pgliteOptions = options;
48
+ // PGlite path: open the embedded instance and Drizzle handle in boot.
49
+ // We capture the raw PGlite client at boot-time so `dispose` can close
50
+ // it deterministically. `services.db` is the Drizzle handle only —
51
+ // exposing the PGlite client would leak driver-specific surface.
52
+ let pgliteHandle;
53
+ return defineDotPip({
54
+ name,
55
+ version: '0.1.0',
56
+ provides: ['db'],
57
+ configure(ctx) {
58
+ ctx.registerService('db', 'db');
59
+ },
60
+ async boot() {
61
+ const { db: handle, pglite } = await initDbRuntimeLocal({
62
+ ...(pgliteOptions.dataDir !== undefined ? { dataDir: pgliteOptions.dataDir } : {}),
63
+ ...(pgliteOptions.memory !== undefined ? { memory: pgliteOptions.memory } : {}),
64
+ ...(pgliteOptions.extensions !== undefined ? { extensions: pgliteOptions.extensions } : {}),
65
+ }, { relations: pgliteOptions.relations });
66
+ pgliteHandle = pglite;
67
+ return { services: { db: handle } };
68
+ },
69
+ async dispose() {
70
+ if (pgliteHandle !== undefined) {
71
+ await pgliteHandle.close();
72
+ pgliteHandle = undefined;
73
+ }
74
+ },
75
+ });
76
+ }
77
+ // Node-postgres path: createDb already reads env vars and constructs the
78
+ // pool. Drizzle owns the pool — closing it goes via the `$client.end()`
79
+ // path that node-postgres exposes through Drizzle's handle.
80
+ return defineDotPip({
81
+ name,
82
+ version: '0.1.0',
83
+ provides: ['db'],
84
+ configure(ctx) {
85
+ ctx.registerService('db', 'db');
86
+ },
87
+ boot() {
88
+ const handle = createDb({
89
+ relations: options.relations,
90
+ ...(options.logger !== undefined ? { logger: options.logger } : {}),
91
+ });
92
+ return { services: { db: handle } };
93
+ },
94
+ async dispose({ services }) {
95
+ // Drizzle exposes the underlying pg.Pool as `$client`. We call its
96
+ // `end()` to drain in-flight queries and close all sockets.
97
+ const pgHandle = services.db;
98
+ if (pgHandle.$client !== undefined) {
99
+ await pgHandle.$client.end();
100
+ }
101
+ },
102
+ });
103
+ }
104
+ //# sourceMappingURL=dot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dot.js","sourceRoot":"","sources":["../src/dot.ts"],"names":[],"mappings":"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"}
package/dist/env.d.ts ADDED
@@ -0,0 +1,23 @@
1
+ export declare const env: Readonly<{
2
+ PGUSER?: string | undefined;
3
+ PGPASSWORD?: string | undefined;
4
+ PGDATABASE?: string | undefined;
5
+ NODE_ENV: "development" | "production" | "test";
6
+ DB_URL: string;
7
+ PGHOST: string;
8
+ PGPORT: number;
9
+ PGSSLMODE: "disable" | "allow" | "prefer" | "require" | "verify-ca" | "verify-full";
10
+ DB_POOL_MIN: number;
11
+ DB_POOL_MAX: number;
12
+ DB_POOL_IDLE_TIMEOUT: number;
13
+ DB_POOL_CONNECTION_TIMEOUT: number;
14
+ DB_LOGGING: boolean;
15
+ DB_MIGRATIONS_FOLDER: string;
16
+ DB_SCHEMA: string;
17
+ DB_STATEMENT_TIMEOUT: number;
18
+ DB_QUERY_TIMEOUT: number;
19
+ DB_IDLE_IN_TRANSACTION_SESSION_TIMEOUT: number;
20
+ DB_SEED_ON_START: boolean;
21
+ DB_DROP_ON_START: boolean;
22
+ }>;
23
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;EAoFd,CAAC"}
package/dist/env.js ADDED
@@ -0,0 +1,77 @@
1
+ import { createEnv } from '@t3-oss/env-core';
2
+ import { z } from '@arki/contracts';
3
+ export const env = createEnv({
4
+ onValidationError(issues) {
5
+ console.error('❌ [@arki/db] Invalid environment variables:\n' +
6
+ issues.map(i => ` ${(i.path ?? []).join('.')}: ${i.message}`).join('\n'));
7
+ throw new Error('Invalid environment variables');
8
+ },
9
+ /**
10
+ * Environment variables schema for database services (PostgreSQL)
11
+ */
12
+ server: {
13
+ // General Configuration
14
+ NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),
15
+ // Database Connection - Primary method (connection string)
16
+ // Either DB_URL must be provided (validated after env creation)
17
+ DB_URL: z.url(),
18
+ // Database Connection - Individual parameters (alternative to DB_URL)
19
+ PGUSER: z.string().optional(),
20
+ PGPASSWORD: z.string().optional(),
21
+ PGHOST: z.string().default('localhost'),
22
+ PGPORT: z.coerce.number().default(5432),
23
+ PGDATABASE: z.string().optional(),
24
+ PGSSLMODE: z.enum(['disable', 'allow', 'prefer', 'require', 'verify-ca', 'verify-full']).default('prefer'),
25
+ // Connection Pool Configuration
26
+ DB_POOL_MIN: z.coerce.number().default(2),
27
+ DB_POOL_MAX: z.coerce.number().default(20),
28
+ DB_POOL_IDLE_TIMEOUT: z.coerce.number().default(30_000), // 30 seconds
29
+ DB_POOL_CONNECTION_TIMEOUT: z.coerce.number().default(2000), // 2 seconds
30
+ // Database Behavior Configuration
31
+ DB_LOGGING: z.coerce.boolean().default(false),
32
+ DB_MIGRATIONS_FOLDER: z.string().default('./migrations'),
33
+ DB_SCHEMA: z.string().default('public'),
34
+ // Performance and Reliability
35
+ DB_STATEMENT_TIMEOUT: z.coerce.number().default(30_000), // 30 seconds
36
+ DB_QUERY_TIMEOUT: z.coerce.number().default(60_000), // 1 minute
37
+ DB_IDLE_IN_TRANSACTION_SESSION_TIMEOUT: z.coerce.number().default(10_000), // 10 seconds
38
+ // Development and Testing
39
+ DB_SEED_ON_START: z
40
+ .string()
41
+ .optional()
42
+ .transform(val => val === 'true'),
43
+ DB_DROP_ON_START: z
44
+ .string()
45
+ .optional()
46
+ .transform(val => val === 'true'),
47
+ },
48
+ client: {},
49
+ clientPrefix: '',
50
+ /**
51
+ * Destructure all variables from `process.env` to make sure they aren't tree-shaken away.
52
+ */
53
+ runtimeEnv: {
54
+ NODE_ENV: process.env['NODE_ENV'],
55
+ DB_URL: process.env['DB_URL'],
56
+ PGUSER: process.env['PGUSER'],
57
+ PGPASSWORD: process.env['PGPASSWORD'],
58
+ PGHOST: process.env['PGHOST'],
59
+ PGPORT: process.env['PGPORT'],
60
+ PGDATABASE: process.env['PGDATABASE'],
61
+ PGSSLMODE: process.env['PGSSLMODE'],
62
+ DB_POOL_MIN: process.env['DB_POOL_MIN'],
63
+ DB_POOL_MAX: process.env['DB_POOL_MAX'],
64
+ DB_POOL_IDLE_TIMEOUT: process.env['DB_POOL_IDLE_TIMEOUT'],
65
+ DB_POOL_CONNECTION_TIMEOUT: process.env['DB_POOL_CONNECTION_TIMEOUT'],
66
+ DB_LOGGING: process.env['DB_LOGGING'],
67
+ DB_MIGRATIONS_FOLDER: process.env['DB_MIGRATIONS_FOLDER'],
68
+ DB_SCHEMA: process.env['DB_SCHEMA'],
69
+ DB_STATEMENT_TIMEOUT: process.env['DB_STATEMENT_TIMEOUT'],
70
+ DB_QUERY_TIMEOUT: process.env['DB_QUERY_TIMEOUT'],
71
+ DB_IDLE_IN_TRANSACTION_SESSION_TIMEOUT: process.env['DB_IDLE_IN_TRANSACTION_SESSION_TIMEOUT'],
72
+ DB_SEED_ON_START: process.env['DB_SEED_ON_START'],
73
+ DB_DROP_ON_START: process.env['DB_DROP_ON_START'],
74
+ },
75
+ skipValidation: !!process.env['SKIP_ENV_VALIDATION'] || !!process.env['CI'] || process.env['NODE_ENV'] === 'test',
76
+ });
77
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { AnyRelations, Logger } from 'drizzle-orm';
2
+ /**
3
+ * Create a database connection using environment configuration.
4
+ *
5
+ * `relations` is required (mark the field even when empty) so TypeScript can
6
+ * infer the precise relations type for `db.query.*` autocomplete. Use
7
+ * `defineRelations(schema, callback)` to build the value.
8
+ *
9
+ * @throws Error if DB_URL is not configured.
10
+ */
11
+ export declare function createDb<TRelations extends AnyRelations>(config: {
12
+ relations: TRelations;
13
+ logger?: boolean | Logger | undefined;
14
+ }): import("drizzle-orm/node-postgres").NodePgDatabase<TRelations> & {
15
+ $client: import("pg").Pool;
16
+ };
17
+ export { getDbConnectionOptions, getDbConnectionParams } from './connection-options.js';
18
+ //# sourceMappingURL=factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAOxD;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,UAAU,SAAS,YAAY,EACtD,MAAM,EAAE;IACN,SAAS,EAAE,UAAU,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;CACvC;;EAwBF;AAED,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC"}
@@ -0,0 +1,31 @@
1
+ import { getDbConnectionOptions } from './connection-options.js';
2
+ import { debugFactory } from './debug.js';
3
+ import { env } from './env.js';
4
+ import { initDbWithOptions } from './init.js';
5
+ /**
6
+ * Create a database connection using environment configuration.
7
+ *
8
+ * `relations` is required (mark the field even when empty) so TypeScript can
9
+ * infer the precise relations type for `db.query.*` autocomplete. Use
10
+ * `defineRelations(schema, callback)` to build the value.
11
+ *
12
+ * @throws Error if DB_URL is not configured.
13
+ */
14
+ export function createDb(config) {
15
+ debugFactory('[factory] Creating database from environment configuration');
16
+ const connectionUrl = env.DB_URL;
17
+ if (!connectionUrl) {
18
+ debugFactory('[factory] Database creation failed: DB_URL not configured');
19
+ throw new Error('Database URL is not configured. Please set DB_URL environment variable.');
20
+ }
21
+ const connectionOptions = getDbConnectionOptions();
22
+ debugFactory('[factory] Connection options (min: %d, max: %d, idleTimeout: %dms, connTimeout: %dms)', connectionOptions.min, connectionOptions.max, connectionOptions.idleTimeoutMillis, connectionOptions.connectionTimeoutMillis);
23
+ const db = initDbWithOptions(connectionOptions, {
24
+ ...config,
25
+ logger: config.logger ?? (env.DB_LOGGING || env.NODE_ENV === 'development'),
26
+ });
27
+ debugFactory('[factory] Database created successfully');
28
+ return db;
29
+ }
30
+ export { getDbConnectionOptions, getDbConnectionParams } from './connection-options.js';
31
+ //# sourceMappingURL=factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.js","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAE9C;;;;;;;;GAQG;AACH,MAAM,UAAU,QAAQ,CACtB,MAGC;IAED,YAAY,CAAC,4DAA4D,CAAC,CAAC;IAE3E,MAAM,aAAa,GAAG,GAAG,CAAC,MAAM,CAAC;IACjC,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,YAAY,CAAC,2DAA2D,CAAC,CAAC;QAC1E,MAAM,IAAI,KAAK,CAAC,yEAAyE,CAAC,CAAC;IAC7F,CAAC;IAED,MAAM,iBAAiB,GAAG,sBAAsB,EAAE,CAAC;IAEnD,YAAY,CAAC,uFAAuF,EAClG,iBAAiB,CAAC,GAAG,EAAE,iBAAiB,CAAC,GAAG,EAC5C,iBAAiB,CAAC,iBAAiB,EAAE,iBAAiB,CAAC,uBAAuB,CAAC,CAAC;IAElF,MAAM,EAAE,GAAG,iBAAiB,CAAa,iBAAiB,EAAE;QAC1D,GAAG,MAAM;QACT,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,QAAQ,KAAK,aAAa,CAAC;KAC5E,CAAC,CAAC;IAEH,YAAY,CAAC,yCAAyC,CAAC,CAAC;IAExD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC"}
@@ -0,0 +1,85 @@
1
+ import type { PgColumn } from 'drizzle-orm/pg-core';
2
+ import { z } from '@arki/contracts';
3
+ export declare const createId: () => string;
4
+ export declare const createPrefixedId: <T extends string>(prefix: T) => `${T}${string}`;
5
+ /**
6
+ * Type-safe ID factory that generates all ID-related utilities at once
7
+ *
8
+ * @param prefix - The prefix for the ID type (e.g., 'pt', 'usr', 'ant')
9
+ * @returns An object with create function, schema, and column helpers
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * export type PoetId = `pt${string}`;
14
+ * const poetId = createIdFactory<'pt', PoetId>('pt');
15
+ *
16
+ * export const createPoetId = poetId.create;
17
+ * export const poetIdSchema = poetId.schema;
18
+ *
19
+ * export const poets = schema.table('poets', {
20
+ * id: poetId.primaryColumn(),
21
+ * // ... other columns
22
+ * });
23
+ * ```
24
+ */
25
+ export declare function createIdFactory<TPrefix extends string, TId extends `${TPrefix}${string}`>(prefix: TPrefix): {
26
+ /**
27
+ * Creates a new ID with the specified prefix
28
+ */
29
+ create: () => TId;
30
+ /**
31
+ * Creates a new ID with the specified prefix
32
+ */
33
+ make: () => TId;
34
+ /**
35
+ * Creates a new ID with the specified prefix
36
+ */
37
+ new: () => TId;
38
+ schema: z.ZodPipe<z.ZodString, z.ZodTransform<Awaited<TId>, string>> | z.ZodPipe<z.core.$ZodBranded<z.ZodString, TId, "out">, z.ZodTransform<Awaited<TId>, string & z.core.$brand<TId>>>;
39
+ /**
40
+ * Drizzle column helper for primary key columns
41
+ * Automatically configures as varchar(256), not null, primary key, with proper type and default
42
+ */
43
+ primaryColumn: (name?: string) => import("drizzle-orm/pg-core").SetHasRuntimeDefault<import("drizzle-orm/pg-core").Set$Type<import("drizzle-orm/pg-core").SetIsPrimaryKey<import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").PgVarcharBuilder<[string, ...string[]]>>>, TId>>;
44
+ optionalColumn: (name: string) => import("drizzle-orm/pg-core").SetHasRuntimeDefault<import("drizzle-orm/pg-core").Set$Type<import("drizzle-orm/pg-core").PgVarcharBuilder<[string, ...string[]]>, TId | null>>;
45
+ requiredColumn: (name: string) => import("drizzle-orm/pg-core").SetHasRuntimeDefault<import("drizzle-orm/pg-core").Set$Type<import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").PgVarcharBuilder<[string, ...string[]]>>, TId>>;
46
+ /**
47
+ * Drizzle column helper for foreign key reference columns
48
+ * Configures as varchar(256), not null, with proper type (no default or primary key)
49
+ */
50
+ reference: (name: string) => import("drizzle-orm/pg-core").Set$Type<import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").PgVarcharBuilder<[string, ...string[]]>>, TId>;
51
+ /**
52
+ * Drizzle column helper for optional foreign key reference columns
53
+ * Configures as varchar(256), nullable, with proper type
54
+ */
55
+ optionalReference: (name: string) => import("drizzle-orm/pg-core").Set$Type<import("drizzle-orm/pg-core").PgVarcharBuilder<[string, ...string[]]>, TId>;
56
+ /**
57
+ * Drizzle column helper for foreign key reference with relation
58
+ * Configures as varchar(256), not null, with proper type and foreign key constraint
59
+ */
60
+ foreignKey: (name: string, referenceFn: () => PgColumn, options?: {
61
+ onDelete?: "cascade" | "restrict" | "no action" | "set null" | "set default";
62
+ }) => import("drizzle-orm/pg-core").Set$Type<import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").PgVarcharBuilder<[string, ...string[]]>>, TId>;
63
+ /**
64
+ * Drizzle column helper for optional foreign key reference with relation
65
+ * Configures as varchar(256), nullable, with proper type and foreign key constraint
66
+ */
67
+ optionalForeignKey: (name: string, referenceFn: () => PgColumn, options?: {
68
+ onDelete?: "cascade" | "restrict" | "no action" | "set null" | "set default";
69
+ }) => import("drizzle-orm/pg-core").Set$Type<import("drizzle-orm/pg-core").PgVarcharBuilder<[string, ...string[]]>, TId>;
70
+ /**
71
+ * Creates a foreign key factory bound to a specific table
72
+ * This allows creating multiple foreign keys to the same table without repeating the reference
73
+ */
74
+ createForeignKeyFactory: (referenceFn: () => PgColumn) => {
75
+ required: (name: string, options?: {
76
+ onDelete?: "cascade" | "restrict" | "no action" | "set null" | "set default";
77
+ }) => import("drizzle-orm/pg-core").Set$Type<import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").PgVarcharBuilder<[string, ...string[]]>>, TId>;
78
+ optional: (name: string, options?: {
79
+ onDelete?: "cascade" | "restrict" | "no action" | "set null" | "set default";
80
+ }) => import("drizzle-orm/pg-core").Set$Type<import("drizzle-orm/pg-core").PgVarcharBuilder<[string, ...string[]]>, TId>;
81
+ };
82
+ };
83
+ export * from 'drizzle-orm';
84
+ export { createInsertSchema, createSelectSchema, createSchemaFactory, createUpdateSchema } from 'drizzle-orm/zod';
85
+ //# sourceMappingURL=id-factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"id-factory.d.ts","sourceRoot":"","sources":["../src/id-factory.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAGpD,OAAO,EAAqB,CAAC,EAAE,MAAM,iBAAiB,CAAC;AAGvD,eAAO,MAAM,QAAQ,cAAqB,CAAC;AAE3C,eAAO,MAAM,gBAAgB,GAAI,CAAC,SAAS,MAAM,EAAE,QAAQ,CAAC,KAAG,GAAG,CAAC,GAAG,MAAM,EAE3E,CAAC;AAkBF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,eAAe,CAAC,OAAO,SAAS,MAAM,EAAE,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,EAAE,EAAE,MAAM,EAAE,OAAO;IAatG;;OAEG;kBACS,GAAG;IACf;;OAEG;gBACO,GAAG;IACb;;OAEG;eACM,GAAG;;IAIZ;;;OAGG;;2BAWoB,MAAM;2BAQN,MAAM;IAS7B;;;OAGG;sBACe,MAAM;IAGxB;;;OAGG;8BACuB,MAAM;IAGhC;;;OAGG;uBAEK,MAAM,eACC,MAAM,QAAQ,YACjB;QAAE,QAAQ,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,WAAW,GAAG,UAAU,GAAG,aAAa,CAAA;KAAE;IAO5F;;;OAGG;+BAEK,MAAM,eACC,MAAM,QAAQ,YACjB;QAAE,QAAQ,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,WAAW,GAAG,UAAU,GAAG,aAAa,CAAA;KAAE;IAO5F;;;OAGG;2CACoC,MAAM,QAAQ;yBAE3C,MAAM,YACF;YAAE,QAAQ,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,WAAW,GAAG,UAAU,GAAG,aAAa,CAAA;SAAE;yBAGpF,MAAM,YACF;YAAE,QAAQ,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,WAAW,GAAG,UAAU,GAAG,aAAa,CAAA;SAAE;;EAMjG;AAGD,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,119 @@
1
+ import { createId as createCuid } from '@paralleldrive/cuid2';
2
+ import { varchar } from 'drizzle-orm/pg-core';
3
+ import { COLUMN_ZOD_SCHEMA, z } from '@arki/contracts';
4
+ // Core ID creation
5
+ export const createId = () => createCuid();
6
+ export const createPrefixedId = (prefix) => {
7
+ return `${prefix}${createId()}`;
8
+ };
9
+ /**
10
+ * Stash a Zod schema on a Drizzle column builder so that
11
+ * `@arki/contracts`'s `createSelectSchema`/`createInsertSchema`/`createUpdateSchema`
12
+ * wrappers auto-apply it as a refine — turning the brand from a phantom-only
13
+ * type into a real runtime check.
14
+ *
15
+ * The builder's `config` object is the SAME reference passed to the constructed
16
+ * column (see `PgVarcharBuilder.build` → `new PgVarchar(table, this.config)`),
17
+ * so writing here is readable from the column later.
18
+ */
19
+ function tagColumnSchema(builder, schema) {
20
+ const cfg = builder.config;
21
+ cfg[COLUMN_ZOD_SCHEMA] = schema;
22
+ return builder;
23
+ }
24
+ /**
25
+ * Type-safe ID factory that generates all ID-related utilities at once
26
+ *
27
+ * @param prefix - The prefix for the ID type (e.g., 'pt', 'usr', 'ant')
28
+ * @returns An object with create function, schema, and column helpers
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * export type PoetId = `pt${string}`;
33
+ * const poetId = createIdFactory<'pt', PoetId>('pt');
34
+ *
35
+ * export const createPoetId = poetId.create;
36
+ * export const poetIdSchema = poetId.schema;
37
+ *
38
+ * export const poets = schema.table('poets', {
39
+ * id: poetId.primaryColumn(),
40
+ * // ... other columns
41
+ * });
42
+ * ```
43
+ */
44
+ export function createIdFactory(prefix) {
45
+ /**
46
+ * Zod validation schema for the ID type. Uses refine instead of transform
47
+ * for better type safety; auto-applied at parse time by @arki/contracts'
48
+ * schema wrappers when this factory's columns appear on the table.
49
+ */
50
+ const schema = z
51
+ .string()
52
+ .startsWith(prefix)
53
+ .brand()
54
+ .transform(id => id);
55
+ const factory = {
56
+ /**
57
+ * Creates a new ID with the specified prefix
58
+ */
59
+ create: () => createPrefixedId(prefix),
60
+ /**
61
+ * Creates a new ID with the specified prefix
62
+ */
63
+ make: () => createPrefixedId(prefix),
64
+ /**
65
+ * Creates a new ID with the specified prefix
66
+ */
67
+ new: () => createPrefixedId(prefix),
68
+ schema,
69
+ /**
70
+ * Drizzle column helper for primary key columns
71
+ * Automatically configures as varchar(256), not null, primary key, with proper type and default
72
+ */
73
+ primaryColumn: (name = 'id') => tagColumnSchema(varchar(name, { length: 256 })
74
+ .notNull()
75
+ .primaryKey()
76
+ .$type()
77
+ .$defaultFn(() => createPrefixedId(prefix)), schema),
78
+ optionalColumn: (name) => tagColumnSchema(varchar(name, { length: 256 })
79
+ .$type()
80
+ .$defaultFn(() => null), schema),
81
+ requiredColumn: (name) => tagColumnSchema(varchar(name, { length: 256 })
82
+ .notNull()
83
+ .$type()
84
+ .$defaultFn(() => createPrefixedId(prefix)), schema),
85
+ /**
86
+ * Drizzle column helper for foreign key reference columns
87
+ * Configures as varchar(256), not null, with proper type (no default or primary key)
88
+ */
89
+ reference: (name) => tagColumnSchema(varchar(name, { length: 256 }).notNull().$type(), schema),
90
+ /**
91
+ * Drizzle column helper for optional foreign key reference columns
92
+ * Configures as varchar(256), nullable, with proper type
93
+ */
94
+ optionalReference: (name) => tagColumnSchema(varchar(name, { length: 256 }).$type(), schema),
95
+ /**
96
+ * Drizzle column helper for foreign key reference with relation
97
+ * Configures as varchar(256), not null, with proper type and foreign key constraint
98
+ */
99
+ foreignKey: (name, referenceFn, options) => tagColumnSchema(varchar(name, { length: 256 }).notNull().$type().references(referenceFn, options), schema),
100
+ /**
101
+ * Drizzle column helper for optional foreign key reference with relation
102
+ * Configures as varchar(256), nullable, with proper type and foreign key constraint
103
+ */
104
+ optionalForeignKey: (name, referenceFn, options) => tagColumnSchema(varchar(name, { length: 256 }).$type().references(referenceFn, options), schema),
105
+ /**
106
+ * Creates a foreign key factory bound to a specific table
107
+ * This allows creating multiple foreign keys to the same table without repeating the reference
108
+ */
109
+ createForeignKeyFactory: (referenceFn) => ({
110
+ required: (name, options) => factory.foreignKey(name, referenceFn, options),
111
+ optional: (name, options) => factory.optionalForeignKey(name, referenceFn, options),
112
+ }),
113
+ };
114
+ return factory;
115
+ }
116
+ // Re-export drizzle and zod utilities
117
+ export * from 'drizzle-orm';
118
+ export { createInsertSchema, createSelectSchema, createSchemaFactory, createUpdateSchema } from 'drizzle-orm/zod';
119
+ //# sourceMappingURL=id-factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"id-factory.js","sourceRoot":"","sources":["../src/id-factory.ts"],"names":[],"mappings":"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"}
package/dist/id.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ export declare const createId: () => string;
2
+ export declare const createPrefixedId: <T extends string>(prefix: T) => `${T}${string}`;
3
+ export * from './id-factory.js';
4
+ //# sourceMappingURL=id.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"id.d.ts","sourceRoot":"","sources":["../src/id.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,QAAQ,cAEpB,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,CAAC,SAAS,MAAM,EAAE,QAAQ,CAAC,KAAG,GAAG,CAAC,GAAG,MAAM,EAE3E,CAAC;AAGF,cAAc,iBAAiB,CAAC"}
package/dist/id.js ADDED
@@ -0,0 +1,10 @@
1
+ import { createId as createCuid } from '@paralleldrive/cuid2';
2
+ export const createId = () => {
3
+ return createCuid();
4
+ };
5
+ export const createPrefixedId = (prefix) => {
6
+ return `${prefix}${createId()}`;
7
+ };
8
+ // Re-export the new ID factory
9
+ export * from './id-factory.js';
10
+ //# sourceMappingURL=id.js.map