@fougere/adapter-sql 0.2.0-alpha.2
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/LICENSE +21 -0
- package/README.md +18 -0
- package/dist/check.d.ts +41 -0
- package/dist/check.d.ts.map +1 -0
- package/dist/check.js +67 -0
- package/dist/check.js.map +1 -0
- package/dist/crud.d.ts +153 -0
- package/dist/crud.d.ts.map +1 -0
- package/dist/crud.js +458 -0
- package/dist/crud.js.map +1 -0
- package/dist/ddl.d.ts +87 -0
- package/dist/ddl.d.ts.map +1 -0
- package/dist/ddl.js +194 -0
- package/dist/ddl.js.map +1 -0
- package/dist/dialect.d.ts +54 -0
- package/dist/dialect.d.ts.map +1 -0
- package/dist/dialect.js +109 -0
- package/dist/dialect.js.map +1 -0
- package/dist/diff.d.ts +86 -0
- package/dist/diff.d.ts.map +1 -0
- package/dist/diff.js +168 -0
- package/dist/diff.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/setup.d.ts +37 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +40 -0
- package/dist/setup.js.map +1 -0
- package/dist/table.d.ts +169 -0
- package/dist/table.d.ts.map +1 -0
- package/dist/table.js +292 -0
- package/dist/table.js.map +1 -0
- package/dist/values.d.ts +32 -0
- package/dist/values.d.ts.map +1 -0
- package/dist/values.js +70 -0
- package/dist/values.js.map +1 -0
- package/package.json +56 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Fougere contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# @fougere/adapter-sql
|
|
2
|
+
> Entity → SQL tables, through Kysely
|
|
3
|
+
The SQL realization of the schema: the tables, the additive migration and the
|
|
4
|
+
per-entity scoped ORM. Four dialects — SQLite, PostgreSQL, MySQL, SQL Server.
|
|
5
|
+
|
|
6
|
+
Validation judges, storage realizes: this ORM passes no judgment on what a handler
|
|
7
|
+
hands it — it applies the `lifecycle` rules.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
```bash
|
|
11
|
+
pnpm add @fougere/adapter-sql
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
Part of [Fougere](https://github.com/chok/fougere) — one schema, a gradient from
|
|
17
|
+
monolith to distributed, the same user code.
|
|
18
|
+
Reference documentation: [the site](https://chok.github.io/fougere/) (en/fr).
|
package/dist/check.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shape → CHECK constraints.
|
|
3
|
+
*
|
|
4
|
+
* `oneOf`, `min`, `max` were declared on the field and read by the façade alone: a
|
|
5
|
+
* handler writing through the ORM put `status: 'brouillon'` in a column that declares
|
|
6
|
+
* two values, and nothing said a word. The rule was in the schema; no one held it on
|
|
7
|
+
* that path.
|
|
8
|
+
*
|
|
9
|
+
* So the storage learns what the shape already says. `validate` judges what a client
|
|
10
|
+
* proposes; this holds what anyone writes — including us.
|
|
11
|
+
*
|
|
12
|
+
* Only the keywords a database can decide alone. `pattern` and `format` are left to
|
|
13
|
+
* the façade: regex dialects diverge (POSIX here, PCRE there, nothing in SQLite
|
|
14
|
+
* without an extension), and a constraint that means something different per engine
|
|
15
|
+
* is worse than none.
|
|
16
|
+
*
|
|
17
|
+
* Every value is inlined with `sql.lit`, not bound: SQLite answers `parameters
|
|
18
|
+
* prohibited in CHECK constraints`, and a constraint is part of the schema rather
|
|
19
|
+
* than of a query. The values are the author's own literals — `oneOf('draft', …)`,
|
|
20
|
+
* `max: 160` — never anything a request carried, and Kysely escapes them.
|
|
21
|
+
*/
|
|
22
|
+
import { type Expression, type SqlBool } from 'kysely';
|
|
23
|
+
import type { ColumnDef } from './table.js';
|
|
24
|
+
/** What a column's shape can be checked for, beyond its type. */
|
|
25
|
+
export interface ShapeBounds {
|
|
26
|
+
enum?: readonly (string | number)[];
|
|
27
|
+
minLength?: number;
|
|
28
|
+
maxLength?: number;
|
|
29
|
+
minimum?: number;
|
|
30
|
+
maximum?: number;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The CHECK expression for one column, or nothing when its shape bounds nothing.
|
|
34
|
+
*
|
|
35
|
+
* A nullable column passes when it holds `null`: `NOT NULL` is the axis that decides
|
|
36
|
+
* presence, and stacking the two would make `optional()` unwritable.
|
|
37
|
+
*/
|
|
38
|
+
export declare function checkFor(column: ColumnDef): Expression<SqlBool> | undefined;
|
|
39
|
+
/** Read the bounds off a field's base shape — the keywords a database can decide. */
|
|
40
|
+
export declare function boundsOf(shape: Record<string, unknown> | undefined): ShapeBounds | undefined;
|
|
41
|
+
//# sourceMappingURL=check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../src/check.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,EAAO,KAAK,UAAU,EAAE,KAAK,OAAO,EAAE,MAAM,QAAQ,CAAC;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,iEAAiE;AACjE,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,SAAS,CAuB3E;AAED,qFAAqF;AACrF,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,CAU5F"}
|
package/dist/check.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shape → CHECK constraints.
|
|
3
|
+
*
|
|
4
|
+
* `oneOf`, `min`, `max` were declared on the field and read by the façade alone: a
|
|
5
|
+
* handler writing through the ORM put `status: 'brouillon'` in a column that declares
|
|
6
|
+
* two values, and nothing said a word. The rule was in the schema; no one held it on
|
|
7
|
+
* that path.
|
|
8
|
+
*
|
|
9
|
+
* So the storage learns what the shape already says. `validate` judges what a client
|
|
10
|
+
* proposes; this holds what anyone writes — including us.
|
|
11
|
+
*
|
|
12
|
+
* Only the keywords a database can decide alone. `pattern` and `format` are left to
|
|
13
|
+
* the façade: regex dialects diverge (POSIX here, PCRE there, nothing in SQLite
|
|
14
|
+
* without an extension), and a constraint that means something different per engine
|
|
15
|
+
* is worse than none.
|
|
16
|
+
*
|
|
17
|
+
* Every value is inlined with `sql.lit`, not bound: SQLite answers `parameters
|
|
18
|
+
* prohibited in CHECK constraints`, and a constraint is part of the schema rather
|
|
19
|
+
* than of a query. The values are the author's own literals — `oneOf('draft', …)`,
|
|
20
|
+
* `max: 160` — never anything a request carried, and Kysely escapes them.
|
|
21
|
+
*/
|
|
22
|
+
import { sql } from 'kysely';
|
|
23
|
+
/**
|
|
24
|
+
* The CHECK expression for one column, or nothing when its shape bounds nothing.
|
|
25
|
+
*
|
|
26
|
+
* A nullable column passes when it holds `null`: `NOT NULL` is the axis that decides
|
|
27
|
+
* presence, and stacking the two would make `optional()` unwritable.
|
|
28
|
+
*/
|
|
29
|
+
export function checkFor(column) {
|
|
30
|
+
const bounds = column.bounds;
|
|
31
|
+
if (!bounds)
|
|
32
|
+
return undefined;
|
|
33
|
+
const col = sql.ref(column.name);
|
|
34
|
+
const terms = [];
|
|
35
|
+
if (bounds.enum?.length) {
|
|
36
|
+
terms.push(sql `${col} in (${sql.join(bounds.enum.map((v) => sql.lit(v)))})`);
|
|
37
|
+
}
|
|
38
|
+
// Length, not value: a text bound is about the string, and `maxLength` is already
|
|
39
|
+
// spent on the column type where the dialect uses it (varchar(n)) — stating it
|
|
40
|
+
// again costs nothing and holds where the type does not (text columns).
|
|
41
|
+
if (bounds.minLength !== undefined)
|
|
42
|
+
terms.push(sql `length(${col}) >= ${sql.lit(bounds.minLength)}`);
|
|
43
|
+
if (bounds.maxLength !== undefined)
|
|
44
|
+
terms.push(sql `length(${col}) <= ${sql.lit(bounds.maxLength)}`);
|
|
45
|
+
if (bounds.minimum !== undefined)
|
|
46
|
+
terms.push(sql `${col} >= ${sql.lit(bounds.minimum)}`);
|
|
47
|
+
if (bounds.maximum !== undefined)
|
|
48
|
+
terms.push(sql `${col} <= ${sql.lit(bounds.maximum)}`);
|
|
49
|
+
if (terms.length === 0)
|
|
50
|
+
return undefined;
|
|
51
|
+
const all = terms.reduce((left, right) => sql `${left} and ${right}`);
|
|
52
|
+
return column.nullable ? sql `${col} is null or (${all})` : all;
|
|
53
|
+
}
|
|
54
|
+
/** Read the bounds off a field's base shape — the keywords a database can decide. */
|
|
55
|
+
export function boundsOf(shape) {
|
|
56
|
+
if (!shape)
|
|
57
|
+
return undefined;
|
|
58
|
+
const bounds = {};
|
|
59
|
+
if (Array.isArray(shape.enum) && shape.enum.length > 0)
|
|
60
|
+
bounds.enum = shape.enum;
|
|
61
|
+
for (const key of ['minLength', 'maxLength', 'minimum', 'maximum']) {
|
|
62
|
+
if (typeof shape[key] === 'number')
|
|
63
|
+
bounds[key] = shape[key];
|
|
64
|
+
}
|
|
65
|
+
return Object.keys(bounds).length > 0 ? bounds : undefined;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check.js","sourceRoot":"","sources":["../src/check.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,EAAE,GAAG,EAAiC,MAAM,QAAQ,CAAC;AAY5D;;;;;GAKG;AACH,MAAM,UAAU,QAAQ,CAAC,MAAiB;IACxC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IAC7B,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAE9B,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACjC,MAAM,KAAK,GAA0B,EAAE,CAAC;IAExC,IAAI,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;QACxB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAS,GAAG,GAAG,QAAQ,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACxF,CAAC;IACD,kFAAkF;IAClF,+EAA+E;IAC/E,wEAAwE;IACxE,IAAI,MAAM,CAAC,SAAS,KAAK,SAAS;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAS,UAAU,GAAG,QAAQ,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IAC7G,IAAI,MAAM,CAAC,SAAS,KAAK,SAAS;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAS,UAAU,GAAG,QAAQ,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IAC7G,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAS,GAAG,GAAG,OAAO,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACjG,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAS,GAAG,GAAG,OAAO,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAEjG,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAEzC,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,CAAS,GAAG,IAAI,QAAQ,KAAK,EAAE,CAAC,CAAC;IAE9E,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAS,GAAG,GAAG,gBAAgB,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;AAC1E,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,QAAQ,CAAC,KAA0C;IACjE,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAE7B,MAAM,MAAM,GAAgB,EAAE,CAAC;IAC/B,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,CAAC,IAAI,GAAG,KAAK,CAAC,IAAgB,CAAC;IAC7F,KAAK,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,CAAU,EAAE,CAAC;QAC5E,IAAI,OAAO,KAAK,CAAC,GAAG,CAAC,KAAK,QAAQ;YAAE,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,CAAW,CAAC;IACzE,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AAC7D,CAAC"}
|
package/dist/crud.d.ts
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SqlEntityOrm — per-entity ORM over Kysely, one implementation for every engine.
|
|
3
|
+
*
|
|
4
|
+
* Structurally matches @fougere/core's EntityOrm (duck typed, no dep). There is
|
|
5
|
+
* no generated table object: Kysely addresses tables and columns by name, so the
|
|
6
|
+
* entity stays the only description. The field↔column mapping is explicit rather
|
|
7
|
+
* than a global plugin — auth tables carry their own naming and must not be
|
|
8
|
+
* rewritten behind the caller's back.
|
|
9
|
+
*
|
|
10
|
+
* `create` and `update` re-read the row instead of using `RETURNING`: the
|
|
11
|
+
* contract is to hand back the COMPLETE row, including defaults realised by SQL.
|
|
12
|
+
* That also makes the code identical on MySQL and SQL Server, which have no
|
|
13
|
+
* `RETURNING` clause.
|
|
14
|
+
*/
|
|
15
|
+
import { type Kysely } from 'kysely';
|
|
16
|
+
import { type SchemaView, type SchemaSource } from '@fougere/schema';
|
|
17
|
+
import { type DialectName } from './dialect.js';
|
|
18
|
+
/** ListOptions — duplicated from @fougere/core to avoid a runtime dep. */
|
|
19
|
+
interface ListOptions {
|
|
20
|
+
limit?: number;
|
|
21
|
+
offset?: number;
|
|
22
|
+
page?: number;
|
|
23
|
+
after?: string;
|
|
24
|
+
orderBy?: string;
|
|
25
|
+
order?: 'asc' | 'desc';
|
|
26
|
+
count?: boolean;
|
|
27
|
+
}
|
|
28
|
+
interface ListResult<T> extends Array<T> {
|
|
29
|
+
total?: number;
|
|
30
|
+
endCursor?: string;
|
|
31
|
+
hasMore?: boolean;
|
|
32
|
+
}
|
|
33
|
+
interface SelectOption {
|
|
34
|
+
select?: SchemaView;
|
|
35
|
+
}
|
|
36
|
+
export declare class SqlEntityOrm {
|
|
37
|
+
private db;
|
|
38
|
+
private table;
|
|
39
|
+
private pk;
|
|
40
|
+
/** The axes `applyCreate`/`applyUpdate` read — held once, they are asked per write. */
|
|
41
|
+
private fields;
|
|
42
|
+
private selectFields?;
|
|
43
|
+
/** field → column and back; the entity names travel, the SQL names stay inside. */
|
|
44
|
+
private toColumn;
|
|
45
|
+
private toField;
|
|
46
|
+
/** field → the value pair a driver needs; only for the shapes a driver can't bind. */
|
|
47
|
+
private codecs;
|
|
48
|
+
/** How many keys one statement may carry here — see `Dialect.maxBindings`. */
|
|
49
|
+
private maxBindings;
|
|
50
|
+
/** How this engine spells an upsert, or `false` when it cannot — see `Dialect.upsert`. */
|
|
51
|
+
private upsertClause;
|
|
52
|
+
constructor(db: Kysely<any>, source: SchemaSource, tableName: string, selectFields?: Set<string>, dialect?: DialectName);
|
|
53
|
+
/** The Kysely instance this ORM wraps — no judge sits behind it. See EntityOrm.client. */
|
|
54
|
+
get client(): Kysely<any>;
|
|
55
|
+
/** Returns a scoped ORM that restricts all read results to the fields of the given schema. */
|
|
56
|
+
output(schema: SchemaView): SqlEntityOrm;
|
|
57
|
+
private resolveSelect;
|
|
58
|
+
private column;
|
|
59
|
+
/** The value a driver can bind — `true` becomes 1, a Date becomes its ISO string. */
|
|
60
|
+
private write;
|
|
61
|
+
/** Entity keys → column keys, and entity values → bindable values. */
|
|
62
|
+
private toRow;
|
|
63
|
+
/** Column keys → entity keys, and column values → the values the entity declares. */
|
|
64
|
+
private fromRow;
|
|
65
|
+
/**
|
|
66
|
+
* Apply a primary-key filter (simple or composite).
|
|
67
|
+
*
|
|
68
|
+
* The key crosses to the column exactly like every other value — `whereAll` states
|
|
69
|
+
* the rule two lines below and this did not follow it. It cost nothing while every
|
|
70
|
+
* generated key was a string; a key that holds a Date (`primary(created())`) inserted
|
|
71
|
+
* fine and then failed its own re-read, with the row already persisted.
|
|
72
|
+
*/
|
|
73
|
+
private wherePk;
|
|
74
|
+
private whereAll;
|
|
75
|
+
list(options?: ListOptions & SelectOption & {
|
|
76
|
+
where?: Record<string, unknown>;
|
|
77
|
+
}): Promise<ListResult<Record<string, unknown>>>;
|
|
78
|
+
/**
|
|
79
|
+
* One query for N keys, never N queries — what every page-level read stands on:
|
|
80
|
+
* a computed field, a relation, a resolver on the other side of a wire.
|
|
81
|
+
*
|
|
82
|
+
* A composite key has no list form: it is refused by name rather than answering a
|
|
83
|
+
* partial result that reads as complete.
|
|
84
|
+
*/
|
|
85
|
+
findByKeys(ids: readonly string[], options?: SelectOption): Promise<Map<string, Record<string, unknown>>>;
|
|
86
|
+
/**
|
|
87
|
+
* The other direction of a relation, in one query — see the port's `findAllByKeys`.
|
|
88
|
+
*
|
|
89
|
+
* The grouping key is read off the ROW rather than trusted from the request: a codec
|
|
90
|
+
* may write a value one way and read it back another, and a group keyed on the
|
|
91
|
+
* request's spelling would then be empty while the rows sit there.
|
|
92
|
+
*/
|
|
93
|
+
findAllByKeys(field: string, keys: readonly string[], options?: SelectOption): Promise<Map<string, Record<string, unknown>[]>>;
|
|
94
|
+
/**
|
|
95
|
+
* Write the row, or make the existing one look like this — one statement.
|
|
96
|
+
*
|
|
97
|
+
* The gesture an import needs and the port did not have: `create` throws on the
|
|
98
|
+
* second run (`UNIQUE constraint failed`), so re-reading anything meant deleting
|
|
99
|
+
* first. Measured pulling 500 rows from an API twice.
|
|
100
|
+
*
|
|
101
|
+
* Both lifecycles are realized, each on the side it belongs to: `applyCreate` fills
|
|
102
|
+
* what a first write owes (a generated key, `created()`, a declared default) and
|
|
103
|
+
* `applyUpdate` stamps what every write owes (`updated()`). On conflict the key and
|
|
104
|
+
* the creation stamps are left alone — a row keeps the moment it appeared, whatever
|
|
105
|
+
* later overwrites say.
|
|
106
|
+
*/
|
|
107
|
+
upsert(input: Record<string, unknown>, options?: SelectOption): Promise<Record<string, unknown>>;
|
|
108
|
+
/**
|
|
109
|
+
* Upsert a whole page in one statement — what an import writes through.
|
|
110
|
+
*
|
|
111
|
+
* Row by row, 500 rows were 500 statements (measured pulling an API); the shape of
|
|
112
|
+
* an import is a page, so the write should be one too. Sliced like every other batch,
|
|
113
|
+
* but by rows × COLUMNS: a statement binds values, not rows, so the ceiling divides.
|
|
114
|
+
*
|
|
115
|
+
* Answers how many rows were written and not the rows themselves. `create` hands back
|
|
116
|
+
* the complete row because a caller acts on it; an import acts on none of them, and
|
|
117
|
+
* re-reading a page to satisfy a symmetry nobody uses would double the work.
|
|
118
|
+
*/
|
|
119
|
+
upsertAll(inputs: readonly Record<string, unknown>[], _options?: SelectOption): Promise<number>;
|
|
120
|
+
/**
|
|
121
|
+
* The COLUMNS a later write must not touch: the key, and a stamp that is create-only.
|
|
122
|
+
* One that is also `update: 'now'` is the opposite — it exists to move.
|
|
123
|
+
*/
|
|
124
|
+
private frozenColumns;
|
|
125
|
+
findById(id: string | Record<string, unknown>, options?: SelectOption): Promise<Record<string, unknown> | undefined>;
|
|
126
|
+
findBy(criteria: Record<string, unknown>, options?: SelectOption): Promise<Record<string, unknown> | undefined>;
|
|
127
|
+
findAllBy(criteria: Record<string, unknown>, options?: SelectOption): Promise<Record<string, unknown>[]>;
|
|
128
|
+
/**
|
|
129
|
+
* One criteria object per statement — the oversized set is the one that splits.
|
|
130
|
+
*
|
|
131
|
+
* Only ONE criterion may be split: two split sets would need their cross product,
|
|
132
|
+
* which is a different query, so the second is refused rather than silently wrong.
|
|
133
|
+
*/
|
|
134
|
+
private refuseOversized;
|
|
135
|
+
private splitCriteria;
|
|
136
|
+
create(input: Record<string, unknown>, options?: SelectOption): Promise<Record<string, unknown>>;
|
|
137
|
+
update(id: string | Record<string, unknown>, input: Record<string, unknown>, options?: SelectOption): Promise<Record<string, unknown>>;
|
|
138
|
+
delete(id: string | Record<string, unknown>): Promise<boolean>;
|
|
139
|
+
}
|
|
140
|
+
export interface OrmFactoryOptions {
|
|
141
|
+
/** Override table name resolution. Default: camelCase → snake_case + 's'. */
|
|
142
|
+
tableName?: (entityName: string) => string;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Create an OrmFactory backed by Kysely — same call shape on every engine.
|
|
146
|
+
*
|
|
147
|
+
* ```ts
|
|
148
|
+
* const app = await createApp({ createContainer, ormFactory: createOrmFactory(db) });
|
|
149
|
+
* ```
|
|
150
|
+
*/
|
|
151
|
+
export declare function createOrmFactory(db: Kysely<any>, options?: OrmFactoryOptions, dialect?: DialectName): (entity: SchemaSource, name: string) => SqlEntityOrm;
|
|
152
|
+
export {};
|
|
153
|
+
//# sourceMappingURL=crud.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crud.d.ts","sourceRoot":"","sources":["../src/crud.ts"],"names":[],"mappings":"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"}
|