prisma-effect-kysely 1.11.0 → 1.13.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/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.13.0
4
+
5
+ ### Minor Changes
6
+
7
+ - feat: use Schema.DateFromSelf for native Date types
8
+
9
+ BREAKING CHANGE: DateTime fields now use Schema.DateFromSelf instead of Schema.Date
10
+ - DateTime fields now encode to native Date objects instead of ISO strings
11
+ - This enables Kysely to work with native Date objects directly without requiring `.toISOString()` conversions
12
+ - Added Effect Schema validation for generator config and scaffold results
13
+ - Removed type assertions in favor of strict Schema validation
14
+ - Added multi-domain support with contract library scaffolding
15
+
3
16
  All notable changes to this project will be documented in this file.
4
17
 
5
18
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
@@ -10,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
10
23
  ### Fixed
11
24
 
12
25
  #### Dependency Configuration
26
+
13
27
  - **Fixed Effect as peer dependency** to prevent version conflicts and follow best practices
14
28
  - **Problem**: `effect` was listed as a regular dependency, causing potential version conflicts in user projects
15
29
  - **Solution**: Moved `effect` to `peerDependencies` (required, not optional)
@@ -23,6 +37,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
23
37
  ### Removed
24
38
 
25
39
  #### Unused Dependencies
40
+
26
41
  - **Removed `@prisma/client` and `@prisma/dmmf`** from dependencies
27
42
  - **Analysis**: Code analysis revealed these packages are never imported in the codebase
28
43
  - **Impact**: Smaller package size, cleaner dependency tree
@@ -30,7 +45,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
30
45
  ### Changed
31
46
 
32
47
  #### Package Structure
48
+
33
49
  **Before:**
50
+
34
51
  ```json
35
52
  "dependencies": {
36
53
  "@prisma/client": "6.16.3",
@@ -42,6 +59,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
42
59
  ```
43
60
 
44
61
  **After:**
62
+
45
63
  ```json
46
64
  "dependencies": {
47
65
  "@prisma/generator-helper": "^6.17.0",
@@ -56,14 +74,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
56
74
  ### Migration Guide
57
75
 
58
76
  **For New Users:**
77
+
59
78
  - Install Effect explicitly: `npm install effect` or `pnpm install effect`
60
79
 
61
80
  **For Existing Users:**
81
+
62
82
  - If you already have `effect` installed: No action needed
63
83
  - If you don't have `effect`: Run `npm install effect` or `pnpm install effect`
64
84
  - npm 7+ will automatically install peer dependencies
65
85
 
66
86
  **Benefits:**
87
+
67
88
  - ✅ Prevents Effect version conflicts between your project and the generator
68
89
  - ✅ You control which Effect version to use
69
90
  - ✅ Smaller package size (removed unused dependencies)
@@ -74,6 +95,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
74
95
  ### Fixed
75
96
 
76
97
  #### TypeScript Schema [TypeId] Preservation Bug
98
+
77
99
  - **Fixed `generated()` and `columnType()` helpers losing Schema [TypeId] symbol**
78
100
  - **Problem**: Helpers returned result of `.annotations()` directly, causing TypeScript compilation errors in generated code: `Property '[TypeId]' is missing in type 'typeof Date$'`
79
101
  - **Root Cause**: `.annotations()` doesn't automatically preserve Schema type for TypeScript's type system without explicit wrapping
@@ -88,6 +110,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88
110
  ### Added
89
111
 
90
112
  #### Enhanced Test Coverage for Type Safety
113
+
91
114
  - **Added TypeScript compile-time validation tests** to prevent future regressions
92
115
  - Type assertions that fail at compile-time if Schema types lose [TypeId]
93
116
  - Runtime validation using `Schema.isSchema()` checks
@@ -103,16 +126,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
103
126
  ### Technical Details
104
127
 
105
128
  **Why the Bug Occurred**:
129
+
106
130
  - Effect Schema's `.annotations()` method creates a new schema with modified annotations
107
131
  - TypeScript's type inference doesn't automatically preserve the `Schema<T>` type with its `[TypeId]` symbol
108
132
  - Without `Schema.asSchema()` wrapper, TypeScript sees the result as a plain object losing Schema type information
109
133
 
110
134
  **Prevention Strategy**:
135
+
111
136
  - Always use explicit return types for functions returning schemas
112
137
  - Always wrap `.annotations()` results with `Schema.asSchema()`
113
138
  - Include both compile-time type assertions AND runtime validation in tests
114
139
 
115
140
  **Example Fix**:
141
+
116
142
  ```typescript
117
143
  // Before (incorrect):
