@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.
Files changed (40) hide show
  1. package/README.md +582 -104
  2. package/dist/cli.js +66 -53
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/generate-schema.d.ts +12 -0
  5. package/dist/commands/generate-schema.d.ts.map +1 -0
  6. package/dist/commands/generate-schema.js +156 -0
  7. package/dist/commands/generate-schema.js.map +1 -0
  8. package/dist/commands/generate.d.ts.map +1 -1
  9. package/dist/commands/generate.js +104 -25
  10. package/dist/commands/generate.js.map +1 -1
  11. package/dist/commands/init.d.ts +4 -0
  12. package/dist/commands/init.d.ts.map +1 -0
  13. package/dist/commands/init.js +38 -0
  14. package/dist/commands/init.js.map +1 -0
  15. package/dist/commands/status.d.ts.map +1 -1
  16. package/dist/commands/status.js +2 -1
  17. package/dist/commands/status.js.map +1 -1
  18. package/dist/index.d.ts +5 -1
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js.map +1 -1
  21. package/dist/utils/adapter-helper.d.ts.map +1 -1
  22. package/dist/utils/adapter-helper.js +0 -1
  23. package/dist/utils/adapter-helper.js.map +1 -1
  24. package/dist/utils/auto-discover.d.ts +28 -0
  25. package/dist/utils/auto-discover.d.ts.map +1 -0
  26. package/dist/utils/auto-discover.js +75 -0
  27. package/dist/utils/auto-discover.js.map +1 -0
  28. package/dist/utils/discover-packages.d.ts +29 -0
  29. package/dist/utils/discover-packages.d.ts.map +1 -0
  30. package/dist/utils/discover-packages.js +86 -0
  31. package/dist/utils/discover-packages.js.map +1 -0
  32. package/dist/utils/parse-library-init.d.ts +23 -0
  33. package/dist/utils/parse-library-init.d.ts.map +1 -0
  34. package/dist/utils/parse-library-init.js +191 -0
  35. package/dist/utils/parse-library-init.js.map +1 -0
  36. package/dist/utils/schema-generators.d.ts +13 -0
  37. package/dist/utils/schema-generators.d.ts.map +1 -0
  38. package/dist/utils/schema-generators.js +224 -0
  39. package/dist/utils/schema-generators.js.map +1 -0
  40. 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
- ## Quick Start
16
+ ---
17
17
 
18
- ### 1. Initialize CLI Configuration
18
+ ## For Downstream Users (Using Superfunctions Libraries)
19
19
 
20
- ```bash
21
- npx superfunctions init
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
- This creates a `superfunctions.config.js` with adapter configuration:
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
- ### 2. Create Library Config Files
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
- **conduct.config.ts:**
46
-
47
- ```typescript
48
- import type { ConductSchemaConfig } from 'conduct';
100
+ ```javascript
101
+ import { defineConfig } from '@superfunctions/cli';
49
102
 
50
- export const config: ConductSchemaConfig = {
51
- namespace: 'conduct',
52
-
53
- // Optional: Customize table/field names
54
- models: {
55
- project: {
56
- modelName: 'projects',
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
- // Optional: Add custom fields
64
- additionalFields: {
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
- // Optional: Enable plugins
71
- plugins: [
72
- // conductAuditPlugin(),
73
- // conductMetricsPlugin(),
74
- ],
75
- };
76
-
77
- export default config;
115
+ migrationsDir: './migrations',
116
+ });
78
117
  ```
79
118
 
80
- **authfn.config.ts:**
119
+ **Option C: Custom auto-discovery patterns**
81
120
 
82
- ```typescript
83
- import type { AuthFnSchemaConfig } from '@superfunctions/authfn';
121
+ ```javascript
122
+ import { defineConfig } from '@superfunctions/cli';
84
123
 
85
- export const config: AuthFnSchemaConfig = {
86
- namespace: 'auth',
87
-
88
- models: {
89
- user: {
90
- modelName: 'users',
91
- },
92
- },
124
+ export default defineConfig({
125
+ adapter: { /* ... */ },
93
126
 
94
- additionalFields: {
95
- user: {
96
- role: { type: 'string', required: true },
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
- plugins: [
101
- // authFnTwoFactorPlugin(),
102
- ],
103
- };
104
-
105
- export default config;
140
+ migrationsDir: './migrations',
141
+ });
106
142
  ```
107
143
 
108
- ### 3. Generate Migrations
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
- 🔍 Discovering library configurations...
119
- 📦 Found 2 library config(s):
120
- - conduct (./conduct.config.ts)
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
- 📖 Loading conduct config...
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
- 📖 Loading authfn config...
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
- ### 4. Apply Migrations
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
- ## Commands
190
+ ### Benefits of This Approach
154
191
 
155
- ### `init`
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
- Initialize configuration file.
197
+ ---
158
198
 
159
- ```bash
160
- npx superfunctions init [--force]
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
- ## Library Config Files
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
- ### Naming Convention
428
+ **Spread operators**
429
+ ```typescript
430
+ const baseConfig = { ... };
431
+ createLibrary({ ...baseConfig, plugins: [ ... ] });
432
+ ```
197
433
 
198
- `<library-name>.config.{ts,js,mjs}`
434
+ ✅ **Plugin function calls**
435
+ ```typescript
436
+ plugins: [
437
+ conductAuditPlugin(),
438
+ conductMetricsPlugin({ ... })
439
+ ]
440
+ ```
199
441
 
200
- ### Supported Locations (Auto-discovered)
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
- - Project root: `conduct.config.ts`
203
- - src directory: `src/conduct.config.ts`
204
- - lib directory: `lib/conduct.config.ts`
205
- - server directory: `server/conduct.config.ts`
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
- ### Config Structure
469
+ Generated migrations work with `drizzle-kit push`.
208
470
 
209
- Each config file should export the library's configuration object. The structure is library-specific but generally includes:
471
+ ### Prisma
210
472
 
211
- - `namespace` - Table prefix for isolation
212
- - `models` - Custom table/field names
213
- - `additionalFields` - Extra fields per table
214
- - `plugins` - Enabled plugins that add tables
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
- ## Advanced: Manual Discovery Paths
484
+ Generated migrations work with `npx prisma migrate deploy`.
217
485
 
218
- If your configs are in non-standard locations:
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
- // Explicitly specify config paths
226
- discoverConfigs: [
227
- './lib/server/custom-conduct.config.ts',
228
- './config/authfn.ts',
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
- ## How It Works
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
- 1. **Discovery**: CLI finds library config files using naming convention
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
- ## Configuration
716
+ app.use('/api/conduct', toExpressRouter(conduct));
717
+ app.use('/api/auth', toExpressRouter(auth));
718
+
719
+ app.listen(3000);
720
+ ```
243
721
 
244
- See full configuration examples and options in the [documentation](https://superfunctions.dev/docs/cli).
722
+ ---
245
723
 
246
724
  ## License
247
725