@housekit/orm 0.1.18 → 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/dist/index.js CHANGED
@@ -192,8 +192,8 @@ class BinaryReader {
192
192
  return new Date(Number(ms));
193
193
  }
194
194
  readNullable(reader) {
195
- const isNull = this.readUInt8();
196
- if (isNull === 1)
195
+ const isNull2 = this.readUInt8();
196
+ if (isNull2 === 1)
197
197
  return null;
198
198
  return reader();
199
199
  }
@@ -2157,6 +2157,144 @@ function generateRandom(structure, randomSeed, maxStringLength = 10, maxArrayLen
2157
2157
  };
2158
2158
  }
2159
2159
 
2160
+ // src/modules/conditional.ts
2161
+ function ifNull(col, alt) {
2162
+ return sql`ifNull(${col}, ${alt})`;
2163
+ }
2164
+ function sqlIf(condition, trueVal, falseVal) {
2165
+ return sql`if(${condition}, ${trueVal}, ${falseVal})`;
2166
+ }
2167
+ function multiIf(...args) {
2168
+ if (args.length < 3) {
2169
+ throw new Error("multiIf requires at least 3 arguments: condition, value, default");
2170
+ }
2171
+ if (args.length % 2 === 0) {
2172
+ throw new Error("multiIf requires an odd number of arguments: condition-value pairs plus a default value");
2173
+ }
2174
+ const params = args.map((arg) => sql`${arg}`).join(", ");
2175
+ return sql`multiIf(${params})`;
2176
+ }
2177
+ function caseWhen() {
2178
+ return new CaseWhenBuilder;
2179
+ }
2180
+
2181
+ class CaseWhenBuilder {
2182
+ conditions = [];
2183
+ values = [];
2184
+ defaultValue;
2185
+ when(condition, value) {
2186
+ this.conditions.push(condition);
2187
+ this.values.push(value);
2188
+ return this;
2189
+ }
2190
+ otherwise(value) {
2191
+ this.defaultValue = value;
2192
+ return this.build();
2193
+ }
2194
+ build() {
2195
+ if (!this.defaultValue) {
2196
+ throw new Error("CaseWhenBuilder requires a default value via .otherwise()");
2197
+ }
2198
+ const args = [];
2199
+ for (let i = 0;i < this.conditions.length; i++) {
2200
+ args.push(this.conditions[i]);
2201
+ args.push(this.values[i]);
2202
+ }
2203
+ args.push(this.defaultValue);
2204
+ return multiIf(...args);
2205
+ }
2206
+ }
2207
+ function coalesce(...args) {
2208
+ const chunks = ["coalesce("];
2209
+ const params = [];
2210
+ args.forEach((arg, i) => {
2211
+ params.push(arg);
2212
+ if (i < args.length - 1) {
2213
+ chunks.push(", ");
2214
+ }
2215
+ });
2216
+ chunks.push(")");
2217
+ return new SQL(chunks, params);
2218
+ }
2219
+ function greatest(...args) {
2220
+ const chunks = ["greatest("];
2221
+ const params = [];
2222
+ args.forEach((arg, i) => {
2223
+ params.push(arg);
2224
+ if (i < args.length - 1) {
2225
+ chunks.push(", ");
2226
+ }
2227
+ });
2228
+ chunks.push(")");
2229
+ return new SQL(chunks, params);
2230
+ }
2231
+ function least(...args) {
2232
+ const chunks = ["least("];
2233
+ const params = [];
2234
+ args.forEach((arg, i) => {
2235
+ params.push(arg);
2236
+ if (i < args.length - 1) {
2237
+ chunks.push(", ");
2238
+ }
2239
+ });
2240
+ chunks.push(")");
2241
+ return new SQL(chunks, params);
2242
+ }
2243
+ function isNull(col) {
2244
+ return sql`${col} IS NULL`;
2245
+ }
2246
+ function isNotNull(col) {
2247
+ return sql`${col} IS NOT NULL`;
2248
+ }
2249
+ function nullIf(condition, col) {
2250
+ return sql`nullIf(${col}, ${condition})`;
2251
+ }
2252
+ function nullIfEqual(col, value) {
2253
+ return sql`nullIf(${col}, ${value})`;
2254
+ }
2255
+ function not(expr) {
2256
+ return sql`NOT (${expr})`;
2257
+ }
2258
+ function and(...exprs) {
2259
+ const filtered = exprs.filter((e) => !!e);
2260
+ if (filtered.length === 0)
2261
+ return;
2262
+ if (filtered.length === 1)
2263
+ return filtered[0];
2264
+ const finalChunks = ["("];
2265
+ const finalParams = [];
2266
+ filtered.forEach((e, i) => {
2267
+ finalParams.push(e);
2268
+ if (i < filtered.length - 1) {
2269
+ finalChunks.push(") AND (");
2270
+ } else {
2271
+ finalChunks.push(")");
2272
+ }
2273
+ });
2274
+ return new SQL(finalChunks, finalParams);
2275
+ }
2276
+ function or(...exprs) {
2277
+ const filtered = exprs.filter((e) => !!e);
2278
+ if (filtered.length === 0)
2279
+ return;
2280
+ if (filtered.length === 1)
2281
+ return filtered[0];
2282
+ const finalChunks = ["("];
2283
+ const finalParams = [];
2284
+ filtered.forEach((e, i) => {
2285
+ finalParams.push(e);
2286
+ if (i < filtered.length - 1) {
2287
+ finalChunks.push(") OR (");
2288
+ } else {
2289
+ finalChunks.push(")");
2290
+ }
2291
+ });
2292
+ return new SQL(finalChunks, finalParams);
2293
+ }
2294
+ function xor(expr1, expr2) {
2295
+ return sql`xor(${expr1}, ${expr2})`;
2296
+ }
2297
+
2160
2298
  // src/utils/lru-cache.ts
