uql-orm 0.31.0 → 0.31.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/README.md +10 -11
- package/dist/type/entity.d.ts +26 -10
- package/dist/type/utility.d.ts +2 -1
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -34,17 +34,16 @@ npm install uql-orm pg # or mysql2, mariadb, better-sqlite3, mongodb, @tursoda
|
|
|
34
34
|
|
|
35
35
|
That is the whole install ([setup](https://uql-orm.dev/getting-started)), and the [imperative API](https://uql-orm.dev/entities/imperative) skips decorators altogether.
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
37
|
+
<a href="https://uql-orm.dev">
|
|
38
|
+
<picture>
|
|
39
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://uql-orm.dev/demo-dark.webp">
|
|
40
|
+
<img src="https://uql-orm.dev/demo-light.webp" alt="A UQL query being typed: the compiler underlines the misspelled 'emial', then 'titel' three levels deep inside $populate">
|
|
41
|
+
</picture>
|
|
42
|
+
</a>
|
|
43
|
+
|
|
44
|
+
Our type-safety automatically prevents the bugs above, without codegen: the entity classes are the schema, pure TypeScript power. That demo editor is [on the home page](https://uql-orm.dev).
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
from the browser to the server. The same object runs on every supported database.
|
|
46
|
+
The query is just JSON: build it dynamically, store it, diff it, or send it from the browser to the server. The same object runs on every supported database.
|
|
48
47
|
|
|
49
48
|
## Why UQL?
|
|
50
49
|
|
|
@@ -71,7 +70,7 @@ Release notes live in [CHANGELOG.md](https://github.com/rogerpadilla/uql/blob/ma
|
|
|
71
70
|
|
|
72
71
|
## Made with UQL
|
|
73
72
|
|
|
74
|
-
**[Variability.ai](https://variability.ai)** - AI meeting
|
|
73
|
+
**[Variability.ai](https://variability.ai)** - AI meeting ntetaker and video summarizer for Zoom, Meet, Slack, and Teams. Instant summaries with action items in 35+ languages. Built by UQL's author.
|
|
75
74
|
|
|
76
75
|
Built something? [Open a PR](https://github.com/rogerpadilla/uql/blob/main/CONTRIBUTING.md) and add it here.
|
|
77
76
|
|
package/dist/type/entity.d.ts
CHANGED
|
@@ -13,17 +13,21 @@ export declare const idKey: unique symbol;
|
|
|
13
13
|
export type Key<E> = keyof E & string;
|
|
14
14
|
/**
|
|
15
15
|
* Infers the field names of an entity.
|
|
16
|
-
* Includes scalar fields, JSON fields,
|
|
16
|
+
* Includes scalar fields, JSON fields, scalar arrays (e.g. vector `number[]`) and arrays of JSON.
|
|
17
17
|
* The `-?` modifier strips optionality so the indexed access yields clean key unions
|
|
18
18
|
* (without it, optional properties leak `undefined` into the union).
|
|
19
19
|
*
|
|
20
|
+
* `readonly Json[]` is its own arm because the brand sits on the element, so the `Json` arm cannot
|
|
21
|
+
* see it. What keeps a to-many relation out of that arm is the weak-type check: `Json<unknown>` is
|
|
22
|
+
* all-optional, which a class with named properties is not assignable to.
|
|
23
|
+
*
|
|
20
24
|
* The check is bracketed so `any` resolves once rather than matching both this and
|
|
21
25
|
* {@link RelationKey}: an unbracketed `any extends X` satisfies either branch. It reads
|
|
22
26
|
* `readonly Scalar[]`, which every mutable one satisfies too, so declaring a vector or a scalar
|
|
23
27
|
* array `readonly` does not push the field over into {@link RelationKey}.
|
|
24
28
|
*/
|
|
25
29
|
export type FieldKey<E> = {
|
|
26
|
-
readonly [K in keyof E]-?: [NonNullable<E[K]>] extends [Scalar | readonly Scalar[] | Json] ? K : never;
|
|
30
|
+
readonly [K in keyof E]-?: [NonNullable<E[K]>] extends [Scalar | readonly Scalar[] | Json | readonly Json[]] ? K : never;
|
|
27
31
|
}[Key<E>];
|
|
28
32
|
/**
|
|
29
33
|
* Infers the relation names of an entity: whatever is left once its fields and its methods are
|
|
@@ -41,10 +45,21 @@ type IsJson<T> = '__json' extends keyof T ? true : false;
|
|
|
41
45
|
/** The payload `P` of a branded `Json<P>`, or `never` for any non-JSON type. */
|
|
42
46
|
type UnwrapJson<T> = IsJson<T> extends true ? (T extends Json<infer P> ? P : never) : never;
|
|
43
47
|
/**
|
|
44
|
-
* The
|
|
45
|
-
* `Unpacked`, a no-op for the non-array case
|
|
48
|
+
* The one branded value a field value `V` holds: `Json<T>` for both `Json<T>` and `Json<T>[]`, via
|
|
49
|
+
* `Unpacked`, a no-op for the non-array case.
|
|
50
|
+
*/
|
|
51
|
+
type JsonElement<V> = NonNullable<Unpacked<NonNullable<V>>>;
|
|
52
|
+
/** The `Json` payload of a field value `V`; `never` when `V` is not a JSON field. */
|
|
53
|
+
type JsonPayload<V> = UnwrapJson<JsonElement<V>>;
|
|
54
|
+
/**
|
|
55
|
+
* The fields carrying the `Json` brand, `never` on an entity with none - which is most of them, and
|
|
56
|
+
* what makes {@link JsonFieldPaths} collapse to `never` without deriving a path for anything. Tests
|
|
57
|
+
* the brand rather than the payload, whose extra `Json<infer P>` inference is only worth doing once
|
|
58
|
+
* a field is known to be JSON.
|
|
46
59
|
*/
|
|
47
|
-
type
|
|
60
|
+
type JsonFieldKey<E> = {
|
|
61
|
+
readonly [K in keyof E]-?: IsJson<JsonElement<E[K]>> extends true ? K : never;
|
|
62
|
+
}[Key<E>];
|
|
48
63
|
/**
|
|
49
64
|
* Recursively derives dot-notation key paths from a JSON payload type. Handles every shape at
|
|
50
65
|
* entry: an untyped (`unknown`) payload accepts any suffix via a `string` pattern, scalars are
|
|
@@ -57,15 +72,15 @@ type DeepJsonKeys<T, D extends unknown[] = []> = unknown extends T ? string : No
|
|
|
57
72
|
}[keyof NonNullable<T> & string];
|
|
58
73
|
/**
|
|
59
74
|
* Extracts dot-notation paths from `Json<T>` values, handling both scalar JSON
|
|
60
|
-
* and arrays of JSON (
|
|
75
|
+
* and arrays of JSON (`Json<{foo: string}>[]`, a column holding a list of documents).
|
|
61
76
|
* For `kind?: Json<{ public: number; theme: { color: string } }>`,
|
|
62
77
|
* produces `'kind.public' | 'kind.theme' | 'kind.theme.color'`.
|
|
63
78
|
* For `items?: Json<{id: string}>[]`, produces `'items.id'`.
|
|
64
79
|
* An untyped `Json<unknown>` field yields the scoped pattern `` `${K}.${string}` ``.
|
|
65
80
|
*/
|
|
66
81
|
export type JsonFieldPaths<E> = {
|
|
67
|
-
readonly [K in
|
|
68
|
-
}[
|
|
82
|
+
readonly [K in JsonFieldKey<E>]: `${K & string}.${DeepJsonKeys<JsonPayload<E[K]>>}`;
|
|
83
|
+
}[JsonFieldKey<E>];
|
|
69
84
|
/**
|
|
70
85
|
* The value type inside `T` at dot-path `P`; `unknown` when unresolvable (e.g. through a
|
|
71
86
|
* `Record<string, unknown>` leaf). Arrays are stepped into via their element type.
|
|
@@ -73,9 +88,10 @@ export type JsonFieldPaths<E> = {
|
|
|
73
88
|
type PathValue<T, P extends string> = unknown extends T ? unknown : NonNullable<T> extends readonly (infer U)[] ? PathValue<NonNullable<U>, P> : P extends `${infer K}.${infer Rest}` ? K extends keyof NonNullable<T> ? PathValue<NonNullable<T>[K], Rest> : unknown : P extends keyof NonNullable<T> ? NonNullable<T>[P] : unknown;
|
|
74
89
|
/**
|
|
75
90
|
* The value type at a JSON dot-path `P` of entity `E`; `unknown` when unresolvable, which keeps
|
|
76
|
-
* untyped paths fully permissive in `$where`.
|
|
91
|
+
* untyped paths fully permissive in `$where`. Gated on {@link JsonFieldKey}, the same predicate
|
|
92
|
+
* {@link JsonFieldPaths} derives its keys from, so a path that is offered always resolves a value.
|
|
77
93
|
*/
|
|
78
|
-
export type JsonFieldPathValue<E, P extends string> = P extends `${infer F}.${infer Rest}` ? F extends
|
|
94
|
+
export type JsonFieldPathValue<E, P extends string> = P extends `${infer F}.${infer Rest}` ? F extends JsonFieldKey<E> ? PathValue<JsonPayload<E[F]>, Rest> : unknown : unknown;
|
|
79
95
|
/**
|
|
80
96
|
* Extracts only the array-typed keys from `T`, mapping each to its element type via `Unpacked`.
|
|
81
97
|
* Used by `$push` and `$pull` to provide type-safe element targets.
|
package/dist/type/utility.d.ts
CHANGED
|
@@ -25,7 +25,8 @@ export type PrimaryKey = string | number | bigint;
|
|
|
25
25
|
/**
|
|
26
26
|
* Marker type for JSON/JSONB fields.
|
|
27
27
|
* Wrapping a field's TypeScript type with `Json<T>` ensures it is classified as a `FieldKey`
|
|
28
|
-
* (not a `RelationKey`), enabling type-safe usage in `$where`, `$select`, and `$sort`.
|
|
28
|
+
* (not a `RelationKey`), enabling type-safe usage in `$where`, `$select`, and `$sort`. A column
|
|
29
|
+
* holding a list of documents is `Json<T>[]`, also a field, whose dot-paths address the element.
|
|
29
30
|
*
|
|
30
31
|
* @example
|
|
31
32
|
* ```ts
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"homepage": "https://uql-orm.dev",
|
|
4
4
|
"description": "JSON-native TypeScript ORM for Node.js, Bun and Deno. Supports PostgreSQL, PGlite, MySQL, MariaDB, SQLite, CockroachDB, Turso, Neon, Cloudflare D1 and MongoDB. Queries are plain JSON, typed to the leaf.",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"version": "0.31.
|
|
6
|
+
"version": "0.31.2",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"engines": {
|
|
9
9
|
"node": ">=24"
|
|
@@ -129,13 +129,13 @@
|
|
|
129
129
|
}
|
|
130
130
|
},
|
|
131
131
|
"devDependencies": {
|
|
132
|
-
"@electric-sql/pglite": "0.5.
|
|
133
|
-
"@electric-sql/pglite-pgvector": "0.0.
|
|
132
|
+
"@electric-sql/pglite": "0.5.8",
|
|
133
|
+
"@electric-sql/pglite-pgvector": "0.0.9",
|
|
134
134
|
"@libsql/client": "^0.17.4",
|
|
135
135
|
"@neondatabase/serverless": "^1.1.0",
|
|
136
|
-
"@nestjs/common": "^
|
|
137
|
-
"@nestjs/core": "^
|
|
138
|
-
"@nestjs/testing": "^
|
|
136
|
+
"@nestjs/common": "^12.0.1",
|
|
137
|
+
"@nestjs/core": "^12.0.1",
|
|
138
|
+
"@nestjs/testing": "^12.0.1",
|
|
139
139
|
"@tursodatabase/database": "^0.7.2",
|
|
140
140
|
"@tursodatabase/serverless": "^1.4.0",
|
|
141
141
|
"@types/better-sqlite3": "^9.6.0",
|
|
@@ -145,8 +145,8 @@
|
|
|
145
145
|
"better-sqlite3": "^13.0.3",
|
|
146
146
|
"express": "^5.2.1",
|
|
147
147
|
"mariadb": "^3.5.3",
|
|
148
|
-
"mongodb": "^7.
|
|
149
|
-
"mysql2": "^3.
|
|
148
|
+
"mongodb": "^7.6.0",
|
|
149
|
+
"mysql2": "^3.24.2",
|
|
150
150
|
"pg": "^8.23.0",
|
|
151
151
|
"pg-query-stream": "^4.17.0",
|
|
152
152
|
"rxjs": "^7.8.2",
|