Skip to content

Commit

Permalink
feat(rest-api-client): supports the upsert option (#3118)
Browse files Browse the repository at this point in the history
  • Loading branch information
chihiro-adachi authored Jan 8, 2025
1 parent 7684fb9 commit 3de0173
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 17 deletions.
24 changes: 14 additions & 10 deletions packages/rest-api-client/docs/record.md
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ If you'd like to update over 100 records, please consider using [updateAllRecord
| Name | Type | Required | Description |
| ------------------------- | :--------------: | :-------------------------: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| app | Number or String | Yes | The app ID. |
| upsert | Boolean | No | Whether to execute in UPSERT mode. If true is specified, it will be executed in UPSERT mode. |
| records | Array | Yes | Holds an array of objects that include `id`/`updateKey`, `revision` and `record` objects.<br />Up to 100 records can be specified. |
| records[].id | Number or String | Conditionally<br />Required | The record ID of the record to be updated. Required, if `updateKey` will not be specified. |
| records[].updateKey | Object | Conditionally<br />Required | The unique key of the record to be updated. Required, if `id` will not be specified. To specify this field, the field must have the "Prohibit duplicate values" option turned on. |
Expand All @@ -309,11 +310,12 @@ If you'd like to update over 100 records, please consider using [updateAllRecord

#### Returns

| Name | Type | Description |
| ------------------ | :----: | ------------------------------------------------------------------------------ |
| records | Array | Holds an array of objects that include `id` and `revision` of updated records. |
| records[].id | String | The ID of the record. |
| records[].revision | String | The revision number of the record. |
| Name | Type | Description |
| ------------------- | :----: | ---------------------------------------------------------------------------------------------------------------------------------- |
| records | Array | Holds an array of objects that include `id` and `revision` of updated records. |
| records[].id | String | The ID of the record. |
| records[].revision | String | The revision number of the record. |
| records[].operation | String | The operation performed on the record. This is output when UPSERT mode is enabled. `INSERT` : New registration / `UPDATE` : Update |

#### Reference

Expand All @@ -332,6 +334,7 @@ For more information, please see [an example of KintoneAllRecordsError](errorHan
| Name | Type | Required | Description |
| ------------------------- | :--------------: | :-------------------------: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| app | Number or String | Yes | The app ID. |
| upsert | boolean | No | Whether to execute in UPSERT mode. If true is specified, it will be executed in UPSERT mode. |
| records | Array | Yes | Holds an array of objects that include `id`/`updateKey`, `revision` and `record` objects.<br />Over 100 records can be specified. |
| records[].id | Number or String | Conditionally<br />Required | The record ID of the record to be updated. Required, if `updateKey` will not be specified. |
| records[].updateKey | Object | Conditionally<br />Required | The unique key of the record to be updated. Required, if `id` will not be specified. To specify this field, the field must have the "Prohibit duplicate values" option turned on. |
Expand All @@ -342,11 +345,12 @@ For more information, please see [an example of KintoneAllRecordsError](errorHan

#### Returns

| Name | Type | Description |
| ------------------ | :----: | ------------------------------------------------------------------------------ |
| records | Array | Holds an array of objects that include `id` and `revision` of updated records. |
| records[].id | String | The ID of the record. |
| records[].revision | String | The revision number of the record. |
| Name | Type | Description |
| ------------------- | :----: | ---------------------------------------------------------------------------------------------------------------------------------- |
| records | Array | Holds an array of objects that include `id` and `revision` of updated records. |
| records[].id | String | The ID of the record. |
| records[].revision | String | The revision number of the record. |
| records[].operation | String | The operation performed on the record. This is output when UPSERT mode is enabled. `INSERT` : New registration / `UPDATE` : Update |

### deleteRecords

Expand Down
30 changes: 23 additions & 7 deletions packages/rest-api-client/src/client/RecordClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type {
CommentID,
Comment,
Mention,
UpdateRecordsForResponse,
} from "./types";
import { BaseClient } from "./BaseClient";

Expand Down Expand Up @@ -167,6 +168,7 @@ export class RecordClient extends BaseClient {

public updateRecords(params: {
app: AppID;
upsert?: boolean;
records: Array<
| { id: RecordID; record?: RecordForParameter; revision?: Revision }
| {
Expand All @@ -175,7 +177,9 @@ export class RecordClient extends BaseClient {
revision?: Revision;
}
>;
}): Promise<{ records: Array<{ id: string; revision: string }> }> {
}): Promise<{
records: UpdateRecordsForResponse;
}> {
const path = this.buildPathWithGuestSpaceId({
endpointName: "records",
});
Expand Down Expand Up @@ -415,6 +419,7 @@ export class RecordClient extends BaseClient {

public async updateAllRecords(params: {
app: AppID;
upsert?: boolean;
records: Array<
| { id: RecordID; record?: RecordForParameter; revision?: Revision }
| {
Expand All @@ -423,13 +428,16 @@ export class RecordClient extends BaseClient {
revision?: Revision;
}
>;
}): Promise<{ records: Array<{ id: string; revision: string }> }> {
}): Promise<{
records: UpdateRecordsForResponse;
}> {
return this.updateAllRecordsRecursive(params, params.records.length, []);
}

private async updateAllRecordsRecursive(
params: {
app: AppID;
upsert?: boolean;
records: Array<
| { id: RecordID; record?: RecordForParameter; revision?: Revision }
| {
Expand All @@ -440,11 +448,13 @@ export class RecordClient extends BaseClient {
>;
},
numOfAllRecords: number,
results: Array<{ id: string; revision: string }>,
): Promise<{ records: Array<{ id: string; revision: string }> }> {
results: UpdateRecordsForResponse,
): Promise<{
records: UpdateRecordsForResponse;
}> {
const CHUNK_LENGTH =
this.bulkRequestClient.REQUESTS_LENGTH_LIMIT * UPDATE_RECORDS_LIMIT;
const { app, records } = params;
const { app, upsert, records } = params;
const recordsChunk = records.slice(0, CHUNK_LENGTH);
if (recordsChunk.length === 0) {
return { records: results };
Expand All @@ -453,6 +463,7 @@ export class RecordClient extends BaseClient {
try {
newResults = await this.updateAllRecordsWithBulkRequest({
app,
upsert,
records: recordsChunk,
});
} catch (e: any) {
Expand All @@ -467,6 +478,7 @@ export class RecordClient extends BaseClient {
return this.updateAllRecordsRecursive(
{
app,
upsert,
records: records.slice(CHUNK_LENGTH),
},
numOfAllRecords,
Expand All @@ -476,6 +488,7 @@ export class RecordClient extends BaseClient {

private async updateAllRecordsWithBulkRequest(params: {
app: AppID;
upsert?: boolean;
records: Array<
| { id: RecordID; record?: RecordForParameter; revision?: Revision }
| {
Expand All @@ -484,7 +497,7 @@ export class RecordClient extends BaseClient {
revision?: Revision;
}
>;
}): Promise<Array<{ id: string; revision: string }>> {
}): Promise<UpdateRecordsForResponse> {
const separatedRecords = this.separateArrayRecursive(
UPDATE_RECORDS_LIMIT,
[],
Expand All @@ -495,11 +508,14 @@ export class RecordClient extends BaseClient {
endpointName: "records" as const,
payload: {
app: params.app,
upsert: params.upsert,
records,
},
}));
const results = (await this.bulkRequestClient.send({ requests }))
.results as Array<{ records: Array<{ id: string; revision: string }> }>;
.results as Array<{
records: UpdateRecordsForResponse;
}>;
return results
.map((result) => result.records)
.reduce((acc, records) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,7 @@ describe("AllRecordsTest", () => {
describe("updateAllRecords", () => {
const params = {
app: APP_ID,
upsert: false,
records: Array.from({ length: 3000 }, (_, index) => index + 1).map(
(value) => ({
id: value,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ describe("RecordTest", () => {
describe("updateRecords", () => {
const params = {
app: APP_ID,
upsert: false,
records: [{ id: RECORD_ID, record, revision: 5 }],
};
beforeEach(async () => {
Expand Down
5 changes: 5 additions & 0 deletions packages/rest-api-client/src/client/types/record/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,8 @@ export type Comment = {
};

export type CommentID = string | number;

export type UpdateRecordsForResponse = Array<
| { id: string; revision: string }
| { id: string; operation: "INSERT" | "UPDATE"; revision: string }
>;

0 comments on commit 3de0173

Please sign in to comment.