118
144
  export const generated = <T>(schema: Schema.Schema<T>) => {
@@ -130,6 +156,7 @@ export const generated = <T>(schema: Schema.Schema<T>): Schema.Schema<T> => {
130
156
  ### Fixed
131
157
 
132
158
  #### TypeScript Type Inference for Generated Fields - Explicit Omit Types
159
+
133
160
  - **Generate explicit Insert type definitions using TypeScript's Omit utility for compile-time type safety**
134
161
  - **Problem**: v1.8.4 fixed runtime behavior (generated fields correctly omitted from Insertable schema), but TypeScript's `Schema.Schema.Type` inference couldn't see runtime AST field filtering, causing all fields to appear in Insert types
135
162
  - **Root Cause**: TypeScript's structural type inference works on static schema structure; runtime AST transformations are invisible to the type system
@@ -145,6 +172,7 @@ export const generated = <T>(schema: Schema.Schema<T>): Schema.Schema<T> => {
145
172
  - Non-ID fields with `@default` (e.g., `@default(now())`)
146
173
  - Fields with `@updatedAt` directive (auto-managed by database)
147
174
  - **Example**:
175
+
148
176
  ```typescript
149
177
  // Prisma schema:
150
178
  model User {
@@ -173,6 +201,7 @@ export const generated = <T>(schema: Schema.Schema<T>): Schema.Schema<T> => {
173
201
  name: 'John Doe'
174
202
  };
175
203
  ```
204
+
176
205
  - **Implementation**:
177
206
  - Added `getOmittedInsertFields()` helper in `src/effect/generator.ts` to identify fields during code generation
178
207
  - Uses DMMF properties: `hasDefaultValue` and `isUpdatedAt`
@@ -182,6 +211,7 @@ export const generated = <T>(schema: Schema.Schema<T>): Schema.Schema<T> => {
182
211
  - Tests: `src/__tests__/type-inference-generated.test.ts` (10 new tests, all passing)
183
212
 
184
213
  ### Technical Details
214
+
185
215
  - **Architecture**: Explicit type generation (industry standard for code generators)
186
216
  - **Rationale**: TypeScript's structural type inference works on static schema structure; runtime AST transformations are invisible to the type system
187
217
  - **Not a Workaround**: Standard practice when type inference can't capture runtime behavior (same approach as Prisma Client, Drizzle ORM, tRPC)
@@ -191,7 +221,9 @@ export const generated = <T>(schema: Schema.Schema<T>): Schema.Schema<T> => {
191
221
  - **Type Safety Guarantee**: Models without generated fields continue to use plain `Schema.Schema.Type` (no unnecessary `Omit`)
192
222
 
193
223
  ### Breaking Changes
224
+
194
225
  None - This is a non-breaking enhancement. The change is purely additive at the type level:
226
+
195
227
  - Runtime behavior unchanged from v1.8.4
196
228
  - Generated schemas remain the same
197
229
  - Only TypeScript type definitions become more restrictive (catching bugs earlier)
@@ -201,6 +233,7 @@ None - This is a non-breaking enhancement. The change is purely additive at the
201
233
  ### Fixed
202
234
 
203
235
  #### Native @effect/sql Pattern for Generated Fields
236
+
204
237
  - **Implemented native field filtering for `generated()` fields following @effect/sql Model.Generated pattern**
205
238
  - **Problem**: Generated fields (those with `@default` in Prisma schema) were incorrectly made optional in Insertable schema using `Union(T, Undefined)`, which doesn't properly reflect TypeScript optionality and doesn't follow Effect ecosystem patterns
206
239
  - **Solution**: OMIT generated fields entirely from Insertable schema (not make them optional) following @effect/sql's `Model.Generated` pattern
@@ -217,6 +250,7 @@ None - This is a non-breaking enhancement. The change is purely additive at the
217
250
  - Respects TypeScript optionality semantics (property optional `?:` vs value optional `| undefined`)
218
251
  - Cleaner implementation with fewer special cases
219
252
  - **Example**:
253
+
220
254
  ```typescript
221
255
  // Prisma schema:
222
256
  model Agent {
@@ -238,6 +272,7 @@ None - This is a non-breaking enhancement. The change is purely additive at the
238
272
  // Insert only requires 'name' - generated fields completely absent
239
273
  const insert: AgentInsert = { name: 'test' };
240
274
  ```
275
+
241
276
  - **Test Coverage**: 15 tests passing including comprehensive runtime validation and AST structure verification
242
277
  - Location: `src/kysely/helpers.ts:43-119, 188-224`
243
278
  - Tests: `src/__tests__/kysely-helpers.test.ts:186-283`
@@ -245,21 +280,28 @@ None - This is a non-breaking enhancement. The change is purely additive at the
245
280
  ### Known Limitations
246
281
 
247
282
  #### TypeScript Type Inference for Insertable Types
283
+
248
284
  - **TypeScript's `Schema.Schema.Type` inference still includes all fields in Insert types**
249
285
  - **Issue**: While runtime validation correctly omits generated fields, TypeScript type inference from `Schema.Schema.Type<typeof Model.Insertable>` cannot see runtime AST field filtering and still infers all fields as required
250
286
  - **Root Cause**: TypeScript's structural type inference works on the base schema structure before runtime transformations
251
287
  - **Workaround**: Use explicit type annotations or runtime validation (Effect Schema will filter out extra fields)
252
288
  - **Planned Fix**: Update code generator (`src/effect/generator.ts`) to create explicit TypeScript type definitions using `Omit` utility type:
289
+
253
290
  ```typescript
254
291
  // Current:
255
292
  export type AgentInsert = Schema.Schema.Type<typeof Agent.Insertable>;
256
293
 
257
294
  // Planned:
258
- export type AgentInsert = Omit<Schema.Schema.Type<typeof Agent.Insertable>, 'id' | 'session_id'>;
295
+ export type AgentInsert = Omit<
296
+ Schema.Schema.Type<typeof Agent.Insertable>,
297
+ 'id' | 'session_id'
298
+ >;
259
299
  ```
300
+
260
301
  - **Status**: Code generation fix planned for v1.9.0
261
302
 
262
303
  ### Technical Details
304
+
263
305
  - **Quality Assurance**: All 15 kysely-helpers tests passing, zero TypeScript errors in implementation
264
306
  - **Test Approach**: TDD (Test-Driven Development) - wrote failing tests first, then implemented to make them pass
265
307
  - **Research**: Validated approach against @effect/sql's `Model.Generated` pattern (official Effect ecosystem standard)
@@ -271,6 +313,7 @@ None - This is a non-breaking enhancement. The change is purely additive at the
271
313
  ### Added
272
314
 
273
315
  #### Semantic Join Table Column Names
316
+
274
317
  - **Generated join tables now use semantic snake_case field names** instead of Prisma's generic A/B columns
275
318
  - **Problem**: Prisma's implicit M2M join tables use non-semantic `A` and `B` column names, causing poor developer experience and forcing developers to remember alphabetical model ordering
276
319
  - **Solution**: Map semantic names like `product_id`, `product_tag_id` to actual database columns using Effect Schema's `propertySignature` with `fromKey`
@@ -280,6 +323,7 @@ None - This is a non-breaking enhancement. The change is purely additive at the
280
323
  - Type-safe bidirectional transformation (encode/decode)
281
324
  - Follows snake_case convention for database identifiers (Prisma best practice)
282
325
  - **Example**:
326
+
283
327
  ```typescript
284
328
  // Before (v1.8.2):
285
329
  export const _ProductToProductTag = Schema.Struct({
@@ -289,16 +333,22 @@ None - This is a non-breaking enhancement. The change is purely additive at the
289
333
 
290
334
  // After (v1.8.3):
291
335
  export const _ProductToProductTag = Schema.Struct({
292
- product_id: Schema.propertySignature(columnType(Schema.UUID, Schema.Never, Schema.Never)).pipe(Schema.fromKey("A")),
293
- product_tag_id: Schema.propertySignature(columnType(Schema.UUID, Schema.Never, Schema.Never)).pipe(Schema.fromKey("B")),
336
+ product_id: Schema.propertySignature(
337
+ columnType(Schema.UUID, Schema.Never, Schema.Never)
338
+ ).pipe(Schema.fromKey('A')),
339
+ product_tag_id: Schema.propertySignature(
340
+ columnType(Schema.UUID, Schema.Never, Schema.Never)
341
+ ).pipe(Schema.fromKey('B')),
294
342
  });
295
343
  ```
344
+
296
345
  - Location: `src/effect/join-table.ts:37-69`
297
346
  - New utility: `toSnakeCase()` in `src/utils/naming.ts:61-73`
298
347
 
299
348
  ### Fixed
300
349
 
301
350
  #### Unused Enum Type Imports
351
+
302
352
  - **types.ts now imports only Schema wrappers**: Eliminated TypeScript "declared but never read" warnings
303
353
  - **Problem**: Generated `types.ts` imported both plain enum types (e.g., `BudgetStatus`) and schema wrappers (e.g., `BudgetStatusSchema`), but only schema wrappers were used
304
354
  - **Solution**: Import generation now only includes `*Schema` wrappers
@@ -306,6 +356,7 @@ None - This is a non-breaking enhancement. The change is purely additive at the
306
356
  - Location: `src/effect/generator.ts:95-107`
307
357
 
308
358
  ### Technical Details
359
+
309
360
  - **Quality Assurance**: All 165 tests passing (15 naming tests + 10 join table tests + 140 existing), zero TypeScript errors
310
361
  - **Test Coverage**: New comprehensive tests for `toSnakeCase` utility and semantic join table column generation
311
362
  - **Documentation**: Updated CLAUDE.md with join table naming behavior explanation
@@ -320,6 +371,7 @@ None - This is a non-breaking enhancement. The change is purely additive at the
320
371
  This release transforms the project into an enterprise-ready open source package following 2025 best practices.
321
372
 
322
373
  #### Code Quality & Formatting
374
+
323
375
  - **ESLint 9**: Flat config format with TypeScript and Jest support (2025 standard)
324
376
  - Comprehensive rules for source and test files
325
377
  - Automatic unused import detection
@@ -338,6 +390,7 @@ This release transforms the project into an enterprise-ready open source package
338
390
  - `npm run format:check` - Check formatting without changes
339
391
 
340
392
  #### Governance Documentation
393
+
341
394
  - **SECURITY.md**: Professional vulnerability reporting process
342
395
  - Supported versions table
343
396
  - Response timeline SLAs (Critical: 7 days, High: 14 days, Medium: 30 days)
@@ -357,6 +410,7 @@ This release transforms the project into an enterprise-ready open source package
357
410
  - **Governance docs added to npm package**: All governance files now distributed with package
358
411
 
359
412
  #### Automated Dependency Management
413
+
360
414
  - **renovate.json**: Renovate Cloud (free tier) configuration
361
415
  - Weekly automated updates (Mondays at 3am UTC)
362
416
  - Auto-merge for patch updates after CI passes
@@ -369,6 +423,7 @@ This release transforms the project into an enterprise-ready open source package
369
423
  - Effect package pinned to prevent breaking changes
370
424
 
371
425
  ### Changed
426
+
372
427
  - **prepublishOnly script**: Now includes linting step (`npm run lint && npm run typecheck && npm run test && npm run build`)
373
428
  - **prepare script**: Updated from `npm run build` to `husky` for pre-commit hook initialization
374
429
  - **Source code cleanup**: Removed unused imports detected by ESLint
@@ -378,6 +433,7 @@ This release transforms the project into an enterprise-ready open source package
378
433
  - `src/effect/join-table.ts`: Prefixed unused parameter with underscore
379
434
 
380
435
  ### Technical Details
436
+
381
437
  - **Quality Assurance**: All 154 tests passing, zero TypeScript errors
382
438
  - **ESLint Status**: Passing with 2 minor warnings in test files (acceptable for test code)
383
439
  - **Build**: Clean compilation to dist/ directory
@@ -385,6 +441,7 @@ This release transforms the project into an enterprise-ready open source package
385
441
  - **Compliance**: Follows OpenSSF Best Practices baseline
386
442
 
387
443
  ### Dependencies
444
+
388
445
  - **Added devDependencies**:
389
446
  - `@eslint/js@^9.37.0`
390
447
  - `typescript-eslint@^8.46.0`
@@ -421,15 +478,15 @@ This release transforms the project into an enterprise-ready open source package
421
478
  ```typescript
422
479
  // Generated from: enum ACTIVE_STATUS { ACTIVE, INACTIVE }
423
480
  export enum ACTIVE_STATUS {
424
- ACTIVE = "ACTIVE",
425
- INACTIVE = "INACTIVE"
481
+ ACTIVE = 'ACTIVE',
482
+ INACTIVE = 'INACTIVE',
426
483
  }
427
484
  export const ActiveStatusSchema = Schema.Enums(ACTIVE_STATUS);
428
485
  export type ActiveStatusType = Schema.Schema.Type<typeof ActiveStatusSchema>;
429
486
 
430
487
  // Usage:
431
- const status = ACTIVE_STATUS.ACTIVE; // Direct enum access
432
- Schema.decodeSync(ActiveStatusSchema)(input); // Validation
488
+ const status = ACTIVE_STATUS.ACTIVE; // Direct enum access
489
+ Schema.decodeSync(ActiveStatusSchema)(input); // Validation
433
490
  ```
434
491
 
435
492
  ## [1.5.3] - 2025-10-12
@@ -452,6 +509,7 @@ Schema.decodeSync(ActiveStatusSchema)(input); // Validation
452
509
  - Generates operational schemas (`Selectable`, `Insertable`, `Updateable`) for join tables
453
510
  - Both `Type` and `Encoded` exports for complete type coverage
454
511
  - Example:
512
+
455
513
  ```typescript
456
514
  // Generated join table schema
457
515
  export const _CategoryToPost = Schema.Struct({
@@ -468,6 +526,7 @@ Schema.decodeSync(ActiveStatusSchema)(input); // Validation
468
526
  _CategoryToPost: Schema.Schema.Encoded<typeof _CategoryToPost>;
469
527
  }
470
528
  ```
529
+
471
530
  - **Benefits**:
472
531
  - ✨ Type-safe Kysely queries through intermediate tables
473
532
  - ✨ Complete database schema representation
@@ -515,9 +574,9 @@ Schema.decodeSync(ActiveStatusSchema)(input); // Validation
515
574
  - ✅ **New Pattern**: Native TypeScript enum + Effect Schema wrapper
516
575
  ```typescript
517
576
  export enum ProductStatus {
518
- ACTIVE = "ACTIVE",
519
- DRAFT = "DRAFT",
520
- ARCHIVED = "ARCHIVED"
577
+ ACTIVE = 'ACTIVE',
578
+ DRAFT = 'DRAFT',
579
+ ARCHIVED = 'ARCHIVED',
521
580
  }
522
581
  export const ProductStatusSchema = Schema.Enums(ProductStatus);
523
582
  export type ProductStatusType = Schema.Schema.Type<typeof ProductStatusSchema>;
@@ -562,15 +621,18 @@ Schema.decodeSync(ActiveStatusSchema)(input); // Validation
562
621
  ### Technical Details
563
622
 
564
623
  **TDD Implementation**: All changes developed using Test-Driven Development (Red-Green-Refactor)
624
+
565
625
  - 18+ new tests covering enum generation, property access, field mapping, and imports
566
626
  - All 134 tests passing with strict TypeScript configuration
567
627
  - Zero type coercions - maintains full type safety
568
628
 
569
629
  **Expert Validation**:
630
+
570
631
  - ✅ Effect Architecture Specialist: Confirmed Schema.Enums is canonical pattern for Effect v3.18+
571
632
  - ✅ TypeScript Pro: Validated all optimizations are type-safe with zero runtime overhead
572
633
 
573
634
  **Changed Files**:
635
+
574
636
  - `src/effect/enum.ts`: Complete rewrite of enum generation logic
575
637
  - `src/effect/type.ts`: Updated to return Schema wrappers for enum fields
576
638
  - `src/effect/generator.ts`: Optimized import generation, removed Array.from()
@@ -579,6 +641,7 @@ Schema.decodeSync(ActiveStatusSchema)(input); // Validation
579
641
  - `src/__tests__/helpers/dmmf-mocks.ts`: New test helpers without type coercions
580
642
 
581
643
  **Test Coverage**:
644
+
582
645
  - `src/__tests__/enum-generation.test.ts`: Tests 1-6 (Schema.Enums pattern)
583
646
  - `src/__tests__/enum-property-access.test.ts`: Tests 7-10 (property access validation)
584
647
  - `src/__tests__/field-type-generation.test.ts`: Tests 11-12 (field type mapping)
@@ -588,21 +651,23 @@ Schema.decodeSync(ActiveStatusSchema)(input); // Validation
588
651
  **Migration Guide**:
589
652
 
590
653
  Before (v1.4.x):
654
+
591
655
  ```typescript
592
656
  // Generated code
593
- export const PRODUCT_STATUS = Schema.Literal("ACTIVE", "DRAFT", "ARCHIVED");
657
+ export const PRODUCT_STATUS = Schema.Literal('ACTIVE', 'DRAFT', 'ARCHIVED');
594
658
 
595
659
  // Usage
596
660
  const status = PRODUCT_STATUS.literals[0]; // "ACTIVE"
597
661
  ```
598
662
 
599
663
  After (v1.5.0):
664
+
600
665
  ```typescript
601
666
  // Generated code
602
667
  export enum ProductStatus {
603
- ACTIVE = "ACTIVE",
604
- DRAFT = "DRAFT",
605
- ARCHIVED = "ARCHIVED"
668
+ ACTIVE = 'ACTIVE',
669
+ DRAFT = 'DRAFT',
670
+ ARCHIVED = 'ARCHIVED',
606
671
  }
607
672
  export const ProductStatusSchema = Schema.Enums(ProductStatus);
608
673
 
@@ -630,6 +695,7 @@ const status = ProductStatus.ACTIVE; // "ACTIVE"
630
695
  **Problem**: When TypeScript compiled helper functions to `.d.ts` files, the return types of AST transformation functions (`selectable()`, `insertable()`, `updateable()`) were inferred as `S.Schema<unknown, unknown, never>` instead of preserving the Kysely mapped types. This caused downstream type resolution to fail when consumers used compiled declaration files (dist/ paths) instead of source files.
631
696
 
632
697
  **Solution**: Added explicit return type annotations with type assertions to all helper functions:
698
+
633
699
  - `selectable()` → `: S.Schema<Selectable<Type>, Selectable<Encoded>, never>`
634
700
  - `insertable()` → `: S.Schema<Insertable<Type>, Insertable<Encoded>, never>`
635
701
  - `updateable()` → `: S.Schema<Updateable<Type>, Updateable<Encoded>, never>`
@@ -640,6 +706,7 @@ const status = ProductStatus.ACTIVE; // "ACTIVE"
640
706
  **Testing**: Added comprehensive test suite (`declaration-inference.test.ts`) with 7 tests validating type preservation in compiled declarations, following TDD principles (Red-Green-Refactor).
641
707
 
642
708
  **Changed files:**
709
+
643
710
  - `src/kysely/helpers.ts`: Added return type annotations (4 functions)
644
711
  - `src/__tests__/declaration-inference.test.ts`: New test suite (260 lines)
645
712
 
@@ -669,6 +736,7 @@ const status = ProductStatus.ACTIVE; // "ACTIVE"
669
736
  **Impact**: Projects using `prisma-effect-kysely` v1.4.0 or earlier may have experienced TypeScript compilation errors when using `Schema.decode()` or `Schema.decodeUnknownSync()`. This release resolves those errors without requiring any code changes in consuming projects.
670
737
 
671
738
  **Changed files:**
739
+
672
740
  - `src/kysely/helpers.ts`: Added `S.asSchema()` wrappers (6 locations)
673
741
  - `src/prisma/enum.ts`: Added return type annotation
674
742
  - `src/prisma/generator.ts`: Added return type annotations (3 methods)
@@ -699,6 +767,7 @@ The generator now converts all model names to PascalCase when creating TypeScrip
699
767
  **Impact**: Projects using snake_case model names will see different export names (breaking change for those projects). Projects using PascalCase models (recommended Prisma convention) will see no changes.
700
768
 
701
769
  **Changed files:**
770
+
702
771
  - `src/utils/naming.ts`: New naming utility
703
772
  - `src/effect/generator.ts`: Updated to use PascalCase for all exports
704
773
  - `src/__tests__/fixtures/test.prisma`: Added snake_case test model
@@ -725,20 +794,24 @@ The generator now converts all model names to PascalCase when creating TypeScrip
725
794
  ### Why This Matters
726
795
 
727
796
  Effect Schema has bidirectional transformations:
797
+
728
798
  - **Application types** (`Schema.Schema.Type`) - Decoded types with `Date` objects (for repository layer)
729
799
  - **Database types** (`Schema.Schema.Encoded`) - Encoded types with ISO strings (for queries layer)
730
800
 
731
801
  Previously, only Application types were exported, forcing queries to use `any` types. Now both sides of the transformation are properly typed.
732
802
 
733
803
  **Example Usage:**
804
+
734
805
  ```typescript
735
806
  import { agentInsertEncoded } from '@libs/types';
736
807
 
737
808
  // Queries layer - uses Encoded types (ISO strings)
738
- insert: (rowData: agentInsertEncoded) => db.insertInto('agent').values(rowData)
809
+ insert: (rowData: agentInsertEncoded) => db.insertInto('agent').values(rowData);
739
810
 
740
811
  // Repository layer - uses Application types (Date objects)
741
- const input: CreateAgentInput = { /* ... Date objects ... */ };
812
+ const input: CreateAgentInput = {
813
+ /* ... Date objects ... */
814
+ };
742
815
  const encoded = Schema.encode(AgentSchemas.Insertable)(input); // Encoded to ISO strings
743
816
  ```
744
817
 
@@ -1 +1 @@
1
- {"version":3,"file":"join-table.d.ts","sourceRoot":"","sources":["../../src/effect/join-table.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGxD;;GAEG;AACH,wBAAgB,gCAAgC,CAAC,SAAS,EAAE,aAAa,GAAG,MAAM,CAcjF;AAoBD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,aAAa,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,GAAG,MAAM,CAgD9F"}
1
+ {"version":3,"file":"join-table.d.ts","sourceRoot":"","sources":["../../src/effect/join-table.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGxD;;GAEG;AACH,wBAAgB,gCAAgC,CAAC,SAAS,EAAE,aAAa,UAcxE;AAoBD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,aAAa,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,UAgDrF"}
@@ -1,4 +1,4 @@
1
- import type { DMMF } from "@prisma/generator-helper";
1
+ import type { DMMF } from '@prisma/generator-helper';
2
2
  /**
3
3
  * Map Prisma field type to Effect Schema type
4
4
  * Priority order: annotation → UUID → scalar → enum → unknown fallback
@@ -1 +1 @@
1
- {"version":3,"file":"type.d.ts","sourceRoot":"","sources":["../../src/effect/type.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AA0BrD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,UA8B1E;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,UAcpE"}
1
+ {"version":3,"file":"type.d.ts","sourceRoot":"","sources":["../../src/effect/type.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AA2BrD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,UA6B1E;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,UAcpE"}
@@ -8,17 +8,23 @@ const naming_1 = require("../utils/naming");
8
8
  /**
9
9
  * Prisma scalar type mapping to Effect Schema types
10
10
  * Uses const assertion to avoid type guards
11
+ *
12
+ * Note: DateTime uses Schema.DateFromSelf (not Schema.Date) so that:
13
+ * - Type = Date (runtime)
14
+ * - Encoded = Date (database)
15
+ * This allows Kysely to work with native Date objects directly.
16
+ * Schema.Date would encode to string, requiring ISO string conversions.
11
17
  */
12
18
  const PRISMA_SCALAR_MAP = {
13
- String: "Schema.String",
14
- Int: "Schema.Number",
15
- Float: "Schema.Number",
16
- BigInt: "Schema.BigInt",
17
- Decimal: "Schema.String", // For precision
18
- Boolean: "Schema.Boolean",
19
- DateTime: "Schema.Date",
20
- Json: "Schema.Unknown", // Safe unknown type
21
- Bytes: "Schema.Uint8Array",
19
+ String: 'Schema.String',
20
+ Int: 'Schema.Number',
21
+ Float: 'Schema.Number',
22
+ BigInt: 'Schema.BigInt',
23
+ Decimal: 'Schema.String', // For precision
24
+ Boolean: 'Schema.Boolean',
25
+ DateTime: 'Schema.DateFromSelf', // Native Date type for Kysely compatibility
26
+ Json: 'Schema.Unknown', // Safe unknown type
27
+ Bytes: 'Schema.Uint8Array',
22
28
  };
23
29
  /**
24
30
  * Map Prisma field type to Effect Schema type
@@ -31,8 +37,8 @@ function mapFieldToEffectType(field, dmmf) {
31
37
  return typeOverride;
32
38
  }
33
39
  // PRIORITY 2: Handle String type with UUID detection
34
- if (field.type === "String" && (0, type_1.isUuidField)(field)) {
35
- return "Schema.UUID";
40
+ if (field.type === 'String' && (0, type_1.isUuidField)(field)) {
41
+ return 'Schema.UUID';
36
42
  }
37
43
  // PRIORITY 3: Handle scalar types with const assertion lookup
38
44
  const scalarType = PRISMA_SCALAR_MAP[field.type];
@@ -48,7 +54,7 @@ function mapFieldToEffectType(field, dmmf) {
48
54
  return (0, naming_1.toPascalCase)(field.type, 'Schema');
49
55
  }
50
56
  // PRIORITY 5: Fallback to Unknown
51
- return "Schema.Unknown";
57
+ return 'Schema.Unknown';
52
58
  }
53
59
  /**
54
60
  * Build complete field type with array and optional wrapping
@@ -1 +1 @@
1
- {"version":3,"file":"type.js","sourceRoot":"","sources":["../../src/effect/type.ts"],"names":[],"mappings":";;AA8BA,oDA8BC;AAKD,wCAcC;AA9ED,yCAKwB;AACxB,sDAAiE;AACjE,4CAA+C;AAE/C;;;GAGG;AACH,MAAM,iBAAiB,GAAG;IACxB,MAAM,EAAE,eAAe;IACvB,GAAG,EAAE,eAAe;IACpB,KAAK,EAAE,eAAe;IACtB,MAAM,EAAE,eAAe;IACvB,OAAO,EAAE,eAAe,EAAE,gBAAgB;IAC1C,OAAO,EAAE,gBAAgB;IACzB,QAAQ,EAAE,aAAa;IACvB,IAAI,EAAE,gBAAgB,EAAE,oBAAoB;IAC5C,KAAK,EAAE,mBAAmB;CAClB,CAAC;AAEX;;;GAGG;AACH,SAAgB,oBAAoB,CAAC,KAAiB,EAAE,IAAmB;IACzE,+CAA+C;IAC/C,MAAM,YAAY,GAAG,IAAA,uCAAyB,EAAC,KAAK,CAAC,CAAC;IACtD,IAAI,YAAY,EAAE,CAAC;QACjB,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,qDAAqD;IACrD,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAA,kBAAW,EAAC,KAAK,CAAC,EAAE,CAAC;QAClD,OAAO,aAAa,CAAC;IACvB,CAAC;IAED,8DAA8D;IAC9D,MAAM,UAAU,GACd,iBAAiB,CAAC,KAAK,CAAC,IAAsC,CAAC,CAAC;IAClE,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,oCAAoC;IACpC,8DAA8D;IAC9D,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,CAAC,CAAC;IACxE,IAAI,OAAO,EAAE,CAAC;QACZ,gDAAgD;QAChD,2CAA2C;QAC3C,OAAO,IAAA,qBAAY,EAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC5C,CAAC;IAED,kCAAkC;IAClC,OAAO,gBAAgB,CAAC;AAC1B,CAAC;AAED;;GAEG;AACH,SAAgB,cAAc,CAAC,KAAiB,EAAE,IAAmB;IACnE,IAAI,QAAQ,GAAG,oBAAoB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAEjD,gBAAgB;IAChB,IAAI,IAAA,kBAAW,EAAC,KAAK,CAAC,EAAE,CAAC;QACvB,QAAQ,GAAG,gBAAgB,QAAQ,GAAG,CAAC;IACzC,CAAC;IAED,4DAA4D;IAC5D,IAAI,CAAC,IAAA,sBAAe,EAAC,KAAK,CAAC,IAAI,CAAC,IAAA,sBAAe,EAAC,KAAK,CAAC,EAAE,CAAC;QACvD,QAAQ,GAAG,sBAAsB,QAAQ,GAAG,CAAC;IAC/C,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
1
+ {"version":3,"file":"type.js","sourceRoot":"","sources":["../../src/effect/type.ts"],"names":[],"mappings":";;AA+BA,oDA6BC;AAKD,wCAcC;AA9ED,yCAA4F;AAC5F,sDAAiE;AACjE,4CAA+C;AAE/C;;;;;;;;;GASG;AACH,MAAM,iBAAiB,GAAG;IACxB,MAAM,EAAE,eAAe;IACvB,GAAG,EAAE,eAAe;IACpB,KAAK,EAAE,eAAe;IACtB,MAAM,EAAE,eAAe;IACvB,OAAO,EAAE,eAAe,EAAE,gBAAgB;IAC1C,OAAO,EAAE,gBAAgB;IACzB,QAAQ,EAAE,qBAAqB,EAAE,4CAA4C;IAC7E,IAAI,EAAE,gBAAgB,EAAE,oBAAoB;IAC5C,KAAK,EAAE,mBAAmB;CAClB,CAAC;AAEX;;;GAGG;AACH,SAAgB,oBAAoB,CAAC,KAAiB,EAAE,IAAmB;IACzE,+CAA+C;IAC/C,MAAM,YAAY,GAAG,IAAA,uCAAyB,EAAC,KAAK,CAAC,CAAC;IACtD,IAAI,YAAY,EAAE,CAAC;QACjB,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,qDAAqD;IACrD,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAA,kBAAW,EAAC,KAAK,CAAC,EAAE,CAAC;QAClD,OAAO,aAAa,CAAC;IACvB,CAAC;IAED,8DAA8D;IAC9D,MAAM,UAAU,GAAG,iBAAiB,CAAC,KAAK,CAAC,IAAsC,CAAC,CAAC;IACnF,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,oCAAoC;IACpC,8DAA8D;IAC9D,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,CAAC,CAAC;IACxE,IAAI,OAAO,EAAE,CAAC;QACZ,gDAAgD;QAChD,2CAA2C;QAC3C,OAAO,IAAA,qBAAY,EAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC5C,CAAC;IAED,kCAAkC;IAClC,OAAO,gBAAgB,CAAC;AAC1B,CAAC;AAED;;GAEG;AACH,SAAgB,cAAc,CAAC,KAAiB,EAAE,IAAmB;IACnE,IAAI,QAAQ,GAAG,oBAAoB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAEjD,gBAAgB;IAChB,IAAI,IAAA,kBAAW,EAAC,KAAK,CAAC,EAAE,CAAC;QACvB,QAAQ,GAAG,gBAAgB,QAAQ,GAAG,CAAC;IACzC,CAAC;IAED,4DAA4D;IAC5D,IAAI,CAAC,IAAA,sBAAe,EAAC,KAAK,CAAC,IAAI,CAAC,IAAA,sBAAe,EAAC,KAAK,CAAC,EAAE,CAAC;QACvD,QAAQ,GAAG,sBAAsB,QAAQ,GAAG,CAAC;IAC/C,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Generator Configuration
3
+ *
4
+ * Defines configuration options for prisma-effect-kysely generator
5
+ * with support for multi-domain organization and library scaffolding.
6
+ * Uses Effect Schema for strict validation.
7
+ */
8
+ import { Schema } from 'effect';
9
+ import type { GeneratorOptions } from '@prisma/generator-helper';
10
+ /**
11
+ * Generator configuration schema
12
+ */
13
+ declare const GeneratorConfigSchema: Schema.Struct<{
14
+ /**
15
+ * Output directory for generated Effect schemas
16
+ */
17
+ output: typeof Schema.String;
18
+ /**
19
+ * Enable multi-domain detection from schema file structure
20
+ */
21
+ multiFileDomains: Schema.Literal<["true", "false"]>;
22
+ /**
23
+ * Automatically scaffold contract libraries for detected domains
24
+ */
25
+ scaffoldLibraries: Schema.Literal<["true", "false"]>;
26
+ /**
27
+ * Path to monorepo-library-generator for library scaffolding
28
+ */
29
+ libraryGenerator: Schema.optional<typeof Schema.String>;
30
+ /**
31
+ * Preview features to enable
32
+ */
33
+ previewFeatures: Schema.Array$<typeof Schema.String>;
34
+ }>;
35
+ /**
36
+ * Generator configuration type derived from schema
37
+ */
38
+ export type GeneratorConfig = Schema.Schema.Type<typeof GeneratorConfigSchema>;
39
+ /**
40
+ * Parse and validate generator configuration from Prisma options
41
+ */
42
+ export declare function parseGeneratorConfig(options: GeneratorOptions): {
43
+ readonly output: string;
44
+ readonly multiFileDomains: "true" | "false";
45
+ readonly scaffoldLibraries: "true" | "false";
46
+ readonly libraryGenerator?: string | undefined;
47
+ readonly previewFeatures: readonly string[];
48
+ };
49
+ /**
50
+ * Check if multi-domain mode is enabled
51
+ */
52
+ export declare function isMultiDomainEnabled(config: GeneratorConfig): boolean;
53
+ /**
54
+ * Check if library scaffolding is enabled
55
+ */
56
+ export declare function isScaffoldingEnabled(config: GeneratorConfig): boolean;
57
+ export {};
58
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/generator/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAOjE;;GAEG;AACH,QAAA,MAAM,qBAAqB;IACzB;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;EAEH,CAAC;AAEH;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAE/E;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,gBAAgB;;;;;;EAwB7D;AAoCD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,eAAe,WAE3D;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,eAAe,WAE3D"}