kysely-rizzolver 0.0.2 → 0.0.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 (78) hide show
  1. package/README.md +14 -10
  2. package/dist/cjs/fetch-result-factory.js +1 -0
  3. package/dist/cjs/fetch-result-factory.js.map +1 -0
  4. package/dist/cjs/fetch-result.d.ts +11 -8
  5. package/dist/cjs/fetch-result.js +5 -0
  6. package/dist/cjs/fetch-result.js.map +1 -0
  7. package/dist/cjs/fk-gather-result-factory.d.ts +69 -0
  8. package/dist/cjs/fk-gather-result-factory.js +111 -0
  9. package/dist/cjs/fk-gather-result-factory.js.map +1 -0
  10. package/dist/cjs/fk-gather-result.d.ts +115 -0
  11. package/dist/cjs/fk-gather-result.js +127 -0
  12. package/dist/cjs/fk-gather-result.js.map +1 -0
  13. package/dist/cjs/fks.d.ts +111 -0
  14. package/dist/cjs/fks.js +101 -0
  15. package/dist/cjs/fks.js.map +1 -0
  16. package/dist/cjs/index.d.ts +10 -4
  17. package/dist/cjs/index.js +17 -1
  18. package/dist/cjs/index.js.map +1 -0
  19. package/dist/cjs/kysely-rizzolver-builder.d.ts +17 -0
  20. package/dist/cjs/kysely-rizzolver-builder.js +23 -0
  21. package/dist/cjs/kysely-rizzolver-builder.js.map +1 -0
  22. package/dist/cjs/kysely-rizzolver-fk-builder.d.ts +20 -0
  23. package/dist/cjs/kysely-rizzolver-fk-builder.js +23 -0
  24. package/dist/cjs/kysely-rizzolver-fk-builder.js.map +1 -0
  25. package/dist/cjs/kysely-rizzolver.d.ts +64 -85
  26. package/dist/cjs/kysely-rizzolver.js +47 -90
  27. package/dist/cjs/kysely-rizzolver.js.map +1 -0
  28. package/dist/cjs/model-collection.d.ts +5 -1
  29. package/dist/cjs/model-collection.js +24 -2
  30. package/dist/cjs/model-collection.js.map +1 -0
  31. package/dist/cjs/query-builder.d.ts +14 -12
  32. package/dist/cjs/query-builder.js +10 -4
  33. package/dist/cjs/query-builder.js.map +1 -0
  34. package/dist/cjs/selector.d.ts +71 -7
  35. package/dist/cjs/selector.js +2 -1
  36. package/dist/cjs/selector.js.map +1 -0
  37. package/dist/cjs/type-helpers.d.ts +20 -0
  38. package/dist/cjs/type-helpers.js +1 -0
  39. package/dist/cjs/type-helpers.js.map +1 -0
  40. package/dist/esm/fetch-result-factory.js +1 -0
  41. package/dist/esm/fetch-result-factory.js.map +1 -0
  42. package/dist/esm/fetch-result.js +5 -0
  43. package/dist/esm/fetch-result.js.map +1 -0
  44. package/dist/esm/fk-gather-result-factory.js +108 -0
  45. package/dist/esm/fk-gather-result-factory.js.map +1 -0
  46. package/dist/esm/fk-gather-result.js +115 -0
  47. package/dist/esm/fk-gather-result.js.map +1 -0
  48. package/dist/esm/fks.js +96 -0
  49. package/dist/esm/fks.js.map +1 -0
  50. package/dist/esm/index.js +4 -1
  51. package/dist/esm/index.js.map +1 -0
  52. package/dist/esm/kysely-rizzolver-builder.js +20 -0
  53. package/dist/esm/kysely-rizzolver-builder.js.map +1 -0
  54. package/dist/esm/kysely-rizzolver-fk-builder.js +20 -0
  55. package/dist/esm/kysely-rizzolver-fk-builder.js.map +1 -0
  56. package/dist/esm/kysely-rizzolver.js +47 -90
  57. package/dist/esm/kysely-rizzolver.js.map +1 -0
  58. package/dist/esm/model-collection.js +24 -2
  59. package/dist/esm/model-collection.js.map +1 -0
  60. package/dist/esm/query-builder.js +10 -4
  61. package/dist/esm/query-builder.js.map +1 -0
  62. package/dist/esm/selector.js +2 -1
  63. package/dist/esm/selector.js.map +1 -0
  64. package/dist/esm/type-helpers.js +1 -0
  65. package/dist/esm/type-helpers.js.map +1 -0
  66. package/dist/types/fetch-result.d.ts +11 -8
  67. package/dist/types/fk-gather-result-factory.d.ts +69 -0
  68. package/dist/types/fk-gather-result.d.ts +115 -0
  69. package/dist/types/fks.d.ts +111 -0
  70. package/dist/types/index.d.ts +10 -4
  71. package/dist/types/kysely-rizzolver-builder.d.ts +17 -0
  72. package/dist/types/kysely-rizzolver-fk-builder.d.ts +20 -0
  73. package/dist/types/kysely-rizzolver.d.ts +64 -85
  74. package/dist/types/model-collection.d.ts +5 -1
  75. package/dist/types/query-builder.d.ts +14 -12
  76. package/dist/types/selector.d.ts +71 -7
  77. package/dist/types/type-helpers.d.ts +20 -0
  78. package/package.json +1 -1
