@jarenjs/linq 0.84.3 → 0.86.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.
package/docs/DB-CLIENT.md CHANGED
@@ -843,10 +843,10 @@ never builds one; the migration between two of them is
843
843
 
844
844
  ## 7. Cost
845
845
 
846
- `@jarenjs/linq/db` builds to **<!--fact:bundle.db-->675,752<!--/fact--> bytes** as a minified,
846
+ `@jarenjs/linq/db` builds to **<!--fact:bundle.db-->724,181<!--/fact--> bytes** as a minified,
847
847
  tree-shaken ESM bundle — the figure `scripts/check-tree-shaking.js`
848
848
  measures and `npm run test:tree-shaking` reports, published rounded
849
- (<!--fact:bundle.db.kb-->676<!--/fact--> kB) beside the other nine subpath prices in
849
+ (<!--fact:bundle.db.kb-->724<!--/fact--> kB) beside the other nine subpath prices in
850
850
  [docs/CONSUMING.md](../../../docs/CONSUMING.md).
851
851
 
852
852
  It is by far the largest of the ten, and the reason is §1.1's edge rather
@@ -37,7 +37,7 @@ is the index of those guides, and it is how a reader reaches any of them.
37
37
  | Document | Lines | What it writes, and when to open it |
38
38
  |---|---:|---|
39
39
  | [LINQ-FORMAT.md](LINQ-FORMAT.md) | 944 | this file, the binder and the family's **normative reference**: what a pen is, the rules all of them keep, the shared `JL01xx` table, and the cross-pen views derived from the guides it indexes. **Read it when** you want a rule that is true of every pen, an index of the documents, or one place to look up a method without knowing which pen owns it |
40
- | [QUERY-PEN.md](QUERY-PEN.md) | 1,752 | the chain, `.` — query documents (`jaren-query`) and the provider seam. **Read it when** you are querying data, or implementing a provider that answers a query document |
40
+ | [QUERY-PEN.md](QUERY-PEN.md) | 1,761 | the chain, `.` — query documents (`jaren-query`) and the provider seam. **Read it when** you are querying data, or implementing a provider that answers a query document |
41
41
  | [SCHEMA-PEN.md](SCHEMA-PEN.md) | 1,205 | `./schema` — JSON Schema 2020-12: the structural keywords, the constraints and the annotations, each with a method of its own, plus `$query`, `$defs`/`$ref` recursion and the normalizer's per-field predicates. **Read it when** you are describing the shape of data — for validation, for a form, or as the base of an entity |
42
42
  | [MODEL-PEN.md](MODEL-PEN.md) | 1,116 | `./model` — the `x-entity` vocabulary on JSON Schema, and the `$model` 0.1 document `openStore` accepts unchanged. **Read it when** you are declaring a store's entities, their keys and their relations |
43
43
  | [JSLT-PEN.md](JSLT-PEN.md) | 955 | `./jslt` — `$jslt` 0.1 stylesheets: the envelope and its rules, whose bodies are captured over the matched value. **Read it when** you are transforming one document into another |
@@ -204,7 +204,7 @@ and the bundle is the byte count the tree-shaking probe builds.
204
204
  | Document | Subpath | Lines | Mapping rows | Worked examples | Refusals | Bundle |
205
205
  |---|---|---:|---:|---:|---:|---:|
206
206
  | [LINQ-FORMAT.md](LINQ-FORMAT.md) | — | 944 | — | — | — | — |
207
- | [QUERY-PEN.md](QUERY-PEN.md) | `.` | 1,752 | 34 | 8 | 15 | 175,221 B |
207
+ | [QUERY-PEN.md](QUERY-PEN.md) | `.` | 1,761 | 34 | 8 | 15 | 175,560 B |
208
208
  | [SCHEMA-PEN.md](SCHEMA-PEN.md) | `./schema` | 1,205 | 82 | 10 | 4 | 35,285 B |
209
209
  | [MODEL-PEN.md](MODEL-PEN.md) | `./model` | 1,116 | 30 | 6 | 3 | 44,143 B |
