Skip to content

Commit 3e1ee21

Browse files
committed
Refactor code structure for improved readability and maintainability
1 parent 187d406 commit 3e1ee21

File tree

9 files changed

+10252
-16
lines changed

9 files changed

+10252
-16
lines changed

objectql.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export default {
55
filename: 'objectos.db'
66
}
77
},
8-
presets: [
8+
modules: [
99
'@objectql/starter-basic',
1010
'@objectql/starter-enterprise'
1111
]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export * from './loader';
22
export * from './plugin';
33
export * from './driver';
4+
export * from './module';
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { ObjectLoader } from './loader';
2+
import * as path from 'path';
3+
import * as fs from 'fs';
4+
5+
/**
6+
* Resolves a list of module names (npm packages or local paths) to their paths
7+
* and loads them using ObjectLoader.
8+
*/
9+
export async function loadModules(loader: ObjectLoader, modules: string[]) {
10+
if (!modules || modules.length === 0) return;
11+
12+
console.log(`Loading ${modules.length} modules...`);
13+
14+
for (const moduleName of modules) {
15+
try {
16+
// Check if it is a local path
17+
if (moduleName.startsWith('./') || moduleName.startsWith('/') || moduleName.startsWith('../')) {
18+
const localPath = path.resolve(process.cwd(), moduleName);
19+
if (fs.existsSync(localPath)) {
20+
console.log(` - ${moduleName} -> ${localPath}`);
21+
loader.load(localPath);
22+
continue;
23+
}
24+
}
25+
26+
// 1. Resolve package path
27+
// We use require.resolve to find the entry point, then go up to find the package root
28+
const entryPath = require.resolve(moduleName, { paths: [process.cwd()] });
29+
30+
// Let's try to find the package root directory
31+
let currentDir = path.dirname(entryPath);
32+
let packageRoot = '';
33+
34+
// Go up until we find package.json
35+
while (currentDir !== path.parse(currentDir).root) {
36+
if (fs.existsSync(path.join(currentDir, 'package.json'))) {
37+
// Check if name matches
38+
try {
39+
const pkg = require(path.join(currentDir, 'package.json'));
40+
if (pkg.name === moduleName) {
41+
packageRoot = currentDir;
42+
break;
43+
}
44+
} catch (e) {}
45+
}
46+
currentDir = path.dirname(currentDir);
47+
}
48+
49+
if (!packageRoot) {
50+
console.warn(`Could not find package root for module '${moduleName}'. Using entry directory.`);
51+
packageRoot = path.dirname(entryPath);
52+
}
53+
54+
// Now, where is the schema?
55+
// Convention: check 'src', then root.
56+
const srcDir = path.join(packageRoot, 'src');
57+
const targetDir = fs.existsSync(srcDir) ? srcDir : packageRoot;
58+
59+
console.log(` - ${moduleName} -> ${targetDir}`);
60+
61+
// Load it!
62+
loader.load(targetDir);
63+
64+
} catch (e: any) {
65+
console.warn(`Failed to load module '${moduleName}': ${e.message}`);
66+
}
67+
}
68+
}
69+
70+

packages/foundation/types/src/config.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,14 @@ export interface ObjectQLConfig {
2121
*/
2222
packages?: string[];
2323
/**
24-
* List of npm packages or presets to load.
24+
* @deprecated Use 'modules' instead.
2525
*/
2626
presets?: string[];
27+
/**
28+
* List of modules to load.
29+
* Can be npm packages or local directories.
30+
*/
31+
modules?: string[];
2732
/**
2833
* List of plugins to load.
2934
* Can be an instance of ObjectQLPlugin or a package name string.

packages/tools/cli/src/commands/dev.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,20 @@ import chalk from 'chalk';
88
export async function dev(options: {
99
port: number;
1010
dir: string;
11+
config?: string;
12+
modules?: string;
1113
watch?: boolean;
1214
}) {
1315
console.log(chalk.cyan('🚀 Starting ObjectQL Development Server...\n'));
1416

1517
// For now, delegate to serve command
1618
// In future, can add file watching and auto-reload
17-
await serve({ port: options.port, dir: options.dir });
19+
await serve({
20+
port: options.port,
21+
dir: options.dir,
22+
config: options.config,
23+
modules: options.modules
24+
});
1825

1926
if (options.watch !== false) {
2027
console.log(chalk.yellow('\n👀 Watching for file changes... (Not yet implemented)'));

packages/tools/cli/src/commands/serve.ts

Lines changed: 72 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { ObjectQL } from '@objectql/core';
22
import { SqlDriver } from '@objectql/driver-sql';
3-
import { ObjectLoader } from '@objectql/platform-node';
3+
import { ObjectLoader, loadModules } from '@objectql/platform-node';
44
import { createNodeHandler } from '@objectql/server';
55
import { createServer } from 'http';
66
import * as path from 'path';
7+
import * as fs from 'fs';
78
import chalk from 'chalk';
89

910
const CONSOLE_HTML = `
@@ -33,29 +34,89 @@ const CONSOLE_HTML = `
3334
</html>
3435
`;
3536

36-
export async function serve(options: { port: number; dir: string }) {
37+
export async function serve(options: {
38+
port: number;
39+
dir: string;
40+
config?: string;
41+
modules?: string;
42+
}) {
3743
console.log(chalk.blue('Starting ObjectQL Dev Server...'));
3844

3945
const rootDir = path.resolve(process.cwd(), options.dir);
4046
console.log(chalk.gray(`Loading schema from: ${rootDir}`));
4147

42-
// 1. Init ObjectQL with in-memory SQLite for Dev
48+
// Try to load configuration
49+
let config: any = null;
50+
const configPath = options.config || path.join(process.cwd(), 'objectql.config.ts');
51+
52+
if (fs.existsSync(configPath)) {
53+
try {
54+
console.log(chalk.gray(`Loading config from: ${configPath}`));
55+
if (configPath.endsWith('.ts')) {
56+
require('ts-node/register');
57+
}
58+
const loaded = require(configPath);
59+
config = loaded.default || loaded;
60+
} catch (e: any) {
61+
console.warn(chalk.yellow(`⚠️ Failed to load config: ${e.message}`));
62+
}
63+
} else if (options.config) {
64+
console.error(chalk.red(`❌ Config file not found: ${options.config}`));
65+
process.exit(1);
66+
}
67+
68+
// Process modules override
69+
if (options.modules) {
70+
const moduleList = options.modules.split(',').map(p => p.trim());
71+
if (!config) config = {};
72+
config.modules = moduleList;
73+
console.log(chalk.yellow(`⚠️ Overriding modules: ${moduleList.join(', ')}`));
74+
}
75+
76+
const loadedConfig = config?.datasource?.default || config?.datasources?.default;
77+
let datasourceValue = loadedConfig;
78+
79+
// Normalize config if it uses simplified format (type: 'sqlite')
80+
if (loadedConfig && !loadedConfig.client && loadedConfig.type === 'sqlite') {
81+
datasourceValue = {
82+
client: 'sqlite3',
83+
connection: {
84+
filename: loadedConfig.filename || ':memory:'
85+
},
86+
useNullAsDefault: true
87+
};
88+
}
89+
90+
const datasource = datasourceValue || {
91+
client: 'sqlite3',
92+
connection: {
93+
filename: ':memory:'
94+
},
95+
useNullAsDefault: true
96+
};
97+
98+
// 1. Init ObjectQL
4399
const app = new ObjectQL({
44100
datasources: {
45-
default: new SqlDriver({
46-
client: 'sqlite3',
47-
connection: {
48-
filename: ':memory:' // Or local file './dev.db'
49-
},
50-
useNullAsDefault: true
51-
})
52-
}
101+
default: new SqlDriver(datasource)
102+
},
103+
...config
53104
});
54105

55106
// 2. Load Schema
56107
try {
57108
const loader = new ObjectLoader(app.metadata);
109+
110+
// Load modules first (if any)
111+
// Backwards compatibility for presets
112+
const modulesToLoad = config?.modules || config?.presets;
113+
if (modulesToLoad) {
114+
await loadModules(loader, modulesToLoad);
115+
}
116+
117+
// Load project source
58118
loader.load(rootDir);
119+
59120
await app.init();
60121
console.log(chalk.green('✅ Schema loaded successfully.'));
61122
} catch (e: any) {

packages/tools/cli/src/commands/start.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { ObjectQL } from '@objectql/core';
22
import { SqlDriver } from '@objectql/driver-sql';
3-
import { ObjectLoader } from '@objectql/platform-node';
3+
import { ObjectLoader, loadModules } from '@objectql/platform-node';
44
import { createNodeHandler } from '@objectql/server';
55
import { createServer } from 'http';
66
import * as path from 'path';
@@ -11,6 +11,7 @@ interface StartOptions {
1111
port: number;
1212
dir: string;
1313
config?: string;
14+
modules?: string;
1415
}
1516

1617
// Flexible config type that handles both ObjectQLConfig and custom config formats
@@ -49,6 +50,14 @@ export async function start(options: StartOptions) {
4950
}
5051
}
5152

53+
// Process modules override
54+
if (options.modules) {
55+
const moduleList = options.modules.split(',').map(p => p.trim());
56+
if (!config) config = {};
57+
config.modules = moduleList;
58+
console.log(chalk.yellow(`⚠️ Overriding modules: ${moduleList.join(', ')}`));
59+
}
60+
5261
// Initialize datasource from config or use default SQLite
5362
// Note: Config files may use 'datasource' (singular) while ObjectQLConfig uses 'datasources' (plural)
5463
const datasourceConfig = config?.datasources?.default || config?.datasource?.default || {
@@ -67,7 +76,17 @@ export async function start(options: StartOptions) {
6776
// Load Schema
6877
try {
6978
const loader = new ObjectLoader(app.metadata);
79+
80+
// Load modules first (if any)
81+
// Backwards compatibility for presets
82+
const modulesToLoad = config?.modules || config?.presets;
83+
if (modulesToLoad) {
84+
await loadModules(loader, modulesToLoad);
85+
}
86+
87+
// Load project source
7088
loader.load(rootDir);
89+
7190
await app.init();
7291
console.log(chalk.green('✅ Schema loaded successfully.'));
7392
} catch (e: any) {

packages/tools/cli/src/index.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,11 +193,15 @@ program
193193
.description('Start development server with hot reload')
194194
.option('-p, --port <number>', 'Port to listen on', '3000')
195195
.option('-d, --dir <path>', 'Directory containing schema', '.')
196+
.option('-c, --config <path>', 'Path to objectql.config.ts/js')
197+
.option('--modules <items>', 'Comma-separated list of modules to load (overrides config)')
196198
.option('--no-watch', 'Disable file watching')
197199
.action(async (options) => {
198200
await dev({
199201
port: parseInt(options.port),
200202
dir: options.dir,
203+
config: options.config,
204+
modules: options.modules,
201205
watch: options.watch
202206
});
203207
});
@@ -209,11 +213,13 @@ program
209213
.option('-p, --port <number>', 'Port to listen on', '3000')
210214
.option('-d, --dir <path>', 'Directory containing schema', '.')
211215
.option('-c, --config <path>', 'Path to objectql.config.ts/js')
216+
.option('--modules <items>', 'Comma-separated list of modules to load (overrides config)')
212217
.action(async (options) => {
213218
await start({
214219
port: parseInt(options.port),
215220
dir: options.dir,
216-
config: options.config
221+
config: options.config,
222+
modules: options.modules
217223
});
218224
});
219225

0 commit comments

Comments
 (0)