@pipedream/kintone 0.0.3 → 0.1.0

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.
@@ -0,0 +1,62 @@
1
+ import { parseObject } from "../../common/utils.mjs";
2
+ import kintone from "../../kintone.app.mjs";
3
+
4
+ export default {
5
+ key: "kintone-add-comment",
6
+ name: "Add Comment",
7
+ description: "Adds a comment to a record in a Kintone App. [See the documentation](https://kintone.dev/en/docs/kintone/rest-api/records/add-comment/)",
8
+ version: "0.0.1",
9
+ type: "action",
10
+ annotations: {
11
+ destructiveHint: false,
12
+ openWorldHint: true,
13
+ readOnlyHint: false,
14
+ },
15
+ props: {
16
+ kintone,
17
+ appId: {
18
+ propDefinition: [
19
+ kintone,
20
+ "appId",
21
+ ],
22
+ },
23
+ recordId: {
24
+ propDefinition: [
25
+ kintone,
26
+ "recordId",
27
+ ({ appId }) => ({
28
+ appId,
29
+ }),
30
+ ],
31
+ },
32
+ commentText: {
33
+ type: "string",
34
+ label: "Comment Text",
35
+ description: "The comment text (max 65,535 characters)",
36
+ },
37
+ mentions: {
38
+ type: "object",
39
+ label: "Mentions",
40
+ description: "Optional array of mentions. Example: `[{\"code\": \"user_code\", \"type\": \"USER\"}]` (USER, GROUP, or ORGANIZATION)",
41
+ optional: true,
42
+ },
43
+ },
44
+ async run({ $ }) {
45
+ const response = await this.kintone.addComment({
46
+ $,
47
+ data: {
48
+ app: this.appId,
49
+ record: this.recordId,
50
+ comment: {
51
+ text: this.commentText,
52
+ ...(this.mentions && {
53
+ mentions: parseObject(this.mentions),
54
+ }),
55
+ },
56
+ },
57
+ });
58
+
59
+ $.export("$summary", `Successfully added comment with ID: ${response.id}`);
60
+ return response;
61
+ },
62
+ };
@@ -0,0 +1,47 @@
1
+ import { ConfigurationError } from "@pipedream/platform";
2
+ import { parseObject } from "../../common/utils.mjs";
3
+ import kintone from "../../kintone.app.mjs";
4
+
5
+ export default {
6
+ key: "kintone-create-record",
7
+ name: "Create Record",
8
+ description: "Adds a new record to a Kintone App. [See the documentation](https://kintone.dev/en/docs/kintone/rest-api/records/add-record/)",
9
+ version: "0.0.1",
10
+ type: "action",
11
+ annotations: {
12
+ destructiveHint: false,
13
+ openWorldHint: true,
14
+ readOnlyHint: false,
15
+ },
16
+ props: {
17
+ kintone,
18
+ appId: {
19
+ propDefinition: [
20
+ kintone,
21
+ "appId",
22
+ ],
23
+ },
24
+ record: {
25
+ propDefinition: [
26
+ kintone,
27
+ "record",
28
+ ],
29
+ },
30
+ },
31
+ async run({ $ }) {
32
+ try {
33
+ const response = await this.kintone.addRecord({
34
+ $,
35
+ data: {
36
+ app: this.appId,
37
+ record: parseObject(this.record),
38
+ },
39
+ });
40
+
41
+ $.export("$summary", `Successfully created record (ID: ${response.id})`);
42
+ return response;
43
+ } catch (error) {
44
+ throw new ConfigurationError(error.message);
45
+ }
46
+ },
47
+ };
@@ -0,0 +1,96 @@
1
+ import { ConfigurationError } from "@pipedream/platform";
2
+ import { parseObject } from "../../common/utils.mjs";
3
+ import kintone from "../../kintone.app.mjs";
4
+
5
+ export default {
6
+ key: "kintone-update-record",
7
+ name: "Update Record",
8
+ description: "Updates an existing record in a Kintone App. [See the documentation](https://kintone.dev/en/docs/kintone/rest-api/records/update-record/)",
9
+ version: "0.0.1",
10
+ type: "action",
11
+ annotations: {
12
+ destructiveHint: false,
13
+ openWorldHint: true,
14
+ readOnlyHint: false,
15
+ },
16
+ props: {
17
+ kintone,
18
+ appId: {
19
+ propDefinition: [
20
+ kintone,
21
+ "appId",
22
+ ],
23
+ },
24
+ recordId: {
25
+ propDefinition: [
26
+ kintone,
27
+ "recordId",
28
+ ({ appId }) => ({
29
+ appId,
30
+ }),
31
+ ],
32
+ description: "The Record ID of the record to update. Use this OR `Update Key`, not both",
33
+ optional: true,
34
+ },
35
+ updateKeyField: {
36
+ type: "string",
37
+ label: "Unique Key Field Code",
38
+ description: "The field code of the unique key (when using `Update Key` instead of Record ID). Must have 'Prohibit duplicate values' enabled",
39
+ optional: true,
40
+ },
41
+ updateKeyValue: {
42
+ type: "string",
43
+ label: "Unique Key Value",
44
+ description: "The value of the unique key to identify the record",
45
+ optional: true,
46
+ },
47
+ revision: {
48
+ type: "integer",
49
+ label: "Revision",
50
+ description: "The expected revision number. If the value does not match, an error will occur and the record will not be updated. If the value is not specified, the revision number will not be checked",
51
+ optional: true,
52
+ },
53
+ record: {
54
+ propDefinition: [
55
+ kintone,
56
+ "record",
57
+ ],
58
+ description: `Field codes and values are specified in this object.
59
+ \nFields not specified here will retain their current values.
60
+ \nFor more information on field types, refer to the following article: [Field Types](https://kintone.dev/en/docs/kintone/overview/field-types/).
61
+ \nExample: {"Text": {"value": "Sample"}, "Number": {"value": 1}}`,
62
+ },
63
+ },
64
+ async run({ $ }) {
65
+ if (!this.recordId && (!this.updateKeyField && !this.updateKeyValue)) {
66
+ throw new ConfigurationError("Either `Record ID` or both `Update Key Field` and `Update Key Value` must be provided");
67
+ }
68
+ if (this.recordId && this.updateKeyField) {
69
+ throw new ConfigurationError("Cannot specify both `Record ID` and `Update Key`");
70
+ }
71
+
72
+ let updateKey;
73
+ if (this.updateKeyField && this.updateKeyValue) {
74
+ updateKey = {
75
+ field: this.updateKeyField,
76
+ value: this.updateKeyValue,
77
+ };
78
+ }
79
+
80
+ const response = await this.kintone.updateRecord({
81
+ $,
82
+ data: {
83
+ app: this.appId,
84
+ id: this.recordId,
85
+ updateKey,
86
+ revision: this.revision === undefined
87
+ ? -1
88
+ : this.revision,
89
+ record: parseObject(this.record),
90
+ },
91
+ });
92
+
93
+ $.export("$summary", `Successfully updated record (revision: ${response.revision})`);
94
+ return response;
95
+ },
96
+ };
@@ -0,0 +1 @@
1
+ export const LIMIT = 100;
@@ -0,0 +1,25 @@
1
+ export const parseObject = (obj) => {
2
+ if (!obj) return null;
3
+
4
+ if (typeof obj === "string") {
5
+ try {
6
+ return JSON.parse(obj);
7
+ } catch (e) {
8
+ return obj;
9
+ }
10
+ }
11
+ if (Array.isArray(obj)) {
12
+ return obj.map((item) => parseObject(item));
13
+ }
14
+ if (typeof obj === "object") {
15
+ const newObj = {};
16
+ for (const [
17
+ key,
18
+ value,
19
+ ] of Object.entries(obj)) {
20
+ newObj[key] = parseObject(value);
21
+ }
22
+ return newObj;
23
+ }
24
+ return obj;
25
+ };
package/kintone.app.mjs CHANGED
@@ -1,11 +1,135 @@
1
+ import { axios } from "@pipedream/platform";
2
+ import { LIMIT } from "./common/constants.mjs";
3
+
1
4
  export default {
2
5
  type: "app",
3
6
  app: "kintone",
4
- propDefinitions: {},
7
+ propDefinitions: {
8
+ appId: {
9
+ type: "integer",
10
+ label: "App ID",
11
+ description: "The Kintone App ID",
12
+ async options({ page }) {
13
+ const { apps } = await this.getApps({
14
+ params: {
15
+ limit: LIMIT,
16
+ offset: page * LIMIT,
17
+ },
18
+ });
19
+ return apps.map((app) => ({
20
+ label: app.name,
21
+ value: parseInt(app.appId),
22
+ }));
23
+ },
24
+ },
25
+ recordId: {
26
+ type: "string",
27
+ label: "Record ID",
28
+ description: "The ID of the record",
29
+ async options({
30
+ appId, page,
31
+ }) {
32
+ const { records } = await this.getRecords({
33
+ params: {
34
+ app: appId,
35
+ query: `order by $id desc limit ${LIMIT} offset ${page * LIMIT}`,
36
+ },
37
+ });
38
+
39
+ return records.map((record) => record.$id.value);
40
+ },
41
+ },
42
+ record: {
43
+ type: "object",
44
+ label: "Record",
45
+ description: `Field codes and values are specified in this object.
46
+ \nThe values that can be specified vary depending on the type of field.
47
+ \nIf ignored, the record will be added with default field values.
48
+ \nIf field codes that don't exist are specified, these will be ignored.
49
+ \nFor more information on field types, refer to the following article: [Field Types](https://kintone.dev/en/docs/kintone/overview/field-types/).
50
+ \nExample: {"Text": {"value": "Sample"}, "Number": {"value": 1}}`,
51
+ },
52
+ },
5
53
  methods: {
6
- // this.$auth contains connected account data
7
- authKeys() {
8
- console.log(Object.keys(this.$auth));
54
+ _getBaseUrl() {
55
+ return `https://${this.$auth.subdomain}.kintone.com/k/v1`;
56
+ },
57
+ _getHeaders() {
58
+ return {
59
+ "Authorization": `Bearer ${this.$auth.oauth_access_token}`,
60
+ };
61
+ },
62
+ _makeRequest({
63
+ $ = this, path, ...opts
64
+ }) {
65
+ return axios($, {
66
+ url: `${this._getBaseUrl()}${path}`,
67
+ headers: this._getHeaders(),
68
+ ...opts,
69
+ });
70
+ },
71
+ getApps(opts = {}) {
72
+ return this._makeRequest({
73
+ path: "/apps.json",
74
+ ...opts,
75
+ });
76
+ },
77
+ addRecord(opts = {}) {
78
+ return this._makeRequest({
79
+ path: "/record.json",
80
+ method: "POST",
81
+ ...opts,
82
+ });
83
+ },
84
+ updateRecord(opts = {}) {
85
+ return this._makeRequest({
86
+ path: "/record.json",
87
+ method: "PUT",
88
+ ...opts,
89
+ });
90
+ },
91
+ addComment(opts = {}) {
92
+ return this._makeRequest({
93
+ path: "/record/comment.json",
94
+ method: "POST",
95
+ ...opts,
96
+ });
97
+ },
98
+ getRecords(opts = {}) {
99
+ return this._makeRequest({
100
+ path: "/records.json",
101
+ ...opts,
102
+ });
103
+ },
104
+ async *paginate({
105
+ fn, params = {}, query = "", maxResults = null, ...opts
106
+ }) {
107
+ let hasMore = false;
108
+ let count = 0;
109
+ let page = 0;
110
+ let offset = 0;
111
+
112
+ do {
113
+ offset = page * LIMIT;
114
+ if (offset >= 10100) return;
115
+ params.query = `${query} limit ${LIMIT} offset ${offset}`;
116
+ page++;
117
+
118
+ const { records } = await fn({
119
+ params,
120
+ ...opts,
121
+ });
122
+ for (const d of records) {
123
+ yield d;
124
+
125
+ if (maxResults && ++count === maxResults) {
126
+ return count;
127
+ }
128
+ }
129
+
130
+ hasMore = records.length === LIMIT;
131
+
132
+ } while (hasMore);
9
133
  },
10
134
  },
11
135
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pipedream/kintone",
3
- "version": "0.0.3",
3
+ "version": "0.1.0",
4
4
  "description": "Pipedream Kintone Components",
5
5
  "main": "kintone.app.mjs",
6
6
  "keywords": [
@@ -11,5 +11,8 @@
11
11
  "author": "Pipedream <support@pipedream.com> (https://pipedream.com/)",
12
12
  "publishConfig": {
13
13
  "access": "public"
14
+ },
15
+ "dependencies": {
16
+ "@pipedream/platform": "^3.2.5"
14
17
  }
15
18
  }
@@ -0,0 +1,76 @@
1
+ import { DEFAULT_POLLING_SOURCE_TIMER_INTERVAL } from "@pipedream/platform";
2
+ import kintone from "../../kintone.app.mjs";
3
+ import sampleEmit from "./test-event.mjs";
4
+
5
+ export default {
6
+ key: "kintone-new-record",
7
+ name: "New Record",
8
+ description: "Emit new event when a new record is added to a Kintone App. [See the documentation](https://kintone.dev/en/docs/kintone/rest-api/records/get-records/)",
9
+ version: "0.0.1",
10
+ type: "source",
11
+ dedupe: "unique",
12
+ props: {
13
+ kintone,
14
+ db: "$.service.db",
15
+ timer: {
16
+ type: "$.interface.timer",
17
+ default: {
18
+ intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL,
19
+ },
20
+ },
21
+ appId: {
22
+ propDefinition: [
23
+ kintone,
24
+ "appId",
25
+ ],
26
+ },
27
+ },
28
+ methods: {
29
+ _getLastDate() {
30
+ return this.db.get("lastDate") || "1970-01-01T00:00:00Z";
31
+ },
32
+ _setLastDate(lastDate) {
33
+ this.db.set("lastDate", lastDate);
34
+ },
35
+ async emitEvent(maxResults = false) {
36
+ const lastDate = this._getLastDate();
37
+
38
+ const query = `Created_datetime > "${lastDate}" order by Created_datetime desc`;
39
+
40
+ const response = this.kintone.paginate({
41
+ fn: this.kintone.getRecords,
42
+ maxResults,
43
+ query,
44
+ params: {
45
+ app: this.appId,
46
+ },
47
+ });
48
+
49
+ let responseArray = [];
50
+ for await (const item of response) {
51
+ responseArray.push(item);
52
+ }
53
+
54
+ if (responseArray.length) {
55
+ this._setLastDate(responseArray[0].Created_datetime.value);
56
+ }
57
+
58
+ for (const item of responseArray.reverse()) {
59
+ this.$emit(item, {
60
+ id: item.$id.value,
61
+ summary: `New record with ID: ${item.$id.value}`,
62
+ ts: Date.parse(item.Created_datetime.value),
63
+ });
64
+ }
65
+ },
66
+ },
67
+ hooks: {
68
+ async deploy() {
69
+ await this.emitEvent(25);
70
+ },
71
+ },
72
+ async run() {
73
+ await this.emitEvent();
74
+ },
75
+ sampleEmit,
76
+ };
@@ -0,0 +1,64 @@
1
+ export default {
2
+ "Last_user": {
3
+ "type":"MODIFIER",
4
+ "value": {
5
+ "code":"test@example.com",
6
+ "name":"test@example.com"
7
+ }
8
+ },
9
+ "Rich_text": {
10
+ "type":"RICH_TEXT",
11
+ "value":""
12
+ },
13
+ "Attachment": {
14
+ "type":"FILE",
15
+ "value":[]
16
+ },
17
+ "$revision": {
18
+ "type":"__REVISION__",
19
+ "value":"4"
20
+ },
21
+ "Single_line_text": {
22
+ "type":"SINGLE_LINE_TEXT",
23
+ "value":"value example"
24
+ },
25
+ "Date": {
26
+ "type":"DATE",
27
+ "value":"2026-02-19"
28
+ },
29
+ "Updated_datetime": {
30
+ "type":"UPDATED_TIME",
31
+ "value":"2026-02-19T20:21:00Z"
32
+ },
33
+ "Created_datetime": {
34
+ "type":"CREATED_TIME",
35
+ "value":"2026-02-19T19:53:00Z"
36
+ },
37
+ "Date_and_time": {
38
+ "type":"DATETIME",
39
+ "value":""
40
+ },
41
+ "Record_number": {
42
+ "type":"RECORD_NUMBER",
43
+ "value":"2"
44
+ },
45
+ "Author": {
46
+ "type":"CREATOR",
47
+ "value": {
48
+ "code":"test@example.com",
49
+ "name":"test@example.com"
50
+ }
51
+ },
52
+ "Drop_down": {
53
+ "type":"DROP_DOWN",
54
+ "value":"Not started"
55
+ },
56
+ "User_selection": {
57
+ "type":"USER_SELECT",
58
+ "value":[]
59
+ },
60
+ "$id": {
61
+ "type":"__ID__",
62
+ "value":"2"
63
+ }
64
+ };