rado 1.0.7 → 1.0.9

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 (44) hide show
  1. package/README.md +1 -0
  2. package/dist/core/Column.js +3 -4
  3. package/dist/core/Database.d.ts +0 -1
  4. package/dist/core/Database.js +2 -5
  5. package/dist/core/Emitter.d.ts +2 -1
  6. package/dist/core/Emitter.js +8 -16
  7. package/dist/core/Query.js +2 -4
  8. package/dist/core/Resolver.js +5 -10
  9. package/dist/core/Selection.js +9 -14
  10. package/dist/core/Sql.d.ts +4 -1
  11. package/dist/core/Sql.js +29 -27
  12. package/dist/core/Table.js +2 -4
  13. package/dist/core/Virtual.js +3 -6
  14. package/dist/core/expr/Conditions.js +7 -14
  15. package/dist/core/expr/Include.js +1 -2
  16. package/dist/core/expr/Input.js +3 -6
  17. package/dist/core/expr/Json.d.ts +9 -3
  18. package/dist/core/expr/Json.js +16 -5
  19. package/dist/core/query/Delete.js +1 -2
  20. package/dist/core/query/Insert.js +2 -4
  21. package/dist/core/query/Select.js +1 -2
  22. package/dist/core/query/Update.js +1 -2
  23. package/dist/driver/better-sqlite3.js +1 -2
  24. package/dist/driver/mysql2.d.ts +1 -0
  25. package/dist/driver/mysql2.js +14 -9
  26. package/dist/driver/pg.js +4 -8
  27. package/dist/driver/pglite.js +1 -2
  28. package/dist/driver/sql.js.js +2 -4
  29. package/dist/mysql/columns.d.ts +2 -1
  30. package/dist/mysql/columns.js +4 -0
  31. package/dist/mysql/dialect.js +7 -6
  32. package/dist/mysql/transactions.js +1 -2
  33. package/dist/postgres/columns.d.ts +2 -2
  34. package/dist/postgres/columns.js +3 -3
  35. package/dist/postgres/dialect.js +9 -13
  36. package/dist/sqlite/dialect.js +9 -10
  37. package/dist/sqlite/diff.js +1 -2
  38. package/dist/sqlite/functions.d.ts +0 -2
  39. package/dist/sqlite/functions.js +0 -2
  40. package/dist/sqlite/transactions.js +2 -4
  41. package/dist/universal/columns.d.ts +7 -1
  42. package/dist/universal/columns.js +39 -6
  43. package/dist/universal/transactions.js +1 -2
  44. package/package.json +12 -15
