forge-sql-orm 2.1.1 → 2.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/dist/ForgeSQLORM.js +142 -103
- package/dist/ForgeSQLORM.js.map +1 -1
- package/dist/ForgeSQLORM.mjs +142 -103
- package/dist/ForgeSQLORM.mjs.map +1 -1
- package/dist/core/ForgeSQLORM.d.ts.map +1 -1
- package/dist/core/ForgeSQLQueryBuilder.d.ts +24 -25
- package/dist/core/ForgeSQLQueryBuilder.d.ts.map +1 -1
- package/dist/lib/drizzle/extensions/additionalActions.d.ts.map +1 -1
- package/dist/utils/cacheContextUtils.d.ts +4 -2
- package/dist/utils/cacheContextUtils.d.ts.map +1 -1
- package/dist/utils/cacheUtils.d.ts.map +1 -1
- package/dist/utils/forgeDriver.d.ts.map +1 -1
- package/dist/utils/forgeDriverProxy.d.ts.map +1 -1
- package/dist/utils/sqlUtils.d.ts +1 -1
- package/dist/utils/sqlUtils.d.ts.map +1 -1
- package/dist/webtriggers/applyMigrationsWebTrigger.d.ts.map +1 -1
- package/dist/webtriggers/dropMigrationWebTrigger.d.ts.map +1 -1
- package/dist/webtriggers/dropTablesMigrationWebTrigger.d.ts.map +1 -1
- package/dist/webtriggers/fetchSchemaWebTrigger.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/core/ForgeSQLORM.ts +29 -23
- package/src/core/ForgeSQLQueryBuilder.ts +185 -128
- package/src/lib/drizzle/extensions/additionalActions.ts +125 -76
- package/src/lib/drizzle/extensions/types.d.ts +16 -11
- package/src/utils/cacheContextUtils.ts +16 -4
- package/src/utils/cacheUtils.ts +3 -1
- package/src/utils/forgeDriver.ts +16 -21
- package/src/utils/forgeDriverProxy.ts +10 -3
- package/src/utils/sqlUtils.ts +59 -35
- package/src/webtriggers/applyMigrationsWebTrigger.ts +18 -14
- package/src/webtriggers/dropMigrationWebTrigger.ts +8 -4
- package/src/webtriggers/dropTablesMigrationWebTrigger.ts +8 -4
- package/src/webtriggers/fetchSchemaWebTrigger.ts +7 -3
|
@@ -13,7 +13,11 @@ import {
|
|
|
13
13
|
} from "drizzle-orm/mysql-core/query-builders/select.types";
|
|
14
14
|
import { InferInsertModel, Query, SQL } from "drizzle-orm";
|
|
15
15
|
import { parseDateTime, formatDateTime } from "../utils/sqlUtils";
|
|
16
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
MySqlRemoteDatabase,
|
|
18
|
+
MySqlRemotePreparedQueryHKT,
|
|
19
|
+
MySqlRemoteQueryResultHKT,
|
|
20
|
+
} from "drizzle-orm/mysql-proxy";
|
|
17
21
|
import { SqlHints } from "../utils/sqlHints";
|
|
18
22
|
import {
|
|
19
23
|
ClusterStatementRowCamelCase,
|
|
@@ -22,27 +26,35 @@ import {
|
|
|
22
26
|
} from "./SystemTables";
|
|
23
27
|
import { ForgeSQLCacheOperations } from "./ForgeSQLCacheOperations";
|
|
24
28
|
import {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
DeleteAndEvictCacheType,
|
|
30
|
+
ExecuteQuery,
|
|
31
|
+
ExecuteQueryCacheable,
|
|
32
|
+
InsertAndEvictCacheType,
|
|
33
|
+
SelectAliasedCacheableType,
|
|
34
|
+
SelectAliasedDistinctCacheableType,
|
|
35
|
+
SelectAliasedDistinctType,
|
|
36
|
+
SelectAliasedType,
|
|
37
|
+
SelectAllDistinctFromAliasedType,
|
|
38
|
+
SelectAllDistinctFromCacheableAliasedType,
|
|
39
|
+
SelectAllFromAliasedType,
|
|
40
|
+
SelectAllFromCacheableAliasedType,
|
|
41
|
+
UpdateAndEvictCacheType,
|
|
33
42
|
} from "..";
|
|
34
43
|
import {
|
|
35
44
|
MySqlDeleteBase,
|
|
36
45
|
MySqlInsertBuilder,
|
|
37
|
-
|
|
46
|
+
MySqlSelectBase,
|
|
38
47
|
MySqlUpdateBuilder,
|
|
39
48
|
} from "drizzle-orm/mysql-core/query-builders";
|
|
40
|
-
|
|
41
|
-
import {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
import {
|
|
49
|
+
|
|
50
|
+
import {
|
|
51
|
+
GetSelectTableName,
|
|
52
|
+
GetSelectTableSelection,
|
|
53
|
+
} from "drizzle-orm/query-builders/select.types";
|
|
54
|
+
import { SQLWrapper } from "drizzle-orm/sql/sql";
|
|
55
|
+
import type { MySqlQueryResultKind } from "drizzle-orm/mysql-core/session";
|
|
56
|
+
import type { WithBuilder } from "drizzle-orm/mysql-core/subquery";
|
|
57
|
+
import { WithSubquery } from "drizzle-orm/subquery";
|
|
46
58
|
|
|
47
59
|
/**
|
|
48
60
|
* Core interface for ForgeSQL operations.
|
|
@@ -62,20 +74,20 @@ export interface ForgeSqlOperation extends QueryBuilderForgeSql {
|
|
|
62
74
|
getDrizzleQueryBuilder(): MySqlRemoteDatabase<Record<string, unknown>> & {
|
|
63
75
|
selectAliased: SelectAliasedType;
|
|
64
76
|
selectAliasedDistinct: SelectAliasedDistinctType;
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
77
|
+
executeQuery: ExecuteQuery;
|
|
78
|
+
selectAliasedCacheable: SelectAliasedCacheableType;
|
|
79
|
+
selectAliasedDistinctCacheable: SelectAliasedDistinctCacheableType;
|
|
80
|
+
executeQueryCacheable: ExecuteQueryCacheable;
|
|
81
|
+
insertWithCacheContext: InsertAndEvictCacheType;
|
|
82
|
+
insertAndEvictCache: InsertAndEvictCacheType;
|
|
83
|
+
updateAndEvictCache: UpdateAndEvictCacheType;
|
|
84
|
+
updateWithCacheContext: UpdateAndEvictCacheType;
|
|
85
|
+
deleteAndEvictCache: DeleteAndEvictCacheType;
|
|
86
|
+
deleteWithCacheContext: DeleteAndEvictCacheType;
|
|
87
|
+
selectFrom: SelectAllFromAliasedType;
|
|
88
|
+
selectDistinctFrom: SelectAllDistinctFromAliasedType;
|
|
89
|
+
selectFromCacheable: SelectAllFromCacheableAliasedType;
|
|
90
|
+
selectDistinctFromCacheable: SelectAllDistinctFromCacheableAliasedType;
|
|
79
91
|
};
|
|
80
92
|
|
|
81
93
|
/**
|
|
@@ -128,10 +140,10 @@ export interface QueryBuilderForgeSql {
|
|
|
128
140
|
getDrizzleQueryBuilder(): MySqlRemoteDatabase<Record<string, unknown>> & {
|
|
129
141
|
selectAliased: SelectAliasedType;
|
|
130
142
|
selectAliasedDistinct: SelectAliasedDistinctType;
|
|
131
|
-
|
|
143
|
+
executeQuery: ExecuteQuery;
|
|
132
144
|
selectAliasedCacheable: SelectAliasedCacheableType;
|
|
133
145
|
selectAliasedDistinctCacheable: SelectAliasedDistinctCacheableType;
|
|
134
|
-
|
|
146
|
+
executeQueryCacheable: ExecuteQueryCacheable;
|
|
135
147
|
insertWithCacheContext: InsertAndEvictCacheType;
|
|
136
148
|
insertAndEvictCache: InsertAndEvictCacheType;
|
|
137
149
|
updateAndEvictCache: UpdateAndEvictCacheType;
|
|
@@ -173,10 +185,19 @@ export interface QueryBuilderForgeSql {
|
|
|
173
185
|
* ```
|
|
174
186
|
*/
|
|
175
187
|
selectFrom<T extends MySqlTable>(
|
|
176
|
-
|
|
177
|
-
):
|
|
188
|
+
table: T,
|
|
189
|
+
): MySqlSelectBase<
|
|
190
|
+
GetSelectTableName<T>,
|
|
191
|
+
T["_"]["columns"] extends undefined ? GetSelectTableSelection<T> : T["_"]["columns"],
|
|
192
|
+
T["_"]["columns"] extends undefined ? "single" : "partial",
|
|
193
|
+
MySqlRemotePreparedQueryHKT,
|
|
194
|
+
GetSelectTableName<T> extends string ? Record<string & GetSelectTableName<T>, "not-null"> : {},
|
|
195
|
+
false,
|
|
196
|
+
never,
|
|
197
|
+
any
|
|
198
|
+
>;
|
|
178
199
|
|
|
179
|
-
|
|
200
|
+
/**
|
|
180
201
|
* Creates a distinct select query with unique field aliases to prevent field name collisions in joins.
|
|
181
202
|
* This is particularly useful when working with Atlassian Forge SQL, which collapses fields with the same name in joined tables.
|
|
182
203
|
*
|
|
@@ -195,21 +216,30 @@ export interface QueryBuilderForgeSql {
|
|
|
195
216
|
selectDistinct<TSelection extends SelectedFields>(
|
|
196
217
|
fields: TSelection,
|
|
197
218
|
): MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT>;
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
219
|
+
/**
|
|
220
|
+
* Creates a select distinct query builder for all columns from a table with field aliasing support.
|
|
221
|
+
* This is a convenience method that automatically selects all distinct columns from the specified table.
|
|
222
|
+
*
|
|
223
|
+
* @template T - The type of the table
|
|
224
|
+
* @param table - The table to select from
|
|
225
|
+
* @returns Select distinct query builder with all table columns and field aliasing support
|
|
226
|
+
* @example
|
|
227
|
+
* ```typescript
|
|
228
|
+
* const uniqueUsers = await forgeSQL.selectDistinctFrom(userTable).where(eq(userTable.status, 'active'));
|
|
229
|
+
* ```
|
|
230
|
+
*/
|
|
231
|
+
selectDistinctFrom<T extends MySqlTable>(
|
|
232
|
+
table: T,
|
|
233
|
+
): MySqlSelectBase<
|
|
234
|
+
GetSelectTableName<T>,
|
|
235
|
+
T["_"]["columns"] extends undefined ? GetSelectTableSelection<T> : T["_"]["columns"],
|
|
236
|
+
T["_"]["columns"] extends undefined ? "single" : "partial",
|
|
237
|
+
MySqlRemotePreparedQueryHKT,
|
|
238
|
+
GetSelectTableName<T> extends string ? Record<string & GetSelectTableName<T>, "not-null"> : {},
|
|
239
|
+
false,
|
|
240
|
+
never,
|
|
241
|
+
any
|
|
242
|
+
>;
|
|
213
243
|
|
|
214
244
|
/**
|
|
215
245
|
* Creates a cacheable select query with unique field aliases to prevent field name collisions in joins.
|
|
@@ -247,9 +277,18 @@ export interface QueryBuilderForgeSql {
|
|
|
247
277
|
* ```
|
|
248
278
|
*/
|
|
249
279
|
selectCacheableFrom<T extends MySqlTable>(
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
280
|
+
table: T,
|
|
281
|
+
cacheTTL?: number,
|
|
282
|
+
): MySqlSelectBase<
|
|
283
|
+
GetSelectTableName<T>,
|
|
284
|
+
T["_"]["columns"] extends undefined ? GetSelectTableSelection<T> : T["_"]["columns"],
|
|
285
|
+
T["_"]["columns"] extends undefined ? "single" : "partial",
|
|
286
|
+
MySqlRemotePreparedQueryHKT,
|
|
287
|
+
GetSelectTableName<T> extends string ? Record<string & GetSelectTableName<T>, "not-null"> : {},
|
|
288
|
+
false,
|
|
289
|
+
never,
|
|
290
|
+
any
|
|
291
|
+
>;
|
|
253
292
|
|
|
254
293
|
/**
|
|
255
294
|
* Creates a cacheable distinct select query with unique field aliases to prevent field name collisions in joins.
|
|
@@ -273,25 +312,34 @@ export interface QueryBuilderForgeSql {
|
|
|
273
312
|
cacheTTL?: number,
|
|
274
313
|
): MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT>;
|
|
275
314
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
315
|
+
/**
|
|
316
|
+
* Creates a cacheable select distinct query builder for all columns from a table with field aliasing and caching support.
|
|
317
|
+
* This is a convenience method that automatically selects all distinct columns from the specified table with caching enabled.
|
|
318
|
+
*
|
|
319
|
+
* @template T - The type of the table
|
|
320
|
+
* @param table - The table to select from
|
|
321
|
+
* @param cacheTTL - Optional cache TTL override (defaults to global cache TTL)
|
|
322
|
+
* @returns Select distinct query builder with all table columns, field aliasing, and caching support
|
|
323
|
+
* @example
|
|
324
|
+
* ```typescript
|
|
325
|
+
* const uniqueUsers = await forgeSQL.selectDistinctCacheableFrom(userTable, 300).where(eq(userTable.status, 'active'));
|
|
326
|
+
* ```
|
|
327
|
+
*/
|
|
328
|
+
selectDistinctCacheableFrom<T extends MySqlTable>(
|
|
329
|
+
table: T,
|
|
330
|
+
cacheTTL?: number,
|
|
331
|
+
): MySqlSelectBase<
|
|
332
|
+
GetSelectTableName<T>,
|
|
333
|
+
T["_"]["columns"] extends undefined ? GetSelectTableSelection<T> : T["_"]["columns"],
|
|
334
|
+
T["_"]["columns"] extends undefined ? "single" : "partial",
|
|
335
|
+
MySqlRemotePreparedQueryHKT,
|
|
336
|
+
GetSelectTableName<T> extends string ? Record<string & GetSelectTableName<T>, "not-null"> : {},
|
|
337
|
+
false,
|
|
338
|
+
never,
|
|
339
|
+
any
|
|
340
|
+
>;
|
|
341
|
+
|
|
342
|
+
/**
|
|
295
343
|
* Creates an insert query builder.
|
|
296
344
|
*
|
|
297
345
|
* ⚠️ **IMPORTANT**: This method does NOT support optimistic locking/versioning.
|
|
@@ -460,12 +508,14 @@ export interface QueryBuilderForgeSql {
|
|
|
460
508
|
* ```typescript
|
|
461
509
|
* // Using SQLWrapper
|
|
462
510
|
* const result = await forgeSQL.execute(sql`SELECT * FROM users WHERE id = ${userId}`);
|
|
463
|
-
*
|
|
511
|
+
*
|
|
464
512
|
* // Using string
|
|
465
513
|
* const result = await forgeSQL.execute("SELECT * FROM users WHERE status = 'active'");
|
|
466
514
|
* ```
|
|
467
515
|
*/
|
|
468
|
-
execute(
|
|
516
|
+
execute(
|
|
517
|
+
query: SQLWrapper | string,
|
|
518
|
+
): Promise<MySqlQueryResultKind<MySqlRemoteQueryResultHKT, unknown>>;
|
|
469
519
|
|
|
470
520
|
/**
|
|
471
521
|
* Executes a raw SQL query with both local and global cache support.
|
|
@@ -480,57 +530,64 @@ export interface QueryBuilderForgeSql {
|
|
|
480
530
|
* ```typescript
|
|
481
531
|
* // Using SQLWrapper with custom TTL
|
|
482
532
|
* const result = await forgeSQL.executeCacheable(sql`SELECT * FROM users WHERE id = ${userId}`, 300);
|
|
483
|
-
*
|
|
533
|
+
*
|
|
484
534
|
* // Using string with default TTL
|
|
485
535
|
* const result = await forgeSQL.executeCacheable("SELECT * FROM users WHERE status = 'active'");
|
|
486
536
|
* ```
|
|
487
537
|
*/
|
|
488
|
-
executeCacheable(
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
}
|
|
538
|
+
executeCacheable(
|
|
539
|
+
query: SQLWrapper | string,
|
|
540
|
+
cacheTtl?: number,
|
|
541
|
+
): Promise<MySqlQueryResultKind<MySqlRemoteQueryResultHKT, unknown>>;
|
|
542
|
+
/**
|
|
543
|
+
* Creates a Common Table Expression (CTE) builder for complex queries.
|
|
544
|
+
* CTEs allow you to define temporary named result sets that exist within the scope of a single query.
|
|
545
|
+
*
|
|
546
|
+
* @returns WithBuilder for creating CTEs
|
|
547
|
+
* @example
|
|
548
|
+
* ```typescript
|
|
549
|
+
* const withQuery = forgeSQL.$with('userStats').as(
|
|
550
|
+
* forgeSQL.select({ userId: users.id, count: sql<number>`count(*)` })
|
|
551
|
+
* .from(users)
|
|
552
|
+
* .groupBy(users.id)
|
|
553
|
+
* );
|
|
554
|
+
* ```
|
|
555
|
+
*/
|
|
556
|
+
$with: WithBuilder;
|
|
557
|
+
|
|
558
|
+
/**
|
|
559
|
+
* Creates a query builder that uses Common Table Expressions (CTEs).
|
|
560
|
+
* CTEs allow you to define temporary named result sets that exist within the scope of a single query.
|
|
561
|
+
*
|
|
562
|
+
* @param queries - Array of CTE queries created with $with()
|
|
563
|
+
* @returns Query builder with CTE support
|
|
564
|
+
* @example
|
|
565
|
+
* ```typescript
|
|
566
|
+
* const withQuery = forgeSQL.$with('userStats').as(
|
|
567
|
+
* forgeSQL.select({ userId: users.id, count: sql<number>`count(*)` })
|
|
568
|
+
* .from(users)
|
|
569
|
+
* .groupBy(users.id)
|
|
570
|
+
* );
|
|
571
|
+
*
|
|
572
|
+
* const result = await forgeSQL.with(withQuery)
|
|
573
|
+
* .select({ userId: withQuery.userId, count: withQuery.count })
|
|
574
|
+
* .from(withQuery);
|
|
575
|
+
* ```
|
|
576
|
+
*/
|
|
577
|
+
with(...queries: WithSubquery[]): {
|
|
578
|
+
select: {
|
|
579
|
+
(): MySqlSelectBuilder<undefined, MySqlRemotePreparedQueryHKT>;
|
|
580
|
+
<TSelection extends SelectedFields>(
|
|
581
|
+
fields: TSelection,
|
|
582
|
+
): MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT>;
|
|
583
|
+
};
|
|
584
|
+
selectDistinct: {
|
|
585
|
+
(): MySqlSelectBuilder<undefined, MySqlRemotePreparedQueryHKT>;
|
|
586
|
+
<TSelection extends SelectedFields>(
|
|
587
|
+
fields: TSelection,
|
|
588
|
+
): MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT>;
|
|
589
|
+
};
|
|
590
|
+
};
|
|
534
591
|
}
|
|
535
592
|
|
|
536
593
|
/**
|
|
@@ -807,10 +864,10 @@ export const forgeDateTimeString = customType<{
|
|
|
807
864
|
return "datetime";
|
|
808
865
|
},
|
|
809
866
|
toDriver(value: Date) {
|
|
810
|
-
return formatDateTime(value, "yyyy-
|
|
867
|
+
return formatDateTime(value, "yyyy-MM-dd' 'HH:mm:ss.SSS", false);
|
|
811
868
|
},
|
|
812
869
|
fromDriver(value: unknown) {
|
|
813
|
-
const format = "yyyy-
|
|
870
|
+
const format = "yyyy-MM-dd' 'HH:mm:ss.SSS";
|
|
814
871
|
return parseDateTime(value as string, format);
|
|
815
872
|
},
|
|
816
873
|
});
|
|
@@ -830,10 +887,10 @@ export const forgeTimestampString = customType<{
|
|
|
830
887
|
return "timestamp";
|
|
831
888
|
},
|
|
832
889
|
toDriver(value: Date) {
|
|
833
|
-
return formatDateTime(value, "yyyy-
|
|
890
|
+
return formatDateTime(value, "yyyy-MM-dd' 'HH:mm:ss.SSS", true);
|
|
834
891
|
},
|
|
835
892
|
fromDriver(value: unknown) {
|
|
836
|
-
const format = "yyyy-
|
|
893
|
+
const format = "yyyy-MM-dd' 'HH:mm:ss.SSS";
|
|
837
894
|
return parseDateTime(value as string, format);
|
|
838
895
|
},
|
|
839
896
|
});
|
|
@@ -853,10 +910,10 @@ export const forgeDateString = customType<{
|
|
|
853
910
|
return "date";
|
|
854
911
|
},
|
|
855
912
|
toDriver(value: Date) {
|
|
856
|
-
return formatDateTime(value, "yyyy-
|
|
913
|
+
return formatDateTime(value, "yyyy-MM-dd", false);
|
|
857
914
|
},
|
|
858
915
|
fromDriver(value: unknown) {
|
|
859
|
-
const format = "yyyy-
|
|
916
|
+
const format = "yyyy-MM-dd";
|
|
860
917
|
return parseDateTime(value as string, format);
|
|
861
918
|
},
|
|
862
919
|
});
|
|
@@ -876,7 +933,7 @@ export const forgeTimeString = customType<{
|
|
|
876
933
|
return "time";
|
|
877
934
|
},
|
|
878
935
|
toDriver(value: Date) {
|
|
879
|
-
return formatDateTime(value, "HH:mm:ss.SSS");
|
|
936
|
+
return formatDateTime(value, "HH:mm:ss.SSS", false);
|
|
880
937
|
},
|
|
881
938
|
fromDriver(value: unknown) {
|
|
882
939
|
return parseDateTime(value as string, "HH:mm:ss.SSS");
|