ggaction 0.0.9 → 0.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (222) hide show
  1. package/CHANGELOG.md +84 -0
  2. package/README.md +5 -4
  3. package/knowledge/action-card.schema.json +1 -0
  4. package/knowledge/action-cards.json +1 -10941
  5. package/knowledge/action-cards.schema.json +1 -0
  6. package/knowledge/extension-authoring.md +248 -0
  7. package/knowledge/intent-taxonomy.json +1 -183
  8. package/knowledge/intent-taxonomy.schema.json +1 -0
  9. package/knowledge/mcp-resources.json +1 -95
  10. package/knowledge/mcp-resources.schema.json +1 -0
  11. package/knowledge/task-packet.schema.json +1 -159
  12. package/knowledge/task-resolver.js +1 -1230
  13. package/package.json +19 -2
  14. package/src/actions/boxPlots/edit.js +45 -298
  15. package/src/actions/boxPlots/options.js +46 -77
  16. package/src/actions/boxPlots/resolve.js +1 -1
  17. package/src/actions/charts/bar.js +3 -0
  18. package/src/actions/charts/heatmap.js +73 -83
  19. package/src/actions/charts/index.js +1 -1
  20. package/src/actions/charts/parallel.js +35 -1
  21. package/src/actions/charts/shared.js +20 -0
  22. package/src/actions/composition/actions.js +46 -49
  23. package/src/actions/data/bin2d.js +105 -2
  24. package/src/actions/data/box.js +17 -17
  25. package/src/actions/data/density.js +42 -78
  26. package/src/actions/data/gradientProfile.js +22 -52
  27. package/src/actions/data/horizon.js +16 -41
  28. package/src/actions/data/index.js +10 -10
  29. package/src/actions/data/interval.js +16 -38
  30. package/src/actions/data/intervalEdit.js +55 -0
  31. package/src/actions/data/regression.js +7 -17
  32. package/src/actions/data/shared.js +47 -0
  33. package/src/actions/data/timeUnit.js +14 -38
  34. package/src/actions/data/window.js +14 -38
  35. package/src/actions/distributions/revision.js +154 -34
  36. package/src/actions/encodings/angle.js +9 -10
  37. package/src/actions/encodings/appearance.js +17 -51
  38. package/src/actions/encodings/density/resolve.js +3 -1
  39. package/src/actions/encodings/density.js +1 -15
  40. package/src/actions/encodings/horizon/resolve.js +13 -3
  41. package/src/actions/encodings/horizon.js +8 -7
  42. package/src/actions/encodings/index.js +9 -9
  43. package/src/actions/encodings/offset.js +8 -24
  44. package/src/actions/encodings/parallel.js +9 -10
  45. package/src/actions/encodings/pathOrder.js +6 -13
  46. package/src/actions/encodings/position/policies/index.js +4 -4
  47. package/src/actions/encodings/position/policies/line.js +47 -17
  48. package/src/actions/encodings/position/resolve.js +24 -5
  49. package/src/actions/encodings/ranged.js +18 -23
  50. package/src/actions/encodings/remove.js +15 -25
  51. package/src/actions/encodings/ruleAppearance.js +9 -24
  52. package/src/actions/encodings/shared.js +37 -0
  53. package/src/actions/encodings/strokeDash.js +8 -23
  54. package/src/actions/encodings/text.js +9 -10
  55. package/src/actions/errorBands/create.js +105 -39
  56. package/src/actions/errorBands/edit.js +89 -93
  57. package/src/actions/errorBands/index.js +1 -2
  58. package/src/actions/errorBars/create.js +78 -27
  59. package/src/actions/errorBars/edit.js +81 -48
  60. package/src/actions/errorBars/index.js +1 -2
  61. package/src/actions/facets/actions.js +45 -69
  62. package/src/actions/facets/derive.js +38 -53
  63. package/src/actions/facets/replay.js +0 -1
  64. package/src/actions/gradientPlots/components.js +59 -48
  65. package/src/actions/gradientPlots/edit.js +35 -216
  66. package/src/actions/gradientPlots/index.js +11 -10
  67. package/src/actions/gradientPlots/materialize.js +21 -35
  68. package/src/actions/gradientPlots/options.js +5 -7
  69. package/src/actions/gradientPlots/paint.js +9 -6
  70. package/src/actions/gradientPlots/resolve.js +1 -1
  71. package/src/actions/guides/axes/index.js +3 -3
  72. package/src/actions/guides/axes/labels.js +68 -26
  73. package/src/actions/guides/axes/lines.js +22 -2
  74. package/src/actions/guides/axes/policy.js +28 -8
  75. package/src/actions/guides/axes/ticks.js +27 -9
  76. package/src/actions/guides/axes/titles.js +113 -65
  77. package/src/actions/guides/grids/resolve.js +14 -0
  78. package/src/actions/guides/guides.js +2 -4
  79. package/src/actions/guides/index.js +2 -2
  80. package/src/actions/guides/legends/categorical/actions.js +44 -68
  81. package/src/actions/guides/legends/categorical/components.js +6 -1
  82. package/src/actions/guides/legends/categorical/index.js +2 -2
  83. package/src/actions/guides/legends/categorical/layout.js +148 -175
  84. package/src/actions/guides/legends/categorical/recipes.js +5 -0
  85. package/src/actions/guides/legends/categorical/resolve.js +8 -1
  86. package/src/actions/guides/legends/continuous/common.js +117 -66
  87. package/src/actions/guides/legends/continuous/gradient.js +38 -37
  88. package/src/actions/guides/legends/continuous/interval.js +97 -76
  89. package/src/actions/guides/legends/continuous/opacity.js +28 -38
  90. package/src/actions/guides/legends/edit.js +14 -1
  91. package/src/actions/guides/legends/index.js +1 -1
  92. package/src/actions/guides/legends/lane.js +2 -1
  93. package/src/actions/guides/legends/remove.js +8 -0
  94. package/src/actions/guides/legends/size.js +36 -43
  95. package/src/actions/guides/legends/strokeWidth.js +20 -26
  96. package/src/actions/guides/polar/axes/labels.js +17 -1
  97. package/src/actions/guides/polar/axes/shared.js +7 -1
  98. package/src/actions/guides/polar/axes/titles.js +19 -2
  99. package/src/actions/guides/polar/grids.js +4 -0
  100. package/src/actions/guides/polar/resolve.js +6 -0
  101. package/src/actions/index.js +13 -13
  102. package/src/actions/intervals/resolve.js +87 -117
  103. package/src/actions/marks/arc/actions.js +31 -36
  104. package/src/actions/marks/area/actions.js +23 -31
  105. package/src/actions/marks/index.js +6 -6
  106. package/src/actions/marks/line/actions.js +33 -52
  107. package/src/actions/marks/line/materialize.js +7 -5
  108. package/src/actions/marks/point/materialize.js +5 -3
  109. package/src/actions/marks/remove.js +21 -0
  110. package/src/actions/marks/rule/actions.js +53 -53
  111. package/src/actions/marks/shared.js +8 -4
  112. package/src/actions/marks/text/actions.js +14 -6
  113. package/src/actions/marks/text/layout.js +21 -45
  114. package/src/actions/marks/tick/actions.js +22 -21
  115. package/src/actions/primitives/createGraphics.js +4 -0
  116. package/src/actions/primitives/editGraphics.js +4 -0
  117. package/src/actions/primitives/index.js +3 -3
  118. package/src/actions/primitives/semantic.js +1 -1
  119. package/src/actions/primitives/semanticValidation/index.js +2 -2
  120. package/src/actions/primitives/semanticValidation/layer.js +1 -1
  121. package/src/actions/regression/edit.js +3 -43
  122. package/src/actions/scales/consumers/families.js +24 -4
  123. package/src/actions/scales/consumers/index.js +1 -1
  124. package/src/actions/scales/consumers/seriesLayout.js +17 -0
  125. package/src/actions/scales/definitions.js +100 -103
  126. package/src/actions/scales/materialize.js +5 -0
  127. package/src/actions/selection/actions.js +79 -121
  128. package/src/actions/titles/actions.js +48 -94
  129. package/src/actions/titles/resolve.js +14 -27
  130. package/src/actions/violinPlots/create.js +37 -44
  131. package/src/core/action.js +20 -5
  132. package/src/core/extensionRegistry.js +104 -0
  133. package/src/core/textMetrics.js +74 -37
  134. package/src/core/validation.js +18 -0
  135. package/src/extension.js +8 -1
  136. package/src/grammar/aggregate.js +48 -28
  137. package/src/grammar/arcs.js +58 -11
  138. package/src/grammar/areaSeries.js +14 -16
  139. package/src/grammar/bin2d.js +37 -23
  140. package/src/grammar/boxPlot.js +14 -13
  141. package/src/grammar/categoricalDensity.js +14 -14
  142. package/src/grammar/categoryOrder.js +8 -14
  143. package/src/grammar/curveCommands.js +87 -20
  144. package/src/grammar/density.js +162 -141
  145. package/src/grammar/facets/index.js +14 -0
  146. package/src/grammar/facets/scales.js +7 -4
  147. package/src/grammar/gradientProfile.js +12 -15
  148. package/src/grammar/histogram.js +145 -83
  149. package/src/grammar/horizon.js +60 -23
  150. package/src/grammar/interval.js +14 -13
  151. package/src/grammar/lineSeries.js +91 -61
  152. package/src/grammar/numeric.js +290 -0
  153. package/src/grammar/paint.js +3 -4
  154. package/src/grammar/palettes.js +21 -32
  155. package/src/grammar/pathCommands.js +6 -0
  156. package/src/grammar/polarPaths.js +5 -5
  157. package/src/grammar/regression/derive.js +48 -9
  158. package/src/grammar/regression/models.js +248 -69
  159. package/src/grammar/regression/parameters.js +8 -0
  160. package/src/grammar/scales/color.js +35 -26
  161. package/src/grammar/scales/continuous.js +71 -24
  162. package/src/grammar/scales/definition.js +1 -1
  163. package/src/grammar/scales/discretized.js +42 -12
  164. package/src/grammar/scales/fields.js +21 -4
  165. package/src/grammar/scales/ordinal.js +117 -61
  166. package/src/grammar/scales/temporal.js +40 -11
  167. package/src/grammar/scales/transformed.js +199 -52
  168. package/src/grammar/schemas/graphicBounds.js +270 -79
  169. package/src/grammar/seriesLayout.js +50 -18
  170. package/src/grammar/ticks.js +123 -53
  171. package/src/grammar/timeUnit.js +18 -8
  172. package/src/grammar/transforms.js +4 -1
  173. package/src/grammar/window.js +70 -57
  174. package/src/index.js +1 -1
  175. package/src/layout/canvas.js +4 -8
  176. package/src/layout/composition.js +39 -40
  177. package/src/layout/facets.js +10 -14
  178. package/src/layout/labels.js +91 -15
  179. package/src/layout/legend.js +22 -20
  180. package/src/layout/legendLane.js +54 -40
  181. package/src/layout/title.js +7 -7
  182. package/src/materialization/bars/aggregate.js +14 -40
  183. package/src/materialization/bars/grouped.js +7 -18
  184. package/src/materialization/bars/histogram.js +2 -19
  185. package/src/materialization/bars/ranged.js +20 -15
  186. package/src/materialization/bars/resolve.js +21 -0
  187. package/src/materialization/facetGuides/legacyCategorical.js +2 -1
  188. package/src/materialization/facetGuides/placement.js +34 -19
  189. package/src/materialization/facetGuides/preparation.js +9 -5
  190. package/src/materialization/facets.js +39 -27
  191. package/src/materialization/guides/resources.js +2 -1
  192. package/src/materialization/marks/capabilities.js +5 -2
  193. package/src/materialization/marks/index.js +24 -4
  194. package/src/materialization/scales/policies/bar.js +61 -59
  195. package/src/materialization/scales/policies/binnedPosition.js +34 -0
  196. package/src/materialization/scales/policies/series.js +13 -7
  197. package/src/materialization/scales/resolve.js +4 -5
  198. package/src/materialization/selection/items/arc.js +16 -2
  199. package/src/materialization/selection/items/bar.js +4 -2
  200. package/src/materialization/selection/items/common.js +21 -1
  201. package/src/materialization/selection/items/path.js +19 -2
  202. package/src/materialization/selection/items/point.js +4 -16
  203. package/src/materialization/selection/items/tick.js +13 -21
  204. package/src/materialization/selection/point.js +11 -4
  205. package/src/materialization/selection/styles.js +19 -27
  206. package/src/materialization/text.js +4 -1
  207. package/src/mcp/adapter.js +8 -3
  208. package/src/renderers/canvas/fill.js +2 -2
  209. package/src/renderers/canvas/index.js +35 -2
  210. package/src/renderers/canvas/native.js +160 -0
  211. package/src/renderers/pdf.js +14 -0
  212. package/src/renderers/svg.js +37 -4
  213. package/types/extension.d.ts +19 -0
  214. package/types/index.d.ts +3 -0
  215. package/types/program.d.ts +509 -131
  216. package/types/svg.d.ts +1 -0
  217. package/src/actions/errorBands/components.js +0 -81
  218. package/src/actions/errorBands/options.js +0 -39
  219. package/src/actions/errorBands/resolve.js +0 -28
  220. package/src/actions/errorBars/components.js +0 -62
  221. package/src/actions/errorBars/options.js +0 -58
  222. package/src/actions/errorBars/resolve.js +0 -25
