Skip to content

Commit 6221013

Browse files
Claudehotlong
andauthored
fix: use dynamic imports in EnvironmentDriverRegistry to avoid circular deps
- Replace static imports with dynamic imports for drivers - Add NoopSecretEncryptor to runtime package (avoid cross-package dependency) - Export SecretEncryptor interface from runtime - Use correct SqlDriver configuration for SQLite (better-sqlite3 client) Agent-Logs-Url: https://github.com/objectstack-ai/framework/sessions/8385b77f-f7ed-4241-8e09-25c65d8d98b0 Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent 8d0f0cd commit 6221013

2 files changed

Lines changed: 42 additions & 13 deletions

File tree

packages/runtime/src/environment-registry.ts

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,6 @@
22

33
import type { Contracts } from '@objectstack/spec';
44
type IDataDriver = Contracts.IDataDriver;
5-
import { TursoDriver } from '@objectstack/driver-turso';
6-
import { InMemoryDriver } from '@objectstack/driver-memory';
7-
import { NoopSecretEncryptor } from '@objectstack/service-tenant/environment-provisioning';
8-
import { LocalSQLiteDriver } from '@objectstack/driver-sql/local-sqlite';
95

106
/**
117
* Environment-scoped driver registry with LRU caching.
@@ -44,20 +40,42 @@ interface CacheEntry {
4440
expiresAt: number;
4541
}
4642

43+
/**
44+
* Secret encryptor interface - must match service-tenant NoopSecretEncryptor
45+
*/
46+
export interface SecretEncryptor {
47+
readonly keyId: string;
48+
encrypt(plaintext: string): Promise<string> | string;
49+
decrypt(ciphertext: string): Promise<string> | string;
50+
}
51+
52+
/**
53+
* No-op encryptor used in development / tests. **Never** use in production.
54+
*/
55+
export class NoopSecretEncryptor implements SecretEncryptor {
56+
readonly keyId = 'noop';
57+
encrypt(plaintext: string): string {
58+
return plaintext;
59+
}
60+
decrypt(ciphertext: string): string {
61+
return ciphertext;
62+
}
63+
}
64+
4765
/**
4866
* Default implementation of EnvironmentDriverRegistry with LRU caching.
4967
*/
5068
export class DefaultEnvironmentDriverRegistry implements EnvironmentDriverRegistry {
5169
private readonly controlPlaneDriver: IDataDriver;
52-
private readonly encryptor: NoopSecretEncryptor;
70+
private readonly encryptor: SecretEncryptor;
5371
private readonly cacheTTL: number;
5472
private readonly hostnameCache = new Map<string, CacheEntry>();
5573
private readonly idCache = new Map<string, CacheEntry>();
5674
private readonly pendingResolves = new Map<string, Promise<CacheEntry | null>>();
5775

5876
constructor(config: {
5977
controlPlaneDriver: IDataDriver;
60-
encryptor?: NoopSecretEncryptor;
78+
encryptor?: SecretEncryptor;
6179
cacheTTLMs?: number;
6280
}) {
6381
this.controlPlaneDriver = config.controlPlaneDriver;
@@ -219,7 +237,7 @@ export class DefaultEnvironmentDriverRegistry implements EnvironmentDriverRegist
219237
);
220238

221239
// Instantiate driver based on driver type
222-
const driver = this.createDriver(databaseDriver, databaseUrl, plaintextSecret);
240+
const driver = await this.createDriver(databaseDriver, databaseUrl, plaintextSecret);
223241

224242
return {
225243
environmentId,
@@ -228,11 +246,13 @@ export class DefaultEnvironmentDriverRegistry implements EnvironmentDriverRegist
228246
};
229247
}
230248

231-
private createDriver(driverType: string, databaseUrl: string, authToken: string): IDataDriver {
249+
private async createDriver(driverType: string, databaseUrl: string, authToken: string): Promise<IDataDriver> {
250+
// Dynamic import drivers to avoid circular dependencies
232251
switch (driverType) {
233252
case 'memory': {
234253
// Memory driver: URL format is memory://dbname or memory://
235254
const dbName = databaseUrl.replace('memory://', '') || 'default';
255+
const { InMemoryDriver } = await import('@objectstack/driver-memory');
236256
return new InMemoryDriver({
237257
name: `com.objectstack.driver.memory.${dbName}`,
238258
persistence: 'file', // Use file persistence for environments
@@ -242,14 +262,19 @@ export class DefaultEnvironmentDriverRegistry implements EnvironmentDriverRegist
242262
case 'sqlite': {
243263
// SQLite driver: URL format is file:./path/to/db.db
244264
const filePath = databaseUrl.replace('file:', '');
245-
return new LocalSQLiteDriver({
246-
name: 'com.objectstack.driver.sql',
247-
url: filePath,
265+
const { SqlDriver } = await import('@objectstack/driver-sql');
266+
return new SqlDriver({
267+
client: 'better-sqlite3',
268+
connection: {
269+
filename: filePath,
270+
},
271+
useNullAsDefault: true,
248272
});
249273
}
250274

251275
case 'turso': {
252276
// Turso driver: URL format is libsql://hostname
277+
const { TursoDriver } = await import('@objectstack/driver-turso');
253278
return new TursoDriver({
254279
name: 'com.objectstack.driver.turso',
255280
url: databaseUrl,
@@ -269,7 +294,7 @@ export class DefaultEnvironmentDriverRegistry implements EnvironmentDriverRegist
269294
export function createEnvironmentDriverRegistry(
270295
controlPlaneDriver: IDataDriver,
271296
options?: {
272-
encryptor?: NoopSecretEncryptor;
297+
encryptor?: SecretEncryptor;
273298
cacheTTLMs?: number;
274299
},
275300
): EnvironmentDriverRegistry {

packages/runtime/src/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,12 @@ export { MiddlewareManager } from './middleware.js';
2424
export {
2525
DefaultEnvironmentDriverRegistry,
2626
createEnvironmentDriverRegistry,
27+
NoopSecretEncryptor,
28+
} from './environment-registry.js';
29+
export type {
30+
EnvironmentDriverRegistry,
31+
SecretEncryptor,
2732
} from './environment-registry.js';
28-
export type { EnvironmentDriverRegistry } from './environment-registry.js';
2933

3034
// Re-export from @objectstack/rest
3135
export {

0 commit comments

Comments
 (0)