@jarenjs/linq 0.72.0 → 0.72.3

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/ARCHITECTURE.md CHANGED
@@ -49,6 +49,10 @@ document (`{ $count: … }`), and `groupBy` packs its default return as
49
49
  `{ key: …, items: [ '$it' ] }` because an object member takes exactly
50
50
  one item.
51
51
 
52
+ The emitter also owns `requireNonNegativeInteger`, the shared count/index guard
53
+ for synchronous and asynchronous sequence windows and positional terminals.
54
+ Both surfaces report the same `JL0005` refusal at their existing call boundary.
55
+
52
56
  ## The typed surface (`types/index.d.ts`)
53
57
 
54
58
  Hand-authored declarations are the public type contract (the runtime
package/docs/DB-CLIENT.md CHANGED
@@ -826,10 +826,10 @@ never builds one; the migration between two of them is
826
826
 
827
827
  ## 7. Cost
828
828
 
829
- `@jarenjs/linq/db` builds to **<!--fact:bundle.db-->625,827<!--/fact--> bytes** as a minified,
829
+ `@jarenjs/linq/db` builds to **<!--fact:bundle.db-->627,769<!--/fact--> bytes** as a minified,
830
830
  tree-shaken ESM bundle — the figure `scripts/check-tree-shaking.js`
831
831
  measures and `npm run test:tree-shaking` reports, published rounded
832
- (<!--fact:bundle.db.kb-->626<!--/fact--> kB) beside the other nine subpath prices in
832
+ (<!--fact:bundle.db.kb-->628<!--/fact--> kB) beside the other nine subpath prices in
833
833
  [docs/CONSUMING.md](../../../docs/CONSUMING.md).
834
834
 
835
835
  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) | 948 | 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,724 | 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,725 | 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,092 | `./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 |
@@ -205,7 +205,7 @@ and the bundle is the byte count the tree-shaking probe builds.
205
205
  | Document | Subpath | Lines | Mapping rows | Worked examples | Refusals | Bundle |
206
206
  |---|---|---:|---:|---:|---:|---:|
207
207
  | [LINQ-FORMAT.md](LINQ-FORMAT.md) | — | 948 | — | — | — | — |
208
- | [QUERY-PEN.md](QUERY-PEN.md) | `.` | 1,724 | 34 | 8 | 15 | 174,188 B |
208
+ | [QUERY-PEN.md](QUERY-PEN.md) | `.` | 1,725 | 34 | 8 | 15 | 174,131 B |
209
209
  | [SCHEMA-PEN.md](SCHEMA-PEN.md) | `./schema` | 1,205 | 82 | 10 | 4 | 36,717 B |
210
210
  | [MODEL-PEN.md](MODEL-PEN.md) | `./model` | 1,092 | 28 | 6 | 3 | 45,143 B |
211
211
  | [JSLT-PEN.md](JSLT-PEN.md) | `./jslt` | 955 | 17 | 8 | 3 | 19,856 B |
@@ -219,8 +219,8 @@ and the bundle is the byte count the tree-shaking probe builds.
219
219
  | [JTLT-PEN.md](JTLT-PEN.md) | `./jtlt` | 83 | 13 | 1 | 2 | 16,725 B |
220
220
  | [PROJECT-PEN.md](PROJECT-PEN.md) | `./project` | 75 | 9 | 1 | 1 | 15,132 B |
221
221
  | [CHARTS-PEN.md](CHARTS-PEN.md) | `./charts` | 94 | 21 | 1 | 1 | 17,014 B |
222
- | [DB-CLIENT.md](DB-CLIENT.md) | `./db` | 893 | 41 | 4 | 2 | 625,827 B |
223
- | **16 documents** | | **12,390** | **371** | **73** | | |
222
+ | [DB-CLIENT.md](DB-CLIENT.md) | `./db` | 893 | 41 | 4 | 2 | 627,769 B |
223
+ | **16 documents** | | **12,391** | **371** | **73** | | |
224
224
  <!--/fact-->
225
225
 
226
226
  A pen whose mapping rows are far below its worked examples is a pen
@@ -262,7 +262,7 @@ it and each document publishes it. The rounded column is what
262
262
  <!--fact:pens.cost-->
263
263
  | Subpath | Document | Bundle | Rounded |
264
264
  |---|---|---:|---:|
265
- | `@jarenjs/linq` | [QUERY-PEN.md](QUERY-PEN.md) | 174,188 B | 174 kB |
265
+ | `@jarenjs/linq` | [QUERY-PEN.md](QUERY-PEN.md) | 174,131 B | 174 kB |
266
266
  | `@jarenjs/linq/schema` | [SCHEMA-PEN.md](SCHEMA-PEN.md) | 36,717 B | 37 kB |
267
267
  | `@jarenjs/linq/model` | [MODEL-PEN.md](MODEL-PEN.md) | 45,143 B | 45 kB |
268
268
  | `@jarenjs/linq/jslt` | [JSLT-PEN.md](JSLT-PEN.md) | 19,856 B | 20 kB |
@@ -276,7 +276,7 @@ it and each document publishes it. The rounded column is what
276
276
  | `@jarenjs/linq/jtlt` | [JTLT-PEN.md](JTLT-PEN.md) | 16,725 B | 17 kB |
277
277
  | `@jarenjs/linq/project` | [PROJECT-PEN.md](PROJECT-PEN.md) | 15,132 B | 15 kB |
278
278
  | `@jarenjs/linq/charts` | [CHARTS-PEN.md](CHARTS-PEN.md) | 17,014 B | 17 kB |
279
- | `@jarenjs/linq/db` | [DB-CLIENT.md](DB-CLIENT.md) | 625,827 B | 626 kB |
279
+ | `@jarenjs/linq/db` | [DB-CLIENT.md](DB-CLIENT.md) | 627,769 B | 628 kB |
280
280
  <!--/fact-->
281
281
 
282
282
  Read these as prices, not as scores. `./db` is the largest by an order of
package/docs/QUERY-PEN.md CHANGED
@@ -728,7 +728,8 @@ const rows = await fromAsync(fed.source('orders'))
728
728
  ```