@@ -1,10 +1,17 @@
1
+ import type { Kysely } from 'kysely';
1
2
  import { type FetchResultFactory } from './fetch-result-factory.js';
3
+ import { FkGatherResultFactory } from './fk-gather-result-factory.js';
4
+ import { DBWithFk, GatherOpts, GatherWhereExpression, MAX_FK_GATHER_DEPTH, NoNullGatherOpts, ValidFkDepth } from './fks.js';
5
+ import { type ModelCollection } from './model-collection.js';
2
6
  import { type QueryBuilder } from './query-builder.js';
3
7
  import { type Selector } from './selector.js';
4
- import { type ModelCollection } from './model-collection.js';
5
- export interface KyselyRizzolverBase<DB, T extends Record<keyof DB & string, readonly string[]>> {
6
- readonly fields: T;
7
- readonly fetches: FetchResultFactory<DB>;
8
+ import { WithMandatory } from './type-helpers.js';
9
+ export interface KyselyRizzolverBase<DB, T extends Record<keyof DB & string, readonly string[]>, FKDefs extends KyselyRizzolverFKs<DB>> {
10
+ readonly _types: Readonly<{
11
+ fields: T;
12
+ fkDefs: FKDefs;
13
+ dbfk: DBWithFk<DB, FKDefs>;
14
+ }>;
8
15
  }
9
16
  /**
10
17
  * A {@link KyselyRizzolver} is a class that is used to define the structure of
@@ -17,14 +24,16 @@ export interface KyselyRizzolverBase<DB, T extends Record<keyof DB & string, rea
17
24
  * {@link KyselyRizzolver.builder|.builderForSchema()} or
18
25
  * {@link KyselyRizzolver.builderNoSchema|.builderNoSchema()}.
19
26
  */
20
- export declare class KyselyRizzolver<DB, T extends Record<keyof DB & string, readonly string[]>> implements KyselyRizzolverBase<DB, T> {
21
- readonly fields: T;
22
- readonly fetches: FetchResultFactory<DB>;
23
- constructor(fields: T);
27
+ export declare class KyselyRizzolver<DB, T extends Record<keyof DB & string, readonly string[]>, FKDefs extends KyselyRizzolverFKs<DB>, DefaultGatherDepth extends ValidFkDepth = typeof MAX_FK_GATHER_DEPTH> implements KyselyRizzolverBase<DB, T, FKDefs> {
28
+ readonly _types: KyselyRizzolverBase<DB, T, FKDefs>['_types'];
29
+ readonly fetchObjs: FetchResultFactory<DB>;
30
+ readonly gatherObjs: FkGatherResultFactory<DB, FKDefs>;
31
+ readonly defaultGatherDepth: DefaultGatherDepth;
32
+ constructor(fields: T, fks: FKDefs, defaultGatherDepth?: DefaultGatherDepth);
24
33
  /**
25
34
  * Intantiates a new {@link Selector} for the given table.
26
35
  */
27
- newSelector<Table extends keyof DB & string, Alias extends string>(table: Table, alias: Alias): Selector<this, Table, Alias, AllTableFields<this, Table>>;
36
+ newSelector<Table extends keyof DB & string, Alias extends string>(table: Table, alias: Alias): Selector<this, Table, Alias, KyAllTableFields<this, Table>>;
28
37
  /**
29
38
  * Instantiates a new {@link QueryBuilder}.
30
39
  */
@@ -33,19 +42,25 @@ export declare class KyselyRizzolver<DB, T extends Record<keyof DB & string, rea
33
42
  * Instantiates a new {@link ModelCollection}.
34
43
  */
35
44
  newModelCollection(): ModelCollection<DB>;
45
+ gatherOne<Table extends keyof DB & string, Opts extends WithMandatory<GatherOpts<DB, ValidFkDepth>, 'depth'>>(db: Kysely<DB>, table: Table, where: GatherWhereExpression<DB, Table>, opts: Opts): Promise<ReturnType<typeof this.gatherObjs.newGatherOne<Table, Opts['depth']>>>;
46
+ gatherOne<Table extends keyof DB & string>(db: Kysely<DB>, table: Table, where: GatherWhereExpression<DB, Table>, opts?: Omit<GatherOpts<DB, any>, 'depth'>): Promise<ReturnType<typeof this.gatherObjs.newGatherOne<Table, DefaultGatherDepth>>>;
47
+ gatherOneX<Table extends keyof DB & string, Opts extends WithMandatory<GatherOpts<DB, ValidFkDepth>, 'depth'>>(db: Kysely<DB>, table: Table, where: GatherWhereExpression<DB, Table>, opts: Opts): Promise<ReturnType<typeof this.gatherObjs.newGatherOneX<Table, Opts['depth']>>>;
48
+ gatherOneX<Table extends keyof DB & string>(db: Kysely<DB>, table: Table, where: GatherWhereExpression<DB, Table>, opts?: Omit<GatherOpts<DB, any>, 'depth'>): Promise<ReturnType<typeof this.gatherObjs.newGatherOneX<Table, DefaultGatherDepth>>>;
49
+ gatherSome<Table extends keyof DB & string, Opts extends WithMandatory<NoNullGatherOpts<DB, ValidFkDepth>, 'depth'>>(db: Kysely<DB>, table: Table, where: GatherWhereExpression<DB, Table>, opts: Opts): Promise<ReturnType<typeof this.gatherObjs.newGatherSome<Table, Opts['depth']>>>;
50
+ gatherSome<Table extends keyof DB & string>(db: Kysely<DB>, table: Table, where: GatherWhereExpression<DB, Table>, opts?: Omit<NoNullGatherOpts<DB, any>, 'depth'>): Promise<ReturnType<typeof this.gatherObjs.newGatherSome<Table, DefaultGatherDepth>>>;
36
51
  /**
37
52
  * Starts building a new {@link KyselyRizzolver} using a builder pattern for
38
53
  * a schema.
39
54
  *
40
- * Call {@link KyselyRizzolverBuilderForSchema.table|.table()} for each
55
+ * Call {@link KyselyRizzolverBuilder.table|.table()} for each
41
56
  * table that exists on the `DB` type parameter with all of their column
42
57
  * names as a const array. After all tables have been added, call
43
- * {@link KyselyRizzolverBuilderForSchema.build|.build()} to get a new
58
+ * {@link KyselyRizzolverBuilder.build|.build()} to get a new
44
59
  * {@link KyselyRizzolver} instance.
45
60
  *
46
61
  * Example:
47
62
  * ```
48
- * const rizzolver = KyselyRizzolver.builderForSchema<DB>()
63
+ * const rizzolver = KyselyRizzolver.builder<DB>()
49
64
  * .table('user', ['id', 'name', 'email'] as const)
50
65
  * .table('post', ['id', 'title', 'content', 'authorId'] as const)
51
66
  * .build();
@@ -53,86 +68,50 @@ export declare class KyselyRizzolver<DB, T extends Record<keyof DB & string, rea
53
68
  *
54
69
  * Note: The `as const` assertion is necessary for correct type inference.
55
70
  */
56
- static builderForSchema<DB>(): KyselyRizzolverBuilderForSchema<DB, {}>;
57
- /**
58
- * Starts building a new {@link KyselyRizzolver} using a builder pattern
59
- * without a schema.
60
- *
61
- * Call {@link KyselyRizzolverBuilderNoSchema.table|.table()} for each
62
- * table with all of their column names as a const array.
63
- *
64
- * Example:
65
- * ```
66
- * const rizzolver = KyselyRizzolver.builder()
67
- * .table('user', ['id', 'name', 'email'] as const) // note `as const` is necessary
68
- * .table('post', ['id', 'title', 'content', 'authorId'] as const)
69
- * .build();
70
- * ```
71
- *
72
- * Since this version of builder is schemaless, it cannot infer the value
73
- * types for the columns. The `user` type will be `{ id: unknown, name:
74
- * unknown, email: unknown }`.
75
- *
76
- * You may call
77
- * {@link KyselyRizzolverBuilderNoSchema.asModel|.asModel\<M\>()}
78
- * immediately after the .table() call to provide the types, where `M` is an
79
- * type like `{ column1: type1, column2: type2, ... }`.
80
- *
81
- * Example:
82
- * ```
83
- * const rizzolver = KyselyRizzolver.builder()
84
- * .table('user', ['id', 'name', 'email'] as const)
85
- * .asModel<{id: number, name: string, email: string}>()
86
- * .table('post', ['id', 'title', 'content', 'authorId'] as const)
87
- * .asModel<{id: number, title: string, content: string, authorId: number}>()
88
- * .build();
89
- * ```
90
- *
91
- * p.s. if your .table() and .asModel() columns differ, it will let you know
92
- * at compile time ;)
93
- *
94
- * Once all tables have been added, call
95
- * {@link KyselyRizzolverBuilderNoSchema.build|.build()} to get a new
96
- * {@link KyselyRizzolver} instance.
97
- */
98
- static builderNoSchema(): KyselyRizzolverBuilderNoSchema<{}, null>;
71
+ static builder<DB>(): import("./kysely-rizzolver-builder.js").KyselyRizzolverBuilder<DB, {}, 3>;
99
72
  }
100
- export type KyselyRizzolverBuilderForSchema<DB, T extends Partial<Record<keyof DB & string, readonly string[]>>> = {
101
- table<K extends Exclude<keyof DB & string, keyof T>, U extends readonly (keyof DB[K])[]>(name: K, fields: U & ([keyof DB[K]] extends [U[number]] ? unknown : `Missing key: ${Exclude<keyof DB[K] & string, U[number]>}`)): KyselyRizzolverBuilderForSchema<DB, T & {
102
- [key in K]: U;
103
- }>;
104
- build(): T extends Record<keyof DB & string, readonly string[]> ? KyselyRizzolver<DB, T> : never;
105
- };
106
- export type KyselyRizzolverBuilderNoSchema<T extends Record<string, {
107
- model: any;
108
- columns: readonly string[];
109
- }>, Last extends keyof T | null> = {
110
- table<K extends string, U extends readonly string[]>(name: K, fields: U): KyselyRizzolverBuilderNoSchema<T & {
111
- [k in K]: {
112
- model: Record<U[number], unknown>;
113
- columns: U;
114
- };
115
- }, K>;
116
- asModel<M>(): Last extends keyof T ? keyof M extends T[Last]['columns'][number] ? T[Last]['columns'][number] extends keyof M ? KyselyRizzolverBuilderNoSchema<T & {
117
- [k in Last]: {
118
- model: M;
119
- columns: T[k]['columns'];
73
+ /**
74
+ * The shape of the foreign key definitions on a {@link KyselyRizzolverBase}.
75
+ */
76
+ export type KyselyRizzolverFKs<DB> = {
77
+ [table in keyof DB & string]?: {
78
+ [fkName: string]: {
79
+ myField: string;
80
+ otherTable: keyof DB & string;
81
+ otherField: string;
82
+ isNullable: boolean;
120
83
  };
121
- }, never> : `column '${Exclude<T[Last]['columns'][number], keyof M & string>}' defined in table() but missing from asModel()` : `column '${Exclude<keyof M & string, T[Last]['columns'][number]>}' defined in asModel() but missing from table()` : `asModel() must be called after table()`;
122
- build(): KyselyRizzolver<{
123
- [k in keyof T]: T[k]['model'];
124
- }, {
125
- [k in keyof T]: T[k]['columns'];
126
- }>;
84
+ };
127
85
  };
128
- export type KyDB<KY extends KyselyRizzolverBase<any, any>> = KY extends KyselyRizzolverBase<infer DB, any> ? DB : never;
129
- export type TableName<T extends KyselyRizzolverBase<any, any>> = keyof KyDB<T> & string;
86
+ /**
87
+ * Extracts the `DB` type from a {@link KyselyRizzolverBase}.
88
+ */
89
+ export type KyDB<KY extends KyselyRizzolverBase<any, any, any>> = KY extends KyselyRizzolverBase<infer DB, any, any> ? DB : never;
90
+ /**
91
+ * Variant of {@link TableName} that takes a {@link KyselyRizzolverBase} instead
92
+ * of a `DB` type.
93
+ */
94
+ export type KyTableName<T extends KyselyRizzolverBase<any, any, any>> = keyof KyDB<T> & string;
95
+ /**
96
+ * Variant of {@link AnyTableField} that takes a {@link KyselyRizzolverBase}
97
+ * instead of a `DB` type.
98
+ */
99
+ export type KyAnyTableField<KY extends KyselyRizzolverBase<any, any, any>, Table extends KyTableName<KY>> = keyof KyDB<KY>[Table] & string;
100
+ /**
101
+ * Variant of {@link AllTableFields} that takes a {@link KyselyRizzolverBase}
102
+ * instead of a `DB` type.
103
+ */
104
+ export type KyAllTableFields<KY extends KyselyRizzolverBase<any, any, any>, Table extends KyTableName<KY>> = KY extends KyselyRizzolverBase<any, infer T, any> ? T[Table] extends infer U ? U extends readonly KyAnyTableField<KY, Table>[] ? U : never : never : never;
105
+ /**
106
+ * A union of all the known table names of a database.
107
+ */
108
+ export type TableName<DB> = keyof DB & string;
130
109
  /**
131
110
  * A union of all the known fields of a table.
132
111
  */
133
- export type AnyTableField<KY extends KyselyRizzolverBase<any, any>, Table extends TableName<KY>> = keyof KyDB<KY>[Table] & string;
112
+ export type AnyTableField<DB, Table extends TableName<DB>> = keyof DB[Table] & string;
134
113
  /**
135
114
  * An array of all the known fields of a table, in a type that is compatible
136
115
  * with that table's ${@link Selectable} type.
137
116
  */
138
- export type AllTableFields<KY extends KyselyRizzolverBase<any, any>, Table extends TableName<KY>> = KY extends KyselyRizzolverBase<any, infer T> ? T[Table] extends infer U ? U extends readonly AnyTableField<KY, Table>[] ? U : never : never : never;
117
+ export type AllTableFields<DB, Table extends TableName<DB>> = AnyTableField<DB, Table>[];
@@ -17,7 +17,11 @@ import type { Selectable } from 'kysely';
17
17
  */
18
18
  export type ModelCollection<DB> = {
19
19
  add<Table extends keyof DB & string>(table: Table, selectable?: Selectable<DB[Table]>): ModelCollection<DB>;
20
- get collection(): Data<DB>;
20
+ addCollection(collection: ModelCollection<DB>): ModelCollection<DB>;
21
+ get(): Data<DB>;
22
+ get<Table extends keyof DB & string>(table: Table): Record<number, Selectable<DB[Table]>>;
23
+ get<Table extends keyof DB & string>(table: Table, id: number): Selectable<DB[Table]> | undefined;
24
+ getX<Table extends keyof DB & string>(table: Table, id: number): Record<number, Selectable<DB[Table]>>;
21
25
  };
22
26
  export declare function newModelCollection<DB>(init?: Data<DB>): ModelCollection<DB>;
23
27
  type Data<DB> = {
@@ -1,6 +1,6 @@
1
1
  import { type FetchOneResult, type FetchOneXResult, type FetchSomeResult } from './fetch-result.js';
2
- import type { AllTableFields, AnyTableField, KyDB, KyselyRizzolverBase, TableName } from './kysely-rizzolver.js';
3
- import { type Selector, type SelectorResult } from './selector.js';
2
+ import type { KyAllTableFields, KyAnyTableField, KyDB, KyselyRizzolverBase, KyTableName } from './kysely-rizzolver.js';
3
+ import { type Selector, type SelectorResult, AnySelector } from './selector.js';
4
4
  import { type ModelCollection } from './model-collection.js';
5
5
  import type { UnionToTuple } from './type-helpers.js';
6
6
  /**
@@ -12,11 +12,12 @@ import type { UnionToTuple } from './type-helpers.js';
12
12
  * method, followed by a call to {@link QueryBuilder.run} to parse the results
13
13
  * of the query using a simple builder pattern.
14
14
  */
15
- export interface QueryBuilder<KY extends KyselyRizzolverBase<any, any>, T extends Data<KY>> {
15
+ export interface QueryBuilder<KY extends KyselyRizzolverBase<any, any, any>, T extends Data<KY>> {
16
16
  /**
17
17
  * The record of {@link Selector} this query builder has, keyed by their alias.
18
18
  */
19
19
  selectors: T;
20
+ numSelectors: UnionToTuple<keyof T>['length'];
20
21
  /**
21
22
  * Given a {@link Selector} alias `k`, Gets a `"table as alias"` expression
22
23
  * for that selector.
@@ -37,7 +38,7 @@ export interface QueryBuilder<KY extends KyselyRizzolverBase<any, any>, T extend
37
38
  * Gets a const array of all the fields of all the {@link Selector}s this
38
39
  * query builder has. The order is arbitrary and should not be relied upon.
39
40
  */
40
- allFields: FieldsOf<T, keyof T>;
41
+ allFields(): FieldsOf<T, keyof T>;
41
42
  /**
42
43
  * Given one of more {@link Selector} aliases, gets an array of
43
44
  * `"table.field as alias"` expressions for all of their fields.
@@ -66,11 +67,11 @@ export interface QueryBuilder<KY extends KyselyRizzolverBase<any, any>, T extend
66
67
  /**
67
68
  * Adds a new {@link Selector} to the query builder.
68
69
  */
69
- add<Table extends TableName<KY>, Alias extends string, Keys extends readonly AnyTableField<KY, Table>[] = AllTableFields<KY, Table>>(selector: Selector<KY, Table, Alias, Keys>): MoreData<KY, T, Table, Alias, Keys>;
70
+ add<Table extends KyTableName<KY>, Alias extends string, Keys extends readonly KyAnyTableField<KY, Table>[] = KyAllTableFields<KY, Table>>(selector: Selector<KY, Table, Alias, Keys>): MoreData<KY, T, Table, Alias, Keys>;
70
71
  /**
71
72
  * Adds a new {@link Selector} to the query builder.
72
73
  */
73
- add<Table extends TableName<KY>, Alias extends string, Keys extends readonly AnyTableField<KY, Table>[] = AllTableFields<KY, Table>>(table: Table, alias: Alias, keys?: Keys): MoreData<KY, T, Table, Alias, Keys>;
74
+ add<Table extends KyTableName<KY>, Alias extends string, Keys extends readonly KyAnyTableField<KY, Table>[] = KyAllTableFields<KY, Table>>(table: Table, alias: Alias, keys?: Keys): MoreData<KY, T, Table, Alias, Keys>;
74
75
  /**
75
76
  * Parses the results of a query into the {@link Selectable} instances
76
77
  * defined by the {@link Selector}s this query builder has.
@@ -85,7 +86,7 @@ export interface QueryBuilder<KY extends KyselyRizzolverBase<any, any>, T extend
85
86
  * db
86
87
  * .selectFrom(qb.table('u'))
87
88
  * .leftJoin(qb.table('a'), (join) => join.onRef('u.address_id', '=', 'a.id'))
88
- * .select(qb.allFields)
89
+ * .select(qb.allFields())
89
90
  * .execute()
90
91
  * );
91
92
  *
@@ -122,19 +123,20 @@ export interface QueryBuilder<KY extends KyselyRizzolverBase<any, any>, T extend
122
123
  run<Row extends Record<string, unknown>>(rows: Row[]): DeferredResult<KY, T, Row>;
123
124
  run<Row extends Record<string, unknown>>(callback: (qb: this) => Promise<Row[]>): DeferredResult<KY, T, Row>;
124
125
  }
125
- export declare function newQueryBuilder<KY extends KyselyRizzolverBase<any, any>>(rizzolver: KY): QueryBuilder<KY, {}>;
126
- type Data<KY extends KyselyRizzolverBase<any, any>> = {
126
+ export type AnyQueryBuilder = QueryBuilder<KyselyRizzolverBase<any, any, any>, Record<string, AnySelector<any, string, string, string[]>>>;
127
+ export declare function newQueryBuilder<KY extends KyselyRizzolverBase<any, any, any>>(rizzolver: KY): QueryBuilder<KY, {}>;
128
+ type Data<KY extends KyselyRizzolverBase<any, any, any>> = {
127
129
  [alias: string]: Selector<KY, any, string, any>;
128
130
  };
129
- type MoreData<KY extends KyselyRizzolverBase<any, any>, T extends Data<KY>, Table extends TableName<KY>, A extends string, K extends readonly AnyTableField<KY, Table>[] = AllTableFields<KY, Table>> = QueryBuilder<KY, T & {
131
+ type MoreData<KY extends KyselyRizzolverBase<any, any, any>, T extends Data<KY>, Table extends KyTableName<KY>, A extends string, K extends readonly KyAnyTableField<KY, Table>[] = KyAllTableFields<KY, Table>> = QueryBuilder<KY, T & {
130
132
  [k in A]: Selector<KY, Table, A, K>;
131
133
  }>;
132
- interface DeferredResult<KY extends KyselyRizzolverBase<any, any>, T extends Data<KY>, Row extends Record<string, unknown>> extends Promise<Result<KY, T, Row>> {
134
+ interface DeferredResult<KY extends KyselyRizzolverBase<any, any, any>, T extends Data<KY>, Row extends Record<string, unknown>> extends Promise<Result<KY, T, Row>> {
133
135
  newFetchOneResult<K extends keyof T>(selectorAlias: K): Promise<FetchOneResult<KyDB<KY>, T[K]['input']['table'], SelectorResult<KY, any, T[K]['input']['table'], T[K]['input']['tableFields']>[number]['model'] & {}>>;
134
136
  newFetchOneXResult<K extends keyof T>(selectorAlias: K): Promise<FetchOneXResult<KyDB<KY>, T[K]['input']['table'], SelectorResult<KY, any, T[K]['input']['table'], T[K]['input']['tableFields']>[number]['model'] & {}>>;
135
137
  newFetchSomeResult<K extends keyof T>(selectorAlias: K): Promise<FetchSomeResult<KyDB<KY>, T[K]['input']['table'], SelectorResult<KY, any, T[K]['input']['table'], T[K]['input']['tableFields']>[number]['model'] & {}>>;
136
138
  }
137
- type Result<KY extends KyselyRizzolverBase<any, any>, T extends Data<KY>, Row extends Record<string, unknown>> = {
139
+ type Result<KY extends KyselyRizzolverBase<any, any, any>, T extends Data<KY>, Row extends Record<string, unknown>> = {
138
140
  first: {
139
141
  row: Row;
140
142
  selectors: {
@@ -1,5 +1,5 @@
1
1
  import type { Selectable } from 'kysely';
2
- import type { AllTableFields, AnyTableField, KyDB, KyselyRizzolverBase, TableName } from './kysely-rizzolver.js';
2
+ import type { AllTableFields, AnyTableField, KyAllTableFields, KyAnyTableField, KyDB, KyselyRizzolverBase, KyTableName, TableName } from './kysely-rizzolver.js';
3
3
  /**
4
4
  * A {@link Selector} makes it easier to build select expressions for a
5
5
  * table in a type-safe way. It can process the results of queries into
@@ -8,7 +8,7 @@ import type { AllTableFields, AnyTableField, KyDB, KyselyRizzolverBase, TableNam
8
8
  * {@link Selector} is a low level utility that is used by
9
9
  * {@link QueryBuilder} to work with multiple selectors.
10
10
  */
11
- export type Selector<KY extends KyselyRizzolverBase<any, any>, Table extends TableName<KY>, Alias extends string, TableFields extends readonly AnyTableField<KY, Table>[] = AllTableFields<KY, Table>> = {
11
+ export type AnySelector<DB, Table extends TableName<DB>, Alias extends string, TableFields extends AnyTableField<DB, Table>[] = AllTableFields<DB, Table>> = {
12
12
  input: {
13
13
  /**
14
14
  * The table name that's being selected from.
@@ -29,7 +29,66 @@ export type Selector<KY extends KyselyRizzolverBase<any, any>, Table extends Tab
29
29
  /**
30
30
  * A `"table as alias"` expression for using in select expressions.
31
31
  */
32
- selectTable: TableAlias<KY, Table, Alias>;
32
+ selectTable: TableAlias<DB, Table, Alias>;
33
+ /**
34
+ * An array of `"table.field as alias"` expressions for using in select expressions.
35
+ */
36
+ selectFields: FieldsAsAliases<Alias, TableFields>;
37
+ /**
38
+ * A utility method that allows you to reference a specific field.
39
+ */
40
+ field<Field extends TableFields[number]>(field: Field): {
41
+ str: `_${Alias}_${Field}`;
42
+ /**
43
+ * A utility method that allows you to reference the field from a different table alias.
44
+ *
45
+ * This is useful if you need to reference the field from a subquery for example.
46
+ */
47
+ from<A extends string>(alias: A): `${A}.${FieldAlias<Alias, Field>}`;
48
+ };
49
+ /**
50
+ * Parses the results of a query into the model defined by this selector for each row.
51
+ *
52
+ * Example:
53
+ * ```
54
+ * const selector = newSelector('user', 'u');
55
+ * const data = await db.selectFrom(selector.tableAlias).selectAll().execute();
56
+ * const parsed = selector.select(data);
57
+ * // => type would be { row: Row, model: Selectable<User> | undefined }[]
58
+ * ```
59
+ */
60
+ select<Row extends Record<string, unknown>>(rows: Row[]): AnySelectorResult<DB, Row, Table, TableFields>;
61
+ };
62
+ /**
63
+ * A {@link Selector} makes it easier to build select expressions for a
64
+ * table in a type-safe way. It can process the results of queries into
65
+ * Kysely's {@link Selectable} instances.
66
+ *
67
+ * {@link Selector} is a low level utility that is used by
68
+ * {@link QueryBuilder} to work with multiple selectors.
69
+ */
70
+ export type Selector<KY extends KyselyRizzolverBase<any, any, any>, Table extends KyTableName<KY>, Alias extends string, TableFields extends readonly KyAnyTableField<KY, Table>[] = KyAllTableFields<KY, Table>> = {
71
+ input: {
72
+ /**
73
+ * The table name that's being selected from.
74
+ */
75
+ table: Table;
76
+ /**
77
+ * The alias for the table.
78
+ */
79
+ alias: Alias;
80
+ /**
81
+ * An array of the fields to be selected from the table.
82
+ *
83
+ * This can be omitted, in which case it will default to all the fields of
84
+ * the table.
85
+ */
86
+ tableFields: TableFields;
87
+ };
88
+ /**
89
+ * A `"table as alias"` expression for using in select expressions.
90
+ */
91
+ selectTable: KyTableAlias<KY, Table, Alias>;
33
92
  /**
34
93
  * An array of `"table.field as alias"` expressions for using in select expressions.
35
94
  */
@@ -59,13 +118,18 @@ export type Selector<KY extends KyselyRizzolverBase<any, any>, Table extends Tab
59
118
  */
60
119
  select<Row extends Record<string, unknown>>(rows: Row[]): SelectorResult<KY, Row, Table, TableFields>;
61
120
  };
62
- export declare function newSelector<KY extends KyselyRizzolverBase<any, any>, Table extends TableName<KY>, Alias extends string>(rizzolver: KY, tableName: Table, alias: Alias): Selector<KY, Table, Alias, AllTableFields<KY, Table>>;
63
- export declare function newSelector<KY extends KyselyRizzolverBase<any, any>, Table extends TableName<KY>, Alias extends string, Keys extends readonly AnyTableField<KY, Table>[]>(rizzolver: KY, tableName: Table, alias: Alias, keys?: Keys): Selector<KY, Table, Alias, Keys>;
64
- export type SelectorResult<KY extends KyselyRizzolverBase<any, any>, Row extends Record<string, unknown>, Table extends TableName<KY>, TableFields extends readonly AnyTableField<KY, Table>[] = AllTableFields<KY, Table>> = {
121
+ export declare function newSelector<KY extends KyselyRizzolverBase<any, any, any>, Table extends KyTableName<KY>, Alias extends string>(rizzolver: KY, tableName: Table, alias: Alias): Selector<KY, Table, Alias, KyAllTableFields<KY, Table>>;
122
+ export declare function newSelector<KY extends KyselyRizzolverBase<any, any, any>, Table extends KyTableName<KY>, Alias extends string, Keys extends readonly KyAnyTableField<KY, Table>[]>(rizzolver: KY, tableName: Table, alias: Alias, keys?: Keys): Selector<KY, Table, Alias, Keys>;
123
+ export type SelectorResult<KY extends KyselyRizzolverBase<any, any, any>, Row extends Record<string, unknown>, Table extends KyTableName<KY>, TableFields extends readonly KyAnyTableField<KY, Table>[] = KyAllTableFields<KY, Table>> = {
65
124
  row: Row;
66
125
  model: Selectable<Pick<KyDB<KY>[Table], TableFields[number]>> | undefined;
67
126
  }[];
68
- type TableAlias<KY extends KyselyRizzolverBase<any, any>, Table extends TableName<KY>, Alias extends string> = `${Table} as ${Alias}`;
127
+ export type AnySelectorResult<DB, Row extends Record<string, unknown>, Table extends TableName<DB>, TableFields extends readonly AnyTableField<DB, Table>[] = AllTableFields<DB, Table>> = {
128
+ row: Row;
129
+ model: Selectable<Pick<DB[Table], TableFields[number]>> | undefined;
130
+ }[];
131
+ type KyTableAlias<KY extends KyselyRizzolverBase<any, any, any>, Table extends KyTableName<KY>, Alias extends string> = `${Table} as ${Alias}`;
132
+ type TableAlias<DB, Table extends TableName<DB>, Alias extends string> = `${Table} as ${Alias}`;
69
133
  type FieldAlias<TableAlias extends string, TableField extends string> = `_${TableAlias}_${TableField}`;
70
134
  type FieldAsAlias<TableAlias extends string, TableField extends string> = `${TableAlias}.${TableField} as ${FieldAlias<TableAlias, TableField>}`;
71
135
  type FieldsAsAliases<TableAlias extends string, TableFields extends readonly string[]> = TableFields extends readonly [infer TableField extends string, ...infer Tail extends string[]] ? [FieldAsAlias<TableAlias, TableField>, ...FieldsAsAliases<TableAlias, Tail>] : [];
@@ -1,3 +1,4 @@
1
+ import type { Generated } from 'kysely';
1
2
  /**
2
3
  * I can't explain this.
3
4
  *
@@ -8,4 +9,23 @@ type LastInUnion<U> = (U extends any ? () => U : never) extends infer F ? (F ext
8
9
  * Recursively converts a union type to a tuple by splitting it into its head and tail.
9
10
  */
10
11
  export type UnionToTuple<U, Last = LastInUnion<U>> = [U] extends [never] ? [] : [...UnionToTuple<Exclude<U, Last>>, Last];
12
+ /**
13
+ * Omit properties of `T` that are of type `never`.
14
+ */
15
+ export type OmitNever<T> = {
16
+ [K in keyof T as T[K] extends never ? never : K]: T[K];
17
+ };
18
+ /**
19
+ * Omit properties of `T` that are of type `ValueType`.
20
+ */
21
+ export type OmitByValue<T, ValueType> = OmitNever<{
22
+ [K in keyof T]: T[K] extends ValueType ? never : T[K];
23
+ }>;
24
+ export type WithMandatory<T, K extends keyof T> = T & {
25
+ [P in K]-?: T[P];
26
+ };
27
+ type IsNumericField<T> = T extends Generated<number> ? true : number & T extends never ? never : T extends number ? true : never;
28
+ export type NumericFields<T> = {
29
+ [K in keyof T]: [IsNumericField<T[K]>] extends [never] ? never : K;
30
+ }[keyof T];
11
31
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kysely-rizzolver",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "Complex Kysely queries, maximum rizz, type-safe every time.",
5
5
  "author": "YLivay",
6
6
  "repository": {