2161
2299
  class LRUCache {
2162
2300
  map = new Map;
@@ -2731,6 +2869,7 @@ class QueryCompiler {
2731
2869
  class ClickHouseQueryBuilder {
2732
2870
  client;
2733
2871
  _select = null;
2872
+ _selectResolver = null;
2734
2873
  _table = null;
2735
2874
  _prewhere = null;
2736
2875
  _sample = null;
@@ -2753,7 +2892,17 @@ class ClickHouseQueryBuilder {
2753
2892
  }
2754
2893
  select(fields) {
2755
2894
  if (fields) {
2895
+ if (typeof fields === "function") {
2896
+ if (!this._table) {
2897
+ this._selectResolver = fields;
2898
+ return this;
2899
+ }
2900
+ this._select = fields(this._table.$columns);
2901
+ this._selectResolver = null;
2902
+ return this;
2903
+ }
2756
2904
  this._select = fields;
2905
+ this._selectResolver = null;
2757
2906
  return this;
2758
2907
  }
2759
2908
  return this;
@@ -2767,16 +2916,48 @@ class ClickHouseQueryBuilder {
2767
2916
  if (defaultFinal !== undefined) {
2768
2917
  this._final = Boolean(defaultFinal);
2769
2918
  }
2919
+ this.resolveSelect();
2770
2920
  return this;
2771
2921
  }
2772
2922
  fromSubquery(subquery, alias) {
2773
2923
  this._table = this.createSubqueryTable(alias, subquery);
2774
2924
  this._final = false;
2925
+ this.resolveSelect();
2775
2926
  return this;
2776
2927
  }
2928
+ resolveSelect() {
2929
+ if (!this._selectResolver)
2930
+ return;
2931
+ if (!this._table) {
2932
+ throw new Error("Call .from() before using callback select");
2933
+ }
2934
+ this._select = this._selectResolver(this._table.$columns);
2935
+ this._selectResolver = null;
2936
+ }
2777
2937
  where(expression) {
2778
- if (expression) {
2938
+ if (!expression)
2939
+ return this;
2940
+ if (typeof expression === "object" && "toSQL" in expression) {
2779
2941
  this._where = expression;
2942
+ return this;
2943
+ }
2944
+ if (typeof expression === "object") {
2945
+ const table = this._table;
2946
+ if (!table)
2947
+ return this;
2948
+ const chunks = [];
2949
+ const columns = table.$columns || table;
2950
+ for (const [key, value] of Object.entries(expression)) {
2951
+ const column = table[key] || columns?.[key];
2952
+ if (column) {
2953
+ chunks.push(eq(column, value));
2954
+ }
2955
+ }
2956
+ if (chunks.length > 0) {
2957
+ const combined = chunks.length === 1 ? chunks[0] : and(...chunks);
2958
+ if (combined)
2959
+ this._where = combined;
2960
+ }
2780
2961
  }
2781
2962
  return this;
2782
2963
  }
@@ -3012,6 +3193,7 @@ class ClickHouseQueryBuilder {
3012
3193
  return buildTable(alias);
3013
3194
  }
3014
3195
  getState() {
3196
+ this.resolveSelect();
3015
3197
  return {
3016
3198
  select: this._select,
3017
3199
  table: this._table,
@@ -3728,8 +3910,8 @@ class BinaryWriter {
3728
3910
  const ticks = typeof value === "number" ? BigInt(Math.round(value * multiplier)) : BigInt(Math.round(value.getTime() * multiplier / 1000));
3729
3911
  this.writeInt64(ticks);
3730
3912
  }
3731
- writeNullable(isNull) {
3732
- this.writeUInt8(isNull ? 1 : 0);
3913
+ writeNullable(isNull2) {
3914
+ this.writeUInt8(isNull2 ? 1 : 0);
3733
3915
  }
3734
3916
  writeArrayLength(length) {
3735
3917
  this.writeUInt64(length);
@@ -4329,7 +4511,7 @@ var globalBatcher = (client) => {
4329
4511
  };
4330
4512
 
4331
4513
  // src/builders/insert.ts
4332
- import { v4 as uuidv42, v7 as uuidv7 } from "uuid";
4514
+ import { v1 as uuidv1, v4 as uuidv42, v6 as uuidv6, v7 as uuidv7 } from "uuid";
4333
4515
 
4334
4516
  class BinaryTransform extends Transform2 {
4335
4517
  serializer;
@@ -4379,6 +4561,7 @@ class ClickHouseInsertBuilder {
4379
4561
  _batchSize = 1000;
4380
4562
  _batchConfig = null;
4381
4563
  _forceJson = false;
4564
+ _returning = false;
4382
4565
  constructor(client, table) {
4383
4566
  this.client = client;
4384
4567
  this.table = table;
@@ -4397,6 +4580,10 @@ class ClickHouseInsertBuilder {
4397
4580
  async insert(data) {
4398
4581
  return this.values(data);
4399
4582
  }
4583
+ returning() {
4584
+ this._returning = true;
4585
+ return this;
4586
+ }
4400
4587
  syncInsert() {
4401
4588
  this._async = false;
4402
4589
  return this;
@@ -4462,6 +4649,23 @@ class ClickHouseInsertBuilder {
4462
4649
  throw new Error("❌ No values to insert");
4463
4650
  }
4464
4651
  const plan = buildInsertPlan(this.table);
4652
+ if (this._returning) {
4653
+ if (this._batchConfig) {
4654
+ throw new Error("❌ returning() cannot be used with background batching");
4655
+ }
4656
+ const { processedRows, resultRows } = await this.collectReturningRows(plan);
4657
+ const stream = Readable.from(processedRows, { objectMode: true });
4658
+ await this.client.insert({
4659
+ table: this.table.$table,
4660
+ values: stream,
4661
+ format: "JSONEachRow",
4662
+ clickhouse_settings: {
4663
+ async_insert: this._async ? 1 : 0,
4664
+ wait_for_async_insert: this._waitForAsync ? 1 : 0
4665
+ }
4666
+ });
4667
+ return resultRows;
4668
+ }
4465
4669
  if (this._batchConfig && !this._forceJson) {
4466
4670
  const batcher = globalBatcher(this.client);
4467
4671
  const rowIterator = this.processRows(plan);
@@ -4477,6 +4681,7 @@ class ClickHouseInsertBuilder {
4477
4681
  } else {
4478
4682
  await this.executeJsonInsert(plan, tableName, format);
4479
4683
  }
4684
+ return;
4480
4685
  }
4481
4686
  resolveFormat(plan) {
4482
4687
  if (this._format !== "auto") {
@@ -4569,13 +4774,73 @@ class ClickHouseInsertBuilder {
4569
4774
  yield processedRow;
4570
4775
  }
4571
4776
  }
4777
+ async collectReturningRows(plan) {
4778
+ const processedRows = [];
4779
+ const resultRows = [];
4780
+ const values2 = this._values;
4781
+ const iterable = values2 instanceof Readable ? values2 : Array.isArray(values2) ? values2 : isIterable(values2) ? values2 : isAsyncIterable(values2) ? values2 : [values2];
4782
+ for await (const row of iterable) {
4783
+ const processed = processRowWithPlan(row, plan, "json");
4784
+ for (const col of plan.columns) {
4785
+ if (processed[col.columnName] !== undefined)
4786
+ continue;
4787
+ const expr = col.column.meta?.defaultExpr;
4788
+ if (!expr)
4789
+ continue;
4790
+ const resolved = this.resolveClientDefaultExpr(expr);
4791
+ if (resolved !== undefined) {
4792
+ processed[col.columnName] = col.transform(resolved);
4793
+ }
4794
+ }
4795
+ this.assertReturningRow(row, processed, plan);
4796
+ processedRows.push(processed);
4797
+ const resultRow = {};
4798
+ for (const col of plan.columns) {
4799
+ const value = processed[col.columnName];
4800
+ resultRow[col.propKey] = value;
4801
+ }
4802
+ resultRows.push(resultRow);
4803
+ }
4804
+ return { processedRows, resultRows };
4805
+ }
4806
+ assertReturningRow(rawRow, processed, plan) {
4807
+ for (const col of plan.columns) {
4808
+ const hasValue = rawRow[col.propKey] !== undefined || rawRow[col.columnName] !== undefined;
4809
+ if (hasValue)
4810
+ continue;
4811
+ if (processed[col.columnName] !== undefined) {
4812
+ continue;
4813
+ }
4814
+ if (col.defaultFn || col.autoUUIDVersion !== null && !col.useServerUUID || col.hasDefault) {
4815
+ continue;
4816
+ }
4817
+ if (col.useServerUUID || col.column.meta?.defaultExpr) {
4818
+ throw new Error(`❌ returning() cannot infer column '${col.columnName}' because it uses a server-side default. Provide a value or remove the default expression.`);
4819
+ }
4820
+ }
4821
+ }
4822
+ resolveClientDefaultExpr(expr) {
4823
+ const normalized = expr.replace(/\s+/g, "").toLowerCase();
4824
+ if (normalized === "now()" || normalized === "now64()" || normalized.startsWith("now64(")) {
4825
+ return new Date;
4826
+ }
4827
+ if (normalized === "generateuuidv4()")
4828
+ return uuidv42();
4829
+ if (normalized === "generateuuidv7()")
4830
+ return uuidv7();
4831
+ if (normalized === "generateuuidv1()")
4832
+ return uuidv1();
4833
+ if (normalized === "generateuuidv6()")
4834
+ return uuidv6();
4835
+ return;
4836
+ }
4572
4837
  async then(onfulfilled, onrejected) {
4573
4838
  try {
4574
- await this.execute();
4839
+ const result = await this.execute();
4575
4840
  if (onfulfilled) {
4576
- return Promise.resolve(onfulfilled());
4841
+ return Promise.resolve(onfulfilled(result));
4577
4842
  }
4578
- return Promise.resolve();
4843
+ return Promise.resolve(result);
4579
4844
  } catch (error) {
4580
4845
  if (onrejected) {
4581
4846
  return Promise.resolve(onrejected(error));
@@ -4836,159 +5101,21 @@ function wrapClientWithLogger(client, logger) {
4836
5101
  return wrapped;
4837
5102
  }
4838
5103
 
4839
- // src/modules/conditional.ts
4840
- function ifNull(col, alt) {
4841
- return sql`ifNull(${col}, ${alt})`;
4842
- }
4843
- function sqlIf(condition, trueVal, falseVal) {
4844
- return sql`if(${condition}, ${trueVal}, ${falseVal})`;
4845
- }
4846
- function multiIf(...args) {
4847
- if (args.length < 3) {
4848
- throw new Error("multiIf requires at least 3 arguments: condition, value, default");
4849
- }
4850
- if (args.length % 2 === 0) {
4851
- throw new Error("multiIf requires an odd number of arguments: condition-value pairs plus a default value");
4852
- }
4853
- const params = args.map((arg) => sql`${arg}`).join(", ");
4854
- return sql`multiIf(${params})`;
4855
- }
4856
- function caseWhen() {
4857
- return new CaseWhenBuilder;
5104
+ // src/relational.ts
5105
+ function buildJoinCondition(fields, references) {
5106
+ if (!fields || !references || fields.length === 0 || references.length === 0)
5107
+ return null;
5108
+ const pairs = fields.map((f, i) => sql`${f} = ${references[i]}`);
5109
+ const filtered = pairs.filter((p) => Boolean(p));
5110
+ if (filtered.length === 0)
5111
+ return null;
5112
+ if (filtered.length === 1)
5113
+ return filtered[0];
5114
+ return and(...filtered) || null;
4858
5115
  }
4859
-
4860
- class CaseWhenBuilder {
4861
- conditions = [];
4862
- values = [];
4863
- defaultValue;
4864
- when(condition, value) {
4865
- this.conditions.push(condition);
4866
- this.values.push(value);
4867
- return this;
4868
- }
4869
- otherwise(value) {
4870
- this.defaultValue = value;
4871
- return this.build();
4872
- }
4873
- build() {
4874
- if (!this.defaultValue) {
4875
- throw new Error("CaseWhenBuilder requires a default value via .otherwise()");
4876
- }
4877
- const args = [];
4878
- for (let i = 0;i < this.conditions.length; i++) {
4879
- args.push(this.conditions[i]);
4880
- args.push(this.values[i]);
4881
- }
4882
- args.push(this.defaultValue);
4883
- return multiIf(...args);
4884
- }
4885
- }
4886
- function coalesce(...args) {
4887
- const chunks = ["coalesce("];
4888
- const params = [];
4889
- args.forEach((arg, i) => {
4890
- params.push(arg);
4891
- if (i < args.length - 1) {
4892
- chunks.push(", ");
4893
- }
4894
- });
4895
- chunks.push(")");
4896
- return new SQL(chunks, params);
4897
- }
4898
- function greatest(...args) {
4899
- const chunks = ["greatest("];
4900
- const params = [];
4901
- args.forEach((arg, i) => {
4902
- params.push(arg);
4903
- if (i < args.length - 1) {
4904
- chunks.push(", ");
4905
- }
4906
- });
4907
- chunks.push(")");
4908
- return new SQL(chunks, params);
4909
- }
4910
- function least(...args) {
4911
- const chunks = ["least("];
4912
- const params = [];
4913
- args.forEach((arg, i) => {
4914
- params.push(arg);
4915
- if (i < args.length - 1) {
4916
- chunks.push(", ");
4917
- }
4918
- });
4919
- chunks.push(")");
4920
- return new SQL(chunks, params);
4921
- }
4922
- function isNull(col) {
4923
- return sql`${col} IS NULL`;
4924
- }
4925
- function isNotNull(col) {
4926
- return sql`${col} IS NOT NULL`;
4927
- }
4928
- function nullIf(condition, col) {
4929
- return sql`nullIf(${col}, ${condition})`;
4930
- }
4931
- function nullIfEqual(col, value) {
4932
- return sql`nullIf(${col}, ${value})`;
4933
- }
4934
- function not(expr) {
4935
- return sql`NOT (${expr})`;
4936
- }
4937
- function and(...exprs) {
4938
- const filtered = exprs.filter((e) => !!e);
4939
- if (filtered.length === 0)
4940
- return;
4941
- if (filtered.length === 1)
4942
- return filtered[0];
4943
- const finalChunks = ["("];
4944
- const finalParams = [];
4945
- filtered.forEach((e, i) => {
4946
- finalParams.push(e);
4947
- if (i < filtered.length - 1) {
4948
- finalChunks.push(") AND (");
4949
- } else {
4950
- finalChunks.push(")");
4951
- }
4952
- });
4953
- return new SQL(finalChunks, finalParams);
4954
- }
4955
- function or(...exprs) {
4956
- const filtered = exprs.filter((e) => !!e);
4957
- if (filtered.length === 0)
4958
- return;
4959
- if (filtered.length === 1)
4960
- return filtered[0];
4961
- const finalChunks = ["("];
4962
- const finalParams = [];
4963
- filtered.forEach((e, i) => {
4964
- finalParams.push(e);
4965
- if (i < filtered.length - 1) {
4966
- finalChunks.push(") OR (");
4967
- } else {
4968
- finalChunks.push(")");
4969
- }
4970
- });
4971
- return new SQL(finalChunks, finalParams);
4972
- }
4973
- function xor(expr1, expr2) {
4974
- return sql`xor(${expr1}, ${expr2})`;
4975
- }
4976
-
4977
- // src/relational.ts
4978
- function buildJoinCondition(fields, references) {
4979
- if (!fields || !references || fields.length === 0 || references.length === 0)
4980
- return null;
4981
- const pairs = fields.map((f, i) => sql`${f} = ${references[i]}`);
4982
- const filtered = pairs.filter((p) => Boolean(p));
4983
- if (filtered.length === 0)
4984
- return null;
4985
- if (filtered.length === 1)
4986
- return filtered[0];
4987
- return and(...filtered) || null;
4988
- }
4989
- function isDistributedTable(tableDef) {
4990
- const options = tableDef.$options;
4991
- return !!(options?.onCluster || options?.shardKey);
5116
+ function isDistributedTable(tableDef) {
5117
+ const options = tableDef.$options;
5118
+ return !!(options?.onCluster || options?.shardKey);
4992
5119
  }
4993
5120
  function buildRelationalAPI(client, schema) {
4994
5121
  if (!schema)
@@ -5210,7 +5337,7 @@ function createHousekitClient(config) {
5210
5337
  const builder = new ClickHouseQueryBuilder(client);
5211
5338
  if (!fieldsOrTable)
5212
5339
  return builder.select();
5213
- if (typeof fieldsOrTable === "object" && fieldsOrTable !== null && "$table" in fieldsOrTable && "$columns" in fieldsOrTable) {
5340
+ if (typeof fieldsOrTable === "object" && fieldsOrTable !== null && "$table" in fieldsOrTable) {
5214
5341
  return builder.select().from(fieldsOrTable);
5215
5342
  }
5216
5343
  return builder.select(fieldsOrTable);
@@ -5263,6 +5390,105 @@ function createHousekitClient(config) {
5263
5390
  return baseClient;
5264
5391
  }
5265
5392
  var createClientFromConfigObject = createHousekitClient;
5393
+
5394
+ // src/codegen/zod.ts
5395
+ import { z } from "zod";
5396
+ function mapClickHouseTypeToZod(column) {
5397
+ const type = column.type.toLowerCase();
5398
+ let zodType;
5399
+ if (type.startsWith("nullable(")) {
5400
+ const innerType = column.type.slice("nullable(".length, -1);
5401
+ const innerColumn = new ClickHouseColumn(column.name, innerType);
5402
+ zodType = mapClickHouseTypeToZod(innerColumn).nullable();
5403
+ } else if (type.startsWith("array(")) {
5404
+ const innerType = column.type.slice("array(".length, -1);
5405
+ const innerColumn = new ClickHouseColumn(column.name, innerType);
5406
+ zodType = z.array(mapClickHouseTypeToZod(innerColumn));
5407
+ } else if (type.startsWith("fixedstring")) {
5408
+ zodType = z.string();
5409
+ } else if (type.startsWith("enum")) {
5410
+ if (column.meta?.enumValues) {
5411
+ zodType = z.enum(column.meta.enumValues);
5412
+ } else {
5413
+ zodType = z.string();
5414
+ }
5415
+ } else if (type.startsWith("datetime64")) {
5416
+ zodType = z.date();
5417
+ } else if (type.startsWith("decimal")) {
5418
+ zodType = z.string().refine((val) => !isNaN(parseFloat(val)), {
5419
+ message: "Must be a valid decimal number string"
5420
+ });
5421
+ } else {
5422
+ switch (type) {
5423
+ case "uuid":
5424
+ case "string":
5425
+ case "json":
5426
+ case "ipv4":
5427
+ case "ipv6":
5428
+ zodType = z.string();
5429
+ break;
5430
+ case "int8":
5431
+ case "uint8":
5432
+ case "int16":
5433
+ case "uint16":
5434
+ case "int32":
5435
+ case "uint32":
5436
+ case "float32":
5437
+ case "float64":
5438
+ zodType = z.number();
5439
+ break;
5440
+ case "int64":
5441
+ case "uint64":
5442
+ case "int128":
5443
+ case "uint128":
5444
+ case "int256":
5445
+ case "uint256":
5446
+ zodType = z.bigint();
5447
+ break;
5448
+ case "boolean":
5449
+ case "bool":
5450
+ zodType = z.boolean();
5451
+ break;
5452
+ case "date":
5453
+ case "datetime":
5454
+ zodType = z.date();
5455
+ break;
5456
+ default:
5457
+ zodType = z.string();
5458
+ break;
5459
+ }
5460
+ }
5461
+ if (column.isNull && !type.startsWith("nullable(")) {
5462
+ zodType = zodType.nullable();
5463
+ }
5464
+ return zodType;
5465
+ }
5466
+ function generateSelectSchema(table) {
5467
+ const shape = {};
5468
+ for (const key in table.$columns) {
5469
+ if (Object.prototype.hasOwnProperty.call(table.$columns, key)) {
5470
+ const column = table.$columns[key];
5471
+ shape[key] = mapClickHouseTypeToZod(column);
5472
+ }
5473
+ }
5474
+ return z.object(shape);
5475
+ }
5476
+ function generateInsertSchema(table) {
5477
+ const shape = {};
5478
+ for (const key in table.$columns) {
5479
+ if (Object.prototype.hasOwnProperty.call(table.$columns, key)) {
5480
+ const column = table.$columns[key];
5481
+ let zodType = mapClickHouseTypeToZod(column);
5482
+ const isOptionalBySchema = !column.isNull && (column.meta?.default !== undefined || column.meta?.defaultFn !== undefined || column.meta?.defaultExpr !== undefined || column.meta?.autoGenerate !== undefined);
5483
+ const isOptionalByNullable = column.isNull;
5484
+ if (isOptionalBySchema || isOptionalByNullable) {
5485
+ zodType = zodType.optional();
5486
+ } else {}
5487
+ shape[key] = zodType;
5488
+ }
5489
+ }
5490
+ return z.object(shape);
5491
+ }
5266
5492
  // src/modules/array.ts
5267
5493
  function arrayJoin(separator, col) {
5268
5494
  if (col) {
@@ -6269,7 +6495,21 @@ var t = {
6269
6495
  ring: (name) => new ClickHouseColumn(name, "Ring"),
6270
6496
  polygon: (name) => new ClickHouseColumn(name, "Polygon"),
6271
6497
  multiPolygon: (name) => new ClickHouseColumn(name, "MultiPolygon"),
6272
- enum: (name, values2) => new ClickHouseColumn(name, "String", true, { enumValues: values2 })
6498
+ enum: (name, values2) => new ClickHouseColumn(name, "String", true, { enumValues: values2 }),
6499
+ timestamps: () => ({
6500
+ created_at: new ClickHouseColumn("created_at", "DateTime").default("now()"),
6501
+ updated_at: new ClickHouseColumn("updated_at", "DateTime").default("now()")
6502
+ }),
6503
+ primaryUuid: (name) => {
6504
+ const colName = name ?? "id";
6505
+ return {
6506
+ [colName]: new ClickHouseColumn(colName, "UUID").autoGenerate().primaryKey().default("generateUUIDv4()")
6507
+ };
6508
+ },
6509
+ softDeletes: () => ({
6510
+ is_deleted: new ClickHouseColumn("is_deleted", "Bool").default(false),
6511
+ deleted_at: new ClickHouseColumn("deleted_at", "DateTime").nullable()
6512
+ })
6273
6513
  };
6274
6514
  function defineTable(tableName, columnsOrCallback, options) {
6275
6515
  const columns = typeof columnsOrCallback === "function" ? columnsOrCallback(t) : columnsOrCallback;
@@ -6306,104 +6546,6 @@ function relations(table2, relationsBuilder) {
6306
6546
  table2.$relations = rels;
6307
6547
  return rels;
6308
6548
  }
6309
- // src/codegen/zod.ts
6310
- import { z } from "zod";
6311
- function mapClickHouseTypeToZod(column) {
6312
- const type = column.type.toLowerCase();
6313
- let zodType;
6314
- if (type.startsWith("nullable(")) {
6315
- const innerType = column.type.slice("nullable(".length, -1);
6316
- const innerColumn = new ClickHouseColumn(column.name, innerType);
6317
- zodType = mapClickHouseTypeToZod(innerColumn).nullable();
6318
- } else if (type.startsWith("array(")) {
6319
- const innerType = column.type.slice("array(".length, -1);
6320
- const innerColumn = new ClickHouseColumn(column.name, innerType);
6321
- zodType = z.array(mapClickHouseTypeToZod(innerColumn));
6322
- } else if (type.startsWith("fixedstring")) {
6323
- zodType = z.string();
6324
- } else if (type.startsWith("enum")) {
6325
- if (column.meta?.enumValues) {
6326
- zodType = z.enum(column.meta.enumValues);
6327
- } else {
6328
- zodType = z.string();
6329
- }
6330
- } else if (type.startsWith("datetime64")) {
6331
- zodType = z.date();
6332
- } else if (type.startsWith("decimal")) {
6333
- zodType = z.string().refine((val) => !isNaN(parseFloat(val)), {
6334
- message: "Must be a valid decimal number string"
6335
- });
6336
- } else {
6337
- switch (type) {
6338
- case "uuid":
6339
- case "string":
6340
- case "json":
6341
- case "ipv4":
6342
- case "ipv6":
6343
- zodType = z.string();
6344
- break;
6345
- case "int8":
6346
- case "uint8":
6347
- case "int16":
6348
- case "uint16":
6349
- case "int32":
6350
- case "uint32":
6351
- case "float32":
6352
- case "float64":
6353
- zodType = z.number();
6354
- break;
6355
- case "int64":
6356
- case "uint64":
6357
- case "int128":
6358
- case "uint128":
6359
- case "int256":
6360
- case "uint256":
6361
- zodType = z.bigint();
6362
- break;
6363
- case "boolean":
6364
- case "bool":
6365
- zodType = z.boolean();
6366
- break;
6367
- case "date":
6368
- case "datetime":
6369
- zodType = z.date();
6370
- break;
6371
- default:
6372
- zodType = z.string();
6373
- break;
6374
- }
6375
- }
6376
- if (column.isNull && !type.startsWith("nullable(")) {
6377
- zodType = zodType.nullable();
6378
- }
6379
- return zodType;
6380
- }
6381
- function generateSelectSchema(table2) {
6382
- const shape = {};
6383
- for (const key in table2.$columns) {
6384
- if (Object.prototype.hasOwnProperty.call(table2.$columns, key)) {
6385
- const column = table2.$columns[key];
6386
- shape[key] = mapClickHouseTypeToZod(column);
6387
- }
6388
- }
6389
- return z.object(shape);
6390
- }
6391
- function generateInsertSchema(table2) {
6392
- const shape = {};
6393
- for (const key in table2.$columns) {
6394
- if (Object.prototype.hasOwnProperty.call(table2.$columns, key)) {
6395
- const column = table2.$columns[key];
6396
- let zodType = mapClickHouseTypeToZod(column);
6397
- const isOptionalBySchema = !column.isNull && (column.meta?.default !== undefined || column.meta?.defaultFn !== undefined || column.meta?.defaultExpr !== undefined || column.meta?.autoGenerate !== undefined);
6398
- const isOptionalByNullable = column.isNull;
6399
- if (isOptionalBySchema || isOptionalByNullable) {
6400
- zodType = zodType.optional();
6401
- } else {}
6402
- shape[key] = zodType;
6403
- }
6404
- }
6405
- return z.object(shape);
6406
- }
6407
6549
  // src/index.ts
6408
6550
  async function createClientFromConfig(databaseName = "default") {
6409
6551
  const config = await loadConfig();
@@ -6419,6 +6561,18 @@ async function createClientFromConfig(databaseName = "default") {
6419
6561
  };
6420
6562
  return createClientFromConfigObject(clientConfig);
6421
6563
  }
6564
+ function housekit(config, options) {
6565
+ return createHousekitClient({
6566
+ ...config,
6567
+ schema: options?.schema
6568
+ });
6569
+ }
6570
+ function createSchema(table2) {
6571
+ return {
6572
+ select: generateSelectSchema(table2),
6573
+ insert: generateInsertSchema(table2)
6574
+ };
6575
+ }
6422
6576
  async function loadConfig() {
6423
6577
  const root = process.cwd();
6424
6578
  const extensions = ["ts", "js", "mjs", "cjs"];
@@ -6728,6 +6882,7 @@ export {
6728
6882
  htmlEscape,
6729
6883
  housekitMetadataSchemas,
6730
6884
  housekitMetadataDefaults,
6885
+ housekit,
6731
6886
  hdfs,
6732
6887
  hasAny,
6733
6888
  hasAll,
@@ -6797,6 +6952,7 @@ export {
6797
6952
  dateDiff,
6798
6953
  dateAdd,
6799
6954
  createdAt,
6955
+ createSchema,
6800
6956
  createMigrationBridge,
6801
6957
  createHousekitClient,
6802
6958
  createClients,