@opensaas/stack-core 0.11.0 → 0.12.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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +56 -0
- package/dist/config/types.d.ts +45 -1
- package/dist/config/types.d.ts.map +1 -1
- package/dist/fields/index.d.ts +42 -1
- package/dist/fields/index.d.ts.map +1 -1
- package/dist/fields/index.js +123 -3
- package/dist/fields/index.js.map +1 -1
- package/package.json +1 -1
- package/src/config/types.ts +49 -1
- package/src/fields/index.ts +136 -3
- package/tsconfig.tsbuildinfo +1 -1
package/src/fields/index.ts
CHANGED
|
@@ -5,6 +5,7 @@ import type {
|
|
|
5
5
|
DecimalField,
|
|
6
6
|
CheckboxField,
|
|
7
7
|
TimestampField,
|
|
8
|
+
CalendarDayField,
|
|
8
9
|
PasswordField,
|
|
9
10
|
SelectField,
|
|
10
11
|
RelationshipField,
|
|
@@ -67,14 +68,21 @@ export function text<
|
|
|
67
68
|
},
|
|
68
69
|
getPrismaType: (_fieldName: string) => {
|
|
69
70
|
const validation = options?.validation
|
|
71
|
+
const db = options?.db
|
|
70
72
|
const isRequired = validation?.isRequired
|
|
73
|
+
const isNullable = db?.isNullable ?? !isRequired
|
|
71
74
|
let modifiers = ''
|
|
72
75
|
|
|
73
76
|
// Optional modifier
|
|
74
|
-
if (
|
|
77
|
+
if (isNullable) {
|
|
75
78
|
modifiers += '?'
|
|
76
79
|
}
|
|
77
80
|
|
|
81
|
+
// Native type modifier (e.g., @db.Text)
|
|
82
|
+
if (db?.nativeType) {
|
|
83
|
+
modifiers += ` @db.${db.nativeType}`
|
|
84
|
+
}
|
|
85
|
+
|
|
78
86
|
// Unique/index modifiers
|
|
79
87
|
if (options?.isIndexed === 'unique') {
|
|
80
88
|
modifiers += ' @unique'
|
|
@@ -83,8 +91,8 @@ export function text<
|
|
|
83
91
|
}
|
|
84
92
|
|
|
85
93
|
// Map modifier
|
|
86
|
-
if (
|
|
87
|
-
modifiers += ` @map("${
|
|
94
|
+
if (db?.map) {
|
|
95
|
+
modifiers += ` @map("${db.map}")`
|
|
88
96
|
}
|
|
89
97
|
|
|
90
98
|
return {
|
|
@@ -421,6 +429,131 @@ export function timestamp<
|
|
|
421
429
|
}
|
|
422
430
|
}
|
|
423
431
|
|
|
432
|
+
/**
|
|
433
|
+
* Calendar Day field - date only (no time) in ISO8601 format
|
|
434
|
+
*
|
|
435
|
+
* **Features:**
|
|
436
|
+
* - Stores date values only (no time component)
|
|
437
|
+
* - PostgreSQL/MySQL: Uses native DATE type via @db.Date
|
|
438
|
+
* - SQLite: Uses String representation
|
|
439
|
+
* - Accepts ISO8601 date strings (YYYY-MM-DD format)
|
|
440
|
+
* - Optional validation for required fields
|
|
441
|
+
* - Database column mapping and nullability control
|
|
442
|
+
* - Index support (boolean or 'unique')
|
|
443
|
+
*
|
|
444
|
+
* **Usage Example:**
|
|
445
|
+
* ```typescript
|
|
446
|
+
* // In opensaas.config.ts
|
|
447
|
+
* fields: {
|
|
448
|
+
* birthDate: calendarDay({
|
|
449
|
+
* validation: { isRequired: true }
|
|
450
|
+
* }),
|
|
451
|
+
* startDate: calendarDay({
|
|
452
|
+
* defaultValue: '2025-01-01',
|
|
453
|
+
* db: { map: 'start_date' }
|
|
454
|
+
* }),
|
|
455
|
+
* endDate: calendarDay({
|
|
456
|
+
* isIndexed: true
|
|
457
|
+
* })
|
|
458
|
+
* }
|
|
459
|
+
*
|
|
460
|
+
* // Creating with date values
|
|
461
|
+
* const event = await context.db.event.create({
|
|
462
|
+
* data: {
|
|
463
|
+
* startDate: '2025-01-15',
|
|
464
|
+
* endDate: '2025-01-20'
|
|
465
|
+
* }
|
|
466
|
+
* })
|
|
467
|
+
* ```
|
|
468
|
+
*
|
|
469
|
+
* @param options - Field configuration options
|
|
470
|
+
* @returns Calendar Day field configuration
|
|
471
|
+
*/
|
|
472
|
+
export function calendarDay<
|
|
473
|
+
TTypeInfo extends import('../config/types.js').TypeInfo = import('../config/types.js').TypeInfo,
|
|
474
|
+
>(options?: Omit<CalendarDayField<TTypeInfo>, 'type'>): CalendarDayField<TTypeInfo> {
|
|
475
|
+
return {
|
|
476
|
+
type: 'calendarDay',
|
|
477
|
+
...options,
|
|
478
|
+
getZodSchema: (fieldName: string, operation: 'create' | 'update') => {
|
|
479
|
+
const validation = options?.validation
|
|
480
|
+
const isRequired = validation?.isRequired
|
|
481
|
+
|
|
482
|
+
// Accept ISO8601 date strings (YYYY-MM-DD)
|
|
483
|
+
const baseSchema = z.string({
|
|
484
|
+
message: `${formatFieldName(fieldName)} must be a valid date in ISO8601 format (YYYY-MM-DD)`,
|
|
485
|
+
})
|
|
486
|
+
|
|
487
|
+
// Validate ISO8601 date format (YYYY-MM-DD)
|
|
488
|
+
const dateSchema = baseSchema.regex(/^\d{4}-\d{2}-\d{2}$/, {
|
|
489
|
+
message: `${formatFieldName(fieldName)} must be in YYYY-MM-DD format`,
|
|
490
|
+
})
|
|
491
|
+
|
|
492
|
+
if (isRequired && operation === 'create') {
|
|
493
|
+
return dateSchema
|
|
494
|
+
} else if (isRequired && operation === 'update') {
|
|
495
|
+
// Required in update mode: can be undefined for partial updates
|
|
496
|
+
return z.union([dateSchema, z.undefined()])
|
|
497
|
+
} else {
|
|
498
|
+
return dateSchema.optional().nullable()
|
|
499
|
+
}
|
|
500
|
+
},
|
|
501
|
+
getPrismaType: (_fieldName: string, provider?: string) => {
|
|
502
|
+
const validation = options?.validation
|
|
503
|
+
const db = options?.db
|
|
504
|
+
const isRequired = validation?.isRequired
|
|
505
|
+
const isNullable = db?.isNullable ?? !isRequired
|
|
506
|
+
|
|
507
|
+
let modifiers = ''
|
|
508
|
+
|
|
509
|
+
// Optional modifier
|
|
510
|
+
if (isNullable) {
|
|
511
|
+
modifiers += '?'
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
// Add @db.Date attribute for date-only storage
|
|
515
|
+
// Only for PostgreSQL/MySQL - SQLite doesn't support native DATE type
|
|
516
|
+
// SQLite will use TEXT for DateTime fields
|
|
517
|
+
if (provider && provider.toLowerCase() !== 'sqlite') {
|
|
518
|
+
modifiers += ' @db.Date'
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
// Default value if provided
|
|
522
|
+
if (options?.defaultValue !== undefined) {
|
|
523
|
+
modifiers += ` @default("${options.defaultValue}")`
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
// Database mapping
|
|
527
|
+
if (db?.map) {
|
|
528
|
+
modifiers += ` @map("${db.map}")`
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
// Unique/index modifiers
|
|
532
|
+
if (options?.isIndexed === 'unique') {
|
|
533
|
+
modifiers += ' @unique'
|
|
534
|
+
} else if (options?.isIndexed === true) {
|
|
535
|
+
modifiers += ' @index'
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
return {
|
|
539
|
+
type: 'DateTime',
|
|
540
|
+
modifiers: modifiers.trimStart() || undefined,
|
|
541
|
+
}
|
|
542
|
+
},
|
|
543
|
+
getTypeScriptType: () => {
|
|
544
|
+
const validation = options?.validation
|
|
545
|
+
const db = options?.db
|
|
546
|
+
const isRequired = validation?.isRequired
|
|
547
|
+
const isNullable = db?.isNullable ?? !isRequired
|
|
548
|
+
|
|
549
|
+
return {
|
|
550
|
+
type: 'Date',
|
|
551
|
+
optional: isNullable,
|
|
552
|
+
}
|
|
553
|
+
},
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
|
|
424
557
|
/**
|
|
425
558
|
* Password field (automatically hashed using bcrypt)
|
|
426
559
|
*
|