uql-orm 0.47.0 → 0.48.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.
Files changed (36) hide show
  1. package/dist/browser/querier/httpQuerier.d.ts +2 -2
  2. package/dist/browser/type/clientQuerier.d.ts +3 -3
  3. package/dist/browser/uql-browser.min.js.map +2 -2
  4. package/dist/dialect/abstractDialect.d.ts +35 -1
  5. package/dist/dialect/abstractDialect.js +29 -0
  6. package/dist/dialect/abstractSqlDialect.d.ts +13 -5
  7. package/dist/dialect/abstractSqlDialect.js +45 -49
  8. package/dist/entity/decorator/members.d.ts +2 -0
  9. package/dist/entity/decorator/members.js +2 -0
  10. package/dist/entity/index.d.ts +1 -1
  11. package/dist/entity/index.js +1 -1
  12. package/dist/entity/metadata/definition.d.ts +11 -2
  13. package/dist/entity/metadata/definition.js +11 -0
  14. package/dist/mongo/mongoDialect.d.ts +36 -6
  15. package/dist/mongo/mongoDialect.js +116 -31
  16. package/dist/mongo/mongodbQuerier.d.ts +8 -3
  17. package/dist/mongo/mongodbQuerier.js +30 -11
  18. package/dist/querier/abstractQuerier.d.ts +33 -4
  19. package/dist/querier/abstractQuerier.js +92 -43
  20. package/dist/querier/abstractQuerierPool.d.ts +2 -2
  21. package/dist/querier/abstractSqlQuerier.d.ts +3 -2
  22. package/dist/querier/abstractSqlQuerier.js +132 -31
  23. package/dist/querier/relationCount.js +15 -9
  24. package/dist/type/entity.d.ts +1 -1
  25. package/dist/type/queryRaw.d.ts +1 -1
  26. package/dist/type/queryWhere.d.ts +11 -1
  27. package/dist/type/universalQuerier.d.ts +2 -2
  28. package/dist/util/dialect.util.d.ts +7 -0
  29. package/dist/util/dialect.util.js +14 -0
  30. package/dist/util/fieldOption.util.d.ts +1 -1
  31. package/dist/util/fieldOption.util.js +1 -1
  32. package/dist/util/relationQuery.util.d.ts +9 -6
  33. package/dist/util/relationQuery.util.js +11 -11
  34. package/dist/util/rowKey.util.d.ts +18 -4
  35. package/dist/util/rowKey.util.js +29 -5
  36. package/package.json +1 -1