210
210
  | [JSLT-PEN.md](JSLT-PEN.md) | `./jslt` | 955 | 17 | 8 | 3 | 18,424 B |
@@ -217,9 +217,9 @@ and the bundle is the byte count the tree-shaking probe builds.
217
217
  | [JTLT-PEN.md](JTLT-PEN.md) | `./jtlt` | 83 | 13 | 1 | 2 | 15,293 B |
218
218
  | [PROJECT-PEN.md](PROJECT-PEN.md) | `./project` | 81 | 9 | 1 | 1 | 13,793 B |
219
219
  | [CHARTS-PEN.md](CHARTS-PEN.md) | `./charts` | 94 | 21 | 1 | 1 | 15,582 B |
220
- | [DB-CLIENT.md](DB-CLIENT.md) | `./db` | 1,085 | 46 | 4 | 2 | 675,752 B |
220
+ | [DB-CLIENT.md](DB-CLIENT.md) | `./db` | 1,085 | 46 | 4 | 2 | 724,181 B |
221
221
  | [FORMULA-PEN.md](FORMULA-PEN.md) | `./formula` | 41 | 2 | — | — | 14,850 B |
222
- | **16 documents** | | **12,579** | **368** | **72** | | |
222
+ | **16 documents** | | **12,588** | **368** | **72** | | |
223
223
  <!--/fact-->
224
224
 
225
225
  A pen whose mapping rows are far below its worked examples is a pen
@@ -261,7 +261,7 @@ it and each document publishes it. The rounded column is what
261
261
  <!--fact:pens.cost-->
262
262
  | Subpath | Document | Bundle | Rounded |
263
263
  |---|---|---:|---:|
264
- | `@jarenjs/linq` | [QUERY-PEN.md](QUERY-PEN.md) | 175,221 B | 175 kB |
264
+ | `@jarenjs/linq` | [QUERY-PEN.md](QUERY-PEN.md) | 175,560 B | 176 kB |
265
265
  | `@jarenjs/linq/schema` | [SCHEMA-PEN.md](SCHEMA-PEN.md) | 35,285 B | 35 kB |
266
266
  | `@jarenjs/linq/model` | [MODEL-PEN.md](MODEL-PEN.md) | 44,143 B | 44 kB |
267
267
  | `@jarenjs/linq/jslt` | [JSLT-PEN.md](JSLT-PEN.md) | 18,424 B | 18 kB |
@@ -274,7 +274,7 @@ it and each document publishes it. The rounded column is what
274
274
  | `@jarenjs/linq/jtlt` | [JTLT-PEN.md](JTLT-PEN.md) | 15,293 B | 15 kB |
275
275
  | `@jarenjs/linq/project` | [PROJECT-PEN.md](PROJECT-PEN.md) | 13,793 B | 14 kB |
276
276
  | `@jarenjs/linq/charts` | [CHARTS-PEN.md](CHARTS-PEN.md) | 15,582 B | 16 kB |
277
- | `@jarenjs/linq/db` | [DB-CLIENT.md](DB-CLIENT.md) | 675,752 B | 676 kB |
277
+ | `@jarenjs/linq/db` | [DB-CLIENT.md](DB-CLIENT.md) | 724,181 B | 724 kB |
278
278
  | `@jarenjs/linq/formula` | [FORMULA-PEN.md](FORMULA-PEN.md) | 14,850 B | 15 kB |
279
279
  <!--/fact-->
280
280
 
package/docs/QUERY-PEN.md CHANGED
@@ -1683,14 +1683,14 @@ are shorter:
1683
1683
  ## 17. Cost
1684
1684
 
1685
1685
  A consumer importing `from` from `@jarenjs/linq` and calling one
