diff --git a/components/formcarry/formcarry.app.mjs b/components/formcarry/formcarry.app.mjs index 28b0481b10085..ef2b929af8e18 100644 --- a/components/formcarry/formcarry.app.mjs +++ b/components/formcarry/formcarry.app.mjs @@ -1,11 +1,63 @@ +import { axios } from "@pipedream/platform"; + export default { type: "app", app: "formcarry", - propDefinitions: {}, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + _baseUrl() { + return "https://formcarry.com/api"; + }, + _headers() { + return { + api_key: `${this.$auth.api_key}`, + }; + }, + _makeRequest({ + $ = this, + path, + ...opts + }) { + return axios($, { + url: `${this._baseUrl()}${path}`, + headers: this._headers(), + ...opts, + }); + }, + listSubmissions({ + formId, ...opts + }) { + return this._makeRequest({ + path: `/form/${formId}/submissions`, + ...opts, + }); + }, + async *paginate({ + fn, + args = {}, + resourceKey, + max, + }) { + args = { + ...args, + params: { + ...args?.params, + limit: 50, + page: 1, + }, + }; + let nextPage, count = 0; + do { + const response = await fn(args); + const items = response[resourceKey]; + for (const item of items) { + yield item; + if (max && ++count >= max) { + return; + } + } + nextPage = response.pagination.next_page; + args.params.page = nextPage; + } while (nextPage); }, }, }; diff --git a/components/formcarry/package.json b/components/formcarry/package.json new file mode 100644 index 0000000000000..ae0f801777cf4 --- /dev/null +++ b/components/formcarry/package.json @@ -0,0 +1,18 @@ +{ + "name": "@pipedream/formcarry", + "version": "0.1.0", + "description": "Pipedream Formcarry Components", + "main": "formcarry.app.mjs", + "keywords": [ + "pipedream", + "formcarry" + ], + "homepage": "https://pipedream.com/apps/formcarry", + "author": "Pipedream (https://pipedream.com/)", + "publishConfig": { + "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^3.0.3" + } +} diff --git a/components/formcarry/sources/new-form-submission/new-form-submission.mjs b/components/formcarry/sources/new-form-submission/new-form-submission.mjs new file mode 100644 index 0000000000000..99e75453e5caa --- /dev/null +++ b/components/formcarry/sources/new-form-submission/new-form-submission.mjs @@ -0,0 +1,82 @@ +import formcarry from "../../formcarry.app.mjs"; +import { DEFAULT_POLLING_SOURCE_TIMER_INTERVAL } from "@pipedream/platform"; + +export default { + key: "formcarry-new-form-submission", + name: "New Form Submission", + description: "Emit new event when the specified form receives a new submission. [See the documentation](https://formcarry.com/docs/formcarry-api/submissions-api#cc7f3010897b4c938c8829db46b18656)", + version: "0.0.1", + type: "source", + dedupe: "unique", + props: { + formcarry, + db: "$.service.db", + timer: { + type: "$.interface.timer", + default: { + intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, + }, + }, + formId: { + type: "string", + label: "Form ID", + description: "The ID of the form to watch for new submissions", + }, + }, + hooks: { + async deploy() { + await this.processEvent(25); + }, + }, + methods: { + _getLastTs() { + return this.db.get("lastTs") || 0; + }, + _setLastTs(lastTs) { + this.db.set("lastTs", lastTs); + }, + generateMeta(submission) { + return { + id: submission._id, + summary: `New Form Submission ID: ${submission._id}`, + ts: Date.parse(submission.createdAt), + }; + }, + async processEvent(max) { + const lastTs = this._getLastTs(); + + const results = this.formcarry.paginate({ + fn: this.formcarry.listSubmissions, + args: { + formId: this.formId, + }, + resourceKey: "submissions", + max, + }); + + const submissions = []; + for await (const item of results) { + const ts = Date.parse(item.createdAt); + if (ts >= lastTs) { + submissions.push(item); + } else { + break; + } + } + + if (!submissions.length) { + return; + } + + this._setLastTs(Date.parse(submissions[0].createdAt)); + + submissions.forEach((submission) => { + const meta = this.generateMeta(submission); + this.$emit(submission, meta); + }); + }, + }, + async run() { + await this.processEvent(); + }, +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 897ec0ec5e7d9..c14b40f1bb76a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -3549,6 +3549,12 @@ importers: components/formcan: specifiers: {} + components/formcarry: + specifiers: + '@pipedream/platform': ^3.0.3 + dependencies: + '@pipedream/platform': 3.0.3 + components/formdesk: specifiers: {} @@ -12964,6 +12970,55 @@ packages: - aws-crt dev: false + /@aws-sdk/client-sso-oidc/3.600.0_tdq3komn4zwyd65w7klbptsu34: + resolution: {integrity: sha512-7+I8RWURGfzvChyNQSyj5/tKrqRbzRl7H+BnTOf/4Vsw1nFOi5ROhlhD4X/Y0QCTacxnaoNcIrqnY7uGGvVRzw==} + engines: {node: '>=16.0.0'} + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/client-sts': 3.600.0 + '@aws-sdk/core': 3.598.0 + '@aws-sdk/credential-provider-node': 3.600.0_f7n47caigsrjd2lr2szmwfuee4 + '@aws-sdk/middleware-host-header': 3.598.0 + '@aws-sdk/middleware-logger': 3.598.0 + '@aws-sdk/middleware-recursion-detection': 3.598.0 + '@aws-sdk/middleware-user-agent': 3.598.0 + '@aws-sdk/region-config-resolver': 3.598.0 + '@aws-sdk/types': 3.598.0 + '@aws-sdk/util-endpoints': 3.598.0 + '@aws-sdk/util-user-agent-browser': 3.598.0 + '@aws-sdk/util-user-agent-node': 3.598.0 + '@smithy/config-resolver': 3.0.3 + '@smithy/core': 2.2.3 + '@smithy/fetch-http-handler': 3.2.1 + '@smithy/hash-node': 3.0.2 + '@smithy/invalid-dependency': 3.0.2 + '@smithy/middleware-content-length': 3.0.2 + '@smithy/middleware-endpoint': 3.0.4 + '@smithy/middleware-retry': 3.0.6 + '@smithy/middleware-serde': 3.0.3 + '@smithy/middleware-stack': 3.0.3 + '@smithy/node-config-provider': 3.1.3 + '@smithy/node-http-handler': 3.1.2 + '@smithy/protocol-http': 4.0.3 + '@smithy/smithy-client': 3.1.6 + '@smithy/types': 3.3.0 + '@smithy/url-parser': 3.0.3 + '@smithy/util-base64': 3.0.0 + '@smithy/util-body-length-browser': 3.0.0 + '@smithy/util-body-length-node': 3.0.0 + '@smithy/util-defaults-mode-browser': 3.0.6 + '@smithy/util-defaults-mode-node': 3.0.6 + '@smithy/util-endpoints': 2.0.3 + '@smithy/util-middleware': 3.0.3 + '@smithy/util-retry': 3.0.2 + '@smithy/util-utf8': 3.0.0 + tslib: 2.6.3 + transitivePeerDependencies: + - '@aws-sdk/client-sts' + - aws-crt + dev: false + /@aws-sdk/client-sso/3.423.0: resolution: {integrity: sha512-znIufHkwhCIePgaYciIs3x/+BpzR57CZzbCKHR9+oOvGyufEPPpUT5bFLvbwTgfiVkTjuk6sG/ES3U5Bc+xtrA==} engines: {node: '>=14.0.0'} @@ -13199,7 +13254,7 @@ packages: dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/client-sso-oidc': 3.600.0 + '@aws-sdk/client-sso-oidc': 3.600.0_tdq3komn4zwyd65w7klbptsu34 '@aws-sdk/core': 3.598.0 '@aws-sdk/credential-provider-node': 3.600.0_f7n47caigsrjd2lr2szmwfuee4 '@aws-sdk/middleware-host-header': 3.598.0 @@ -13241,55 +13296,6 @@ packages: - aws-crt dev: false - /@aws-sdk/client-sts/3.600.0_dseaa2p5u2yk67qiepewcq3hkq: - resolution: {integrity: sha512-KQG97B7LvTtTiGmjlrG1LRAY8wUvCQzrmZVV5bjrJ/1oXAU7DITYwVbSJeX9NWg6hDuSk0VE3MFwIXS2SvfLIA==} - engines: {node: '>=16.0.0'} - dependencies: - '@aws-crypto/sha256-browser': 5.2.0 - '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/client-sso-oidc': 3.600.0 - '@aws-sdk/core': 3.598.0 - '@aws-sdk/credential-provider-node': 3.600.0_f7n47caigsrjd2lr2szmwfuee4 - '@aws-sdk/middleware-host-header': 3.598.0 - '@aws-sdk/middleware-logger': 3.598.0 - '@aws-sdk/middleware-recursion-detection': 3.598.0 - '@aws-sdk/middleware-user-agent': 3.598.0 - '@aws-sdk/region-config-resolver': 3.598.0 - '@aws-sdk/types': 3.598.0 - '@aws-sdk/util-endpoints': 3.598.0 - '@aws-sdk/util-user-agent-browser': 3.598.0 - '@aws-sdk/util-user-agent-node': 3.598.0 - '@smithy/config-resolver': 3.0.3 - '@smithy/core': 2.2.3 - '@smithy/fetch-http-handler': 3.2.1 - '@smithy/hash-node': 3.0.2 - '@smithy/invalid-dependency': 3.0.2 - '@smithy/middleware-content-length': 3.0.2 - '@smithy/middleware-endpoint': 3.0.4 - '@smithy/middleware-retry': 3.0.6 - '@smithy/middleware-serde': 3.0.3 - '@smithy/middleware-stack': 3.0.3 - '@smithy/node-config-provider': 3.1.3 - '@smithy/node-http-handler': 3.1.2 - '@smithy/protocol-http': 4.0.3 - '@smithy/smithy-client': 3.1.6 - '@smithy/types': 3.3.0 - '@smithy/url-parser': 3.0.3 - '@smithy/util-base64': 3.0.0 - '@smithy/util-body-length-browser': 3.0.0 - '@smithy/util-body-length-node': 3.0.0 - '@smithy/util-defaults-mode-browser': 3.0.6 - '@smithy/util-defaults-mode-node': 3.0.6 - '@smithy/util-endpoints': 2.0.3 - '@smithy/util-middleware': 3.0.3 - '@smithy/util-retry': 3.0.2 - '@smithy/util-utf8': 3.0.0 - tslib: 2.6.3 - transitivePeerDependencies: - - '@aws-sdk/client-sso-oidc' - - aws-crt - dev: false - /@aws-sdk/core/3.556.0: resolution: {integrity: sha512-vJaSaHw2kPQlo11j/Rzuz0gk1tEaKdz+2ser0f0qZ5vwFlANjt08m/frU17ctnVKC1s58bxpctO/1P894fHLrA==} engines: {node: '>=14.0.0'} @@ -17616,7 +17622,7 @@ packages: '@aws-sdk/client-sns': 3.423.0 '@aws-sdk/client-sqs': 3.423.0 '@aws-sdk/client-ssm': 3.423.0 - '@aws-sdk/client-sts': 3.600.0_dseaa2p5u2yk67qiepewcq3hkq + '@aws-sdk/client-sts': 3.600.0 '@aws-sdk/s3-request-presigner': 3.609.0 '@pipedream/helper_functions': 0.3.12 '@pipedream/platform': 1.6.6