@housekit/orm 0.1.17 → 0.1.21

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 CHANGED
@@ -167,7 +167,9 @@ await builder.append(row2);
167
167
  ### Simple Repository Pattern
168
168
 
169
169
  ```typescript
170
- async insertEvents(events: auditEvents[]) {
170
+ import type { InferInsert } from '@housekit/orm';
171
+
172
+ async insertEvents(events: InferInsert<typeof auditEvents>[]) {
171
173
  return await db.insert(auditEvents).values(events);
172
174
  }
173
175
 
@@ -178,27 +180,34 @@ await repository.insertEvents([
178
180
  ]);
179
181
  ```
180
182
 
181
- ### How It Works
182
-
183
- When you write `table.$inferInsert`, it includes a callable signature. TypeScript interprets `table[]` as invoking that callable and applying the array type, giving you `TableInsert<T>[]` automatically.
184
-
185
- ### Alternative Approaches
183
+ ### Type Helpers
186
184
 
187
185
  ```typescript
188
- import { TableInsertArray } from '@housekit/orm';
186
+ import type { TableInsertArray, InferInsert } from '@housekit/orm';
187
+
188
+ // Using the direct helper
189
+ async insertEvents(events: InferInsert<typeof salesEvents>[]) {
190
+ return await db.insert(salesEvents).values(events);
191
+ }
189
192
 
190
193
  // Using explicit type helper
191
194
  async insertEvents(events: TableInsertArray<typeof salesEvents>) {
192
195
  return await db.insert(salesEvents).values(events);
193
196
  }
197
+ ```
194
198
 
