@flourish/sdk 5.2.0 → 5.2.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.
@@ -18,5 +18,9 @@
18
18
  "rollup": "^1.16.2",
19
19
  "rollup-plugin-node-resolve": "^5.1.0",
20
20
  "rollup-plugin-uglify": "^6.0.2"
21
+ },
22
+ "engines": {
23
+ "node": "20.19.x",
24
+ "npm": "10.8.2"
21
25
  }
22
26
  }
package/test/lib/sdk.js CHANGED
@@ -4,7 +4,6 @@ const assert = require("assert"),
4
4
 
5
5
  const { readConfig, readAndValidateConfig } = require("../../lib/sdk.js");
6
6
 
7
-
8
7
  describe("readConfig", () => {
9
8
  before(async function() {
10
9
  const { temporaryDirectory } = await import("tempy");
@@ -45,11 +45,11 @@ describe("validate_config", function() {
45
45
  }
46
46
 
47
47
  function bindingPlus(o) {
48
- return metadataPlus({ data: [ Object.assign({}, binding, o) ] });
48
+ return metadataPlus({ data: [Object.assign({}, binding, o)] });
49
49
  }
50
50
 
51
51
  function settingPlus(o, other, more_settings=[]) {
52
- return metadataPlus(Object.assign({ settings: [ Object.assign({}, setting_foo, o), setting_bar ].concat(more_settings) }, other));
52
+ return metadataPlus(Object.assign({ settings: [Object.assign({}, setting_foo, o), setting_bar].concat(more_settings) }, other));
53
53
  }
54
54
 
55
55
  function testBoolean(name) {
@@ -325,30 +325,30 @@ describe("validate_config", function() {
325
325
  "template.yml: “build.foo.files” must be an array");
326
326
  });
327
327
  it("should reject a null file", function() {
328
- expectFailure(metadataPlus({ build: { foo: { script: "", files: [ null ] } } }),
328
+ expectFailure(metadataPlus({ build: { foo: { script: "", files: [null] } } }),
329
329
  "template.yml: the entries of “build.foo.files” must be strings");
330
330
  });
331
331
  it("should reject an undefined file", function() {
332
- expectFailure(metadataPlus({ build: { foo: { script: "", files: [ undefined ] } } }),
332
+ expectFailure(metadataPlus({ build: { foo: { script: "", files: [undefined] } } }),
333
333
  "template.yml: the entries of “build.foo.files” must be strings");
334
334
  });
335
335
  it("should reject a numeric file", function() {
336
- expectFailure(metadataPlus({ build: { foo: { script: "", files: [ 23 ] } } }),
336
+ expectFailure(metadataPlus({ build: { foo: { script: "", files: [23] } } }),
337
337
  "template.yml: the entries of “build.foo.files” must be strings");
338
338
  });
339
339
  it("should reject a true file", function() {
340
- expectFailure(metadataPlus({ build: { foo: { script: "", files: [ true ] } } }),
340
+ expectFailure(metadataPlus({ build: { foo: { script: "", files: [true] } } }),
341
341
  "template.yml: the entries of “build.foo.files” must be strings");
342
342
  });
343
343
  it("should reject a false file", function() {
344
- expectFailure(metadataPlus({ build: { foo: { script: "", files: [ false ] } } }),
344
+ expectFailure(metadataPlus({ build: { foo: { script: "", files: [false] } } }),
345
345
  "template.yml: the entries of “build.foo.files” must be strings");
346
346
  });
347
347
  it("should accept a string file", function() {
348
- expectSuccess(metadataPlus({ build: { foo: { script: "", files: [ "" ] } } }));
348
+ expectSuccess(metadataPlus({ build: { foo: { script: "", files: [""] } } }));
349
349
  });
350
350
  it("should accept two strings", function() {
351
- expectSuccess(metadataPlus({ build: { foo: { script: "", files: [ "one", "two" ] } } }));
351
+ expectSuccess(metadataPlus({ build: { foo: { script: "", files: ["one", "two"] } } }));
352
352
  });
353
353
 
354
354
  it("should reject a null directory", function() {
@@ -410,23 +410,23 @@ describe("validate_config", function() {
410
410
  type = binding.type;
411
411
 
412
412
  it("should require name", function() {
413
- expectFailure(metadataPlus({ data: [ { dataset, key, type } ] }),
413
+ expectFailure(metadataPlus({ data: [{ dataset, key, type }] }),
414
414
  "template.yml data binding must specify a name");
415
415
  });
416
416
  it("should require dataset", function() {
417
- expectFailure(metadataPlus({ data: [ { name, key, type } ] }),
417
+ expectFailure(metadataPlus({ data: [{ name, key, type }] }),
418
418
  "template.yml data binding “My binding” must specify a dataset");
419
419
  });
420
420
  it("should require key", function() {
421
- expectFailure(metadataPlus({ data: [ { name, dataset, type } ] }),
421
+ expectFailure(metadataPlus({ data: [{ name, dataset, type }] }),
422
422
  "template.yml data binding “My binding” must specify a key");
423
423
  });
424
424
  it("should require type", function() {
425
- expectFailure(metadataPlus({ data: [ { name, dataset, key } ] }),
425
+ expectFailure(metadataPlus({ data: [{ name, dataset, key }] }),
426
426
  "template.yml data binding “My binding” must specify a type");
427
427
  });
428
428
  it("should require column for non-optional column bindings", function() {
429
- expectFailure(metadataPlus({ data: [ { name, dataset, key, type } ] }),
429
+ expectFailure(metadataPlus({ data: [{ name, dataset, key, type }] }),
430
430
  "template.yml non-optional data binding “My binding” must specify column");
431
431
  });
432
432
  it("should accept name/dataset/key/type=column/column", function() {
@@ -528,17 +528,17 @@ describe("validate_config", function() {
528
528
  expectSuccess(bindingPlus({ optional: false }));
529
529
  });
530
530
  it("should require column if optional is false", function() {
531
- expectFailure(metadataPlus({ data: [ { name, dataset, key, type, optional: false } ] }),
531
+ expectFailure(metadataPlus({ data: [{ name, dataset, key, type, optional: false }] }),
532
532
  "template.yml non-optional data binding “My binding” must specify column");
533
533
  });
534
534
 
535
535
  it("should reject duplicates", function() {
536
- expectFailure(metadataPlus({ data: [ binding, binding ] }),
536
+ expectFailure(metadataPlus({ data: [binding, binding] }),
537
537
  "template.yml: there is more than one data binding with dataset “dataset” and key “key”");
538
538
  });
539
539
 
540
540
  it("should ignore headings", function() {
541
- expectSuccess(metadataPlus({ data: [ "Heading", binding ] }));
541
+ expectSuccess(metadataPlus({ data: ["Heading", binding] }));
542
542
  });
543
543
  });
544
544
 
@@ -571,19 +571,19 @@ describe("validate_config", function() {
571
571
  });
572
572
 
573
573
  it("should require property", function() {
574
- expectFailure(metadataPlus({ settings: [ { name: "Foo", type: "string" } ] }),
574
+ expectFailure(metadataPlus({ settings: [{ name: "Foo", type: "string" }] }),
575
575
  "template.yml setting must specify a property:");
576
576
  });
577
577
  it("should require type", function() {
578
- expectFailure(metadataPlus({ settings: [ { name: "Foo", property: "foo" } ] }),
578
+ expectFailure(metadataPlus({ settings: [{ name: "Foo", property: "foo" }] }),
579
579
  "template.yml setting “foo” must specify a type:");
580
580
  });
581
581
  it("should require name", function() {
582
- expectFailure(metadataPlus({ settings: [ { property: "foo", type: "string" } ] }),
582
+ expectFailure(metadataPlus({ settings: [{ property: "foo", type: "string" }] }),
583
583
  "template.yml setting “foo” must specify a name:");
584
584
  });
585
585
  it("should not require name if choices are specified", function() {
586
- expectSuccess(metadataPlus({ settings: [ { property: "foo", type: "string", choices: [] } ] }));
586
+ expectSuccess(metadataPlus({ settings: [{ property: "foo", type: "string", choices: [] }] }));
587
587
  });
588
588
 
589
589
  describe("optional settings", function() {
@@ -828,43 +828,43 @@ describe("validate_config", function() {
828
828
 
829
829
  it("should accept an array containing an object with multiple string values", function() {
830
830
  const blah = { name: "Blah", property: "blah", type: "string" };
831
- expectSuccess(settingPlus({ show_if: [ { "bar": "xxx", "blah": "xxx" }] }, undefined, [blah]));
831
+ expectSuccess(settingPlus({ show_if: [{ "bar": "xxx", "blah": "xxx" }] }, undefined, [blah]));
832
832
  });
833
833
 
834
834
  it("should accept an array containing an object with multiple array values", function() {
835
835
  const blah = { name: "Blah", property: "blah", type: "string" };
836
- expectSuccess(settingPlus({ show_if: [ { "bar": ["xxx"], "blah": ["xxx"] }] }, undefined, [blah]));
836
+ expectSuccess(settingPlus({ show_if: [{ "bar": ["xxx"], "blah": ["xxx"] }] }, undefined, [blah]));
837
837
  });
838
838
 
839
839
  it("should reject an array containing any objects with empty array values", function() {
840
840
  const blah = { name: "Blah", property: "blah", type: "string" };
841
- expectFailure(settingPlus({ show_if: [ { "bar": [], "blah": "xxx" }] }, undefined, [blah]),
841
+ expectFailure(settingPlus({ show_if: [{ "bar": [], "blah": "xxx" }] }, undefined, [blah]),
842
842
  "template.yml setting “foo” “show_if” property: condition for bar is empty");
843
843
  });
844
844
 
845
845
  it("should reject an array containing any objects referring to non-existent settings", function() {
846
- expectFailure(settingPlus({ show_if: [ { "bar": "xxx", "baz": "xxx" }] }),
846
+ expectFailure(settingPlus({ show_if: [{ "bar": "xxx", "baz": "xxx" }] }),
847
847
  "template.yml: “show_if” or “hide_if” property refers to non-existent setting “baz”");
848
848
  });
849
849
 
850
850
  it("should accept an array containing an object with a string value and a valid data binding", function() {
851
- expectSuccess(settingPlus({ show_if: [ { "bar": "xxx", "data.dataset.key": true }] }, { data: [ binding ] }));
851
+ expectSuccess(settingPlus({ show_if: [{ "bar": "xxx", "data.dataset.key": true }] }, { data: [binding] }));
852
852
  });
853
853
 
854
854
  it("should reject an array with a data reference when there are no data bindings", function() {
855
- expectFailure(settingPlus({ show_if: [ { "bar": "xxx", "data.dataset.key": true }] }),
855
+ expectFailure(settingPlus({ show_if: [{ "bar": "xxx", "data.dataset.key": true }] }),
856
856
  "template.yml: “show_if” or “hide_if” property refers to data binding “data.dataset.key” when none are defined");
857
857
  });
858
858
 
859
859
  it("should reject an array with a reference to a non-existent data binding", function() {
860
- expectFailure(settingPlus({ show_if: [ { "bar": "xxx", "data.dataset.nosuchkey": true }] }, { data: [ binding ] }),
860
+ expectFailure(settingPlus({ show_if: [{ "bar": "xxx", "data.dataset.nosuchkey": true }] }, { data: [binding] }),
861
861
  "template.yml: “show_if” or “hide_if” property refers to non-existent data binding “data.dataset.nosuchkey”");
862
862
  });
863
863
 
864
864
  it("should accept an array containing multiple objects of including string and boolean values", function() {
865
865
  const blah = { name: "Blah", property: "blah", type: "string" };
866
866
  const bool = { name: "Bool", property: "bool", type: "boolean" };
867
- expectSuccess(settingPlus({ show_if: [ { "bar": "xxx", "blah": "xxx" }, { "bool": true }] }, undefined, [blah, bool]));
867
+ expectSuccess(settingPlus({ show_if: [{ "bar": "xxx", "blah": "xxx" }, { "bool": true }] }, undefined, [blah, bool]));
868
868
  });
869
869
 
870
870
  it("should forbid empty objects", function() {
@@ -887,26 +887,26 @@ describe("validate_config", function() {
887
887
  "template.yml: “show_if” or “hide_if” property refers to non-existent setting “baz”");
888
888
  });
889
889
  it("should accept a reference to a data binding", function() {
890
- expectSuccess(settingPlus({ show_if: "data.dataset.key" }, { data: [ binding ] }));
890
+ expectSuccess(settingPlus({ show_if: "data.dataset.key" }, { data: [binding] }));
891
891
  });
892
892
  it("should reject a data reference when there are no data bindings", function() {
893
893
  expectFailure(settingPlus({ show_if: "data.dataset.key" }),
894
894
  "template.yml: “show_if” or “hide_if” property refers to data binding “data.dataset.key” when none are defined");
895
895
  });
896
896
  it("should reject a reference to a non-existent data binding", function() {
897
- expectFailure(settingPlus({ show_if: "data.dataset.nosuchkey" }, { data: [ binding ] }),
897
+ expectFailure(settingPlus({ show_if: "data.dataset.nosuchkey" }, { data: [binding] }),
898
898
  "template.yml: “show_if” or “hide_if” property refers to non-existent data binding “data.dataset.nosuchkey”");
899
899
  });
900
900
 
901
901
  // This test is skipped because it doesn’t pass, and looks like it would be
902
902
  // complicated to fix.
903
903
  it.skip("should reject a string value when referencing a data binding", function() {
904
- expectFailure(settingPlus({ show_if: { "data.dataset.key": "foo" } }, { data: [ binding ] }));
904
+ expectFailure(settingPlus({ show_if: { "data.dataset.key": "foo" } }, { data: [binding] }));
905
905
  });
906
906
 
907
907
  it("should reject a reference to a data binding that has no key", function() {
908
908
  const binding_undef_key = { name: "No-key binding", dataset: "dataset", key: undefined, type: "column", column: "Foo::A" };
909
- expectFailure(settingPlus({ show_if: "data.dataset" }, { data: [ binding_undef_key ] }),
909
+ expectFailure(settingPlus({ show_if: "data.dataset" }, { data: [binding_undef_key] }),
910
910
  "template.yml: “show_if” or “hide_if” property specifies invalid data binding or column type “data.dataset”");
911
911
  });
912
912
  it("should accept settings whose names start with /data./ [kiln/flourish-sdk#45]", function() {
package/server/columns.js DELETED
@@ -1,201 +0,0 @@
1
- /* * * * * * GENERATED FILE - DO NOT EDIT * * * * * *
2
- * * * * * * GENERATED FILE - DO NOT EDIT * * * * * *
3
- * * * * * * GENERATED FILE - DO NOT EDIT * * * * * */
4
-
5
- 'use strict';
6
-
7
- Object.defineProperty(exports, '__esModule', { value: true });
8
-
9
- const MAX_INTEGER = Math.pow(2, 31) - 1;
10
- const MAX_RANGE_LENGTH = Math.pow(2, 15);
11
-
12
- // Attempt to parse col_spec as a columns spec;
13
- // return true if we succeed, and false if not.
14
- function looksLikeMultipleColumns(col_spec) {
15
- try {
16
- parseColumns(col_spec);
17
- }
18
- catch (e) {
19
- return false;
20
- }
21
- return true;
22
- }
23
-
24
- function parseColumn(col_spec, is_optional) {
25
- col_spec = col_spec.toUpperCase();
26
- if (!/^[A-Z]+$/.test(col_spec)) {
27
- if (!col_spec) {
28
- if (is_optional) return -1; // Use -1 for unassigned optional binding
29
- else throw new Error("Non-optional data binding must specify column");
30
- }
31
- if (looksLikeMultipleColumns(col_spec)) {
32
- throw new Error("You can only select one column");
33
- }
34
- else throw new Error("Invalid column specification: " + col_spec);
35
- }
36
-
37
- var col_ix = 0;
38
- for (var i = 0; i < col_spec.length; i++) {
39
- col_ix = col_ix * 26 + (col_spec.charCodeAt(i) - 64);
40
- }
41
-
42
- if (col_ix - 1 > MAX_INTEGER) console.warn("Column index out of range");
43
- return Math.min(col_ix - 1, MAX_INTEGER);
44
- }
45
-
46
- function printColumn(col_ix) {
47
- col_ix += 1;
48
- var col_spec = "";
49
- while (col_ix > 0) {
50
- var q = Math.floor(col_ix / 26),
51
- r = col_ix % 26;
52
-
53
- if (r == 0) {
54
- q -= 1;
55
- r += 26;
56
- }
57
-
58
- col_spec = String.fromCharCode(64 + r) + col_spec;
59
- col_ix = q;
60
- }
61
- return col_spec;
62
- }
63
-
64
- function parseRange(col_range) {
65
- var dash_mo = col_range.match(/\s*(?:[-–—:]|\.\.)\s*/);
66
- if (!dash_mo) throw new Error("Failed to parse column range: " + col_range);
67
-
68
- var first = col_range.substr(0, dash_mo.index),
69
- last = col_range.substr(dash_mo.index + dash_mo[0].length);
70
-
71
- var first_ix = parseColumn(first),
72
- last_ix = parseColumn(last);
73
-
74
- var r = [];
75
- var incrementer = last_ix >= first_ix ? 1 : -1;
76
- var n = Math.abs(last_ix - first_ix) + 1;
77
-
78
- if (n > MAX_RANGE_LENGTH) {
79
- console.warn("Truncating excessively long range");
80
- n = MAX_RANGE_LENGTH;
81
- }
82
-
83
- for (var i = 0; i < n; i++) {
84
- r.push(first_ix + i*incrementer);
85
- }
86
-
87
- return r;
88
- }
89
-
90
- function printRange(start, end) {
91
- return printColumn(start) + "-" + printColumn(end);
92
- }
93
-
94
- function parseColumns(cols_spec) {
95
- var indexes = [];
96
-
97
- cols_spec = cols_spec.replace(/^\s+|\s+$/g, "");
98
- var split_cols = cols_spec.split(/\s*,\s*/);
99
- if (split_cols.length == 1 && split_cols[0] === "") split_cols = [];
100
-
101
- for (var i = 0; i < split_cols.length; i++) {
102
- var col_or_range = split_cols[i];
103
- if (/^[A-Za-z]+$/.test(col_or_range)) {
104
- indexes.push(parseColumn(col_or_range));
105
- }
106
- else {
107
- Array.prototype.push.apply(indexes, parseRange(col_or_range));
108
- }
109
- }
110
-
111
- return indexes;
112
- }
113
-
114
- function splitIntoRanges(indexes) {
115
- if (!indexes.length) {
116
- return [];
117
- }
118
- var ranges = [];
119
- var start = indexes[0], end = indexes[0];
120
- var direction = null;
121
- for (var i = 0; i < indexes.length - 1; i++) {
122
- var diff = indexes[i + 1] - indexes[i];
123
- if (direction === null && Math.abs(diff) === 1) {
124
- // It's a range with either ascending columns (direction=1), or descending
125
- // columns (direction=-1)
126
- end = indexes[i + 1];
127
- direction = diff;
128
- continue;
129
- }
130
-
131
- if (diff === direction) {
132
- // The range is continuing in the same direction as before
133
- end = indexes[i + 1];
134
- continue;
135
- }
136
-
137
- // There's nothing more in the range, so add it, and start a new range from the
138
- // next column
139
- ranges.push([start, end]);
140
- start = end = indexes[i + 1];
141
- direction = null;
142
- }
143
- // There will always be a range which hasn't been added at the end
144
- ranges.push([start, end]);
145
- return ranges;
146
- }
147
-
148
- function printColumns(indexes) {
149
- var ranges = splitIntoRanges(indexes);
150
-
151
- var r = [];
152
- for (var i = 0; i < ranges.length; i++) {
153
- var range = ranges[i];
154
- if (range[0] == range[1]) r.push(printColumn(range[0]));
155
- else r.push(printRange(range[0], range[1]));
156
- }
157
- return r.join(",");
158
- }
159
-
160
- function parseDataBinding(d, data_table_ids) {
161
- var r = {};
162
-
163
- if (!(d.type in d)) {
164
- if (d.optional) return r;
165
- throw new Error("Data binding must specify '" + d.type + "': " + JSON.stringify(d));
166
- }
167
-
168
- var double_colon_ix = d[d.type].indexOf("::");
169
- if (double_colon_ix == -1) throw new Error("Invalid data binding: " + d[d.type]);
170
- var data_table_name = d[d.type].substr(0, double_colon_ix);
171
- r.data_table_id = data_table_ids[data_table_name];
172
-
173
- var col_spec = d[d.type].substr(double_colon_ix + 2);
174
- if (d.type == "column") r.column = parseColumn(col_spec, d.optional);
175
- else if (d.type == "columns") r.columns = parseColumns(col_spec);
176
- else throw new Error("Unknown data binding type: " + d.type);
177
-
178
- return r;
179
- }
180
-
181
- function printDataBinding(r, data_table_names, print_data_table_name, optional) {
182
- var data_table_name = print_data_table_name ? data_table_names[r.data_table_id] + "::" : "";
183
- if ("column" in r) {
184
- return data_table_name + printColumn(r.column);
185
- }
186
- else if ("columns" in r) {
187
- return data_table_name + printColumns(r.columns);
188
- }
189
- else if (optional) {
190
- return "";
191
- }
192
- throw new Error("Data binding must have .column or .columns");
193
- }
194
-
195
- exports.parseColumn = parseColumn;
196
- exports.parseColumns = parseColumns;
197
- exports.parseDataBinding = parseDataBinding;
198
- exports.parseRange = parseRange;
199
- exports.printColumn = printColumn;
200
- exports.printColumns = printColumns;
201
- exports.printDataBinding = printDataBinding;