@stacksjs/database 0.70.37 → 0.70.39

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.
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Create all authentication tables
3
+ */
4
+ export declare function migrateAuthTables(options?: { verbose?: boolean }): Promise<{ success: boolean, error?: string }>;
@@ -0,0 +1,16 @@
1
+ /*.ts`; an explicit `--class` filters to one.
2
+ */
3
+ export declare function runClassSeeders(options?: RunOptions): Promise<{ ran: string[], skipped: string[] }>;
4
+ declare interface RunOptions {
5
+ class?: string
6
+ dir?: string
7
+ }
8
+ /**
9
+ * Base class for class-based seeders. Subclass this and implement
10
+ * `async run()`. Seeders may call `this.call()` to invoke other
11
+ * seeders, mirroring Laravel's nested-seeder pattern.
12
+ */
13
+ export declare abstract class Seeder {
14
+ abstract run(): Promise<void> | void;
15
+ protected call(other: new () => Seeder): Promise<void>;
16
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Create the `model_audits` table used by the `useAudit` ORM trait.
3
+ *
4
+ * The trait writes one row per create/update/delete on any model that
5
+ * declares `traits: { useAudit: true }`. The schema is intentionally
6
+ * polymorphic — `auditable_type` + `auditable_id` rather than per-table
7
+ * audit columns — so adding the trait to a new model never requires a
8
+ * follow-up migration.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * import { createModelAuditsTable } from '@stacksjs/database'
13
+ * await createModelAuditsTable() // idempotent — checks before writing
14
+ * ```
15
+ */
16
+ export declare function createModelAuditsTable(): Promise<void>;
@@ -0,0 +1 @@
1
+ export declare function createErrorsTable(): Promise<void>;
@@ -0,0 +1,3 @@
1
+ export * from './audits';
2
+ export * from './errors';
3
+ export * from './jobs';
@@ -0,0 +1,3 @@
1
+ import type { MigrationResult } from '../migrations';
2
+ import type { Result } from '@stacksjs/error-handling';
3
+ export declare function createJobsMigration(): Promise<Result<MigrationResult[] | string, Error>>;
@@ -0,0 +1,87 @@
1
+ import type { QueryBuilder, QueryBuilderConfig, SupportedDialect } from 'bun-query-builder';
2
+ /**
3
+ * Create a database connection with the given options
4
+ */
5
+ export declare function createDatabase(options: DatabaseOptions): Database;
6
+ /**
7
+ * Create a SQLite database connection
8
+ */
9
+ export declare function createSqliteDatabase(database: string, options?: Partial<Omit<DatabaseOptions, 'driver' | 'connection'>>): Database;
10
+ /**
11
+ * Create a PostgreSQL database connection
12
+ */
13
+ export declare function createPostgresDatabase(connection: DatabaseConnectionConfig, options?: Partial<Omit<DatabaseOptions, 'driver' | 'connection'>>): Database;
14
+ /**
15
+ * Create a MySQL database connection
16
+ */
17
+ export declare function createMysqlDatabase(connection: DatabaseConnectionConfig, options?: Partial<Omit<DatabaseOptions, 'driver' | 'connection'>>): Database;
18
+ export declare interface DatabaseConnectionConfig {
19
+ database: string
20
+ host?: string
21
+ port?: number
22
+ username?: string
23
+ password?: string
24
+ url?: string
25
+ }
26
+ export declare interface DatabaseOptions {
27
+ driver: SupportedDialect
28
+ connection: DatabaseConnectionConfig
29
+ verbose?: boolean
30
+ timestamps?: {
31
+ createdAt?: string
32
+ updatedAt?: string
33
+ defaultOrderColumn?: string
34
+ }
35
+ softDeletes?: {
36
+ enabled?: boolean
37
+ column?: string
38
+ defaultFilter?: boolean
39
+ }
40
+ hooks?: QueryBuilderConfig['hooks']
41
+ }
42
+ /**
43
+ * Database class for managing database connections
44
+ *
45
+ * @example
46
+ * ```ts
47
+ * // Initialize with SQLite
48
+ * const db = new Database({
49
+ * driver: 'sqlite',
50
+ * connection: { database: 'database/app.sqlite' }
51
+ * })
52
+ *
53
+ * // Initialize with PostgreSQL
54
+ * const db = new Database({
55
+ * driver: 'postgres',
56
+ * connection: {
57
+ * database: 'myapp',
58
+ * host: 'localhost',
59
+ * port: 5432,
60
+ * username: 'postgres',
61
+ * password: 'secret'
62
+ * }
63
+ * })
64
+ *
65
+ * // Use the query builder
66
+ * const users = await db.query.selectFrom('users').where('active', '=', true).get()
67
+ * ```
68
+ */
69
+ export declare class Database {
70
+ constructor(options: DatabaseOptions);
71
+ get driver(): SupportedDialect;
72
+ get connection(): DatabaseConnectionConfig;
73
+ get isInitialized(): boolean;
74
+ get query(): QueryBuilder<any>;
75
+ initialize(): void;
76
+ switchDriver(driver: SupportedDialect, connection: DatabaseConnectionConfig): void;
77
+ close(): void;
78
+ static fromConfig(config: {
79
+ default: SupportedDialect
80
+ connections: {
81
+ sqlite?: { database: string }
82
+ mysql?: { name: string, host?: string, port?: number, username?: string, password?: string }
83
+ postgres?: { name: string, host?: string, port?: number, username?: string, password?: string }
84
+ }
85
+ }, env?: string): Database;
86
+ static fromEnv(): Database;
87
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Get default connection config for a given database driver.
3
+ * Reads from the typed env proxy so values are auto-coerced.
4
+ */
5
+ export declare function getConnectionDefaults(driver: string, envProxy?: Record<string, any>): ConnectionDefaults;
6
+ /**
7
+ * Database Defaults & Constants
8
+ *
9
+ * Centralizes all hardcoded default values for database connections
10
+ * so they are defined once and easily discoverable.
11
+ */
12
+ // ============================================================================
13
+ // HOST / PORT DEFAULTS
14
+ // ============================================================================
15
+ export declare const DB_HOST_DEFAULT: '127.0.0.1';
16
+ export declare const DB_PORTS: {
17
+ mysql: 3306;
18
+ postgres: 5432;
19
+ sqlite: 0
20
+ };
21
+ export declare const DB_NAMES: {
22
+ default: 'stacks';
23
+ sqlitePath: 'database/stacks.sqlite';
24
+ sqliteTestingPath: 'database/stacks_testing.sqlite'
25
+ };
26
+ export declare const DB_USERS: {
27
+ mysql: 'root';
28
+ postgres: 'postgres';
29
+ sqlite: ''
30
+ };
31
+ export declare const REDIS_DEFAULTS: {
32
+ host: 'localhost';
33
+ port: 6379
34
+ };
35
+ export declare const AWS_DEFAULTS: {
36
+ region: 'us-east-1'
37
+ };
38
+ // ============================================================================
39
+ // CONNECTION CONFIG BUILDERS
40
+ // ============================================================================
41
+ export declare interface ConnectionDefaults {
42
+ database: string
43
+ host?: string
44
+ port?: number
45
+ username?: string
46
+ password?: string
47
+ prefix?: string
48
+ }
@@ -0,0 +1,120 @@
1
+ import type { SupportedDialect } from 'bun-query-builder';
2
+ /**
3
+ * Get the connection string for a given driver and configuration
4
+ */
5
+ export declare function getConnectionString(driver: SupportedDialect, config: DatabaseConnections[keyof DatabaseConnections]): string;
6
+ /**
7
+ * Validate driver configuration
8
+ */
9
+ export declare function validateDriverConfig(driver: SupportedDialect, config: DatabaseConnections[keyof DatabaseConnections]): { valid: boolean, errors: string[] };
10
+ /**
11
+ * Merge user configuration with defaults
12
+ */
13
+ export declare function mergeWithDefaults<T extends keyof DatabaseConnections>(driver: T, config: Partial<DatabaseConnections[T]>): DatabaseConnections[T];
14
+ /**
15
+ * Get the appropriate configuration for a driver from environment variables
16
+ */
17
+ export declare function getConfigFromEnv(driver: SupportedDialect): DatabaseConnections[keyof DatabaseConnections];
18
+ /**
19
+ * Detect the best available driver based on environment
20
+ */
21
+ export declare function detectDriver(): SupportedDialect;
22
+ /**
23
+ * Default configuration values for each driver
24
+ */
25
+ export declare const driverDefaults: {
26
+ sqlite: {
27
+ database: 'database/stacks.sqlite';
28
+ prefix: ''
29
+ };
30
+ mysql: {
31
+ name: 'stacks';
32
+ host: '127.0.0.1';
33
+ port: 3306;
34
+ username: 'root';
35
+ password: '';
36
+ prefix: '';
37
+ charset: 'utf8mb4';
38
+ collation: 'utf8mb4_unicode_ci'
39
+ };
40
+ postgres: {
41
+ name: 'stacks';
42
+ host: '127.0.0.1';
43
+ port: 5432;
44
+ username: 'postgres';
45
+ password: '';
46
+ prefix: '';
47
+ schema: 'public'
48
+ };
49
+ browser: {}
50
+ };
51
+ /**
52
+ * SQLite specific configuration
53
+ */
54
+ export declare interface SqliteConfig {
55
+ database: string
56
+ prefix?: string
57
+ }
58
+ /**
59
+ * MySQL specific configuration
60
+ */
61
+ export declare interface MysqlConfig {
62
+ name: string
63
+ host?: string
64
+ port?: number
65
+ username?: string
66
+ password?: string
67
+ prefix?: string
68
+ charset?: string
69
+ collation?: string
70
+ }
71
+ /**
72
+ * PostgreSQL specific configuration
73
+ */
74
+ export declare interface PostgresConfig {
75
+ name: string
76
+ host?: string
77
+ port?: number
78
+ username?: string
79
+ password?: string
80
+ prefix?: string
81
+ schema?: string
82
+ sslMode?: 'disable' | 'require' | 'verify-ca' | 'verify-full'
83
+ }
84
+ /**
85
+ * DynamoDB specific configuration
86
+ */
87
+ export declare interface DynamoDbConfig {
88
+ key: string
89
+ secret: string
90
+ region?: string
91
+ prefix?: string
92
+ endpoint?: string
93
+ tableName?: string
94
+ singleTable?: {
95
+ enabled?: boolean
96
+ pkAttribute?: string
97
+ skAttribute?: string
98
+ entityTypeAttribute?: string
99
+ keyDelimiter?: string
100
+ gsiCount?: number
101
+ }
102
+ }
103
+ /**
104
+ * All database connections configuration
105
+ */
106
+ export declare interface DatabaseConnections {
107
+ sqlite?: SqliteConfig
108
+ mysql?: MysqlConfig
109
+ postgres?: PostgresConfig
110
+ dynamodb?: DynamoDbConfig
111
+ }
112
+ /**
113
+ * Full database configuration
114
+ */
115
+ export declare interface FullDatabaseConfig {
116
+ default: SupportedDialect
117
+ connections: DatabaseConnections
118
+ migrations?: string
119
+ migrationLocks?: string
120
+ }
@@ -0,0 +1,2 @@
1
+ export * from './passwords';
2
+ export * from './traits';
@@ -0,0 +1,4 @@
1
+ // SQLite/MySQL version
2
+ export declare function createPasswordResetsTable(): Promise<void>;
3
+ // PostgreSQL version
4
+ export declare function createPostgresPasswordResetsTable(): Promise<void>;
@@ -0,0 +1,33 @@
1
+ // bun-query-builder utilities are used via db.unsafe() for raw SQL
2
+ export declare function getTraitTables(): string[];
3
+ // SQLite/MySQL version
4
+ export declare function createPasskeyMigration(): Promise<void>;
5
+ // PostgreSQL version
6
+ export declare function createPostgresPasskeyMigration(): Promise<void>;
7
+ export declare function createTaggableTable(): Promise<void>;
8
+ export declare function createPostgresTagsTable(): Promise<void>;
9
+ // SQLite/MySQL version
10
+ export declare function createCategorizableTable(): Promise<void>;
11
+ // PostgreSQL version
12
+ export declare function createPostgresCategorizableTable(): Promise<void>;
13
+ // SQLite/MySQL version
14
+ export declare function createCommentablesTable(options?: {
15
+ requiresApproval?: boolean
16
+ reportable?: boolean
17
+ votable?: boolean
18
+ requiresAuth?: boolean
19
+ }): Promise<void>;
20
+ // PostgreSQL version
21
+ export declare function createPostgresCommentsTable(): Promise<void>;
22
+ export declare function dropCommonTables(): Promise<void>;
23
+ export declare function truncateMigrationTables(): Promise<void>;
24
+ export declare function dropMigrationTables(): Promise<void>;
25
+ export declare function createCommentUpvoteMigration(): Promise<void>;
26
+ export declare function createPostgresCommentUpvoteMigration(): Promise<void>;
27
+ export declare function createCommentablesPivotTable(): Promise<void>;
28
+ export declare function createPostgresCommentablesPivotTable(): Promise<void>;
29
+ export declare function createTaggablesTable(): Promise<void>;
30
+ export declare function createPostgresTaggablesTable(): Promise<void>;
31
+ export declare function createQueryLogsTable(): Promise<void>;
32
+ // PostgreSQL version
33
+ export declare function createPostgresQueryLogsTable(): Promise<void>;
@@ -0,0 +1,148 @@
1
+ import type { Model } from '@stacksjs/types';
2
+ /**
3
+ * Marshall a JS object to DynamoDB format
4
+ */
5
+ declare function marshall(obj: Record<string, any>): Record<string, any>;
6
+ /**
7
+ * Unmarshall a DynamoDB object to JS format
8
+ */
9
+ declare function unmarshall(obj: Record<string, any>): Record<string, any>;
10
+ /**
11
+ * Generate key pattern for an entity
12
+ */
13
+ export declare function generateKeyPattern(entityName: string, idField?: string): string;
14
+ /**
15
+ * Parse a key pattern and extract values
16
+ */
17
+ export declare function parseKeyPattern(pattern: string, key: string): Record<string, string>;
18
+ /**
19
+ * Build a key from a pattern and values
20
+ */
21
+ export declare function buildKey(pattern: string, values: Record<string, string>): string;
22
+ /**
23
+ * Create a new DynamoDB client instance
24
+ */
25
+ export declare function createDynamo(): DynamoClient;
26
+ /**
27
+ * DynamoDB client singleton
28
+ */
29
+ export declare const dynamo: DynamoClient;
30
+ /**
31
+ * DynamoDB connection configuration
32
+ */
33
+ export declare interface DynamoConnectionConfig {
34
+ region: string
35
+ table: string
36
+ endpoint?: string
37
+ credentials?: {
38
+ accessKeyId: string
39
+ secretAccessKey: string
40
+ sessionToken?: string
41
+ }
42
+ pkAttribute?: string
43
+ skAttribute?: string
44
+ entityTypeAttribute?: string
45
+ keyDelimiter?: string
46
+ }
47
+ /**
48
+ * Entity mapping for single-table design
49
+ */
50
+ export declare interface SingleTableEntityMapping {
51
+ entityType: string
52
+ pkPattern: string
53
+ skPattern?: string
54
+ gsi1pk?: string
55
+ gsi1sk?: string
56
+ gsi2pk?: string
57
+ gsi2sk?: string
58
+ }
59
+ /**
60
+ * Sort key builder for fluent API
61
+ */
62
+ export declare interface SortKeyBuilder {
63
+ equals(value: string): EntityQueryBuilder
64
+ beginsWith(prefix: string): EntityQueryBuilder
65
+ between(start: string, end: string): EntityQueryBuilder
66
+ lt(value: string): EntityQueryBuilder
67
+ lte(value: string): EntityQueryBuilder
68
+ gt(value: string): EntityQueryBuilder
69
+ gte(value: string): EntityQueryBuilder
70
+ }
71
+ /**
72
+ * Batch write operation
73
+ */
74
+ export declare interface BatchWriteOperation {
75
+ put?: { entity: string, item: Record<string, any> }
76
+ delete?: { entity: string, pk: string, sk: string }
77
+ }
78
+ /**
79
+ * Transact write operation
80
+ */
81
+ export declare interface TransactWriteOperation {
82
+ put?: { entity: string, item: Record<string, any>, condition?: string }
83
+ update?: { entity: string, pk: string, sk?: string, set?: Record<string, any>, add?: Record<string, number>, remove?: string[] }
84
+ delete?: { entity: string, pk: string, sk: string, condition?: string }
85
+ conditionCheck?: { entity: string, pk: string, sk: string, condition: string }
86
+ }
87
+ /**
88
+ * Query result
89
+ */
90
+ export declare interface QueryResult<T = any> {
91
+ items: T[]
92
+ count: number
93
+ scannedCount?: number
94
+ lastKey?: Record<string, any>
95
+ }
96
+ /**
97
+ * Entity-centric query builder for DynamoDB
98
+ */
99
+ export declare class EntityQueryBuilder<T = any> {
100
+ constructor(client: any, tableName: string, config: { pkAttribute: string, skAttribute: string, entityTypeAttribute: string, keyDelimiter: string });
101
+ entity(entityType: string): this;
102
+ pk(value: string): this;
103
+ get sk(): SortKeyBuilder;
104
+ index(indexName: string): this;
105
+ project(...attributes: string[]): this;
106
+ filter(attribute: string, operator: string, value?: any): this;
107
+ where(attribute: string, value: any): this;
108
+ whereIn(attribute: string, values: any[]): this;
109
+ limit(count: number): this;
110
+ asc(): this;
111
+ desc(): this;
112
+ consistent(): this;
113
+ startFrom(key: Record<string, any>): this;
114
+ toRequest(): Record<string, any>;
115
+ get(): Promise<T[]>;
116
+ first(): Promise<T | undefined>;
117
+ getAll(): Promise<T[]>;
118
+ count(): Promise<number>;
119
+ }
120
+ /**
121
+ * DynamoDB client with entity-centric API
122
+ */
123
+ declare class DynamoClient {
124
+ connection(config: DynamoConnectionConfig): this;
125
+ isConfigured(): boolean;
126
+ setClient(client: any): this;
127
+ getClient(): any;
128
+ registerEntity(mapping: SingleTableEntityMapping): this;
129
+ registerModel(model: Model): this;
130
+ getEntityMapping(entityType: string): SingleTableEntityMapping | undefined;
131
+ entity<T = any>(entityType: string): EntityQueryBuilder<T>;
132
+ batchWrite(operations: BatchWriteOperation[]): Promise<void>;
133
+ transactWrite(operations: TransactWriteOperation[]): Promise<void>;
134
+ put(entity: string, item: Record<string, any>): Promise<void>;
135
+ get<T = any>(pk: string, sk?: string): Promise<T | undefined>;
136
+ delete(pk: string, sk?: string): Promise<void>;
137
+ update(pk: string, sk: string | undefined, updates: Record<string, any>): Promise<void>;
138
+ getTableName(): string;
139
+ getConfig(): {
140
+ tableName: string
141
+ pkAttribute: string
142
+ skAttribute: string
143
+ entityTypeAttribute: string
144
+ keyDelimiter: string
145
+ };
146
+ }
147
+ // Export marshall/unmarshall utilities
148
+ export { marshall, unmarshall };
@@ -0,0 +1,29 @@
1
+ import type { Attribute, AttributesElements, Model } from '@stacksjs/types';
2
+ import type { DateValidatorType, EnumValidatorType, NumberValidatorType, StringValidatorType, ValidationType } from '@stacksjs/ts-validation';
3
+ export declare function deleteMigrationFiles(): Promise<void>;
4
+ export declare function deleteFrameworkModels(): Promise<void>;
5
+ export declare function getLastMigrationFields(modelName: string): Promise<AttributesElements>;
6
+ export declare function modelTableName(model: Model | string): Promise<string>;
7
+ export declare function hasTableBeenMigrated(tableName: string): Promise<boolean>;
8
+ export declare function hasMigrationBeenCreated(tableName: string): Promise<boolean>;
9
+ export declare function getExecutedMigrations(): Promise<{ name: string }[]>;
10
+ export declare function prepareTextColumnType(validator: StringValidatorType, driver?: string): string;
11
+ // Add new function for date/time column types
12
+ export declare function prepareDateTimeColumnType(validator: DateValidatorType, driver?: string): string;
13
+ export declare function compareRanges(range1: Range, range2: Range): boolean;
14
+ export declare function checkPivotMigration(dynamicPart: string): Promise<boolean>;
15
+ export declare function pluckChanges(array1: string[], array2: string[]): { added: string[], removed: string[] } | null;
16
+ export declare function arrangeColumns(attributes: AttributesElements | undefined): Array<[string, Attribute]>;
17
+ export declare function isArrayEqual(arr1: (number | undefined)[], arr2: (number | undefined)[]): boolean;
18
+ export declare function findDifferingKeys(obj1: any, obj2: any): { key: string, max: number, min: number }[];
19
+ export declare function fetchTables(): Promise<string[]>;
20
+ export declare function getUpvoteTableName(model: Model, tableName: string): string | undefined;
21
+ export declare function prepareNumberColumnType(validator: NumberValidatorType, driver?: string): string;
22
+ // Add new function for enum column types
23
+ export declare function prepareEnumColumnType(validator: EnumValidatorType, driver?: string): string;
24
+ export declare function mapFieldTypeToColumnType(validator: ValidationType, driver?: string): string;
25
+ export declare function checkIsRequired(rule: string): boolean;
26
+ declare interface Range {
27
+ min: number
28
+ max: number
29
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Drivers — barrel export.
3
+ *
4
+ * Helpers shared across driver implementations live in `./helpers.ts` (NOT
5
+ * inline here) so driver modules can import them without re-importing this
6
+ * barrel and triggering a self-cycle. See `./helpers.ts` for the rationale.
7
+ */
8
+ export * from './helpers';
9
+ export * from './mysql';
10
+ export * from './postgres';
11
+ export * from './sqlite';
12
+ export * from './defaults/index';
13
+ export * from './dynamodb';
@@ -0,0 +1,7 @@
1
+ import type { Ok } from '@stacksjs/error-handling';
2
+ export declare function resetMysqlDatabase(): Promise<Ok<string, never>>;
3
+ export declare function dropMysqlTables(): Promise<void>;
4
+ export declare function generateMysqlMigration(modelPath: string): Promise<void>;
5
+ export declare function generateMysqlTraitMigrations(): Promise<void>;
6
+ export declare function createMysqlForeignKeyMigrations(modelPath: string): Promise<void>;
7
+ export declare function createAlterTableMigration(modelPath: string): Promise<void>;
@@ -0,0 +1,7 @@
1
+ import type { Ok } from '@stacksjs/error-handling';
2
+ export declare function dropPostgresTables(): Promise<void>;
3
+ export declare function generatePostgresTraitMigrations(): Promise<void>;
4
+ export declare function resetPostgresDatabase(): Promise<Ok<string, never>>;
5
+ export declare function generatePostgresMigration(modelPath: string): Promise<void>;
6
+ export declare function createPostgresForeignKeyMigrations(modelPath: string): Promise<void>;
7
+ export declare function fetchPostgresTables(): Promise<string[]>;
@@ -0,0 +1,23 @@
1
+ import type { Ok } from '@stacksjs/error-handling';
2
+ export declare function resetSqliteDatabase(): Promise<Ok<string, never>>;
3
+ /**
4
+ * Configure SQLite for the Stacks workload. Idempotent — the pragmas are
5
+ * cheap to re-apply, but each one is a no-op once set so repeated calls
6
+ * during dev hot-reload don't accumulate state.
7
+ *
8
+ * - WAL journaling: lets readers and a single writer proceed in parallel
9
+ * instead of serializing every transaction. Critical for dev where the
10
+ * API server, queue worker, and dashboard all hit the same file.
11
+ * - foreign_keys=ON: SQLite ships with FK enforcement OFF by default.
12
+ * Without this, FK constraint violations are silently ignored — broken
13
+ * relations land in the DB and fail later, far from the original write.
14
+ * - busy_timeout: backs off when the file is locked by another writer
15
+ * instead of failing the whole query immediately.
16
+ */
17
+ export declare function configureSqlitePragmas(): Promise<void>;
18
+ export declare function dropSqliteTables(): Promise<void>;
19
+ export declare function fetchSqliteFile(): string;
20
+ export declare function fetchTestSqliteFile(): string;
21
+ export declare function generateSqliteMigration(modelPath: string): Promise<void>;
22
+ export declare function createSqliteForeignKeyMigrations(_modelPath: string): Promise<void>;
23
+ export declare function copyModelFiles(modelPath: string): Promise<void>;
@@ -0,0 +1,112 @@
1
+ export type {
2
+ DatabaseConnectionConfig,
3
+ DatabaseOptions,
4
+ } from './database';
5
+ export type {
6
+ DatabaseConnections,
7
+ DynamoDbConfig,
8
+ FullDatabaseConfig,
9
+ MysqlConfig,
10
+ PostgresConfig,
11
+ SqliteConfig,
12
+ } from './driver-config';
13
+ export type {
14
+ QueryBuilder,
15
+ QueryBuilderConfig,
16
+ Seeder as QueryBuilderSeeder,
17
+ SupportedDialect,
18
+ } from 'bun-query-builder';
19
+ export type {
20
+ DynamoConnectionConfig,
21
+ SingleTableEntityMapping,
22
+ SortKeyBuilder,
23
+ BatchWriteOperation,
24
+ TransactWriteOperation,
25
+ QueryResult,
26
+ } from './drivers/dynamodb';
27
+ /**
28
+ * @stacksjs/database
29
+ *
30
+ * Database module powered by bun-query-builder.
31
+ * Provides database initialization, driver configuration, migrations,
32
+ * seeding, and a fluent query builder interface.
33
+ *
34
+ * @example
35
+ * ```ts
36
+ * import { Database, db, createSqliteDatabase } from '@stacksjs/database'
37
+ *
38
+ * // Use the default db instance (configured from environment)
39
+ * const users = await db.selectFrom('users').where('active', '=', true).get()
40
+ *
41
+ * // Or create a custom database instance
42
+ * const customDb = new Database({
43
+ * driver: 'postgres',
44
+ * connection: {
45
+ * database: 'myapp',
46
+ * host: 'localhost',
47
+ * port: 5432,
48
+ * username: 'postgres',
49
+ * password: 'secret'
50
+ * }
51
+ * })
52
+ *
53
+ * // Helper functions for quick setup
54
+ * const sqliteDb = createSqliteDatabase('database/app.sqlite')
55
+ * ```
56
+ */
57
+ // Database initialization and management
58
+ export {
59
+ Database,
60
+ createDatabase,
61
+ createMysqlDatabase,
62
+ createPostgresDatabase,
63
+ createSqliteDatabase,
64
+ } from './database';
65
+ // Driver configuration
66
+ export {
67
+ detectDriver,
68
+ driverDefaults,
69
+ getConfigFromEnv,
70
+ getConnectionString,
71
+ mergeWithDefaults,
72
+ validateDriverConfig,
73
+ } from './driver-config';
74
+ // Core database utilities and default instance
75
+ export * from './utils';
76
+ // Types (compatibility layer for Kysely types)
77
+ export * from './types';
78
+ // Migrations
79
+ export * from './migrations';
80
+ // Query logger DI hook (router calls setQueryTracker on init)
81
+ export { setQueryTracker, logQuery } from './query-logger';
82
+ // Class-based seeders (supplements the model-attribute auto-seeder)
83
+ export { Seeder, runClassSeeders } from './class-seeder';
84
+ // Zero-downtime migration helpers
85
+ export { addColumnSafely, backfillInBatches, renameColumnSafely } from './safe-migrations';
86
+ // Seeding
87
+ export * from './seeder';
88
+ // Driver utilities
89
+ export * from './drivers/index';
90
+ // Custom migrations (jobs, errors, etc.)
91
+ export * from './custom/index';
92
+ // Auth tables migration
93
+ export * from './auth-tables';
94
+ // SQL dialect helpers & connection defaults
95
+ export * from './sql-helpers';
96
+ export * from './defaults';
97
+ // Re-export bun-query-builder functions and types
98
+ export {
99
+ createQueryBuilder,
100
+ setConfig,
101
+ } from 'bun-query-builder';
102
+ // DynamoDB entity-centric API
103
+ export {
104
+ createDynamo,
105
+ dynamo,
106
+ EntityQueryBuilder,
107
+ generateKeyPattern,
108
+ parseKeyPattern,
109
+ buildKey,
110
+ marshall,
111
+ unmarshall,
112
+ } from './drivers/dynamodb';
package/dist/index.js CHANGED
@@ -133,7 +133,7 @@ Or enable auto-install in your mock.config.ts: { autoInstallLocales: true }`)}th
133
133
  )`);let K=O.prepare("INSERT OR IGNORE INTO migrations (migration) VALUES (?)");for(let W of X)K.run(W)}finally{O.close()}}}catch(G){$0.debug(`[migration] Could not record dropped migrations as executed: ${G}`)}}async function uE(){let $=d8();if($==="sqlite")return;let Z=l1.connections[$],X=(Z?.name||"stacks").replace(/['"]/g,""),_=Z?.host||"localhost",Y=Z?.port||($==="postgres"?5432:3306),L=Z?.username||($==="postgres"?process.env.USER||"postgres":"root"),z=Z?.password||"",j=$==="postgres"?"postgres":"mysql";try{d9({dialect:$,database:{database:j,host:_,port:Y,username:L,password:z}}),b1();let U=F9();if($==="postgres")try{await U.unsafe(`CREATE DATABASE "${X}"`),$0.info(`Created database "${X}"`)}catch(Q){if(Q?.message?.includes("already exists")||Q?.errno==="42P04")$0.info(`Database "${X}" already exists`);else throw Q}else if($==="mysql")try{await U.unsafe(`CREATE DATABASE IF NOT EXISTS \`${X}\``),$0.info(`Ensured database "${X}" exists`)}catch(Q){if(Q?.message?.includes("database exists"))$0.info(`Database "${X}" already exists`);else throw Q}b1()}catch(U){$0.warn(`Could not auto-create database "${X}": ${U?.message||U}`),$0.info("If the database already exists, this warning can be ignored."),b1()}}async function oV(){let $=Date.now();try{if($0.info("Migrating database..."),await uE(),c5(),d8()==="sqlite")dE();let Z=v6.userModelsPath();return $0.debug(`[migration] Running migrations from: ${Z}`),await S6(Z),$0.success(`Database migration completed in ${Date.now()-$}ms.`),c8("Database migration completed.")}catch(Z){let X=Z instanceof Error?Z.message:String(Z);return $0.error(`[migration] Failed after ${Date.now()-$}ms: ${X}`),$0.info("[migration] Run `./buddy migrate:fresh` to drop and recreate the schema if state is partial."),f5(g5("Migration failed",Z))}}var mE=["oauth_refresh_tokens","oauth_access_tokens","oauth_clients","passkeys","failed_jobs","jobs","notifications","password_reset_tokens"];async function aV(){try{c5();let $=v6.userModelsPath(),Z=d8();return await sE(Z),await M6($,{dialect:Z}),c8("All tables dropped successfully!")}catch($){return f5(g5("Database reset failed",$))}}async function sE($){if($==="mysql")try{await v.unsafe("SET FOREIGN_KEY_CHECKS = 0").execute()}catch(Z){$0.warn(`Could not disable foreign key checks: ${Z instanceof Error?Z.message:String(Z)}`)}if($==="sqlite")try{await v.unsafe("PRAGMA foreign_keys = OFF").execute()}catch(Z){$0.warn(`Could not disable foreign key checks: ${Z instanceof Error?Z.message:String(Z)}`)}for(let Z of mE)try{let X;if($==="postgres")X=`DROP TABLE IF EXISTS "${Z}" CASCADE`;else if($==="mysql")X=`DROP TABLE IF EXISTS \`${Z}\``;else X=`DROP TABLE IF EXISTS "${Z}"`;$0.info(`Dropping framework table: ${Z}`),await v.unsafe(X).execute(),$0.info(`Dropped framework table: ${Z}`)}catch(X){$0.warn(`Could not drop table ${Z}: ${X instanceof Error?X.message:String(X)}`)}if($==="mysql")try{await v.unsafe("SET FOREIGN_KEY_CHECKS = 1").execute()}catch(Z){$0.warn(`Could not re-enable foreign key checks: ${Z instanceof Error?Z.message:String(Z)}`)}if($==="sqlite")try{await v.unsafe("PRAGMA foreign_keys = ON").execute()}catch(Z){$0.warn(`Could not re-enable foreign key checks: ${Z instanceof Error?Z.message:String(Z)}`)}}async function tV(){try{$0.info("Generating migrations..."),c5();let $=d8(),{modelsDir:Z,skip:X}=p4();if(X)return $0.info("No app/Models directory found; using committed framework migrations"),c8("Migrations generated");$0.debug(`[migration] Generating migrations for dialect: ${$}, models: ${Z}`);let _=await A5(Z,{dialect:$});if(_.hasChanges){let Y=lE(_.sqlStatements??[]);if(Y>0)$0.success(`Migrations generated (${Y} file${Y===1?"":"s"})`);else $0.success("Migrations generated")}else $0.info("No changes detected");return c8("Migrations generated")}catch($){return f5(g5("Migration generation failed",$))}}function lE($){if(!$?.length)return 0;let Z=Q8(process.cwd(),"database","migrations");try{H0("fs").mkdirSync(Z,{recursive:!0})}catch{}let X="";try{for(let U of h6(Z).filter((Q)=>Q.endsWith(".sql")))X+=`
134
134
  ${f4(Q8(Z,U),"utf8")}`}catch{}let _=(U)=>U.replace(/\s+/g," ").trim(),Y=_(X),L=nE($),z=0,j=iE(Z);for(let U of L){let Q=U.statements.filter((O)=>!Y.includes(_(O)));if(Q.length===0)continue;let E=`${String(j).padStart(10,"0")}-${U.label}.sql`,G=Q8(Z,E),F=`${Q.map((O)=>O.trim().replace(/;\s*$/,"")).join(`;
135
135
  `)};
136
- `;g4(G,F),$0.debug(`[migration] Wrote ${E} (${Q.length} stmt${Q.length===1?"":"s"})`),z+=1,j+=1}return z}function nE($){let Z=new Map,X=(_,Y)=>{let L=Z.get(_)??[];L.push(Y),Z.set(_,L)};for(let _ of $){let Y=_.trim();if(!Y)continue;let L=Y.match(/^\s*CREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?["`]?(\w+)["`]?/i);if(L){X(`create-${L[1]}-table`,Y);continue}let z=Y.match(/^\s*ALTER\s+TABLE\s+["`]?(\w+)["`]?\s+(?:ADD\s+COLUMN\s+["`]?(\w+)["`]?|DROP\s+COLUMN\s+["`]?(\w+)["`]?|ADD\s+CONSTRAINT)/i);if(z){X(`alter-${z[1]}-${z[2]||z[3]||"constraint"}`,Y);continue}let j=Y.match(/^\s*CREATE\s+(?:UNIQUE\s+)?INDEX\s+(?:IF\s+NOT\s+EXISTS\s+)?["`]?(\w+)["`]?\s+ON\s+["`]?(\w+)["`]?/i);if(j){X(`create-${j[1]}-index-in-${j[2]}`,Y);continue}let U=Y.match(/^\s*DROP\s+TABLE\s+(?:IF\s+EXISTS\s+)?["`]?(\w+)["`]?/i);if(U){X(`drop-${U[1]}-table`,Y);continue}X("auto-misc",Y)}return[...Z.entries()].map(([_,Y])=>({label:_,statements:Y}))}function iE($){let Z=0;try{for(let X of h6($)){let _=X.match(/^(\d+)-/);if(_)Z=Math.max(Z,Number.parseInt(_[1],10))}}catch{}return Z+1}async function eV(){try{$0.info("Generating fresh migrations..."),c5();let $=d8(),{modelsDir:Z,skip:X}=p4();if(X)return $0.info("No app/Models directory found; using committed framework migrations"),c8("Migrations generated");return await A5(Z,{dialect:$,full:!0}),$0.success("Migrations generated"),c8("Migrations generated")}catch($){return f5(g5("Fresh migration generation failed",$))}}import{memoryUsage as aE}from"process";import{config as Z8}from"@stacksjs/config";import{log as n1}from"@stacksjs/logging";function b6($){let Z={normalized:"",type:"OTHER",tables:[]};if(!$)return Z;try{let X=$.trim().toUpperCase();if(X.startsWith("SELECT"))Z.type="SELECT";else if(X.startsWith("INSERT"))Z.type="INSERT";else if(X.startsWith("UPDATE"))Z.type="UPDATE";else if(X.startsWith("DELETE"))Z.type="DELETE";return Z.tables=rE($,Z.type),Z.normalized=oE($),Z}catch{return{normalized:$,type:"OTHER",tables:[]}}}function rE($,Z){let X=[],_=$.toLowerCase();try{let Y=null,L=null,z=null,j=null,U=null,Q=/join\s+([\w.]+)/gi;switch(Z){case"SELECT":if(Y=_.match(/from\s+([\w.]+)/i),Y&&Y[1])X.push(Y[1].replace(/`/g,"").split(".").pop());L=Q.exec(_);while(L!==null){if(L[1])X.push(L[1].replace(/`/g,"").split(".").pop());L=Q.exec(_)}break;case"INSERT":if(z=_.match(/into\s+([\w.]+)/i),z&&z[1])X.push(z[1].replace(/`/g,"").split(".").pop());break;case"UPDATE":if(j=_.match(/update\s+([\w.]+)/i),j&&j[1])X.push(j[1].replace(/`/g,"").split(".").pop());break;case"DELETE":if(U=_.match(/from\s+([\w.]+)/i),U&&U[1])X.push(U[1].replace(/`/g,"").split(".").pop());break}}catch{}return[...new Set(X)].filter(Boolean)}function oE($){try{let Z=$;return Z=Z.replace(/(?<![a-zA-Z_])\b\d+\b(?![a-zA-Z_])/g,"?"),Z=Z.replace(/'([^']|'')*'/g,"?"),Z=Z.replace(/"([^"]|"")*"/g,"?"),Z=Z.replace(/\btrue\b/gi,"?"),Z=Z.replace(/\bfalse\b/gi,"?"),Z=Z.replace(/\bnull\b/gi,"?"),Z=Z.replace(/\s+/g," ").trim(),Z}catch{return $}}await p0();var c4=()=>{};function tE($){c4=$}var f6=!1;async function eE($){if(f6)return;try{let{query:Z,durationMs:X,error:_,bindings:Y}=$O($);try{c4(Z,X,Z8.database?.default||"unknown")}catch{}if(!Z8.database?.queryLogging?.enabled)return;let L=ZO(X,_),z=await XO(Z,X,L,_,Y);if(Z8.database?.queryLogging?.analysis?.enabled&&(L==="slow"||Z8.database.queryLogging.analysis.analyzeAll))await zO(z);f6=!0;try{await OO(z)}finally{f6=!1}if(L!=="completed")n1[L==="failed"?"error":"warn"](`Query ${L}:`,{query:z.query,duration:z.duration,connection:z.connection,..._&&{error:_}})}catch(Z){n1.error("Failed to log query:",Z)}}function $O($){let Z=$.query?.sql||"",X=$.queryDurationMillis||0,_=$.error,Y;if($.query?.parameters)try{Y=JSON.stringify($.query.parameters)}catch{Y="[]"}return{query:Z,durationMs:X,error:_,bindings:Y}}function ZO($,Z){let X=Z8.database?.queryLogging?.slowThreshold||100;if(Z)return"failed";if($>X)return"slow";return"completed"}async function XO($,Z,X,_,Y){let L=Z8.database.default||"unknown",z=b6($).normalized||$,{trace:j,caller:U}=LO();return{query:$,normalized_query:z,duration:Z,connection:L,status:X,error:_?String(_):void 0,executed_at:new Date().toISOString(),bindings:Y,trace:j,...U,memory_usage:aE().heapUsed/1024/1024}}var _O=[/\b(?:sk|pk|rk|api|secret|token|bearer|password|pwd|key)[_-]?[A-Za-z0-9]{12,}/gi,/\bsk_(?:live|test)_[A-Za-z0-9]{20,}/g,/\bAKIA[0-9A-Z]{16}/g,/\b[A-Za-z0-9_-]{40,}\b(?=\s|$|['"])/g];function YO($){let Z=$;for(let X of _O)Z=Z.replace(X,"<redacted>");return Z}function LO(){try{let $=Error("Stack trace capture").stack||"",X=$.split(`
136
+ `;g4(G,F),$0.debug(`[migration] Wrote ${E} (${Q.length} stmt${Q.length===1?"":"s"})`),z+=1,j+=1}return z}function nE($){let Z=new Map,X=(_,Y)=>{let L=Z.get(_)??[];L.push(Y),Z.set(_,L)};for(let _ of $){let Y=_.trim();if(!Y)continue;let L=Y.match(/^\s*CREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?["`]?(\w+)["`]?/i);if(L){X(`create-${L[1]}-table`,Y);continue}let z=Y.match(/^\s*ALTER\s+TABLE\s+["`]?(\w+)["`]?\s+(?:ADD\s+COLUMN\s+["`]?(\w+)["`]?|DROP\s+COLUMN\s+["`]?(\w+)["`]?|ADD\s+CONSTRAINT)/i);if(z){X(`alter-${z[1]}-${z[2]||z[3]||"constraint"}`,Y);continue}let j=Y.match(/^\s*CREATE\s+(?:UNIQUE\s+)?INDEX\s+(?:IF\s+NOT\s+EXISTS\s+)?["`]?(\w+)["`]?\s+ON\s+["`]?(\w+)["`]?/i);if(j){X(`create-${j[1]}-index-in-${j[2]}`,Y);continue}let U=Y.match(/^\s*DROP\s+TABLE\s+(?:IF\s+EXISTS\s+)?["`]?(\w+)["`]?/i);if(U){X(`drop-${U[1]}-table`,Y);continue}X("auto-misc",Y)}return[...Z.entries()].map(([_,Y])=>({label:_,statements:Y}))}function iE($){let Z=0;try{for(let X of h6($)){let _=X.match(/^(\d+)-/);if(_?.[1])Z=Math.max(Z,Number.parseInt(_[1],10))}}catch{}return Z+1}async function eV(){try{$0.info("Generating fresh migrations..."),c5();let $=d8(),{modelsDir:Z,skip:X}=p4();if(X)return $0.info("No app/Models directory found; using committed framework migrations"),c8("Migrations generated");return await A5(Z,{dialect:$,full:!0}),$0.success("Migrations generated"),c8("Migrations generated")}catch($){return f5(g5("Fresh migration generation failed",$))}}import{memoryUsage as aE}from"process";import{config as Z8}from"@stacksjs/config";import{log as n1}from"@stacksjs/logging";function b6($){let Z={normalized:"",type:"OTHER",tables:[]};if(!$)return Z;try{let X=$.trim().toUpperCase();if(X.startsWith("SELECT"))Z.type="SELECT";else if(X.startsWith("INSERT"))Z.type="INSERT";else if(X.startsWith("UPDATE"))Z.type="UPDATE";else if(X.startsWith("DELETE"))Z.type="DELETE";return Z.tables=rE($,Z.type),Z.normalized=oE($),Z}catch{return{normalized:$,type:"OTHER",tables:[]}}}function rE($,Z){let X=[],_=$.toLowerCase();try{let Y=null,L=null,z=null,j=null,U=null,Q=/join\s+([\w.]+)/gi;switch(Z){case"SELECT":if(Y=_.match(/from\s+([\w.]+)/i),Y&&Y[1])X.push(Y[1].replace(/`/g,"").split(".").pop());L=Q.exec(_);while(L!==null){if(L[1])X.push(L[1].replace(/`/g,"").split(".").pop());L=Q.exec(_)}break;case"INSERT":if(z=_.match(/into\s+([\w.]+)/i),z&&z[1])X.push(z[1].replace(/`/g,"").split(".").pop());break;case"UPDATE":if(j=_.match(/update\s+([\w.]+)/i),j&&j[1])X.push(j[1].replace(/`/g,"").split(".").pop());break;case"DELETE":if(U=_.match(/from\s+([\w.]+)/i),U&&U[1])X.push(U[1].replace(/`/g,"").split(".").pop());break}}catch{}return[...new Set(X)].filter(Boolean)}function oE($){try{let Z=$;return Z=Z.replace(/(?<![a-zA-Z_])\b\d+\b(?![a-zA-Z_])/g,"?"),Z=Z.replace(/'([^']|'')*'/g,"?"),Z=Z.replace(/"([^"]|"")*"/g,"?"),Z=Z.replace(/\btrue\b/gi,"?"),Z=Z.replace(/\bfalse\b/gi,"?"),Z=Z.replace(/\bnull\b/gi,"?"),Z=Z.replace(/\s+/g," ").trim(),Z}catch{return $}}await p0();var c4=()=>{};function tE($){c4=$}var f6=!1;async function eE($){if(f6)return;try{let{query:Z,durationMs:X,error:_,bindings:Y}=$O($);try{c4(Z,X,Z8.database?.default||"unknown")}catch{}if(!Z8.database?.queryLogging?.enabled)return;let L=ZO(X,_),z=await XO(Z,X,L,_,Y);if(Z8.database?.queryLogging?.analysis?.enabled&&(L==="slow"||Z8.database.queryLogging.analysis.analyzeAll))await zO(z);f6=!0;try{await OO(z)}finally{f6=!1}if(L!=="completed")n1[L==="failed"?"error":"warn"](`Query ${L}:`,{query:z.query,duration:z.duration,connection:z.connection,..._&&{error:_}})}catch(Z){n1.error("Failed to log query:",Z)}}function $O($){let Z=$.query?.sql||"",X=$.queryDurationMillis||0,_=$.error,Y;if($.query?.parameters)try{Y=JSON.stringify($.query.parameters)}catch{Y="[]"}return{query:Z,durationMs:X,error:_,bindings:Y}}function ZO($,Z){let X=Z8.database?.queryLogging?.slowThreshold||100;if(Z)return"failed";if($>X)return"slow";return"completed"}async function XO($,Z,X,_,Y){let L=Z8.database.default||"unknown",z=b6($).normalized||$,{trace:j,caller:U}=LO();return{query:$,normalized_query:z,duration:Z,connection:L,status:X,error:_?String(_):void 0,executed_at:new Date().toISOString(),bindings:Y,trace:j,...U,memory_usage:aE().heapUsed/1024/1024}}var _O=[/\b(?:sk|pk|rk|api|secret|token|bearer|password|pwd|key)[_-]?[A-Za-z0-9]{12,}/gi,/\bsk_(?:live|test)_[A-Za-z0-9]{20,}/g,/\bAKIA[0-9A-Z]{16}/g,/\b[A-Za-z0-9_-]{40,}\b(?=\s|$|['"])/g];function YO($){let Z=$;for(let X of _O)Z=Z.replace(X,"<redacted>");return Z}function LO(){try{let $=Error("Stack trace capture").stack||"",X=$.split(`
137
137
  `).slice(1).find((Y)=>!Y.includes("query-logger.ts")),_={};if(X){let Y=X.match(/at (.+?) \(/),L=X.match(/\((.+?):(\d+):(\d+)\)/);if(Y&&Y[1]){let z=Y[1].split(".");_={model:z.length>1?z[0]:void 0,method:z.length>1?z[1]:z[0]}}if(L&&L[1]&&L[2])_={..._,file:L[1],line:Number.parseInt(L[2],10)}}return{trace:YO($),caller:_}}catch{return{trace:"",caller:{}}}}async function zO($){try{let{tables:Z,type:X}=b6($.query);if($.affected_tables=JSON.stringify(Z||[]),X==="SELECT"&&Z8.database?.queryLogging?.analysis?.explainPlan){let Y=await jO($.query);if(Y){if($.explain_plan=Y.plan,$.indexes_used=JSON.stringify(Y.indexesUsed||[]),$.missing_indexes=JSON.stringify(Y.missingIndexes||[]),Z8.database?.queryLogging?.analysis?.suggestions)$.optimization_suggestions=JSON.stringify(EO(Y,$))}}let _=[X];if(Z&&Z.length>0)_.push(...Z.map((Y)=>`table:${Y}`));$.tags=JSON.stringify(_)}catch(Z){n1.debug("Error during query analysis:",Z)}}var UO=new Set(["sqlite","mysql","postgres"]);async function jO($){try{let Z=(await import("@stacksjs/config")).config?.database?.default,X=typeof Z==="string"?Z:"sqlite";if(!UO.has(X))return null;let _;if(X==="mysql")_=`EXPLAIN FORMAT=JSON ${$}`;else if(X==="postgres")_=`EXPLAIN (FORMAT JSON) ${$}`;else _=`EXPLAIN QUERY PLAN ${$}`;let Y=await v.unsafe?.(_);if(!Y)return null;let L=Array.isArray(Y)?Y:Y.rows??[],z=JSON.stringify(L),j=[],U=[];if(X==="sqlite")for(let Q of L){let E=Q?.detail||"",G=E.match(/USING (?:COVERING )?INDEX (\w+)/i);if(G&&G[1])j.push(G[1]);else{let F=E.match(/^SCAN\s+(\w+)/i);if(F&&F[1])U.push(F[1])}}else if(X==="mysql"){let Q=z;for(let E of Q.matchAll(/"key"\s*:\s*"([^"]+)"/g))if(E[1])j.push(E[1]);for(let E of Q.matchAll(/"table_name"\s*:\s*"([^"]+)"[^}]*"access_type"\s*:\s*"ALL"/g))if(E[1])U.push(E[1])}else if(X==="postgres"){let Q=z;for(let E of Q.matchAll(/"Index Name"\s*:\s*"([^"]+)"/g))if(E[1])j.push(E[1]);for(let E of Q.matchAll(/"Node Type"\s*:\s*"Seq Scan"[^}]*"Relation Name"\s*:\s*"([^"]+)"/g))if(E[1])U.push(E[1])}return{plan:z.length>4000?`${z.slice(0,4000)}\u2026`:z,indexesUsed:Array.from(new Set(j)),missingIndexes:Array.from(new Set(U))}}catch(Z){return n1.debug("[query-logger] EXPLAIN failed (non-fatal):",Z),null}}function EO($,Z){let X=[];if($.missingIndexes&&$.missingIndexes.length>0)X.push(`Consider adding index on ${$.missingIndexes.join(", ")}`);if(Z.status==="slow"){if(X.push("Consider optimizing this query to reduce execution time"),Z.query.toLowerCase().includes("select *"))X.push("Specify only needed columns instead of using SELECT *");if(!Z.query.toLowerCase().includes("limit"))X.push("Consider adding LIMIT clause to reduce result set size")}return X}async function OO($){try{await v.insertInto("query_logs").values($).execute()}catch(Z){n1.error("Failed to store query log:",Z)}}import{log as i1}from"@stacksjs/logging";import{path as QO}from"@stacksjs/path";import{fs as d4}from"@stacksjs/storage";class u4{async call($){await new $().run()}}async function GO($={}){let Z=$.dir??QO.projectPath("database/seeders"),X=[],_=[];if(!d4.existsSync(Z))return i1.info(`[seeder] No class seeders directory at ${Z}`),{ran:X,skipped:_};let Y=d4.readdirSync(Z).filter((L)=>L.endsWith(".ts")&&!L.startsWith("_"));for(let L of Y){let z=L.replace(/\.ts$/,"");if($.class&&z!==$.class){_.push(z);continue}try{let j=await import(`${Z}/${L}`),U=j.default??j[z];if(!U){i1.warn(`[seeder] ${L} has no default export`),_.push(z);continue}let Q=new U;if(typeof Q.run!=="function"){i1.warn(`[seeder] ${z} does not implement run()`),_.push(z);continue}i1.info(`[seeder] Running ${z}\u2026`),await Q.run(),X.push(z)}catch(j){i1.error(`[seeder] ${z} failed:`,j),_.push(z)}}return{ran:X,skipped:_}}async function FO($,Z,X,_){let{type:Y,defaultValue:L,notNull:z=!1,batchSize:j=1000}=_,U=$,Q=L===void 0?"":` DEFAULT ${l4(L)}`;if(await u8(U,`ALTER TABLE ${c0(Z)} ADD COLUMN ${c0(X)} ${Y}${Q}`),L!==void 0)await s4($,Z,X,L,j);if(z)await u8(U,`ALTER TABLE ${c0(Z)} ALTER COLUMN ${c0(X)} SET NOT NULL`)}async function u8($,Z){if(typeof $.unsafe==="function")return await $.unsafe(Z)??{};return await u1`${u1.raw(Z)}`.execute($),{}}async function s4($,Z,X,_,Y=1000){let L=$,z=0,j=0;do{let U=`
138
138
  UPDATE ${c0(Z)} SET ${c0(X)} = ${l4(_)}
139
139
  WHERE ${c0(X)} IS NULL
@@ -0,0 +1,35 @@
1
+ import type { Result } from '@stacksjs/error-handling';
2
+ export type { MigrationResult as MigrationResultType };
3
+ /**
4
+ * Run database migrations
5
+ */
6
+ export declare function runDatabaseMigration(): Promise<Result<string, Error>>;
7
+ /**
8
+ * Reset the database (drop all tables)
9
+ */
10
+ export declare function resetDatabase(): Promise<Result<string, Error>>;
11
+ /*` definitions to the stored snapshot
12
+ * (`.qb/model-snapshot.<dialect>.json`) via bun-query-builder, then — if
13
+ * there are changes — writes the resulting ALTER/CREATE/DROP statements
14
+ * out to a fresh file in `database/migrations/`. Each statement is
15
+ * grouped by table + DDL verb and lands in its own file using the
16
+ * runner's existing naming convention so it picks them up the same way
17
+ * as a hand-written migration.
18
+ *
19
+ * Without this write step the qb generator stages the diff in memory but
20
+ * the runner never sees it, so model edits silently no-op'd — defeating
21
+ * the "models are the source of truth" promise.
22
+ */
23
+ export declare function generateMigrations(): Promise<Result<string, Error>>;
24
+ /**
25
+ * Generate fresh migrations (full regeneration, ignoring previous state)
26
+ */
27
+ export declare function generateMigrations2(): Promise<Result<string, Error>>;
28
+ /**
29
+ * Migration result type for compatibility
30
+ */
31
+ export declare interface MigrationResult {
32
+ migrationName: string
33
+ direction: 'Up' | 'Down'
34
+ status: 'Success' | 'Error' | 'NotExecuted'
35
+ }
@@ -0,0 +1,26 @@
1
+ export declare function setQueryTracker(fn: QueryTracker): void;
2
+ /**
3
+ * Process an executed query and store it in the database
4
+ */
5
+ export declare function logQuery(event: LogEvent): Promise<void>;
6
+ /**
7
+ * Query log event type - compatible with bun-query-builder hooks
8
+ */
9
+ declare interface LogEvent {
10
+ query?: {
11
+ sql?: string
12
+ parameters?: unknown[]
13
+ }
14
+ queryDurationMillis?: number
15
+ error?: Error | unknown
16
+ }
17
+ /**
18
+ * Soft dependency on the router's query tracker. Importing it directly
19
+ * creates the cycle `database → router → database` (router uses db
20
+ * helpers transitively via middleware). The DI shape below lets the
21
+ * router register its tracker at module-init time and lets the database
22
+ * package stay leaf-node — runs that don't load the router (CLI tools,
23
+ * cron tasks) silently no-op the tracker call.
24
+ */
25
+ // eslint-disable-next-line pickier/no-unused-vars
26
+ declare type QueryTracker = (query: string, durationMs?: number, connection?: string) => void;
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Parse and normalize a SQL query
3
+ */
4
+ export declare function parseQuery(sql: string): { normalized: string, type: string, tables: string[] };
@@ -0,0 +1,72 @@
1
+ import { db } from './utils';
2
+ /**
3
+ * Add a column to `tableName` without taking a table-level lock long
4
+ * enough to disrupt traffic. The column is created nullable, backfilled
5
+ * in batches, and (if `notNull: true`) the constraint is added at the
6
+ * end.
7
+ *
8
+ * Pre-conditions:
9
+ * - `tableName` exists
10
+ * - `columnName` does NOT already exist (this helper doesn't gracefully
11
+ * handle the rerun case — wrap in `if (!columnExists)` if you need that)
12
+ *
13
+ * Caveats:
14
+ * - SQLite doesn't support adding NOT NULL columns to existing tables
15
+ * without a default; we work around it by always supplying one
16
+ * - Postgres < 11 rewrites the entire table when a default is added;
17
+ * this helper assumes ≥ 11
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * await addColumnSafely(db, 'users', 'email_verified', {
22
+ * type: 'boolean',
23
+ * defaultValue: false,
24
+ * notNull: true,
25
+ * })
26
+ * ```
27
+ */
28
+ export declare function addColumnSafely(db: Database, tableName: string, columnName: string, options: AddColumnSafelyOptions): Promise<void>;
29
+ /**
30
+ * Back-fill `columnName` with `value` for any row where it's currently
31
+ * NULL. Runs in batches so the UPDATE doesn't lock the entire table.
32
+ *
33
+ * Useful as a standalone helper when you want to backfill an *existing*
34
+ * column (e.g. populating a denormalized count) — `addColumnSafely`
35
+ * uses it internally.
36
+ */
37
+ export declare function backfillInBatches(db: Database, tableName: string, columnName: string, value: string | number | boolean | null, batchSize?: number): Promise<void>;
38
+ /**
39
+ * Rename a column safely on a table that's actively serving traffic.
40
+ *
41
+ * Most database engines DO support `RENAME COLUMN` as a metadata-only
42
+ * operation (no rewrite, no long lock), which means the headline
43
+ * concern is *application-side*: app code reads the old column name,
44
+ * the migration renames it, and the next request 500s.
45
+ *
46
+ * This helper wraps the rename in a multi-step sequence the framework
47
+ * docs can teach as the canonical pattern:
48
+ *
49
+ * 1. Add the new column
50
+ * 2. Backfill from old → new
51
+ * 3. Update writes to dual-write old AND new (app-level, deploy step)
52
+ * 4. Update reads to read from new (app-level, deploy step)
53
+ * 5. Drop the old column (separate migration)
54
+ *
55
+ * For the rare case where the rename *can* happen atomically (small
56
+ * table, no live traffic), pass `{ atomic: true }` and we'll just emit
57
+ * the RENAME COLUMN.
58
+ *
59
+ * @example
60
+ * ```ts
61
+ * // Step 1 of the rename sequence — the rest is app-side coordination.
62
+ * await renameColumnSafely(db, 'users', 'name', 'full_name', { type: 'varchar(255)' })
63
+ * ```
64
+ */
65
+ export declare function renameColumnSafely(db: Database, tableName: string, oldName: string, newName: string, options: { type: string, atomic?: boolean }): Promise<void>;
66
+ declare interface AddColumnSafelyOptions {
67
+ type: string
68
+ defaultValue?: string | number | boolean | null
69
+ notNull?: boolean
70
+ batchSize?: number
71
+ }
72
+ declare type Database = typeof db;
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Main seeding function
3
+ * Seeds the database using model factory functions
4
+ * Loads models from both framework defaults and user-defined models,
5
+ * with user models taking precedence.
6
+ */
7
+ export declare function seed(config?: SeederConfig): Promise<SeedSummary>;
8
+ /**
9
+ * Seed a specific model by name
10
+ * Searches both default and user models
11
+ */
12
+ export declare function seedModel$(modelName: string, options?: { count?: number, fresh?: boolean, verbose?: boolean }): Promise<SeedResult>;
13
+ /**
14
+ * Fresh seed - truncate all tables and reseed
15
+ */
16
+ export declare function freshSeed(config?: SeederConfig): Promise<SeedSummary>;
17
+ /**
18
+ * Get list of seedable models without seeding
19
+ * Returns models from both default and user directories
20
+ */
21
+ export declare function listSeedableModels(): Promise<Array<{ name: string, table: string, count: number, source: 'default' | 'user' }>>;
22
+ /**
23
+ * Seeder configuration options
24
+ */
25
+ export declare interface SeederConfig {
26
+ modelsDir?: string
27
+ defaultCount?: number
28
+ verbose?: boolean
29
+ fresh?: boolean
30
+ only?: string[]
31
+ except?: string[]
32
+ includeDefaults?: boolean
33
+ }
34
+ /**
35
+ * Result of a single model seeding operation
36
+ */
37
+ export declare interface SeedResult {
38
+ model: string
39
+ table: string
40
+ count: number
41
+ success: boolean
42
+ error?: string
43
+ duration: number
44
+ }
45
+ /**
46
+ * Result of the entire seeding operation
47
+ */
48
+ export declare interface SeedSummary {
49
+ total: number
50
+ successful: number
51
+ failed: number
52
+ results: SeedResult[]
53
+ duration: number
54
+ }
55
+ // Legacy exports for backwards compatibility
56
+ export { seed as runSeeders };
57
+ export { freshSeed as freshWithSeed };
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Create SQL dialect helpers for a given driver.
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * import { sqlHelpers } from '@stacksjs/database'
7
+ * const sql = sqlHelpers('postgres')
8
+ * await db.unsafe(`SELECT * FROM users WHERE id = ${sql.param(1)}`, [userId])
9
+ * ```
10
+ */
11
+ export declare function sqlHelpers(driver: string): SqlDialectHelpers;
12
+ /**
13
+ * SQL Dialect Helpers
14
+ *
15
+ * Cross-database compatibility utilities for PostgreSQL, MySQL, and SQLite.
16
+ * Centralizes the isPostgres/isMysql/now/boolTrue/boolFalse/param helpers
17
+ * that were previously duplicated across tokens.ts, auth-tables.ts, and setup.ts.
18
+ */
19
+ export declare interface SqlDialectHelpers {
20
+ driver: string
21
+ isPostgres: boolean
22
+ isMysql: boolean
23
+ isSqlite: boolean
24
+ now: string
25
+ boolTrue: string
26
+ boolFalse: string
27
+ autoIncrement: string
28
+ primaryKey: string
29
+ param: (index: number) => string
30
+ params: (...values: unknown[]) => { sql: string, values: unknown[] }
31
+ }
@@ -0,0 +1,66 @@
1
+ /**
2
+ * SQL template tag function.
3
+ * Creates parameterized SQL queries from template literals.
4
+ *
5
+ * @example
6
+ * ```ts
7
+ * const query = sql`SELECT * FROM users WHERE id = ${userId}`
8
+ * ```
9
+ */
10
+ export declare function sql(strings: TemplateStringsArray, ...values: unknown[]): Sql;
11
+ /**
12
+ * Type for raw SQL expressions.
13
+ * Used when building dynamic SQL queries.
14
+ */
15
+ export declare interface RawBuilder<T = unknown> {
16
+ readonly sql: string
17
+ readonly parameters?: unknown[]
18
+ readonly __result?: T
19
+ }
20
+ /**
21
+ * SQL template tag type.
22
+ * Used for tagged template literals that produce SQL.
23
+ */
24
+ export declare interface Sql {
25
+ readonly sql: string
26
+ readonly parameters: unknown[]
27
+ }
28
+ /**
29
+ * Database types - Compatibility layer
30
+ *
31
+ * These types provide backwards compatibility with code that
32
+ * previously used Kysely types. They work with bun-query-builder's
33
+ * native type system.
34
+ */
35
+ /**
36
+ * Marks a column as auto-generated (e.g., auto-increment primary keys).
37
+ * When inserting, this field is optional. When selecting, it's required.
38
+ */
39
+ export type Generated<T> = T;
40
+ /**
41
+ * Marks a column as always generated (computed columns).
42
+ * This field cannot be inserted or updated directly.
43
+ */
44
+ export type GeneratedAlways<T> = T;
45
+ /**
46
+ * Utility type for insert operations.
47
+ * Makes Generated fields optional, keeps required fields required.
48
+ */
49
+ export type Insertable<T> = {
50
+ [K in keyof T]?: T[K]
51
+ }
52
+ /**
53
+ * Utility type for select operations.
54
+ * All fields are as defined in the table type.
55
+ */
56
+ export type Selectable<T> = T;
57
+ /**
58
+ * Utility type for update operations.
59
+ * All fields are optional since you may update only some fields.
60
+ */
61
+ export type Updateable<T> = Partial<T>;
62
+ /**
63
+ * Database type alias for backwards compatibility.
64
+ * Use the query builder from bun-query-builder instead.
65
+ */
66
+ export type Database = any;
@@ -0,0 +1,139 @@
1
+ import { createQueryBuilder, setConfig } from 'bun-query-builder';
2
+ import type { DatabaseSchema } from 'bun-query-builder';
3
+ // Function to initialize the config when it's available
4
+ export declare function initializeDbConfig(config: any): void;
5
+ export declare function ensureDatabaseConfigLoaded(): Promise<void>;
6
+ /**
7
+ * Lazy proxy for the query builder - connection is only made when first used.
8
+ * This is the main entry point for database operations.
9
+ */
10
+ export declare const db: Proxy;
11
+ /**
12
+ * Fluent chain returned by entry-point methods like `selectFrom`/`updateTable`.
13
+ *
14
+ * bun-query-builder marks legacy chain methods (e.g. `selectAll`, `whereILike`,
15
+ * `selectAllRelations`) as optional in its declarations even though they're
16
+ * always present at runtime. Re-typing them here avoids forcing every call
17
+ * site to use `?.()` or `!` on the chain.
18
+ *
19
+ * Returns are typed as `any` deliberately — typing each variant precisely
20
+ * would re-introduce the optional methods, and we already lose strict column
21
+ * typing one step into a chain (the underlying query builder is constructed
22
+ * with no schema). Tests cover the runtime semantics.
23
+ */
24
+ export declare interface FluentChain {
25
+ where: (...args: any[]) => FluentChain
26
+ whereNull: (...args: any[]) => FluentChain
27
+ whereNotNull: (...args: any[]) => FluentChain
28
+ whereIn: (...args: any[]) => FluentChain
29
+ whereNotIn: (...args: any[]) => FluentChain
30
+ whereLike: (...args: any[]) => FluentChain
31
+ whereNotLike: (...args: any[]) => FluentChain
32
+ whereILike: (...args: any[]) => FluentChain
33
+ whereNotILike: (...args: any[]) => FluentChain
34
+ whereBetween: (...args: any[]) => FluentChain
35
+ whereNotBetween: (...args: any[]) => FluentChain
36
+ whereRaw: (...args: any[]) => FluentChain
37
+ whereColumn: (...args: any[]) => FluentChain
38
+ orWhere: (...args: any[]) => FluentChain
39
+ orWhereNull: (...args: any[]) => FluentChain
40
+ orWhereNotNull: (...args: any[]) => FluentChain
41
+ orWhereIn: (...args: any[]) => FluentChain
42
+ orWhereNotIn: (...args: any[]) => FluentChain
43
+ orWhereLike: (...args: any[]) => FluentChain
44
+ orWhereNotLike: (...args: any[]) => FluentChain
45
+ orWhereILike: (...args: any[]) => FluentChain
46
+ orWhereColumn: (...args: any[]) => FluentChain
47
+ andWhere: (...args: any[]) => FluentChain
48
+ having: (...args: any[]) => FluentChain
49
+ groupBy: (...args: any[]) => FluentChain
50
+ orderBy: (...args: any[]) => FluentChain
51
+ limit: (...args: any[]) => FluentChain
52
+ offset: (...args: any[]) => FluentChain
53
+ select: (...args: any[]) => FluentChain
54
+ selectAll: () => FluentChain
55
+ selectAllRelations: () => FluentChain
56
+ selectRaw: (...args: any[]) => FluentChain
57
+ distinct: () => FluentChain
58
+ distinctOn: (...args: any[]) => FluentChain
59
+ innerJoin: (...args: any[]) => FluentChain
60
+ leftJoin: (...args: any[]) => FluentChain
61
+ rightJoin: (...args: any[]) => FluentChain
62
+ fullJoin: (...args: any[]) => FluentChain
63
+ crossJoin: (...args: any[]) => FluentChain
64
+ with: (...args: any[]) => FluentChain
65
+ union: (...args: any[]) => FluentChain
66
+ unionAll: (...args: any[]) => FluentChain
67
+ values: (...args: any[]) => FluentChain
68
+ set: (...args: any[]) => FluentChain
69
+ returning: (...args: any[]) => FluentChain
70
+ returningAll: () => FluentChain
71
+ onConflict: (...args: any[]) => FluentChain
72
+ onDuplicateKeyUpdate: (...args: any[]) => FluentChain
73
+ onConflictDoNothing: (...args: any[]) => FluentChain
74
+ onDuplicateKeyIgnore: () => FluentChain
75
+ forUpdate: () => FluentChain
76
+ forShare: () => FluentChain
77
+ toSQL: () => string
78
+ execute: () => Promise<any>
79
+ executeTakeFirst: () => Promise<any>
80
+ executeTakeFirstOrThrow: () => Promise<any>
81
+ pluck: (...args: any[]) => Promise<any>
82
+ count: (...args: any[]) => Promise<number>
83
+ sum: (...args: any[]) => Promise<number>
84
+ avg: (...args: any[]) => Promise<number>
85
+ min: (...args: any[]) => Promise<any>
86
+ max: (...args: any[]) => Promise<any>
87
+ exists: () => Promise<boolean>
88
+ doesntExist: () => Promise<boolean>
89
+ [key: string]: any
90
+ }
91
+ // Permissive schema type that accepts any table name with any columns
92
+ // This allows the query builder to work before model types are generated
93
+ declare type AnySchema = DatabaseSchema<any> & Record<string, { columns: Record<string, any>, primaryKey: string }>;
94
+ // The bun-query-builder types `unsafe()` as returning `Promise<any>`, but at
95
+ // runtime it returns a Bun SQL Statement that has `.execute()`. This interface
96
+ // corrects the return type so callers can chain `.execute()` without type errors.
97
+ declare type UnsafeReturn = Promise<any> & { execute: () => Promise<any> }
98
+ /**
99
+ * Top-level surface of the lazy `db` proxy. Methods that return a chainable
100
+ * builder are typed as `FluentChain` to flatten the optional-method noise
101
+ * inherent in bun-query-builder's declarations. Methods that introduce their
102
+ * own generics (`transaction<T>`, etc.) are kept as their original signatures
103
+ * via the underlying QueryBuilder type so call-site inference still works.
104
+ */
105
+ declare type RawQueryBuilder = ReturnType<typeof createQueryBuilder>;
106
+ declare type GenericPassthroughKeys = | 'transaction'
107
+ | 'savepoint'
108
+ | 'beginDistributed'
109
+ | 'transactional'
110
+ | 'configure'
111
+ | 'reserve'
112
+ | 'commitDistributed'
113
+ | 'rollbackDistributed'
114
+ | 'setTransactionDefaults'
115
+ | 'close'
116
+ | 'listen'
117
+ | 'unlisten'
118
+ | 'notify'
119
+ | 'copyTo'
120
+ | 'copyFrom'
121
+ | 'ping'
122
+ | 'waitForReady'
123
+ | 'count'
124
+ | 'sum'
125
+ | 'avg'
126
+ | 'min'
127
+ | 'max'
128
+ | 'insertOrIgnore'
129
+ | 'insertGetId'
130
+ | 'updateOrInsert'
131
+ | 'upsert'
132
+ | 'create'
133
+ | 'createMany'
134
+ | 'sql'
135
+ | 'raw'
136
+ | 'simple'
137
+ | 'file';
138
+ // Export setConfig if available
139
+ export { setConfig };
@@ -0,0 +1,26 @@
1
+ import type { BigintValidatorType, BinaryValidatorType, BlobValidatorType, BooleanValidatorType, DatetimeValidatorType, DateValidatorType, DecimalValidatorType, EnumValidatorType, FloatValidatorType, IntegerValidatorType, JsonValidatorType, NumberValidatorType, SmallintValidatorType, StringValidatorType, TimestampTzValidatorType, TimestampValidatorType, UnixValidatorType, ValidationType } from '@stacksjs/ts-validation';
2
+ export declare function isStringValidator(v: ValidationType): v is StringValidatorType;
3
+ export declare function isNumberValidator(v: ValidationType): v is NumberValidatorType;
4
+ export declare function enumValidator(v: ValidationType): v is EnumValidatorType;
5
+ export declare function isBooleanValidator(v: ValidationType): v is BooleanValidatorType;
6
+ export declare function isDateValidator(v: ValidationType): v is DateValidatorType;
7
+ export declare function isUnixValidator(v: ValidationType): v is UnixValidatorType;
8
+ export declare function isFloatValidator(v: ValidationType): v is FloatValidatorType;
9
+ export declare function isDatetimeValidator(v: ValidationType): v is DatetimeValidatorType;
10
+ export declare function isTimestampValidator(v: ValidationType): v is TimestampValidatorType;
11
+ export declare function isTimestampTzValidator(v: ValidationType): v is TimestampTzValidatorType;
12
+ export declare function isDecimalValidator(v: ValidationType): v is DecimalValidatorType;
13
+ export declare function isSmallintValidator(v: ValidationType): v is SmallintValidatorType;
14
+ export declare function isIntegerValidator(v: ValidationType): v is IntegerValidatorType;
15
+ export declare function isBigintValidator(v: ValidationType): v is BigintValidatorType;
16
+ export declare function isBinaryValidator(v: ValidationType): v is BinaryValidatorType;
17
+ export declare function isBlobValidator(v: ValidationType): v is BlobValidatorType;
18
+ export declare function isJsonValidator(v: ValidationType): v is JsonValidatorType;
19
+ export declare function checkValidator(validator: ValidationType, driver: string): string;
20
+ export declare function prepareNumberColumnType(validator: NumberValidatorType, driver?: string): string;
21
+ // Add new function for enum column types
22
+ export declare function prepareEnumColumnType(validator: EnumValidatorType, driver?: string): string;
23
+ export declare function prepareTextColumnType(validator: StringValidatorType, driver?: string): string;
24
+ // Add new function for date/time column types
25
+ export declare function prepareDateTimeColumnType(validator: DateValidatorType, driver?: string): string;
26
+ export declare function findCharacterLength(validator: ValidationType): number;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@stacksjs/database",
3
3
  "type": "module",
4
- "version": "0.70.37",
4
+ "version": "0.70.39",
5
5
  "description": "The Stacks database integration.",
6
6
  "author": "Chris Breuer",
7
7
  "contributors": [
@@ -53,15 +53,15 @@
53
53
  "bun-query-builder": "^0.1.21"
54
54
  },
55
55
  "devDependencies": {
56
- "@stacksjs/cli": "0.70.30",
57
- "@stacksjs/config": "0.70.30",
58
- "@stacksjs/logging": "0.70.30",
59
- "@stacksjs/router": "0.70.30",
56
+ "@stacksjs/cli": "0.70.37",
57
+ "@stacksjs/config": "0.70.37",
58
+ "@stacksjs/logging": "0.70.37",
59
+ "@stacksjs/router": "0.70.37",
60
60
  "better-dx": "^0.2.12",
61
- "@stacksjs/path": "0.70.30",
62
- "@stacksjs/query-builder": "0.70.30",
63
- "@stacksjs/storage": "0.70.30",
64
- "@stacksjs/strings": "0.70.30",
65
- "@stacksjs/utils": "0.70.30"
61
+ "@stacksjs/path": "0.70.37",
62
+ "@stacksjs/query-builder": "0.70.37",
63
+ "@stacksjs/storage": "0.70.37",
64
+ "@stacksjs/strings": "0.70.37",
65
+ "@stacksjs/utils": "0.70.37"
66
66
  }
67
67
  }