@jbrowse/cli 5.0.0-beta.13 → 5.0.0-beta.14

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,10 +1,12 @@
1
1
  // Generated by scripts/generateMarkRules.ts from plugins/marks/src/LinearMarkDisplay/markVocabulary.ts: do not edit, `pnpm autogen` rewrites it.
2
2
  /**
3
3
  * The names a `marks` list is written in and the ones a slot left off reads
4
- * as, in a module that imports nothing: the config schema declares its
4
+ * as, in a module that imports only the rule list's seam: the config schema declares its
5
5
  * enumerations and defaults from here, the rule list reads the same constants,
6
- * and `jbrowse validate` carries a copy of both.
6
+ * and `jbrowse validate` carries a copy of both. What a step writes, and
7
+ * the defaults it writes under, are the step table's.
7
8
  */
9
+ export { BIN_OVERLAP_FIELD, DEFAULT_AGGREGATE_OP, DEFAULT_BIN_AS, DEFAULT_COVERAGE_AS, DEFAULT_FORMULA_AS, DEFAULT_PILEUP_AS, } from './markRuleFacts.js';
8
10
  export const MARK_TYPES = [
9
11
  'bar',
10
12
  'point',
@@ -26,34 +28,29 @@ export const DEFAULT_LINK_SHAPE = 'dome';
26
28
  export const DEFAULT_LINK_STROKE_PX = 2;
27
29
  /** The fraction of its row a span fills where its `rowProportion` is left unwritten. */
28
30
  export const DEFAULT_ROW_PROPORTION = 1;
29
- /** The cuts a threshold colour paints, render-core's `MAX_COLOR_CUTS`. */
31
+ /** The cuts a threshold color paints, render-core's `MAX_COLOR_CUTS`. */
30
32
  export const MAX_THRESHOLD_CUTS = 8;
31
33
  export const SIZE_SCALES = ['linear', 'log'];
32
- export const MARK_SOURCES = ['features', 'density'];
33
- export const DEFAULT_MARK_SOURCE = 'features';
34
- export const DEFAULT_FORMULA_AS = 'value';
35
34
  export const DEFAULT_BIN_FIELD = 'start';
36
- export const DEFAULT_BIN_AS = ['start', 'end'];
37
- /** What a `bin` over `fields` writes on each piece: the bases of its interval inside its bin. */
38
- export const BIN_OVERLAP_FIELD = 'overlap';
39
- export const DEFAULT_COVERAGE_AS = 'coverage';
40
35
  export const DEFAULT_FLATTEN_FIELD = 'subfeatures';
41
36
  export const DEFAULT_CELLS_FIELD = 'seq';
42
- /** What a `cells` step writes: `state` on every cell, `base` on a mismatch or an insertion, `match` off a gap or a reference `N`, `length` on an insertion. */
43
- export const CELLS_FIELDS = ['state', 'base', 'match', 'length'];
44
- export const DEFAULT_PILEUP_AS = 'row';
37
+ /** The rows before and after each row a `window` reads: a moving average over 21. */
38
+ export const DEFAULT_WINDOW_FRAME = [-10, 10];
39
+ /**
40
+ * Whether a `window`'s `frame` is what the step reads: two whole row offsets,
41
+ * either `null` for unbounded, the first not past the second.
42
+ */
43
+ export function isWindowFrame(frame) {
44
+ if (!Array.isArray(frame) || frame.length !== 2) {
45
+ return false;
46
+ }
47
+ const [before, after] = frame;
48
+ const end = (v) => v === null || Number.isInteger(v);
49
+ return (end(before) &&
50
+ end(after) &&
51
+ (before === null || after === null || Number(before) <= Number(after)));
52
+ }
45
53
  export const DEFAULT_PILEUP_FIELDS = ['start', 'end'];
46
54
  export const DEFAULT_TEXT_FIELD = 'name';
47
55
  export const DEFAULT_X2 = 'end';
48
- /** What a `mate` step writes on every feature it answers. */
49
- export const MATE_FIELDS = [
50
- 'mate.refName',
51
- 'mate.start',
52
- 'mate.end',
53
- 'mate.mateDirection',
54
- 'mateDirection',
55
- 'alt',
56
- 'svType',
57
- ];
58
56
  export const AGGREGATE_OPS = ['count', 'sum', 'mean', 'min', 'max'];
59
- export const DEFAULT_AGGREGATE_OP = 'count';
@@ -1,55 +1,21 @@
1
1
  // Generated by scripts/generateMarkRules.ts from plugins/marks/src/LinearMarkDisplay/stepChannels.ts: do not edit, `pnpm autogen` rewrites it.
2
- import { aggregateFieldName } from './markRuleFacts.js';
3
- import { DEFAULT_AGGREGATE_OP, DEFAULT_COVERAGE_AS, DEFAULT_PILEUP_AS, } from './markVocabulary.js';
2
+ import { stepsOutput } from './markRuleFacts.js';
4
3
  /** The far end a `mate` step writes, as `x2` reads a position on another sequence. */
5
4
  export const MATE_X2 = { chrom: 'mate.refName', pos: 'mate.start' };
6
- function outputOf(step, fallback) {
7
- return typeof step.as === 'string' && step.as !== '' ? step.as : fallback;
8
- }
9
5
  /**
10
6
  * What {@link StepChannels} a mark's steps leave it, read over the display's,
11
- * the facet's and then the mark's own steps in the order they run. An
12
- * `aggregate` or `coverage` makes its features anew, so it clears the row and
13
- * the other end a step before it wrote, and an aggregate writing two
14
- * summaries names no `y`.
7
+ * the facet's and then the mark's own steps in the order they run. A step
8
+ * that makes its features anew keeps a channel only where it keeps the field
9
+ * that channel read, as an `aggregate` grouped by a pileup's `row` does.
15
10
  */
16
11
  export function stepChannels(steps) {
17
- let channels = {};
18
- for (const step of steps) {
19
- switch (step?.type) {
20
- case undefined: {
21
- break;
22
- }
23
- case 'coverage': {
24
- channels = { y: outputOf(step, DEFAULT_COVERAGE_AS) };
25
- break;
26
- }
27
- case 'aggregate': {
28
- const [only, ...rest] = step.ops ?? [];
29
- channels =
30
- only && rest.length === 0
31
- ? {
32
- y: aggregateFieldName({
33
- op: only.op ?? DEFAULT_AGGREGATE_OP,
34
- field: only.field,
35
- as: only.as,
36
- }),
37
- }
38
- : {};
39
- break;
40
- }
41
- case 'pileup': {
42
- channels = { ...channels, row: outputOf(step, DEFAULT_PILEUP_AS) };
43
- break;
44
- }
45
- case 'mate': {
46
- channels = { ...channels, x2: MATE_X2 };
47
- break;
48
- }
49
- default: {
50
- break;
51
- }
52
- }
53
- }
54
- return channels;
12
+ const { channels, surviving } = stepsOutput(steps);
13
+ const y = channels.get('y');
14
+ const row = channels.get('row');
15
+ const x2 = channels.has('x2') && (!surviving || surviving.has(MATE_X2.pos));
16
+ return {
17
+ ...(y === undefined ? {} : { y }),
18
+ ...(row === undefined ? {} : { row }),
19
+ ...(x2 ? { x2: MATE_X2 } : {}),
20
+ };
55
21
  }
@@ -0,0 +1,202 @@
1
+ // Generated by scripts/generateMarkRules.ts from packages/core/src/util/stepOutputs.ts: do not edit, `pnpm autogen` rewrites it.
2
+ /**
3
+ * What each transform step does to the rows it reads, stated once for the
4
+ * runtime's facet split, the validator, the field pickers and the channels a
5
+ * mark adopts by default. Imports nothing, so the validator's copy of the mark
6
+ * rule list carries it unchanged.
7
+ *
8
+ * Every step type answers three things:
9
+ * - `rowwise`: it answers each row from that row alone and in order, so a
10
+ * facet split may run ahead of it.
11
+ * - `replacesRows`: it makes its rows anew (an aggregate, a coverage), so a
12
+ * field survives it only where it writes that field or keeps it as a group.
13
+ * - `writes`: the fields it sets, each with the kind of value it holds and the
14
+ * channel a mark leaving that channel unwritten reads it through.
15
+ */
16
+ /** The field an aggregate op writes: `as` where named, else `count` for a count, else `<op>_<field>`. */
17
+ export function aggregateFieldName({ op, field, as, }) {
18
+ return as || (op === 'count' || !field ? op : `${op}_${field}`);
19
+ }
20
+ export const DEFAULT_FORMULA_AS = 'value';
21
+ export const DEFAULT_COVERAGE_AS = 'coverage';
22
+ export const DEFAULT_PILEUP_AS = 'row';
23
+ export const DEFAULT_AGGREGATE_OP = 'count';
24
+ export const DEFAULT_BIN_AS = ['start', 'end'];
25
+ /** What a `bin` over `fields` writes on each piece: the bases of its interval inside its bin. */
26
+ export const BIN_OVERLAP_FIELD = 'overlap';
27
+ /** What a `cells` step writes: `state` on every cell, `base` on a mismatch or an insertion, `match` off a gap or a reference `N`, `length` on an insertion. */
28
+ export const CELLS_FIELDS = ['state', 'base', 'match', 'length'];
29
+ /** What a `mate` step writes on every feature it answers. */
30
+ export const MATE_FIELDS = [
31
+ 'mate.refName',
32
+ 'mate.start',
33
+ 'mate.end',
34
+ 'mate.mateDirection',
35
+ 'mateDirection',
36
+ 'alt',
37
+ 'svType',
38
+ ];
39
+ /** Where a row stands, which every row keeps through every step. */
40
+ export const POSITION_FIELDS = ['refName', 'start', 'end'];
41
+ function named(as, fallback) {
42
+ return typeof as === 'string' && as !== '' ? as : fallback;
43
+ }
44
+ function binEdges(step) {
45
+ const { as } = step;
46
+ return Array.isArray(as) && as.length === 2 ? as : DEFAULT_BIN_AS;
47
+ }
48
+ // A single op names the `y` its mark reads; two leave the mark to choose.
49
+ function summaries(step) {
50
+ const ops = step.ops ?? [];
51
+ return ops.map(({ op = DEFAULT_AGGREGATE_OP, field, as }) => ({
52
+ field: aggregateFieldName({ op, field, as }),
53
+ kind: 'numeric',
54
+ ...(ops.length === 1 ? { fills: 'y' } : {}),
55
+ }));
56
+ }
57
+ const kept = (field) => ({ field, kind: 'unknown' });
58
+ export const STEP_OUTPUTS = {
59
+ filter: { rowwise: true, replacesRows: false, writes: () => [] },
60
+ formula: {
61
+ rowwise: true,
62
+ replacesRows: false,
63
+ writes: step => [
64
+ { field: named(step.as, DEFAULT_FORMULA_AS), kind: 'numeric' },
65
+ ],
66
+ },
67
+ bin: {
68
+ rowwise: true,
69
+ replacesRows: false,
70
+ writes: step => [
71
+ ...binEdges(step).map(field => ({ field, kind: 'numeric' })),
72
+ ...(step.fields?.length === 2
73
+ ? [{ field: BIN_OVERLAP_FIELD, kind: 'numeric' }]
74
+ : []),
75
+ ],
76
+ },
77
+ cells: {
78
+ rowwise: true,
79
+ replacesRows: false,
80
+ writes: () => [
81
+ { field: 'start', kind: 'numeric' },
82
+ { field: 'end', kind: 'numeric' },
83
+ { field: 'state', kind: 'categorical' },
84
+ { field: 'base', kind: 'categorical' },
85
+ { field: 'match', kind: 'numeric' },
86
+ { field: 'length', kind: 'numeric' },
87
+ ],
88
+ },
89
+ aggregate: {
90
+ rowwise: false,
91
+ replacesRows: true,
92
+ writes: (step, edges) => [
93
+ ...(step.groupby?.length ? step.groupby : edges).map(kept),
94
+ ...summaries(step),
95
+ ],
96
+ },
97
+ window: { rowwise: false, replacesRows: false, writes: summaries },
98
+ coverage: {
99
+ rowwise: false,
100
+ replacesRows: true,
101
+ writes: step => [
102
+ {
103
+ field: named(step.as, DEFAULT_COVERAGE_AS),
104
+ kind: 'numeric',
105
+ fills: 'y',
106
+ },
107
+ ],
108
+ },
109
+ pileup: {
110
+ rowwise: false,
111
+ replacesRows: false,
112
+ writes: step => [
113
+ {
114
+ field: named(step.as, DEFAULT_PILEUP_AS),
115
+ kind: 'numeric',
116
+ fills: 'row',
117
+ },
118
+ ],
119
+ },
120
+ flatten: {
121
+ rowwise: false,
122
+ replacesRows: false,
123
+ writes: step => [
124
+ ...(step.index ? [{ field: step.index, kind: 'numeric' }] : []),
125
+ ...(step.key ? [{ field: step.key, kind: 'categorical' }] : []),
126
+ ],
127
+ },
128
+ mate: {
129
+ rowwise: false,
130
+ replacesRows: false,
131
+ writes: () => MATE_FIELDS.map(field => ({
132
+ field,
133
+ kind: field === 'mate.start' || field === 'mate.end'
134
+ ? 'numeric'
135
+ : 'categorical',
136
+ ...(field === 'mate.refName' ? { fills: 'x2' } : {}),
137
+ })),
138
+ },
139
+ };
140
+ function outputOf(step) {
141
+ return Object.hasOwn(STEP_OUTPUTS, step.type)
142
+ ? STEP_OUTPUTS[step.type]
143
+ : undefined;
144
+ }
145
+ /**
146
+ * The fields one step writes. A step this table does not know writes nothing
147
+ * it can name.
148
+ */
149
+ export function stepWrites(step, edges = DEFAULT_BIN_AS) {
150
+ return outputOf(step)?.writes(step, edges) ?? [];
151
+ }
152
+ /** Whether a step answers each row from that row alone, in order. */
153
+ export function isRowwise(step) {
154
+ return outputOf(step)?.rowwise ?? false;
155
+ }
156
+ /**
157
+ * What a run of steps leaves: every field written, the last write of each
158
+ * winning, and, where a step made the rows anew, the only fields that survive
159
+ * it (`undefined` while the input's own fields all do). `channels` are what
160
+ * the output fills where a mark leaves them unwritten.
161
+ */
162
+ export function stepsOutput(steps) {
163
+ let edges = DEFAULT_BIN_AS;
164
+ let surviving;
165
+ const written = new Map();
166
+ let channels = new Map();
167
+ for (const step of steps) {
168
+ const output = step && outputOf(step);
169
+ if (!step || !output) {
170
+ continue;
171
+ }
172
+ const writes = output.writes(step, edges);
173
+ if (output.replacesRows) {
174
+ surviving = new Set(POSITION_FIELDS);
175
+ for (const [field] of written) {
176
+ if (!writes.some(w => w.field === field)) {
177
+ written.delete(field);
178
+ }
179
+ }
180
+ for (const w of writes) {
181
+ surviving.add(w.field);
182
+ }
183
+ channels = new Map([...channels].filter(([, f]) => surviving.has(f)));
184
+ }
185
+ else {
186
+ for (const w of writes) {
187
+ surviving?.add(w.field);
188
+ }
189
+ }
190
+ for (const w of writes) {
191
+ const held = written.get(w.field);
192
+ written.set(w.field, w.kind === 'unknown' && held ? { ...held, field: w.field } : w);
193
+ if (w.fills) {
194
+ channels.set(w.fills, w.field);
195
+ }
196
+ }
197
+ if (step.type === 'bin') {
198
+ edges = binEdges(step);
199
+ }
200
+ }
201
+ return { written: [...written.values()], surviving, channels };
202
+ }
@@ -175,8 +175,8 @@ function unknownKeyMessage(key, schema, accepted) {
175
175
  if (title.endsWith('TrackEntry')) {
176
176
  return `"${key}" is neither a config slot nor a property of ${title.replace(/TrackEntry$/, '')}${guess} — the entry's keys are folded onto that display, and one it does not declare silently does nothing`;
177
177
  }
178
- if (schema['x-closed'] === true) {
179
- return `unknown slot "${key}"${guess} — ${title} takes ${listed(accepted)}, and JBrowse refuses to load it rather than drop a key it does not declare`;
178
+ if (schema['x-closed']) {
179
+ return `unknown slot "${key}"${guess} — ${title} takes ${listed(accepted)}; JBrowse warns on the console and loads without it, so this setting does nothing`;
180
180
  }
181
181
  return `unknown slot "${key}"${guess} — JBrowse ignores keys it does not declare, so this setting silently does nothing`;
182
182
  }
@@ -422,4 +422,7 @@ export function hasDeclaredShape(data, pointer) {
422
422
  * beside them, the way `LinearGenomeViewPlugin` is core's.
423
423
  */
424
424
  export const rootConfigurationSlots = new Set(Object.keys(defs.RootConfiguration.properties));
425
+ export function hasSchemaDefinition(name) {
426
+ return Object.hasOwn(defs, name);
427
+ }
425
428
  export { schemaId as configSchemaUrl };
@@ -3,16 +3,17 @@
3
3
  // cross-references a schema cannot express and the warnings for stale
4
4
  // spellings a migration still rewrites.
5
5
  //
6
- // Why a validator at all, given MST type-checks a config on load: MST models
7
- // ignore snapshot keys they do not declare, so a misspelt slot leaves the track
8
- // loading normally with the setting doing nothing.
6
+ // Why a validator at all, given MST type-checks a config on load: a key no
7
+ // schema declares does nothing, named on the console by a display and dropped
8
+ // in silence by a track, an adapter or a session snapshot, so a misspelt slot
9
+ // leaves the track loading normally.
9
10
  //
10
11
  // Pure: no filesystem, no process exit. The command wrapper owns both.
11
- import { fileNameOf, isLooseTrackConfig, matchFormat, } from '@jbrowse/add-track-core';
12
+ import { fileNameOf, isLooseTrackConfig, matchFormat, trackTypeForAdapter, } from '@jbrowse/add-track-core';
12
13
  import { configManifest } from './configManifest.generated.js';
13
14
  import { displayDefaultsForTrackType } from './displayDefaultKeys.js';
14
15
  import { isRecord, liftToSnapshot } from './liftConfig.js';
15
- import { colorProblems, colorSlotsOf, scaleEndProblems, scaleEndsOf, } from './markRules/colorScale.js';
16
+ import { colorProblems, colorSlotsOf, scaleEndProblems, scaleEndsOf, withImpliedField, } from './markRules/colorScale.js';
16
17
  import { markProblems } from './markRules/markProblems.js';
17
18
  import { hasDeclaredShape, rootConfigurationSlots, schemaProblems, } from './schemaValidate.js';
18
19
  import { didYouMean } from './suggest.js';
@@ -44,6 +45,12 @@ class Report {
44
45
  const SELF_SUPPLIED = {
45
46
  sequenceAdapter: '`sequenceAdapter` is set by hand. JBrowse takes the sequence from the assembly the track is displayed against, so this is only needed to read some OTHER sequence — and it pins the track to that source even when the assembly changes. Delete it unless that is what you meant',
46
47
  };
48
+ // What replaced a dropped legacy key, where there is something to say: a
49
+ // config written before v4 carries a `sequenceAdapter` on its BAM and CRAM
50
+ // adapters.
51
+ const DROPPED = {
52
+ sequenceAdapter: 'JBrowse takes the sequence from the assembly the track is displayed against. ',
53
+ };
47
54
  // The warnings a slot table carries: a legacy key or value a migration
48
55
  // rewrites, and a declared key JBrowse fills in for itself.
49
56
  function warnSlots(obj, entry, where, report) {
@@ -56,7 +63,9 @@ function warnSlots(obj, entry, where, report) {
56
63
  report.warn(`${where}.${key}`, `${JSON.stringify(value)} is a legacy value of "${key}" that a migration rewrites — the config loads, but the current spelling is one of the enum's members`);
57
64
  }
58
65
  else if (!declared.has(key) && entry.legacyKeys?.includes(key)) {
59
- report.warn(`${where}.${key}`, `"${key}" is a legacy key that a migration rewrites into current slots — the config loads, but check the settings inside it landed`);
66
+ report.warn(`${where}.${key}`, entry.droppedKeys?.includes(key)
67
+ ? `"${key}" is a legacy key that is never read. ${DROPPED[key] ?? ''}The config loads, and the key can be deleted`
68
+ : `"${key}" is a legacy key that a migration rewrites into current slots — the config loads, but check the settings inside it landed`);
60
69
  }
61
70
  }
62
71
  for (const slot of entry.slots) {
@@ -337,7 +346,7 @@ function checkMarkDisplay(display, manifest, where, report) {
337
346
  });
338
347
  }
339
348
  }
340
- // A problem the colour and scale rules and the mark rule list both reach, such
349
+ // A problem the color and scale rules and the mark rule list both reach, such
341
350
  // as scales.y's ends on a mark display, is reported once.
342
351
  function pushOnce(report, problem) {
343
352
  if (!report.problems.some(p => p.where === problem.where && p.rule === problem.rule)) {
@@ -352,7 +361,7 @@ function declaredMembers(written, slot) {
352
361
  const declared = new Set((slot.subSlots ?? []).map(s => s.name));
353
362
  return Object.fromEntries(Object.entries(written).filter(([key]) => declared.has(key)));
354
363
  }
355
- // What the display's colour objects and its value scale say together that it
364
+ // What the display's color objects and its value scale say together that it
356
365
  // cannot draw as written: its schema's fieldPresets stand in for the plugin
357
366
  // code the CLI does not run, and every quantitative scale's ends answer to
358
367
  // one rule.
@@ -376,9 +385,9 @@ function checkScaleSlots(display, slots, where, report) {
376
385
  }
377
386
  const members = declaredMembers(written, slot);
378
387
  if (slot.fieldPresets) {
379
- for (const problem of colorProblems(colorSlotsOf(name => name === 'field'
388
+ for (const problem of colorProblems(withImpliedField(colorSlotsOf(name => name === 'field'
380
389
  ? (members.field ?? slot.fieldDefault)
381
- : members[name]), slot.fieldPresets)) {
390
+ : members[name]), slot.impliedField), slot.fieldPresets)) {
382
391
  warn(`${where}.${slot.name}`, problem);
383
392
  }
384
393
  }
@@ -395,6 +404,30 @@ function checkScaleSlots(display, slots, where, report) {
395
404
  // entry. Only a mark display declares `marks`, so the walk is over the whole
396
405
  // file, past a place where the schema refused the key: a session display node
397
406
  // drops it.
407
+ // a track's type as written, or as a loose `{ trackId, uri }` entry's file
408
+ // name decides it, the way add-track does
409
+ function trackTypeOf(node) {
410
+ if (typeof node.type === 'string') {
411
+ return node.type;
412
+ }
413
+ if (typeof node.uri !== 'string') {
414
+ return undefined;
415
+ }
416
+ const fileName = fileNameOf(node.uri);
417
+ const format = matchFormat(fileName, typeof node.adapterType === 'string' ? node.adapterType : undefined);
418
+ return (format?.trackType ??
419
+ (format && 'adapterType' in format.spec
420
+ ? trackTypeForAdapter(format.spec.adapterType, fileName)
421
+ : undefined));
422
+ }
423
+ // The shorthand router hands a `displayDefaults` key only to the displays
424
+ // whose slot takes its value (`collectDisplayOverrides`), so a categorical
425
+ // color on a FeatureTrack never reaches its quantitative display's `score`
426
+ // presets. The same cut here, through each display's own schema branch.
427
+ function displayDefaultsReaching(display, defaults) {
428
+ return Object.fromEntries(Object.entries(defaults).filter(([key, value]) => schemaProblems({ type: display, [key]: value }, `/$defs/${display}`)
429
+ .length === 0));
430
+ }
398
431
  function checkMarkDisplays(node, manifest, where, report) {
399
432
  if (Array.isArray(node)) {
400
433
  for (const [i, item] of node.entries()) {
@@ -408,10 +441,11 @@ function checkMarkDisplays(node, manifest, where, report) {
408
441
  if (slots) {
409
442
  checkScaleSlots(node, slots, where, report);
410
443
  }
411
- if (typeof node.type === 'string' && isRecord(node.displayDefaults)) {
412
- for (const display of displayDefaultsForTrackType(node.type, manifest)
444
+ const trackType = trackTypeOf(node);
445
+ if (trackType && isRecord(node.displayDefaults)) {
446
+ for (const display of displayDefaultsForTrackType(trackType, manifest)
413
447
  .displayTypes) {
414
- checkScaleSlots(node.displayDefaults, manifest.displays[display]?.slots ?? [], `${where}.displayDefaults`, report);
448
+ checkScaleSlots(displayDefaultsReaching(display, node.displayDefaults), manifest.displays[display]?.slots ?? [], `${where}.displayDefaults`, report);
415
449
  }
416
450
  }
417
451
  if (holdsMarkRules(node, manifest) &&
package/dist/index.js CHANGED
@@ -51,7 +51,7 @@ const registry = [
51
51
  },
52
52
  {
53
53
  name: 'make-density',
54
- summary: 'Counts feature starts per bin into a bigWig density sidecar, with bedGraphToBigWig',
54
+ summary: 'Counts feature starts per bin into a bigWig, with bedGraphToBigWig',
55
55
  load: () => import('./commands/make-density/index.js').then(m => m.run),
56
56
  },
57
57
  {
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const version = '5.0.0-beta.13';
1
+ export const version = '5.0.0-beta.14';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jbrowse/cli",
3
- "version": "5.0.0-beta.13",
3
+ "version": "5.0.0-beta.14",
4
4
  "type": "module",
5
5
  "description": "A command line tool for working with JBrowse 2",
6
6
  "keywords": [
@@ -31,9 +31,9 @@
31
31
  "cli-progress": "^3.12.0",
32
32
  "serve-handler": "^6.1.7",
33
33
  "tmp": "^0.2.7",
34
- "@jbrowse/cigar-utils": "^5.0.0-beta.13",
35
- "@jbrowse/add-track-core": "^5.0.0-beta.13",
36
- "@jbrowse/text-indexing-core": "^5.0.0-beta.13"
34
+ "@jbrowse/add-track-core": "^5.0.0-beta.14",
35
+ "@jbrowse/cigar-utils": "^5.0.0-beta.14",
36
+ "@jbrowse/text-indexing-core": "^5.0.0-beta.14"
37
37
  },
38
38
  "publishConfig": {
39
39
  "access": "public"
@@ -1,12 +0,0 @@
1
- /**
2
- * Where the density sidecar for a data file lives: `<file>.density.bw`, with a
3
- * `.gz`/`.bgz` stripped first so `genes.gff3.gz` yields `genes.gff3.density.bw`
4
- * rather than a name carrying the compression of a file it is not compressed
5
- * like.
6
- *
7
- * One rule, two commands: `make-density` writes here by default and `add-track`
8
- * probes here, so a sidecar built with no `--out` is the one the track picks up.
9
- */
10
- export function densitySidecarPath(file) {
11
- return `${file.replace(/\.b?gz$/i, '')}.density.bw`;
12
- }
@@ -1,9 +0,0 @@
1
- // Generated by scripts/generateMarkRules.ts from packages/core/src/util/aggregateFieldName.ts: do not edit, `pnpm autogen` rewrites it.
2
- /**
3
- * The field an aggregate op writes: `as` where named, else `count` for a
4
- * count, else `<op>_<field>`. Imports nothing, so the validator's copy of the
5
- * mark rule list carries it unchanged.
6
- */
7
- export function aggregateFieldName({ op, field, as, }) {
8
- return as || (op === 'count' || !field ? op : `${op}_${field}`);
9
- }