Skip to content

Commit ee5a778

Browse files
committed
chore: wip
1 parent 4068f34 commit ee5a778

File tree

4 files changed

+101
-14
lines changed

4 files changed

+101
-14
lines changed

packages/bun-query-builder/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@
2121
],
2222
"exports": {
2323
".": {
24+
"bun": "./src/index.ts",
2425
"types": "./dist/index.d.ts",
2526
"import": "./dist/index.js"
2627
},
2728
"./*": {
29+
"bun": "./src/*",
2830
"import": "./dist/*"
2931
}
3032
},

packages/bun-query-builder/src/client.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
import type { SchemaMeta } from './meta'
55
import type { DatabaseSchema } from './schema'
66
import { config } from './config'
7-
import { bunSql, getOrCreateBunSql } from './db'
7+
import { bunSql, getOrCreateBunSql, resetConnection } from './db'
8+
9+
export { resetConnection }
810

911
// Type guard for raw SQL expressions
1012
interface RawExpression {

packages/bun-query-builder/src/config.ts

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,48 @@ export const defaultConfig: QueryBuilderConfig = {
5959
},
6060
}
6161

62-
// eslint-disable-next-line antfu/no-top-level-await
63-
export const config: QueryBuilderConfig = await loadConfig({
64-
name: 'query-builder',
65-
alias: 'qb',
66-
defaultConfig,
67-
})
62+
// Lazy-loaded config to avoid top-level await (enables bun --compile)
63+
let _config: QueryBuilderConfig | null = null
64+
65+
export async function getConfig(): Promise<QueryBuilderConfig> {
66+
if (!_config) {
67+
_config = await loadConfig({
68+
name: 'query-builder',
69+
alias: 'qb',
70+
defaultConfig,
71+
})
72+
}
73+
return _config
74+
}
75+
76+
// For backwards compatibility - synchronous access with default fallback
77+
export const config: QueryBuilderConfig = defaultConfig
78+
79+
/**
80+
* Programmatically set/override the query builder configuration.
81+
* This is useful when you want to configure bun-query-builder from
82+
* your application code rather than using a config file.
83+
*/
84+
export function setConfig(userConfig: Partial<QueryBuilderConfig>): void {
85+
// Merge user config with existing config
86+
Object.assign(config, userConfig)
87+
88+
// Handle nested objects like database, timestamps, etc.
89+
if (userConfig.database) {
90+
config.database = { ...config.database, ...userConfig.database }
91+
}
92+
if (userConfig.timestamps) {
93+
config.timestamps = { ...config.timestamps, ...userConfig.timestamps }
94+
}
95+
if (userConfig.pagination) {
96+
config.pagination = { ...config.pagination, ...userConfig.pagination }
97+
}
98+
if (userConfig.softDeletes) {
99+
config.softDeletes = { ...config.softDeletes, ...userConfig.softDeletes }
100+
}
101+
102+
// Also update the cached config if it exists
103+
if (_config) {
104+
Object.assign(_config, config)
105+
}
106+
}

packages/bun-query-builder/src/db.ts

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,22 +78,41 @@ export function getBunSql(): SQL {
7878
}
7979
}
8080

81-
// Note: This is created once when the module loads
82-
// Using a fallback in-memory SQLite if main database is unavailable
81+
// Note: Connection is created lazily on first access, not at module load time
8382
let _bunSqlInstance: SQL | null = null
83+
let _currentDialect: string | null = null
84+
let _currentDatabase: string | null = null
8485

8586
export function getOrCreateBunSql(forceNew = false): SQL {
86-
// If forceNew is true or we don't have an instance, create a new one
87-
if (forceNew || !_bunSqlInstance) {
87+
// Check if config has changed since we created the connection
88+
const configChanged = _bunSqlInstance !== null && (
89+
_currentDialect !== config.dialect
90+
|| _currentDatabase !== config.database.database
91+
)
92+
93+
// If forceNew is true, config changed, or we don't have an instance, create a new one
94+
if (forceNew || configChanged || !_bunSqlInstance) {
8895
_bunSqlInstance = getBunSql()
96+
_currentDialect = config.dialect
97+
_currentDatabase = config.database.database
8998
}
9099
return _bunSqlInstance
91100
}
92101

102+
/**
103+
* Resets the cached database connection.
104+
* Call this after changing config via setConfig() to ensure the new config is used.
105+
*/
106+
export function resetConnection(): void {
107+
_bunSqlInstance = null
108+
_currentDialect = null
109+
_currentDatabase = null
110+
}
111+
93112
// Wrapper that catches "Connection closed" errors and retries with a fresh connection
94113
export async function withFreshConnection<T>(fn: (sql: SQL) => Promise<T>): Promise<T> {
95114
try {
96-
return await fn(_bunSqlInstance || getOrCreateBunSql())
115+
return await fn(getOrCreateBunSql())
97116
}
98117
catch (error: any) {
99118
// If connection is closed, create a fresh connection and retry once
@@ -106,7 +125,33 @@ export async function withFreshConnection<T>(fn: (sql: SQL) => Promise<T>): Prom
106125
}
107126
}
108127

109-
export const bunSql = getOrCreateBunSql()
128+
/**
129+
* Lazy SQL connection proxy - connection is only created when first accessed.
130+
* This allows setConfig() to be called before any database connection is made.
131+
*/
132+
function createLazyBunSql(): SQL {
133+
// Create a proxy that lazily initializes the connection on first use
134+
return new Proxy({} as SQL, {
135+
get(_target, prop) {
136+
// Get or create the actual SQL instance
137+
const sql = getOrCreateBunSql()
138+
const value = (sql as any)[prop]
139+
// If it's a function, bind it to the sql instance
140+
if (typeof value === 'function') {
141+
return value.bind(sql)
142+
}
143+
return value
144+
},
145+
apply(_target, _thisArg, args) {
146+
// Handle tagged template literal calls: bunSql`SELECT ...`
147+
const sql = getOrCreateBunSql()
148+
return (sql as any)(...args)
149+
},
150+
})
151+
}
152+
153+
// Export a lazy proxy - no connection is made until first use
154+
export const bunSql: SQL = createLazyBunSql()
110155

111156
// Add global error handler for unhandled rejections from SQL connections
112157
if (typeof process !== 'undefined' && process.on) {
@@ -123,7 +168,6 @@ if (typeof process !== 'undefined' && process.on) {
123168
|| reason.code === '3D000')
124169
) {
125170
// Suppress these errors - they're expected when database isn't available
126-
127171
}
128172
}
129173
Object.defineProperty(sqlConnectionErrorHandler, 'name', { value: 'sqlConnectionErrorHandler' })

0 commit comments

Comments
 (0)