package/README.md CHANGED
@@ -1,4 +1,5 @@
1
1
  [![npm](https://img.shields.io/npm/v/rado.svg)](https://npmjs.org/package/rado)
2
+ [![jsr](https://jsr.io/badges/@rado/rado)](https://jsr.io/@rado/rado)
2
3
 
3
4
  # rado
4
5
 
@@ -68,10 +68,9 @@ var column = new Proxy(createColumn, {
68
68
  get(target, method) {
69
69
  return target[method] ??= (...args) => {
70
70
  while (args.length > 0)
71
- if (args.at(-1) === void 0)
72
- args.pop();
73
- if (args.length === 0)
74
- return sql.unsafe(method);
71
+ if (args.at(-1) === void 0) args.pop();
72
+ else break;
73
+ if (args.length === 0) return sql.unsafe(method);
75
74
  return sql`${sql.unsafe(method)}(${sql.join(
76
75
  args.map(sql.inline),
77
76
  sql`, `
@@ -8,7 +8,6 @@ import { QueryBatch } from './Query.js';
8
8
  import { Resolver } from './Resolver.js';
9
9
  import type { Table } from './Table.js';
10
10
  export declare class Database<Meta extends QueryMeta = Either> extends Builder<Meta> implements HasResolver<Meta> {
11
- #private;
12
11
  driver: Driver;
13
12
  dialect: Dialect;
14
13
  diff: Diff;
@@ -49,8 +49,7 @@ var Database = class extends Builder {
49
49
  txGenerator(function* (tx) {
50
50
  for (const table of tables) {
51
51
  const diff = yield* computeDiff(table);
52
- if (diff.length > 0)
53
- yield* tx.batch(diff.map(sql.unsafe));
52
+ if (diff.length > 0) yield* tx.batch(diff.map(sql.unsafe));
54
53
  }
55
54
  })
56
55
  );
@@ -60,11 +59,9 @@ var Database = class extends Builder {
60
59
  }
61
60
  execute(input) {
62
61
  const emitter = this.dialect.emit(input);
63
- if (emitter.hasParams)
64
- throw new Error("Query has parameters");
62
+ if (emitter.hasParams) throw new Error("Query has parameters");
65
63
  return this.driver.exec(emitter.sql);
66
64
  }
67
- #transactionLock;
68
65
  transaction(run, options = {}) {
69
66
  return this.driver.transaction(
70
67
  (inner) => {
@@ -6,6 +6,7 @@ import { Sql } from './Sql.js';
6
6
  import type { TableApi } from './Table.js';
7
7
  import type { FieldData } from './expr/Field.js';
8
8
  import type { IncludeData } from './expr/Include.js';
9
+ import { type JsonPath } from './expr/Json.js';
9
10
  import type { Delete } from './query/Delete.js';
10
11
  import type { Insert } from './query/Insert.js';
11
12
  import type { SelectData } from './query/Select.js';
@@ -21,7 +22,7 @@ export declare abstract class Emitter {
21
22
  abstract emitIdentifier(value: string): void;
22
23
  abstract emitValue(value: unknown): void;
23
24
  abstract emitInline(value: unknown): void;
24
- abstract emitJsonPath(value: Array<number | string>): void;
25
+ abstract emitJsonPath(path: JsonPath): void;
25
26
  abstract emitPlaceholder(value: string): void;
26
27
  emitIdentifierOrSelf(value: string): void;
27
28
  selfName?: string;
@@ -17,8 +17,7 @@ var Emitter = class {
17
17
  }
18
18
  bind(inputs) {
19
19
  return this.params.map((param) => {
20
- if (param instanceof ValueParam)
21
- return this.processValue(param.value);
20
+ if (param instanceof ValueParam) return this.processValue(param.value);
22
21
  if (inputs && param.name in inputs)
23
22
  return this.processValue(inputs[param.name]);
24
23
  throw new Error(`Missing input for named parameter: ${param.name}`);
@@ -29,8 +28,7 @@ var Emitter = class {
29
28
  }
30
29
  emitIdentifierOrSelf(value) {
31
30
  if (value === Sql.SELF_TARGET) {
32
- if (!this.selfName)
33
- throw new Error("Self target not defined");
31
+ if (!this.selfName) throw new Error("Self target not defined");
34
32
  this.emitIdentifier(this.selfName);
35
33
  } else {
36
34
  this.emitIdentifier(value);
@@ -78,8 +76,7 @@ var Emitter = class {
78
76
  }
79
77
  emitDelete(deleteOp) {
80
78
  const { cte, from, where, returning } = getData(deleteOp);
81
- if (cte)
82
- this.emitWith(cte);
79
+ if (cte) this.emitWith(cte);
83
80
  const table = getTable(from);
84
81
  sql.query({
85
82
  deleteFrom: sql.identifier(table.name),
@@ -89,8 +86,7 @@ var Emitter = class {
89
86
  }
90
87
  emitInsert(insert) {
91
88
  const { cte, into, values, select, onConflict, returning } = getData(insert);
92
- if (cte)
93
- this.emitWith(cte);
89
+ if (cte) this.emitWith(cte);
94
90
  const table = getTable(into);
95
91
  const tableName = sql.identifier(table.name);
96
92
  sql.query({
@@ -113,8 +109,7 @@ var Emitter = class {
113
109
  limit,
114
110
  offset
115
111
  }) {
116
- if (cte)
117
- this.emitWith(cte);
112
+ if (cte) this.emitWith(cte);
118
113
  const prefix = distinctOn ? sql`distinct on (${sql.join(distinctOn, sql`, `)})` : distinct && sql`distinct`;
119
114
  sql.query({
120
115
  select: sql.join([prefix, select]),
@@ -133,8 +128,7 @@ var Emitter = class {
133
128
  emitUpdate(update) {
134
129
  const { cte, table, set, where, returning } = getData(update);
135
130
  const tableApi = getTable(table);
136
- if (cte)
137
- this.emitWith(cte);
131
+ if (cte) this.emitWith(cte);
138
132
  sql.query({
139
133
  update: sql.identifier(tableApi.name),
140
134
  set,
@@ -158,8 +152,7 @@ var Emitter = class {
158
152
  const wrapQuery = Boolean(data.limit || data.offset || data.orderBy);
159
153
  const innerQuery = sql.chunk("emitSelect", data);
160
154
  const inner = wrapQuery ? sql`select * from (${innerQuery})` : innerQuery;
161
- if (!data.select)
162
- throw new Error("No selection defined");
155
+ if (!data.select) throw new Error("No selection defined");
163
156
  const fields = data.select.fieldNames();
164
157
  const subject = jsonArray(
165
158
  ...fields.map((name) => sql`_.${sql.identifier(name)}`)
@@ -168,8 +161,7 @@ var Emitter = class {
168
161
  }
169
162
  emitUniversal(runtimes) {
170
163
  const sql2 = runtimes[this.runtime] ?? runtimes.default;
171
- if (!sql2)
172
- throw new Error("Unsupported runtime");
164
+ if (!sql2) throw new Error("Unsupported runtime");
173
165
  sql2.emitTo(this);
174
166
  }
175
167
  };
@@ -17,8 +17,7 @@ var Executable = class {
17
17
  *[Symbol.iterator]() {
18
18
  const interim = this.#execute();
19
19
  const isAsync = interim instanceof Promise;
20
- if (!isAsync)
21
- return interim;
20
+ if (!isAsync) return interim;
22
21
  let result;
23
22
  yield interim.then((v) => result = v);
24
23
  return result;
@@ -82,8 +81,7 @@ var Query = class extends Executable {
82
81
  }
83
82
  toSQL(db) {
84
83
  const resolver = db ? getResolver(db) : getData(this).resolver;
85
- if (!resolver)
86
- throw new Error("Query has no resolver");
84
+ if (!resolver) throw new Error("Query has no resolver");
87
85
  return resolver.toSQL(this);
88
86
  }
89
87
  };
@@ -51,8 +51,7 @@ var Batch = class {
51
51
  };
52
52
  for (let i = 0; i < this.#queries.length; i++) {
53
53
  const { mapRow } = this.#queries[i];
54
- if (!mapRow)
55
- continue;
54
+ if (!mapRow) continue;
56
55
  const rows = results[i];
57
56
  for (let j = 0; j < results[i].length; j++) {
58
57
  ctx.values = rows[i];
@@ -64,8 +63,7 @@ var Batch = class {
64
63
  };
65
64
  execute() {
66
65
  const results = this.#driver.batch(this.#queries);
67
- if (results instanceof Promise)
68
- return results.then(this.#transform);
66
+ if (results instanceof Promise) return results.then(this.#transform);
69
67
  return this.#transform(results);
70
68
  }
71
69
  };
@@ -81,8 +79,7 @@ var PreparedStatement = class {
81
79
  this.#specs = specs;
82
80
  }
83
81
  #transform = (rows) => {
84
- if (!this.#mapRow)
85
- return rows;
82
+ if (!this.#mapRow) return rows;
86
83
  const ctx = {
87
84
  values: void 0,
88
85
  index: 0,
@@ -97,14 +94,12 @@ var PreparedStatement = class {
97
94
  };
98
95
  all(inputs) {
99
96
  const rows = this.#stmt.values(this.#emitter.bind(inputs));
100
- if (rows instanceof Promise)
101
- return rows.then(this.#transform);
97
+ if (rows instanceof Promise) return rows.then(this.#transform);
102
98
  return this.#transform(rows);
103
99
  }
104
100
  get(inputs) {
105
101
  const rows = this.all(inputs);
106
- if (rows instanceof Promise)
107
- return rows.then((rows2) => rows2[0]);
102
+ if (rows instanceof Promise) return rows.then((rows2) => rows2[0]);
108
103
  return rows[0];
109
104
  }
110
105
  run(inputs) {
@@ -15,8 +15,7 @@ var SqlColumn = class {
15
15
  }
16
16
  result(ctx) {
17
17
  const value = ctx.values[ctx.index++];
18
- if (!this.sql.mapFromDriverValue)
19
- return value;
18
+ if (!this.sql.mapFromDriverValue) return value;
20
19
  return this.sql.mapFromDriverValue(value, ctx.specs);
21
20
  }
22
21
  };
@@ -42,8 +41,7 @@ var ObjectColumn = class {
42
41
  }
43
42
  }
44
43
  }
45
- if (isNullable)
46
- return null;
44
+ if (isNullable) return null;
47
45
  return result;
48
46
  }
49
47
  };
@@ -60,8 +58,7 @@ var Selection = class {
60
58
  }
61
59
  #defineColumn(nullable, input) {
62
60
  const expr = getSql(input);
63
- if (expr)
64
- return new SqlColumn(expr, getField(input)?.targetName);
61
+ if (expr) return new SqlColumn(expr, getField(input)?.targetName);
65
62
  return new ObjectColumn(
66
63
  nullable,
67
64
  Object.entries(input).map(([name, value]) => [
@@ -76,9 +73,9 @@ var Selection = class {
76
73
  #fieldNames(input, names, name) {
77
74
  const expr = getSql(input);
78
75
  if (expr) {
79
- const exprName = name ?? expr.alias;
80
- if (!exprName)
81
- throw new Error("Missing field name");
76
+ let exprName = name ?? expr.alias;
77
+ if (!exprName) throw new Error("Missing field name");
78
+ while (names.has(exprName)) exprName = `${exprName}_`;
82
79
  return [exprName];
83
80
  }
84
81
  return Object.entries(input).flatMap(
@@ -90,15 +87,13 @@ var Selection = class {
90
87
  if (expr) {
91
88
  let exprName = name ?? expr.alias;
92
89
  if (exprName) {
93
- while (names.has(exprName))
94
- exprName = `${exprName}_`;
90
+ while (names.has(exprName)) exprName = `${exprName}_`;
95
91
  names.add(exprName);
96
92
  if (hasField(input)) {
97
93
  const field = getField(input);
98
- if (field.fieldName === exprName)
99
- return expr;
94
+ if (field.fieldName === exprName) return expr;
100
95
  }
101
- return sql`${expr} as ${sql.identifier(exprName)}`;
96
+ return sql`${expr.forSelection()} as ${sql.identifier(exprName)}`;
102
97
  }
103
98
  return expr;
104
99
  }
@@ -3,6 +3,7 @@ import type { Emitter } from './Emitter.js';
3
3
  import { type HasSql, internalSql } from './Internal.js';
4
4
  import type { Runtime } from './MetaData.js';
5
5
  import type { FieldData } from './expr/Field.js';
6
+ import type { JsonPath } from './expr/Json.js';
6
7
  type EmitMethods = {
7
8
  [K in keyof Emitter as K extends `emit${string}` ? K : never]: Emitter[K];
8
9
  };
@@ -31,7 +32,8 @@ export declare class Sql<Value = unknown> implements HasSql<Value> {
31
32
  value(value: unknown): Sql<Value>;
32
33
  getValue(): Value | undefined;
33
34
  inline(value: unknown): Sql<Value>;
34
- jsonPath(path: Array<string | number>): Sql<Value>;
35
+ jsonPath(path: JsonPath): Sql<Value>;
36
+ forSelection(): Sql<Value>;
35
37
  placeholder(name: string): Sql<Value>;
36
38
  identifier(identifier: string): Sql<Value>;
37
39
  inlineValues(): Sql<Value>;
@@ -48,6 +50,7 @@ export declare namespace sql {
48
50
  export function placeholder<T>(name: string): Sql<T>;
49
51
  export function identifier<T>(identifier: string): Sql<T>;
50
52
  export function field<T>(field: FieldData): Sql<T>;
53
+ export function jsonPath<T>(path: JsonPath): Sql<T>;
51
54
  export function chunk<Type extends keyof EmitMethods>(type: Type, inner: Parameters<EmitMethods[Type]>[0]): Sql;
52
55
  export function universal<T>(runtimes: Partial<Record<Runtime | 'default', Sql<T>>>): Sql<T>;
53
56
  type QueryChunk = HasSql | undefined;
package/dist/core/Sql.js CHANGED
@@ -29,8 +29,7 @@ var Sql = class _Sql {
29
29
  return this;
30
30
  }
31
31
  unsafe(sql2) {
32
- if (sql2.length > 0)
33
- this.chunk("emitUnsafe", sql2);
32
+ if (sql2.length > 0) this.chunk("emitUnsafe", sql2);
34
33
  return this;
35
34
  }
36
35
  field(field) {
@@ -38,8 +37,7 @@ var Sql = class _Sql {
38
37
  }
39
38
  add(sql2) {
40
39
  const inner = getSql(sql2);
41
- if (!(inner instanceof _Sql))
42
- throw new Error("Invalid SQL");
40
+ if (!(inner instanceof _Sql)) throw new Error("Invalid SQL");
43
41
  this.#chunks.push(...inner.#chunks);
44
42
  return this;
45
43
  }
@@ -47,21 +45,28 @@ var Sql = class _Sql {
47
45
  return this.chunk("emitValue", value);
48
46
  }
49
47
  getValue() {
50
- if (this.#chunks.length !== 1)
51
- return;
48
+ if (this.#chunks.length !== 1) return;
52
49
  const chunk = this.#chunks[0];
53
- if (chunk?.type === "emitValue")
54
- return chunk.inner;
50
+ if (chunk?.type === "emitValue") return chunk.inner;
55
51
  }
56
52
  inline(value) {
57
53
  return this.chunk("emitInline", value);
58
54
  }
59
55
  jsonPath(path) {
60
- const last = this.#chunks.at(-1);
61
- if (last?.type === "emitJsonPath")
62
- last.inner.push(...path);
63
- else
64
- this.chunk("emitJsonPath", path);
56
+ const inner = path.target.#chunks[0];
57
+ if (inner?.type !== "emitJsonPath") return this.chunk("emitJsonPath", path);
58
+ const innerPath = inner.inner;
59
+ return this.chunk("emitJsonPath", {
60
+ ...innerPath,
61
+ segments: [...innerPath.segments, ...path.segments]
62
+ });
63
+ }
64
+ forSelection() {
65
+ if (this.#chunks.length === 1) {
66
+ const first = this.#chunks[0];
67
+ if (first.type === "emitJsonPath")
68
+ return sql.jsonPath({ ...first.inner, asSql: false }).mapWith(this);
69
+ }
65
70
  return this;
66
71
  }
67
72
  placeholder(name) {
@@ -73,8 +78,7 @@ var Sql = class _Sql {
73
78
  inlineValues() {
74
79
  return new _Sql(
75
80
  this.#chunks.map((chunk) => {
76
- if (chunk.type !== "emitValue")
77
- return chunk;
81
+ if (chunk.type !== "emitValue") return chunk;
78
82
  return new Chunk("emitInline", chunk.inner);
79
83
  })
80
84
  );
@@ -82,8 +86,7 @@ var Sql = class _Sql {
82
86
  inlineFields(withTableName) {
83
87
  return new _Sql(
84
88
  this.#chunks.flatMap((chunk) => {
85
- if (chunk.type !== "emitField")
86
- return [chunk];
89
+ if (chunk.type !== "emitField") return [chunk];
87
90
  const data = chunk.inner;
88
91
  if (withTableName)
89
92
  return [
@@ -99,8 +102,7 @@ var Sql = class _Sql {
99
102
  return sql.chunk("emitSelf", { name, inner: this });
100
103
  }
101
104
  emitTo(emitter) {
102
- for (const chunk of this.#chunks)
103
- emitter[chunk.type](chunk.inner);
105
+ for (const chunk of this.#chunks) emitter[chunk.type](chunk.inner);
104
106
  }
105
107
  };
106
108
  function sql(strings, ...inner) {
@@ -143,6 +145,10 @@ function sql(strings, ...inner) {
143
145
  return empty().field(field2);
144
146
  }
145
147
  sql2.field = field;
148
+ function jsonPath(path) {
149
+ return empty().jsonPath(path);
150
+ }
151
+ sql2.jsonPath = jsonPath;
146
152
  function chunk(type, inner) {
147
153
  return empty().chunk(type, inner);
148
154
  }
@@ -155,12 +161,9 @@ function sql(strings, ...inner) {
155
161
  return join(
156
162
  Object.entries(ast).map(([key, value2]) => {
157
163
  const statement = key.replace(/([A-Z])/g, " $1").toLocaleLowerCase();
158
- if (value2 === true)
159
- return sql2.unsafe(statement);
160
- if (Array.isArray(value2))
161
- value2 = join(value2);
162
- if (!key)
163
- return value2;
164
+ if (value2 === true) return sql2.unsafe(statement);
165
+ if (Array.isArray(value2)) value2 = join(value2);
166
+ if (!key) return value2;
164
167
  return value2 && sql2`${sql2.unsafe(statement)} ${value2}`;
165
168
  })
166
169
  );
@@ -170,8 +173,7 @@ function sql(strings, ...inner) {
170
173
  const parts = items.filter(Boolean);
171
174
  const sql3 = new Sql();
172
175
  for (let i = 0; i < parts.length; i++) {
173
- if (i > 0)
174
- sql3.add(separator);
176
+ if (i > 0) sql3.add(separator);
175
177
  sql3.add(parts[i]);
176
178
  }
177
179
  return sql3;
@@ -71,8 +71,7 @@ var TableApi = class extends TableData {
71
71
  const columnApi = getData(column);
72
72
  const { name: givenName } = columnApi;
73
73
  const field = new Field(this.aliased, givenName ?? name, columnApi);
74
- if (columnApi.json)
75
- return [name, jsonExpr(field)];
74
+ if (columnApi.json) return [name, jsonExpr(field)];
76
75
  return [name, field];
77
76
  })
78
77
  );
@@ -114,8 +113,7 @@ function table(name, columns, config, schemaName) {
114
113
  [internalTarget]: api.target(),
115
114
  ...api.fields()
116
115
  };
117
- if (config)
118
- api.config = config(table2);
116
+ if (config) api.config = config(table2);
119
117
  return table2;
120
118
  }
121
119
  function alias(table2, alias2) {
@@ -7,17 +7,14 @@ function virtual(alias, source) {
7
7
  if (source && hasSql(source)) {
8
8
  const expr = getSql(source);
9
9
  const name = expr.alias;
10
- if (!name)
11
- throw new Error("Cannot alias a virtual field without a name");
10
+ if (!name) throw new Error("Cannot alias a virtual field without a name");
12
11
  return Object.assign(new Field(alias, name, expr), target);
13
12
  }
14
13
  return new Proxy(target, {
15
14
  get(target2, field) {
16
- if (field in target2)
17
- return target2[field];
15
+ if (field in target2) return target2[field];
18
16
  const from = source?.[field];
19
- if (typeof field !== "string")
20
- return from;
17
+ if (typeof field !== "string") return from;
21
18
  return target2[field] = new Field(
22
19
  alias,
23
20
  field,
@@ -23,18 +23,14 @@ var arrayContained = binop("<@");
23
23
  var arrayOverlaps = binop("&&");
24
24
  function and(...conditions) {
25
25
  const inputs = conditions.filter((v) => v !== void 0).map(input);
26
- if (inputs.length === 0)
27
- return bool(sql`true`);
28
- if (inputs.length === 1)
29
- return bool(inputs[0]);
26
+ if (inputs.length === 0) return bool(sql`true`);
27
+ if (inputs.length === 1) return bool(inputs[0]);
30
28
  return bool(sql`(${sql.join(inputs, sql` and `)})`);
31
29
  }
32
30
  function or(...conditions) {
33
31
  const inputs = conditions.filter((v) => v !== void 0).map(input);
34
- if (inputs.length === 0)
35
- return bool(sql`true`);
36
- if (inputs.length === 1)
37
- return bool(inputs[0]);
32
+ if (inputs.length === 0) return bool(sql`true`);
33
+ if (inputs.length === 1) return bool(inputs[0]);
38
34
  return bool(sql`(${sql.join(inputs, sql` or `)})`);
39
35
  }
40
36
  function not(condition) {
@@ -43,8 +39,7 @@ function not(condition) {
43
39
  function inArray(left, right) {
44
40
  const value = (hasSql(right) ? getSql(right).getValue() : void 0) ?? right;
45
41
  if (Array.isArray(value)) {
46
- if (value.length === 0)
47
- return sql`false`;
42
+ if (value.length === 0) return sql`false`;
48
43
  return bool(sql`${input(left)} in (${sql.join(value.map(input), sql`, `)})`);
49
44
  }
50
45
  return bool(sql`${input(left)} in ${input(right)}`);
@@ -52,8 +47,7 @@ function inArray(left, right) {
52
47
  function notInArray(left, right) {
53
48
  const value = (hasSql(right) ? getSql(right).getValue() : void 0) ?? right;
54
49
  if (Array.isArray(value)) {
55
- if (value.length === 0)
56
- return sql`true`;
50
+ if (value.length === 0) return sql`true`;
57
51
  return bool(
58
52
  sql`${input(left)} not in (${sql.join(value.map(input), sql`, `)})`
59
53
  );
@@ -94,8 +88,7 @@ function when(...cases) {
94
88
  const [condition, result] = pair;
95
89
  return sql`when ${input(condition)} then ${input(result)}`;
96
90
  }
97
- if (index === cases.length - 1)
98
- return sql`else ${input(pair)}`;
91
+ if (index === cases.length - 1) return sql`else ${input(pair)}`;
99
92
  throw new Error("Unexpected else condition");
100
93
  })
101
94
  ),
@@ -15,8 +15,7 @@ var Include = class {
15
15
  const parsed = specs.parsesJson ? value : JSON.parse(value);
16
16
  if (first)
17
17
  return parsed ? select.mapRow({ values: parsed, index: 0, specs }) : null;
18
- if (!parsed)
19
- return [];
18
+ if (!parsed) return [];
20
19
  const rows = parsed;
21
20
  const ctx = {
22
21
  values: void 0,
@@ -2,12 +2,9 @@
2
2
  import { getSql, getTable, hasSql, hasTable } from "../Internal.js";
3
3
  import { sql } from "../Sql.js";
4
4
  function input(value) {
5
- if (typeof value !== "object" || value === null)
6
- return sql.value(value);
7
- if (hasTable(value))
8
- return sql.identifier(getTable(value).name);
9
- if (hasSql(value))
10
- return getSql(value);
5
+ if (typeof value !== "object" || value === null) return sql.value(value);
6
+ if (hasTable(value)) return sql.identifier(getTable(value).name);
7
+ if (hasSql(value)) return getSql(value);
11
8
  return sql.value(value);
12
9
  }
13
10
  export {
@@ -1,4 +1,5 @@
1
- import type { HasSql } from '../Internal.js';
1
+ import { type HasSql } from '../Internal.js';
2
+ import { type Sql } from '../Sql.js';
2
3
  import type { Input } from './Input.js';
3
4
  export interface JsonArrayHasSql<Value> extends HasSql<Array<Value>> {
4
5
  [index: number]: JsonExpr<Value>;
@@ -10,7 +11,12 @@ type NullableEach<T> = {
10
11
  [P in keyof T]: T[P] | null;
11
12
  };
12
13
  export type JsonExpr<Value> = [NonNullable<Value>] extends [Array<infer V>] ? JsonArrayHasSql<null extends Value ? V | null : V> : [NonNullable<Value>] extends [object] ? JsonRecordHasSql<null extends Value ? NullableEach<Value> : Value> : HasSql<Value>;
14
+ export interface JsonPath {
15
+ target: Sql;
16
+ segments: Array<number | string>;
17
+ asSql: boolean;
18
+ }
13
19
  export declare function jsonExpr<Value>(e: HasSql<Value>): JsonExpr<Value>;
14
- export declare function jsonAggregateArray(...args: Array<Input<unknown>>): import("../Sql.ts").Sql<unknown>;
15
- export declare function jsonArray(...args: Array<Input<unknown>>): import("../Sql.ts").Sql<unknown>;
20
+ export declare function jsonAggregateArray(...args: Array<Input<unknown>>): Sql<unknown>;
21
+ export declare function jsonArray(...args: Array<Input<unknown>>): Sql<unknown>;
16
22
  export {};
@@ -1,22 +1,33 @@
1
1
  // src/core/expr/Json.ts
2
+ import { getSql } from "../Internal.js";
2
3
  import { sql } from "../Sql.js";
3
4
  import { callFunction } from "./Functions.js";
4
5
  var INDEX_PROPERTY = /^\d+$/;
5
6
  function jsonExpr(e) {
6
7
  return new Proxy(e, {
7
8
  get(target, prop) {
8
- if (typeof prop !== "string")
9
- return Reflect.get(target, prop);
9
+ if (typeof prop !== "string") return Reflect.get(target, prop);
10
10
  const isNumber = INDEX_PROPERTY.test(prop);
11
- return jsonExpr(sql`${target}`.jsonPath([isNumber ? Number(prop) : prop]));
11
+ return jsonExpr(
12
+ sql.jsonPath({
13
+ target: getSql(target),
14
+ asSql: true,
15
+ segments: [isNumber ? Number(prop) : prop]
16
+ }).mapWith({
17
+ mapFromDriverValue(value, specs) {
18
+ return specs.parsesJson ? value : JSON.parse(value);
19
+ }
20
+ })
21
+ );
12
22
  }
13
23
  });
14
24
  }
15
25
  function jsonAggregateArray(...args) {
16
26
  return callFunction(
17
27
  sql.universal({
28
+ // Once sqlite 3.45+ is more commonplace we can use jsonb_group_array
18
29
  sqlite: sql`json_group_array`,
19
- postgres: sql`json_agg`,
30
+ postgres: sql`jsonb_agg`,
20
31
  mysql: sql`json_arrayagg`
21
32
  }),
22
33
  args
@@ -25,7 +36,7 @@ function jsonAggregateArray(...args) {
25
36
  function jsonArray(...args) {
26
37
  return callFunction(
27
38
  sql.universal({
28
- postgres: sql`json_build_array`,
39
+ postgres: sql`jsonb_build_array`,
29
40
  default: sql`json_array`
30
41
  }),
31
42
  args
@@ -16,8 +16,7 @@ var Delete = class extends Query {
16
16
  constructor(data) {
17
17
  super(data);
18
18
  this[internalData] = data;
19
- if (data.returning)
20
- this[internalSelection] = data.returning;
19
+ if (data.returning) this[internalSelection] = data.returning;
21
20
  }
22
21
  get [internalQuery]() {
23
22
  return sql.chunk("emitDelete", this);
@@ -18,8 +18,7 @@ var Insert = class extends Query {
18
18
  constructor(data) {
19
19
  super(data);
20
20
  this[internalData] = data;
21
- if (data.returning)
22
- this[internalSelection] = data.returning;
21
+ if (data.returning) this[internalSelection] = data.returning;
23
22
  }
24
23
  get [internalQuery]() {
25
24
  return sql.chunk("emitInsert", this);
@@ -87,8 +86,7 @@ var InsertInto = class {
87
86
  const { $default, mapToDriverValue } = getData(column);
88
87
  if (value !== void 0)
89
88
  return input(mapToDriverValue?.(value) ?? value);
90
- if ($default)
91
- return $default();
89
+ if ($default) return $default();
92
90
  return defaultKeyword;
93
91
  }),
94
92
  sql`, `
@@ -102,8 +102,7 @@ var Select = class _Select extends UnionBase {
102
102
  }
103
103
  get [internalSelection]() {
104
104
  const { select } = getData(this);
105
- if (!select)
106
- throw new Error("No selection defined");
105
+ if (!select) throw new Error("No selection defined");
107
106
  return select;
108
107
  }
109
108
  get [internalQuery]() {
@@ -18,8 +18,7 @@ var Update = class extends Query {
18
18
  constructor(data) {
19
19
  super(data);
20
20
  this[internalData] = data;
21
- if (data.returning)
22
- this[internalSelection] = data.returning;
21
+ if (data.returning) this[internalSelection] = data.returning;
23
22
  }
24
23
  get [internalQuery]() {
25
24
  return sql.chunk("emitUpdate", this);
@@ -18,8 +18,7 @@ var PreparedStatement = class {
18
18
  return this.stmt.get(...params);
19
19
  }
20
20
  values(params) {
21
- if (this.isSelection)
22
- return this.stmt.raw(true).all(...params);
21
+ if (this.isSelection) return this.stmt.raw(true).all(...params);
23
22
  this.stmt.run(...params);
24
23
  return [];
25
24
  }
@@ -4,6 +4,7 @@ import { AsyncDatabase, type TransactionOptions } from '../core/Database.js';
4
4
  import type { AsyncDriver, AsyncStatement, BatchQuery, PrepareOptions } from '../core/Driver.js';
5
5
  type Queryable = PromiseConnection | Pool | PoolConnection;
6
6
  declare class PreparedStatement implements AsyncStatement {
7
+ #private;
7
8
  private client;
8
9
  private sql;
9
10
  private name?;
@@ -9,17 +9,25 @@ var PreparedStatement = class {
9
9
  this.sql = sql;
10
10
  this.name = name;
11
11
  }
12
+ #transformParam = (param) => {
13
+ if (param instanceof Uint8Array) return Buffer.from(param);
14
+ return param;
15
+ };
12
16
  all(params) {
13
- return this.client.query(this.sql, params).then((res) => res[0]);
17
+ return this.client.query(this.sql, params.map(this.#transformParam)).then((res) => res[0]);
14
18
  }
15
19
  async run(params) {
16
- await this.client.query(this.sql, params);
20
+ await this.client.query(this.sql, params.map(this.#transformParam));
17
21
  }
18
22
  get(params) {
19
23
  return this.all(params).then((rows) => rows[0] ?? null);
20
24
  }
21
25
  values(params) {
22
- return this.client.query({ sql: this.sql, values: params, rowsAsArray: true }).then((res) => res[0]);
26
+ return this.client.query({
27
+ sql: this.sql,
28
+ values: params.map(this.#transformParam),
29
+ rowsAsArray: true
30
+ }).then((res) => res[0]);
23
31
  }
24
32
  free() {
25
33
  }
@@ -37,8 +45,7 @@ var Mysql2Driver = class _Mysql2Driver {
37
45
  return new PreparedStatement(this.client, sql, options?.name);
38
46
  }
39
47
  async close() {
40
- if ("end" in this.client)
41
- return this.client.end();
48
+ if ("end" in this.client) return this.client.end();
42
49
  }
43
50
  async batch(queries) {
44
51
  const transact = async (tx) => {
@@ -47,8 +54,7 @@ var Mysql2Driver = class _Mysql2Driver {
47
54
  results.push(await tx.prepare(sql).values(params));
48
55
  return results;
49
56
  };
50
- if (this.depth > 0)
51
- return transact(this);
57
+ if (this.depth > 0) return transact(this);
52
58
  return this.transaction(transact, {});
53
59
  }
54
60
  async transaction(run, options) {
@@ -60,8 +66,7 @@ var Mysql2Driver = class _Mysql2Driver {
60
66
  );
61
67
  if (this.depth === 0) {
62
68
  const setOptions = setTransaction(options);
63
- if (setOptions)
64
- await client.query(setOptions);
69
+ if (setOptions) await client.query(setOptions);
65
70
  }
66
71
  const result = await run(driver);
67
72
  await client.query(
package/dist/driver/pg.js CHANGED
@@ -53,10 +53,8 @@ var PgDriver = class _PgDriver {
53
53
  return new PreparedStatement(this.client, sql, options?.name);
54
54
  }
55
55
  async close() {
56
- if ("end" in this.client)
57
- return this.client.end();
58
- if ("release" in this.client)
59
- return this.client.release();
56
+ if ("end" in this.client) return this.client.end();
57
+ if ("release" in this.client) return this.client.release();
60
58
  }
61
59
  async batch(queries) {
62
60
  return this.transaction(async (tx) => {
@@ -70,8 +68,7 @@ var PgDriver = class _PgDriver {
70
68
  const client = "totalCount" in this.client ? await this.client.connect() : this.client;
71
69
  try {
72
70
  await client.query(this.depth > 0 ? `savepoint d${this.depth}` : "begin");
73
- if (this.depth === 0)
74
- await client.query(setTransaction(options));
71
+ if (this.depth === 0) await client.query(setTransaction(options));
75
72
  const result = await run(new _PgDriver(client, this.depth + 1));
76
73
  await client.query(
77
74
  this.depth > 0 ? `release savepoint d${this.depth}` : "commit"
@@ -83,8 +80,7 @@ var PgDriver = class _PgDriver {
83
80
  );
84
81
  throw error;
85
82
  } finally {
86
- if ("release" in client)
87
- client.release();
83
+ if ("release" in client) client.release();
88
84
  }
89
85
  }
90
86
  };
@@ -54,8 +54,7 @@ var PGliteDriver = class _PGliteDriver {
54
54
  results.push(await tx.prepare(sql).values(params));
55
55
  return results;
56
56
  };
57
- if (this.depth > 0)
58
- return transact(this);
57
+ if (this.depth > 0) return transact(this);
59
58
  return this.transaction(transact, {});
60
59
  }
61
60
  async transaction(run, options) {
@@ -10,14 +10,12 @@ var PreparedStatement = class {
10
10
  }
11
11
  *iterate(params) {
12
12
  this.stmt.bind(params);
13
- while (this.stmt.step())
14
- yield this.stmt.getAsObject();
13
+ while (this.stmt.step()) yield this.stmt.getAsObject();
15
14
  this.stmt.reset();
16
15
  }
17
16
  *iterateValues(params) {
18
17
  this.stmt.bind(params);
19
- while (this.stmt.step())
20
- yield this.stmt.get();
18
+ while (this.stmt.step()) yield this.stmt.get();
21
19
  this.stmt.reset();
22
20
  }
23
21
  all(params) {
@@ -1,4 +1,4 @@
1
- import { type Column, JsonColumn } from '../core/Column.js';
1
+ import { JsonColumn, type Column } from '../core/Column.js';
2
2
  type Precision = 0 | 1 | 2 | 3 | 4 | 5 | 6;
3
3
  export declare function bigint(name: string | undefined, options: {
4
4
  mode: 'number';
@@ -11,6 +11,7 @@ export declare function binary(name?: string, options?: {
11
11
  length?: number;
12
12
  }): Column<Uint8Array | null>;
13
13
  export declare function boolean(name?: string): Column<boolean | null>;
14
+ export declare function blob(name?: string): Column<Uint8Array | null>;
14
15
  export declare function char(name?: string, options?: {
15
16
  length: number;
16
17
  }): Column<string | null>;
@@ -13,6 +13,9 @@ function binary(name, options) {
13
13
  function boolean(name) {
14
14
  return column({ name, type: column.boolean() });
15
15
  }
16
+ function blob(name) {
17
+ return column({ name, type: column.blob() });
18
+ }
16
19
  function char(name, options) {
17
20
  return column({ name, type: column.char(options?.length) });
18
21
  }
@@ -125,6 +128,7 @@ function year(name) {
125
128
  export {
126
129
  bigint,
127
130
  binary,
131
+ blob,
128
132
  boolean,
129
133
  char,
130
134
  date,
@@ -16,14 +16,15 @@ var mysqlDialect = new Dialect(
16
16
  this.sql += "?";
17
17
  this.params.push(new ValueParam(value));
18
18
  }
19
- emitJsonPath(path) {
20
- this.sql += `->>${this.quoteString(
21
- `$${path.map((p) => typeof p === "number" ? `[${p}]` : `.${p}`).join("")}`
22
- )}`;
19
+ emitJsonPath({ target, asSql, segments }) {
20
+ target.emitTo(this);
21
+ this.sql += asSql ? "->>" : "->";
22
+ this.sql += this.quoteString(
23
+ `$${segments.map((p) => typeof p === "number" ? `[${p}]` : `.${p}`).join("")}`
24
+ );
23
25
  }
24
26
  emitInline(value) {
25
- if (value === null || value === void 0)
26
- return this.sql += "null";
27
+ if (value === null || value === void 0) return this.sql += "null";
27
28
  if (typeof value === "number" || typeof value === "boolean")
28
29
  return this.sql += value;
29
30
  if (typeof value === "string")
@@ -7,8 +7,7 @@ function startTransaction(options) {
7
7
  ].filter(Boolean).join(" ");
8
8
  }
9
9
  function setTransaction(options) {
10
- if (!options.isolationLevel)
11
- return;
10
+ if (!options.isolationLevel) return;
12
11
  return [
13
12
  "set transaction",
14
13
  options.isolationLevel && `isolation level ${options.isolationLevel}`
@@ -1,4 +1,4 @@
1
- import { type Column, JsonColumn } from '../core/Column.js';
1
+ import { JsonColumn, type Column } from '../core/Column.js';
2
2
  type Precision = 0 | 1 | 2 | 3 | 4 | 5 | 6;
3
3
  type IntervalFields = 'year' | 'month' | 'day' | 'hour' | 'minute' | 'second' | 'year to month' | 'day to hour' | 'day to minute' | 'day to second' | 'hour to minute' | 'hour to second' | 'minute to second';
4
4
  export declare function bigint(name: string | undefined, options: {
@@ -30,7 +30,7 @@ export declare function interval(name?: string, options?: {
30
30
  }): Column<string | null>;
31
31
  export declare function serial(name?: string): Column<number>;
32
32
  export declare function boolean(name?: string): Column<boolean | null>;
33
- export declare function blob(name?: string): Column<Uint8Array | null>;
33
+ export declare function bytea(name?: string): Column<Uint8Array | null>;
34
34
  export declare function text(name?: string): Column<string | null>;
35
35
  export declare function json<T>(name?: string): JsonColumn<T | null>;
36
36
  export declare function jsonb<T>(name?: string): JsonColumn<T | null>;
@@ -68,8 +68,8 @@ function serial(name) {
68
68
  function boolean(name) {
69
69
  return column({ name, type: column.boolean() });
70
70
  }
71
- function blob(name) {
72
- return column({ name, type: column.blob() });
71
+ function bytea(name) {
72
+ return column({ name, type: column.bytea() });
73
73
  }
74
74
  function text(name) {
75
75
  return column({ name, type: column.text() });
@@ -157,8 +157,8 @@ function varchar(name, options) {
157
157
  export {
158
158
  bigint,
159
159
  bigserial,
160
- blob,
161
160
  boolean,
161
+ bytea,
162
162
  char,
163
163
  cidr,
164
164
  date,
@@ -16,22 +16,18 @@ var postgresDialect = new Dialect(
16
16
  this.sql += `$${++this.paramIndex}`;
17
17
  this.params.push(new ValueParam(value));
18
18
  }
19
- emitJsonPath(path) {
20
- for (let i = 0; i < path.length; i++) {
21
- const access = path[i];
22
- if (i <= path.length - 2)
23
- this.sql += "->";
24
- else if (i === path.length - 1)
25
- this.sql += "->>";
26
- if (typeof access === "number")
27
- this.sql += access;
28
- else
29
- this.sql += this.quoteString(access);
19
+ emitJsonPath({ target, asSql, segments }) {
20
+ target.emitTo(this);
21
+ for (let i = 0; i < segments.length; i++) {
22
+ const access = segments[i];
23
+ if (i <= segments.length - 2) this.sql += "->";
24
+ else if (i === segments.length - 1) this.sql += asSql ? "->>" : "->";
25
+ if (typeof access === "number") this.sql += access;
26
+ else this.sql += this.quoteString(access);
30
27
  }
31
28
  }
32
29
  emitInline(value) {
33
- if (value === null || value === void 0)
34
- return this.sql += "null";
30
+ if (value === null || value === void 0) return this.sql += "null";
35
31
  if (typeof value === "number" || typeof value === "boolean")
36
32
  return this.sql += value;
37
33
  if (typeof value === "string")
@@ -18,20 +18,19 @@ var sqliteDialect = new Dialect(
18
18
  this.sql += "?";
19
19
  this.params.push(new ValueParam(value));
20
20
  }
21
- emitJsonPath(path) {
22
- this.sql += `->>${this.quoteString(
23
- `$${path.map((p) => typeof p === "number" ? `[${p}]` : `.${p}`).join("")}`
24
- )}`;
21
+ emitJsonPath({ target, asSql, segments }) {
22
+ target.emitTo(this);
23
+ this.sql += asSql ? "->>" : "->";
24
+ this.sql += this.quoteString(
25
+ `$${segments.map((p) => typeof p === "number" ? `[${p}]` : `.${p}`).join("")}`
26
+ );
25
27
  }
26
28
  emitInline(value) {
27
- if (value === null || value === void 0)
28
- return this.sql += "null";
29
- if (typeof value === "number")
30
- return this.sql += value;
29
+ if (value === null || value === void 0) return this.sql += "null";
30
+ if (typeof value === "number") return this.sql += value;
31
31
  if (typeof value === "string")
32
32
  return this.sql += this.quoteString(value);
33
- if (typeof value === "boolean")
34
- return this.sql += value ? "1" : "0";
33
+ if (typeof value === "boolean") return this.sql += value ? "1" : "0";
35
34
  this.sql += `json(${this.quoteString(JSON.stringify(value))})`;
36
35
  }
37
36
  emitPlaceholder(name) {
@@ -104,8 +104,7 @@ var sqliteDiff = (hasTable) => {
104
104
  sp.rollback(tableInfo);
105
105
  });
106
106
  } catch (err) {
107
- if (!(err instanceof Rollback))
108
- throw err;
107
+ if (!(err instanceof Rollback)) throw err;
109
108
  const localInstruction = err.data;
110
109
  const schemaInstruction = inline(tableApi.createTable());
111
110
  const stripStmt = (q) => q.slice("create table ".length);
@@ -5,8 +5,6 @@ import { type Input } from '../core/expr/Input.js';
5
5
  export declare const count: (x?: HasSql) => Sql<number>;
6
6
  /** The iif(X,Y,Z) function returns the value Y if X is true, and Z otherwise. The iif(X,Y,Z) function is logically equivalent to and generates the same bytecode as the CASE HasSql "CASE WHEN X THEN Y ELSE Z END".*/
7
7
  export declare const iif: <T>(x: Input<boolean>, y: Input<T>, z: Input<T>) => Sql<T>;
8
- /** Use the match operator for the FTS5 module */
9
- export declare const match: (table: HasTable, searchTerm: Input<string>) => Sql<boolean>;
10
8
  /** Returns a real value reflecting the accuracy of the current match */
11
9
  export declare const bm25: (table: HasTable, ...weights: Array<Input<number>>) => Sql<number>;
12
10
  /** The highlight() function returns a copy of the text from a specified column of the current row with extra markup text inserted to mark the start and end of phrase matches. */
@@ -4,7 +4,6 @@ import { Functions } from "../core/expr/Functions.js";
4
4
  import { input } from "../core/expr/Input.js";
5
5
  var count = Functions.count;
6
6
  var iif = Functions.iif;
7
- var match = Functions.match;
8
7
  var bm25 = Functions.bm25;
9
8
  var highlight = Functions.highlight;
10
9
  var snippet = Functions.snippet;
@@ -118,7 +117,6 @@ export {
118
117
  log2,
119
118
  lower,
120
119
  ltrim,
121
- match,
122
120
  max,
123
121
  min,
124
122
  mod,
@@ -3,8 +3,7 @@ var locks = /* @__PURE__ */ new WeakMap();
3
3
  function execTransaction(driver, depth, wrap, run, options) {
4
4
  const needsLock = options.async;
5
5
  const behavior = options.behavior ?? "deferred";
6
- if (!needsLock)
7
- return transact();
6
+ if (!needsLock) return transact();
8
7
  let trigger;
9
8
  const lock = new Promise((resolve) => trigger = resolve);
10
9
  const current = Promise.resolve(locks.get(driver));
@@ -14,8 +13,7 @@ function execTransaction(driver, depth, wrap, run, options) {
14
13
  try {
15
14
  driver.exec(depth > 0 ? `savepoint d${depth}` : `begin ${behavior}`);
16
15
  const result = run(wrap(depth + 1));
17
- if (result instanceof Promise)
18
- return result.then(release, rollback);
16
+ if (result instanceof Promise) return result.then(release, rollback);
19
17
  return release(result);
20
18
  } catch (error) {
21
19
  return rollback(error);
@@ -1,6 +1,12 @@
1
- import { type Column, JsonColumn } from '../core/Column.js';
1
+ import { JsonColumn, type Column } from '../core/Column.js';
2
2
  export declare function id(name?: string): Column<number>;
3
3
  export declare function text(name?: string): Column<string | null>;
4
+ export declare function varchar(name?: string, options?: {
5
+ length: number;
6
+ }): Column<string | null>;
4
7
  export declare function integer(name?: string): Column<number | null>;
8
+ export declare function number(name?: string): Column<number | null>;
5
9
  export declare function boolean(name?: string): Column<boolean | null>;
6
10
  export declare function json<T>(name?: string): JsonColumn<T>;
11
+ export declare function jsonb<T>(name?: string): JsonColumn<T>;
12
+ export declare function blob(name?: string): Column<Uint8Array | null>;
@@ -6,6 +6,18 @@ var idType = sql.universal({
6
6
  postgres: sql`integer generated always as identity`,
7
7
  mysql: sql`int not null auto_increment`
8
8
  });
9
+ var blobType = sql.universal({
10
+ postgres: sql`bytea`,
11
+ default: sql`blob`
12
+ });
13
+ var numberType = sql.universal({
14
+ mysql: sql`double`,
15
+ default: sql`numeric`
16
+ });
17
+ var jsonbType = sql.universal({
18
+ mysql: sql`json`,
19
+ default: sql`jsonb`
20
+ });
9
21
  function id(name) {
10
22
  return column({
11
23
  name,
@@ -16,18 +28,20 @@ function id(name) {
16
28
  function text(name) {
17
29
  return column({ name, type: column.text() });
18
30
  }
31
+ function varchar(name, options) {
32
+ return column({ name, type: column.varchar(options?.length) });
33
+ }
19
34
  function integer(name) {
20
35
  return column({ name, type: column.integer() });
21
36
  }
37
+ function number(name) {
38
+ return column({ name, type: numberType, mapFromDriverValue: Number });
39
+ }
22
40
  function boolean(name) {
23
41
  return column({
24
42
  name,
25
43
  type: column.boolean(),
26
- mapFromDriverValue(value) {
27
- if (typeof value === "number")
28
- return value === 1;
29
- return Boolean(value);
30
- }
44
+ mapFromDriverValue: Boolean
31
45
  });
32
46
  }
33
47
  function json(name) {
@@ -42,10 +56,29 @@ function json(name) {
42
56
  }
43
57
  });
44
58
  }
59
+ function jsonb(name) {
60
+ return new JsonColumn({
61
+ name,
62
+ type: jsonbType,
63
+ mapToDriverValue(value) {
64
+ return JSON.stringify(value);
65
+ },
66
+ mapFromDriverValue(value, { parsesJson }) {
67
+ return parsesJson ? value : JSON.parse(value);
68
+ }
69
+ });
70
+ }
71
+ function blob(name) {
72
+ return column({ name, type: blobType });
73
+ }
45
74
  export {
75
+ blob,
46
76
  boolean,
47
77
  id,
48
78
  integer,
49
79
  json,
50
- text
80
+ jsonb,
81
+ number,
82
+ text,
83
+ varchar
51
84
  };
@@ -12,8 +12,7 @@ function txGenerator(create) {
12
12
  }
13
13
  };
14
14
  const handle = ({ done, value }) => {
15
- if (done)
16
- return value;
15
+ if (done) return value;
17
16
  return next(typeof value === "function" ? tx.transaction(value) : value);
18
17
  };
19
18
  return next();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rado",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -26,8 +26,7 @@
26
26
  },
27
27
  "files": ["dist"],
28
28
  "devDependencies": {
29
- "@benmerckx/suite": "^0.3.0",
30
- "@biomejs/biome": "^1.6.1",
29
+ "@biomejs/biome": "^1.8.3",
31
30
  "@cloudflare/workers-types": "^4.20230628.0",
32
31
  "@electric-sql/pglite": "^0.1.5",
33
32
  "@sqlite.org/sqlite-wasm": "^3.42.0-build4",
@@ -36,19 +35,17 @@
36
35
  "@types/glob": "^8.0.0",
37
36
  "@types/pg": "^8.11.5",
38
37
  "@types/sql.js": "^1.4.2",
39
- "better-sqlite3": "^11.0.0",
40
- "esbuild": "^0.18.11",
41
- "glob": "^8.0.3",
38
+ "better-sqlite3": "^11.2.1",
39
+ "esbuild": "^0.23.1",
40
+ "glob": "^11.0.0",
42
41
  "madge": "^8.0.0",
43
- "mysql2": "^3.9.7",
44
- "pg": "^8.11.5",
45
- "rimraf": "^4.1.2",
46
- "sade": "^1.8.1",
42
+ "mysql2": "^3.11.0",
43
+ "pg": "^8.12.0",
47
44
  "speedscope": "^1.15.0",
48
- "sql.js": "^1.8.0",
49
- "sqlite3": "^5.1.6",
50
- "tsx": "^4.7.2",
51
- "typescript": "^5.4.5",
52
- "uvu": "^0.5.6"
45
+ "sql.js": "^1.11.0",
46
+ "sqlite3": "^5.1.7",
47
+ "tsx": "^4.19.0",
48
+ "typescript": "^5.5.4",
49
+ "@alinea/suite": "^0.4.0"
53
50
  }
54
51
  }