@superfunctions/cli 0.1.0 → 0.1.3
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 +582 -104
- package/dist/cli.js +66 -53
- package/dist/cli.js.map +1 -1
- package/dist/commands/generate-schema.d.ts +12 -0
- package/dist/commands/generate-schema.d.ts.map +1 -0
- package/dist/commands/generate-schema.js +156 -0
- package/dist/commands/generate-schema.js.map +1 -0
- package/dist/commands/generate.d.ts.map +1 -1
- package/dist/commands/generate.js +104 -25
- package/dist/commands/generate.js.map +1 -1
- package/dist/commands/init.d.ts +4 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +38 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +2 -1
- package/dist/commands/status.js.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/utils/adapter-helper.d.ts.map +1 -1
- package/dist/utils/adapter-helper.js +0 -1
- package/dist/utils/adapter-helper.js.map +1 -1
- package/dist/utils/auto-discover.d.ts +28 -0
- package/dist/utils/auto-discover.d.ts.map +1 -0
- package/dist/utils/auto-discover.js +75 -0
- package/dist/utils/auto-discover.js.map +1 -0
- package/dist/utils/discover-packages.d.ts +29 -0
- package/dist/utils/discover-packages.d.ts.map +1 -0
- package/dist/utils/discover-packages.js +86 -0
- package/dist/utils/discover-packages.js.map +1 -0
- package/dist/utils/parse-library-init.d.ts +23 -0
- package/dist/utils/parse-library-init.d.ts.map +1 -0
- package/dist/utils/parse-library-init.js +191 -0
- package/dist/utils/parse-library-init.js.map +1 -0
- package/dist/utils/schema-generators.d.ts +13 -0
- package/dist/utils/schema-generators.d.ts.map +1 -0
- package/dist/utils/schema-generators.js +224 -0
- package/dist/utils/schema-generators.js.map +1 -0
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -13,15 +13,65 @@ npm install @prisma/client # For Prisma
|
|
|
13
13
|
npm install kysely # For Kysely
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
---
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
## For Downstream Users (Using Superfunctions Libraries)
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
### Quick Start
|
|
21
|
+
|
|
22
|
+
#### 1. Initialize Your Libraries
|
|
23
|
+
|
|
24
|
+
Configure your libraries once in your application code:
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
// src/conduct.ts
|
|
28
|
+
import { createConductBackend } from 'conduct';
|
|
29
|
+
import { adapter } from './db';
|
|
30
|
+
|
|
31
|
+
export const conduct = createConductBackend({
|
|
32
|
+
database: adapter,
|
|
33
|
+
storage: s3Storage,
|
|
34
|
+
|
|
35
|
+
// Schema customizations
|
|
36
|
+
additionalFields: {
|
|
37
|
+
project: {
|
|
38
|
+
department: { type: 'string', required: false },
|
|
39
|
+
priority: { type: 'number', required: false },
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
plugins: [
|
|
44
|
+
conductAuditPlugin(),
|
|
45
|
+
]
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
// src/auth.ts
|
|
51
|
+
import { createAuthFn } from '@superfunctions/authfn';
|
|
52
|
+
import { adapter } from './db';
|
|
53
|
+
|
|
54
|
+
export const auth = createAuthFn({
|
|
55
|
+
database: adapter,
|
|
56
|
+
|
|
57
|
+
additionalFields: {
|
|
58
|
+
user: {
|
|
59
|
+
role: { type: 'string', required: true },
|
|
60
|
+
department: { type: 'string', required: false },
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
plugins: [
|
|
65
|
+
authFnTwoFactorPlugin(),
|
|
66
|
+
],
|
|
67
|
+
});
|
|
22
68
|
```
|
|
23
69
|
|
|
24
|
-
|
|
70
|
+
#### 2. Configure CLI
|
|
71
|
+
|
|
72
|
+
Create `superfunctions.config.js`:
|
|
73
|
+
|
|
74
|
+
**Option A: Explicit file paths (recommended for production)**
|
|
25
75
|
|
|
26
76
|
```javascript
|
|
27
77
|
import { defineConfig } from '@superfunctions/cli';
|
|
@@ -34,80 +84,64 @@ export default defineConfig({
|
|
|
34
84
|
connectionString: process.env.DATABASE_URL,
|
|
35
85
|
}
|
|
36
86
|
},
|
|
87
|
+
|
|
88
|
+
// Point to files that initialize libraries
|
|
89
|
+
libraries: [
|
|
90
|
+
'./src/conduct.ts',
|
|
91
|
+
'./src/auth.ts',
|
|
92
|
+
],
|
|
93
|
+
|
|
37
94
|
migrationsDir: './migrations',
|
|
38
95
|
});
|
|
39
96
|
```
|
|
40
97
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
For each @superfunctions library you use, create a config file following the pattern: `<library-name>.config.ts`
|
|
98
|
+
**Option B: Auto-discovery (good for small projects/prototyping)**
|
|
44
99
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
```typescript
|
|
48
|
-
import type { ConductSchemaConfig } from 'conduct';
|
|
100
|
+
```javascript
|
|
101
|
+
import { defineConfig } from '@superfunctions/cli';
|
|
49
102
|
|
|
50
|
-
export
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
fields: {
|
|
58
|
-
slug: 'project_slug',
|
|
59
|
-
}
|
|
60
|
-
},
|
|
103
|
+
export default defineConfig({
|
|
104
|
+
adapter: {
|
|
105
|
+
type: 'drizzle',
|
|
106
|
+
drizzle: {
|
|
107
|
+
dialect: 'postgres',
|
|
108
|
+
connectionString: process.env.DATABASE_URL,
|
|
109
|
+
}
|
|
61
110
|
},
|
|
62
111
|
|
|
63
|
-
//
|
|
64
|
-
|
|
65
|
-
project: {
|
|
66
|
-
customField: { type: 'string', required: false },
|
|
67
|
-
},
|
|
68
|
-
},
|
|
112
|
+
// Auto-discover initialization files
|
|
113
|
+
autoDiscover: true, // Scans src/, lib/, server/, app/ directories
|
|
69
114
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
// conductAuditPlugin(),
|
|
73
|
-
// conductMetricsPlugin(),
|
|
74
|
-
],
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
export default config;
|
|
115
|
+
migrationsDir: './migrations',
|
|
116
|
+
});
|
|
78
117
|
```
|
|
79
118
|
|
|
80
|
-
**
|
|
119
|
+
**Option C: Custom auto-discovery patterns**
|
|
81
120
|
|
|
82
|
-
```
|
|
83
|
-
import
|
|
121
|
+
```javascript
|
|
122
|
+
import { defineConfig } from '@superfunctions/cli';
|
|
84
123
|
|
|
85
|
-
export
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
models: {
|
|
89
|
-
user: {
|
|
90
|
-
modelName: 'users',
|
|
91
|
-
},
|
|
92
|
-
},
|
|
124
|
+
export default defineConfig({
|
|
125
|
+
adapter: { /* ... */ },
|
|
93
126
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
127
|
+
// Custom patterns
|
|
128
|
+
autoDiscover: {
|
|
129
|
+
patterns: [
|
|
130
|
+
'src/**/*.ts',
|
|
131
|
+
'api/**/*.ts',
|
|
132
|
+
],
|
|
133
|
+
exclude: [
|
|
134
|
+
'**/*.test.ts',
|
|
135
|
+
'**/*.spec.ts',
|
|
136
|
+
'**/examples/**',
|
|
137
|
+
]
|
|
98
138
|
},
|
|
99
139
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
],
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
export default config;
|
|
140
|
+
migrationsDir: './migrations',
|
|
141
|
+
});
|
|
106
142
|
```
|
|
107
143
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
The CLI auto-discovers your library configs:
|
|
144
|
+
#### 3. Generate Migrations
|
|
111
145
|
|
|
112
146
|
```bash
|
|
113
147
|
npx superfunctions generate
|
|
@@ -115,15 +149,18 @@ npx superfunctions generate
|
|
|
115
149
|
|
|
116
150
|
**Output:**
|
|
117
151
|
```
|
|
118
|
-
🔍
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
- authfn (./authfn.config.ts)
|
|
152
|
+
🔍 Parsing library initialization files...
|
|
153
|
+
✅ ./src/conduct.ts: Found 1 initialization(s)
|
|
154
|
+
✅ ./src/auth.ts: Found 1 initialization(s)
|
|
122
155
|
|
|
123
|
-
|
|
156
|
+
📦 Found 2 library initialization(s):
|
|
157
|
+
- conduct (createConductBackend)
|
|
158
|
+
- authfn (createAuthFn)
|
|
159
|
+
|
|
160
|
+
📖 Processing conduct...
|
|
124
161
|
✅ Generated schema (v1, 8 tables)
|
|
125
162
|
|
|
126
|
-
📖
|
|
163
|
+
📖 Processing authfn...
|
|
127
164
|
✅ Generated schema (v1, 4 tables)
|
|
128
165
|
|
|
129
166
|
💾 Writing migration files...
|
|
@@ -138,7 +175,7 @@ npx superfunctions generate
|
|
|
138
175
|
npx drizzle-kit push
|
|
139
176
|
```
|
|
140
177
|
|
|
141
|
-
|
|
178
|
+
#### 4. Apply Migrations
|
|
142
179
|
|
|
143
180
|
Use your ORM tool to apply migrations:
|
|
144
181
|
|
|
@@ -150,16 +187,166 @@ npx prisma migrate deploy
|
|
|
150
187
|
npx kysely migrate latest
|
|
151
188
|
```
|
|
152
189
|
|
|
153
|
-
|
|
190
|
+
### Benefits of This Approach
|
|
154
191
|
|
|
155
|
-
|
|
192
|
+
✅ **Single source of truth**: Configure libraries once in your app code
|
|
193
|
+
✅ **No duplication**: CLI reads from your actual initialization
|
|
194
|
+
✅ **Type safety**: Full IDE autocomplete and type checking
|
|
195
|
+
✅ **Less boilerplate**: No separate `*.config.ts` files needed
|
|
156
196
|
|
|
157
|
-
|
|
197
|
+
---
|
|
158
198
|
|
|
159
|
-
|
|
160
|
-
|
|
199
|
+
## For Library Authors (Building with @superfunctions/db)
|
|
200
|
+
|
|
201
|
+
If you're building a library that uses `@superfunctions/db` adapter, you need to export a `getSchema` function for CLI integration.
|
|
202
|
+
|
|
203
|
+
### Required Export
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
// your-library/src/schema/index.ts
|
|
207
|
+
import type { TableSchema } from '@superfunctions/db';
|
|
208
|
+
|
|
209
|
+
export interface YourLibraryConfig {
|
|
210
|
+
// Your library's config structure
|
|
211
|
+
additionalFields?: Record<string, Record<string, FieldDefinition>>;
|
|
212
|
+
plugins?: Plugin[];
|
|
213
|
+
// ... other options
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Generate schema from config
|
|
218
|
+
* This is called by @superfunctions/cli to generate migrations
|
|
219
|
+
*/
|
|
220
|
+
export function getSchema(config: YourLibraryConfig = {}): {
|
|
221
|
+
version: number;
|
|
222
|
+
schemas: TableSchema[];
|
|
223
|
+
} {
|
|
224
|
+
const baseSchema = getBaseSchema(config);
|
|
225
|
+
const pluginSchemas = getPluginSchemas(config);
|
|
226
|
+
|
|
227
|
+
return {
|
|
228
|
+
version: 1, // Increment when schema changes
|
|
229
|
+
schemas: [
|
|
230
|
+
...baseSchema,
|
|
231
|
+
...pluginSchemas,
|
|
232
|
+
],
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function getBaseSchema(config: YourLibraryConfig): TableSchema[] {
|
|
237
|
+
return [
|
|
238
|
+
{
|
|
239
|
+
modelName: 'your_table',
|
|
240
|
+
fields: {
|
|
241
|
+
id: { type: 'number', required: true },
|
|
242
|
+
name: { type: 'string', required: true },
|
|
243
|
+
...config.additionalFields?.your_table, // Apply custom fields
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
// ... more tables
|
|
247
|
+
];
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function getPluginSchemas(config: YourLibraryConfig): TableSchema[] {
|
|
251
|
+
if (!config.plugins || config.plugins.length === 0) {
|
|
252
|
+
return [];
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const schemas: TableSchema[] = [];
|
|
256
|
+
for (const plugin of config.plugins) {
|
|
257
|
+
if (plugin.schema) {
|
|
258
|
+
// Plugins can contribute additional tables
|
|
259
|
+
schemas.push(...Object.values(plugin.schema));
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return schemas;
|
|
263
|
+
}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### Export from Main Entry Point
|
|
267
|
+
|
|
268
|
+
```typescript
|
|
269
|
+
// your-library/src/index.ts
|
|
270
|
+
|
|
271
|
+
// Runtime exports
|
|
272
|
+
export { createYourLibrary } from './main.js';
|
|
273
|
+
export type { YourLibraryConfig } from './types.js';
|
|
274
|
+
|
|
275
|
+
// CLI integration export
|
|
276
|
+
export { getSchema } from './schema/index.js';
|
|
277
|
+
export type { YourLibraryConfig as YourLibrarySchemaConfig } from './schema/index.js';
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### Add Package Metadata
|
|
281
|
+
|
|
282
|
+
Add `superfunctions` metadata to your `package.json`:
|
|
283
|
+
|
|
284
|
+
```json
|
|
285
|
+
{
|
|
286
|
+
"name": "@your-org/your-library",
|
|
287
|
+
"version": "1.0.0",
|
|
288
|
+
|
|
289
|
+
"superfunctions": {
|
|
290
|
+
"initFunction": "createYourLibrary",
|
|
291
|
+
"schemaVersion": 1
|
|
292
|
+
},
|
|
293
|
+
|
|
294
|
+
"exports": {
|
|
295
|
+
".": "./dist/index.js"
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
**Fields:**
|
|
301
|
+
- `initFunction` (required): Name of your library's initialization function
|
|
302
|
+
- `schemaVersion` (optional): Current schema version number
|
|
303
|
+
|
|
304
|
+
The CLI will automatically discover your library by scanning `node_modules` for packages with this metadata. **No registration with the CLI repo needed!**
|
|
305
|
+
|
|
306
|
+
### Plugin Schema Support
|
|
307
|
+
|
|
308
|
+
Plugins can add their own tables:
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
// Plugin example
|
|
312
|
+
export function yourLibraryAuditPlugin() {
|
|
313
|
+
return {
|
|
314
|
+
name: 'audit',
|
|
315
|
+
schema: {
|
|
316
|
+
audit_log: {
|
|
317
|
+
modelName: 'audit_logs',
|
|
318
|
+
fields: {
|
|
319
|
+
id: { type: 'number', required: true },
|
|
320
|
+
entity_type: { type: 'string', required: true },
|
|
321
|
+
entity_id: { type: 'string', required: true },
|
|
322
|
+
action: { type: 'string', required: true },
|
|
323
|
+
user_id: { type: 'string', required: false },
|
|
324
|
+
timestamp: { type: 'date', required: true },
|
|
325
|
+
changes: { type: 'json', required: false },
|
|
326
|
+
},
|
|
327
|
+
},
|
|
328
|
+
},
|
|
329
|
+
// ... plugin logic
|
|
330
|
+
};
|
|
331
|
+
}
|
|
161
332
|
```
|
|
162
333
|
|
|
334
|
+
When users enable the plugin in their config:
|
|
335
|
+
|
|
336
|
+
```typescript
|
|
337
|
+
createYourLibrary({
|
|
338
|
+
plugins: [
|
|
339
|
+
yourLibraryAuditPlugin(),
|
|
340
|
+
]
|
|
341
|
+
});
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
The CLI will automatically include the audit_logs table in the generated migrations.
|
|
345
|
+
|
|
346
|
+
---
|
|
347
|
+
|
|
348
|
+
## CLI Commands
|
|
349
|
+
|
|
163
350
|
### `generate [library]`
|
|
164
351
|
|
|
165
352
|
Generate migration files from schema diffs.
|
|
@@ -183,6 +370,21 @@ Check current schema versions and migration status.
|
|
|
183
370
|
npx superfunctions status
|
|
184
371
|
```
|
|
185
372
|
|
|
373
|
+
**Output:**
|
|
374
|
+
```
|
|
375
|
+
📊 Schema Status
|
|
376
|
+
|
|
377
|
+
Library: conduct
|
|
378
|
+
Current version: 1
|
|
379
|
+
Latest version: 1
|
|
380
|
+
Status: ✅ Up-to-date
|
|
381
|
+
|
|
382
|
+
Library: authfn
|
|
383
|
+
Current version: 0
|
|
384
|
+
Latest version: 1
|
|
385
|
+
Status: ⚠️ Needs migration
|
|
386
|
+
```
|
|
387
|
+
|
|
186
388
|
### `validate`
|
|
187
389
|
|
|
188
390
|
Validate configuration file structure.
|
|
@@ -191,57 +393,333 @@ Validate configuration file structure.
|
|
|
191
393
|
npx superfunctions validate
|
|
192
394
|
```
|
|
193
395
|
|
|
194
|
-
|
|
396
|
+
---
|
|
397
|
+
|
|
398
|
+
## How It Works
|
|
399
|
+
|
|
400
|
+
### High-Level Flow
|
|
401
|
+
|
|
402
|
+
1. **Parse initialization files**: CLI reads files specified in `libraries` array
|
|
403
|
+
2. **Extract configs**: Uses TypeScript AST parser to extract library initialization calls and their configs
|
|
404
|
+
3. **Generate schemas**: For each library, calls `libraryPackage.getSchema(extractedConfig)`
|
|
405
|
+
4. **Introspect database**: Connects to database and reads current schema
|
|
406
|
+
5. **Diff schemas**: Compares desired schema with current state
|
|
407
|
+
6. **Generate migrations**: Creates ORM-specific SQL migration files
|
|
408
|
+
7. **Track versions**: Stores schema versions in database for tracking
|
|
409
|
+
|
|
410
|
+
### What Gets Parsed
|
|
411
|
+
|
|
412
|
+
The CLI can extract configs from:
|
|
413
|
+
|
|
414
|
+
✅ **Object literals**
|
|
415
|
+
```typescript
|
|
416
|
+
createLibrary({
|
|
417
|
+
additionalFields: { ... },
|
|
418
|
+
plugins: [ ... ]
|
|
419
|
+
});
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
✅ **Variable references**
|
|
423
|
+
```typescript
|
|
424
|
+
const config = { ... };
|
|
425
|
+
createLibrary(config);
|
|
426
|
+
```
|
|
195
427
|
|
|
196
|
-
|
|
428
|
+
✅ **Spread operators**
|
|
429
|
+
```typescript
|
|
430
|
+
const baseConfig = { ... };
|
|
431
|
+
createLibrary({ ...baseConfig, plugins: [ ... ] });
|
|
432
|
+
```
|
|
197
433
|
|
|
198
|
-
|
|
434
|
+
✅ **Plugin function calls**
|
|
435
|
+
```typescript
|
|
436
|
+
plugins: [
|
|
437
|
+
conductAuditPlugin(),
|
|
438
|
+
conductMetricsPlugin({ ... })
|
|
439
|
+
]
|
|
440
|
+
```
|
|
199
441
|
|
|
200
|
-
|
|
442
|
+
⚠️ **Runtime values are marked as `undefined`**
|
|
443
|
+
```typescript
|
|
444
|
+
// These cannot be evaluated statically:
|
|
445
|
+
connectionString: process.env.DATABASE_URL // → undefined
|
|
446
|
+
name: `${prefix}_table` // → undefined
|
|
447
|
+
```
|
|
201
448
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
449
|
+
**Workaround**: Keep database/storage/auth in runtime config, keep schema customizations as static objects.
|
|
450
|
+
|
|
451
|
+
---
|
|
452
|
+
|
|
453
|
+
## Adapter Support
|
|
454
|
+
|
|
455
|
+
### Drizzle
|
|
456
|
+
|
|
457
|
+
```javascript
|
|
458
|
+
export default defineConfig({
|
|
459
|
+
adapter: {
|
|
460
|
+
type: 'drizzle',
|
|
461
|
+
drizzle: {
|
|
462
|
+
dialect: 'postgres', // or 'mysql', 'sqlite'
|
|
463
|
+
connectionString: process.env.DATABASE_URL,
|
|
464
|
+
}
|
|
465
|
+
},
|
|
466
|
+
});
|
|
467
|
+
```
|
|
206
468
|
|
|
207
|
-
|
|
469
|
+
Generated migrations work with `drizzle-kit push`.
|
|
208
470
|
|
|
209
|
-
|
|
471
|
+
### Prisma
|
|
210
472
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
473
|
+
```javascript
|
|
474
|
+
export default defineConfig({
|
|
475
|
+
adapter: {
|
|
476
|
+
type: 'prisma',
|
|
477
|
+
prisma: {
|
|
478
|
+
// Prisma client instance will be used
|
|
479
|
+
}
|
|
480
|
+
},
|
|
481
|
+
});
|
|
482
|
+
```
|
|
215
483
|
|
|
216
|
-
|
|
484
|
+
Generated migrations work with `npx prisma migrate deploy`.
|
|
217
485
|
|
|
218
|
-
|
|
486
|
+
### Kysely
|
|
219
487
|
|
|
220
488
|
```javascript
|
|
221
|
-
// superfunctions.config.js
|
|
222
489
|
export default defineConfig({
|
|
223
|
-
adapter: {
|
|
490
|
+
adapter: {
|
|
491
|
+
type: 'kysely',
|
|
492
|
+
kysely: {
|
|
493
|
+
dialect: 'postgres', // or 'mysql', 'sqlite'
|
|
494
|
+
connectionString: process.env.DATABASE_URL,
|
|
495
|
+
}
|
|
496
|
+
},
|
|
497
|
+
});
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
Generated migrations work with `npx kysely migrate latest`.
|
|
501
|
+
|
|
502
|
+
---
|
|
503
|
+
|
|
504
|
+
## Troubleshooting
|
|
505
|
+
|
|
506
|
+
### No library initializations found
|
|
507
|
+
|
|
508
|
+
**Problem**: CLI can't find library initialization calls in your files.
|
|
509
|
+
|
|
510
|
+
**Solution**:
|
|
511
|
+
- Make sure files are specified correctly in `libraries` array
|
|
512
|
+
- Verify function names match registry (e.g., `createConductBackend`, not `initConduct`)
|
|
513
|
+
- Check that initialization calls are at the top level (not inside functions/conditions)
|
|
514
|
+
|
|
515
|
+
### Cannot extract config
|
|
516
|
+
|
|
517
|
+
**Problem**: Config uses complex expressions that can't be statically analyzed.
|
|
518
|
+
|
|
519
|
+
**Solution**:
|
|
520
|
+
```typescript
|
|
521
|
+
// Instead of:
|
|
522
|
+
const conduct = createConductBackend(getConfig());
|
|
523
|
+
|
|
524
|
+
// Do this:
|
|
525
|
+
export const conductConfig = {
|
|
526
|
+
additionalFields: { ... },
|
|
527
|
+
plugins: [ ... ]
|
|
528
|
+
};
|
|
529
|
+
export const conduct = createConductBackend({
|
|
530
|
+
database: adapter,
|
|
531
|
+
...conductConfig
|
|
532
|
+
});
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
### Library doesn't export getSchema
|
|
536
|
+
|
|
537
|
+
**Problem**: Library hasn't integrated with CLI yet.
|
|
538
|
+
|
|
539
|
+
**Solution**: Contact library maintainer or see "For Library Authors" section to add support.
|
|
540
|
+
|
|
541
|
+
---
|
|
542
|
+
|
|
543
|
+
## FAQ
|
|
544
|
+
|
|
545
|
+
### Why not use separate config files like before?
|
|
546
|
+
|
|
547
|
+
**Problem with separate configs**: Users had to maintain two configs - one for CLI (`conduct.config.ts`) and one for runtime (`app.ts`). This creates duplication and drift risk.
|
|
548
|
+
|
|
549
|
+
**Solution**: Configure once in your app code. CLI parses those files directly.
|
|
550
|
+
|
|
551
|
+
### Can I still use separate config files?
|
|
552
|
+
|
|
553
|
+
Yes, if needed:
|
|
554
|
+
|
|
555
|
+
```typescript
|
|
556
|
+
// conduct.config.ts
|
|
557
|
+
export const conductConfig = {
|
|
558
|
+
additionalFields: { ... },
|
|
559
|
+
plugins: [ ... ]
|
|
560
|
+
};
|
|
561
|
+
|
|
562
|
+
// app.ts
|
|
563
|
+
import { conductConfig } from './conduct.config';
|
|
564
|
+
export const conduct = createConductBackend({
|
|
565
|
+
database: adapter,
|
|
566
|
+
...conductConfig
|
|
567
|
+
});
|
|
568
|
+
```
|
|
569
|
+
|
|
570
|
+
Point CLI to `app.ts` - it will resolve the import and extract the config.
|
|
571
|
+
|
|
572
|
+
### How does the CLI discover libraries?
|
|
573
|
+
|
|
574
|
+
The CLI scans `node_modules` for packages with `superfunctions` metadata in their `package.json`. This allows any library to integrate without needing changes to the CLI itself.
|
|
575
|
+
|
|
576
|
+
### How does this compare to better-auth?
|
|
577
|
+
|
|
578
|
+
**better-auth**: Single library, single config
|
|
579
|
+
**superfunctions**: Multiple libraries, need to identify which is which
|
|
580
|
+
|
|
581
|
+
**Solution**: Point to specific files containing each library's initialization. CLI uses function names (`createConductBackend`, `createAuthFn`) to identify libraries.
|
|
582
|
+
|
|
583
|
+
### What if I have multiple instances of the same library?
|
|
584
|
+
|
|
585
|
+
CLI will detect all instances and generate schemas for each. Make sure they use different namespaces to avoid conflicts.
|
|
586
|
+
|
|
587
|
+
### Can the parser handle TypeScript?
|
|
588
|
+
|
|
589
|
+
Yes, uses TypeScript compiler API to parse both `.ts` and `.js` files.
|
|
590
|
+
|
|
591
|
+
### What about JavaScript projects?
|
|
592
|
+
|
|
593
|
+
Works with JavaScript too. Just point to `.js` files in `libraries` array.
|
|
594
|
+
|
|
595
|
+
### Should I use explicit paths or auto-discovery?
|
|
596
|
+
|
|
597
|
+
**Use explicit paths (`libraries`) when:**
|
|
598
|
+
- ✅ Production applications
|
|
599
|
+
- ✅ Monorepos with multiple packages
|
|
600
|
+
- ✅ Complex project structures
|
|
601
|
+
- ✅ Need predictable behavior
|
|
602
|
+
- ✅ Want fast CLI performance
|
|
603
|
+
|
|
604
|
+
**Use auto-discovery (`autoDiscover`) when:**
|
|
605
|
+
- ✅ Small/simple projects
|
|
606
|
+
- ✅ Prototyping
|
|
607
|
+
- ✅ Don't want to maintain file list
|
|
608
|
+
- ✅ Standard project structure (src/, lib/, etc.)
|
|
609
|
+
|
|
610
|
+
**Performance note:** Auto-discovery scans your codebase which can be slow in large projects. Explicit paths are always faster.
|
|
611
|
+
|
|
612
|
+
---
|
|
613
|
+
|
|
614
|
+
## Examples
|
|
615
|
+
|
|
616
|
+
### Full Stack App Example
|
|
617
|
+
|
|
618
|
+
```
|
|
619
|
+
my-app/
|
|
620
|
+
├── superfunctions.config.js
|
|
621
|
+
├── src/
|
|
622
|
+
│ ├── db.ts # Database adapter
|
|
623
|
+
│ ├── conduct.ts # Conduct initialization
|
|
624
|
+
│ ├── auth.ts # AuthFn initialization
|
|
625
|
+
│ └── server.ts # Main app
|
|
626
|
+
├── migrations/
|
|
627
|
+
│ ├── 1234567890_conduct_v1.sql
|
|
628
|
+
│ └── 1234567891_authfn_v1.sql
|
|
629
|
+
└── package.json
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
**superfunctions.config.js:**
|
|
633
|
+
```javascript
|
|
634
|
+
import { defineConfig } from '@superfunctions/cli';
|
|
635
|
+
|
|
636
|
+
export default defineConfig({
|
|
637
|
+
adapter: {
|
|
638
|
+
type: 'drizzle',
|
|
639
|
+
drizzle: {
|
|
640
|
+
dialect: 'postgres',
|
|
641
|
+
connectionString: process.env.DATABASE_URL,
|
|
642
|
+
}
|
|
643
|
+
},
|
|
644
|
+
libraries: [
|
|
645
|
+
'./src/conduct.ts',
|
|
646
|
+
'./src/auth.ts',
|
|
647
|
+
],
|
|
648
|
+
migrationsDir: './migrations',
|
|
649
|
+
});
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
**src/db.ts:**
|
|
653
|
+
```typescript
|
|
654
|
+
import { createDrizzleAdapter } from '@superfunctions/db/drizzle';
|
|
655
|
+
import { drizzle } from 'drizzle-orm/postgres-js';
|
|
656
|
+
import postgres from 'postgres';
|
|
657
|
+
|
|
658
|
+
const client = postgres(process.env.DATABASE_URL!);
|
|
659
|
+
const db = drizzle(client);
|
|
660
|
+
|
|
661
|
+
export const adapter = createDrizzleAdapter({ db });
|
|
662
|
+
```
|
|
663
|
+
|
|
664
|
+
**src/conduct.ts:**
|
|
665
|
+
```typescript
|
|
666
|
+
import { createConductBackend } from 'conduct';
|
|
667
|
+
import { adapter } from './db';
|
|
668
|
+
|
|
669
|
+
export const conduct = createConductBackend({
|
|
670
|
+
database: adapter,
|
|
671
|
+
storage: { /* ... */ },
|
|
672
|
+
|
|
673
|
+
additionalFields: {
|
|
674
|
+
project: {
|
|
675
|
+
department: { type: 'string', required: false },
|
|
676
|
+
owner: { type: 'string', required: true },
|
|
677
|
+
}
|
|
678
|
+
},
|
|
679
|
+
|
|
680
|
+
plugins: [
|
|
681
|
+
conductAuditPlugin(),
|
|
682
|
+
]
|
|
683
|
+
});
|
|
684
|
+
```
|
|
685
|
+
|
|
686
|
+
**src/auth.ts:**
|
|
687
|
+
```typescript
|
|
688
|
+
import { createAuthFn } from '@superfunctions/authfn';
|
|
689
|
+
import { adapter } from './db';
|
|
690
|
+
|
|
691
|
+
export const auth = createAuthFn({
|
|
692
|
+
database: adapter,
|
|
224
693
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
694
|
+
additionalFields: {
|
|
695
|
+
user: {
|
|
696
|
+
role: { type: 'string', required: true },
|
|
697
|
+
department: { type: 'string', required: false },
|
|
698
|
+
}
|
|
699
|
+
},
|
|
700
|
+
|
|
701
|
+
plugins: [
|
|
702
|
+
authFnTwoFactorPlugin(),
|
|
229
703
|
],
|
|
230
704
|
});
|
|
231
705
|
```
|
|
232
706
|
|
|
233
|
-
|
|
707
|
+
**src/server.ts:**
|
|
708
|
+
```typescript
|
|
709
|
+
import express from 'express';
|
|
710
|
+
import { toExpressRouter } from '@superfunctions/http-express';
|
|
711
|
+
import { conduct } from './conduct';
|
|
712
|
+
import { auth } from './auth';
|
|
234
713
|
|
|
235
|
-
|
|
236
|
-
2. **Loading**: Each config is loaded (TypeScript supported via jiti)
|
|
237
|
-
3. **Schema Generation**: Library's `getSchema(config)` function is called
|
|
238
|
-
4. **Introspection**: Current database state is compared with desired state
|
|
239
|
-
5. **Migration Generation**: ORM-specific migration files are created
|
|
240
|
-
6. **Version Tracking**: Schema versions are stored in database
|
|
714
|
+
const app = express();
|
|
241
715
|
|
|
242
|
-
|
|
716
|
+
app.use('/api/conduct', toExpressRouter(conduct));
|
|
717
|
+
app.use('/api/auth', toExpressRouter(auth));
|
|
718
|
+
|
|
719
|
+
app.listen(3000);
|
|
720
|
+
```
|
|
243
721
|
|
|
244
|
-
|
|
722
|
+
---
|
|
245
723
|
|
|
246
724
|
## License
|
|
247
725
|
|