195
- // Using $inferInsert directly
196
- async insertEvents(events: typeof salesEvents.$inferInsert[]) {
197
- return await db.insert(salesEvents).values(events);
199
+ ### Inline Types (No Extra Exports)
200
+
201
+ ```typescript
202
+ import { users } from './schema';
203
+ import type { Infer } from '@housekit/orm';
204
+
205
+ function UserCard({ user }: { user: Infer<typeof users> }) {
206
+ return <div>{user.email}</div>;
198
207
  }
199
208
  ```
200
209
 
201
- **Recommended**: Use `table[]` for the cleanest, most ergonomic DX.
210
+ **Note**: Autocomplete shows clean data types by default without exposing internal types.
202
211
 
203
212
  ---
204
213
 
@@ -288,4 +297,4 @@ const db = await createClient({
288
297
 
289
298
  ## License
290
299
 
291
- MIT © [Pablo Fernandez Ruiz](https://github.com/pablofdezr)
300
+ MIT © [Pablo Fernandez Ruiz](https://github.com/pablofdezr)
@@ -1,7 +1,7 @@
1
1
  import type { ClickHouseClient } from '@clickhouse/client';
2
2
  import type { SQLExpression } from '../expressions';
3
- import type { TableDefinition, TableColumns } from '../core';
4
- export declare class ClickHouseDeleteBuilder<TTable extends TableDefinition<TableColumns>> {
3
+ import type { TableRuntime } from '../core';
4
+ export declare class ClickHouseDeleteBuilder<TTable extends TableRuntime<any, any>> {
5
5
  private client;
6
6
  private table;
7
7
  private _where;
@@ -1,5 +1,5 @@
1
1
  import type { ClickHouseClient } from '@clickhouse/client';
2
- import { type TableDefinition, type TableInsert, type TableColumns } from '../core';
2
+ import { type TableRuntime, type CleanInsert, type CleanSelect } from '../core';
3
3
  import { type BatchTransformOptions } from '../utils/batch-transform';
4
4
  import { Readable } from 'stream';
5
5
  import { type BatchConfig } from '../utils/background-batcher';
@@ -20,7 +20,7 @@ export interface InsertOptions {
20
20
  /** Rows per batch when streaming */
21
21
  batchSize?: number;
22
22
  }
23
- export declare class ClickHouseInsertBuilder<TTable extends TableDefinition<TableColumns>> {
23
+ export declare class ClickHouseInsertBuilder<TTable extends TableRuntime<any, any>, TReturn = void> {
24
24
  private client;
25
25
  private table;
26
26
  private _values;
@@ -31,8 +31,12 @@ export declare class ClickHouseInsertBuilder<TTable extends TableDefinition<Tabl
31
31
  private _batchSize;
32
32
  private _batchConfig;
33
33
  private _forceJson;
34
+ private _returning;
34
35
  constructor(client: ClickHouseClient, table: TTable);
35
- values(value: TableInsert<TTable['$columns']> | Array<TableInsert<TTable['$columns']>> | Iterable<TableInsert<TTable['$columns']>> | AsyncIterable<TableInsert<TTable['$columns']>> | Readable): this;
36
+ values(value: CleanInsert<TTable> | Array<CleanInsert<TTable>> | Iterable<CleanInsert<TTable>> | AsyncIterable<CleanInsert<TTable>> | Readable): this;
37
+ /** @template [T = CleanInsert<TTable>] */
38
+ insert(data: CleanInsert<TTable> | CleanInsert<TTable>[]): Promise<this>;
39
+ returning(): ClickHouseInsertBuilder<TTable, CleanSelect<TTable>[]>;
36
40
  /**
37
41
  * Force synchronous insert (disables async_insert).
38
42
  * Use when you need immediate durability guarantee.
@@ -73,7 +77,7 @@ export declare class ClickHouseInsertBuilder<TTable extends TableDefinition<Tabl
73
77
  * Note: This method is "fire-and-forget" and does not wait for
74
78
  * the database to acknowledge the insert.
75
79
  */
76
- append(row: TableInsert<TTable['$columns']>): Promise<void>;
80
+ append(row: CleanInsert<TTable>): Promise<void>;
77
81
  /**
78
82
  * Force JSON format (useful for debugging or compatibility).
79
83
  *
@@ -104,7 +108,7 @@ export declare class ClickHouseInsertBuilder<TTable extends TableDefinition<Tabl
104
108
  * Up to 5x faster than normal insertion.
105
109
  */
106
110
  turbo(): this;
107
- execute(): Promise<void>;
111
+ execute(): Promise<TReturn>;
108
112
  /**
109
113
  * Resolve the actual format to use based on settings and table capabilities.
110
114
  *
@@ -133,6 +137,9 @@ export declare class ClickHouseInsertBuilder<TTable extends TableDefinition<Tabl
133
137
  * Process rows and yield them with column names mapped and defaults applied
134
138
  */
135
139
  private processRows;
136
- then<TResult1 = void, TResult2 = never>(onfulfilled?: ((value: void) => TResult1 | PromiseLike<TResult1>) | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null): Promise<TResult1 | TResult2>;
140
+ private collectReturningRows;
141
+ private assertReturningRow;
142
+ private resolveClientDefaultExpr;
143
+ then<TResult1 = TReturn, TResult2 = never>(onfulfilled?: ((value: TReturn) => TResult1 | PromiseLike<TResult1>) | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null): Promise<TResult1 | TResult2>;
137
144
  }
138
145
  export {};
@@ -1,5 +1,5 @@
1
1
  import type { ClickHouseClient } from '@clickhouse/client';
2
- import { ClickHouseColumn, type TableDefinition, type TableOptions } from '../core';
2
+ import { ClickHouseColumn, type TableDefinition, type TableOptions, type InferSelectModel } from '../core';
3
3
  import { type SQLExpression } from '../expressions';
4
4
  import { type QueryBuilderState, type SelectionShape, type SelectResult, type ResultWithArrayJoin, type InferQueryResult } from './select.types';
5
5
  export type { QueryBuilderState, SelectionShape, SelectResult } from './select.types';
@@ -8,6 +8,7 @@ type StandardJoinType = 'INNER' | 'LEFT' | 'RIGHT' | 'FULL' | 'CROSS';
8
8
  export declare class ClickHouseQueryBuilder<TTable extends TableDefinition<any> | null = null, TSelection extends SelectionShape | null = null, TResult = InferQueryResult<TTable, TSelection>> {
9
9
  private client;
10
10
  private _select;
11
+ private _selectResolver;
11
12
  private _table;
12
13
  private _prewhere;
13
14
  private _sample;
@@ -27,11 +28,15 @@ export declare class ClickHouseQueryBuilder<TTable extends TableDefinition<any>
27
28
  private _suggestions;
28
29
  constructor(client: ClickHouseClient);
29
30
  select<TNewSelection extends SelectionShape>(fields: TNewSelection): ClickHouseQueryBuilder<TTable, TNewSelection, InferQueryResult<TTable, TNewSelection>>;
31
+ select<TNewSelection extends SelectionShape>(fields: (cols: TTable extends TableDefinition<infer TCols> ? TCols : any) => TNewSelection): ClickHouseQueryBuilder<TTable, TNewSelection, InferQueryResult<TTable, TNewSelection>>;
30
32
  select(): ClickHouseQueryBuilder<TTable, null, InferQueryResult<TTable, null>>;
31
33
  from<TNewTable extends TableDefinition<any>>(table: TNewTable): ClickHouseQueryBuilder<TNewTable, TSelection, InferQueryResult<TNewTable, TSelection>>;
32
34
  from<TSubQuery extends ClickHouseQueryBuilder<any, any, any>>(subquery: TSubQuery, alias?: string): ClickHouseQueryBuilder<any, TSelection, any>;
33
35
  private fromSubquery;
34
- where(expression: SQLExpression | undefined | null): this;
36
+ private resolveSelect;
37
+ where(expression: SQLExpression | (TTable extends TableDefinition<infer TCols> ? Partial<InferSelectModel<{
38
+ $columns: TCols;
39
+ }>> : Record<string, any>) | undefined | null): this;
35
40
  orderBy(col: ClickHouseColumn | SQLExpression | {
36
41
  col: ClickHouseColumn | SQLExpression;
37
42
  dir: 'ASC' | 'DESC';
@@ -214,12 +219,10 @@ export declare class ClickHouseQueryBuilder<TTable extends TableDefinition<any>
214
219
  kind: "cte";
215
220
  query?: string;
216
221
  }>;
217
- $inferSelect?: import("../table").InferSelectModel<{
222
+ $inferSelect: InferSelectModel<{
218
223
  $columns: TSelection extends SelectionShape ? { [K in keyof (TSelection extends infer T_1 ? T_1 extends TSelection ? T_1 extends SelectionShape ? SelectResult<T_1> : Record<string, any> : never : never)]: ClickHouseColumn<(TSelection extends infer T_2 ? T_2 extends TSelection ? T_2 extends SelectionShape ? SelectResult<T_2> : Record<string, any> : never : never)[K], true, false>; } : Record<string, ClickHouseColumn<any, true, false>>;
219
- }> | undefined;
220
- $inferInsert?: import("../table").InferInsertModel<{
221
- $columns: TSelection extends SelectionShape ? { [K in keyof (TSelection extends infer T_2 ? T_2 extends TSelection ? T_2 extends SelectionShape ? SelectResult<T_2> : Record<string, any> : never : never)]: ClickHouseColumn<(TSelection extends infer T_3 ? T_3 extends TSelection ? T_3 extends SelectionShape ? SelectResult<T_3> : Record<string, any> : never : never)[K], true, false>; } : Record<string, ClickHouseColumn<any, true, false>>;
222
- }> | undefined;
224
+ }>;
225
+ $inferInsert: import("..").TableInsert<TSelection extends SelectionShape ? { [K in keyof (TSelection extends infer T_2 ? T_2 extends TSelection ? T_2 extends SelectionShape ? SelectResult<T_2> : Record<string, any> : never : never)]: ClickHouseColumn<(TSelection extends infer T_3 ? T_3 extends TSelection ? T_3 extends SelectionShape ? SelectResult<T_3> : Record<string, any> : never : never)[K], true, false>; } : Record<string, ClickHouseColumn<any, true, false>>>;
223
226
  } & (TSelection extends SelectionShape ? { [K in keyof (TSelection extends infer T_3 ? T_3 extends TSelection ? T_3 extends SelectionShape ? SelectResult<T_3> : Record<string, any> : never : never)]: ClickHouseColumn<(TSelection extends infer T_4 ? T_4 extends TSelection ? T_4 extends SelectionShape ? SelectResult<T_4> : Record<string, any> : never : never)[K], true, false>; } : Record<string, ClickHouseColumn<any, true, false>>);
224
227
  register: (mainQuery: ClickHouseQueryBuilder<any, any, any>) => ClickHouseQueryBuilder<any, any, any>;
225
228
  };
@@ -1,7 +1,7 @@
1
1
  import type { ClickHouseClient } from '@clickhouse/client';
2
2
  import type { SQLExpression } from '../expressions';
3
- import { type TableDefinition, type TableColumns } from '../core';
4
- export declare class ClickHouseUpdateBuilder<TTable extends TableDefinition<TableColumns>> {
3
+ import { type TableRuntime } from '../core';
4
+ export declare class ClickHouseUpdateBuilder<TTable extends TableRuntime<any, any>> {
5
5
  private client;
6
6
  private table;
7
7
  private _set;
package/dist/client.d.ts CHANGED
@@ -3,9 +3,9 @@ import { ClickHouseQueryBuilder } from './builders/select';
3
3
  import { ClickHouseInsertBuilder } from './builders/insert';
4
4
  import { ClickHouseDeleteBuilder } from './builders/delete';
5
5
  import { ClickHouseUpdateBuilder } from './builders/update';
6
- import { type TableDefinition, type TableColumns, type TableInsert } from './core';
6
+ import { type TableDefinition, type TableRuntime, type CleanInsert } from './core';
7
7
  import { type HousekitLogger } from './logger';
8
- import { type RelationalFindOptions } from './relational';
8
+ import { type RelationalAPI } from './relational';
9
9
  export type HousekitClientConfig = ClickHouseClientConfigOptions & {
10
10
  schema?: Record<string, TableDefinition<any>>;
11
11
  logger?: HousekitLogger;
@@ -15,13 +15,13 @@ export interface HousekitClient<TSchema extends Record<string, TableDefinition<a
15
15
  rawClient: ClickHouseClient;
16
16
  select: <T extends Record<string, any> | TableDefinition<any>>(fieldsOrTable?: T) => any;
17
17
  with: (name: string, query: ClickHouseQueryBuilder<any>) => ClickHouseQueryBuilder<any>;
18
- insert: <TCols extends TableColumns>(table: TableDefinition<TCols>) => ClickHouseInsertBuilder<any>;
19
- insertMany: <TCols extends TableColumns>(table: TableDefinition<TCols>, values: Array<TableInsert<TCols>> | Iterable<TableInsert<TCols>> | AsyncIterable<TableInsert<TCols>>, opts?: {
18
+ insert: <TTable extends TableRuntime<any, any>>(table: TTable) => ClickHouseInsertBuilder<TTable>;
19
+ insertMany: <TTable extends TableRuntime<any, any>>(table: TTable, values: Array<CleanInsert<TTable>> | Iterable<CleanInsert<TTable>> | AsyncIterable<CleanInsert<TTable>>, opts?: {
20
20
  maxBlockSize?: number;
21
21
  asyncInsertWait?: boolean;
22
22
  }) => Promise<void>;
23
- update: <TCols extends TableColumns>(table: TableDefinition<TCols>) => ClickHouseUpdateBuilder<any>;
24
- delete: <TCols extends TableColumns>(table: TableDefinition<TCols>) => ClickHouseDeleteBuilder<any>;
23
+ update: <TTable extends TableRuntime<any, any>>(table: TTable) => ClickHouseUpdateBuilder<TTable>;
24
+ delete: <TTable extends TableRuntime<any, any>>(table: TTable) => ClickHouseDeleteBuilder<TTable>;
25
25
  command: (params: {
26
26
  query: string;
27
27
  query_params?: Record<string, unknown>;
@@ -39,12 +39,7 @@ export interface HousekitClient<TSchema extends Record<string, TableDefinition<a
39
39
  close: () => Promise<void>;
40
40
  schema: TSchema;
41
41
  _config: HousekitClientConfig;
42
- query: TSchema extends Record<string, TableDefinition<any>> ? {
43
- [K in keyof TSchema]: {
44
- findMany: (opts?: RelationalFindOptions) => Promise<any[]>;
45
- findFirst: (opts?: RelationalFindOptions) => Promise<any | null>;
46
- };
47
- } : undefined;
42
+ query: TSchema extends Record<string, TableDefinition<any>> ? RelationalAPI<TSchema> : undefined;
48
43
  }
49
44
  export declare function createHousekitClient<TSchema extends Record<string, TableDefinition<any>> | undefined = any>(config: HousekitClientConfig & {
50
45
  schema?: TSchema;
package/dist/index.d.ts CHANGED
@@ -1,7 +1,21 @@
1
+ import type { ClickHouseClientConfigOptions } from '@clickhouse/client';
1
2
  import { type TableDefinition, type TableColumns } from './core';
2
- import { createClientFromConfigObject, type ClientConfigWithSchema } from './client';
3
+ import { createClientFromConfigObject, type ClientConfigWithSchema, type HousekitClient as HousekitClientType } from './client';
4
+ import { generateSelectSchema, generateInsertSchema } from './codegen/zod';
3
5
  export { ClickHouseColumn } from './column';
4
- export { type TableDefinition, type TableColumns, type TableOptions, type IndexDefinition, type ProjectionDefinition, type TableInsert, index, projection, deriveTable, renderSchema } from './table';
6
+ export { type TableDefinition, type TableColumns, type TableOptions, type IndexDefinition, type ProjectionDefinition, type InsertModel, type TableModel, type TableInsertArray, type TableRuntime, type TableInsert, index, projection, deriveTable, renderSchema } from './table';
7
+ /**
8
+ * Infer the SELECT type (result) from a table definition.
9
+ */
10
+ export type Infer<T> = T extends {
11
+ $inferSelect: infer U;
12
+ } ? U : never;
13
+ /**
14
+ * Infer the INSERT type (input) from a table definition.
15
+ */
16
+ export type InferInsert<T> = T extends {
17
+ $inferInsert: infer U;
18
+ } ? U : never;
5
19
  export { Engine, type EngineConfiguration } from './engines';
6
20
  export * from './external';
7
21
  export * from './expressions';
@@ -25,6 +39,13 @@ export { SyncBinarySerializer, BinaryWorkerPool, type BinaryWorkerPoolOptions, }
25
39
  * Load housekit.config.js/ts and create a client by name.
26
40
  */
27
41
  export declare function createClientFromConfig(databaseName?: string): Promise<HousekitClient>;
42
+ export declare function housekit<TSchema extends Record<string, TableDefinition<any>> = Record<string, TableDefinition<any>>>(config: ClickHouseClientConfigOptions, options?: {
43
+ schema?: TSchema;
44
+ }): HousekitClientType<TSchema>;
45
+ export declare function createSchema<TCols extends TableColumns>(table: TableDefinition<TCols>): {
46
+ select: import("zod").ZodObject<any, import("zod/v4/core").$strip>;
47
+ insert: import("zod").ZodObject<any, import("zod/v4/core").$strip>;
48
+ };
28
49
  export type HousekitClient = ReturnType<typeof createClientFromConfigObject>;
29
50
  export declare function createClient(): Promise<HousekitClient>;
30
51
  export declare function createClient(config: ClientConfigWithSchema): HousekitClient;
@@ -53,7 +74,6 @@ export declare function closeAllClients(clients: Record<string, HousekitClient>)
53
74
  import { defineTable, defineProjection, detectMaterializedViewDrift, extractMVQuery, createMigrationBridge, generateBlueGreenMigration, relations } from './schema-builder';
54
75
  import { sql } from './expressions';
55
76
  import { deriveTable } from './table';
56
- import { generateSelectSchema, generateInsertSchema } from './codegen/zod';
57
77
  /**
58
78
  * Optional default export for users who prefer this style.
59
79
  * Named exports are recommended for better tree-shaking.
@@ -122,6 +142,15 @@ declare const _default: {
122
142
  polygon: (name: string) => import("./column").ClickHouseColumn<[number, number][][], true, false>;
123
143
  multiPolygon: (name: string) => import("./column").ClickHouseColumn<[number, number][][][], true, false>;
124
144
  enum: (name: string, values: readonly string[]) => import("./column").ClickHouseColumn<string, false, false>;
145
+ timestamps: () => {
146
+ created_at: import("./column").ClickHouseColumn<string | Date, true, false>;
147
+ updated_at: import("./column").ClickHouseColumn<string | Date, true, false>;
148
+ };
149
+ primaryUuid: <TName extends string = "id">(name?: TName) => { [K in TName]: import("./column").ClickHouseColumn<string>; };
150
+ softDeletes: () => {
151
+ is_deleted: import("./column").ClickHouseColumn<boolean, true, false>;
152
+ deleted_at: import("./column").ClickHouseColumn<string | Date, false, false>;
153
+ };
125
154
  };
126
155
  table: typeof defineTable;
127
156
  defineTable: typeof defineTable;