729
729
 
730
730
  `fed.source(name)` is an ordinary provider source (§8) with the root
731
- `$.<name>[*]`, and all of a federation's sources share one scope which
731
+ `$.<name>[*]` (a quoted member selector for names containing punctuation,
732
+ spaces or other characters), and all of a federation's sources share one scope — which
732
733
  is exactly what admits the join. The federation is what executes it:
733
734
 
734
735
  1. each side's own document — the filters and the projection the chain
@@ -1671,14 +1672,14 @@ are shorter:
1671
1672
  ## 17. Cost
1672
1673
 
1673
1674
  A consumer importing `from` from `@jarenjs/linq` and calling one
1674
- terminal bundles **<!--fact:bundle.chain-->174,188<!--/fact--> bytes** (esbuild, ESM, minified, tree-shaken,
1675
+ terminal bundles **<!--fact:bundle.chain-->174,131<!--/fact--> bytes** (esbuild, ESM, minified, tree-shaken,
1675
1676
  `platform: 'neutral'`). The figure is measured by
1676
1677
  `scripts/check-tree-shaking.js`'s chain probe and compared with this
1677
1678
  section on every `npm run test:tree-shaking`: it is derived, never typed,
1678
1679
  and a stale one is red here rather than wrong in a document somebody
1679
1680
  reads.
1680
1681
 
1681
- Of that, **<!--fact:bundle.chain.own-->40,258<!--/fact--> bytes** are the chain's own modules — `sequence.js`,
1682
+ Of that, **<!--fact:bundle.chain.own-->40,131<!--/fact--> bytes** are the chain's own modules — `sequence.js`,
1682
1683
  `async.js`, `expression.js`, `document.js`, `provider.js`,
1683
1684
  `concurrency.js`, `errors.js` and `schema-of.js`. The remaining ~134 kB
1684
1685
  is the query ENGINE and the core it stands on: a chain's document has to
@@ -1705,7 +1706,7 @@ making:
1705
1706
  `docs/CONSUMING.md` states the rounded price of all ten subpaths in one
1706
1707
  table, each figure held equal to the same measurements. Two of its rows
1707
1708
  are the ones to read together: the chain at <!--fact:bundle.chain.kb-->174<!--/fact--> kB and
1708
- `./db` at <!--fact:bundle.db.kb-->626<!--/fact--> kB.
1709
+ `./db` at <!--fact:bundle.db.kb-->628<!--/fact--> kB.
1709
1710
  The client costs what the store costs, by construction, and the chain
1710
1711
  costs what running a query costs.
1711
1712
 
@@ -1714,7 +1715,7 @@ the reason is worth knowing: a bundler counts a shared module once, and
1714
1715
  the chain and every pen share the expression capture (`expression.js`)
1715
1716
  and the coded errors under it (`errors.js`, and `@jarenjs/core`'s error
1716
1717
  and object helpers). A consumer importing the chain AND the schema pen
1717
- bundles **<!--fact:bundle.chain.withSchemaPen-->198,858<!--/fact--> bytes** — **<!--fact:bundle.chain.shared-->12,047<!--/fact--> bytes** less than the sum of the
1718
+ bundles **<!--fact:bundle.chain.withSchemaPen-->198,801<!--/fact--> bytes** — **<!--fact:bundle.chain.shared-->12,047<!--/fact--> bytes** less than the sum of the
1718
1719
  figure above and [SCHEMA-PEN.md](SCHEMA-PEN.md#7-cost) §7's, which is
1719
1720
  what those shared modules weigh. The probe measures that pair too, so
1720
1721
  the saving is derived like everything else here. What the chain does NOT
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@jarenjs/linq",
3
3
  "private": false,
4
- "version": "0.72.0",
4
+ "version": "0.72.3",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
7
7
  "types": "./types/index.d.ts",
@@ -104,13 +104,13 @@
104
104
  "prepack": "npm run build:types"
105
105
  },
106
106
  "dependencies": {
107
- "@jarenjs/core": "^0.72.0",
108
- "@jarenjs/json": "^0.72.0"
107
+ "@jarenjs/core": "^0.72.3",
108
+ "@jarenjs/json": "^0.72.3"
109
109
  },
110
110
  "peerDependencies": {
111
- "@jarenjs/db": "^0.72.0",
112
- "@jarenjs/formats": "^0.72.0",
113
- "@jarenjs/validate": "^0.72.0"
111
+ "@jarenjs/db": "^0.72.3",
112
+ "@jarenjs/formats": "^0.72.3",
113
+ "@jarenjs/validate": "^0.72.3"
114
114
  },
115
115
  "peerDependenciesMeta": {
116
116
  "@jarenjs/db": {
package/src/async.js CHANGED
@@ -45,7 +45,7 @@ import {
45
45
  } from './provider.js';
46
46
  import {
47
47
  emitDocument, wrapTerminal, snapshot, fanProjection, isReservedBinding, RESERVED_BINDINGS_TEXT,
48
- PROJECTING_STAGES,
48
+ PROJECTING_STAGES, requireNonNegativeInteger,
49
49
  } from './document.js';
50
50
  import { adaptAsyncSource } from './sources.js';
51
51
  import { applyMapAsync, normalizeMapAsyncOptions } from './concurrency.js';
@@ -369,8 +369,8 @@ export class AsyncSequence {
369
369
  }, params);
370
370
  }
371
371
 
372
- skip(count) { return this.#with({ kind: 'skip', count: requireIndex(count, 'skip') }); }
373
- take(count) { return this.#with({ kind: 'take', count: requireIndex(count, 'take') }); }
372
+ skip(count) { return this.#with({ kind: 'skip', count: requireNonNegativeInteger(count, 'skip') }); }
373
+ take(count) { return this.#with({ kind: 'take', count: requireNonNegativeInteger(count, 'take') }); }
374
374
  distinct() { return this.#with({ kind: 'distinct' }); }
375
375
  reverse() { return this.#with({ kind: 'reverse' }); }
376
376
 
@@ -722,7 +722,7 @@ export class AsyncSequence {
722
722
 
723
723
  /** @param {number} index */
724
724
  async elementAt(index) {
725
- requireIndex(index, 'elementAt');
725
+ requireNonNegativeInteger(index, 'elementAt');
726
726
  const w = this.#pushable()
727
727
  ? await this.#pushWindow('elementAt', [index]) : await this.skip(index).#window(1);
728
728
  if (w.length === 0) throw new LinqRuntimeError('JL2003', `elementAt(${index}) is out of range`);
@@ -731,7 +731,7 @@ export class AsyncSequence {
731
731
 
732
732
  /** @param {number} index @param {any} [defaultValue] */
733
733
  async elementAtOrDefault(index, defaultValue) {
734
- requireIndex(index, 'elementAtOrDefault');
734
+ requireNonNegativeInteger(index, 'elementAtOrDefault');
735
735
  const w = this.#pushable()
736
736
  ? await this.#pushWindow('elementAt', [index]) : await this.skip(index).#window(1);
737
737
  return w.length === 0 ? defaultValue : w[0];
@@ -832,14 +832,6 @@ async function collect(stream) {
832
832
  return out;
833
833
  }
834
834
 
835
- /** @param {number} value @param {string} what */
836
- function requireIndex(value, what) {
837
- if (!Number.isInteger(value) || value < 0) {
838
- throw new LinqBuildError('JL0005', `${what} takes a non-negative integer, got ${value}`);
839
- }
840
- return value;
841
- }
842
-
843
835
  /** @param {any} bindings */
844
836
  function validateParams(bindings) {
845
837
  if (bindings === null || typeof bindings !== 'object' || Array.isArray(bindings)) {
package/src/db/ledger.js CHANGED
@@ -132,7 +132,8 @@ export function createDbLedger(client, options = {}) {
132
132
  return inside(async (tx) => {
133
133
  const c = rows(tx);
134
134
  const record = await c.get(r.id);
135
- if (record === undefined || record.generation !== r.generation || record.status !== 'started') {
135
+ if (record === undefined || record.generation !== r.generation || record.status !== 'started'
136
+ || record.expiresAt <= at) {
136
137
  throw stale(ref, 'the key expired, was reclaimed under a newer generation, or was settled already');
137
138
  }
138
139
  await c.put({ ...record, ...changes, updatedAt: at }, r.id);
package/src/document.js CHANGED
@@ -39,6 +39,19 @@
39
39
 
40
40
  import { LinqBuildError } from './errors.js';
41
41
 
42
+ /**
43
+ * Validate a sequence window's count or a positional terminal's index.
44
+ * @param {number} value
45
+ * @param {string} what - The operator named by a refusal
46
+ * @returns {number} The unchanged count or index
47
+ */
48
+ export function requireNonNegativeInteger(value, what) {
49
+ if (!Number.isInteger(value) || value < 0) {
50
+ throw new LinqBuildError('JL0005', `${what} takes a non-negative integer, got ${value}`);
51
+ }
52
+ return value;
53
+ }
54
+
42
55
  /** The binding names the emitted documents own (QUERY-PEN §7): the
43
56
  * item bindings, the accumulator and the group — and the relation-hop
44
57
  * bindings `r1`, `r2`, … a capture allocates (expression.js). A
package/src/expression.js CHANGED
@@ -98,7 +98,7 @@ function bracketName(name) {
98
98
  * @param {string} name
99
99
  * @returns {string}
100
100
  */
101
- function memberSegment(name) {
101
+ export function memberSegment(name) {
102
102
  return SHORTHAND_RE.test(name) ? `.${name}` : bracketName(name);
103
103
  }
104
104
 
package/src/federate.js CHANGED
@@ -45,6 +45,7 @@
45
45
 
46
46
  import { LinqBuildError, LinqRuntimeError } from './errors.js';
47
47
  import { compileDocument, isProviderSource, providerRoot } from './provider.js';
48
+ import { memberSegment } from './expression.js';
48
49
 
49
50
  /** The strategies this boundary knows. One, for now, and it says so. */
50
51
  const STRATEGIES = new Set(['hash']);
@@ -123,18 +124,6 @@ function byteSize(row) {
123
124
  return encoder.encode(text).length;
124
125
  }
125
126
 
126
- /**
127
- * The root NAME a root expression carries: `'$.Post[*]'` → `'Post'`.
128
- * A federated source's root is always this shape, because the
129
- * federation names it.
130
- * @param {string} root
131
- * @returns {string}
132
- */
133
- function rootName(root) {
134
- const match = /^\$\.([^.[\]]+)\[\*\]$/.exec(root);
135
- return match === null ? '' : match[1];
136
- }
137
-
138
127
  /**
139
128
  * The FLWOR a terminal wrapped, and how to put a rewritten one back.
140
129
  *
@@ -412,7 +401,7 @@ export function federate(spec) {
412
401
  // the federated root, which is what the chain binds and what the
413
402
  // resident document ranges over; the source's OWN root is what its
414
403
  // child document uses, and `childDocument` rewrites between them
415
- const root = `$.${name}[*]`;
404
+ const root = `$${memberSegment(name)}[*]`;
416
405
  members.set(root, { name, root, provider, estimatedRows });
417
406
  }
418
407
 
@@ -448,8 +437,8 @@ export function federate(spec) {
448
437
  }, open);
449
438
 
450
439
  const input = {
451
- [rootName(plan.build.root)]: built.rows,
452
- [rootName(plan.probe.root)]: probed.rows,
440
+ [plan.build.member.name]: built.rows,
441
+ [plan.probe.member.name]: probed.rows,
453
442
  };
454
443
  const compiled = compileDocument(plan.resident,
455
444
  { ...options, externals: options?.externalNames ?? [] });
@@ -462,7 +451,7 @@ export function federate(spec) {
462
451
  catch (error) {
463
452
  // the call's own failure is the one the caller gets: a cursor
464
453
  // that also fails to close must not replace the budget's refusal
465
- await closeAll(open);
454
+ await closeAll(open).catch(() => {});
466
455
  throw error;
467
456
  }
468
457
  };
@@ -513,7 +502,7 @@ export function federate(spec) {
513
502
  const handleFor = (name) => {
514
503
  let handle = handles.get(name);
515
504
  if (handle === undefined) {
516
- const root = `$.${name}[*]`;
505
+ const root = `$${memberSegment(name)}[*]`;
517
506
  if (!members.has(root)) {
518
507
  throw new LinqBuildError('JL0005',
519
508
  `'${name}' is not one of this federation's sources (${names.join(', ')})`);
package/src/sequence.js CHANGED
@@ -20,7 +20,7 @@ import {
20
20
  } from './expression.js';
21
21
  import {
22
22
  emitDocument, wrapTerminal, snapshot, fanProjection, isReservedBinding, RESERVED_BINDINGS_TEXT,
23
- PROJECTING_STAGES,
23
+ PROJECTING_STAGES, requireNonNegativeInteger,
24
24
  } from './document.js';
25
25
  import {
26
26
  classifySource, compileDocument, executeInMemory, providerRoot, providerRelations, sharesScope,
@@ -31,14 +31,6 @@ import { schemaOf } from './schema-of.js';
31
31
 
32
32
  const VAR_NAME_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
33
33
 
34
- /** @param {number} value @param {string} what */
35
- function requireIndex(value, what) {
36
- if (!Number.isInteger(value) || value < 0) {
37
- throw new LinqBuildError('JL0005', `${what} takes a non-negative integer, got ${value}`);
38
- }
39
- return value;
40
- }
41
-
42
34
  /** The immutable query sequence. Construct via `from`/`fromDocument`. */
43
35
  export class Sequence {
44
36
  #source;
@@ -315,11 +307,11 @@ export class Sequence {
315
307
  }
316
308
 
317
309
  skip(count) {
318
- return this.#with({ kind: 'skip', count: requireIndex(count, 'skip') });
310
+ return this.#with({ kind: 'skip', count: requireNonNegativeInteger(count, 'skip') });
319
311
  }
320
312
 
321
313
  take(count) {
322
- return this.#with({ kind: 'take', count: requireIndex(count, 'take') });
314
+ return this.#with({ kind: 'take', count: requireNonNegativeInteger(count, 'take') });
323
315
  }
324
316
 
325
317
  distinct() {
@@ -557,7 +549,7 @@ export class Sequence {
557
549
  }
558
550
 
559
551
  elementAt(index) {
560
- requireIndex(index, 'elementAt');
552
+ requireNonNegativeInteger(index, 'elementAt');
561
553
  const w = this.#window('elementAt', [index]);
562
554
  if (w.length === 0) throw new LinqRuntimeError('JL2003', `elementAt(${index}) is out of range`);
563
555
  return w[0];
@@ -565,7 +557,7 @@ export class Sequence {
565
557
 
566
558
  /** @param {number} index @param {any} [defaultValue] */
567
559
  elementAtOrDefault(index, defaultValue) {
568
- requireIndex(index, 'elementAtOrDefault');
560
+ requireNonNegativeInteger(index, 'elementAtOrDefault');
569
561
  const w = this.#window('elementAt', [index]);
570
562
  return w.length === 0 ? defaultValue : w[0];
571
563
  }
package/types/charts.d.ts CHANGED
@@ -75,7 +75,7 @@ export interface ValueSeries {
75
75
  /**
76
76
  * one boxplot category: raw samples in `values`, or a precomputed five-number summary
77
77
  */
78
- export type Box = unknown & { label: string; values?: Array<number | null>; min?: number; q1?: number; med?: number; q3?: number; max?: number; outliers?: Array<number>; [key: string]: unknown; };
78
+ export type Box = ({ values: unknown; [key: string]: unknown; } | Array<unknown> | string | number | boolean | null | { min: unknown; q1: unknown; med: unknown; q3: unknown; max: unknown; [key: string]: unknown; }) & { label: string; values?: Array<number | null>; min?: number; q1?: number; med?: number; q3?: number; max?: number; outliers?: Array<number>; [key: string]: unknown; };
79
79
 
80
80
  export interface TreemapItem {
81
81
  label: string;
@@ -120,6 +120,16 @@ export interface SankeyLink {
120
120
  }
121
121
 
122
122
 
123
+ /**
124
+ * Schema constraints this type cannot express: minimum=-180, maximum=180
125
+ */
126
+ export type MapPointAtItem1 = number;
127
+
128
+ /**
129
+ * Schema constraints this type cannot express: minimum=-90, maximum=90
130
+ */
131
+ export type MapPointAtItem2 = number;
132
+
123
133
  /**
124
134
  * a place marker: the convenience path for a caller holding positions rather than GeoJSON
125
135
  */
@@ -128,17 +138,37 @@ export interface MapPoint {
128
138
  * a GeoJSON position: [longitude, latitude]
129
139
  * Schema constraints this type cannot express: minItems=2, maxItems=3
130
140
  */
131
- at: [number, number, ...Array<number>];
141
+ at: [MapPointAtItem1, MapPointAtItem2, ...Array<number>];
132
142
  label?: string;
133
143
  value?: number;
134
144
  [key: string]: unknown;
135
145
  }
136
146
 
137
147
 
148
+ export interface SamplingPolicyAnyOf3 {
149
+ method?: "lttb" | "minmax";
150
+ /**
151
+ * the most points one series may draw; an explicit target makes the rendered line independent of any layout
152
+ * Schema constraints this type cannot express: type="integer", minimum=2
153
+ */
154
+ target?: number;
155
+ /**
156
+ * the width the derived target assumes, in CSS pixels (default 560)
157
+ * Schema constraints this type cannot express: exclusiveMinimum=0
158
+ */
159
+ width?: number;
160
+ /**
161
+ * Schema constraints this type cannot express: exclusiveMinimum=0
162
+ */
163
+ pixelRatio?: number;
164
+ [key: string]: unknown;
165
+ }
166
+
167
+
138
168
  /**
139
169
  * how many of a line's points are drawn: false never samples, a method name or object samples whatever the count, and an omitted member samples a TIME line above 2000 points through @jarenjs/core/series. Distinct from stream.maxPoints, which decides what exists rather than what is drawn.
140
170
  */
141
- export type SamplingPolicy = false | "lttb" | "minmax" | { method?: "lttb" | "minmax"; target?: number; width?: number; pixelRatio?: number; [key: string]: unknown; };
171
+ export type SamplingPolicy = false | "lttb" | "minmax" | SamplingPolicyAnyOf3;
142
172
 
143
173
  /**
144
174
  * the month, weekday and meridiem names a time-axis pattern with a name token reads (compileDateLocale(pack).names from @jarenjs/locales); a name token with no record is a compile error, never an English fallback
@@ -181,11 +211,24 @@ export interface TimeFormats {
181
211
  }
182
212
 
183
213
 
214
+ export interface DomainPolicyX {
215
+ /**
216
+ * Schema constraints this type cannot express: exclusiveMinimum=0
217
+ */
218
+ window: number;
219
+ /**
220
+ * Schema constraints this type cannot express: exclusiveMinimum=0
221
+ */
222
+ slide?: number;
223
+ [key: string]: unknown;
224
+ }
225
+
226
+
184
227
  /**
185
228
  * domain-stability policy: a quantized sliding x window and/or pinned or step-quantized y bounds, so most streaming ticks keep the scales still
186
229
  */
187
230
  export interface DomainPolicy {
188
- x?: { window: number; slide?: number; [key: string]: unknown; };
231
+ x?: DomainPolicyX;
189
232
  y?: "step" | { min?: number; max?: number; [key: string]: unknown; };
190
233
  [key: string]: unknown;
191
234
  }