kysely-hydrate 0.7.3 → 0.9.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/README.md +83 -6
- package/dist/{errors-EVqhxGJc.mjs → errors-CbAVHTlW.mjs} +2 -2
- package/dist/experimental.mjs +1 -1
- package/dist/index.d.mts +95 -13
- package/dist/index.mjs +23 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -130,8 +130,10 @@ type Result = Array<{
|
|
|
130
130
|
- [Sorting with `.orderBy()`](#sorting-with-orderby)
|
|
131
131
|
- [Pagination and aggregation](#pagination-and-aggregation)
|
|
132
132
|
- [Inspect the SQL](#inspecting-the-sql)
|
|
133
|
+
- [Hydrating pre-fetched rows with `.hydrate()`](#hydrating-pre-fetched-rows-with-hydrate)
|
|
133
134
|
- [Mapped properties with `.mapFields()`](#mapped-properties-with-mapfields)
|
|
134
135
|
- [Computed properties with `.extras()`](#computed-properties-with-extras)
|
|
136
|
+
- [Computed properties with `.extend()`](#computed-properties-with-extend)
|
|
135
137
|
- [Excluded properties with `.omit()`](#excluded-properties-with-omit)
|
|
136
138
|
- [Output transformations with `.map()`](#output-transformations-with-map)
|
|
137
139
|
- [Composable mappings with `.with()`](#composable-mappings-with-with)
|
|
@@ -146,7 +148,7 @@ type Result = Array<{
|
|
|
146
148
|
- [Output transformations with `.map()`](#output-transformations-with-map-1)
|
|
147
149
|
- [Attached collections with `.attach*()`](#attached-collections-with-attach)
|
|
148
150
|
- [Prefixed collections with `.has*()`](#prefixed-collections-with-has)
|
|
149
|
-
- [Composing hydrators with `.
|
|
151
|
+
- [Composing hydrators with `.with()`](#composing-hydrators-with-with)
|
|
150
152
|
- [FAQ](#faq)
|
|
151
153
|
|
|
152
154
|
## Installation
|
|
@@ -798,6 +800,53 @@ You can inspect the generated SQL using `.toQuery()`, `.toJoinedQuery()`, or `.t
|
|
|
798
800
|
- `toJoinedQuery()`: Returns the query with all joins applied (subject to row explosion).
|
|
799
801
|
- `toBaseQuery()`: Returns the base query without any joins (but with modifications).
|
|
800
802
|
|
|
803
|
+
### Hydrating pre-fetched rows with `.hydrate()`
|
|
804
|
+
|
|
805
|
+
Sometimes you already have the flat rows—from a separate query, a cache, a
|
|
806
|
+
transaction, or from calling `.toQuery().execute()` directly—and want to hydrate
|
|
807
|
+
them without re-executing the query.
|
|
808
|
+
|
|
809
|
+
The `.hydrate()` method applies the same hydration logic that `.execute()` uses,
|
|
810
|
+
including nested joins, `mapFields`, `extras`, `omit`, and `map`.
|
|
811
|
+
|
|
812
|
+
```ts
|
|
813
|
+
const qs = querySet(db)
|
|
814
|
+
.selectAs("user", db.selectFrom("users").select(["id", "username"]))
|
|
815
|
+
.leftJoinMany(
|
|
816
|
+
"posts",
|
|
817
|
+
({ eb, qs }) => qs(eb.selectFrom("posts").select(["id", "title", "userId"])),
|
|
818
|
+
"posts.userId",
|
|
819
|
+
"user.id",
|
|
820
|
+
);
|
|
821
|
+
|
|
822
|
+
// Fetch the flat rows yourself
|
|
823
|
+
const rows = await qs.toQuery().execute();
|
|
824
|
+
|
|
825
|
+
// Hydrate them
|
|
826
|
+
const users = await qs.hydrate(rows);
|
|
827
|
+
// ⬇
|
|
828
|
+
type Result = Array<{
|
|
829
|
+
id: number;
|
|
830
|
+
username: string;
|
|
831
|
+
posts: Array<{ id: number; title: string; userId: number }>;
|
|
832
|
+
}>;
|
|
833
|
+
```
|
|
834
|
+
|
|
835
|
+
It also accepts a single row and returns a single hydrated result:
|
|
836
|
+
|
|
837
|
+
```ts
|
|
838
|
+
const [row] = await qs.toQuery().execute();
|
|
839
|
+
const user = await qs.hydrate(row);
|
|
840
|
+
// ⬇ { id: number; username: string; posts: Array<...> }
|
|
841
|
+
```
|
|
842
|
+
|
|
843
|
+
For convenience, `.hydrate()` accepts a `Promise` as input, so you can skip
|
|
844
|
+
the intermediate `await`:
|
|
845
|
+
|
|
846
|
+
```ts
|
|
847
|
+
const users = await qs.hydrate(qs.toQuery().execute());
|
|
848
|
+
```
|
|
849
|
+
|
|
801
850
|
### Mapped properties with `.mapFields()`
|
|
802
851
|
|
|
803
852
|
Transform individual fields in the result set. This changes the output type for
|
|
@@ -843,6 +892,34 @@ type Result = Array<{
|
|
|
843
892
|
}>;
|
|
844
893
|
```
|
|
845
894
|
|
|
895
|
+
### Computed properties with `.extend()`
|
|
896
|
+
|
|
897
|
+
Like `.extras()`, but takes a single function that returns an object. All
|
|
898
|
+
returned keys are merged into the output. This is useful when multiple computed
|
|
899
|
+
fields share intermediate work.
|
|
900
|
+
|
|
901
|
+
```ts
|
|
902
|
+
const users = await querySet(db)
|
|
903
|
+
.selectAs("user", db.selectFrom("users").select(["id", "firstName", "lastName", "birthDate"]))
|
|
904
|
+
.extend((row) => {
|
|
905
|
+
const names = [row.firstName, row.lastName];
|
|
906
|
+
return {
|
|
907
|
+
fullName: names.join(" "),
|
|
908
|
+
initials: names.map((n) => n[0]).join(""),
|
|
909
|
+
};
|
|
910
|
+
})
|
|
911
|
+
.execute();
|
|
912
|
+
// ⬇
|
|
913
|
+
type Result = Array<{
|
|
914
|
+
id: number;
|
|
915
|
+
firstName: string;
|
|
916
|
+
lastName: string;
|
|
917
|
+
birthDate: Date;
|
|
918
|
+
fullName: string;
|
|
919
|
+
initials: string;
|
|
920
|
+
}>;
|
|
921
|
+
```
|
|
922
|
+
|
|
846
923
|
### Excluded properties with `.omit()`
|
|
847
924
|
|
|
848
925
|
Remove fields from the final output. This is useful for removing intermediate
|
|
@@ -1355,7 +1432,7 @@ type Result = UserModel[];
|
|
|
1355
1432
|
|
|
1356
1433
|
As in query sets, `.map()` is a terminal operation—after calling it, you can
|
|
1357
1434
|
only call `.map()` again or `.hydrate()`. You cannot call configuration methods
|
|
1358
|
-
like `.fields()`, `.extras()`, `.has*()`, or `.
|
|
1435
|
+
like `.fields()`, `.extras()`, `.has*()`, or `.with()`.
|
|
1359
1436
|
|
|
1360
1437
|
```ts
|
|
1361
1438
|
const mapped = createHydrator<User>()
|
|
@@ -1368,7 +1445,7 @@ mapped.hydrate(rows);
|
|
|
1368
1445
|
|
|
1369
1446
|
// ❌ These don't compile:
|
|
1370
1447
|
mapped.fields({ ... }); // Error: Property 'fields' does not exist
|
|
1371
|
-
mapped.
|
|
1448
|
+
mapped.with(...); // Error: Property 'with' does not exist
|
|
1372
1449
|
```
|
|
1373
1450
|
|
|
1374
1451
|
### Attached collections with `.attach*()`
|
|
@@ -1423,7 +1500,7 @@ non-nullable column that was made nullable by a left join; or, (b) it's actually
|
|
|
1423
1500
|
nullable in the "posts" table. The query set API, on the other hand, _does_
|
|
1424
1501
|
know the difference, and so does not suffer from this problem.
|
|
1425
1502
|
|
|
1426
|
-
### Composing hydrators with `.
|
|
1503
|
+
### Composing hydrators with `.with()`
|
|
1427
1504
|
|
|
1428
1505
|
Merges two hydrators. The second hydrator's configuration takes precedence.
|
|
1429
1506
|
|
|
@@ -1431,7 +1508,7 @@ This is a good way to build small, reusable hydrators (for a "user preview", a
|
|
|
1431
1508
|
"user display name", etc.) and compose them.
|
|
1432
1509
|
|
|
1433
1510
|
> [!NOTE]
|
|
1434
|
-
> Hydrators must have the same `keyBy`. If they don't, `.
|
|
1511
|
+
> Hydrators must have the same `keyBy`. If they don't, `.with()` throws.
|
|
1435
1512
|
|
|
1436
1513
|
```ts
|
|
1437
1514
|
type UserRow = { id: number; username: string; email: string };
|
|
@@ -1442,7 +1519,7 @@ const withDisplayName = createHydrator<UserRow>().extras({
|
|
|
1442
1519
|
displayName: (u) => `${u.username} <${u.email}>`,
|
|
1443
1520
|
});
|
|
1444
1521
|
|
|
1445
|
-
const combined = base.
|
|
1522
|
+
const combined = base.with(withDisplayName);
|
|
1446
1523
|
// ⬇
|
|
1447
1524
|
type Result = Hydrator<UserRow, { id: number; username: string; displayName: string }>;
|
|
1448
1525
|
```
|
|
@@ -76,12 +76,12 @@ var UnsupportedNodeTypeError = class extends KyselyHydrateError {
|
|
|
76
76
|
}
|
|
77
77
|
};
|
|
78
78
|
/**
|
|
79
|
-
* Error thrown when
|
|
79
|
+
* Error thrown when composing a Hydrator with another Hydrator
|
|
80
80
|
* that has a different keyBy configuration.
|
|
81
81
|
*/
|
|
82
82
|
var KeyByMismatchError = class extends KyselyHydrateError {
|
|
83
83
|
constructor(thisKeyBy, otherKeyBy) {
|
|
84
|
-
super(`Cannot
|
|
84
|
+
super(`Cannot compose hydrators with different keyBy: ${thisKeyBy} vs ${otherKeyBy}`);
|
|
85
85
|
}
|
|
86
86
|
};
|
|
87
87
|
/**
|
package/dist/experimental.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { d as UnsupportedAliasNodeTypeError, f as UnsupportedNodeTypeError, m as WildcardSelectionError, p as UnsupportedTableAliasNodeTypeError, t as AmbiguousColumnReferenceError, u as UnexpectedSelectionTypeError } from "./errors-
|
|
1
|
+
import { d as UnsupportedAliasNodeTypeError, f as UnsupportedNodeTypeError, m as WildcardSelectionError, p as UnsupportedTableAliasNodeTypeError, t as AmbiguousColumnReferenceError, u as UnexpectedSelectionTypeError } from "./errors-CbAVHTlW.mjs";
|
|
2
2
|
import * as k from "kysely";
|
|
3
3
|
|
|
4
4
|
//#region src/experimental/mapped-expression.ts
|
package/dist/index.d.mts
CHANGED
|
@@ -101,6 +101,15 @@ type Extras<Input> = Record<string, (input: Input) => unknown>;
|
|
|
101
101
|
* Uses the return type of each extra function.
|
|
102
102
|
*/
|
|
103
103
|
type InferExtras<Input, E extends Extras<Input>> = { [K in keyof E]: ReturnType<E[K]> };
|
|
104
|
+
/**
|
|
105
|
+
* An extender function that receives the full input and returns an object
|
|
106
|
+
* of computed properties to merge into the output.
|
|
107
|
+
*/
|
|
108
|
+
type Extender<Input> = (input: Input) => Record<string, unknown>;
|
|
109
|
+
/**
|
|
110
|
+
* Infers the output type for an extender function.
|
|
111
|
+
*/
|
|
112
|
+
type InferExtender<Input, F extends Extender<Input>> = ReturnType<F>;
|
|
104
113
|
/**
|
|
105
114
|
* The mode of a collection.
|
|
106
115
|
*
|
|
@@ -298,18 +307,29 @@ interface FullHydrator<Input, Output> extends MappedHydrator<Input, Output> {
|
|
|
298
307
|
*/
|
|
299
308
|
extras<E extends Extras<Input>>(extras: E): FullHydrator<Input, Extend<Output, InferExtras<Input, E>>>;
|
|
300
309
|
/**
|
|
301
|
-
*
|
|
310
|
+
* Adds computed fields to the hydrated output by spreading the return value
|
|
311
|
+
* of a function. Unlike `.extras()` which defines one field at a time,
|
|
312
|
+
* `.extend()` calls a single function whose returned object is merged into
|
|
313
|
+
* the output.
|
|
314
|
+
*
|
|
315
|
+
* @param fn - A function that receives the input and returns an object of
|
|
316
|
+
* computed properties
|
|
317
|
+
* @returns A new Hydrator with the extender applied
|
|
318
|
+
*/
|
|
319
|
+
extend<F extends Extender<Input>>(fn: F): FullHydrator<Input, Extend<Output, InferExtender<Input, F>>>;
|
|
320
|
+
/**
|
|
321
|
+
* Composes this Hydrator with the configuration from another Hydrator. The
|
|
302
322
|
* other Hydrator's configuration takes precedence in case of conflicts.
|
|
303
323
|
*
|
|
304
324
|
* Both hydrators must have the same `keyBy`, and any overlapping fields
|
|
305
325
|
* between the two input types must have compatible types.
|
|
306
326
|
*
|
|
307
|
-
* @param other - The Hydrator to
|
|
327
|
+
* @param other - The Hydrator to compose with
|
|
308
328
|
* @returns A new Hydrator with merged configuration
|
|
309
329
|
* @throws {KeyByMismatchError} If the keyBy configurations don't match
|
|
310
330
|
*/
|
|
311
|
-
|
|
312
|
-
|
|
331
|
+
with<OtherInput extends Partial<Input>, OtherOutput>(other: FullHydrator<OtherInput, OtherOutput>): FullHydrator<Input & OtherInput, Extend<Output, OtherOutput>>;
|
|
332
|
+
with<OtherInput extends Partial<Input>, OtherOutput>(other: MappedHydrator<OtherInput, OtherOutput>): MappedHydrator<Input & OtherInput, Extend<Output, OtherOutput>>;
|
|
313
333
|
/**
|
|
314
334
|
* Configures a nested collection that exists in the same query result. The
|
|
315
335
|
* child data is expected to be prefixed in the input (e.g., `posts$$id`,
|
|
@@ -593,7 +613,7 @@ interface TSelectQuerySet extends TQuerySet {
|
|
|
593
613
|
BaseQuery: TSelectQuery;
|
|
594
614
|
}
|
|
595
615
|
type QuerySetFor<T extends TQuerySet> = T["IsMapped"] extends true ? MappedQuerySet<T> : QuerySet<T>;
|
|
596
|
-
type
|
|
616
|
+
type THydrationInput<T extends TQuerySet> = T["JoinedQuery"]["O"];
|
|
597
617
|
type TOutput<T extends TQuerySet> = T["HydratedOutput"];
|
|
598
618
|
interface TMapped<in out T extends TQuerySet, in out Output> {
|
|
599
619
|
DB: T["DB"];
|
|
@@ -848,6 +868,37 @@ interface MappedQuerySet<in out T extends TQuerySet> extends k.Compilable, k.Ope
|
|
|
848
868
|
* ```
|
|
849
869
|
*/
|
|
850
870
|
toExistsQuery(): OpaqueExistsQueryBuilder;
|
|
871
|
+
/**
|
|
872
|
+
* Hydrates pre-fetched raw joined rows into nested output objects without
|
|
873
|
+
* executing a query.
|
|
874
|
+
*
|
|
875
|
+
* This is useful when you already have the flat SQL result (e.g. from a
|
|
876
|
+
* separate query, a cache, or a transaction) and want to apply the same
|
|
877
|
+
* hydration logic that `.execute()` uses.
|
|
878
|
+
*
|
|
879
|
+
* **Example - single row:**
|
|
880
|
+
* ```ts
|
|
881
|
+
* const qs = querySet(db)
|
|
882
|
+
* .selectAs("user", db.selectFrom("users").select(["id", "username"]))
|
|
883
|
+
* .leftJoinMany("posts", ...);
|
|
884
|
+
*
|
|
885
|
+
* const row = await qs.toQuery().executeTakeFirstOrThrow();
|
|
886
|
+
* const user = await qs.hydrate(row);
|
|
887
|
+
* ```
|
|
888
|
+
*
|
|
889
|
+
* **Example - multiple rows:**
|
|
890
|
+
* ```ts
|
|
891
|
+
* const rows = await qs.toQuery().execute();
|
|
892
|
+
* const users = await qs.hydrate(rows);
|
|
893
|
+
* ```
|
|
894
|
+
*
|
|
895
|
+
* @param input - A single flat row or an iterable of flat rows matching the
|
|
896
|
+
* joined query output shape.
|
|
897
|
+
* @returns The hydrated output(s).
|
|
898
|
+
*/
|
|
899
|
+
hydrate(input: THydrationInput<T> | Promise<THydrationInput<T>>): Promise<TOutput<T>>;
|
|
900
|
+
hydrate(input: Iterable<THydrationInput<T>> | Promise<Iterable<THydrationInput<T>>>): Promise<TOutput<T>[]>;
|
|
901
|
+
hydrate(input: THydrationInput<T> | Iterable<THydrationInput<T>> | Promise<THydrationInput<T>> | Promise<Iterable<THydrationInput<T>>>): Promise<TOutput<T> | TOutput<T>[]>;
|
|
851
902
|
/**
|
|
852
903
|
* Executes the query and returns an array of hydrated rows.
|
|
853
904
|
*
|
|
@@ -1358,7 +1409,38 @@ interface QuerySet<in out T extends TQuerySet> extends MappedQuerySet<T> {
|
|
|
1358
1409
|
* the field value from the entire row.
|
|
1359
1410
|
* @returns A new HydratedQueryBuilder with the extras applied.
|
|
1360
1411
|
*/
|
|
1361
|
-
extras<E extends Extras<
|
|
1412
|
+
extras<E extends Extras<THydrationInput<T>>>(extras: E): QuerySet<TWithExtendedOutput<T, InferExtras<THydrationInput<T>, E>>>;
|
|
1413
|
+
/**
|
|
1414
|
+
* Adds computed fields to the hydrated output by spreading the return value
|
|
1415
|
+
* of a function. Unlike `.extras()` which defines one field at a time,
|
|
1416
|
+
* `.extend()` calls a single function whose returned object is merged into
|
|
1417
|
+
* the output.
|
|
1418
|
+
*
|
|
1419
|
+
* ### Examples
|
|
1420
|
+
*
|
|
1421
|
+
* ```ts
|
|
1422
|
+
* const users = await querySet(db)
|
|
1423
|
+
* .selectAs("users", (eb) => eb.selectFrom("users").select(["users.id", "users.firstName", "users.lastName"]))
|
|
1424
|
+
* .extend((row) => ({
|
|
1425
|
+
* fullName: `${row.firstName} ${row.lastName}`,
|
|
1426
|
+
* initials: `${row.firstName[0]}${row.lastName[0]}`,
|
|
1427
|
+
* }))
|
|
1428
|
+
* .execute();
|
|
1429
|
+
* // ⬇
|
|
1430
|
+
* type Result = Array<{
|
|
1431
|
+
* id: number;
|
|
1432
|
+
* firstName: string;
|
|
1433
|
+
* lastName: string;
|
|
1434
|
+
* fullName: string;
|
|
1435
|
+
* initials: string;
|
|
1436
|
+
* }>;
|
|
1437
|
+
* ```
|
|
1438
|
+
*
|
|
1439
|
+
* @param fn - A function that receives the row and returns an object of
|
|
1440
|
+
* computed properties.
|
|
1441
|
+
* @returns A new HydratedQueryBuilder with the extender applied.
|
|
1442
|
+
*/
|
|
1443
|
+
extend<F extends Extender<THydrationInput<T>>>(fn: F): QuerySet<TWithExtendedOutput<T, InferExtender<THydrationInput<T>, F>>>;
|
|
1362
1444
|
/**
|
|
1363
1445
|
* Transforms already-selected field values in the hydrated output. Fields
|
|
1364
1446
|
* not mentioned in the mappings will still be included as-is.
|
|
@@ -1380,7 +1462,7 @@ interface QuerySet<in out T extends TQuerySet> extends MappedQuerySet<T> {
|
|
|
1380
1462
|
* functions.
|
|
1381
1463
|
* @returns A new HydratedQueryBuilder with the field transformations applied.
|
|
1382
1464
|
*/
|
|
1383
|
-
mapFields<M extends FieldMappings<
|
|
1465
|
+
mapFields<M extends FieldMappings<THydrationInput<T>>>(mappings: M): QuerySet<TWithExtendedOutput<T, InferFields<THydrationInput<T>, M>>>;
|
|
1384
1466
|
/**
|
|
1385
1467
|
* Omits specified fields from the hydrated output. Useful for excluding
|
|
1386
1468
|
* fields that were selected for internal use (e.g., for extras).
|
|
@@ -1402,7 +1484,7 @@ interface QuerySet<in out T extends TQuerySet> extends MappedQuerySet<T> {
|
|
|
1402
1484
|
* @param keys - Field names to omit from the output.
|
|
1403
1485
|
* @returns A new HydratedQueryBuilder with the fields omitted.
|
|
1404
1486
|
*/
|
|
1405
|
-
omit<K$1 extends keyof
|
|
1487
|
+
omit<K$1 extends keyof THydrationInput<T>>(keys: readonly K$1[]): QuerySet<TWithOmit<T, K$1>>;
|
|
1406
1488
|
/**
|
|
1407
1489
|
* Extends this query builder's hydration configuration with another Hydrator.
|
|
1408
1490
|
* The other Hydrator's configuration takes precedence in case of conflicts.
|
|
@@ -1434,8 +1516,8 @@ interface QuerySet<in out T extends TQuerySet> extends MappedQuerySet<T> {
|
|
|
1434
1516
|
* @param hydrator - The Hydrator to extend with.
|
|
1435
1517
|
* @returns A new HydratedQueryBuilder with merged hydration configuration.
|
|
1436
1518
|
*/
|
|
1437
|
-
with<OtherInput extends StrictSubset<
|
|
1438
|
-
with<OtherInput extends StrictSubset<
|
|
1519
|
+
with<OtherInput extends StrictSubset<THydrationInput<T>, OtherInput>, OtherOutput>(hydrator: FullHydrator<OtherInput, OtherOutput>): QuerySet<TWithExtendedOutput<T, OtherOutput>>;
|
|
1520
|
+
with<OtherInput extends StrictSubset<THydrationInput<T>, OtherInput>, OtherOutput>(hydrator: MappedHydrator<OtherInput, OtherOutput>): QuerySet<TWithExtendedOutput<T, OtherOutput>>;
|
|
1439
1521
|
/**
|
|
1440
1522
|
* Attaches data from an external source (not via SQL joins) as a nested
|
|
1441
1523
|
* array. The `fetchFn` is called exactly once per query execution with all
|
|
@@ -2283,8 +2365,8 @@ interface ModifyCollectionReturnMap<T extends TQuerySet, Key extends string, TNe
|
|
|
2283
2365
|
AttachOneOrThrow: QuerySetWithAttach<T, Key, "AttachOneOrThrow", NewValue>;
|
|
2284
2366
|
AttachMany: QuerySetWithAttach<T, Key, "AttachMany", NewValue>;
|
|
2285
2367
|
}
|
|
2286
|
-
type ToFetchFn<T extends TQuerySet, FetchFnReturn extends SomeFetchFnReturn> = SomeFetchFn<
|
|
2287
|
-
type ToAttachedKeysArg<T extends TQuerySet, FetchFnReturn extends SomeFetchFnReturn> = AttachedKeysArg<
|
|
2368
|
+
type ToFetchFn<T extends TQuerySet, FetchFnReturn extends SomeFetchFnReturn> = SomeFetchFn<THydrationInput<T>, FetchFnReturn>;
|
|
2369
|
+
type ToAttachedKeysArg<T extends TQuerySet, FetchFnReturn extends SomeFetchFnReturn> = AttachedKeysArg<THydrationInput<T>, AttachedOutputFromFetchFnReturn<NoInfer<FetchFnReturn>>>;
|
|
2288
2370
|
interface AttachedOutputMap<in out FetchFnReturn extends SomeFetchFnReturn> {
|
|
2289
2371
|
AttachOne: AttachedOutputFromFetchFnReturn<FetchFnReturn> | null;
|
|
2290
2372
|
AttachOneOrThrow: AttachedOutputFromFetchFnReturn<FetchFnReturn>;
|
|
@@ -2581,7 +2663,7 @@ declare class UnsupportedNodeTypeError extends KyselyHydrateError {
|
|
|
2581
2663
|
constructor(kind: string);
|
|
2582
2664
|
}
|
|
2583
2665
|
/**
|
|
2584
|
-
* Error thrown when
|
|
2666
|
+
* Error thrown when composing a Hydrator with another Hydrator
|
|
2585
2667
|
* that has a different keyBy configuration.
|
|
2586
2668
|
*/
|
|
2587
2669
|
declare class KeyByMismatchError extends KyselyHydrateError {
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as KeyByMismatchError, c as UnexpectedComplexAliasError, d as UnsupportedAliasNodeTypeError, f as UnsupportedNodeTypeError, i as InvalidJoinedQuerySetError, l as UnexpectedSelectAllError, m as WildcardSelectionError, n as CardinalityViolationError, o as KyselyHydrateError, p as UnsupportedTableAliasNodeTypeError, r as ExpectedOneItemError, s as UnexpectedCaseError, t as AmbiguousColumnReferenceError, u as UnexpectedSelectionTypeError } from "./errors-
|
|
1
|
+
import { a as KeyByMismatchError, c as UnexpectedComplexAliasError, d as UnsupportedAliasNodeTypeError, f as UnsupportedNodeTypeError, i as InvalidJoinedQuerySetError, l as UnexpectedSelectAllError, m as WildcardSelectionError, n as CardinalityViolationError, o as KyselyHydrateError, p as UnsupportedTableAliasNodeTypeError, r as ExpectedOneItemError, s as UnexpectedCaseError, t as AmbiguousColumnReferenceError, u as UnexpectedSelectionTypeError } from "./errors-CbAVHTlW.mjs";
|
|
2
2
|
import * as k from "kysely";
|
|
3
3
|
|
|
4
4
|
//#region src/helpers/order-by.ts
|
|
@@ -264,7 +264,13 @@ var HydratorImpl = class HydratorImpl {
|
|
|
264
264
|
extras: addObjectToMap(this.#props.extras, extras)
|
|
265
265
|
});
|
|
266
266
|
}
|
|
267
|
-
extend(
|
|
267
|
+
extend(fn) {
|
|
268
|
+
return new HydratorImpl({
|
|
269
|
+
...this.#props,
|
|
270
|
+
extenders: [...this.#props.extenders ?? [], fn]
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
with(other) {
|
|
268
274
|
const otherImpl = other;
|
|
269
275
|
const thisKeyBy = JSON.stringify(this.#props.keyBy);
|
|
270
276
|
const otherKeyBy = JSON.stringify(otherImpl.#props.keyBy);
|
|
@@ -276,6 +282,7 @@ var HydratorImpl = class HydratorImpl {
|
|
|
276
282
|
keyBy: otherProps.keyBy,
|
|
277
283
|
fields: new Map([...ownProps.fields ?? [], ...otherProps.fields ?? []]),
|
|
278
284
|
extras: new Map([...ownProps.extras ?? [], ...otherProps.extras ?? []]),
|
|
285
|
+
extenders: [...ownProps.extenders ?? [], ...otherProps.extenders ?? []],
|
|
279
286
|
collections: mergedCollections,
|
|
280
287
|
attachedCollections: new Map([...ownProps.attachedCollections ?? [], ...otherProps.attachedCollections ?? []]),
|
|
281
288
|
mapFns: [...this.#props.mapFns ?? [], ...otherProps.mapFns ?? []],
|
|
@@ -412,7 +419,7 @@ var HydratorImpl = class HydratorImpl {
|
|
|
412
419
|
* Hydrates a single entity. All attach collections are already fetched and provided in attachedDataMap.
|
|
413
420
|
*/
|
|
414
421
|
#hydrateOne(ctx, prefix, input, inputRows) {
|
|
415
|
-
const { fields, extras, collections, attachedCollections } = this.#props;
|
|
422
|
+
const { fields, extras, extenders, collections, attachedCollections } = this.#props;
|
|
416
423
|
const entity = {};
|
|
417
424
|
if (ctx.autoIncludeFields) for (const key of this.#getAutoFields(ctx, prefix, input)) entity[key] = getPrefixedValue(prefix, input, key);
|
|
418
425
|
if (fields) for (const [key, field] of fields) {
|
|
@@ -420,9 +427,10 @@ var HydratorImpl = class HydratorImpl {
|
|
|
420
427
|
const value = getPrefixedValue(prefix, input, key);
|
|
421
428
|
entity[key] = field === true ? value : field(value);
|
|
422
429
|
}
|
|
423
|
-
if (extras) {
|
|
430
|
+
if (extras || extenders) {
|
|
424
431
|
const accessor = createdPrefixedAccessor(prefix, input);
|
|
425
|
-
for (const [key, extra] of extras) entity[key] = extra(accessor);
|
|
432
|
+
if (extras) for (const [key, extra] of extras) entity[key] = extra(accessor);
|
|
433
|
+
if (extenders) for (const extender of extenders) Object.assign(entity, extender(accessor));
|
|
426
434
|
}
|
|
427
435
|
if (collections) {
|
|
428
436
|
const childCtx = this.#props.hasMultipleManyCollections && !ctx.hasSiblingManyCollections ? {
|
|
@@ -848,13 +856,16 @@ var QuerySetImpl = class QuerySetImpl {
|
|
|
848
856
|
toOperationNode() {
|
|
849
857
|
return this.toQuery().toOperationNode();
|
|
850
858
|
}
|
|
851
|
-
async
|
|
852
|
-
|
|
853
|
-
return this.#props.hydrator.hydrate(rows, {
|
|
859
|
+
async hydrate(input) {
|
|
860
|
+
return this.#props.hydrator.hydrate(await input, {
|
|
854
861
|
[EnableAutoInclusion]: true,
|
|
855
862
|
sort: "nested"
|
|
856
863
|
});
|
|
857
864
|
}
|
|
865
|
+
async execute() {
|
|
866
|
+
const rows = await this.toQuery().execute();
|
|
867
|
+
return this.hydrate(rows);
|
|
868
|
+
}
|
|
858
869
|
async executeTakeFirst() {
|
|
859
870
|
const [result] = await this.execute();
|
|
860
871
|
return result;
|
|
@@ -878,6 +889,9 @@ var QuerySetImpl = class QuerySetImpl {
|
|
|
878
889
|
extras(extras) {
|
|
879
890
|
return this.#clone({ hydrator: asFullHydrator(this.#props.hydrator).extras(extras) });
|
|
880
891
|
}
|
|
892
|
+
extend(fn) {
|
|
893
|
+
return this.#clone({ hydrator: asFullHydrator(this.#props.hydrator).extend(fn) });
|
|
894
|
+
}
|
|
881
895
|
mapFields(mappings) {
|
|
882
896
|
return this.#clone({ hydrator: asFullHydrator(this.#props.hydrator).fields(mappings) });
|
|
883
897
|
}
|
|
@@ -885,7 +899,7 @@ var QuerySetImpl = class QuerySetImpl {
|
|
|
885
899
|
return this.#clone({ hydrator: asFullHydrator(this.#props.hydrator).omit(keys) });
|
|
886
900
|
}
|
|
887
901
|
with(hydrator) {
|
|
888
|
-
return this.#clone({ hydrator: asFullHydrator(this.#props.hydrator).
|
|
902
|
+
return this.#clone({ hydrator: asFullHydrator(this.#props.hydrator).with(hydrator) });
|
|
889
903
|
}
|
|
890
904
|
#addAttach(mode, key, fetchFn, keys) {
|
|
891
905
|
return this.#clone({ hydrator: asFullHydrator(this.#props.hydrator).attach(mode, key, fetchFn, keys) });
|