@flourish/sdk 4.2.2 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -1
- package/RELEASE_NOTES.md +7 -2
- package/common/embed/credit.js +2 -3
- package/common/embed/customer_analytics.js +5 -6
- package/common/embed/embedding.d.ts +1 -1
- package/common/embed/embedding.js +7 -9
- package/common/embed/localizations.d.ts +8 -8
- package/common/package.json +11 -2
- package/common/tsconfig.sdk.tsbuildinfo +1 -1
- package/common/utils/columns.js +7 -8
- package/common/utils/data.d.ts +36 -15
- package/common/utils/data.js +84 -27
- package/common/utils/json.d.ts +6 -3
- package/common/utils/json.js +4 -5
- package/common/utils/state.js +7 -8
- package/common/utils/types.d.ts +63 -0
- package/common/utils/types.js +3 -0
- package/lib/cmd/login.js +12 -17
- package/lib/cmd/logout.js +17 -5
- package/lib/cmd/publish.js +2 -7
- package/lib/cmd/register.js +10 -13
- package/lib/sdk.js +59 -13
- package/package.json +24 -24
- package/rollup.config.mjs +49 -0
- package/server/index.js +29 -10
- package/server/json.js +1 -0
- package/server/views/index.html +5 -2
- package/site/embedded.js +2 -1
- package/site/images/icon-add-folder.svg +1 -1
- package/site/script.js +3 -2
- package/site/sdk.css +1 -1
- package/tsconfig.json +1 -1
- package/server/data.js +0 -327
package/common/utils/data.js
CHANGED
|
@@ -1,16 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.createInterpreter = void 0;
|
|
4
|
+
exports.extractData = extractData;
|
|
5
|
+
exports.getColumnTypesForData = getColumnTypesForData;
|
|
6
|
+
exports.getRandomSeededSample = getRandomSeededSample;
|
|
7
|
+
exports.mulberry32 = mulberry32;
|
|
8
|
+
exports.trimTrailingEmptyRows = trimTrailingEmptyRows;
|
|
9
|
+
exports.dropReturnCharacters = dropReturnCharacters;
|
|
10
|
+
exports.tidyTable = tidyTable;
|
|
11
|
+
exports.stripCommonFixes = stripCommonFixes;
|
|
12
|
+
exports.transposeNestedArray = transposeNestedArray;
|
|
13
|
+
exports.getSlicedData = getSlicedData;
|
|
14
|
+
exports.interpretColumn = interpretColumn;
|
|
15
|
+
exports.sortDataTables = sortDataTables;
|
|
4
16
|
const interpreter_1 = require("@flourish/interpreter");
|
|
5
17
|
require("./polyfills");
|
|
6
|
-
|
|
18
|
+
var interpreter_2 = require("@flourish/interpreter");
|
|
19
|
+
Object.defineProperty(exports, "createInterpreter", { enumerable: true, get: function () { return interpreter_2.createInterpreter; } });
|
|
20
|
+
function getLatestDataTimestamps(data_table_timestamps) {
|
|
21
|
+
const timestamps = {};
|
|
22
|
+
const date_values = data_table_timestamps.map(t => t.last_updated?.getTime()).filter(Boolean);
|
|
23
|
+
if (date_values.length) {
|
|
24
|
+
const latest_date = Math.max(...date_values);
|
|
25
|
+
timestamps.last_updated = new Date(latest_date);
|
|
26
|
+
}
|
|
27
|
+
return timestamps;
|
|
28
|
+
}
|
|
29
|
+
function extractData(data_binding, data_by_id, column_types_by_id, template_data_bindings, timestamps) {
|
|
7
30
|
var columns = [];
|
|
8
31
|
var data_table_ids = [];
|
|
9
32
|
var num_rows = 0;
|
|
10
|
-
var dataset = [];
|
|
33
|
+
var dataset = Object.assign([], { column_names: {}, metadata: {}, timestamps: {} });
|
|
11
34
|
var interpreters_by_id = {};
|
|
12
|
-
dataset.column_names = {};
|
|
13
|
-
dataset.metadata = {};
|
|
14
35
|
function getInterpretationIds(data_table_id, column_index) {
|
|
15
36
|
if (!interpreters_by_id[data_table_id])
|
|
16
37
|
return {};
|
|
@@ -20,9 +41,10 @@ function extractData(data_binding, data_by_id, column_types_by_id, template_data
|
|
|
20
41
|
return by_column_index[column_index];
|
|
21
42
|
}
|
|
22
43
|
function getInterpreter(data_table_id, column_index) {
|
|
23
|
-
const
|
|
24
|
-
if (type_id)
|
|
25
|
-
return interpreter_1.createInterpreter.getInterpretation(type_id);
|
|
44
|
+
const interpretation_ids = getInterpretationIds(data_table_id, column_index);
|
|
45
|
+
if ("type_id" in interpretation_ids) {
|
|
46
|
+
return interpreter_1.createInterpreter.getInterpretation(interpretation_ids.type_id);
|
|
47
|
+
}
|
|
26
48
|
}
|
|
27
49
|
for (var data_table_id in column_types_by_id) {
|
|
28
50
|
var lookup = {};
|
|
@@ -43,7 +65,7 @@ function extractData(data_binding, data_by_id, column_types_by_id, template_data
|
|
|
43
65
|
if (data_binding[key].columns === undefined && data_binding[key].column === undefined)
|
|
44
66
|
continue;
|
|
45
67
|
var b = data_binding[key];
|
|
46
|
-
b.template_data_binding =
|
|
68
|
+
b.template_data_binding = template_data_bindings[key];
|
|
47
69
|
b.key = key;
|
|
48
70
|
if (!(b.data_table_id in data_by_id)) {
|
|
49
71
|
var data_by_id_keys = [];
|
|
@@ -52,7 +74,10 @@ function extractData(data_binding, data_by_id, column_types_by_id, template_data
|
|
|
52
74
|
console.error("Data table id " + b.data_table_id + " not in " + JSON.stringify(data_by_id_keys));
|
|
53
75
|
continue;
|
|
54
76
|
}
|
|
55
|
-
|
|
77
|
+
const data_table = data_by_id[b.data_table_id];
|
|
78
|
+
if (data_table == null) {
|
|
79
|
+
throw new Error(`[BUG] The data from the data table with ID ${b.data_table_id} was missing`);
|
|
80
|
+
}
|
|
56
81
|
if (data_table.length == 0) {
|
|
57
82
|
console.warn("Empty data table");
|
|
58
83
|
continue;
|
|
@@ -64,8 +89,9 @@ function extractData(data_binding, data_by_id, column_types_by_id, template_data
|
|
|
64
89
|
return data_table[0][i];
|
|
65
90
|
});
|
|
66
91
|
dataset.metadata[key] = b.columns.map(function (i) {
|
|
67
|
-
const
|
|
68
|
-
if (type_id) {
|
|
92
|
+
const interpretation_ids = getInterpretationIds(b.data_table_id, i);
|
|
93
|
+
if ("type_id" in interpretation_ids) {
|
|
94
|
+
const { type_id, output_format_id } = interpretation_ids;
|
|
69
95
|
return {
|
|
70
96
|
type: type_id.split("$")[0],
|
|
71
97
|
type_id,
|
|
@@ -77,8 +103,9 @@ function extractData(data_binding, data_by_id, column_types_by_id, template_data
|
|
|
77
103
|
}
|
|
78
104
|
else if ("column" in b && b.column != null) {
|
|
79
105
|
dataset.column_names[key] = data_table[0][b.column];
|
|
80
|
-
const
|
|
81
|
-
if (type_id) {
|
|
106
|
+
const interpretation_ids = getInterpretationIds(b.data_table_id, b.column);
|
|
107
|
+
if ("type_id" in interpretation_ids) {
|
|
108
|
+
const { type_id, output_format_id } = interpretation_ids;
|
|
82
109
|
dataset.metadata[key] = {
|
|
83
110
|
type: type_id.split("$")[0],
|
|
84
111
|
type_id,
|
|
@@ -95,8 +122,11 @@ function extractData(data_binding, data_by_id, column_types_by_id, template_data
|
|
|
95
122
|
}
|
|
96
123
|
columns.push(b);
|
|
97
124
|
}
|
|
125
|
+
// gets the latest timestamp info across all data tables which are linked to by the bindings for this dataset
|
|
126
|
+
// (this is typically only a single data table)\
|
|
127
|
+
dataset.timestamps = getLatestDataTimestamps(data_table_ids.map(id => timestamps.per_data_table[id]));
|
|
98
128
|
function parse(b, column_index, string_value) {
|
|
99
|
-
if (!b.template_data_binding
|
|
129
|
+
if (!b.template_data_binding?.data_type)
|
|
100
130
|
return string_value;
|
|
101
131
|
var interpreter = getInterpreter(b.data_table_id, column_index);
|
|
102
132
|
if (interpreter && interpreter.type == "number")
|
|
@@ -112,9 +142,14 @@ function extractData(data_binding, data_by_id, column_types_by_id, template_data
|
|
|
112
142
|
var o = {};
|
|
113
143
|
for (var j = 0; j < columns.length; j++) {
|
|
114
144
|
b = columns[j];
|
|
115
|
-
|
|
145
|
+
const table = data_by_id[b.data_table_id];
|
|
146
|
+
if (table == null) {
|
|
147
|
+
throw new Error(`[BUG] The data from the data table with ID ${b.data_table_id} was missing`);
|
|
148
|
+
}
|
|
116
149
|
if (i + 1 >= table.length)
|
|
117
150
|
continue;
|
|
151
|
+
if (b.key == null)
|
|
152
|
+
throw new Error(`BUG: 'key' was ${b.key} in ${b}`);
|
|
118
153
|
if ("columns" in b && b.columns != null) {
|
|
119
154
|
o[b.key] = b.columns
|
|
120
155
|
.filter(function (c) { return c < table[i + 1].length; })
|
|
@@ -131,7 +166,6 @@ function extractData(data_binding, data_by_id, column_types_by_id, template_data
|
|
|
131
166
|
}
|
|
132
167
|
return dataset;
|
|
133
168
|
}
|
|
134
|
-
exports.extractData = extractData;
|
|
135
169
|
function getColumnTypesForData(data) {
|
|
136
170
|
return transposeNestedArray(data)
|
|
137
171
|
.map(function (column, i) {
|
|
@@ -146,7 +180,6 @@ function getColumnTypesForData(data) {
|
|
|
146
180
|
return { type_id: type_id, index: i, output_format_id: type_id };
|
|
147
181
|
});
|
|
148
182
|
}
|
|
149
|
-
exports.getColumnTypesForData = getColumnTypesForData;
|
|
150
183
|
// Returns a random seeded sample of column values based on the column length.
|
|
151
184
|
// The sample is consistent and will update if the length of column changes.
|
|
152
185
|
function getRandomSeededSample(column, sample_size) {
|
|
@@ -159,7 +192,6 @@ function getRandomSeededSample(column, sample_size) {
|
|
|
159
192
|
}
|
|
160
193
|
return column;
|
|
161
194
|
}
|
|
162
|
-
exports.getRandomSeededSample = getRandomSeededSample;
|
|
163
195
|
// Seeded RNG implementation taken from https://github.com/bryc/code/blob/master/jshash/PRNGs.md#mulberry32
|
|
164
196
|
function mulberry32(seed) {
|
|
165
197
|
let a = seed;
|
|
@@ -171,7 +203,6 @@ function mulberry32(seed) {
|
|
|
171
203
|
return ((t ^ t >>> 14) >>> 0) / 4294967296;
|
|
172
204
|
};
|
|
173
205
|
}
|
|
174
|
-
exports.mulberry32 = mulberry32;
|
|
175
206
|
function trimTrailingEmptyRows(data) {
|
|
176
207
|
for (var i = data.length; i-- > 1;) {
|
|
177
208
|
if (!data[i] || !data[i].length || (Array.isArray(data[i]) && data[i].findIndex(function (col) { return col !== null && col !== ""; }) == -1)) {
|
|
@@ -182,7 +213,6 @@ function trimTrailingEmptyRows(data) {
|
|
|
182
213
|
}
|
|
183
214
|
return data;
|
|
184
215
|
}
|
|
185
|
-
exports.trimTrailingEmptyRows = trimTrailingEmptyRows;
|
|
186
216
|
function dropReturnCharacters(data) {
|
|
187
217
|
for (const row of data) {
|
|
188
218
|
for (let i = 0; i < row.length; i++) {
|
|
@@ -195,7 +225,6 @@ function dropReturnCharacters(data) {
|
|
|
195
225
|
}
|
|
196
226
|
return data;
|
|
197
227
|
}
|
|
198
|
-
exports.dropReturnCharacters = dropReturnCharacters;
|
|
199
228
|
/**
|
|
200
229
|
* Takes an array of arrays (typically tabular data) and rewrites
|
|
201
230
|
* it so that:
|
|
@@ -223,21 +252,24 @@ function tidyTable(data) {
|
|
|
223
252
|
if (typeof value !== "string") {
|
|
224
253
|
value = "" + value;
|
|
225
254
|
}
|
|
255
|
+
if (typeof value !== "string") {
|
|
256
|
+
throw new Error("BUG: somehow value was not a string");
|
|
257
|
+
}
|
|
226
258
|
// Now value is a definitely a string, strip any leading
|
|
227
259
|
// or trailing whitespace.
|
|
228
260
|
row[i] = value.trim();
|
|
229
261
|
}
|
|
230
262
|
}
|
|
263
|
+
// TypeScript can't infer that the returned data is definitely all
|
|
264
|
+
// strings so use a cast.
|
|
231
265
|
return data;
|
|
232
266
|
}
|
|
233
|
-
exports.tidyTable = tidyTable;
|
|
234
267
|
var ERROR_STRINGS = ["#DIV/0", "#N/A", "#NAME?", "#NULL!", "#NUM!", "#REF!", "#VALUE!", "#ERROR!"];
|
|
235
268
|
var interpreter = (0, interpreter_1.createInterpreter)().nMax(Infinity).nFailingValues(8).failureFraction(0.1);
|
|
236
269
|
function stripCommonFixes(str) {
|
|
237
270
|
str = str || "";
|
|
238
271
|
return str.replace(/[€£$¥%º]/g, "");
|
|
239
272
|
}
|
|
240
|
-
exports.stripCommonFixes = stripCommonFixes;
|
|
241
273
|
function transposeNestedArray(nested_array) {
|
|
242
274
|
var n_inner = nested_array.length;
|
|
243
275
|
var n_outer = n_inner > 0 ? nested_array[0].length : 0;
|
|
@@ -251,7 +283,6 @@ function transposeNestedArray(nested_array) {
|
|
|
251
283
|
}
|
|
252
284
|
return transposed_array;
|
|
253
285
|
}
|
|
254
|
-
exports.transposeNestedArray = transposeNestedArray;
|
|
255
286
|
function getSlicedData(arr) {
|
|
256
287
|
const n = arr.length;
|
|
257
288
|
if (n > 100)
|
|
@@ -268,7 +299,6 @@ function getSlicedData(arr) {
|
|
|
268
299
|
return arr.slice(1, n);
|
|
269
300
|
return arr.slice(0, 1);
|
|
270
301
|
}
|
|
271
|
-
exports.getSlicedData = getSlicedData;
|
|
272
302
|
function interpretColumn(arr) {
|
|
273
303
|
var idata = arr.filter(function (d) {
|
|
274
304
|
return d && !ERROR_STRINGS.includes(d.trim());
|
|
@@ -276,4 +306,31 @@ function interpretColumn(arr) {
|
|
|
276
306
|
.map(stripCommonFixes);
|
|
277
307
|
return interpreter(idata);
|
|
278
308
|
}
|
|
279
|
-
|
|
309
|
+
function sortDataTables(data_tables, data_bindings) {
|
|
310
|
+
// Sort data tables to match order in the template data bindings
|
|
311
|
+
if (!data_bindings || !data_bindings.length)
|
|
312
|
+
return;
|
|
313
|
+
if (!data_tables || !data_tables.length)
|
|
314
|
+
return;
|
|
315
|
+
var table_names = [];
|
|
316
|
+
data_bindings.forEach(function (data_binding) {
|
|
317
|
+
if (typeof data_binding === "string")
|
|
318
|
+
return;
|
|
319
|
+
let column;
|
|
320
|
+
if ("column" in data_binding) {
|
|
321
|
+
column = data_binding.column;
|
|
322
|
+
}
|
|
323
|
+
else if ("columns" in data_binding) {
|
|
324
|
+
column = data_binding.columns;
|
|
325
|
+
}
|
|
326
|
+
if (column) {
|
|
327
|
+
var table_name = column.match(/^(?:[^:]|:[^:])*/);
|
|
328
|
+
if (table_name && table_names.indexOf(table_name[0]) == -1)
|
|
329
|
+
table_names.push(table_name[0]);
|
|
330
|
+
}
|
|
331
|
+
});
|
|
332
|
+
return data_tables.sort(function (dt1, dt2) {
|
|
333
|
+
var i = table_names.indexOf(dt1.name), j = table_names.indexOf(dt2.name);
|
|
334
|
+
return (i == -1 ? Infinity : i) < (j == -1 ? Infinity : j) ? -1 : 1;
|
|
335
|
+
});
|
|
336
|
+
}
|
package/common/utils/json.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
export function
|
|
3
|
-
export function
|
|
1
|
+
import { DatasetType } from "./types";
|
|
2
|
+
export declare function safeStringify(obj: unknown): string | undefined;
|
|
3
|
+
export declare function javaScriptStringify(v: unknown): string | undefined;
|
|
4
|
+
export declare function stringifyPreparedData(data: {
|
|
5
|
+
[dataset: string]: DatasetType;
|
|
6
|
+
}): string;
|
package/common/utils/json.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.safeStringify = safeStringify;
|
|
4
|
+
exports.javaScriptStringify = javaScriptStringify;
|
|
5
|
+
exports.stringifyPreparedData = stringifyPreparedData;
|
|
4
6
|
function escapeChar(c) {
|
|
5
7
|
var hex = c.charCodeAt(0).toString(16);
|
|
6
8
|
while (hex.length < 4)
|
|
@@ -15,7 +17,6 @@ function safeStringify(obj) {
|
|
|
15
17
|
return undefined;
|
|
16
18
|
return raw.replace(/[\u2028\u2029<]/g, escapeChar);
|
|
17
19
|
}
|
|
18
|
-
exports.safeStringify = safeStringify;
|
|
19
20
|
function javaScriptStringify(v) {
|
|
20
21
|
var type = typeof v;
|
|
21
22
|
if (v == null) {
|
|
@@ -40,9 +41,8 @@ function javaScriptStringify(v) {
|
|
|
40
41
|
throw new Error("javaScriptStringify couldn't handle " + type + " object: " + v);
|
|
41
42
|
}
|
|
42
43
|
}
|
|
43
|
-
exports.javaScriptStringify = javaScriptStringify;
|
|
44
44
|
function stringifyDataset(dataset) {
|
|
45
|
-
return "(function(array, column_names, metadata){ array.column_names = column_names; array.metadata = metadata; return array; })(" + javaScriptStringify(dataset) + ", " + safeStringify(dataset.column_names) + ", " + safeStringify(dataset.metadata) + ")";
|
|
45
|
+
return "(function(array, column_names, metadata, timestamps){ array.column_names = column_names; array.metadata = metadata; array.timestamps = timestamps; return array; })(" + javaScriptStringify(dataset) + ", " + safeStringify(dataset.column_names) + ", " + safeStringify(dataset.metadata) + ", " + javaScriptStringify(dataset.timestamps) + ")";
|
|
46
46
|
}
|
|
47
47
|
function stringifyPreparedData(data) {
|
|
48
48
|
var s = "{";
|
|
@@ -57,4 +57,3 @@ function stringifyPreparedData(data) {
|
|
|
57
57
|
s += "}";
|
|
58
58
|
return s;
|
|
59
59
|
}
|
|
60
|
-
exports.stringifyPreparedData = stringifyPreparedData;
|
package/common/utils/state.js
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/* This file is used by the story player, and must be IE-compatible */
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.
|
|
4
|
+
exports.isObject = isObject;
|
|
5
|
+
exports.flatten = flatten;
|
|
6
|
+
exports.unflatten = unflatten;
|
|
7
|
+
exports.merge = merge;
|
|
8
|
+
exports.deepCopyObject = deepCopyObject;
|
|
9
|
+
exports.deepEqual = deepEqual;
|
|
10
|
+
exports.getStateChanges = getStateChanges;
|
|
5
11
|
function isObject(x) {
|
|
6
12
|
return !Array.isArray(x) && typeof x === "object" && x != null;
|
|
7
13
|
}
|
|
8
|
-
exports.isObject = isObject;
|
|
9
14
|
/* Example: { a: { b: { c: 2, d: 3 } } } ↦
|
|
10
15
|
{
|
|
11
16
|
"a": { b: { c: 2, d: 3 } },
|
|
@@ -29,7 +34,6 @@ function flatten(o, keys, result) {
|
|
|
29
34
|
}
|
|
30
35
|
return result;
|
|
31
36
|
}
|
|
32
|
-
exports.flatten = flatten;
|
|
33
37
|
// { "a.b.c": 2, "a.b.d":3 } → { a: { b: { c: 2, d: 3 } } }
|
|
34
38
|
function unflatten(o) {
|
|
35
39
|
var r = {};
|
|
@@ -45,7 +49,6 @@ function unflatten(o) {
|
|
|
45
49
|
}
|
|
46
50
|
return r;
|
|
47
51
|
}
|
|
48
|
-
exports.unflatten = unflatten;
|
|
49
52
|
function merge(dest, source) {
|
|
50
53
|
for (var prop in source) {
|
|
51
54
|
if (isObject(dest[prop]) && isObject(source[prop])) {
|
|
@@ -57,7 +60,6 @@ function merge(dest, source) {
|
|
|
57
60
|
}
|
|
58
61
|
return dest;
|
|
59
62
|
}
|
|
60
|
-
exports.merge = merge;
|
|
61
63
|
function deepCopyObject(obj) {
|
|
62
64
|
if (obj == null)
|
|
63
65
|
return obj;
|
|
@@ -75,7 +77,6 @@ function deepCopyObject(obj) {
|
|
|
75
77
|
}
|
|
76
78
|
return copy;
|
|
77
79
|
}
|
|
78
|
-
exports.deepCopyObject = deepCopyObject;
|
|
79
80
|
// Simple deep equality test for JSON-definable objects
|
|
80
81
|
// The idea is that two objects test equal if they would
|
|
81
82
|
// JSON.stringify to the same thing, modulo key ordering.
|
|
@@ -126,7 +127,6 @@ function deepEqual(a, b) {
|
|
|
126
127
|
return typeof b === "undefined";
|
|
127
128
|
}
|
|
128
129
|
}
|
|
129
|
-
exports.deepEqual = deepEqual;
|
|
130
130
|
function getStateChanges(state1, state2) {
|
|
131
131
|
var diff = {};
|
|
132
132
|
for (var name in state2) {
|
|
@@ -141,4 +141,3 @@ function getStateChanges(state1, state2) {
|
|
|
141
141
|
}
|
|
142
142
|
return diff;
|
|
143
143
|
}
|
|
144
|
-
exports.getStateChanges = getStateChanges;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
type ColumnTypeInMetadata = {
|
|
2
|
+
type: string;
|
|
3
|
+
type_id: string;
|
|
4
|
+
output_format_id: string;
|
|
5
|
+
};
|
|
6
|
+
export type DatasetType = Record<string, unknown>[] & {
|
|
7
|
+
column_names: {
|
|
8
|
+
[data_binding_key: string]: string | string[];
|
|
9
|
+
};
|
|
10
|
+
metadata: {
|
|
11
|
+
[data_binding_key: string]: ColumnTypeInMetadata | (ColumnTypeInMetadata | null)[];
|
|
12
|
+
};
|
|
13
|
+
timestamps: {
|
|
14
|
+
last_updated?: Date;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
export type DataBinding = {
|
|
18
|
+
data_table_id: number;
|
|
19
|
+
} & ({
|
|
20
|
+
column: number;
|
|
21
|
+
columns?: null;
|
|
22
|
+
} | {
|
|
23
|
+
column?: null;
|
|
24
|
+
columns: number[];
|
|
25
|
+
});
|
|
26
|
+
export type DataBindings = Record<string, DataBinding>;
|
|
27
|
+
export type TemplateDataBinding = {
|
|
28
|
+
dataset: string;
|
|
29
|
+
key: string;
|
|
30
|
+
name?: string;
|
|
31
|
+
type?: string;
|
|
32
|
+
description?: string;
|
|
33
|
+
data_type?: string[];
|
|
34
|
+
assignment?: {
|
|
35
|
+
can_rebind?: boolean;
|
|
36
|
+
min_columns?: number;
|
|
37
|
+
max_columns?: number;
|
|
38
|
+
hints: Record<string, unknown>;
|
|
39
|
+
};
|
|
40
|
+
optional?: boolean;
|
|
41
|
+
} & ({
|
|
42
|
+
column: string;
|
|
43
|
+
} | {
|
|
44
|
+
columns: string;
|
|
45
|
+
});
|
|
46
|
+
export type KeyToTemplateDataBinding = {
|
|
47
|
+
[key: string]: TemplateDataBinding;
|
|
48
|
+
};
|
|
49
|
+
export type DatasetToKeyToTemplateDataBinding = {
|
|
50
|
+
[dataset: string]: KeyToTemplateDataBinding;
|
|
51
|
+
};
|
|
52
|
+
export type ColumnType = {
|
|
53
|
+
index: number;
|
|
54
|
+
type_id: string;
|
|
55
|
+
output_format_id: string;
|
|
56
|
+
};
|
|
57
|
+
export type ColumnTypesById = {
|
|
58
|
+
[data_table_id: string]: ColumnType[];
|
|
59
|
+
};
|
|
60
|
+
export type NullableColumnTypesById = {
|
|
61
|
+
[data_table_id: string]: ColumnType[] | null;
|
|
62
|
+
};
|
|
63
|
+
export {};
|
package/lib/cmd/login.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
var { read } = require("read");
|
|
3
4
|
var readline = require("readline"),
|
|
4
|
-
|
|
5
|
-
read = require("read"),
|
|
6
|
-
|
|
7
5
|
log = require("../log"),
|
|
8
6
|
sdk = require("../sdk");
|
|
9
7
|
|
|
@@ -26,25 +24,22 @@ exports.command = function login(args) {
|
|
|
26
24
|
}
|
|
27
25
|
|
|
28
26
|
function getPassword() {
|
|
29
|
-
return
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
return read({ prompt: "Password: ", silent: true })
|
|
28
|
+
.then((response) => {
|
|
29
|
+
console.log();
|
|
30
|
+
return response;
|
|
33
31
|
});
|
|
34
|
-
});
|
|
35
32
|
}
|
|
36
33
|
|
|
37
34
|
function getToken() {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
resolve(token);
|
|
35
|
+
if (args.token) {
|
|
36
|
+
return Promise.resolve(args.token);
|
|
37
|
+
}
|
|
38
|
+
return read({ prompt: "SDK Token: ", silent: true })
|
|
39
|
+
.then((response) => {
|
|
40
|
+
console.log();
|
|
41
|
+
return response;
|
|
46
42
|
});
|
|
47
|
-
});
|
|
48
43
|
}
|
|
49
44
|
|
|
50
45
|
function login(email, password) {
|
package/lib/cmd/logout.js
CHANGED
|
@@ -3,15 +3,27 @@
|
|
|
3
3
|
var log = require("../log"),
|
|
4
4
|
sdk = require("../sdk");
|
|
5
5
|
|
|
6
|
-
exports.command = function logout() {
|
|
7
|
-
|
|
8
|
-
.
|
|
9
|
-
|
|
6
|
+
exports.command = async function logout(server_opts) {
|
|
7
|
+
try {
|
|
8
|
+
await sdk.request(server_opts, "user/logout", {}, { exit_on_failure: false });
|
|
9
|
+
}
|
|
10
|
+
catch (e) {
|
|
11
|
+
log.warn("Failed to revoke SDK Token. Your token may not correspond to a valid active user session.");
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Delete token from local file
|
|
15
|
+
try {
|
|
16
|
+
await sdk.deleteSdkToken(server_opts.host);
|
|
17
|
+
log.victory("Deleted SDK token.");
|
|
18
|
+
}
|
|
19
|
+
catch (e) {
|
|
20
|
+
log.die(e);
|
|
21
|
+
}
|
|
10
22
|
};
|
|
11
23
|
|
|
12
24
|
exports.help = `
|
|
13
25
|
flourish logout
|
|
14
26
|
|
|
15
|
-
|
|
27
|
+
Revokes the active user token and deletes it from the .flourish_sdk file from your HOME or USERPROFILE directory. You
|
|
16
28
|
will not be able to communicate with the server until you “flourish login”
|
|
17
29
|
`;
|
package/lib/cmd/publish.js
CHANGED
|
@@ -5,7 +5,6 @@ var fs = require("fs"),
|
|
|
5
5
|
|
|
6
6
|
archiver = require("archiver"),
|
|
7
7
|
tmp = require("tmp"),
|
|
8
|
-
FormData = require("form-data"),
|
|
9
8
|
|
|
10
9
|
d3_dsv = require("d3-dsv"),
|
|
11
10
|
|
|
@@ -97,16 +96,12 @@ function zipUpTemplate(template_dir, config) {
|
|
|
97
96
|
}
|
|
98
97
|
|
|
99
98
|
async function uploadTemplate(server_opts, template_id, external_version, zip_filename) {
|
|
99
|
+
const { FormData, fileFrom } = await import("node-fetch");
|
|
100
100
|
const body = new FormData();
|
|
101
|
-
const stat = await fs.promises.stat(zip_filename);
|
|
102
101
|
|
|
103
102
|
body.append("id", template_id);
|
|
104
103
|
body.append("version", external_version);
|
|
105
|
-
body.append("template",
|
|
106
|
-
contentType: "application/zip",
|
|
107
|
-
filename: "template.zip",
|
|
108
|
-
knownLength: stat.size
|
|
109
|
-
});
|
|
104
|
+
body.append("template", await fileFrom(zip_filename, "application/zip"), "template.zip");
|
|
110
105
|
|
|
111
106
|
return sdk.request(server_opts, "template/publish", body);
|
|
112
107
|
}
|
package/lib/cmd/register.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
var { read } = require("read");
|
|
3
4
|
var readline = require("readline"),
|
|
4
|
-
|
|
5
|
-
read = require("read"),
|
|
6
|
-
|
|
7
5
|
log = require("../log"),
|
|
8
6
|
sdk = require("../sdk");
|
|
9
7
|
|
|
@@ -17,22 +15,21 @@ exports.command = function register(args) {
|
|
|
17
15
|
|
|
18
16
|
function getPassword() {
|
|
19
17
|
return new Promise(function(resolve, reject) {
|
|
20
|
-
read({ prompt: "Password: ", silent: true }
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
read({ prompt: "Confirm password: ", silent: true }, function(error, pw_ii) {
|
|
24
|
-
if (error) return reject(error);
|
|
18
|
+
read({ prompt: "Password: ", silent: true }).then((pw_i) => {
|
|
19
|
+
read({ prompt: "Confirm password: ", silent: true }).then((pw_ii) => {
|
|
25
20
|
if (pw_i === pw_ii) return resolve(pw_i);
|
|
26
21
|
|
|
27
22
|
log.warn("Passwords not the same! Try again.");
|
|
28
|
-
read({ prompt: "Confirm password: ", silent: true }, function(error, pw_iii) {
|
|
29
|
-
if (error) return reject(error);
|
|
30
23
|
|
|
24
|
+
read({ prompt: "Confirm password: ", silent: true }).then((pw_iii) => {
|
|
31
25
|
if (pw_i === pw_iii) return resolve(pw_i);
|
|
32
26
|
reject(new Error("Passwords still don’t match. Exiting."));
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
|
|
27
|
+
})
|
|
28
|
+
.catch(reject);
|
|
29
|
+
})
|
|
30
|
+
.catch(reject);
|
|
31
|
+
})
|
|
32
|
+
.catch(reject);
|
|
36
33
|
});
|
|
37
34
|
}
|
|
38
35
|
|