Skip to content

Commit 1a7148b

Browse files
authored
JavaScript SDK: Implement loadJSON as a temporary measure for Notebook development (#4179)
* Implement `loadJSON` * Drop support for key parameter
1 parent 9c512b3 commit 1a7148b

File tree

2 files changed

+157
-0
lines changed

2 files changed

+157
-0
lines changed

client/src/sdk/RelAPIMixin.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import {
44
LabeledAction,
55
ListEdbAction,
66
ListSourceAction,
7+
LoadData,
8+
LoadDataAction,
79
ModifyWorkspaceAction,
810
QueryAction,
911
Source,
@@ -171,6 +173,30 @@ function RelAPIMixin(Base) {
171173
return this.createLabeledAction(actionName, action);
172174
}
173175

176+
/**
177+
* Constructs an action to load JSON data
178+
*
179+
* @param {String} name - Name for this action
180+
* @param {String} data - String data in JSON format
181+
* @param {String} path - Path or url to JSON file if `data` is null
182+
* @param {String} relname - Relation name
183+
* @returns {LabledAction}
184+
*/
185+
loadJSONAction(name, data, path, relname) {
186+
let loadData = new LoadData();
187+
loadData.content_type = 'application/json';
188+
loadData.data = data;
189+
loadData.path = path;
190+
loadData.key = [];
191+
192+
let action = new LoadDataAction();
193+
action.rel = relname;
194+
action.value = loadData;
195+
action.type = 'LoadDataAction';
196+
197+
return this.createLabeledAction(name, action)
198+
}
199+
174200
/**
175201
* Query the database `dbname`
176202
*
@@ -325,6 +351,25 @@ function RelAPIMixin(Base) {
325351
return this.runAction(dbname, action, true, Transaction.ModeEnum.OPEN);
326352
}
327353

354+
/**
355+
* Import a JSON string or a JSON file
356+
* Deprecated - Use the language-internal query instead.
357+
*
358+
* @param {String} dbname - The name of the database
359+
* @param {String} data - A string representing the JSON to import. Provide either `data` or `path`
360+
* @param {String} path - Path to a JSON file. Provide either `data` or `path`
361+
* @param {String} relname - The relation name to use for referencing the JSON data
362+
* @returns {Promise} - Resolves to object: {error, result, response} where
363+
* `result` is a `TransactionResult`.
364+
*/
365+
loadJSON(dbname, data, path, relname, actionName = 'action') {
366+
console.warn('loadJSON is deprecated. Use the language-internal query instead.');
367+
368+
const action = this.loadJSONAction(actionName, data, path, relname);
369+
370+
return this.runAction(dbname, action, false, Transaction.ModeEnum.OPEN);
371+
}
372+
328373
//
329374
// Internal helper calling `transactionPost` while managing
330375
// the transaction version.

client/test/sdk/RelAPIMixin.test.js

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
const assert = require('assert');
2+
const fs = require('fs').promises;
3+
const os = require('os');
24
import LocalConnection from '../../src/sdk/LocalConnection.js';
35

46
const defaultSources = ["intrinsics", "stdlib", "ml"];
@@ -426,4 +428,114 @@ describe('RelAPIMixin', () => {
426428
});
427429
}).timeout(60000);
428430
});
431+
432+
describe('#loadJSON from data', () => {
433+
const dbname = createUniqueName('db');
434+
initializeDatabase(dbname);
435+
436+
const relname = 'people';
437+
const jsonString = JSON.stringify({
438+
name: {
439+
first: "William",
440+
last: "Shakespeare"
441+
},
442+
age: 100
443+
});
444+
445+
const tempFileName = `${os.tmpdir()}/${dbname}.json`;
446+
447+
it(`loads the JSON string, ${jsonString}`, () => {
448+
return lc.loadJSON(dbname, jsonString, null, relname).then(res => {
449+
assert.strictEqual(res.error, null);
450+
assert.strictEqual(res.result.problems.length, 0);
451+
});
452+
}).timeout(60000);
453+
it(`finds the relation that was loaded`, () => {
454+
return lc.query(dbname, `def output=${relname}`).then(res => {
455+
assert.strictEqual(res.error, null);
456+
assert.strictEqual(res.result.problems.length, 0);
457+
assert.notStrictEqual(res.result.output, null);
458+
assert.strictEqual(res.result.output.length, 3);
459+
});
460+
}).timeout(60000);
461+
it(`queries to export_json to ${tempFileName}`, () => {
462+
return lc.query(dbname, `def export=export_json[(:path, "${tempFileName}");(:data,${relname})]`).then(res => {
463+
assert.strictEqual(res.error, null);
464+
});
465+
}).timeout(60000);
466+
it(`loads the expected JSON from file ${tempFileName}`, () => {
467+
return fs.readFile(tempFileName, 'utf-8').then(result => {
468+
let json;
469+
try {
470+
json = JSON.parse(result);
471+
}
472+
catch(e) {
473+
assert.notStrictEqual('The loaded JSON does not parse', null);
474+
}
475+
const jsonInput = JSON.parse(jsonString);
476+
assert.strictEqual(json.name.first, jsonInput.name.first);
477+
assert.strictEqual(json.name.last, jsonInput.name.last);
478+
assert.strictEqual(json.age, jsonInput.age);
479+
});
480+
}).timeout(60000);
481+
});
482+
483+
describe('#loadJSON from path', () => {
484+
const dbname = createUniqueName('db');
485+
initializeDatabase(dbname);
486+
487+
const relname = 'people';
488+
const jsonString = JSON.stringify({
489+
name: {
490+
first: "William",
491+
last: "Shakespeare"
492+
},
493+
age: 100
494+
});
495+
496+
const tempFileName = `${os.tmpdir()}/${dbname}.json`;
497+
const tempFileName1 = `${os.tmpdir()}/${dbname}1.json`;
498+
499+
it(`writes the JSON string to temp file ${tempFileName}`, () => {
500+
return fs.writeFile(tempFileName, jsonString).then(() => {
501+
assert(true);
502+
}).catch(error => {
503+
assert.strictEqual(error, null);
504+
});
505+
}).timeout(60000);
506+
it(`loads the JSON file, ${tempFileName}`, () => {
507+
return lc.loadJSON(dbname, null, tempFileName, relname).then(res => {
508+
assert.strictEqual(res.error, null);
509+
assert.strictEqual(res.result.problems.length, 0);
510+
});
511+
}).timeout(60000);
512+
it(`finds the relation that was loaded`, () => {
513+
return lc.query(dbname, `def output=${relname}`).then(res => {
514+
assert.strictEqual(res.error, null);
515+
assert.strictEqual(res.result.problems.length, 0);
516+
assert.notStrictEqual(res.result.output, null);
517+
assert.strictEqual(res.result.output.length, 3);
518+
});
519+
}).timeout(60000);
520+
it(`queries to export_json to ${tempFileName1}`, () => {
521+
return lc.query(dbname, `def export=export_json[(:path, "${tempFileName1}");(:data,${relname})]`).then(res => {
522+
assert.strictEqual(res.error, null);
523+
});
524+
}).timeout(60000);
525+
it(`loads the expected JSON from file ${tempFileName1}`, () => {
526+
return fs.readFile(tempFileName1, 'utf-8').then(result => {
527+
let json;
528+
try {
529+
json = JSON.parse(result);
530+
}
531+
catch(e) {
532+
assert.notStrictEqual('The loaded JSON does not parse', null);
533+
}
534+
const jsonInput = JSON.parse(jsonString);
535+
assert.strictEqual(json.name.first, jsonInput.name.first);
536+
assert.strictEqual(json.name.last, jsonInput.name.last);
537+
assert.strictEqual(json.age, jsonInput.age);
538+
});
539+
}).timeout(60000);
540+
});
429541
});

0 commit comments

Comments
 (0)