Skip to content

Commit b6ed95b

Browse files
authored
JavaScript SDK: Transaction version, cloneDatabase, deserialize TransactionResult (#4111)
* Add Connection.transactionVersion and unit tests * Added cloneDatabase API and associated unit tests * Override generated code for ApiClient.js so that we deserialize whenever we have response.text * Update javascript patch diff to fix ApiClient.js such that it deserializes on all existing response.text fields * Rename Connection to ConnectionBase per RAI renaming plan * Maintain map of database to version in ConnectionBase * Add unit tests for clone/transaction version interaction * Add Connection object as placeholder for eventual cloud connection. * Add sdk imports/exports to index.js * Update generated-javascript-client-sdk-patches.diff with index.js import/export updates for high-level sdk classes * Fix installSource/update query unit test.
1 parent d9dc15d commit b6ed95b

File tree

10 files changed

+470
-194
lines changed

10 files changed

+470
-194
lines changed

client/src/ApiClient.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,7 @@ class ApiClient {
470470
request.end((error, response) => {
471471
if (callback) {
472472
var data = null;
473-
if (!error) {
473+
if (response && response.text) {
474474
try {
475475
data = this.deserialize(response, returnType);
476476
if (this.enableCookies && typeof window === 'undefined'){

client/src/index.js

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,11 @@ import UpdateActionResult from './model/UpdateActionResult';
113113
import WorkspaceLoadProblem from './model/WorkspaceLoadProblem';
114114
import DefaultApi from './api/DefaultApi';
115115

116+
import ConnectionBase from './sdk/ConnectionBase';
117+
import Connection from './sdk/Connection';
118+
import LocalConnection from './sdk/LocalConnection';
119+
import RelAPIMixin from './sdk/RelAPIMixin';
120+
116121

117122
/**
118123
* This_is_a_Client_SDK_for_Delve_API.<br>
@@ -744,5 +749,29 @@ export {
744749
* The DefaultApi service constructor.
745750
* @property {module:api/DefaultApi}
746751
*/
747-
DefaultApi
752+
DefaultApi,
753+
754+
/**
755+
* The ConnectionBase sdk constructor.
756+
* @property {module:sdk/ConnectionBase}
757+
*/
758+
ConnectionBase,
759+
760+
/**
761+
* The Connection sdk constructor.
762+
* @property {module:sdk/Connection}
763+
*/
764+
Connection,
765+
766+
/**
767+
* The LocalConnection sdk constructor.
768+
* @property {module:sdk/LocalConnection}
769+
*/
770+
LocalConnection,
771+
772+
/**
773+
* The RelAPIMixin sdk constructor.
774+
* @property {module:sdk/RelAPIMixin}
775+
*/
776+
RelAPIMixin
748777
};

client/src/sdk/Connection.js

Lines changed: 11 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,101 +1,17 @@
1-
import { DefaultApi } from '../index.js';
2-
import ApiClient from '../ApiClient.js';
1+
import ConnectionBase from './ConnectionBase.js';
2+
import RelAPIMixin from './RelAPIMixin.js';
3+
4+
const Base = RelAPIMixin(ConnectionBase);
35

46
/**
5-
* Class representing a connection to the Rel server
7+
* Class representing a connection to the Rel Server
8+
*
9+
* @inherits ConnectionBase
10+
* @mixes RelAPIMixin
611
*/
7-
class Connection {
8-
/**
9-
* Create a connection
10-
* @param {String} [params.basePath] - The base URL against which to resolve every API call's (relative) path.
11-
* The default is http://127.0.0.1:8010.
12-
* @param {Array.<String>} [params.authentications] - The authentication methods to be included for all API calls.
13-
* This is a placeholder for eventual use with the cloud connection.
14-
* @param {Array.<String>} [params.defaultHeaders] - The default HTTP headers to be included for all API calls.
15-
* The default is {}
16-
* @param {Number} [params.timeout] - The default HTTP timeout for all API calls. The default is 60000
17-
* @param {Boolean} [params.cache] - If set to false an additional timestamp parameter is added to all API GET
18-
* calls to prevent browser caching. The default is true
19-
* @param {Boolean} [params.enableCookies] - If set to true, the client will save the cookies from each server
20-
* response, and return them in the next request.
21-
*/
22-
constructor(params = {}) {
23-
const apiClient = new ApiClient();
24-
this._defaultApi = new DefaultApi(apiClient);
25-
this._api = this._defaultApi.apiClient;
26-
27-
if (params.basePath) {
28-
this._api.basePath = params.basePath;
29-
}
30-
if (params.authentications) {
31-
this._api.authentications = params.authentications;
32-
}
33-
if (params.defaultHeaders) {
34-
this._api.defaultHeaders = params.defaultHeaders;
35-
}
36-
if (params.hasOwnProperty('timeout')) {
37-
this._api.timeout = params.timeout;
38-
}
39-
if (params.hasOwnProperty('cache')) {
40-
this._api.cache = params.cache;
41-
}
42-
if (params.hasOwnProperty('enableCookies')) {
43-
this._api.enableCookies = params.enableCookies;
44-
}
45-
}
46-
47-
get api() {
48-
return this._api;
49-
}
50-
51-
get defaultApi() {
52-
return this._defaultApi;
53-
}
54-
55-
get transactionPost() {
56-
return this._transactionPost;
57-
}
58-
59-
get basePath() {
60-
return this._api.basePath;
61-
}
62-
set basePath(basePath) {
63-
this._api.basePath = basePath;
64-
}
65-
66-
get authentications() {
67-
return this._api.authentications;
68-
}
69-
set authentications(authentications) {
70-
this._api.authentications = authentications;
71-
}
72-
73-
get defaultHeaders() {
74-
return this._api.defaultHeaders;
75-
}
76-
set defaultHeaders(defaultHeaders) {
77-
this._api.defaultHeaders = defaultHeaders;
78-
}
79-
80-
get cache() {
81-
return this._api.cache;
82-
}
83-
set cache(cache) {
84-
this._api.cache = cache;
85-
}
86-
87-
get timeout() {
88-
return this._api.timeout;
89-
}
90-
set timeout(timeout) {
91-
this._api.timeout = timeout;
92-
}
93-
94-
get enableCookies() {
95-
return this._api.enableCookies;
96-
}
97-
set enableCookies(enableCookies) {
98-
this._api.enableCookies = enableCookies;
12+
class Connection extends Base {
13+
constructor(params) {
14+
super(params);
9915
}
10016
}
10117

client/src/sdk/ConnectionBase.js

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import { DefaultApi } from '../index.js';
2+
import ApiClient from '../ApiClient.js';
3+
4+
/**
5+
* Base class representing a connection to the Rel server
6+
*/
7+
class ConnectionBase {
8+
/**
9+
* Create a connection
10+
* @param {String} [params.basePath] - The base URL against which to resolve every API call's (relative) path.
11+
* The default is http://127.0.0.1:8010.
12+
* @param {Array.<String>} [params.authentications] - The authentication methods to be included for all API calls.
13+
* This is a placeholder for eventual use with the cloud connection.
14+
* @param {Array.<String>} [params.defaultHeaders] - The default HTTP headers to be included for all API calls.
15+
* The default is {}
16+
* @param {Number} [params.timeout] - The default HTTP timeout for all API calls. The default is 60000
17+
* @param {Boolean} [params.cache] - If set to false an additional timestamp parameter is added to all API GET
18+
* calls to prevent browser caching. The default is true
19+
* @param {Boolean} [params.enableCookies] - If set to true, the client will save the cookies from each server
20+
* response, and return them in the next request.
21+
*/
22+
constructor(params = {}) {
23+
const apiClient = new ApiClient();
24+
this._defaultApi = new DefaultApi(apiClient);
25+
this._api = this._defaultApi.apiClient;
26+
this._versionMap = new Map()
27+
28+
if (params.basePath) {
29+
this._api.basePath = params.basePath;
30+
}
31+
if (params.authentications) {
32+
this._api.authentications = params.authentications;
33+
}
34+
if (params.defaultHeaders) {
35+
this._api.defaultHeaders = params.defaultHeaders;
36+
}
37+
if (params.hasOwnProperty('timeout')) {
38+
this._api.timeout = params.timeout;
39+
}
40+
if (params.hasOwnProperty('cache')) {
41+
this._api.cache = params.cache;
42+
}
43+
if (params.hasOwnProperty('enableCookies')) {
44+
this._api.enableCookies = params.enableCookies;
45+
}
46+
}
47+
48+
get api() {
49+
return this._api;
50+
}
51+
52+
get defaultApi() {
53+
return this._defaultApi;
54+
}
55+
56+
get transactionPost() {
57+
return this._transactionPost;
58+
}
59+
60+
get basePath() {
61+
return this._api.basePath;
62+
}
63+
set basePath(basePath) {
64+
this._api.basePath = basePath;
65+
}
66+
67+
get authentications() {
68+
return this._api.authentications;
69+
}
70+
set authentications(authentications) {
71+
this._api.authentications = authentications;
72+
}
73+
74+
get defaultHeaders() {
75+
return this._api.defaultHeaders;
76+
}
77+
set defaultHeaders(defaultHeaders) {
78+
this._api.defaultHeaders = defaultHeaders;
79+
}
80+
81+
get cache() {
82+
return this._api.cache;
83+
}
84+
set cache(cache) {
85+
this._api.cache = cache;
86+
}
87+
88+
get timeout() {
89+
return this._api.timeout;
90+
}
91+
set timeout(timeout) {
92+
this._api.timeout = timeout;
93+
}
94+
95+
get enableCookies() {
96+
return this._api.enableCookies;
97+
}
98+
set enableCookies(enableCookies) {
99+
this._api.enableCookies = enableCookies;
100+
}
101+
102+
/**
103+
* Returns the database's current transaction version value.
104+
*
105+
* @param {String} dbname - The name of the database
106+
*/
107+
getTransactionVersion(dbname) {
108+
const version = this._versionMap.get(dbname);
109+
return version == null ? 0 : version;
110+
}
111+
112+
/**
113+
* Sets the database's current transaction version value.
114+
*
115+
* @param {String} dbname - The name of the database
116+
* @param {Int} transactionVersion - The database's transaction version value
117+
*/
118+
setTransactionVersion(dbname, transactionVersion) {
119+
this._versionMap.set(dbname, transactionVersion);
120+
}
121+
}
122+
123+
export default ConnectionBase;

client/src/sdk/LocalConnection.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import Connection from './Connection.js';
1+
import ConnectionBase from './ConnectionBase.js';
22
import RelAPIMixin from './RelAPIMixin.js';
33

4-
const Base = RelAPIMixin(Connection);
4+
const Base = RelAPIMixin(ConnectionBase);
55

66
/**
77
* Class representing a local connection to the Rel Server
88
*
9-
* @inherits Connection
9+
* @inherits ConnectionBase
1010
* @mixes RelAPIMixin
1111
*/
1212
class LocalConnection extends Base {

client/src/sdk/RelAPIMixin.js

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,9 @@ function RelAPIMixin(Base) {
3434
transaction.dbname = dbname;
3535
transaction.readonly = isReadOnly;
3636
transaction.actions = actions;
37+
transaction.version = this.getTransactionVersion(dbname);
3738

38-
try {
39-
this.defaultApi.transactionPost(transaction, (error, result, response) => {
40-
resolve({error, result, response});
41-
});
42-
}
43-
catch(e) {
44-
reject(e);
45-
}
39+
this._transactionPost(transaction, resolve, reject);
4640
});
4741
}
4842

@@ -271,6 +265,36 @@ function RelAPIMixin(Base) {
271265
return this.runActions(dbname, [], true, Transaction.ModeEnum.OPEN);
272266
}
273267

268+
/**
269+
* Create a new database instance by cloning from an existing database, with all of the
270+
* same state as the old database but with a new name.
271+
*
272+
* If overwrite=true is passed, an existing database at `cloneName` will be overwritten
273+
* with `dbName`'s contents.
274+
*
275+
* @param {String} cloneName - The name of the new, cloned database
276+
* @param {String} dbName - The name of the database from which to create the clone
277+
* @param {Boolean} overwrite - If true, overwrites an existing database of name `cloneName`
278+
* @returns {Promise} - Resolves to object: {error, result, response} where
279+
* `result` is a `TransactionResult`.
280+
*/
281+
cloneDatabase(cloneName, dbName, overwrite) {
282+
const mode = overwrite
283+
? Transaction.ModeEnum.CLONE_OVERWRITE
284+
: Transaction.ModeEnum.CLONE;
285+
286+
return new Promise((resolve, reject) => {
287+
let transaction = new Transaction();
288+
transaction.mode = mode;
289+
transaction.dbname = cloneName;
290+
transaction.source_dbname = dbName;
291+
transaction.readonly = false;
292+
transaction.actions = [];
293+
294+
this._transactionPost(transaction, resolve, reject);
295+
});
296+
}
297+
274298
/**
275299
* List Extensional Databases in database `dbname` with the relation name `relname`
276300
*
@@ -300,6 +324,26 @@ function RelAPIMixin(Base) {
300324

301325
return this.runAction(dbname, action, true, Transaction.ModeEnum.OPEN);
302326
}
327+
328+
//
329+
// Internal helper calling `transactionPost` while managing
330+
// the transaction version.
331+
//
332+
_transactionPost(transaction, resolve, reject) {
333+
const dbname = transaction.dbname;
334+
let self = this;
335+
try {
336+
this.defaultApi.transactionPost(transaction, (error, result, response) => {
337+
if (result && result.version > self.getTransactionVersion(dbname)) {
338+
self.setTransactionVersion(dbname, result.version);
339+
}
340+
resolve({error, result, response});
341+
});
342+
}
343+
catch(e) {
344+
reject(e);
345+
}
346+
}
303347
}
304348

305349
return RelAPI;

0 commit comments

Comments
 (0)