uql-orm 0.48.0 → 0.49.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.
@@ -1,4 +1,4 @@
1
- import type { EntityGetter, FieldOptions, FieldType, IdValue, RelationManyToManyOptions, RelationManyToOneOptions, RelationOneToManyOptions, RelationOneToOneOptions, TsTypeOf } from '../../type/index.js';
1
+ import type { EntityGetter, FieldOptions, FieldType, IdValue, NamedIdKey, RelationManyToManyOptions, RelationManyToOneOptions, RelationOneToManyOptions, RelationOneToOneOptions, TsTypeOf } from '../../type/index.js';
2
2
  import type { RejectIncompatible } from '../../util/index.js';
3
3
  /** A member decorator that also constrains the property it may be applied to. */
4
4
  type MemberDecorator<V> = (value: undefined, context: ClassFieldDecoratorContext<unknown, V>) => void;
@@ -54,16 +54,28 @@ export declare function Field<O extends FieldOptions<DeclaredValue<O>> & ({
54
54
  references: EntityGetter;
55
55
  }) & RejectUnknown<O, FieldOptions> & RejectIncompatible<O>>(opts: O): MemberDecorator<DeclaredValue<O> | undefined>;
56
56
  /**
57
- * Declares the primary key, checked the same way as `@Field`.
57
+ * A key the type level cannot name, reported on each `@Id` that leaves it unnamed. Where no `idKey`
58
+ * brand and no conventional name applies, `IdKey` falls back to every field, and `IdValue`,
59
+ * `EntityId` and every by-id method are then typed against a column that is not the key.
60
+ */
61
+ type KeyIsNamed<This> = [NamedIdKey<This>] extends [never] ? {
62
+ readonly __keyNeedsIdKeyBrand: true;
63
+ } : unknown;
64
+ /** {@link MemberDecorator} that also constrains the class, which is where a key is named. */
65
+ type IdDecorator<V> = <This>(value: undefined, context: ClassFieldDecoratorContext<This, V> & KeyIsNamed<This>) => void;
66
+ /**
67
+ * Declares the primary key, checked the same way as `@Field` and additionally against the class:
68
+ * a key not named `id`, `_id` or `uuid` has to be named by the `idKey` brand.
58
69
  *
59
70
  * @example `@Id({ type: Number }) id?: number;`
60
71
  * @example `@Id({ type: 'uuid', onInsert: uuidv7 }) id?: string;`
72
+ * @example `[idKey]?: 'pk';` beside `@Id({ type: Number }) pk?: number;`
61
73
  */
62
74
  export declare function Id<O extends FieldOptions<DeclaredValue<O>> & {
63
75
  type: FieldType;
64
76
  } & RejectUnknown<O, FieldOptions> & RejectIncompatible<O> & {
65
77
  readonly nullable?: false;
66
- }>(opts: O): MemberDecorator<DeclaredValue<O> | undefined>;
78
+ }>(opts: O): IdDecorator<DeclaredValue<O> | undefined>;
67
79
  /**
68
80
  * `E` comes from the mandatory `entity` getter, so the context can insist the property really holds that
69
81
  * entity: `@ManyToOne({ entity: () => Other })` on a `Company` field stops compiling, and a to-many
@@ -14,10 +14,12 @@ export function Field(opts) {
14
14
  };
15
15
  }
16
16
  /**
17
- * Declares the primary key, checked the same way as `@Field`.
17
+ * Declares the primary key, checked the same way as `@Field` and additionally against the class:
18
+ * a key not named `id`, `_id` or `uuid` has to be named by the `idKey` brand.
18
19
  *
19
20
  * @example `@Id({ type: Number }) id?: number;`
20
21
  * @example `@Id({ type: 'uuid', onInsert: uuidv7 }) id?: string;`
22
+ * @example `[idKey]?: 'pk';` beside `@Id({ type: Number }) pk?: number;`
21
23
  */
22
24
  export function Id(opts) {
23
25
  return (_value, context) => {
@@ -182,9 +182,10 @@ export type UpdatePayload<E> = {
182
182
  */
183
183
  export type FieldValue<E> = E[FieldKey<E>];
184
184
  /**
185
- * Infers the name of the key identifier on an entity
185
+ * The key's name where the entity states it: the `idKey` brand first, then the conventional names.
186
+ * `never` when nothing does, which is the case {@link IdKey} falls back on and `@Id` refuses.
186
187
  */
187
- export type IdKey<E> = (E extends {
188
+ export type NamedIdKey<E> = E extends {
188
189
  [idKey]?: infer K;
189
190
  } ? K & FieldKey<E> : E extends {
190
191
  _id?: unknown;
@@ -192,7 +193,11 @@ export type IdKey<E> = (E extends {
192
193
  id?: unknown;
193
194
  } ? 'id' & FieldKey<E> : E extends {
194
195
  uuid?: unknown;
195
- } ? 'uuid' & FieldKey<E> : FieldKey<E>) & string;
196
+ } ? 'uuid' & FieldKey<E> : never;
197
+ /**
198
+ * Infers the name of the key identifier on an entity
199
+ */
200
+ export type IdKey<E> = ([NamedIdKey<E>] extends [never] ? FieldKey<E> : NamedIdKey<E>) & string;
196
201
  /**
197
202
  * Infers the value of the key identifier on an entity.
198
203
  *
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "homepage": "https://uql-orm.dev",
4
4
  "description": "The JSON-native TypeScript ORM for Bun, Browsers, Edge, Deno, Node, Workers. 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.48.0",
6
+ "version": "0.49.0",
7
7
  "type": "module",
8
8
  "engines": {
9
9
  "node": ">=24"