@scriptdb/dmr 1.0.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.
- package/README.md +245 -0
- package/dist/index.js +45 -0
- package/package.json +40 -0
package/README.md
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
# @scriptdb/dmr
|
|
2
|
+
|
|
3
|
+
Database Module Resolver for the script database, providing dynamic module loading and resolution capabilities for database-related modules.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Dynamic module loading**: Load modules from directories at runtime
|
|
8
|
+
- **Module registry**: Maintain a registry of all loaded modules
|
|
9
|
+
- **Require-like functionality**: Access modules using a require-like API
|
|
10
|
+
- **Import functionality**: Access modules using an import-like API
|
|
11
|
+
- **Context creation**: Create a context with all loaded modules
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
bun add @scriptdb/dmr
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import { DatabaseModuleResolver } from '@scriptdb/dmr';
|
|
23
|
+
|
|
24
|
+
// Resolve modules from a directory
|
|
25
|
+
const context = await DatabaseModuleResolver('./database-modules');
|
|
26
|
+
|
|
27
|
+
// Access modules directly from the context
|
|
28
|
+
const userModule = context.user;
|
|
29
|
+
const authModule = context.auth;
|
|
30
|
+
|
|
31
|
+
// Or use the require-like functionality
|
|
32
|
+
const utils = context.require('utils');
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## API Reference
|
|
36
|
+
|
|
37
|
+
### DatabaseModuleResolver(basePath)
|
|
38
|
+
|
|
39
|
+
Resolves and loads modules from the specified directory, creating a context with all loaded modules.
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
await DatabaseModuleResolver(basePath: string): Promise<Record<string, any>>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
- `basePath` (string): The base directory path where modules are located
|
|
46
|
+
|
|
47
|
+
Returns a promise that resolves with a context object containing all loaded modules.
|
|
48
|
+
|
|
49
|
+
### Context Methods
|
|
50
|
+
|
|
51
|
+
#### require(moduleName)
|
|
52
|
+
|
|
53
|
+
Loads a module by name.
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
context.require(moduleName: string): any
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
- `moduleName` (string): The name of the module to load
|
|
60
|
+
|
|
61
|
+
Returns the module's default export if available, otherwise the module itself.
|
|
62
|
+
|
|
63
|
+
#### import(moduleName)
|
|
64
|
+
|
|
65
|
+
Asynchronously loads a module by name.
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
context.import(moduleName: string): Promise<{ default: any }>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
- `moduleName` (string): The name of the module to load
|
|
72
|
+
|
|
73
|
+
Returns a promise that resolves with an object containing the module's default export.
|
|
74
|
+
|
|
75
|
+
## Module Structure
|
|
76
|
+
|
|
77
|
+
To be compatible with the Database Module Resolver, your modules should be TypeScript files (.ts) in the specified directory:
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
database-modules/
|
|
81
|
+
├── user.ts # User module
|
|
82
|
+
├── auth.ts # Authentication module
|
|
83
|
+
├── utils.ts # Utility module
|
|
84
|
+
└── index.ts # Optional main entry point
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Each module can export functions, classes, or objects:
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
// database-modules/user.ts
|
|
91
|
+
export interface User {
|
|
92
|
+
id: number;
|
|
93
|
+
name: string;
|
|
94
|
+
email: string;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export class UserService {
|
|
98
|
+
async getUser(id: number): Promise<User> {
|
|
99
|
+
// Implementation here
|
|
100
|
+
return { id, name: 'John Doe', email: 'john@example.com' };
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export default new UserService();
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Examples
|
|
108
|
+
|
|
109
|
+
### Basic Module Loading
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
import { DatabaseModuleResolver } from '@scriptdb/dmr';
|
|
113
|
+
|
|
114
|
+
// Load modules from the ./database-modules directory
|
|
115
|
+
const context = await DatabaseModuleResolver('./database-modules');
|
|
116
|
+
|
|
117
|
+
// Access modules directly
|
|
118
|
+
const userModule = context.user;
|
|
119
|
+
if (userModule && userModule.getUser) {
|
|
120
|
+
const user = await userModule.getUser(1);
|
|
121
|
+
console.log(user);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Use the require-like functionality
|
|
125
|
+
const utils = context.require('utils');
|
|
126
|
+
if (utils && utils.formatDate) {
|
|
127
|
+
const formattedDate = utils.formatDate(new Date());
|
|
128
|
+
console.log(formattedDate);
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Module with Default Export
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
// database-modules/database.ts
|
|
136
|
+
export class Database {
|
|
137
|
+
private connection: any;
|
|
138
|
+
|
|
139
|
+
constructor() {
|
|
140
|
+
// Initialize connection
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
async query(sql: string, params?: any[]) {
|
|
144
|
+
// Execute query
|
|
145
|
+
return { sql, params, results: [] };
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
async close() {
|
|
149
|
+
// Close connection
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export default new Database();
|
|
154
|
+
|
|
155
|
+
// main.ts
|
|
156
|
+
import { DatabaseModuleResolver } from '@scriptdb/dmr';
|
|
157
|
+
|
|
158
|
+
const context = await DatabaseModuleResolver('./database-modules');
|
|
159
|
+
|
|
160
|
+
// Access the default export
|
|
161
|
+
const db = context.database;
|
|
162
|
+
const result = await db.query('SELECT * FROM users');
|
|
163
|
+
console.log(result);
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Using the Import Functionality
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
import { DatabaseModuleResolver } from '@scriptdb/dmr';
|
|
170
|
+
|
|
171
|
+
const context = await DatabaseModuleResolver('./database-modules');
|
|
172
|
+
|
|
173
|
+
// Use the import functionality to load a module
|
|
174
|
+
const module = await context.import('auth');
|
|
175
|
+
const authService = module.default;
|
|
176
|
+
|
|
177
|
+
if (authService && authService.authenticate) {
|
|
178
|
+
const result = await authService.authenticate('username', 'password');
|
|
179
|
+
console.log(result);
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Advanced Usage with Type Safety
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
import { DatabaseModuleResolver } from '@scriptdb/dmr';
|
|
187
|
+
|
|
188
|
+
interface ModuleContext {
|
|
189
|
+
user?: {
|
|
190
|
+
getUser: (id: number) => Promise<{ id: number; name: string }>;
|
|
191
|
+
};
|
|
192
|
+
auth?: {
|
|
193
|
+
authenticate: (username: string, password: string) => Promise<boolean>;
|
|
194
|
+
};
|
|
195
|
+
utils?: {
|
|
196
|
+
formatDate: (date: Date) => string;
|
|
197
|
+
};
|
|
198
|
+
require: (moduleName: string) => any;
|
|
199
|
+
import: (moduleName: string) => Promise<{ default: any }>;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const context = await DatabaseModuleResolver('./database-modules') as ModuleContext;
|
|
203
|
+
|
|
204
|
+
if (context.user && context.auth) {
|
|
205
|
+
const user = await context.user.getUser(1);
|
|
206
|
+
const isAuthenticated = await context.auth.authenticate('username', 'password');
|
|
207
|
+
|
|
208
|
+
console.log(`User: ${user.name}, Authenticated: ${isAuthenticated}`);
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## Error Handling
|
|
213
|
+
|
|
214
|
+
The Database Module Resolver will throw an error if:
|
|
215
|
+
|
|
216
|
+
- The specified directory doesn't exist
|
|
217
|
+
- There are syntax errors in the module code
|
|
218
|
+
- A module is not found when using require() or import()
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
import { DatabaseModuleResolver } from '@scriptdb/dmr';
|
|
222
|
+
|
|
223
|
+
try {
|
|
224
|
+
const context = await DatabaseModuleResolver('./non-existent-directory');
|
|
225
|
+
} catch (error) {
|
|
226
|
+
console.error('Failed to load modules:', error.message);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
try {
|
|
230
|
+
const module = context.require('non-existent-module');
|
|
231
|
+
} catch (error) {
|
|
232
|
+
console.error('Module not found:', error.message);
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
## Security Considerations
|
|
237
|
+
|
|
238
|
+
- Only load modules from trusted sources
|
|
239
|
+
- Validate module functionality before use
|
|
240
|
+
- Consider implementing a sandboxed environment for untrusted modules
|
|
241
|
+
- Limit module access to sensitive resources
|
|
242
|
+
|
|
243
|
+
## License
|
|
244
|
+
|
|
245
|
+
MIT
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
async function DatabaseModuleResolver(baseBase) {
|
|
5
|
+
const DIR = baseBase;
|
|
6
|
+
const moduleRegistry = new Map;
|
|
7
|
+
const files = fs.readdirSync(DIR).filter((f) => f.endsWith(".ts")).map((f) => path.join(DIR, f));
|
|
8
|
+
for (const filePath of files) {
|
|
9
|
+
const moduleName = path.basename(filePath, ".ts");
|
|
10
|
+
moduleRegistry.set(moduleName, await import(path.resolve(filePath)));
|
|
11
|
+
}
|
|
12
|
+
const context = {
|
|
13
|
+
require: (moduleName) => {
|
|
14
|
+
const module = moduleRegistry.get(moduleName);
|
|
15
|
+
if (!module) {
|
|
16
|
+
throw new Error(`Module '${moduleName}' not found`);
|
|
17
|
+
}
|
|
18
|
+
return module.default || module;
|
|
19
|
+
},
|
|
20
|
+
import: async (moduleName) => {
|
|
21
|
+
const module = moduleRegistry.get(moduleName);
|
|
22
|
+
if (!module) {
|
|
23
|
+
throw new Error(`Module '${moduleName}' not found`);
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
default: module.default || module
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
for (const [name, moduleExports] of moduleRegistry) {
|
|
31
|
+
if (moduleExports.default) {
|
|
32
|
+
context[name] = moduleExports.default;
|
|
33
|
+
} else if (moduleExports[name]) {
|
|
34
|
+
context[name] = moduleExports[name];
|
|
35
|
+
} else {
|
|
36
|
+
context[name] = moduleExports;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return context;
|
|
40
|
+
}
|
|
41
|
+
var src_default = DatabaseModuleResolver;
|
|
42
|
+
export {
|
|
43
|
+
src_default as default,
|
|
44
|
+
DatabaseModuleResolver
|
|
45
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@scriptdb/dmr",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "DMR module resolver for script database",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"dev": "bun --watch src/index.ts",
|
|
20
|
+
"build": "bun build src/index.ts --outdir dist --target node --format esm --splitting",
|
|
21
|
+
"build:cjs": "bun build src/index.ts --outdir dist --target node --format cjs --outfile dist/index.js",
|
|
22
|
+
"build:types": "tsc --emitDeclarationOnly --project tsconfig.build.json",
|
|
23
|
+
"build:all": "bun run build && bun run build:cjs && bun run build:types",
|
|
24
|
+
"test": "bun test",
|
|
25
|
+
"lint": "bun run lint:src",
|
|
26
|
+
"lint:src": "eslint src --ext .ts,.tsx",
|
|
27
|
+
"lint:fix": "eslint src --ext .ts,.tsx --fix",
|
|
28
|
+
"typecheck": "tsc --noEmit",
|
|
29
|
+
"clean": "rm -rf dist"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/bun": "^1.3.2",
|
|
33
|
+
"@types/node": "^20.0.0",
|
|
34
|
+
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
|
35
|
+
"@typescript-eslint/parser": "^6.0.0",
|
|
36
|
+
"bun-types": "latest",
|
|
37
|
+
"eslint": "^8.0.0",
|
|
38
|
+
"typescript": "^5.0.0"
|
|
39
|
+
}
|
|
40
|
+
}
|