@@ -35,13 +35,16 @@ export declare function targetKeyColumns(relOpts: Pick<RelationMeta, 'references
35
35
  /** `{ joined column: true }`: the projection or grouping that keeps a parent's key on the rows read. */
36
36
  export declare function joinedColumns(joins: readonly ParentJoin[]): Record<string, true>;
37
37
  /**
38
- * A parent row keyed by the columns a relation joins *from*, and a child or tally row keyed by the
39
- * columns it carries that key in. The two halves of matching children to parents: they must agree on
40
- * every column, so each is read through `joins` rather than through the parent's own key list - which
41
- * is the same set only for a to-many, and silently a different one otherwise.
38
+ * One side's columns: `'parent'` for the columns a parent is keyed by, `'joined'` for the ones a
39
+ * child or tally row carries that key in. Matching the two halves means agreeing on every column, so
40
+ * each side is read through `joins` rather than through the parent's own key list - the same set only
41
+ * for a to-many, and silently a different one otherwise. `keyof ParentJoin` is what keeps the two
42
+ * sides from being spelled apart.
43
+ *
44
+ * Lifted out of `joins` once per relation, not once per row: {@link rowKey} takes the list and reads
45
+ * each row itself, so a page of children costs one key each and nothing else.
42
46
  */
43
- export declare function parentRowKey(joins: readonly ParentJoin[], parent: unknown): string;
44
- export declare function joinedRowKey(joins: readonly ParentJoin[], row: unknown): string;
47
+ export declare function keyColumns(joins: readonly ParentJoin[], side: keyof ParentJoin): string[];
45
48
  /**
46
49
  * `{ joined column: every parent's value for it }`, the filter that fetches a whole page of parents'
47
50
  * children in one statement.
@@ -1,6 +1,5 @@
1
1
  import { QUERY_BOOLEAN_CLAUSES, QUERY_NUMBER_CLAUSES, QUERY_OBJECT_CLAUSES, QUERY_ROOT_NUMBER_CLAUSES, } from '../type/query.js';
2
2
  import { getKeys, someKey } from './object.util.js';
3
- import { rowKey } from './rowKey.util.js';
4
3
  /**
5
4
  * Whether a relation holds many rows per parent, so it cannot be joined into the parent's row. Takes
6
5
  * the one field it reads, so it answers for a relation being declared as well as for a resolved one.
@@ -37,19 +36,20 @@ export function targetKeyColumns(relOpts, parentKeyCount) {
37
36
  }
38
37
  /** `{ joined column: true }`: the projection or grouping that keeps a parent's key on the rows read. */
39
38
  export function joinedColumns(joins) {
40
- return Object.fromEntries(joins.map(({ joined }) => [joined, true]));
39
+ return Object.fromEntries(keyColumns(joins, 'joined').map((column) => [column, true]));
41
40
  }
42
41
  /**
43
- * A parent row keyed by the columns a relation joins *from*, and a child or tally row keyed by the
44
- * columns it carries that key in. The two halves of matching children to parents: they must agree on
45
- * every column, so each is read through `joins` rather than through the parent's own key list - which
46
- * is the same set only for a to-many, and silently a different one otherwise.
42
+ * One side's columns: `'parent'` for the columns a parent is keyed by, `'joined'` for the ones a
43
+ * child or tally row carries that key in. Matching the two halves means agreeing on every column, so
44
+ * each side is read through `joins` rather than through the parent's own key list - the same set only
45
+ * for a to-many, and silently a different one otherwise. `keyof ParentJoin` is what keeps the two
46
+ * sides from being spelled apart.
47
+ *
48
+ * Lifted out of `joins` once per relation, not once per row: {@link rowKey} takes the list and reads
49
+ * each row itself, so a page of children costs one key each and nothing else.
47
50
  */
48
- export function parentRowKey(joins, parent) {
49
- return rowKey(joins.map(({ parent: key }) => read(parent, key)));
50
- }
51
- export function joinedRowKey(joins, row) {
52
- return rowKey(joins.map(({ joined }) => read(row, joined)));
51
+ export function keyColumns(joins, side) {
52
+ return joins.map((join) => join[side]);
53
53
  }
54
54
  /**
55
55
  * `{ joined column: every parent's value for it }`, the filter that fetches a whole page of parents'
@@ -1,9 +1,23 @@
1
1
  /**
2
- * A row's key as a string, for matching rows to each other in a `Map`.
2
+ * A row's key as a string, for matching rows to each other in a {@link dataKeyed} lookup.
3
+ *
4
+ * Reads the columns off the row rather than taking their values, because every caller matches a
5
+ * whole page of rows against one fixed column list: taking an array would make each of them build
6
+ * one per row, which is what a page of 250 rows paid 56 KB for.
3
7
  *
4
8
  * Values are normalized before joining, not stringified: `String(date)` is locale- and
5
9
  * timezone-dependent, so two equal dates could key apart, and a `Uint8Array` stringifies to its
6
- * bytes with commas. Every part is included, so two rows agreeing on one column of a composite key
7
- * are not treated as one row.
10
+ * bytes with commas. Every column is included, so two rows agreeing on one column of a composite
11
+ * key are not treated as one row.
12
+ */
13
+ export declare function rowKey(row: unknown, columns: readonly string[]): string;
14
+ /**
15
+ * A lookup keyed by data rather than by a name this code chose, so a key that spells `__proto__` or
16
+ * `constructor` is an ordinary entry instead of the prototype: on `{}` those threw when a bucket was
17
+ * pushed to, and a `_count` tally under one silently read back as an object. Cheaper than a `Map`
18
+ * here, and faster than `{}`, which walks the prototype chain on every miss.
19
+ *
20
+ * It carries none of `Object.prototype`, which no type can say: index it and spread it, but calling
21
+ * `hasOwnProperty` on one type-checks and throws.
8
22
  */
9
- export declare function rowKey(values: readonly unknown[]): string;
23
+ export declare function dataKeyed<V>(): Record<string, V>;
@@ -1,15 +1,39 @@
1
1
  /** Separates the parts of a composite key: a unit separator, which no column value carries. */
2
2
  const KEY_SEPARATOR = '\u001f';
3
3
  /**
4
- * A row's key as a string, for matching rows to each other in a `Map`.
4
+ * A row's key as a string, for matching rows to each other in a {@link dataKeyed} lookup.
5
+ *
6
+ * Reads the columns off the row rather than taking their values, because every caller matches a
7
+ * whole page of rows against one fixed column list: taking an array would make each of them build
8
+ * one per row, which is what a page of 250 rows paid 56 KB for.
5
9
  *
6
10
  * Values are normalized before joining, not stringified: `String(date)` is locale- and
7
11
  * timezone-dependent, so two equal dates could key apart, and a `Uint8Array` stringifies to its
8
- * bytes with commas. Every part is included, so two rows agreeing on one column of a composite key
9
- * are not treated as one row.
12
+ * bytes with commas. Every column is included, so two rows agreeing on one column of a composite
13
+ * key are not treated as one row.
14
+ */
15
+ export function rowKey(row, columns) {
16
+ const values = row;
17
+ let key = '';
18
+ for (let i = 0; i < columns.length; i++) {
19
+ if (i) {
20
+ key += KEY_SEPARATOR;
21
+ }
22
+ key += keyPart(values[columns[i]]);
23
+ }
24
+ return key;
25
+ }
26
+ /**
27
+ * A lookup keyed by data rather than by a name this code chose, so a key that spells `__proto__` or
28
+ * `constructor` is an ordinary entry instead of the prototype: on `{}` those threw when a bucket was
29
+ * pushed to, and a `_count` tally under one silently read back as an object. Cheaper than a `Map`
30
+ * here, and faster than `{}`, which walks the prototype chain on every miss.
31
+ *
32
+ * It carries none of `Object.prototype`, which no type can say: index it and spread it, but calling
33
+ * `hasOwnProperty` on one type-checks and throws.
10
34
  */
11
- export function rowKey(values) {
12
- return values.map(keyPart).join(KEY_SEPARATOR);
35
+ export function dataKeyed() {
36
+ return Object.create(null);
13
37
  }
14
38
  function keyPart(value) {
15
39
  if (value instanceof Date) {
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.47.0",
6
+ "version": "0.48.0",
7
7
  "type": "module",
8
8
  "engines": {
9
9
  "node": ">=24"