@@ -14,6 +14,7 @@ import {
14
14
  findDataset,
15
15
  findDatasetConsumer
16
16
  } from "../../selectors/datasets.js";
17
+ import { requireLayer } from "../../selectors/layers.js";
17
18
  export { materializeBin2DData } from "./bin2dMaterialize.js";
18
19
 
19
20
  const OPTIONS = Object.freeze([
@@ -24,7 +25,7 @@ const EDIT_OPTIONS = Object.freeze([
24
25
  ]);
25
26
  const EDITABLE = Object.freeze(EDIT_OPTIONS.slice(1));
26
27
  const OUTPUT_FIELDS = Object.freeze([
27
- "x0", "x1", "y0", "y1", "count"
28
+ "x0", "x1", "y0", "y1", "count", "members"
28
29
  ]);
29
30
 
30
31
  function ownerConfig(program, id) {
@@ -74,6 +75,106 @@ function directLayerConsumers(program, data) {
74
75
  .map(layer => layer.id);
75
76
  }
76
77
 
78
+ function outputFieldChanges(previous, next) {
79
+ return new Map(OUTPUT_FIELDS.flatMap(role => {
80
+ const from = previous.as[role];
81
+ const to = next.as[role];
82
+ return from !== undefined && from !== to
83
+ ? [[from, [role, to]]]
84
+ : [];
85
+ }));
86
+ }
87
+
88
+ function changedConsumerField(field, changes) {
89
+ const change = changes.get(field);
90
+ if (change === undefined) return field;
91
+ const [role, next] = change;
92
+ if (next === undefined) {
93
+ throw new Error(
94
+ `Cannot remove referenced 2D bin ${role} output field "${field}".`
95
+ );
96
+ }
97
+ return next;
98
+ }
99
+
100
+ function rebindLayerOutputFields(program, id, changes) {
101
+ const layer = requireLayer(program, id);
102
+ let next = program;
103
+ const changed = field => changedConsumerField(field, changes);
104
+ const editField = (property, field) => {
105
+ if (field === undefined) return;
106
+ const value = changed(field);
107
+ if (value !== field) next = next.editSemantic({ property, value });
108
+ };
109
+ for (const [channel, encoding] of Object.entries(layer.encoding ?? {})) {
110
+ editField(
111
+ `layer[${id}].encoding.${channel}.field`,
112
+ encoding?.field
113
+ );
114
+ const summary = encoding?.categoryOrder?.by;
115
+ if (summary?.field !== undefined) {
116
+ const field = changed(summary.field);
117
+ if (field !== summary.field) {
118
+ next = next.editSemantic({
119
+ property: `layer[${id}].encoding.${channel}.categoryOrder`,
120
+ value: { ...encoding.categoryOrder, by: { ...summary, field } }
121
+ });
122
+ }
123
+ }
124
+ }
125
+ editField(
126
+ `layer[${id}].encoding.theta.weight`,
127
+ layer.encoding?.theta?.weight
128
+ );
129
+
130
+ const parallel = layer.encoding?.parallel;
131
+ if (parallel?.dimensions !== undefined) {
132
+ const dimensions = parallel.dimensions.map(dimension => {
133
+ const field = changed(dimension.field);
134
+ return { ...dimension, field };
135
+ });
136
+ if (dimensions.some((dimension, index) =>
137
+ dimension.field !== parallel.dimensions[index].field
138
+ )) {
139
+ next = next.editSemantic({
140
+ property: `layer[${id}].encoding.parallel.dimensions`,
141
+ value: dimensions
142
+ });
143
+ }
144
+ }
145
+ editField(
146
+ `layer[${id}].encoding.parallel.key`,
147
+ parallel?.key
148
+ );
149
+
150
+ for (const [selectionId, config] of Object.entries(
151
+ program.materializationConfigs.selections ?? {}
152
+ )) {
153
+ if (config.target !== id) continue;
154
+ const selector = { ...config.selector };
155
+ if (selector.field !== undefined) {
156
+ selector.field = changed(selector.field);
157
+ }
158
+ if (selector.groupBy !== undefined) {
159
+ selector.groupBy = selector.groupBy.map(changed);
160
+ }
161
+ if (JSON.stringify(selector) !== JSON.stringify(config.selector)) {
162
+ next = next._withSelectionConfig(selectionId, { ...config, selector });
163
+ }
164
+ }
165
+
166
+ const jitter = program.materializationConfigs.jitters?.[id];
167
+ const key = jitter?.key === undefined
168
+ ? undefined
169
+ : changed(jitter.key);
170
+ if (key !== undefined && key !== jitter.key) {
171
+ next = next._withMaterializationConfig(
172
+ ["jitters", id], { ...jitter, key }
173
+ );
174
+ }
175
+ return next;
176
+ }
177
+
77
178
  function rejectDerivedConsumers(program, data) {
78
179
  const dependent = findDatasetConsumer(program, data);
79
180
  if (dependent !== undefined) {
@@ -93,7 +194,7 @@ function preflight(program, sourceId, transform) {
93
194
  }
94
195
 
95
196
  function requireCompleteEditOutputFields(value, members) {
96
- const required = [...OUTPUT_FIELDS, ...(members ? ["members"] : [])];
197
+ const required = OUTPUT_FIELDS.filter(field => field !== "members" || members);
97
198
  const missing = required.find(field => !Object.hasOwn(value, field));
98
199
  if (missing !== undefined) {
99
200
  throw new Error(
@@ -140,6 +241,7 @@ function sameRequestedTransform(left, right) {
140
241
  function applyBin2DRevision(program, { owner, previous, source, transform }) {
141
242
  rejectDerivedConsumers(program, previous.id);
142
243
  const consumers = directLayerConsumers(program, previous.id);
244
+ const changes = outputFieldChanges(previous.transform[0], transform);
143
245
  const revision = planDerivedDataRevision(program, {
144
246
  owner,
145
247
  role: "Bin2DData",
@@ -151,6 +253,7 @@ function applyBin2DRevision(program, { owner, previous, source, transform }) {
151
253
  .materializeBin2DData({ id: revision.id });
152
254
  for (const rebind of revision.rebinds) {
153
255
  next = next.rebindLayerData(rebind);
256
+ next = rebindLayerOutputFields(next, rebind.id, changes);
154
257
  next = applyLayerDataRematerialization(next, rebind.id);
155
258
  }
156
259
  next = next.releaseDerivedData(revision.release);
@@ -1,39 +1,39 @@
1
- import { action } from "../../core/action.js";
2
- import { validateUserId } from "../../core/identifiers.js";
3
- import { validateKeys } from "../../core/validation.js";
4
1
  import { BOX_FIELDS, deriveBoxData, normalizeBoxTransform } from "../../grammar/boxPlot.js";
5
- import { MATERIALIZE_OPTIONS, requireDerivedDataset } from "./shared.js";
2
+ import { derivedCreator, derivedMaterializer } from "./shared.js";
6
3
 
7
4
  const OPTIONS = Object.freeze([
8
5
  "id", "source", "category", "field", "whisker", "factor", "as"
9
6
  ]);
10
7
 
11
8
  function materializer(type, op, select) {
12
- return action({ op, description: `Materialize ${type} box-plot data.` }, function (args = {}) {
13
- validateKeys(args, MATERIALIZE_OPTIONS, op);
14
- const { id, source, transform } = requireDerivedDataset(this, args.id, type);
15
- return this.editSemantic({ property: `dataset[${id}].values`, value: select(deriveBoxData(source.values, transform)) });
16
- });
9
+ return derivedMaterializer(
10
+ op,
11
+ `Materialize ${type} box-plot data.`,
12
+ type,
13
+ (values, transform) => select(deriveBoxData(values, transform))
14
+ );
17
15
  }
18
16
 
19
17
  export const materializeBoxSummaryData = materializer("boxSummary", "materializeBoxSummaryData", value => value.summaries);
20
18
  export const materializeBoxOutlierData = materializer("boxOutlier", "materializeBoxOutlierData", value => value.outliers);
21
19
 
22
20
  function creator(type, op, materialize) {
23
- return action({ op, description: `Create immutable ${type} box-plot data.` }, function (args = {}) {
24
- validateKeys(args, OPTIONS, op);
25
- const id = validateUserId(args.id, "Box dataset id");
26
- const source = validateUserId(args.source ?? this.context.currentData, "Box source dataset id");
27
- const transform = normalizeBoxTransform({
21
+ return derivedCreator(
22
+ op,
23
+ `Create immutable ${type} box-plot data.`,
24
+ OPTIONS,
25
+ "Box dataset id",
26
+ "Box source dataset id",
27
+ args => normalizeBoxTransform({
28
28
  type,
29
29
  category: args.category,
30
30
  field: args.field,
31
31
  ...(args.whisker === undefined ? {} : { whisker: args.whisker }),
32
32
  ...(args.factor === undefined ? {} : { factor: args.factor }),
33
33
  as: args.as ?? BOX_FIELDS
34
- });
35
- return this.createDerivedData({ id, source, transform: [transform] })[materialize]({ id });
36
- });
34
+ }),
35
+ materialize
36
+ );
37
37
  }
38
38
 
39
39
  export const createBoxSummaryData = creator("boxSummary", "createBoxSummaryData", "materializeBoxSummaryData");
@@ -1,8 +1,5 @@
1
- import { action } from "../../core/action.js";
2
- import { validateUserId } from "../../core/identifiers.js";
3
- import { validateKeys } from "../../core/validation.js";
4
1
  import { deriveKernelDensity } from "../../grammar/density.js";
5
- import { MATERIALIZE_OPTIONS, requireDerivedDataset } from "./shared.js";
2
+ import { derivedCreator, derivedMaterializer } from "./shared.js";
6
3
 
7
4
  const OPTIONS = Object.freeze([
8
5
  "id", "source", "field", "groupBy", "bandwidth", "extent", "steps",
@@ -26,84 +23,51 @@ function densityTransform(args, placement) {
26
23
  };
27
24
  }
28
25
 
29
- export const materializeDensityData = action(
30
- { op: "materializeDensityData", description: "Materialize one grouped kernel-density dataset." },
31
- function (args = {}) {
32
- validateKeys(args, MATERIALIZE_OPTIONS, "materializeDensityData");
33
- const { id, source, transform } = requireDerivedDataset(
34
- this,
35
- args.id,
36
- "density"
26
+ function requestedTransform(args, op, categorical = false) {
27
+ if (typeof args.field !== "string" || args.field.length === 0) {
28
+ throw new TypeError(`${op} requires a non-empty field string.`);
29
+ }
30
+ if (categorical && args.placement?.type !== "category") {
31
+ throw new Error(
32
+ "createCategoricalDensityData requires normalized category placement."
37
33
  );
38
- const result = deriveKernelDensity(source.values, transform);
39
- return this
40
- .editSemantic({
41
- property: `dataset[${id}].transform`,
42
- value: [{
43
- ...transform,
44
- resolved: {
45
- bandwidth: result.bandwidth,
46
- extent: result.extent,
47
- ...(result.splitDomain === undefined
48
- ? {}
49
- : { splitDomain: result.splitDomain })
50
- }
51
- }]
52
- })
53
- .editSemantic({
54
- property: `dataset[${id}].values`,
55
- value: result.values
56
- });
57
34
  }
58
- );
35
+ return densityTransform(args, categorical ? args.placement : undefined);
36
+ }
59
37
 
60
- export const createDensityData = action(
61
- { op: "createDensityData", description: "Create grouped kernel-density values." },
62
- function (args = {}) {
63
- validateKeys(args, OPTIONS, "createDensityData");
64
- const id = validateUserId(args.id, "Density dataset id");
65
- const source = validateUserId(
66
- args.source ?? this.context.currentData,
67
- "Source dataset id"
68
- );
69
- if (typeof args.field !== "string" || args.field.length === 0) {
70
- throw new TypeError("createDensityData requires a non-empty field string.");
38
+ export const materializeDensityData = derivedMaterializer(
39
+ "materializeDensityData",
40
+ "Materialize one grouped kernel-density dataset.",
41
+ "density",
42
+ deriveKernelDensity,
43
+ (result, transform) => [{
44
+ ...transform,
45
+ resolved: {
46
+ bandwidth: result.bandwidth,
47
+ extent: result.extent,
48
+ ...(result.splitDomain === undefined
49
+ ? {}
50
+ : { splitDomain: result.splitDomain })
71
51
  }
72
- const transform = densityTransform(args);
73
- return this
74
- .createDerivedData({ id, source, transform: [transform] })
75
- .materializeDensityData({ id });
76
- }
52
+ }]
77
53
  );
78
54
 
79
- export const createCategoricalDensityData = action(
80
- {
81
- op: "createCategoricalDensityData",
82
- description: "Create category-placed kernel-density values."
83
- },
84
- function (args = {}) {
85
- validateKeys(args, CATEGORICAL_OPTIONS, "createCategoricalDensityData");
86
- const id = validateUserId(args.id, "Density dataset id");
87
- const source = validateUserId(
88
- args.source ?? this.context.currentData,
89
- "Source dataset id"
90
- );
91
- if (typeof args.field !== "string" || args.field.length === 0) {
92
- throw new TypeError(
93
- "createCategoricalDensityData requires a non-empty field string."
94
- );
95
- }
96
- if (args.placement?.type !== "category") {
97
- throw new Error(
98
- "createCategoricalDensityData requires normalized category placement."
99
- );
100
- }
101
- return this
102
- .createDerivedData({
103
- id,
104
- source,
105
- transform: [densityTransform(args, args.placement)]
106
- })
107
- .materializeDensityData({ id });
108
- }
55
+ export const createDensityData = derivedCreator(
56
+ "createDensityData",
57
+ "Create grouped kernel-density values.",
58
+ OPTIONS,
59
+ "Density dataset id",
60
+ "Source dataset id",
61
+ args => requestedTransform(args, "createDensityData"),
62
+ "materializeDensityData"
63
+ );
64
+
65
+ export const createCategoricalDensityData = derivedCreator(
66
+ "createCategoricalDensityData",
67
+ "Create category-placed kernel-density values.",
68
+ CATEGORICAL_OPTIONS,
69
+ "Density dataset id",
70
+ "Source dataset id",
71
+ args => requestedTransform(args, "createCategoricalDensityData", true),
72
+ "materializeDensityData"
109
73
  );
@@ -1,65 +1,35 @@
1
- import { action } from "../../core/action.js";
2
- import { validateUserId } from "../../core/identifiers.js";
3
- import { validateKeys } from "../../core/validation.js";
4
1
  import {
5
2
  deriveGradientProfiles,
6
3
  normalizeGradientProfileTransform
7
4
  } from "../../grammar/gradientProfile.js";
8
- import { MATERIALIZE_OPTIONS, requireDerivedDataset } from "./shared.js";
5
+ import { derivedCreator, derivedMaterializer } from "./shared.js";
9
6
 
10
7
  const OPTIONS = Object.freeze([
11
8
  "id", "source", "category", "field", "bandwidth", "extent", "steps",
12
9
  "kernel", "normalization", "center", "as"
13
10
  ]);
14
11
 
15
- export const materializeGradientProfileData = action(
16
- {
17
- op: "materializeGradientProfileData",
18
- description: "Materialize one categorical density-profile dataset."
19
- },
20
- function (args = {}) {
21
- validateKeys(
22
- args,
23
- MATERIALIZE_OPTIONS,
24
- "materializeGradientProfileData"
25
- );
26
- const { id, source, transform } = requireDerivedDataset(
27
- this,
28
- args.id,
29
- "gradientProfile"
30
- );
31
- const result = deriveGradientProfiles(source.values, transform);
32
- return this
33
- .editSemantic({
34
- property: `dataset[${id}].transform`,
35
- value: [{
36
- ...transform,
37
- resolved: {
38
- bandwidth: result.bandwidth,
39
- extent: result.extent,
40
- intensityDomain: result.intensityDomain
41
- }
42
- }]
43
- })
44
- .editSemantic({ property: `dataset[${id}].values`, value: result.values });
45
- }
12
+ export const materializeGradientProfileData = derivedMaterializer(
13
+ "materializeGradientProfileData",
14
+ "Materialize one categorical density-profile dataset.",
15
+ "gradientProfile",
16
+ deriveGradientProfiles,
17
+ (result, transform) => [{
18
+ ...transform,
19
+ resolved: {
20
+ bandwidth: result.bandwidth,
21
+ extent: result.extent,
22
+ intensityDomain: result.intensityDomain
23
+ }
24
+ }]
46
25
  );
47
26
 
48
- export const createGradientProfileData = action(
49
- {
50
- op: "createGradientProfileData",
51
- description: "Create one immutable categorical density-profile dataset."
52
- },
53
- function (args = {}) {
54
- validateKeys(args, OPTIONS, "createGradientProfileData");
55
- const id = validateUserId(args.id, "Gradient profile dataset id");
56
- const source = validateUserId(
57
- args.source ?? this.context.currentData,
58
- "Gradient profile source dataset id"
59
- );
60
- const transform = normalizeGradientProfileTransform(args);
61
- return this
62
- .createDerivedData({ id, source, transform: [transform] })
63
- .materializeGradientProfileData({ id });
64
- }
27
+ export const createGradientProfileData = derivedCreator(
28
+ "createGradientProfileData",
29
+ "Create one immutable categorical density-profile dataset.",
30
+ OPTIONS,
31
+ "Gradient profile dataset id",
32
+ "Gradient profile source dataset id",
33
+ normalizeGradientProfileTransform,
34
+ "materializeGradientProfileData"
65
35
  );
@@ -1,11 +1,8 @@
1
- import { action } from "../../core/action.js";
2
- import { validateUserId } from "../../core/identifiers.js";
3
- import { validateKeys } from "../../core/validation.js";
4
1
  import {
5
2
  deriveHorizon,
6
3
  validateHorizonTransform
7
4
  } from "../../grammar/horizon.js";
8
- import { MATERIALIZE_OPTIONS, requireDerivedDataset } from "./shared.js";
5
+ import { derivedCreator, derivedMaterializer } from "./shared.js";
9
6
 
10
7
  const OPTIONS = Object.freeze([
11
8
  "id", "source", "x", "y", "groupBy", "bands", "baseline", "extent",
@@ -29,43 +26,21 @@ function requestedTransform(args) {
29
26
  });
30
27
  }
31
28
 
32
- export const materializeHorizonData = action(
33
- {
34
- op: "materializeHorizonData",
35
- description: "Materialize one immutable Horizon band dataset."
36
- },
37
- function (args = {}) {
38
- validateKeys(args, MATERIALIZE_OPTIONS, "materializeHorizonData");
39
- const { id, source, transform } = requireDerivedDataset(
40
- this,
41
- args.id,
42
- "horizon"
43
- );
44
- const result = deriveHorizon(source.values, transform);
45
- return this
46
- .editSemantic({
47
- property: `dataset[${id}].transform`,
48
- value: [{ ...result.transform, resolved: result.resolved }]
49
- })
50
- .editSemantic({
51
- property: `dataset[${id}].values`,
52
- value: result.values
53
- });
54
- }
29
+ export const materializeHorizonData = derivedMaterializer(
30
+ "materializeHorizonData",
31
+ "Materialize one immutable Horizon band dataset.",
32
+ "horizon",
33
+ deriveHorizon,
34
+ result => [{ ...result.transform, resolved: result.resolved }]
55
35
  );
56
36
 
57
- export const createHorizonData = action(
58
- {
59
- op: "createHorizonData",
60
- description: "Create one immutable Horizon band dataset."
61
- },
62
- function (args = {}) {
63
- validateKeys(args, OPTIONS, "createHorizonData");
64
- const id = validateUserId(args.id, "Horizon dataset id");
65
- const source = validateUserId(args.source, "Horizon source dataset id");
66
- const transform = requestedTransform(args);
67
- return this
68
- .createDerivedData({ id, source, transform: [transform] })
69
- .materializeHorizonData({ id });
70
- }
37
+ export const createHorizonData = derivedCreator(
38
+ "createHorizonData",
39
+ "Create one immutable Horizon band dataset.",
40
+ OPTIONS,
41
+ "Horizon dataset id",
42
+ "Horizon source dataset id",
43
+ requestedTransform,
44
+ "materializeHorizonData",
45
+ true
71
46
  );
@@ -1,4 +1,7 @@
1
- import { createData } from "./create.js";
1
+ import {
2
+ createTimeUnitData,
3
+ materializeTimeUnitData
4
+ } from "./timeUnit.js";
2
5
  import {
3
6
  createDerivedData,
4
7
  rebindLayerData,
@@ -10,28 +13,25 @@ import {
10
13
  materializeFilteredData,
11
14
  materializeMarkFilteredData
12
15
  } from "./filter.js";
16
+ import {
17
+ createGradientProfileData,
18
+ materializeGradientProfileData
19
+ } from "./gradientProfile.js";
13
20
  import { createRegressionData, materializeRegressionData } from "./regression.js";
14
21
  import {
15
22
  createCategoricalDensityData,
16
23
  createDensityData,
17
24
  materializeDensityData
18
25
  } from "./density.js";
19
- import {
20
- createGradientProfileData,
21
- materializeGradientProfileData
22
- } from "./gradientProfile.js";
23
26
  import { createIntervalData, materializeIntervalData } from "./interval.js";
24
27
  import { createHorizonData, materializeHorizonData } from "./horizon.js";
25
- import { createWindowData, materializeWindowData } from "./window.js";
26
- import {
27
- createTimeUnitData,
28
- materializeTimeUnitData
29
- } from "./timeUnit.js";
30
28
  import {
31
29
  createBin2DData,
32
30
  editBin2DData,
33
31
  materializeBin2DData
34
32
  } from "./bin2d.js";
33
+ import { createData } from "./create.js";
34
+ import { createWindowData, materializeWindowData } from "./window.js";
35
35
  import { createBoxSummaryData, createBoxOutlierData, materializeBoxSummaryData, materializeBoxOutlierData } from "./box.js";
36
36
 
37
37
  export function registerDataActions(ProgramClass) {
@@ -1,11 +1,8 @@
1
- import { action } from "../../core/action.js";
2
- import { validateUserId } from "../../core/identifiers.js";
3
- import { validateKeys } from "../../core/validation.js";
4
1
  import {
5
2
  deriveInterval,
6
3
  normalizeIntervalTransform
7
4
  } from "../../grammar/interval.js";
8
- import { MATERIALIZE_OPTIONS, requireDerivedDataset } from "./shared.js";
5
+ import { derivedCreator, derivedMaterializer } from "./shared.js";
9
6
 
10
7
  const OPTIONS = Object.freeze([
11
8
  "id",
@@ -18,43 +15,26 @@ const OPTIONS = Object.freeze([
18
15
  "as"
19
16
  ]);
20
17
 
21
- export const materializeIntervalData = action(
22
- {
23
- op: "materializeIntervalData",
24
- description: "Materialize one grouped interval-summary dataset."
25
- },
26
- function (args = {}) {
27
- validateKeys(args, MATERIALIZE_OPTIONS, "materializeIntervalData");
28
- const { id, source, transform } = requireDerivedDataset(
29
- this,
30
- args.id,
31
- "interval"
32
- );
33
- return this.editSemantic({
34
- property: `dataset[${id}].values`,
35
- value: deriveInterval(source.values, transform)
36
- });
37
- }
18
+ export const materializeIntervalData = derivedMaterializer(
19
+ "materializeIntervalData",
20
+ "Materialize one grouped interval-summary dataset.",
21
+ "interval",
22
+ deriveInterval
38
23
  );
39
24
 
40
- export const createIntervalData = action(
41
- {
42
- op: "createIntervalData",
43
- description: "Create immutable grouped interval-summary values."
44
- },
45
- function (args = {}) {
46
- validateKeys(args, OPTIONS, "createIntervalData");
47
- const id = validateUserId(args.id, "Interval dataset id");
48
- const source = validateUserId(
49
- args.source ?? this.context.currentData,
50
- "Source dataset id"
51
- );
25
+ export const createIntervalData = derivedCreator(
26
+ "createIntervalData",
27
+ "Create immutable grouped interval-summary values.",
28
+ OPTIONS,
29
+ "Interval dataset id",
30
+ "Source dataset id",
31
+ (args, id) => {
52
32
  const as = args.as ?? {
53
33
  center: `__${id}_center`,
54
34
  lower: `__${id}_lower`,
55
35
  upper: `__${id}_upper`
56
36
  };
57
- const transform = normalizeIntervalTransform({
37
+ return normalizeIntervalTransform({
58
38
  field: args.field,
59
39
  groupBy: args.groupBy,
60
40
  center: args.center,
@@ -62,8 +42,6 @@ export const createIntervalData = action(
62
42
  level: args.level,
63
43
  as
64
44
  });
65
- return this
66
- .createDerivedData({ id, source, transform: [transform] })
67
- .materializeIntervalData({ id });
68
- }
45
+ },
46
+ "materializeIntervalData"
69
47
  );