1686
- terminal bundles **<!--fact:bundle.chain-->175,221<!--/fact--> bytes** (esbuild, ESM, minified, tree-shaken,
1686
+ terminal bundles **<!--fact:bundle.chain-->175,560<!--/fact--> bytes** (esbuild, ESM, minified, tree-shaken,
1687
1687
  `platform: 'neutral'`). The figure is measured by
1688
1688
  `scripts/check-tree-shaking.js`'s chain probe and compared with this
1689
1689
  section on every `npm run test:tree-shaking`: it is derived, never typed,
1690
1690
  and a stale one is red here rather than wrong in a document somebody
1691
1691
  reads.
1692
1692
 
1693
- Of that, **<!--fact:bundle.chain.own-->38,701<!--/fact--> bytes** are the chain's own modules — `sequence.js`,
1693
+ Of that, **<!--fact:bundle.chain.own-->39,040<!--/fact--> bytes** are the chain's own modules — `sequence.js`,
1694
1694
  `async.js`, `expression.js`, `document.js`, `provider.js`,
1695
1695
  `concurrency.js`, `errors.js` and `schema-of.js`. The remaining ~134 kB
1696
1696
  is the query ENGINE and the core it stands on: a chain's document has to
@@ -1716,8 +1716,8 @@ making:
1716
1716
 
1717
1717
  `docs/CONSUMING.md` states the rounded price of all ten subpaths in one
1718
1718
  table, each figure held equal to the same measurements. Two of its rows
1719
- are the ones to read together: the chain at <!--fact:bundle.chain.kb-->175<!--/fact--> kB and
1720
- `./db` at <!--fact:bundle.db.kb-->676<!--/fact--> kB.
1719
+ are the ones to read together: the chain at <!--fact:bundle.chain.kb-->176<!--/fact--> kB and
1720
+ `./db` at <!--fact:bundle.db.kb-->724<!--/fact--> kB.
1721
1721
  The client costs what the store costs, by construction, and the chain
1722
1722
  costs what running a query costs.
1723
1723
 
@@ -1726,7 +1726,7 @@ the reason is worth knowing: a bundler counts a shared module once, and
1726
1726
  the chain and every pen share the expression capture (`expression.js`)
1727
1727
  and the coded errors under it (`errors.js`, and `@jarenjs/core`'s error
1728
1728
  and object helpers). A consumer importing the chain AND the schema pen
1729
- bundles **<!--fact:bundle.chain.withSchemaPen-->199,375<!--/fact--> bytes** — **<!--fact:bundle.chain.shared-->11,131<!--/fact--> bytes** less than the sum of the
1729
+ bundles **<!--fact:bundle.chain.withSchemaPen-->199,716<!--/fact--> bytes** — **<!--fact:bundle.chain.shared-->11,129<!--/fact--> bytes** less than the sum of the
1730
1730
  figure above and [SCHEMA-PEN.md](SCHEMA-PEN.md#7-cost) §7's, which is
1731
1731
  what those shared modules weigh. The probe measures that pair too, so
1732
1732
  the saving is derived like everything else here. What the chain does NOT
@@ -1750,3 +1750,12 @@ never builds an index or runs a second ranker. Compile the emitted document with
1750
1750
  `createLexicalProvider` capability that a hand-written query uses. The ordinary
1751
1751
  sequence provider has no implicit search catalog. Filters/facets run before top-k,
1752
1752
  continuations bind the source snapshot, and `$search` remains regex-based.
1753
+
1754
+ For synchronous providers, iteration uses an available `syncQuery(document,
1755
+ options)` cursor and propagates early return to release it. Providers without
1756
+ that member retain their collecting behavior. SQLite entity planning flattens
1757
+ safe identity/object projection chains and projected joins followed by filters
1758
+ and ordering; it retains barriers around windows, grouping and inner ordering.
1759
+ Standalone supported physical min/max and integer sum/average use guarded native
1760
+ aggregates. Explicit SQLite null, collation, raw JSON text and byte semantics are
1761
+ available through [the data layer native surface](../../db/docs/SQLITE-RELATIONAL.md).
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@jarenjs/linq",
3
3
  "private": false,
4
- "version": "0.84.3",
4
+ "version": "0.86.0",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
7
7
  "types": "./types/index.d.ts",
@@ -108,13 +108,13 @@
108
108
  "prepack": "npm run build:types"
109
109
  },
110
110
  "dependencies": {
111
- "@jarenjs/core": "^0.84.3",
112
- "@jarenjs/json": "^0.84.3"
111
+ "@jarenjs/core": "^0.86.0",
112
+ "@jarenjs/json": "^0.86.0"
113
113
  },
114
114
  "peerDependencies": {
115
- "@jarenjs/db": "^0.84.3",
116
- "@jarenjs/formats": "^0.84.3",
117
- "@jarenjs/validate": "^0.84.3"
115
+ "@jarenjs/db": "^0.86.0",
116
+ "@jarenjs/formats": "^0.86.0",
117
+ "@jarenjs/validate": "^0.86.0"
118
118
  },
119
119
  "peerDependenciesMeta": {
120
120
  "@jarenjs/db": {
package/src/sequence.js CHANGED
@@ -507,6 +507,16 @@ export class Sequence {
507
507
  }
508
508
 
509
509
  * [Symbol.iterator]() {
510
+ if (this.#sourceKind === 'provider' && typeof this.#source.syncQuery === 'function') {
511
+ const document = this.toDocument();
512
+ const cursor = this.#source.syncQuery(document === this.#root
513
+ ? { $for: { it: this.#root }, $return: '$it' } : document,
514
+ { externals: Object.fromEntries(this.#params) });
515
+ if (cursor == null || typeof cursor[Symbol.iterator] !== 'function')
516
+ throw new LinqRuntimeError('JL2004', 'syncQuery() must return a synchronous iterable cursor');
517
+ yield* cursor;
518
+ return;
519
+ }
510
520
  yield* this.toArray();
511
521
  }
512
522
 
package/types/index.d.ts CHANGED
@@ -457,6 +457,8 @@ export interface Provider<T = unknown> {
457
457
  /** The item phantom: never present at runtime; what `from` infers `T` from. */
458
458
  readonly __item?: T;
459
459
  execute(document: unknown, options: { externals: Record<string, unknown> }): unknown;
460
+ /** Optional native synchronous cursor; iteration closes it on early return. */
461
+ syncQuery?(document: unknown, options: { externals: Record<string, unknown> }): Iterable<T>;
460
462
  /** The root expression the items are bound through (`'$.Post[*]'`);
461
463
  * absent means the whole input, `'$[*]'`. */
462
464
  readonly root?: string;
package/types/model.d.ts CHANGED
@@ -66,12 +66,24 @@ export interface PhysicalLayout {
66
66
  readonly table: string;
67
67
  readonly kind?: 'table' | 'view';
68
68
  readonly keys?: readonly string[];
69
+ readonly constraints?: readonly object[];
70
+ readonly indexes?: readonly object[];
71
+ readonly triggers?: readonly object[];
72
+ readonly strict?: boolean;
73
+ readonly withoutRowid?: boolean;
69
74
  readonly columns: Readonly<Record<string, {
70
75
  readonly name: string;
71
76
  readonly codec: 'text' | 'integer' | 'number' | 'boolean' | 'json' | 'date' | 'datetime' | 'epoch-ms' | 'bigint' | 'decimal' | 'blob-hex';
72
77
  readonly null: 'null' | 'absent' | 'reject';
73
78
  readonly default?: 'database';
74
79
  readonly generated?: boolean;
80
+ readonly type?: 'INTEGER' | 'REAL' | 'TEXT' | 'BLOB' | 'NUMERIC';
81
+ readonly defaultValue?: unknown;
82
+ readonly collation?: 'BINARY' | 'NOCASE' | 'RTRIM';
83
+ readonly identity?: 'rowid' | 'autoincrement';
84
+ readonly check?: unknown;
85
+ readonly generatedExpression?: unknown;
86
+ readonly stored?: boolean;
75
87
  }>>;
76
88
  }
77
89