@flourish/sdk 3.14.1 → 3.17.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/RELEASE_NOTES.md CHANGED
@@ -1,3 +1,23 @@
1
+ # 3.17.0
2
+
3
+ * Allow published visualisations to be cloned into the SDK
4
+
5
+ # 3.16.0
6
+ * Upgrade all NPM dependencies.
7
+
8
+ # 3.15.1
9
+ * Avoid treating numeric-looking arguments as numbers.
10
+
11
+ # 3.15.0
12
+
13
+ * Reinstate preview link
14
+ * Remove template author info from side panel
15
+ * Fix z-index issue on resize bar
16
+
17
+ # 3.14.2
18
+
19
+ * Improve error checking of conditional-property overrides
20
+
1
21
  # 3.14.1
2
22
 
3
23
  * Remove stray build logging. #64
@@ -0,0 +1,36 @@
1
+ {
2
+ "decisions": {
3
+ "1002401|npm-audit-resolver>yargs-unparser>yargs>string-width>strip-ansi>ansi-regex": {
4
+ "decision": "ignore",
5
+ "madeAt": 1637059117447,
6
+ "expiresAt": 1637663913365
7
+ },
8
+ "1002401|npm-audit-resolver>yargs-unparser>yargs>cliui>string-width>strip-ansi>ansi-regex": {
9
+ "decision": "ignore",
10
+ "madeAt": 1637059117447,
11
+ "expiresAt": 1637663913365
12
+ },
13
+ "1002401|npm-audit-resolver>yargs-unparser>yargs>cliui>wrap-ansi>string-width>strip-ansi>ansi-regex": {
14
+ "decision": "ignore",
15
+ "madeAt": 1637059117447,
16
+ "expiresAt": 1637663913365
17
+ },
18
+ "1004946|npm-audit-resolver>yargs-unparser>yargs>string-width>strip-ansi>ansi-regex": {
19
+ "decision": "ignore",
20
+ "madeAt": 1639560165214,
21
+ "expiresAt": 1642152161687
22
+ },
23
+ "1004946|npm-audit-resolver>yargs-unparser>yargs>cliui>string-width>strip-ansi>ansi-regex": {
24
+ "decision": "ignore",
25
+ "madeAt": 1639560165214,
26
+ "expiresAt": 1642152161687
27
+ },
28
+ "1004946|npm-audit-resolver>yargs-unparser>yargs>cliui>wrap-ansi>string-width>strip-ansi>ansi-regex": {
29
+ "decision": "ignore",
30
+ "madeAt": 1639560165214,
31
+ "expiresAt": 1642152161687
32
+ }
33
+ },
34
+ "rules": {},
35
+ "version": 1
36
+ }
package/bin/flourish CHANGED
@@ -57,6 +57,11 @@ process.on("unhandledRejection", function(reason, p) {
57
57
 
58
58
  function main() {
59
59
  const args = minimist(process.argv.slice(2), OPTS);
60
+
61
+ // minimist unhelpfully treats numeric strings as numbers;
62
+ // which means we have to turn them back into strings.
63
+ args._ = args._.map(x => "" + x);
64
+
60
65
  let command = args._[0];
61
66
 
62
67
  const server_opts = {
@@ -9,7 +9,7 @@ function assign_version_number(args, server_opts) {
9
9
  let template_id_promise, template_version;
10
10
  if (args._.length == 2) {
11
11
  // Assume the supplied argument is a version number, and try to get the id from the current directory
12
- template_id_promise = sdk.readAndValidateConfig(".").then(config => config.id);
12
+ template_id_promise = sdk.readAndValidateConfig(".").then(({config}) => config.id);
13
13
  template_version = args._[1];
14
14
  }
15
15
  else if (args._.length == 3) {
package/lib/cmd/help.js CHANGED
@@ -24,7 +24,7 @@ help.help = `
24
24
  Commands:
25
25
  flourish assign-version-number [template id] version
26
26
  flourish build [build rules...]
27
- flourish delete [--force] template_id
27
+ flourish delete [--force] template_id version
28
28
  flourish [-h|--help|help] [topic]
29
29
  flourish history [--full] template_id
30
30
  flourish list [--full] [template id]
@@ -5,9 +5,13 @@ var fs = require("fs"),
5
5
 
6
6
  archiver = require("archiver"),
7
7
  tmp = require("tmp"),
8
+ FormData = require("form-data"),
9
+
10
+ d3_dsv = require("d3-dsv"),
8
11
 
9
12
  log = require("../log"),
10
- sdk = require("../sdk");
13
+ sdk = require("../sdk"),
14
+ data_utils = require("../../server/data");
11
15
 
12
16
  function zipUpTemplate(template_dir, config) {
13
17
  return new Promise(function(resolve, reject) {
@@ -48,6 +52,21 @@ function zipUpTemplate(template_dir, config) {
48
52
  if (config.settings) zip.append(JSON.stringify(config.settings), { name: "settings.js" });
49
53
  if (config.data) zip.append(JSON.stringify(config.data), { name: "data.json" });
50
54
 
55
+ const data_dir = path.join(template_dir, "data");
56
+ if (fs.existsSync(data_dir)) {
57
+ // FIXME: check inferred types are compatible with specified types of data bindings
58
+ const column_types_by_sheet = {};
59
+ const files = fs.readdirSync(data_dir).filter(d => d.endsWith(".csv"));
60
+ for (const file of files) {
61
+ let csv_text = fs.readFileSync(path.join(template_dir, "data", file), "utf8");
62
+ if (csv_text.charAt(0) === "\uFEFF") csv_text = csv_text.substr(1);
63
+ const parsed_csv = d3_dsv.csvParseRows(csv_text);
64
+ column_types_by_sheet[file.replace(/\.csv$/, "")] = data_utils.getColumnTypesForData(parsed_csv);
65
+ }
66
+ zip.append(JSON.stringify(column_types_by_sheet), { name: "column_types_by_sheet.json" });
67
+ }
68
+
69
+
51
70
  if (fs.existsSync(path.join(template_dir, "GUIDE.md"))) {
52
71
  let file_path = path.join(template_dir, "GUIDE.md");
53
72
  zip.file(file_path, { name: "README.md" });
@@ -77,17 +96,16 @@ function zipUpTemplate(template_dir, config) {
77
96
  }
78
97
 
79
98
  function uploadTemplate(server_opts, template_id, external_version, zip_filename) {
80
- return sdk.request(server_opts, "template/publish", {
81
- id: template_id,
82
- version: external_version,
83
- template: {
84
- value: fs.createReadStream(zip_filename),
85
- options: {
86
- filename: "template.zip",
87
- contentType: "application/zip",
88
- }
89
- }
99
+ const body = new FormData();
100
+
101
+ body.append("id", template_id);
102
+ body.append("version", external_version);
103
+ body.append("template", fs.createReadStream(zip_filename), {
104
+ contentType: "application/zip",
105
+ filename: "template.zip"
90
106
  });
107
+
108
+ return sdk.request(server_opts, "template/publish", body);
91
109
  }
92
110
 
93
111
  function publish(args, server_opts) {
@@ -100,7 +118,7 @@ function publish(args, server_opts) {
100
118
  if (args.release) return sdk.removePrereleaseTag(template_dir);
101
119
  })
102
120
  .then(() => sdk.readAndValidateConfig(template_dir))
103
- .then((config) => {
121
+ .then(({config, warnings}) => {
104
122
  if (!config.id) log.die("The template’s template.yml doesn’t have an id. Add one and try again.");
105
123
 
106
124
  if (config.id.indexOf("/") > -1) {
@@ -143,6 +161,7 @@ function publish(args, server_opts) {
143
161
  log.victory(`Uploaded version ${external_version} on ${dt.toDateString()} at ${dt.toTimeString()}`,
144
162
  `Your template is available at ${protocol}://${server_opts.host}/@${template_path}/${external_version}`);
145
163
  }
164
+ warnings.forEach(warning => log.warn(warning));
146
165
  });
147
166
  })
148
167
  .catch((error) => {
package/lib/cmd/run.js CHANGED
@@ -17,7 +17,8 @@ function run(args) {
17
17
  port: port,
18
18
  listen: args.listen,
19
19
  open: args.open,
20
- debug: args.debug
20
+ debug: args.debug,
21
+ host: args.host
21
22
  });
22
23
  }
23
24
 
@@ -4,7 +4,7 @@ var log = require("../log"),
4
4
  sdk = require("../sdk");
5
5
 
6
6
  function version(args) {
7
- sdk.getSDKVersion()
7
+ sdk.getSdkVersion()
8
8
  .then((version_number) => console.log(version_number))
9
9
  .catch((error) => {
10
10
  if (args.debug) log.die("Failed to get SDK version number", error.message, error.stack);
package/lib/log.js CHANGED
@@ -12,7 +12,7 @@ function info(...lines) {
12
12
  for (let line of lines) console.log(colors.yellow(" " + line));
13
13
  }
14
14
  function warn(...lines) {
15
- for (let line of lines) console.warn(colors.yellow(" " + line));
15
+ for (let line of lines) console.warn(colors.yellow("⚠️ " + line));
16
16
  }
17
17
  function warn_bold(...lines) {
18
18
  for (let line of lines) console.warn(colors.bold.yellow(" " + line));
package/lib/sdk.js CHANGED
@@ -4,7 +4,8 @@ const fs = require("fs"),
4
4
  path = require("path"),
5
5
 
6
6
  cross_spawn = require("cross-spawn"),
7
- mod_request = require("request"),
7
+ fetch = require("node-fetch"),
8
+ FormData = require("form-data"),
8
9
  shell_quote = require("shell-quote"),
9
10
  yaml = require("js-yaml"),
10
11
  nodeResolve = require("resolve"),
@@ -21,7 +22,7 @@ const YAML_DUMP_OPTS = { flowLevel: 4 };
21
22
 
22
23
  const package_json_filename = path.join(__dirname, "..", "package.json");
23
24
  var sdk_version = null;
24
- function getSDKVersion() {
25
+ function getSdkVersion() {
25
26
  if (sdk_version) return Promise.resolve(sdk_version);
26
27
  return new Promise(function(resolve, reject) {
27
28
  fs.readFile(package_json_filename, "utf8", function(error, package_json) {
@@ -33,7 +34,7 @@ function getSDKVersion() {
33
34
  }
34
35
 
35
36
  function getSDKMajorVersion() {
36
- return getSDKVersion()
37
+ return getSdkVersion()
37
38
  .then((sdk_version) => {
38
39
  const version_tuple = sdk_version.split(".").map((x) => parseInt(x));
39
40
  return version_tuple[0];
@@ -94,77 +95,83 @@ const AUTHENTICATED_REQUEST_METHODS = new Set([
94
95
  "user/whoami"
95
96
  ]);
96
97
 
97
- const MULTIPART_REQUEST_METHODS = new Set([
98
- "template/publish",
99
- ]);
98
+ async function request(server_opts, method, data) {
99
+ let sdk_token;
100
100
 
101
- function request(server_opts, method, data) {
102
- let read_sdk_token_if_necessary;
103
101
  if (AUTHENTICATED_REQUEST_METHODS.has(method)) {
104
- read_sdk_token_if_necessary = getSdkToken(server_opts)
105
- .catch((error) => {
106
- log.problem(`Failed to read ${sdk_tokens_file}`, error.message);
107
- })
108
- .then((sdk_token) => {
109
- if (!sdk_token) {
110
- log.die("You are not logged in. Try ‘flourish login’ or ‘flourish register’ first.");
111
- }
112
- return sdk_token;
113
- });
114
- }
115
- else {
116
- read_sdk_token_if_necessary = Promise.resolve();
102
+ try {
103
+ sdk_token = await getSdkToken(server_opts);
104
+ }
105
+ catch (error) {
106
+ log.problem(`Failed to read ${sdk_tokens_file}`, error.message);
107
+ }
108
+ if (!sdk_token) {
109
+ log.die("You are not logged in. Try ‘flourish login’ or ‘flourish register’ first.");
110
+ }
117
111
  }
118
112
 
119
- return Promise.all([read_sdk_token_if_necessary, getSDKVersion()])
120
- .then(([sdk_token, sdk_version]) => new Promise(function(resolve, reject) {
121
- let protocol = "https";
122
- if (server_opts.host.match(/^(localhost|127\.0\.0\.1|.*\.local)(:\d+)?$/)) {
123
- protocol = "http";
124
- }
125
- let url = protocol + "://" + server_opts.host + "/api/v1/" + method;
126
- let request_params = {
127
- method: "POST",
128
- uri: url,
129
- };
130
-
131
- Object.assign(data, { sdk_token, sdk_version });
132
- if (server_opts.user) {
133
- request_params.auth = {
134
- user: server_opts.user,
135
- pass: server_opts.password,
136
- sendImmediately: true,
137
- };
138
- }
113
+ const sdk_version = await getSdkVersion();
114
+ const protocol = server_opts.host.match(/^(localhost|127\.0\.0\.1|.*\.local)(:\d+)?$/) ? "http:" : "https:";
115
+ const url = `${protocol}//${server_opts.host}/api/v1/${method}`;
116
+ const options = { method: data ? "POST" : "GET" };
139
117
 
140
- if (MULTIPART_REQUEST_METHODS.has(method)) {
141
- request_params.formData = data;
142
- }
143
- else {
144
- request_params.headers = { "Content-Type": "application/json" };
145
- request_params.body = JSON.stringify(data);
118
+ if (data) {
119
+ if (data instanceof FormData) {
120
+ if (sdk_token) {
121
+ data.append("sdk_token", sdk_token);
146
122
  }
123
+ data.append("sdk_version", sdk_version);
124
+ options.headers = data.getHeaders();
125
+ options.body = data;
126
+ }
127
+ else {
128
+ options.body = JSON.stringify({ ...data, sdk_token, sdk_version });
129
+ options.headers = { "content-type": "application/json" };
130
+ }
131
+ }
147
132
 
148
- mod_request(request_params, function(error, res) {
149
- if (error) log.die(error);
150
- if (res.statusCode == 200) {
151
- let r;
152
- try { r = JSON.parse(res.body); }
153
- catch (error) {
154
- log.die("Failed to parse response from server", error, res.body);
155
- }
156
- return resolve(r);
157
- }
133
+ if (server_opts.user) {
134
+ options.headers.authorization = Buffer.from(`${server_opts.user}:${server_opts.password}`).toString("base64");
135
+ }
158
136
 
159
- // We got an error response. See if we can parse it to extract an error message
160
- try {
161
- let r = JSON.parse(res.body);
162
- if ("error" in r) log.die("Error from server", r.error);
163
- }
164
- catch (e) { }
165
- log.die("Server error", res.body);
166
- });
167
- }));
137
+ let res;
138
+
139
+ try {
140
+ res = await fetch(url, options);
141
+ }
142
+ catch (e) {
143
+ log.die(e);
144
+ }
145
+
146
+ let text;
147
+
148
+ try {
149
+ // We could use res.json() here, but we're interested in what the body
150
+ // is when it's *not* json (load balancer issues etc.).
151
+ text = await res.text();
152
+ }
153
+ catch (error) {
154
+ log.die("Failed to get response from server", error);
155
+ }
156
+
157
+ let body;
158
+
159
+ try {
160
+ body = JSON.parse(text);
161
+ }
162
+ catch (error) {
163
+ log.die("Failed to parse response body", res.status, error, text);
164
+ }
165
+
166
+ if (res.ok) {
167
+ return body;
168
+ }
169
+
170
+ if (body.error) {
171
+ log.die("Error from server", res.status, body.error);
172
+ }
173
+
174
+ log.die("Server error", res.status, body);
168
175
  }
169
176
 
170
177
  function runBuildCommand(template_dir, command, node_env) {
@@ -346,13 +353,16 @@ async function resolveImports(config, template_dir) {
346
353
  for (let name in override) {
347
354
  if (name === "property" || name === "method") continue;
348
355
  if (method === "extend") {
356
+ if (["show_if", "hide_if"].includes(name) && typeof override[name] === "boolean") {
357
+ throw new Error(`Cannot extend a ${name} with Boolean value for property ${s.property}`);
358
+ }
349
359
  let extendee = s[name];
350
360
  if (extendee === undefined) {
351
361
  if (name === "show_if" && s.hide_if !== undefined) {
352
- Error(`Cannot extend a show_if when hide_if defined for property ${s.property}`);
362
+ throw new Error(`Cannot extend a show_if when hide_if defined for property ${s.property}`);
353
363
  }
354
364
  else if (name === "hide_if" && s.show_if !== undefined) {
355
- Error(`Cannot extend a hide_if when show_if defined for property ${s.property}`);
365
+ throw new Error(`Cannot extend a hide_if when show_if defined for property ${s.property}`);
356
366
  }
357
367
  extendee = {};
358
368
  }
@@ -380,6 +390,26 @@ async function resolveImports(config, template_dir) {
380
390
  return config;
381
391
  }
382
392
 
393
+ // Sets a default binding data_type of string in templates with both typed and untyped bindings, and return a post-publish warning message.
394
+ function checkDataTypes(config) {
395
+ const warnings = [];
396
+ if (!config.data) return { config, warnings };
397
+
398
+ const all_bindings = config.data.filter(binding => typeof binding !== "string"); // filter out title and description strings
399
+ const any_bindings_are_typed = all_bindings.some(binding => binding.data_type);
400
+
401
+ if (any_bindings_are_typed) {
402
+ config.data.forEach(binding => {
403
+ if (typeof binding === "string") return;
404
+ if (!binding.data_type) {
405
+ binding.data_type = "string";
406
+ warnings.push(`Missing data_type for key ${binding.key} in dataset ${binding.dataset} - assuming "string"`);
407
+ }
408
+ });
409
+ }
410
+ return { config, warnings };
411
+ }
412
+
383
413
  function readAndValidateConfig(template_dir) {
384
414
  return readConfig(template_dir)
385
415
  .then((config) => {
@@ -387,7 +417,8 @@ function readAndValidateConfig(template_dir) {
387
417
  return config;
388
418
  })
389
419
  .then(config => addShowConditions(config))
390
- .then(config => resolveImports(config, template_dir));
420
+ .then(config => resolveImports(config, template_dir))
421
+ .then(config => checkDataTypes(config));
391
422
  }
392
423
 
393
424
  function changeVersionNumberInPackageJson(template_dir, change_function) {
@@ -528,7 +559,7 @@ const TEMPLATE_SPECIAL = new Set([
528
559
  ]);
529
560
 
530
561
  module.exports = {
531
- checkTemplateVersion, getSDKVersion, getSDKMajorVersion,
562
+ checkTemplateVersion, getSdkVersion, getSDKMajorVersion,
532
563
 
533
564
  getSdkToken, setSdkToken, deleteSdkTokens,
534
565
  request,
@@ -227,7 +227,8 @@ function validateSetting(template_directory, conditional_settings, setting) {
227
227
  throw new Error(`template.yml setting “${property}” has unsupported width property: must be “full”, “half”, “quarter” or “three quarters”`);
228
228
  }
229
229
  if ("size" in setting) {
230
- if (setting.type !== "code" && setting.type !== "text") throw new Error(`template.yml setting “${property}” has a “size” setting but is not of type “string” or “code”`);
230
+ const can_set_size = setting.type == "code" || setting.type == "text" || (setting.type == "string" && setting.style == "buttons");
231
+ if (!can_set_size) throw new Error(`template.yml setting “${property}” has a “size” property; this requires type “text” or “code”, or type “string” with ”style: buttons”`);
231
232
  else if (setting.size !== "large") throw new Error(`template.yml setting “${property}” has unsupported size property: must be “large”`);
232
233
  }
233
234
  }
@@ -253,8 +254,8 @@ function validateSettings(template_directory, settings, bindings) {
253
254
  if (conditional_settings.size > 0) {
254
255
  conditional_settings.forEach(function(conditional_setting) {
255
256
  if (/^data\./.test(conditional_setting)) {
256
- if (!/^data\.\w+\.\w+$/.test(conditional_setting)) {
257
- throw new Error(`template.yml: “show_if” or “hide_if” property specifies invalid data binding “${conditional_setting}”`);
257
+ if (!/^data\.\w+\.\w+(\.type)?$/.test(conditional_setting)) {
258
+ throw new Error(`template.yml: “show_if” or “hide_if” property specifies invalid data binding or column type “${conditional_setting}”`);
258
259
  }
259
260
  if (!bindings || !Array.isArray(bindings)) {
260
261
  throw new Error(`template.yml: “show_if” or “hide_if” property refers to data binding “${conditional_setting}” when none are defined`);
@@ -271,7 +272,7 @@ function validateSettings(template_directory, settings, bindings) {
271
272
  }
272
273
  }
273
274
 
274
- function validateColSpec(spec, parser, data_table_names) {
275
+ function validateColSpec(spec, parser, data_table_names, is_optional) {
275
276
  const double_colon_ix = spec.indexOf("::");
276
277
  if (double_colon_ix == -1) throw new Error("Invalid data binding: " + spec);
277
278
  const data_table_name = spec.substr(0, double_colon_ix);
@@ -280,7 +281,7 @@ function validateColSpec(spec, parser, data_table_names) {
280
281
  }
281
282
 
282
283
  const col_spec = spec.substr(double_colon_ix + 2);
283
- parser(col_spec);
284
+ parser(col_spec, is_optional);
284
285
  }
285
286
 
286
287
  const VALID_DATA_BINDING_TYPES = new Set(["column", "columns"]);
@@ -320,7 +321,7 @@ function validateDataBinding(binding, data_table_names) {
320
321
  if (typeof binding.column !== "string") {
321
322
  throw new Error(`template.yml: “column” property of data binding “${binding_name}” must be a string`);
322
323
  }
323
- validateColSpec(binding.column, columns.parseColumn, data_table_names);
324
+ validateColSpec(binding.column, columns.parseColumn, data_table_names, binding.optional);
324
325
  }
325
326
  }
326
327
  else if (binding.type == "columns") {
package/package.json CHANGED
@@ -1,11 +1,13 @@
1
1
  {
2
2
  "name": "@flourish/sdk",
3
- "version": "3.14.1",
3
+ "version": "3.17.0",
4
4
  "description": "The Flourish SDK",
5
5
  "module": "src/index.js",
6
6
  "scripts": {
7
7
  "prepare": "cd .. && make sdk_clean sdk",
8
- "test": "mocha"
8
+ "test": "mocha --recursive",
9
+ "audit": "check-audit",
10
+ "audit:resolve": "resolve-audit"
9
11
  },
10
12
  "bin": {
11
13
  "flourish": "bin/flourish"
@@ -14,34 +16,40 @@
14
16
  "license": "SEE LICENSE IN LICENSE.md",
15
17
  "repository": "kiln/flourish-sdk",
16
18
  "dependencies": {
19
+ "@flourish/interpreter": "^6.0.3",
17
20
  "@flourish/semver": "^1.0.1",
18
- "archiver": "^3.0.0",
19
- "chokidar": "^3.0.1",
20
- "colors": "^1.3.3",
21
- "cross-spawn": "^6.0.5",
22
- "d3-dsv": "^1.1.1",
21
+ "@flourish/transform-data": "^2.1.0",
22
+ "@handlebars/allow-prototype-access": "^1.0.3",
23
+ "@rollup/plugin-commonjs": "^17.1.0",
24
+ "archiver": "^5.0.2",
25
+ "chokidar": "^3.4.3",
26
+ "colors": "^1.4.0",
27
+ "cross-spawn": "^7.0.3",
28
+ "d3-dsv": "^2.0.0",
23
29
  "express": "^4.17.1",
24
- "handlebars": "^4.1.2",
25
- "js-yaml": "^3.13.1",
26
- "minimist": "^1.2.0",
30
+ "form-data": "^4.0.0",
31
+ "handlebars": "^4.7.6",
32
+ "js-yaml": "^3.14.0",
33
+ "minimist": "^1.2.5",
27
34
  "ncp": "^2.0.0",
28
- "parse5": "^5.1.0",
35
+ "node-fetch": "^2.6.6",
36
+ "parse5": "^6.0.1",
29
37
  "read": "^1.0.7",
30
- "request": "^2.88.0",
31
- "resolve": "^1.11.1",
38
+ "resolve": "^1.18.1",
32
39
  "rewrite-links": "^1.1.0",
33
- "shell-quote": "^1.6.1",
34
- "tmp": "^0.1.0",
35
- "ws": "^7.0.1"
40
+ "rollup-plugin-terser": "^7.0.2",
41
+ "shell-quote": "^1.7.2",
42
+ "tmp": "^0.2.1",
43
+ "ws": "^7.4.6"
36
44
  },
37
45
  "devDependencies": {
46
+ "@rollup/plugin-node-resolve": "^9.0.0",
38
47
  "d3-request": "^1.0.6",
39
- "mocha": "^6.1.4",
40
- "rollup": "^1.16.2",
41
- "rollup-plugin-node-resolve": "^5.1.0",
42
- "rollup-plugin-uglify": "^6.0.2",
43
- "sinon": "^8.1.1",
44
- "tempy": "^0.3.0"
48
+ "mocha": "^9.1.2",
49
+ "npm-audit-resolver": "^2.3.0",
50
+ "rollup": "^2.32.1",
51
+ "sinon": "^9.2.0",
52
+ "tempy": "^1.0.0"
45
53
  },
46
54
  "engines": {
47
55
  "node": ">=8.3"