backendless 6.3.0 → 6.3.4

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.
@@ -308,6 +308,37 @@ var UnitOfWork = /*#__PURE__*/function () {
308
308
 
309
309
  return this.addOperations(_constants.OperationType.FIND, tableName, payload);
310
310
  }
311
+ /**
312
+ * upsert(object: object): OpResult;
313
+ * upsert(tableName: string, object: object): OpResult;
314
+ * **/
315
+
316
+ }, {
317
+ key: "upsert",
318
+ value: function upsert() {
319
+ var tableName;
320
+ var changes;
321
+
322
+ if (arguments.length === 1) {
323
+ tableName = _utils["default"].getClassName(arguments.length <= 0 ? undefined : arguments[0]);
324
+ changes = arguments.length <= 0 ? undefined : arguments[0];
325
+ } else if (arguments.length === 2) {
326
+ tableName = arguments.length <= 0 ? undefined : arguments[0];
327
+ changes = arguments.length <= 1 ? undefined : arguments[1];
328
+ } else {
329
+ throw new Error('Invalid arguments');
330
+ }
331
+
332
+ if (!tableName || typeof tableName !== 'string') {
333
+ throw new Error('Invalid arguments');
334
+ }
335
+
336
+ if (!changes || (0, _typeof2["default"])(changes) !== 'object' || Array.isArray(changes)) {
337
+ throw new Error('Invalid arguments');
338
+ }
339
+
340
+ return this.addOperations(_constants.OperationType.UPSERT, tableName, changes);
341
+ }
311
342
  /**
312
343
  * create(object: object): OpResult;
313
344
  * create(tableName: string, object: object): OpResult;
@@ -436,6 +467,29 @@ var UnitOfWork = /*#__PURE__*/function () {
436
467
 
437
468
  return this.addOperations(_constants.OperationType.DELETE, tableName, object);
438
469
  }
470
+ /**
471
+ * bulkUpsert(tableName: string, objects: object[]): OpResult;
472
+ * bulkUpsert(objects: object[]): OpResult;
473
+ * **/
474
+
475
+ }, {
476
+ key: "bulkUpsert",
477
+ value: function bulkUpsert(tableName, objects) {
478
+ if (Array.isArray(tableName)) {
479
+ objects = tableName;
480
+ tableName = _utils["default"].getClassName(objects[0]);
481
+ }
482
+
483
+ if (!objects || !Array.isArray(objects)) {
484
+ throw new Error('Objects must be an array of objects.');
485
+ }
486
+
487
+ if (!tableName || typeof tableName !== 'string') {
488
+ throw new Error('Table Name must be a string.');
489
+ }
490
+
491
+ return this.addOperations(_constants.OperationType.UPSERT_BULK, tableName, objects);
492
+ }
439
493
  /**
440
494
  * bulkCreate(tableName: string, objects: object[]): OpResult;
441
495
  * bulkCreate(objects: object[]): OpResult;
@@ -63,9 +63,14 @@ var OperationJSONAdapter = {
63
63
  payload = _ref3.payload;
64
64
  return uow.update.call(uow, table, resolveOpResultValueReference(uow, payload));
65
65
  },
66
- UPDATE_BULK: function UPDATE_BULK(uow, _ref4) {
66
+ UPSERT: function UPSERT(uow, _ref4) {
67
67
  var table = _ref4.table,
68
68
  payload = _ref4.payload;
69
+ return uow.upsert.call(uow, table, resolveOpResultValueReference(uow, payload));
70
+ },
71
+ UPDATE_BULK: function UPDATE_BULK(uow, _ref5) {
72
+ var table = _ref5.table,
73
+ payload = _ref5.payload;
69
74
  var args = baseBulkArgs(uow, {
70
75
  table: table,
71
76
  payload: payload
@@ -73,55 +78,60 @@ var OperationJSONAdapter = {
73
78
  args.push(resolveOpResultValueReference(uow, payload.changes));
74
79
  return uow.bulkUpdate.apply(uow, args);
75
80
  },
76
- DELETE_BULK: function DELETE_BULK(uow, _ref5) {
77
- var table = _ref5.table,
78
- payload = _ref5.payload;
81
+ DELETE_BULK: function DELETE_BULK(uow, _ref6) {
82
+ var table = _ref6.table,
83
+ payload = _ref6.payload;
79
84
  var args = baseBulkArgs(uow, {
80
85
  table: table,
81
86
  payload: payload
82
87
  });
83
88
  return uow.bulkDelete.apply(uow, args);
84
89
  },
85
- CREATE_BULK: function CREATE_BULK(uow, _ref6) {
86
- var table = _ref6.table,
87
- payload = _ref6.payload;
88
- return uow.bulkCreate.call(uow, table, resolveOpResultValueReference(uow, payload));
89
- },
90
- SET_RELATION: function SET_RELATION(uow, _ref7) {
90
+ CREATE_BULK: function CREATE_BULK(uow, _ref7) {
91
91
  var table = _ref7.table,
92
92
  payload = _ref7.payload;
93
+ return uow.bulkCreate.call(uow, table, resolveOpResultValueReference(uow, payload));
94
+ },
95
+ UPSERT_BULK: function UPSERT_BULK(uow, _ref8) {
96
+ var table = _ref8.table,
97
+ payload = _ref8.payload;
98
+ return uow.bulkUpsert.call(uow, table, resolveOpResultValueReference(uow, payload));
99
+ },
100
+ SET_RELATION: function SET_RELATION(uow, _ref9) {
101
+ var table = _ref9.table,
102
+ payload = _ref9.payload;
93
103
  return updateRelations(uow, 'setRelation', {
94
104
  table: table,
95
105
  payload: payload
96
106
  });
97
107
  },
98
- DELETE_RELATION: function DELETE_RELATION(uow, _ref8) {
99
- var table = _ref8.table,
100
- payload = _ref8.payload;
108
+ DELETE_RELATION: function DELETE_RELATION(uow, _ref10) {
109
+ var table = _ref10.table,
110
+ payload = _ref10.payload;
101
111
  return updateRelations(uow, 'deleteRelation', {
102
112
  table: table,
103
113
  payload: payload
104
114
  });
105
115
  },
106
- ADD_RELATION: function ADD_RELATION(uow, _ref9) {
107
- var table = _ref9.table,
108
- payload = _ref9.payload;
116
+ ADD_RELATION: function ADD_RELATION(uow, _ref11) {
117
+ var table = _ref11.table,
118
+ payload = _ref11.payload;
109
119
  return updateRelations(uow, 'addToRelation', {
110
120
  table: table,
111
121
  payload: payload
112
122
  });
113
123
  },
114
- FIND: function FIND(uow, _ref10) {
115
- var table = _ref10.table,
116
- payload = _ref10.payload;
124
+ FIND: function FIND(uow, _ref12) {
125
+ var table = _ref12.table,
126
+ payload = _ref12.payload;
117
127
  return uow.addOperations(_constants.OperationType.FIND, table, payload);
118
128
  }
119
129
  };
120
130
  exports.OperationJSONAdapter = OperationJSONAdapter;
121
131
 
122
- function baseBulkArgs(uow, _ref11) {
123
- var table = _ref11.table,
124
- payload = _ref11.payload;
132
+ function baseBulkArgs(uow, _ref13) {
133
+ var table = _ref13.table,
134
+ payload = _ref13.payload;
125
135
  var args = [];
126
136
 
127
137
  if (payload.conditional) {
@@ -141,9 +151,9 @@ function baseBulkArgs(uow, _ref11) {
141
151
  return args;
142
152
  }
143
153
 
144
- function updateRelations(uow, method, _ref12) {
145
- var table = _ref12.table,
146
- payload = _ref12.payload;
154
+ function updateRelations(uow, method, _ref14) {
155
+ var table = _ref14.table,
156
+ payload = _ref14.payload;
147
157
  var args = [table];
148
158
 
149
159
  if (typeof payload.parentObject === 'string') {
package/lib/urls.js CHANGED
@@ -142,6 +142,11 @@ var Urls = /*#__PURE__*/function () {
142
142
  value: function dataTable(tableName) {
143
143
  return "".concat(this.data(), "/").concat(tableName);
144
144
  }
145
+ }, {
146
+ key: "dataTableUpsert",
147
+ value: function dataTableUpsert(tableName) {
148
+ return "".concat(this.data(), "/").concat(tableName, "/upsert");
149
+ }
145
150
  }, {
146
151
  key: "dataTableDeepSave",
147
152
  value: function dataTableDeepSave(tableName) {
@@ -182,6 +187,11 @@ var Urls = /*#__PURE__*/function () {
182
187
  value: function dataBulkTable(tableName) {
183
188
  return "".concat(this.data(), "/bulk/").concat(tableName);
184
189
  }
190
+ }, {
191
+ key: "dataBulkTableUpsert",
192
+ value: function dataBulkTableUpsert(tableName) {
193
+ return "".concat(this.data(), "/bulkupsert/").concat(tableName);
194
+ }
185
195
  }, {
186
196
  key: "dataBulkTableDelete",
187
197
  value: function dataBulkTableDelete(tableName) {
@@ -314,6 +324,16 @@ var Urls = /*#__PURE__*/function () {
314
324
  key: "fileBinaryPath",
315
325
  value: function fileBinaryPath(path) {
316
326
  return "".concat(this.files(), "/binary/").concat(path);
327
+ }
328
+ }, {
329
+ key: "fileAppendPath",
330
+ value: function fileAppendPath(path) {
331
+ return "".concat(this.files(), "/append/").concat(path);
332
+ }
333
+ }, {
334
+ key: "fileAppendBinaryPath",
335
+ value: function fileAppendBinaryPath(path) {
336
+ return "".concat(this.files(), "/append/binary/").concat(path);
317
337
  } //users
318
338
 
319
339
  }, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "backendless",
3
- "version": "6.3.0",
3
+ "version": "6.3.4",
4
4
  "description": "Backendless JavaScript SDK for Node.js and the browser",
5
5
  "browser": "dist/backendless.js",
6
6
  "main": "lib/index.js",
@@ -83,7 +83,7 @@
83
83
  "rimraf": "^3.0.2",
84
84
  "socket.io": "^2.3.0",
85
85
  "terser-webpack-plugin": "^2.3.8",
86
- "typescript": "^4.3.4",
86
+ "typescript": "^4.5.4",
87
87
  "watch": "^1.0.2",
88
88
  "watchify": "^4.0.0",
89
89
  "webpack": "^4.46.0",
@@ -1,13 +1,15 @@
1
1
  import { RTListeners } from '../rt'
2
2
 
3
3
  const ChangesTypes = {
4
- CREATED: 'created',
5
- UPDATED: 'updated',
6
- DELETED: 'deleted',
7
-
8
- BULK_CREATED: 'bulk-created',
9
- BULK_UPDATED: 'bulk-updated',
10
- BULK_DELETED: 'bulk-deleted',
4
+ CREATED : 'created',
5
+ UPDATED : 'updated',
6
+ DELETED : 'deleted',
7
+ UPSERTED: 'upserted',
8
+
9
+ BULK_CREATED : 'bulk-created',
10
+ BULK_UPDATED : 'bulk-updated',
11
+ BULK_DELETED : 'bulk-deleted',
12
+ BULK_UPSERTED: 'bulk-upserted',
11
13
  }
12
14
 
13
15
  const RelationsChangesTypes = {
@@ -20,6 +22,7 @@ const SingleChangesTypes = [
20
22
  ChangesTypes.CREATED,
21
23
  ChangesTypes.UPDATED,
22
24
  ChangesTypes.DELETED,
25
+ ChangesTypes.UPSERTED,
23
26
  ]
24
27
 
25
28
  export default class RTHandlers extends RTListeners {
@@ -53,6 +56,22 @@ export default class RTHandlers extends RTListeners {
53
56
  this.removeCreateListeners(undefined, callback)
54
57
  }
55
58
 
59
+ addUpsertListener(whereClause, callback, onError) {
60
+ this.addChangesListener(ChangesTypes.UPSERTED, whereClause, callback, onError)
61
+ }
62
+
63
+ removeUpsertListeners(whereClause, callback) {
64
+ this.removeChangesListeners(ChangesTypes.UPSERTED, whereClause, callback)
65
+ }
66
+
67
+ removeUpsertListener(callback) {
68
+ if (!callback || typeof callback !== 'function') {
69
+ throw new Error('Listener Function must be passed.')
70
+ }
71
+
72
+ this.removeUpsertListeners(undefined, callback)
73
+ }
74
+
56
75
  addUpdateListener(whereClause, callback, onError) {
57
76
  this.addChangesListener(ChangesTypes.UPDATED, whereClause, callback, onError)
58
77
  }
@@ -133,6 +152,22 @@ export default class RTHandlers extends RTListeners {
133
152
  this.removeBulkDeleteListeners(undefined, callback)
134
153
  }
135
154
 
155
+ addBulkUpsertListener(whereClause, callback, onError) {
156
+ this.addChangesListener(ChangesTypes.BULK_UPSERTED, whereClause, callback, onError)
157
+ }
158
+
159
+ removeBulkUpsertListeners() {
160
+ this.removeChangesListeners(ChangesTypes.BULK_UPSERTED)
161
+ }
162
+
163
+ removeBulkUpsertListener(callback) {
164
+ if (!callback || typeof callback !== 'function') {
165
+ throw new Error('Listener Function must be passed.')
166
+ }
167
+
168
+ this.removeChangesListeners(ChangesTypes.BULK_UPSERTED, undefined, callback)
169
+ }
170
+
136
171
  addSetRelationListener(relationColumnName, parentObjects, callback, onError) {
137
172
  this.addRelationsChangesListener(RelationsChangesTypes.SET, relationColumnName, parentObjects, callback, onError)
138
173
  }
package/src/data/store.js CHANGED
@@ -48,10 +48,14 @@ export default class DataStore {
48
48
  return this.rtHandlers = this.rtHandlers || new RTHandlers(this)
49
49
  }
50
50
 
51
- async save(object) {
51
+ async save(object, isUpsert) {
52
+ const url = isUpsert
53
+ ? this.app.urls.dataTableUpsert(this.className)
54
+ : this.app.urls.dataTable(this.className)
55
+
52
56
  return this.app.request
53
57
  .put({
54
- url : this.app.urls.dataTable(this.className),
58
+ url,
55
59
  data: convertToServerRecord(object),
56
60
  })
57
61
  .then(result => this.parseResponse(result))
@@ -229,6 +233,27 @@ export default class DataStore {
229
233
  })
230
234
  }
231
235
 
236
+ async bulkUpsert(objects) {
237
+ const errorMessage = 'Objects must be provided and must be an array of objects.'
238
+
239
+ if (!objects || !Array.isArray(objects) || !objects.length) {
240
+ throw new Error(errorMessage)
241
+ }
242
+
243
+ objects = objects.map(object => {
244
+ if (!object || typeof object !== 'object' || Array.isArray(object)) {
245
+ throw new Error(errorMessage)
246
+ }
247
+
248
+ return object
249
+ })
250
+
251
+ return this.app.request.put({
252
+ url : this.app.urls.dataBulkTableUpsert(this.className),
253
+ data: objects,
254
+ })
255
+ }
256
+
232
257
  async bulkUpdate(condition, changes) {
233
258
  if (!condition || typeof condition !== 'string') {
234
259
  throw new Error('Condition must be provided and must be a string.')
@@ -29,7 +29,7 @@ export default class Files {
29
29
  query.overwrite = overwrite
30
30
  }
31
31
 
32
- filePath = FilesUtils.preventSlashInPath(filePath)
32
+ filePath = FilesUtils.trimSlashesInPath(filePath)
33
33
  fileName = FilesUtils.sanitizeFileName(fileName)
34
34
 
35
35
  return this.app.request.put({
@@ -47,7 +47,7 @@ export default class Files {
47
47
  query.overwrite = overwrite
48
48
  }
49
49
 
50
- filePath = FilesUtils.preventSlashInPath(filePath)
50
+ filePath = FilesUtils.trimSlashesInPath(filePath)
51
51
 
52
52
  const pathTokens = FilesUtils.parseFilePath(filePath)
53
53
 
@@ -66,7 +66,7 @@ export default class Files {
66
66
  }
67
67
 
68
68
  return this.app.request.post({
69
- url : `${this.app.urls.filePath(filePath)}/${fileName || ''}`,
69
+ url : `${this.app.urls.filePath(filePath)}/${fileName}`,
70
70
  query: query,
71
71
  data : {
72
72
  url: file
@@ -93,6 +93,94 @@ export default class Files {
93
93
  })
94
94
  }
95
95
 
96
+ async append(filePath, fileName, fileContent) {
97
+ if (!filePath || typeof filePath !== 'string') {
98
+ throw new Error('"filePath" must be provided and must be a string.')
99
+ }
100
+
101
+ filePath = FilesUtils.trimSlashesInPath(filePath)
102
+
103
+ if (arguments.length === 2) {
104
+ fileContent = fileName
105
+ fileName = undefined
106
+
107
+ const pathTokens = FilesUtils.parseFilePath(filePath)
108
+
109
+ if (pathTokens.fileName) {
110
+ filePath = pathTokens.filePath
111
+ fileName = pathTokens.fileName
112
+ }
113
+ }
114
+
115
+ if (!fileName) {
116
+ throw new Error('Can not resolve target file name')
117
+ }
118
+
119
+ fileName = FilesUtils.sanitizeFileName(fileName)
120
+
121
+ if (typeof fileContent === 'string') {
122
+ return this.app.request.post({
123
+ url : `${this.app.urls.fileAppendPath(filePath)}/${fileName}`,
124
+ data: {
125
+ url: fileContent
126
+ },
127
+ })
128
+ }
129
+
130
+ if (FilesUtils.isBytesArray(fileContent)) {
131
+ fileContent = await FilesUtils.toBase64(fileContent)
132
+
133
+ return this.app.request.put({
134
+ url : `${this.app.urls.fileAppendBinaryPath(filePath)}/${fileName}`,
135
+ headers: { 'Content-Type': 'text/plain' },
136
+ data : fileContent,
137
+ })
138
+ }
139
+
140
+ return this.app.request.post({
141
+ url : `${this.app.urls.fileAppendPath(filePath)}/${fileName}`,
142
+ form: {
143
+ file: fileContent
144
+ },
145
+ })
146
+ }
147
+
148
+ async appendText(filePath, fileName, textContent) {
149
+ if (!filePath || typeof filePath !== 'string') {
150
+ throw new Error('"filePath" must be provided and must be a string.')
151
+ }
152
+
153
+ filePath = FilesUtils.trimSlashesInPath(filePath)
154
+
155
+ if (arguments.length === 2) {
156
+ textContent = fileName
157
+ fileName = undefined
158
+
159
+ const pathTokens = FilesUtils.parseFilePath(filePath)
160
+
161
+ if (pathTokens.fileName) {
162
+ filePath = pathTokens.filePath
163
+ fileName = pathTokens.fileName
164
+ }
165
+ }
166
+
167
+ if (!fileName) {
168
+ throw new Error('Can not resolve target file name')
169
+ }
170
+
171
+ if (typeof textContent !== 'string') {
172
+ throw new Error('"textContent" must be a string')
173
+ }
174
+
175
+ fileName = FilesUtils.sanitizeFileName(fileName)
176
+
177
+ return this.app.request.put({
178
+ url : `${this.app.urls.fileAppendPath(filePath)}/${fileName}`,
179
+ headers: { 'Content-Type': 'text/plain' },
180
+ data : textContent,
181
+ })
182
+ }
183
+
96
184
  async listing(filePath, pattern, sub, pagesize, offset) {
97
185
  const query = {}
98
186
 
@@ -100,7 +188,7 @@ export default class Files {
100
188
  throw new Error('"filePath" must be provided and must be a string.')
101
189
  }
102
190
 
103
- filePath = FilesUtils.preventSlashInPath(filePath)
191
+ filePath = FilesUtils.trimSlashesInPath(filePath)
104
192
 
105
193
  if (pattern && typeof pattern === 'string') {
106
194
  query.pattern = pattern
@@ -181,7 +269,7 @@ export default class Files {
181
269
  throw new Error('"filePath" must be provided and must be a string.')
182
270
  }
183
271
 
184
- filePath = FilesUtils.preventSlashInPath(filePath)
272
+ filePath = FilesUtils.trimSlashesInPath(filePath)
185
273
 
186
274
  return this.app.request.get({
187
275
  url : this.app.urls.filePath(filePath),
@@ -196,7 +284,7 @@ export default class Files {
196
284
  throw new Error('Directory "path" must be provided and must be a string.')
197
285
  }
198
286
 
199
- directoryPath = FilesUtils.preventSlashInPath(directoryPath)
287
+ directoryPath = FilesUtils.trimSlashesInPath(directoryPath)
200
288
 
201
289
  return this.app.request.delete({
202
290
  url: this.app.urls.filePath(directoryPath),
@@ -212,7 +300,7 @@ export default class Files {
212
300
  throw new Error('Files Pattern must be provided and must be a string.')
213
301
  }
214
302
 
215
- filesPath = FilesUtils.preventSlashInPath(filesPath)
303
+ filesPath = FilesUtils.trimSlashesInPath(filesPath)
216
304
 
217
305
  return this.app.request.get({
218
306
  url : this.app.urls.filePath(filesPath),
@@ -1,10 +1,33 @@
1
1
  const FilesUtils = {
2
+
3
+ isBytesArray(data) {
4
+ if (typeof Buffer !== 'undefined' && data instanceof Buffer) {
5
+ return true
6
+ }
7
+
8
+ if (typeof ArrayBuffer !== 'undefined' && data instanceof ArrayBuffer) {
9
+ return true
10
+ }
11
+
12
+ return Array.isArray(data)
13
+ },
14
+
2
15
  ensureSlashInPath(path) {
3
16
  return !path.startsWith('/') ? `/${path}` : path
4
17
  },
5
18
 
6
- preventSlashInPath(path) {
7
- return (path && path.startsWith('/')) ? path.slice(1) : path
19
+ trimSlashesInPath(path) {
20
+ if (path) {
21
+ if (path.startsWith('/')) {
22
+ path = path.slice(1)
23
+ }
24
+
25
+ if (path.endsWith('/')) {
26
+ path = path.slice(0, path.length - 1)
27
+ }
28
+ }
29
+
30
+ return path
8
31
  },
9
32
 
10
33
  parseFilePath(path) {
package/src/index.js CHANGED
@@ -420,7 +420,8 @@ class Backendless {
420
420
  /** @deprecated */
421
421
  get applicationId() {
422
422
  // eslint-disable-next-line no-console
423
- console.warn('getter/setter for Backendless.applicationId is deprecated, instead use Backendless.appId')
423
+ // temporary comment it because it breaks JS-CodeRunner version less than 6.3.0
424
+ // console.warn('getter/setter for Backendless.applicationId is deprecated, instead use Backendless.appId')
424
425
 
425
426
  return this.appId
426
427
  }
@@ -18,6 +18,7 @@ export default class EmailEnvelope {
18
18
  this.ccAddresses = Utils.castArray(data.ccAddresses)
19
19
  this.bccAddresses = Utils.castArray(data.bccAddresses)
20
20
  this.query = data.query || null
21
+ this.uniqueEmails = data.uniqueEmails || false
21
22
  }
22
23
 
23
24
  /**
@@ -129,6 +130,23 @@ export default class EmailEnvelope {
129
130
  return this.query
130
131
  }
131
132
 
133
+ /**
134
+ * @param {boolean} uniqueEmails
135
+ * @returns {EmailEnvelope}
136
+ */
137
+ setUniqueEmails(uniqueEmails) {
138
+ this.uniqueEmails = uniqueEmails
139
+
140
+ return this
141
+ }
142
+
143
+ /**
144
+ * @returns {uniqueEmails|boolean}
145
+ */
146
+ getUniqueEmails() {
147
+ return this.uniqueEmails
148
+ }
149
+
132
150
  toJSON() {
133
151
  const data = {}
134
152
 
@@ -148,6 +166,8 @@ export default class EmailEnvelope {
148
166
  data.criteria = this.query
149
167
  }
150
168
 
169
+ data.uniqueEmails = this.uniqueEmails
170
+
151
171
  return data
152
172
  }
153
173
  }
@@ -118,10 +118,14 @@ export default class Messaging {
118
118
 
119
119
  data['template-name'] = templateName
120
120
 
121
- if (templateValues) {
121
+ if (templateValues && !Array.isArray(templateValues)) {
122
122
  data['template-values'] = templateValues
123
123
  }
124
124
 
125
+ if (Array.isArray(templateValues) && !attachments) {
126
+ attachments = templateValues
127
+ }
128
+
125
129
  if (attachments) {
126
130
  data.attachment = attachments
127
131
  }
@@ -5,6 +5,8 @@ export const OperationType = {
5
5
  UPDATE_BULK : 'UPDATE_BULK',
6
6
  DELETE : 'DELETE',
7
7
  DELETE_BULK : 'DELETE_BULK',
8
+ UPSERT : 'UPSERT',
9
+ UPSERT_BULK : 'UPSERT_BULK',
8
10
  FIND : 'FIND',
9
11
  ADD_RELATION : 'ADD_RELATION',
10
12
  SET_RELATION : 'SET_RELATION',