@kintone/kintone-js-sdk
Version:
The SDK of kintone REST API client on node and browser
926 lines (806 loc) • 25 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _Common = _interopRequireDefault(require("../../utils/Common"));
var _RecordCursor = _interopRequireDefault(require("../../module/cursor/RecordCursor"));
var _BulkRequest = _interopRequireDefault(require("../../module/bulkRequest/BulkRequest"));
var _RecordModels = _interopRequireDefault(require("../../model/record/RecordModels"));
var _Connection = _interopRequireDefault(require("../../connection/Connection"));
var _KintoneAPIException = _interopRequireDefault(require("../../exception/KintoneAPIException"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/* eslint-disable no-async-promise-executor, require-atomic-updates */
const LIMIT_UPDATE_RECORD = 100;
const LIMIT_POST_RECORD = 100;
const LIMIT_DELETE_RECORD = 100;
const NUM_BULK_REQUEST = 20;
const LIMIT_RECORD = 500;
const LIMIT_UPSERT_RECORD = 1500;
const DEFAULT_CURSOR_SIZE = 500;
/**
* Record module
*/
class Record {
/**
* The constructor for Record module
* @param {Object} params
* @param {Connection} params.connection
*/
constructor({
connection
} = {}) {
if (!(connection instanceof _Connection.default)) {
throw new _KintoneAPIException.default(`${connection} is not an instance of Connection`);
}
this.connection = connection;
}
/**
* @param {String} method
* @param {String} url
* @param {RecordModel} model
* @return {Promise} Promise
*/
sendRequest(method, url, model) {
return _Common.default.sendRequest(method, url, model, this.connection);
}
/**
* check required arguments
*
* @param {Object} params
* @returns {Promise<Boolean>}
*/
_validateRequiredArgs(params) {
return new Promise((resolve, reject) => {
try {
_Common.default.validateRequiredArgs(params);
resolve();
} catch (error) {
reject(error);
}
});
}
/**
* Get record by specific ID
* TODO: Parse to response model
* @param {Object} params
* @param {Number} params.app
* @param {Number} params.id
* @return {Promise} Promise
*/
getRecord({
app,
id
}) {
const getRecordRequest = new _RecordModels.default.GetRecordRequest(app, id);
return this.sendRequest('GET', 'record', getRecordRequest);
}
/**
* Get multi record with options
* TODO: Parse to response model
* @param {Object} params
* @param {Number} params.app
* @param {String} params.query
* @param {Array<String>} fields
* @param {Boolean} totalCount
* @return {Promise} Promise
*/
getRecords({
app,
query,
fields,
totalCount
} = {}) {
const getRecordsRequest = new _RecordModels.default.GetRecordsRequest(app, query, fields, totalCount);
return this.sendRequest('GET', 'records', getRecordsRequest);
}
getAllRecordsByCursor({
app,
query,
fields
} = {}) {
return this._validateRequiredArgs({
app
}).then(() => {
const kintoneRC = new _RecordCursor.default({
connection: this.connection
});
let myCursor;
return kintoneRC.createCursor({
app,
fields,
query,
DEFAULT_CURSOR_SIZE
}).then(creatCursorResponse => {
myCursor = creatCursorResponse;
return kintoneRC.getAllRecords({
id: myCursor.id
});
}).then(allRecords => {
if (allRecords.totalCount < myCursor.totalCount) {
kintoneRC.deleteCursor({
id: myCursor.id
});
}
return allRecords;
}).catch(err => {
if (myCursor) {
kintoneRC.deleteCursor({
id: myCursor.id
});
}
throw err;
});
});
}
/**
* Get multi records more than default limitation number by query
* TODO: Parse to response model
* @param {Object} params
* @param {Number} params.app
* @param {String} params.query
* @param {Array<String>} params.fields
* @param {Boolean} params.totalCount
* @param {Boolean} params.seek
* @return {Promise} Promise
*/
getAllRecordsByQuery({
app,
query,
fields,
totalCount,
seek = false
} = {}) {
return this._validateRequiredArgs({
app
}).then(() => {
return this.getAllRecordsByQueryRecursive(app, query, fields, totalCount, null, null, seek);
});
}
getAllRecordsByQueryRecursive(app, query, fields, totalCount, lastCount, records, seek) {
let allRecords = records || [];
let validQuery;
let nextCountNum;
const limit = LIMIT_RECORD;
if (seek) {
validQuery = this.createValidQueryForSeek(query, lastCount, limit);
if (fields && fields.length > 0 && fields.indexOf('$id') <= -1) {
fields.push('$id');
}
} else {
validQuery = this.createValidQueryForOffset(query, lastCount, limit);
}
const getRecordsRequest = new _RecordModels.default.GetRecordsRequest(app, validQuery, fields, totalCount);
return this.sendRequest('GET', 'records', getRecordsRequest).then(response => {
allRecords = allRecords.concat(response.records);
if (response.records.length < limit) {
return {
records: allRecords,
totalCount: totalCount ? allRecords.length : null
};
}
if (seek) {
nextCountNum = response.records[limit - 1].$id.value;
} else {
nextCountNum = lastCount + limit;
}
return this.getAllRecordsByQueryRecursive(app, query, fields, totalCount, nextCountNum, allRecords, seek);
});
}
createValidQueryForOffset(query, offset, limit) {
const offsetNum = offset || 0;
return query ? `${query} limit ${limit} offset ${offsetNum}` : `limit ${limit} offset ${offsetNum}`;
}
createValidQueryForSeek(query, lastRecord, limit) {
const lastRecordId = lastRecord || 0;
return query ? `$id > ${lastRecordId} and (${query}) order by $id asc limit ${limit}` : `$id > ${lastRecordId} order by $id asc limit ${limit}`;
}
/**
* Add the record
* @param {Object} params
* @param {Number} params.app
* @param {Record} params.record
* @return {Promise} Promise
*/
addRecord({
app,
record
} = {}) {
const addRecordRequest = new _RecordModels.default.AddRecordRequest(app, record);
return this.sendRequest('POST', 'record', addRecordRequest);
}
/**
* Add multi records
* @param {Object} params
* @param {Number} params.app
* @param {Array<record>} params.records
* @return {Promise} Promise
*/
addRecords({
app,
records
} = {}) {
const addRecordsRequest = new _RecordModels.default.AddRecordsRequest(app);
addRecordsRequest.setRecords(records);
return this.sendRequest('POST', 'records', addRecordsRequest);
}
/**
* Add multi records
* @param {Number} app
* @param {Array<record>} records
* @param {Number} offset
* @return {Promise} Promise
*/
addAllRecordsRecursive(app, records = [], offset = 0, results = []) {
const numRecordsPerBulk = NUM_BULK_REQUEST * LIMIT_POST_RECORD;
let begin = offset || 0;
const length = records.length || 0;
const end = length - begin < LIMIT_POST_RECORD ? length : begin + numRecordsPerBulk;
const recordsPerBulk = records.slice(begin, end);
let allResults = results || [];
return this.addBulkRecord(app, recordsPerBulk).then(response => {
allResults = allResults.concat(response.results);
begin += numRecordsPerBulk;
if (records.length <= begin) {
return allResults;
}
return this.addAllRecordsRecursive(app, records, begin, allResults);
}).catch(errors => {
if (errors.length <= NUM_BULK_REQUEST) {
errors = allResults.concat(errors);
}
throw errors;
});
}
/**
* Add all records
* @param {Object} params
* @param {Number} params.app
* @param {Record} params.records
* @return {Promise} Promise
*/
addAllRecords({
app,
records
}) {
return this._validateRequiredArgs({
app,
records
}).then(() => {
return this.addAllRecordsRecursive(app, records).then(response => {
return {
results: response
};
}).catch(errors => {
const errorsResponse = {
results: errors
};
throw errorsResponse;
});
});
}
addBulkRecord(app, records) {
const bulkRequest = new _BulkRequest.default({
connection: this.connection
});
const length = records.length;
const loopTimes = Math.ceil(length / LIMIT_POST_RECORD);
for (let index = 0; index < loopTimes; index++) {
const begin = index * LIMIT_POST_RECORD;
const end = length - begin < LIMIT_POST_RECORD ? length : begin + LIMIT_POST_RECORD;
const recordsPerRequest = records.slice(begin, end);
bulkRequest.addRecords({
app: app,
records: recordsPerRequest
});
}
return bulkRequest.execute();
}
/**
* Update the specific record by ID
* @param {Object} params
* @param {Number} params.app
* @param {Number} params.id
* @param {Record} params.record
* @param {Number} params.revision
* @return {Promise} Promise
*/
updateRecordByID({
app,
id,
record,
revision
} = {}) {
const updateRecordRequest = new _RecordModels.default.UpdateRecordRequest(app);
updateRecordRequest.setID(id).setRecord(record).setRevision(revision || 0);
return this.sendRequest('PUT', 'record', updateRecordRequest);
}
/**
* Update the specific record by updateKey
* @param {Object} params
* @param {Number} params.app
* @param {RecordUpdateKey} params.updateKey
* @param {Record} params.record
* @param {Number} params.revision
* @return {Promise} Promise
*/
updateRecordByUpdateKey({
app,
updateKey,
record,
revision
}) {
const fieldKey = updateKey ? updateKey.field : undefined;
const fieldValue = updateKey ? updateKey.value : undefined;
const updateRecordRequest = new _RecordModels.default.UpdateRecordRequest(app);
updateRecordRequest.setUpdateKey(fieldKey, fieldValue).setRecord(record).setRevision(revision || 0);
return this.sendRequest('PUT', 'record', updateRecordRequest);
}
/**
* create record Item With id, use to update multi Record
* @param {*} id
* @param {*} recordData
* @param {*} revision
* @return {RecordsUpdateItem}
*/
createRecordItemWithID(id, recordData, revision) {
return new _RecordModels.default.RecordsUpdateItem().setID(id).setRecord(recordData).setRevision(revision || 0);
}
/**
* create record Item With UpdateKey, use to update multi Record
* @param {*} updateKey
* @param {*} recordData
* @param {*} revision
* @return {RecordsUpdateItem}
*/
createRecordItemWithUpdateKey(updateKey, recordData, revision) {
return new _RecordModels.default.RecordsUpdateItem().setUpdateKey(updateKey.field, updateKey.value).setRecord(recordData).setRevision(revision || 0);
}
/**
* Update multi records
* @param {Object} params
* @param {Number} params.app
* @param {Array<RecordUpdateItem>} params.records
* @return {Promise} Promise
*/
updateRecords({
app,
records
} = {}) {
const updateRecordsRequest = new _RecordModels.default.UpdateRecordsRequest(app, records);
return this.sendRequest('PUT', 'records', updateRecordsRequest);
}
/**
* Delete multi records
* @param {Object} params
* @param {Number} params.app
* @param {Array<Number>} params.ids
* @return {Promise} Promise
*/
deleteRecords({
app,
ids
}) {
const deleteRecordsRequest = new _RecordModels.default.DeleteRecordsRequest(app);
deleteRecordsRequest.setIDs(ids);
return this.sendRequest('DELETE', 'records', deleteRecordsRequest);
}
/**
* Delete records at the specific revision
* @param {Object} params
* @param {Number} params.app
* @param {Object} params.idsWithRevision
* @return {Promise}
*/
deleteRecordsWithRevision({
app,
idsWithRevision
} = {}) {
const deleteRecordsRequest = new _RecordModels.default.DeleteRecordsRequest(app);
deleteRecordsRequest.setIDsWithRevision(idsWithRevision);
return this.sendRequest('DELETE', 'records', deleteRecordsRequest);
}
deleteBulkRecord(app, ids) {
const bulkRequest = new _BulkRequest.default({
connection: this.connection
});
const length = ids.length;
const loopTimes = Math.ceil(length / LIMIT_DELETE_RECORD);
for (let index = 0; index < loopTimes; index++) {
const begin = index * LIMIT_DELETE_RECORD;
const end = length - begin < LIMIT_DELETE_RECORD ? length : begin + LIMIT_DELETE_RECORD;
const idsPerRequest = ids.slice(begin, end);
bulkRequest.deleteRecords({
app: app,
ids: idsPerRequest
});
}
return bulkRequest.execute();
}
deleteAllRecords(app, ids, offset = 0, results = []) {
const numIdsPerBulk = NUM_BULK_REQUEST * LIMIT_DELETE_RECORD;
let begin = offset || 0;
const length = ids.length || 0;
const end = length - begin < LIMIT_DELETE_RECORD ? length : begin + numIdsPerBulk;
const idsPerBulk = ids.slice(begin, end);
let allResults = results || [];
return this.deleteBulkRecord(app, idsPerBulk).then(response => {
allResults = allResults.concat(response.results);
begin += numIdsPerBulk;
if (ids.length <= begin) {
return allResults;
}
return this.deleteAllRecords(app, ids, begin, allResults);
}).catch(errors => {
if (errors.length <= NUM_BULK_REQUEST) {
errors = allResults.concat(errors);
}
throw errors;
});
}
/**
* deleteAllRecordsByQuery for use with update all records
* @param {Object} params
* @param {Number} params.app
* @param {String} params.query
* @return {}
**/
deleteAllRecordsByQuery({
app,
query
} = {}) {
return this._validateRequiredArgs({
app
}).then(() => {
return this.getAllRecordsByQuery({
app,
query
});
}).then(resp => {
const ids = [];
const records = resp.records;
if (!records || !records.length) {
return {};
}
for (let i = 0; i < records.length; i++) {
ids.push(records[i].$id.value);
}
return this.deleteAllRecords(app, ids).then(response => {
return {
results: response
};
});
}).catch(errors => {
const errorsResponse = {
results: Array.isArray(errors) ? errors : [errors]
};
throw errorsResponse;
});
}
/**
* Update assignees of the specific record
* @param {Object} params
* @param {Number} params.app
* @param {Number} params.id
* @param {Array<String>} params.assignees
* @param {Number} params.revision
* @return {Promise}
*/
updateRecordAssignees({
app,
id,
assignees,
revision
} = {}) {
const updateRecordRequest = new _RecordModels.default.UpdateRecordAssigneesRequest(app, id, assignees, revision);
return this.sendRequest('PUT', 'RECORD_ASSIGNEES', updateRecordRequest);
}
/**
* Update status of the specific record
* @param {Object} params
* @param {Number} params.app
* @param {Number} params.id
* @param {String} params.action
* @param {String} params.assignee
* @param {Number} params.revision
* @return {Promise}
*/
updateRecordStatus({
app,
id,
action,
assignee,
revision
} = {}) {
const updateRecordRequest = new _RecordModels.default.UpdateRecordStatusRequest(app, id, action, assignee, revision);
return this.sendRequest('PUT', 'RECORD_STATUS', updateRecordRequest);
}
/**
* Update status of the multi records
* @param {Object} params
* @param {Number} params.app
* @param {Array <{RecordStatusUpdate}>} records
* @return {Promise}
*/
updateRecordsStatus({
app,
records
} = {}) {
const updateRecordsRequest = new _RecordModels.default.UpdateRecordsRequest(app, records);
return this.sendRequest('PUT', 'RECORDS_STATUS', updateRecordsRequest);
}
updateBulkRecord(app, records) {
const bulkRequest = new _BulkRequest.default({
connection: this.connection
});
const length = records.length;
const loopTimes = Math.ceil(length / LIMIT_UPDATE_RECORD);
for (let index = 0; index < loopTimes; index++) {
const begin = index * LIMIT_UPDATE_RECORD;
const end = length - begin < LIMIT_UPDATE_RECORD ? length : begin + LIMIT_UPDATE_RECORD;
const recordsPerRequest = records.slice(begin, end);
bulkRequest.updateRecords({
app: app,
records: recordsPerRequest
});
}
return bulkRequest.execute();
}
/**
* updateAllRecords for use with update all records
* @param {Object} params
* @param {Number} params.app
* @param {Object} params.records
* @return {UpdateRecordsResponse}
**/
updateAllRecordsRecursive(app, records, offset, results) {
const numRecordsPerBulk = NUM_BULK_REQUEST * LIMIT_UPDATE_RECORD;
let begin = offset || 0;
const validRecord = Array.isArray(records) ? records : [];
const length = validRecord.length;
const end = length - begin < LIMIT_UPDATE_RECORD ? length : begin + numRecordsPerBulk;
const recordsPerBulk = validRecord.slice(begin, end);
let allResults = results || [];
return this.updateBulkRecord(app, recordsPerBulk).then(response => {
allResults = allResults.concat(response.results);
begin += numRecordsPerBulk;
if (length <= begin) {
return allResults;
}
return this.updateAllRecordsRecursive(app, validRecord, begin, allResults);
}).catch(err => {
let error = Array.isArray(err) ? err : [err];
if (err.length <= NUM_BULK_REQUEST) {
error = allResults.concat(error);
}
throw error;
});
}
updateAllRecords({
app,
records
} = {}) {
return this._validateRequiredArgs({
app,
records
}).then(() => {
return this.updateAllRecordsRecursive(app, records).then(rsp => {
return {
results: rsp
};
}).catch(err => {
const errorsResponse = {
results: err
};
throw errorsResponse;
});
});
}
/**
* Upsert record by update-key
* @param {Object} params
* @param {Number} params.app
* @param {Object} params.updateKey
* @param {Object} params.record
* @param {Number} params.revision
* @return {Promise}
*/
upsertRecord({
app,
updateKey,
record,
revision
} = {}) {
return this._validateRequiredArgs({
app,
updateKey,
record
}).then(() => {
const getRecordsParam = {
app: app,
query: `${updateKey.field} = "${updateKey.value}"`,
fields: [updateKey.field],
totalCount: false
};
return this.getRecords(getRecordsParam).then(resp => {
if (updateKey.value === '' || resp.records.length < 1) {
record[updateKey.field] = {
value: updateKey.value
};
return this.addRecord({
app,
record
});
} else if (resp.records.length === 1) {
return this.updateRecordByUpdateKey({
app,
updateKey,
record,
revision
});
}
throw new _KintoneAPIException.default(`${updateKey.field} is not unique field`);
});
});
}
/**
* Upsert records by update-key
* @param {Object} params
* @param {Number} params.app
* @param {Object} params.recordsWithUpdatekey
* @return {Promise}
*/
upsertRecords({
app,
records
} = {}) {
const doesExistSameFieldValue = (allRecords, comparedRecord) => {
if (comparedRecord.updateKey.value === '') {
// updateKey.value is '' => post
return false;
}
for (let i = 0; i < allRecords.length; i++) {
if (allRecords[i][comparedRecord.updateKey.field].value === `${comparedRecord.updateKey.value}`) {
// exist => put
return true;
}
} // doesn't exist => post
return false;
};
const executeUpsertBulkRequest = (recordsForPost, recordsForPut) => {
let bulkRequest = new _BulkRequest.default({
connection: this.connection
});
bulkRequest = this.makeBulkReq(app, bulkRequest, recordsForPost, 'POST');
bulkRequest = this.makeBulkReq(app, bulkRequest, recordsForPut, 'PUT');
return bulkRequest.execute();
};
return this._validateRequiredArgs({
app,
records
}).then(() => {
const validRecords = Array.isArray(records) ? records : [];
if (validRecords.length > LIMIT_UPSERT_RECORD) {
throw new _KintoneAPIException.default(`upsertRecords can't handle over ${LIMIT_UPSERT_RECORD} records.`);
}
return this.getAllRecordsByQuery({
app
}).then(resp => {
const allRecords = resp.records;
const recordsForPut = [];
const recordsForPost = [];
for (let i = 0; i < validRecords.length; i++) {
if (doesExistSameFieldValue(allRecords, validRecords[i])) {
recordsForPut.push(validRecords[i]);
} else {
const record = validRecords[i].record;
record[validRecords[i].updateKey.field] = {
value: validRecords[i].updateKey.value
};
recordsForPost.push(record);
}
}
return executeUpsertBulkRequest(recordsForPost, recordsForPut);
}).catch(errors => {
const errorsArray = Array.isArray(errors) ? errors : [errors];
const errorsResponse = {
results: errorsArray
};
throw errorsResponse;
});
});
}
makeBulkReq(app, bulkRequest, records, method) {
let recordLimit = 0;
if (method === 'POST') {
recordLimit = LIMIT_POST_RECORD;
} else if (method === 'PUT') {
recordLimit = LIMIT_UPDATE_RECORD;
}
const length = records.length;
const loopTimes = Math.ceil(length / recordLimit);
for (let index = 0; index < loopTimes; index++) {
const begin = index * recordLimit;
const end = length - begin < recordLimit ? length : begin + recordLimit;
const recordsPerRequest = records.slice(begin, end);
if (method === 'POST') {
bulkRequest.addRecords({
app: app,
records: recordsPerRequest
});
} else if (method === 'PUT') {
bulkRequest.updateRecords({
app: app,
records: recordsPerRequest
});
}
}
return bulkRequest;
}
/**
* createRecordStatusItem for use with update multi record status
* @param {Object} params
* @param {Number} params.recordIDInput
* @param {String} params.actionNameInput
* @param {String} params.assigneeIDInput
* @param {String} params.revisionIDInput
* @return {RecordsUpdateStatusItem}
*/
createRecordStatusItem(recordIDInput, actionNameInput, assigneeIDInput, revisionIDInput) {
return new _RecordModels.default.RecordsUpdateStatusItem(recordIDInput, actionNameInput, assigneeIDInput, revisionIDInput);
}
/**
* Get comments of the specific record
* @param {Object} params
* @param {Number} params.app
* @param {Number} params.record
* @param {string} params.order {asc|desc}
* @param {Number} params.offset
* @param {Number} params.limit
* @return {Promise}
*/
getComments({
app,
record,
order,
offset,
limit
}) {
const getCommentsRequest = new _RecordModels.default.GetCommentsRequest(app, record, order, offset, limit);
return this.sendRequest('GET', 'RECORD_COMMENTS', getCommentsRequest);
}
/**
* Add new comment to the specific record
* @param {Object} params
* @param {Number} params.app
* @param {Number} params.record
* @param {CommentContent} comment
* @return {Promise}
*/
addComment({
app,
record,
comment
} = {}) {
const addCommentRequest = new _RecordModels.default.AddCommentRequest(app, record, comment);
return this.sendRequest('POST', 'RECORD_COMMENT', addCommentRequest);
}
/**
* Delete a comment
* @param {Object} params
* @param {Number} params.app
* @param {Number} params.record
* @param {Number} params.comment
* @return {Promise}
*/
deleteComment({
app,
record,
comment
} = {}) {
const deleteCommentRequest = new _RecordModels.default.DeleteCommentRequest(app, record, comment);
return this.sendRequest('DELETE', 'RECORD_COMMENT', deleteCommentRequest);
}
}
var _default = Record;
exports.default = _default;