@jarenjs/linq 0.67.0 → 0.72.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.
@@ -31,11 +31,9 @@ import * as s from '@jarenjs/linq/schema';
31
31
  builds JSON Schema 2020-12 documents: the structural keywords, the
32
32
  constraints and the annotations, each with a method of its own; `$query`
33
33
  captured through the chain's proxy; `$defs`/`$ref` recursion; the
34
- normalizer's per-field predicates. Twenty-five further keywords that
35
- `@jarenjs/validate` also compiles have no method on this surface and are
36
- written through `.keyword()` or `from()` instead
37
- [§6.2](#62-the-absences-twenty-five-keywords-with-no-method) lists them
38
- by family. The type reading is
34
+ normalizer's per-field predicates. Every owned keyword has a dedicated spelling. Annotation-dependent,
35
+ negating and dynamic-reference methods preserve the existing phantom;
36
+ [§6.2](#62-annotation-and-legacy-boundaries) explains those boundaries. The type reading is
39
37
  emit's (EMIT-FORMAT §5–§7), because the agreement pins them equal; a
40
38
  constraint (`min`, `pattern`, `format`) never changes a type — the honest
41
39
  widening emit documents — with one addition: a string with
@@ -297,6 +295,42 @@ Three rules the tables imply, spelled out:
297
295
  so a promise that resolves one calls it with a function and is refused
298
296
  by name (`JL0101`); keep builders out of async return positions.
299
297
 
298
+ ### 2.11 Content, containment and resource identity
299
+
300
+ Each method preserves the current phantom and replaces a prior value in place.
301
+ The content methods describe encoded strings; `contentSchema` is annotation
302
+ information, not a promise that the validator checks the decoded value.
303
+ `contentValidation: true` enables encoding/media checks. Format bounds require
304
+ a format compiler that supports ordering. Schema-valued methods take builders
305
+ and share the root's definition-hoisting context.
306
+
307
+ | Method | Emits | `Infer` / `Input` | Status |
308
+ |---|---|---|---|
309
+ | `.id(uri)` | `$id` | `this` | native; string required |
310
+ | array `.minContains(n)`, `.maxContains(n)` | `minContains`, `maxContains` | `this` | native; non-negative integers |
311
+ | string `.contentEncoding(text)` | `contentEncoding` | `this` | native |
312
+ | string `.contentMediaType(text)` | `contentMediaType` | `this` | native |
313
+ | string `.contentSchema(builder)` | `contentSchema` | `this` | native; named definitions hoist |
314
+ | string `.formatMinimum(text)`, `.formatMaximum(text)` | `formatMinimum`, `formatMaximum` | `this` | native |
315
+ | string `.formatExclusiveMinimum(text)`, `.formatExclusiveMaximum(text)` | `formatExclusiveMinimum`, `formatExclusiveMaximum` | `this` | native |
316
+
317
+ ### 2.12 Applicators, references and legacy keywords
318
+
319
+ All methods below are immutable; repeated calls replace the previous value.
320
+ Raw schemas enter through `from()`. Use `never()` for a false subschema.
321
+
322
+ | Method | Emits | `Infer` / `Input` | Status |
323
+ |---|---|---|---|
324
+ | `.not(builder)` | `not` | `this` | native |
325
+ | `.unevaluatedProperties(builder)`, `.unevaluatedItems(builder)` | `unevaluatedProperties`, `unevaluatedItems` | `this` | native |
326
+ | `.dependentSchemas(map)`, `.dependencies(map)` | `dependentSchemas`, `dependencies` | `this` | native; legacy dependencies also accept arrays of distinct member names |
327
+ | `.anchor(name)`, `.vocabulary(map)` | `$anchor`, `$vocabulary` | `this` | native |
328
+ | `.dynamicRef(uri)`, `.dynamicAnchor(name)` | `$dynamicRef`, `$dynamicAnchor` | `this` | native; no inferred reference identity |
329
+ | `.recursiveRef(uri)`, `.recursiveAnchor(boolean)` | `$recursiveRef`, `$recursiveAnchor` | `this` | native |
330
+ | `.definitions(map)`, `.additionalItems(builder)` | `definitions`, `additionalItems` | `this` | native; legacy vocabulary |
331
+ | `.dollarData(pointer)`, `.data(map)` | `$data`, `data` | `this` | native |
332
+ | `.legacyNullable(boolean)` | `nullable` | `unknown` | native; distinct from `.nullable()` |
333
+
300
334
  ## 3. Worked examples
301
335
 
302
336
  One account service, built up. Every `js` fence below exports exactly one
@@ -830,25 +864,13 @@ JSON are still two, and still a collision.
830
864
 
831
865
  | The spelling that trips it | The message | The spelling that works |
832
866
  |---|---|---|
833
- | `s.string().meta({ type: 'x' })` | `meta() cannot write 'type' — the pen owns that keyword; spell it through the builder method that emits it, keyword('type', value) where no method does, or wrap a hand-written schema with from()` | the method that emits it — or, for a keyword §6.2 lists, `s.keyword(…)` or `s.from({ … })` |
867
+ | `s.string().meta({ type: 'x' })` | `meta() cannot write 'type' — the pen owns that keyword; spell it through the builder method that emits it, keyword('type', value) where no method does, or wrap a hand-written schema with from()` | the method that emits it — or, for a raw value, `.keyword(…)` or `s.from({ … })` |
834
868
  | `.check((o, x) => x.foo.eq(1))` | `a check() rule cannot bind 'foo' — its query evaluates with exactly 2 externals, 'root' and 'path'; anything else has nothing to bind to` | `x.root` and `x.path`, and nothing else |
835
869
 
836
- The owned set is every keyword the pen writes itself plus every keyword
837
- that would change what a document asserts the structural ones, the
838
- constraints, `$schema`/`$id`/`$ref`/`$defs` and the anchors, `$query`,
839
- `default`/`title`/`description`/`examples`/`errorMessage`, and
840
- `x-coerce`/`x-trim`. `meta()` is for everything else: a 2020-12
841
- annotation the pen has no method for (`deprecated`, `readOnly`,
842
- `writeOnly`), and any vendor extension. The type declaration carries the
843
- same set as `OwnedKeyword`, so a forbidden key does not compile either
844
- (§5). Twenty-five of the sixty-nine have no method to be spelled through,
845
- which is why the message names `keyword()` as well;
846
- [§6.2](#62-the-absences-twenty-five-keywords-with-no-method) lists them
847
- and the two doors that stay open for them.
848
-
849
- `check()`'s two externals are the two the validator binds on every
850
- `$query` evaluation. The refusal is raised at BUILD time, earlier than
851
- the validator's own compile error and with the same meaning.
870
+ The owned set is the vocabulary written by the dedicated methods. `meta()`
871
+ refuses those names so an annotation never changes the schema's assertions.
872
+ `keyword()` remains available for raw values and `from()` for whole schemas;
873
+ [§6.2](#62-annotation-and-legacy-boundaries) describes their type boundaries.
852
874
 
853
875
  ## 5. The types
854
876
 
@@ -1081,70 +1103,35 @@ having.
1081
1103
  `packages/json/docs/QUERY-FORMAT.md` §8; a rule outside it is
1082
1104
  application code, run beside validation rather than inside it.
1083
1105
 
1084
- ### 6.2 The absences: twenty-five keywords with no method
1106
+ ### 6.2 Annotation and legacy boundaries
1085
1107
 
1086
- The pen's own list of the keywords it owns
1087
- (`packages/linq/src/schema/builders.js`) is sixty-nine names, and it holds
1088
- two kinds the keywords a method emits, and the ones that "would change
1089
- what a document asserts" and are kept out of `meta()` for that reason
1090
- alone (the comment above the list says so). The second kind has no
1091
- spelling of its own on this surface:
1108
+ Every owned keyword has a dedicated route. The executable census in
1109
+ `test/linq/schema-keyword-corpus.js` checks the actual emitted spelling;
1110
+ a route that returns a different keyword cannot satisfy it.
1092
1111
 
1093
- | Family | Keywords with no method |
1094
- |---|---|
1095
- | negation | `not` |
1096
- | unevaluated | `unevaluatedProperties`, `unevaluatedItems` |
1097
- | conditional members | `dependentSchemas`, `dependencies` |
1098
- | `contains` bounds | `minContains`, `maxContains` |
1099
- | content | `contentEncoding`, `contentMediaType`, `contentSchema` |
1100
- | format bounds | `formatMinimum`, `formatMaximum`, `formatExclusiveMinimum`, `formatExclusiveMaximum` |
1101
- | identification | `$id`, `$anchor`, `$vocabulary` |
1102
- | dynamic references | `$dynamicRef`, `$dynamicAnchor`, `$recursiveRef`, `$recursiveAnchor` |
1103
- | legacy and extension spellings | `definitions`, `additionalItems`, `$data`, `data` |
1104
-
1105
- `@jarenjs/validate` compiles every one of them — `not` in `combine.js`,
1106
- the unevaluated pair in `unevaluated.js`, `dependentSchemas` in
1107
- `object.js`, the `contains` bounds in `array.js`, the content family in
1108
- `content.js`, the dynamic references in `dynamic-ref.js`, `$data` in
1109
- `dollar-data.js` — so the gap is this pen's surface, not the format and
1110
- not the engine. It is tracked in
1111
- [docs/ROADMAP.md](../../../docs/ROADMAP.md) under the data pair, and
1112
- `test/linq/schema-pen.test.js` holds this table equal to the pen's own
1113
- owned set, so a method that lands for one of them fails the suite until
1114
- its row goes.
1115
-
1116
- Two doors are open in the meantime, and both are rows of
1117
- [§2.10](#210-the-document-and-the-builder-itself):
1112
+ `not`, unevaluated constraints, dependencies and dynamic references keep the
1113
+ existing phantom. They may reject more values, but TypeScript does not infer
1114
+ annotation tracking, negation or dynamic scope. `legacyNullable(boolean)`
1115
+ writes the OpenAPI `nullable` spelling exactly and deliberately broadens the
1116
+ phantom to `unknown`; `.nullable()` retains its inferred union and standard
1117
+ JSON Schema emission. These are separate operations.
1118
1118
 
1119
- ```js
1120
- s.string().keyword('not', { type: 'number' })
1121
- // { "type": "string", "not": { "type": "number" } }
1119
+ `contentSchema` remains annotation information in the current validator.
1120
+ Encoding and media checks require `contentValidation: true`; ordered format
1121
+ bounds require a registered format compiler with comparison support.
1122
1122
 
1123
- s.object({ a: s.string() }).keyword('unevaluatedProperties', false)
1124
- // { "type": "object", …, "unevaluatedProperties": false }
1125
- ```
1123
+ `definitions` and `additionalItems` author draft-07 vocabulary. Declare that
1124
+ dialect in a raw root when using them; `document({ draft: '2020-12' })` does
1125
+ not translate a legacy tuple. Schema-valued methods accept builders, including
1126
+ `from(json)` and `never()` for an exact raw or boolean subschema. They share
1127
+ named definition identity with every other branch, including recursive ones.
1128
+ Normalizer annotations in branches the normalizer never visits are refused.
1126
1129
 
1127
- `.keyword(key, value)` writes one keyword onto the node the builder is
1128
- assembling, in the order first set, exactly as a named method does;
1129
- `from(json)` wraps a hand-written subschema whole. Neither changes the
1130
- type reading — `.keyword()` answers `this` and `from<T>()` carries the
1131
- type the caller asserts which is the honest trade rather than a
1132
- shortfall: a keyword with no method has no phantom to read either.
1133
-
1134
- `definitions` is the draft-07 spelling of `$defs`, and `named()` writes
1135
- `$defs`: the pen emits one definitions block under one name, so the older
1136
- keyword is owned to keep a document from carrying both and reached, like
1137
- the rest of the table, through `keyword()` or `from()`.
1138
-
1139
- **`meta()` is not a third door.** Every name in the table is owned, so
1140
- `meta()` refuses it with `JL0104`
1141
- ([§4.4](#44-jl0104--the-keyword-and-the-external)) — and the message
1142
- names both doors that ARE open, `keyword()` and `from()`. One name is on
1143
- the owned list for the opposite reason: `nullable` is refused because
1144
- `.nullable()` already exists and emits a type union
1145
- (`type: ['string', 'null']`) — `nullable` as a keyword is an OpenAPI
1146
- spelling that 2020-12 does not carry, and refusing it is what keeps one
1147
- document from claiming both.
1130
+ `dollarData(pointer)` builds a `$data` reference object; use its `.schema` as
1131
+ a raw constraint value. `data(map)` writes keyword-to-pointer bindings at the
1132
+ schema node. Both leave pointer resolution to the validator. `keyword()` and
1133
+ `from()` remain the escape hatches for future extensions, with no inferred
1134
+ narrowing. A boolean document cannot carry a keyword; widen it first.
1148
1135
 
1149
1136
  ### 6.3 When not to reach for this pen
1150
1137
 
@@ -1180,10 +1167,10 @@ hand, or generate it some other way, when:
1180
1167
 
1181
1168
  ## 7. Cost
1182
1169
 
1183
- `@jarenjs/linq/schema` builds to **<!--fact:bundle.schema-->33,156<!--/fact--> bytes** as a minified,
1170
+ `@jarenjs/linq/schema` builds to **<!--fact:bundle.schema-->36,717<!--/fact--> bytes** as a minified,
1184
1171
  tree-shaken ESM bundle — the figure `scripts/check-tree-shaking.js`
1185
1172
  measures and `npm run test:tree-shaking` reports, published rounded
1186
- (<!--fact:bundle.schema.kb-->33<!--/fact--> kB) beside the other nine subpath prices in
1173
+ (<!--fact:bundle.schema.kb-->37<!--/fact--> kB) beside the other nine subpath prices in
1187
1174
  [docs/CONSUMING.md](../../../docs/CONSUMING.md).
1188
1175
 
1189
1176
  The probe is a gate, not a report: building
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@jarenjs/linq",
3
3
  "private": false,
4
- "version": "0.67.0",
4
+ "version": "0.72.2",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
7
7
  "types": "./types/index.d.ts",
@@ -47,7 +47,27 @@
47
47
  "types": "./types/db.d.ts",
48
48
  "default": "./src/db/index.js"
49
49
  },
50
- "./package.json": "./package.json"
50
+ "./package.json": "./package.json",
51
+ "./charts": {
52
+ "types": "./types/charts.d.ts",
53
+ "default": "./src/charts/index.js"
54
+ },
55
+ "./project": {
56
+ "types": "./types/project.d.ts",
57
+ "default": "./src/project/index.js"
58
+ },
59
+ "./jtlt": {
60
+ "types": "./types/jtlt.d.ts",
61
+ "default": "./src/jtlt/index.js"
62
+ },
63
+ "./messages": {
64
+ "types": "./types/messages.d.ts",
65
+ "default": "./src/messages/index.js"
66
+ },
67
+ "./ai": {
68
+ "types": "./types/ai.d.ts",
69
+ "default": "./src/ai/index.js"
70
+ }
51
71
  },
52
72
  "files": [
53
73
  "types/",
@@ -84,13 +104,13 @@
84
104
  "prepack": "npm run build:types"
85
105
  },
86
106
  "dependencies": {
87
- "@jarenjs/core": "^0.67.0",
88
- "@jarenjs/json": "^0.67.0"
107
+ "@jarenjs/core": "^0.72.2",
108
+ "@jarenjs/json": "^0.72.2"
89
109
  },
90
110
  "peerDependencies": {
91
- "@jarenjs/db": "^0.67.0",
92
- "@jarenjs/formats": "^0.67.0",
93
- "@jarenjs/validate": "^0.67.0"
111
+ "@jarenjs/db": "^0.72.2",
112
+ "@jarenjs/formats": "^0.72.2",
113
+ "@jarenjs/validate": "^0.72.2"
94
114
  },
95
115
  "peerDependenciesMeta": {
96
116
  "@jarenjs/db": {
@@ -0,0 +1,76 @@
1
+ //@ts-check
2
+ /** The AI action document, authored without an AI client, environment or engine. */
3
+ import { DocumentBuilder, optionsOf, snapshot } from '../authored.js';
4
+ import { captureQuery } from '../capture-root.js';
5
+ import { LinqBuildError } from '../errors.js';
6
+
7
+ const FIELDS = {
8
+ chunk: ['strategy', 'size'], grep: ['pattern', 'flags', 'limit'], select: ['query'],
9
+ stat: [], peek: [], map: ['prompt'], reduce: ['query', 'outputSchema'], answer: ['chars'],
10
+ };
11
+ function make(op, from, as, options) {
12
+ if (typeof from !== 'string' || !from || (op !== 'answer' && (typeof as !== 'string' || !as)))
13
+ throw new LinqBuildError('JL0101', 'A step needs a source name and, except answer, a result name');
14
+ return snapshot({ op, from, ...(op === 'answer' ? {} : { as }), ...optionsOf(options, FIELDS[op], `${op}()`) });
15
+ }
16
+ function expression(value) {
17
+ // The program query receives only its input document: an undeclared external
18
+ // is the shared capture's JL0104 refusal, not an invented environment lookup.
19
+ return typeof value === 'function' ? captureQuery('program query', [], value, { fold: false }) : value;
20
+ }
21
+ /** Split a slot into a family of pieces. */
22
+ export function chunk(from, as, options = {}) { return make('chunk', from, as, options); }
23
+ /** Find matching slots with a bounded pattern and options. */
24
+ export function grep(from, as, options) { return make('grep', from, as, options); }
25
+ /** Query one JSON slot; a callback is captured as ordinary query JSON. */
26
+ export function select(from, as, query) { return make('select', from, as, { query: expression(query) }); }
27
+ /** Inspect counts and shape. */
28
+ export function stat(from, as) { return make('stat', from, as, {}); }
29
+ /** Inspect a slot's metadata and excerpt. */
30
+ export function peek(from, as) { return make('peek', from, as, {}); }
31
+ /** Ask one bounded prompt per member of a slot/family. */
32
+ export function map(from, as, prompt) { return make('map', from, as, { prompt }); }
33
+ /** Query the collected results of an earlier map. */
34
+ export function reduce(from, as, query, options = {}) {
35
+ return make('reduce', from, as, { query: expression(query), ...optionsOf(options, ['outputSchema'], 'reduce()') });
36
+ }
37
+ /** Declare the final answer slot and optional excerpt bound. */
38
+ export function answer(from, options = {}) { return make('answer', from, undefined, options); }
39
+
40
+ /** An immutable ordered program; binding types are phantoms. */
41
+ export class ProgramBuilder extends DocumentBuilder {
42
+ /** Append a public step. An answer closes this builder. @param {any} value */
43
+ step(value) {
44
+ if (this.schema.steps.at(-1)?.op === 'answer')
45
+ throw new LinqBuildError('JL0102', 'answer is terminal; start another program to append work');
46
+ if (value === null || typeof value !== 'object' || !Object.hasOwn(FIELDS, value.op))
47
+ throw new LinqBuildError('JL0101', 'step() needs a known program operation');
48
+ const step = optionsOf(value, ['op', 'from', ...(value.op === 'answer' ? [] : ['as']), ...FIELDS[value.op]], 'step()');
49
+ return this.with({ steps: [...this.schema.steps, step] });
50
+ }
51
+ /** Append a chunk step. */
52
+ chunk(from, as, options = {}) { return this.step(chunk(from, as, options)); }
53
+ /** Append a grep step. */
54
+ grep(from, as, options) { return this.step(grep(from, as, options)); }
55
+ /** Append a select step. */
56
+ select(from, as, query) { return this.step(select(from, as, query)); }
57
+ /** Append a stat step. */
58
+ stat(from, as) { return this.step(stat(from, as)); }
59
+ /** Append a peek step. */
60
+ peek(from, as) { return this.step(peek(from, as)); }
61
+ /** Append a map step. */
62
+ map(from, as, prompt) { return this.step(map(from, as, prompt)); }
63
+ /** Append a reduce step. */
64
+ reduce(from, as, query, options = {}) { return this.step(reduce(from, as, query, options)); }
65
+ /** Append the terminal answer. */
66
+ answer(from, options = {}) { return this.step(answer(from, options)); }
67
+ }
68
+
69
+ /** Declare input slot names for TypeScript; they never become document members. @param {readonly string[]} slots */
70
+ export function program(slots = []) {
71
+ if (!Array.isArray(slots) || slots.some((name) => typeof name !== 'string' || !name))
72
+ throw new LinqBuildError('JL0101', 'program() takes input slot names');
73
+ return new ProgramBuilder({ steps: [] });
74
+ }
75
+ /** A raw public program. Compilation remains authoritative for names and semantics. @param {any} document */
76
+ export function from(document) { return new ProgramBuilder(document); }
@@ -0,0 +1,38 @@
1
+ //@ts-check
2
+ /** Immutable JSON document storage shared by the authored-format pens. */
3
+ import { cloneJson, deepFreeze } from '@jarenjs/core/object';
4
+ import { requireJson, requireNameMap } from './json-boundary.js';
5
+ import { LinqBuildError } from './errors.js';
6
+
7
+ /** A snapshot, never a view of a caller-owned document. @param {any} value */
8
+ export function snapshot(value) {
9
+ return deepFreeze(cloneJson(requireJson(value, 'document')));
10
+ }
11
+
12
+ /** The closed option boundary; extensions enter through the raw document factory. */
13
+ export function optionsOf(value, keys, what) {
14
+ if (value === null || typeof value !== 'object' || Array.isArray(value))
15
+ throw new LinqBuildError('JL0101', `${what} takes a plain object`);
16
+ requireNameMap(value, what);
17
+ for (const key of Object.keys(value)) {
18
+ if (!keys.includes(key))
19
+ throw new LinqBuildError('JL0101', `${what} does not take '${key}' — use from() for a raw document`);
20
+ }
21
+ return snapshot(value);
22
+ }
23
+
24
+ /** A standard document with fluent, immutable replacement. */
25
+ export class DocumentBuilder {
26
+ #schema;
27
+ /** @param {any} document */
28
+ constructor(document) { this.#schema = snapshot(document); }
29
+ /** The public document, deeply frozen. */
30
+ get schema() { return this.#schema; }
31
+ /** JSON serialization is exactly the public document. */
32
+ toJSON() { return this.#schema; }
33
+ /** Replace members without changing the original builder. @param {object} patch */
34
+ with(patch) {
35
+ const Kind = /** @type {any} */ (this.constructor);
36
+ return new Kind({ ...this.#schema, ...patch });
37
+ }
38
+ }
@@ -0,0 +1,131 @@
1
+ //@ts-check
2
+ /** Chart-definition factories; the chart engine is injected by the consumer. */
3
+ import { DocumentBuilder, optionsOf } from '../authored.js';
4
+ import { LinqBuildError } from '../errors.js';
5
+ import { CHART_FIELDS } from './vocabulary.js';
6
+
7
+ /** Immutable chart definition; methods keep the original discriminator. */
8
+ export class ChartBuilder extends DocumentBuilder {
9
+ /** @param {Record<string, any>} value */
10
+ options(value) {
11
+ const keys = CHART_FIELDS[this.schema.type];
12
+ if (keys === undefined) throw new LinqBuildError('JL0101', `unknown chart kind '${this.schema.type}'`);
13
+ return this.with(optionsOf(value, keys, `${this.schema.type}()`));
14
+ }
15
+ /** `title`. @param {any} value */
16
+ title(value) { return this.options({ title: value }); }
17
+ /** `stream`. @param {any} value */
18
+ stream(value) { return this.options({ stream: value }); }
19
+ /** `donut`. @param {any} value */
20
+ donut(value) { return this.options({ donut: value }); }
21
+ /** `slices`. @param {any} value */
22
+ slices(value) { return this.options({ slices: value }); }
23
+ /** `stacked`. @param {any} value */
24
+ stacked(value) { return this.options({ stacked: value }); }
25
+ /** `log`. @param {any} value */
26
+ log(value) { return this.options({ log: value }); }
27
+ /** `orient`. @param {any} value */
28
+ orient(value) { return this.options({ orient: value }); }
29
+ /** `catLabel`. @param {any} value */
30
+ catLabel(value) { return this.options({ catLabel: value }); }
31
+ /** `valLabel`. @param {any} value */
32
+ valLabel(value) { return this.options({ valLabel: value }); }
33
+ /** `categories`. @param {any} value */
34
+ categories(value) { return this.options({ categories: value }); }
35
+ /** `series`. @param {any} value */
36
+ series(value) { return this.options({ series: value }); }
37
+ /** `x`. @param {any} value */
38
+ x(value) { return this.options({ x: value }); }
39
+ /** `markers`. @param {any} value */
40
+ markers(value) { return this.options({ markers: value }); }
41
+ /** `xLabel`. @param {any} value */
42
+ xLabel(value) { return this.options({ xLabel: value }); }
43
+ /** `yLabel`. @param {any} value */
44
+ yLabel(value) { return this.options({ yLabel: value }); }
45
+ /** `domain`. @param {any} value */
46
+ domain(value) { return this.options({ domain: value }); }
47
+ /** `sampling`. @param {any} value */
48
+ sampling(value) { return this.options({ sampling: value }); }
49
+ /** `dateNames`. @param {any} value */
50
+ dateNames(value) { return this.options({ dateNames: value }); }
51
+ /** `timeFormats`. @param {any} value */
52
+ timeFormats(value) { return this.options({ timeFormats: value }); }
53
+ /** `candles`. @param {any} value */
54
+ candles(value) { return this.options({ candles: value }); }
55
+ /** `xLog`. @param {any} value */
56
+ xLog(value) { return this.options({ xLog: value }); }
57
+ /** `yLog`. @param {any} value */
58
+ yLog(value) { return this.options({ yLog: value }); }
59
+ /** `refY`. @param {any} value */
60
+ refY(value) { return this.options({ refY: value }); }
61
+ /** `refLabel`. @param {any} value */
62
+ refLabel(value) { return this.options({ refLabel: value }); }
63
+ /** `points`. @param {any} value */
64
+ points(value) { return this.options({ points: value }); }
65
+ /** `max`. @param {any} value */
66
+ max(value) { return this.options({ max: value }); }
67
+ /** `axes`. @param {any} value */
68
+ axes(value) { return this.options({ axes: value }); }
69
+ /** `value`. @param {any} value */
70
+ value(value) { return this.options({ value: value }); }
71
+ /** `min`. @param {any} value */
72
+ min(value) { return this.options({ min: value }); }
73
+ /** `unit`. @param {any} value */
74
+ unit(value) { return this.options({ unit: value }); }
75
+ /** `tone`. @param {any} value */
76
+ tone(value) { return this.options({ tone: value }); }
77
+ /** `boxes`. @param {any} value */
78
+ boxes(value) { return this.options({ boxes: value }); }
79
+ /** `xLabels`. @param {any} value */
80
+ xLabels(value) { return this.options({ xLabels: value }); }
81
+ /** `yLabels`. @param {any} value */
82
+ yLabels(value) { return this.options({ yLabels: value }); }
83
+ /** `values`. @param {any} value */
84
+ values(value) { return this.options({ values: value }); }
85
+ /** `aspect`. @param {any} value */
86
+ aspect(value) { return this.options({ aspect: value }); }
87
+ /** `items`. @param {any} value */
88
+ items(value) { return this.options({ items: value }); }
89
+ /** `xs`. @param {any} value */
90
+ xs(value) { return this.options({ xs: value }); }
91
+ /** `nodes`. @param {any} value */
92
+ nodes(value) { return this.options({ nodes: value }); }
93
+ /** `links`. @param {any} value */
94
+ links(value) { return this.options({ links: value }); }
95
+ /** `label`. @param {any} value */
96
+ label(value) { return this.options({ label: value }); }
97
+ /** `simplify`. @param {any} value */
98
+ simplify(value) { return this.options({ simplify: value }); }
99
+ /** `features`. @param {any} value */
100
+ features(value) { return this.options({ features: value }); }
101
+ }
102
+
103
+ /** A raw public chart definition, including JSON extensions. @param {any} document */
104
+ export function from(document) { return new ChartBuilder(document); }
105
+
106
+ /** A pie chart. @param {object} [options] */
107
+ export function pie(options = {}) { return new ChartBuilder({ type: 'pie' }).options(options); }
108
+ /** A bar chart. @param {object} [options] */
109
+ export function bar(options = {}) { return new ChartBuilder({ type: 'bar' }).options(options); }
110
+ /** A line chart. @param {object} [options] */
111
+ export function line(options = {}) { return new ChartBuilder({ type: 'line' }).options(options); }
112
+ /** A scatter chart. @param {object} [options] */
113
+ export function scatter(options = {}) { return new ChartBuilder({ type: 'scatter' }).options(options); }
114
+ /** A candlestick chart. @param {object} [options] */
115
+ export function candlestick(options = {}) { return new ChartBuilder({ type: 'candlestick' }).options(options); }
116
+ /** A radar chart. @param {object} [options] */
117
+ export function radar(options = {}) { return new ChartBuilder({ type: 'radar' }).options(options); }
118
+ /** A gauge chart. @param {object} [options] */
119
+ export function gauge(options = {}) { return new ChartBuilder({ type: 'gauge' }).options(options); }
120
+ /** A boxplot chart. @param {object} [options] */
121
+ export function boxplot(options = {}) { return new ChartBuilder({ type: 'boxplot' }).options(options); }
122
+ /** A heatmap chart. @param {object} [options] */
123
+ export function heatmap(options = {}) { return new ChartBuilder({ type: 'heatmap' }).options(options); }
124
+ /** A treemap chart. @param {object} [options] */
125
+ export function treemap(options = {}) { return new ChartBuilder({ type: 'treemap' }).options(options); }
126
+ /** A streamgraph chart. @param {object} [options] */
127
+ export function streamgraph(options = {}) { return new ChartBuilder({ type: 'streamgraph' }).options(options); }
128
+ /** A sankey chart. @param {object} [options] */
129
+ export function sankey(options = {}) { return new ChartBuilder({ type: 'sankey' }).options(options); }
130
+ /** A map chart. @param {object} [options] */
131
+ export function map(options = {}) { return new ChartBuilder({ type: 'map' }).options(options); }
@@ -0,0 +1,119 @@
1
+ // Derived from chart-definition.schema.json by scripts/generate-chart-pen.js.
2
+ /** The known member set for each public chart discriminator. */
3
+ export const CHART_FIELDS = Object.freeze({
4
+ "pie": [
5
+ "title",
6
+ "stream",
7
+ "donut",
8
+ "slices"
9
+ ],
10
+ "bar": [
11
+ "title",
12
+ "stream",
13
+ "stacked",
14
+ "log",
15
+ "orient",
16
+ "catLabel",
17
+ "valLabel",
18
+ "categories",
19
+ "series"
20
+ ],
21
+ "line": [
22
+ "title",
23
+ "stream",
24
+ "x",
25
+ "log",
26
+ "markers",
27
+ "xLabel",
28
+ "yLabel",
29
+ "domain",
30
+ "sampling",
31
+ "dateNames",
32
+ "timeFormats",
33
+ "series"
34
+ ],
35
+ "scatter": [
36
+ "title",
37
+ "stream",
38
+ "xLog",
39
+ "yLog",
40
+ "refY",
41
+ "refLabel",
42
+ "xLabel",
43
+ "yLabel",
44
+ "points"
45
+ ],
46
+ "candlestick": [
47
+ "title",
48
+ "stream",
49
+ "xLabel",
50
+ "yLabel",
51
+ "domain",
52
+ "dateNames",
53
+ "timeFormats",
54
+ "candles"
55
+ ],
56
+ "radar": [
57
+ "title",
58
+ "stream",
59
+ "max",
60
+ "axes",
61
+ "series"
62
+ ],
63
+ "gauge": [
64
+ "title",
65
+ "stream",
66
+ "value",
67
+ "min",
68
+ "max",
69
+ "unit",
70
+ "tone"
71
+ ],
72
+ "boxplot": [
73
+ "title",
74
+ "stream",
75
+ "catLabel",
76
+ "valLabel",
77
+ "boxes"
78
+ ],
79
+ "heatmap": [
80
+ "title",
81
+ "stream",
82
+ "log",
83
+ "xLabel",
84
+ "yLabel",
85
+ "xLabels",
86
+ "yLabels",
87
+ "values"
88
+ ],
89
+ "treemap": [
90
+ "title",
91
+ "stream",
92
+ "aspect",
93
+ "items"
94
+ ],
95
+ "streamgraph": [
96
+ "title",
97
+ "stream",
98
+ "xLabel",
99
+ "xs",
100
+ "series"
101
+ ],
102
+ "sankey": [
103
+ "title",
104
+ "stream",
105
+ "nodes",
106
+ "links"
107
+ ],
108
+ "map": [
109
+ "title",
110
+ "stream",
111
+ "value",
112
+ "label",
113
+ "log",
114
+ "aspect",
115
+ "simplify",
116
+ "features",
117
+ "points"
118
+ ]
119
+ });
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