@rwillians/exto 0.1.2 → 0.2.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.
@@ -184,6 +184,14 @@ export const number = () => define((input) => Number.isFinite(input)
184
184
  export const optional = (schema) => define((input) => input === undefined
185
185
  ? { value: undefined }
186
186
  : parse(schema, input));
187
+ /**
188
+ * @public Defines a standard schema for plain objects with string keys.
189
+ * @since 0.2.0
190
+ * @version 1
191
+ */
192
+ export const record = () => define((input) => typeof input === 'object' && input !== null && Object.getPrototypeOf(input) === Object.prototype
193
+ ? { value: input }
194
+ : fail('must be a plain object'));
187
195
  /**
188
196
  * @public Defines a standard schema for strings, optionally limited in
189
197
  * length.
@@ -8,6 +8,7 @@ declare class BunPostgres implements IDatabase {
8
8
  readonly dialect: Dialect;
9
9
  constructor(sql: SQL, loggers?: ILogger[], inTransaction?: boolean);
10
10
  execute(sql: string, params: unknown[]): Promise<Row[] & SQL.ResultMetadata>;
11
+ close(): Promise<void>;
11
12
  transaction<T>(fn: (tx: IDatabase) => Promise<T>): Promise<T>;
12
13
  }
13
14
  declare const connect: (url: string, { loggers }?: {
@@ -8,6 +8,7 @@ declare class BunSQLite implements IDatabase {
8
8
  readonly dialect: Dialect;
9
9
  constructor(conn: Database, loggers?: ILogger[], depth?: number);
10
10
  execute(sql: string, params: unknown[]): Promise<Row[]>;
11
+ close(): Promise<void>;
11
12
  transaction<T>(fn: (tx: IDatabase) => Promise<T>): Promise<T>;
12
13
  }
13
14
  declare const connect: (filename?: string, { loggers }?: {
@@ -1,7 +1,8 @@
1
1
  import * as std from './standard-schema';
2
2
  import { ValidationError } from './standard-schema';
3
- import { type CamelCase, type Expand } from './utils';
4
- type Primitive = 'BIGINT' | 'BINARY' | 'BOOLEAN' | 'CITEXT' | 'DATE' | 'DATETIME' | 'DECIMAL' | 'FLOAT' | 'INTEGER' | 'JSON' | 'SEQUENCE' | 'STRING' | 'TEXT' | 'UUID';
3
+ import { type Expand } from './utils';
4
+ type Primitive = 'BIGINT' | 'BINARY' | 'BOOLEAN' | 'CITEXT' | 'DATE' | 'DECIMAL' | 'FLOAT' | 'INTEGER' | 'JSON' | 'SEQUENCE' | 'STRING' | 'TEXT' | 'TIMESTAMP' | 'UUID';
5
+ type NumericType = 'BIGINT' | 'DECIMAL' | 'FLOAT' | 'INTEGER' | 'SEQUENCE';
5
6
  type ColumnProps<S extends std.Schema = std.Schema> = {
6
7
  type: Primitive;
7
8
  schema: S;
@@ -13,6 +14,8 @@ type ColumnProps<S extends std.Schema = std.Schema> = {
13
14
  nullable?: true;
14
15
  primaryKey?: true;
15
16
  unique?: true;
17
+ fields?: Columns;
18
+ many?: true;
16
19
  };
17
20
  type Column<K extends string = string, P extends ColumnProps = ColumnProps> = P & {
18
21
  key: K;
@@ -20,6 +23,7 @@ type Column<K extends string = string, P extends ColumnProps = ColumnProps> = P
20
23
  input: std.input<P['schema']>;
21
24
  output: std.output<P['schema']>;
22
25
  };
26
+ type Columns = Record<string, Column>;
23
27
  declare class ColumnBuilder<P extends ColumnProps> {
24
28
  readonly props: P;
25
29
  constructor(props: P);
@@ -29,7 +33,7 @@ declare class ColumnBuilder<P extends ColumnProps> {
29
33
  generated(): ColumnBuilder<Expand<P & {
30
34
  generated: true;
31
35
  }>>;
32
- nullable(): ColumnBuilder<Expand<Omit<P, "schema"> & {
36
+ optional(): ColumnBuilder<Expand<Omit<P, "schema"> & {
33
37
  nullable: true;
34
38
  schema: std.Schema<std.input<P['schema']> | null, std.output<P['schema']> | null>;
35
39
  }>>;
@@ -39,8 +43,35 @@ declare class ColumnBuilder<P extends ColumnProps> {
39
43
  unique(): ColumnBuilder<Expand<P & {
40
44
  unique: true;
41
45
  }>>;
46
+ unsigned(this: ColumnBuilder<P & {
47
+ type: 'INTEGER';
48
+ }>): ColumnBuilder<P>;
42
49
  }
43
50
  declare const column: <P extends ColumnProps>(props: P) => ColumnBuilder<P>;
51
+ type Shape = Record<string, ColumnBuilder<ColumnProps>>;
52
+ type ColumnsOfShape<S extends Shape> = {
53
+ [K in keyof S & string]: Column<K, S[K]['props']>;
54
+ };
55
+ declare const embedded: {
56
+ one: <S extends Shape>(shape: S) => ColumnBuilder<{
57
+ type: "JSON";
58
+ schema: std.Schema<Expand<(ColumnsOfShape<S> extends infer T_3 extends Columns ? { [K in keyof T_3 as ColumnsOfShape<S>[K] extends OmitOnInsert | OptionalOnInsert ? never : K]: T_3[K]["input"]; } : never) & (ColumnsOfShape<S> extends infer T_4 extends Columns ? { [K in keyof T_4 as ColumnsOfShape<S>[K] extends OmitOnInsert ? never : ColumnsOfShape<S>[K] extends OptionalOnInsert ? K : never]?: T_4[K]["input"] | undefined; } : never)>, Expand<ColumnsOfShape<S> extends infer T_5 extends Columns ? { [K in keyof T_5]: T_5[K]["output"]; } : never>>;
59
+ fields: ColumnsOfShape<S>;
60
+ }>;
61
+ many: <S extends Shape>(shape: S) => ColumnBuilder<{
62
+ type: "JSON";
63
+ schema: std.Schema<Expand<(ColumnsOfShape<S> extends infer T extends Columns ? { [K in keyof T as ColumnsOfShape<S>[K] extends OmitOnInsert | OptionalOnInsert ? never : K]: T[K]["input"]; } : never) & (ColumnsOfShape<S> extends infer T_1 extends Columns ? { [K in keyof T_1 as ColumnsOfShape<S>[K] extends OmitOnInsert ? never : ColumnsOfShape<S>[K] extends OptionalOnInsert ? K : never]?: T_1[K]["input"] | undefined; } : never)>[], Expand<ColumnsOfShape<S> extends infer T_2 extends Columns ? { [K in keyof T_2]: T_2[K]["output"]; } : never>[]>;
64
+ fields: ColumnsOfShape<S>;
65
+ many: true;
66
+ }>;
67
+ };
68
+ declare const defineType: <S extends std.Schema>({ primitive, schema }: {
69
+ primitive: Exclude<Primitive, 'JSON'>;
70
+ schema: S;
71
+ }) => ColumnBuilder<{
72
+ type: "BIGINT" | "BINARY" | "BOOLEAN" | "CITEXT" | "DATE" | "DECIMAL" | "FLOAT" | "INTEGER" | "SEQUENCE" | "STRING" | "TEXT" | "TIMESTAMP" | "UUID";
73
+ schema: S;
74
+ }>;
44
75
  declare const types: {
45
76
  bigint: () => ColumnBuilder<{
46
77
  type: "BIGINT";
@@ -62,10 +93,6 @@ declare const types: {
62
93
  type: "DATE";
63
94
  schema: std.Schema<string, string>;
64
95
  }>;
65
- datetime: () => ColumnBuilder<{
66
- type: "DATETIME";
67
- schema: std.Schema<string | number | Date, Date>;
68
- }>;
69
96
  decimal: (options?: {
70
97
  precision: number;
71
98
  scale: number;
@@ -92,6 +119,10 @@ declare const types: {
92
119
  type: "JSON";
93
120
  schema: S;
94
121
  }>;
122
+ record: () => ColumnBuilder<{
123
+ type: "JSON";
124
+ schema: std.Schema<Record<string, unknown>, Record<string, unknown>>;
125
+ }>;
95
126
  sequence: () => ColumnBuilder<{
96
127
  type: "SEQUENCE";
97
128
  schema: std.Schema<number, number>;
@@ -108,17 +139,75 @@ declare const types: {
108
139
  type: "TEXT";
109
140
  schema: std.Schema<string, string>;
110
141
  }>;
111
- uuid: () => ColumnBuilder<{
142
+ timestamp: () => ColumnBuilder<{
143
+ type: "TIMESTAMP";
144
+ schema: std.Schema<string | number | Date, Date>;
145
+ }>;
146
+ uuidv7: () => ColumnBuilder<{
112
147
  type: "UUID";
113
148
  schema: std.Schema<string, string>;
114
149
  }>;
115
150
  };
116
- type Columns = Record<string, Column>;
117
- type Table<N extends string = string, C extends Columns = Columns> = {
118
- name: N;
151
+ declare const NAME: unique symbol;
152
+ declare const ALIAS: unique symbol;
153
+ declare const NODE: unique symbol;
154
+ declare const COLUMNS: unique symbol;
155
+ declare const OPERAND: unique symbol;
156
+ declare const KEY: unique symbol;
157
+ type Op = '=' | '!=' | '<' | '<=' | '>' | '>=' | 'is' | 'is not';
158
+ type Node = {
159
+ kind: 'ref';
119
160
  alias: string;
120
- columns: C;
161
+ col: Column;
162
+ path: Column[];
163
+ } | {
164
+ kind: 'fragment';
165
+ strings: readonly string[];
166
+ values: unknown[];
167
+ } | {
168
+ kind: 'call';
169
+ fn: 'COUNT' | 'SUM';
170
+ arg: Node;
171
+ } | {
172
+ kind: 'compare';
173
+ lhs: Node;
174
+ op: Op;
175
+ rhs: Node | {
176
+ kind: 'value';
177
+ value: unknown;
178
+ };
179
+ } | {
180
+ kind: 'group';
181
+ op: 'AND' | 'OR';
182
+ nodes: Node[];
183
+ };
184
+ type Operand<A extends string = string, V = unknown, N extends string = string> = {
185
+ readonly [NODE]: Node;
186
+ readonly [OPERAND]: {
187
+ aliases: A;
188
+ value: V;
189
+ nulls: N;
190
+ };
191
+ };
192
+ type ColumnRef<A extends string = string, K extends string = string, V = unknown> = Operand<A, V, A> & {
193
+ readonly [KEY]: K;
194
+ };
195
+ type FieldRefs<A extends string, C extends Column> = C extends {
196
+ fields: infer F extends Columns;
197
+ } ? C extends {
198
+ many: true;
199
+ } ? {} : {
200
+ readonly [K in keyof F & string]: Operand<A, F[K]['output'], A> & FieldRefs<A, F[K]>;
201
+ } : {};
202
+ type RefTo<A extends string, K extends string, C extends Column> = ColumnRef<A, K, C['output']> & FieldRefs<A, C>;
203
+ type Table<N extends string = string, A extends string = string, C extends Columns = Columns> = {
204
+ readonly [NAME]: N;
205
+ readonly [ALIAS]: A;
206
+ readonly [COLUMNS]: C;
121
207
  };
208
+ type ColumnsOf<T extends Table> = T[typeof COLUMNS];
209
+ type AliasOf<T extends Table> = T[typeof ALIAS];
210
+ type Keys<T extends Table> = keyof ColumnsOf<T> & string;
122
211
  type OmitOnInsert = {
123
212
  generated: true;
124
213
  };
@@ -132,8 +221,7 @@ type OmitOnUpdate = {
132
221
  } | {
133
222
  primaryKey: true;
134
223
  };
135
- type NumericType = 'BIGINT' | 'DECIMAL' | 'FLOAT' | 'INTEGER';
136
- type Infer<C extends Columns> = Expand<{
224
+ type InferForSelect<C extends Columns> = Expand<{
137
225
  [K in keyof C]: C[K]['output'];
138
226
  }>;
139
227
  type InferForInsert<C extends Columns> = Expand<{
@@ -144,20 +232,31 @@ type InferForInsert<C extends Columns> = Expand<{
144
232
  type InferForUpdate<C extends Columns> = Expand<{
145
233
  [K in keyof C as C[K] extends OmitOnUpdate ? never : K]?: C[K]['input'];
146
234
  }>;
235
+ type Infer<M extends 'select' | 'insert' | 'update', T extends Table> = {
236
+ select: InferForSelect<ColumnsOf<T>>;
237
+ insert: InferForInsert<ColumnsOf<T>>;
238
+ update: InferForUpdate<ColumnsOf<T>>;
239
+ }[M];
147
240
  type NumericKeys<C extends Columns> = {
148
241
  [K in keyof C]: C[K] extends OmitOnUpdate ? never : C[K]['type'] extends NumericType ? K : never;
149
242
  }[keyof C];
150
- type DefinedTable<N extends string, C extends Columns> = Table<N, C> & {
151
- as: (alias: string) => DefinedTable<N, C>;
152
- infer: Infer<C>;
153
- inferForInsert: InferForInsert<C>;
154
- inferForUpdate: InferForUpdate<C>;
243
+ declare class Aliasable<N extends string, C extends Columns> {
244
+ as<B extends string>(alias: B): DefinedTable<N, B, C>;
245
+ }
246
+ type DefinedTable<N extends string, A extends string, C extends Columns> = Table<N, A, C> & {
247
+ readonly [K in keyof C & string]: RefTo<A, K, C[K]>;
248
+ } & Aliasable<N, C>;
249
+ declare const RESERVED: readonly ['as'];
250
+ type Reserved<S> = {
251
+ [K in keyof S & typeof RESERVED[number]]: never;
155
252
  };
156
- declare const defineTable: <N extends string, S extends Record<string, ColumnBuilder<ColumnProps>>>(name: N, shapeFn: (t: typeof types) => S) => DefinedTable<N, { [K in keyof S & string as CamelCase<K>]: Column<CamelCase<K>, S[K]['props']>; }>;
253
+ declare const defineTable: <N extends string, S extends Shape>(name: N, shape: S & NoInfer<Reserved<S>>) => DefinedTable<N, N, ColumnsOfShape<S>>;
254
+ declare const parse: <T extends Table>(table: T, input: unknown) => Infer<'insert', T>;
157
255
  type Codec = {
158
256
  encode: (value: any) => unknown;
159
257
  decode: (value: any) => unknown;
160
258
  };
259
+ type DialectName = 'postgres' | 'sqlite' | (string & {});
161
260
  /**
162
261
  * Everything that differs between database engines. SQL generation, param
163
262
  * collection, validation and encoding/decoding all live in the core.
@@ -165,13 +264,17 @@ type Codec = {
165
264
  * `generated` returns the DDL that makes the database generate the column's
166
265
  * value, or `undefined` when the database can't natively, in which case the
167
266
  * value is generated client-side on insert.
267
+ *
268
+ * `json` extracts a field nested in a JSON column, as an SQL value of the
269
+ * field's type: a JSON document itself when the field is a JSON one (a
270
+ * record, or embedded fields).
168
271
  */
169
- type DialectName = 'postgres' | 'sqlite' | (string & {});
170
272
  interface Dialect {
171
273
  name: DialectName;
172
274
  placeholder(index: number): string;
173
275
  type(column: Column): string;
174
276
  generated(column: Column): string | undefined;
277
+ json(sql: string, path: string[], type: Primitive): string;
175
278
  codecs: Record<Primitive, Codec>;
176
279
  }
177
280
  interface ILogger {
@@ -186,32 +289,43 @@ interface IDatabase {
186
289
  transaction<T>(fn: (tx: IDatabase) => Promise<T>): Promise<T>;
187
290
  }
188
291
  declare const exec: (db: IDatabase, sql: string, params?: unknown[]) => Promise<void>;
189
- type Op = '=' | '!=' | '<' | '<=' | '>' | '>=' | 'like' | 'not like' | 'in' | 'not in' | 'is' | 'is not';
190
- type ValueFor<V, O extends Op> = O extends 'is' | 'is not' ? null : O extends 'in' | 'not in' ? NonNullable<V>[] : O extends 'like' | 'not like' ? string : NonNullable<V>;
191
- type ExprNode = {
192
- key: string;
193
- op: Op;
194
- value: unknown;
195
- } | {
196
- group: 'AND' | 'OR';
197
- exprs: ExprNode[];
198
- };
199
- declare const COLUMNS: unique symbol;
200
- type Expr<C extends Columns> = ExprNode & {
201
- readonly [COLUMNS]?: (columns: C) => C;
202
- };
203
- declare const expr: (<C extends Columns, K extends keyof C & string, O extends Op>(key: K, op: O, value: ValueFor<C[K]['output'], O>) => Expr<C>) & {
204
- and: <C extends Columns>(exprs: Expr<C>[]) => Expr<C>;
205
- or: <C extends Columns>(exprs: Expr<C>[]) => Expr<C>;
292
+ type ValueOf<O> = O extends {
293
+ readonly [OPERAND]: {
294
+ value: infer V;
295
+ };
296
+ } ? V : never;
297
+ type AliasesOf<O> = O extends {
298
+ readonly [OPERAND]: {
299
+ aliases: infer A extends string;
300
+ };
301
+ } ? A : never;
302
+ type NullsOf<O> = O extends {
303
+ readonly [OPERAND]: {
304
+ nulls: infer N extends string;
305
+ };
306
+ } ? N : never;
307
+ type ValueIn<O, N extends string> = [NullsOf<O> & N] extends [never] ? ValueOf<O> : ValueOf<O> | null;
308
+ type ComparisonOp = '=' | '!=' | '<' | '<=' | '>' | '>=';
309
+ type ValueFor<V, O extends Op> = O extends 'is' | 'is not' ? null extends V ? null : never : NonNullable<V>;
310
+ type RhsFor<V, O extends Op, A extends string = string> = ValueFor<V, O> | (O extends ComparisonOp ? Operand<A, NonNullable<V> | null> : never);
311
+ type Condition<A extends string = string> = Operand<A, boolean, never>;
312
+ type ExprOf = {
313
+ <L extends Operand, O extends Op>(lhs: L, op: O, rhs: ValueFor<ValueOf<L>, O>): Condition<AliasesOf<L>>;
314
+ <L extends Operand, O extends ComparisonOp, R extends Operand<string, NonNullable<ValueOf<L>> | null>>(lhs: L, op: O, rhs: R): Condition<AliasesOf<L> | AliasesOf<R>>;
206
315
  };
207
- type Condition = {
208
- col: Column;
209
- op: Op;
210
- value: unknown;
211
- } | {
212
- group: 'AND' | 'OR';
213
- conditions: Condition[];
316
+ declare const expr: ExprOf & {
317
+ and: <E extends Condition>(exprs: E[]) => Condition<AliasesOf<E>>;
318
+ or: <E extends Condition>(exprs: E[]) => Condition<AliasesOf<E>>;
319
+ count: <O extends Operand>(arg: O) => Operand<AliasesOf<O>, number, never>;
320
+ sum: <O extends Operand<string, number | null>>(arg: O) => Operand<AliasesOf<O>, number, never>;
214
321
  };
322
+ declare const f: <V extends unknown[]>(strings: TemplateStringsArray, ...values: V) => Operand<AliasesOf<V[number]>, unknown, never>;
323
+ type Scope = Map<string, Table>;
324
+ type Returnable<T extends Table> = Keys<T> | ColumnRef<AliasOf<T>, Keys<T>>;
325
+ type ReturnedKey<R> = R extends string ? R : R extends {
326
+ readonly [KEY]: infer K extends string;
327
+ } ? K : never;
328
+ type Returned<T extends Table, R> = Pick<InferForSelect<ColumnsOf<T>>, ReturnedKey<R> & Keys<T>>;
215
329
  type Changes<C extends Columns> = {
216
330
  set?: InferForUpdate<C>;
217
331
  inc?: {
@@ -230,71 +344,80 @@ type InsertOptions<C extends Columns> = {
230
344
  declare class InsertBuilder<T extends Table> {
231
345
  private readonly table;
232
346
  private readonly rows;
233
- constructor(table: T, rows?: InferForInsert<T['columns']>[]);
234
- values(rows: InferForInsert<T['columns']> | InferForInsert<T['columns']>[]): InsertBuilder<T>;
235
- insert(db: IDatabase, options?: InsertOptions<T['columns']> & {
347
+ constructor(table: T, rows?: InferForInsert<ColumnsOf<T>>[]);
348
+ values(rows: InferForInsert<ColumnsOf<T>> | InferForInsert<ColumnsOf<T>>[]): InsertBuilder<T>;
349
+ insert(db: IDatabase, options?: InsertOptions<ColumnsOf<T>> & {
236
350
  returning?: true;
237
- }): Promise<Infer<T['columns']>[]>;
238
- insert(db: IDatabase, options: InsertOptions<T['columns']> & {
351
+ }): Promise<InferForSelect<ColumnsOf<T>>[]>;
352
+ insert(db: IDatabase, options: InsertOptions<ColumnsOf<T>> & {
239
353
  returning: false;
240
354
  }): Promise<undefined>;
241
- insert<K extends keyof T['columns'] & string>(db: IDatabase, options: InsertOptions<T['columns']> & {
242
- returning: K[];
243
- }): Promise<Expand<Pick<Infer<T['columns']>, K>>[]>;
355
+ insert<R extends Returnable<T>>(db: IDatabase, options: InsertOptions<ColumnsOf<T>> & {
356
+ returning: R[];
357
+ }): Promise<Returned<T, R>[]>;
244
358
  private renderConflict;
245
359
  }
246
360
  declare const into: <T extends Table>(table: T) => InsertBuilder<T>;
247
361
  type Direction = 'ASC' | 'DESC';
248
- type Query<T extends Table> = {
249
- table: T;
250
- select?: string[];
251
- where: Condition[];
252
- orderBy: [Column, Direction][];
362
+ type Field = [key: string, node: Node];
363
+ type Query = {
364
+ table: Table;
365
+ scope: Scope;
366
+ joins: {
367
+ table: Table;
368
+ on: Node;
369
+ }[];
370
+ select?: Field[];
371
+ where: Node[];
372
+ groupBy: Node[];
373
+ orderBy: [Node, Direction][];
253
374
  limit?: number;
254
375
  offset?: number;
255
376
  };
256
- type Keys<T extends Table> = keyof T['columns'] & string;
257
- declare class QueryBuilder<T extends Table, S extends Keys<T> = Keys<T>> {
377
+ declare class QueryBuilder<T extends Table, A extends string = AliasOf<T>, N extends string = never, R = InferForSelect<ColumnsOf<T>>> {
258
378
  private readonly query;
259
- constructor(query: Query<T>);
260
- select<K extends Keys<T>>(keys: K[]): QueryBuilder<T, K>;
261
- where<K extends Keys<T>, O extends Op>(key: K, op: O, value: ValueFor<T['columns'][K]['output'], O>): QueryBuilder<T, S>;
262
- where(expr: Expr<T['columns']>): QueryBuilder<T, S>;
263
- orderBy(keys: (Keys<T> | [Keys<T>, Direction])[]): QueryBuilder<T, S>;
264
- limit(n: number): QueryBuilder<T, S>;
265
- offset(n: number): QueryBuilder<T, S>;
266
- all(db: IDatabase): Promise<Expand<Pick<Expand<T["columns"] extends infer T_1 extends Columns ? { [K in keyof T_1]: T_1[K]["output"]; } : never>, S>>[]>;
267
- one(db: IDatabase): Promise<Expand<Pick<Expand<T["columns"] extends infer T_1 extends Columns ? { [K in keyof T_1]: T_1[K]["output"]; } : never>, S>>>;
379
+ constructor(query: Query);
380
+ select<P extends Record<string, Operand<A>>>(projection: P): QueryBuilder<T, A, N, Expand<{ [K in keyof P & string]: ValueIn<P[K], N>; }>>;
381
+ where<L extends Operand<A>, O extends Op>(lhs: L, op: O, rhs: RhsFor<ValueIn<L, N>, O, A>): QueryBuilder<T, A, N, R>;
382
+ where(condition: Condition<A>): QueryBuilder<T, A, N, R>;
383
+ leftJoin<J extends Table>(table: J, on: Condition<A | AliasOf<J>>): QueryBuilder<T, A | AliasOf<J>, N | AliasOf<J>, R>;
384
+ groupBy(operands: Operand<A>[]): QueryBuilder<T, A, N, R>;
385
+ orderBy(operands: (Operand<A> | [Operand<A>, Direction])[]): QueryBuilder<T, A, N, R>;
386
+ limit(n: number): QueryBuilder<T, A, N, R>;
387
+ offset(n: number): QueryBuilder<T, A, N, R>;
388
+ all(db: IDatabase): Promise<R[]>;
389
+ one(db: IDatabase): Promise<NonNullable<R> | null>;
268
390
  exists(db: IDatabase): Promise<boolean>;
269
391
  count(db: IDatabase): Promise<number>;
270
- update(db: IDatabase, changes: Changes<T['columns']> & {
392
+ update(db: IDatabase, changes: Changes<ColumnsOf<T>> & {
271
393
  returning: false;
272
394
  }): Promise<undefined>;
273
- update<K extends keyof T['columns'] & string>(db: IDatabase, changes: Changes<T['columns']> & {
395
+ update<K extends Returnable<T>>(db: IDatabase, changes: Changes<ColumnsOf<T>> & {
274
396
  returning: K[];
275
- }): Promise<Expand<Pick<Infer<T['columns']>, K>>[]>;
276
- update(db: IDatabase, changes: Changes<T['columns']> & {
397
+ }): Promise<Returned<T, K>[]>;
398
+ update(db: IDatabase, changes: Changes<ColumnsOf<T>> & {
277
399
  returning?: true;
278
- }): Promise<Infer<T['columns']>[]>;
400
+ }): Promise<InferForSelect<ColumnsOf<T>>[]>;
279
401
  delete(db: IDatabase, options: {
280
402
  returning: true;
281
- }): Promise<Infer<T['columns']>[]>;
282
- delete<K extends keyof T['columns'] & string>(db: IDatabase, options: {
403
+ }): Promise<InferForSelect<ColumnsOf<T>>[]>;
404
+ delete<K extends Returnable<T>>(db: IDatabase, options: {
283
405
  returning: K[];
284
- }): Promise<Expand<Pick<Infer<T['columns']>, K>>[]>;
406
+ }): Promise<Returned<T, K>[]>;
285
407
  delete(db: IDatabase, options?: {
286
408
  returning?: false;
287
409
  }): Promise<undefined>;
410
+ private fields;
288
411
  private renderSelect;
289
412
  private top;
290
- private assertUnbounded;
413
+ private assertPlain;
291
414
  }
292
- declare const from: <T extends Table>(table: T) => QueryBuilder<T, Keys<T>>;
415
+ declare const from: <T extends Table>(table: T) => QueryBuilder<T, AliasOf<T>, never, Expand<ColumnsOf<T> extends infer T_1 extends Columns ? { [K in keyof T_1]: T_1[K]["output"]; } : never>>;
293
416
  type IndexOptions = {
294
417
  ifNotExists?: boolean;
295
418
  name?: string;
296
419
  };
297
- declare const createIndex: <T extends Table>(table: T, keys: (keyof T['columns'] & string)[], { ifNotExists, name, unique, }?: IndexOptions & {
420
+ declare const createIndex: <T extends Table>(table: T, keys: Keys<T>[], { ifNotExists, name, unique, }?: IndexOptions & {
298
421
  unique?: boolean;
299
422
  }) => {
300
423
  onto: (db: IDatabase) => Promise<void>;
@@ -306,10 +429,10 @@ declare const create: {
306
429
  onto: (db: IDatabase) => Promise<void>;
307
430
  };
308
431
  index: typeof createIndex;
309
- uniqueIndex: <T extends Table>(table: T, keys: (keyof T['columns'] & string)[], options?: IndexOptions) => {
432
+ uniqueIndex: <T extends Table>(table: T, keys: Keys<T>[], options?: IndexOptions) => {
310
433
  onto: (db: IDatabase) => Promise<void>;
311
434
  };
312
435
  };
313
436
  type Migration = (db: IDatabase) => Promise<void>;
314
437
  declare const defineMigrations: (migrations: Record<string, Migration>) => (db: IDatabase) => Promise<void>;
315
- export { type Codec, type Column, type ColumnProps, type Dialect, type DialectName, type Expr, type IDatabase, type ILogger, type Migration, type Primitive, type Row, type Table, ValidationError, column, create, defineMigrations, defineTable as table, exec, expr, from, into, types as t, };
438
+ export { type Codec, type Column, type ColumnProps, type ColumnRef, type Dialect, type DialectName, type IDatabase, type ILogger, type Infer, type Migration, type Operand, type Primitive, type Row, type Table, ValidationError, column, create, defineMigrations, defineTable as table, defineType, embedded, exec, expr, f, from, into, parse, types as t, };
@@ -143,6 +143,12 @@ export declare const number: () => StandardSchemaV1<number, number>;
143
143
  * @version 1
144
144
  */
145
145
  export declare const optional: <T extends StandardSchemaV1>(schema: T) => StandardSchemaV1<input<T> | undefined, output<T> | undefined>;
146
+ /**
147
+ * @public Defines a standard schema for plain objects with string keys.
148
+ * @since 0.2.0
149
+ * @version 1
150
+ */
151
+ export declare const record: () => StandardSchemaV1<Record<string, unknown>, Record<string, unknown>>;
146
152
  /**
147
153
  * @public Defines a standard schema for strings, optionally limited in
148
154
  * length.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rwillians/exto",
3
- "description": "A zero-dependencies teeny tiny ORM for SQL databases.",
4
- "version": "0.1.2",
3
+ "description": "A teeny tiny, type-safe query builder for Bun, with adapters for SQLite and PostgreSQL.",
4
+ "version": "0.2.0",
5
5
  "author": "Rafael Willians <me@rwillians.com>",
6
6
  "license": "MIT",
7
7
  "publishConfig": {
@@ -12,12 +12,9 @@
12
12
  "url": "git://github.com/rwillians/exto.git"
13
13
  },
14
14
  "keywords": [
15
- "builder",
16
15
  "bun",
17
- "orm",
16
+ "migrations",
18
17
  "postgres",
19
- "query builder",
20
- "query",
21
18
  "sql",
22
19
  "sqlite",
23
20
  "type-safe",
@@ -27,7 +24,10 @@
27
24
  "type": "module",
28
25
  "module": "dist/esm/index.js",
29
26
  "main": "dist/cjs/index.js",
30
- "files": ["dist/", "LICENSE"],
27
+ "files": [
28
+ "dist/",
29
+ "LICENSE"
30
+ ],
31
31
  "exports": {
32
32
  ".": {
33
33
  "types": "./dist/types/index.d.ts",
@@ -57,9 +57,10 @@
57
57
  },
58
58
  "devDependencies": {
59
59
  "@types/bun": "latest",
60
+ "typescript": "^7.1.0-dev.20261114.1",
60
61
  "zod": "^4.6.7"
61
62
  },
62
63
  "peerDependencies": {
63
- "typescript": "^7"
64
+ "typescript": "^7.1.0-0"
64
65
  }
65
66
  }