diff --git a/components/copper/actions/associate-to-project/associate-to-project.mjs b/components/copper/actions/associate-to-project/associate-to-project.mjs new file mode 100644 index 0000000000000..1f9417ffb322b --- /dev/null +++ b/components/copper/actions/associate-to-project/associate-to-project.mjs @@ -0,0 +1,53 @@ +import copper from "../../copper.app.mjs"; + +export default { + key: "copper-associate-to-project", + name: "Associate to Project", + description: "Relates an existing project with an existing CRM object. [See the documentation](https://developer.copper.com/related-items/relate-an-existing-record-to-an-entity.html)", + version: "0.0.1", + type: "action", + props: { + copper, + projectId: { + propDefinition: [ + copper, + "objectId", + () => ({ + objectType: "projects", + }), + ], + label: "Project ID", + description: "The ID of the project you wish to relate", + }, + objectType: { + propDefinition: [ + copper, + "objectType", + ], + }, + objectId: { + propDefinition: [ + copper, + "objectId", + (c) => ({ + objectType: c.objectType, + }), + ], + }, + }, + async run({ $ }) { + const response = await this.copper.relateProjectToCrmObject({ + $, + objectType: this.objectType, + objectId: this.objectId, + data: { + resource: { + id: this.projectId, + type: "project", + }, + }, + }); + $.export("$summary", `Successfully associated Project ID ${this.projectId} with CRM ID ${this.objectId}`); + return response; + }, +}; diff --git a/components/copper/actions/create-update-person/create-update-person.mjs b/components/copper/actions/create-update-person/create-update-person.mjs new file mode 100644 index 0000000000000..b57c0c21ada11 --- /dev/null +++ b/components/copper/actions/create-update-person/create-update-person.mjs @@ -0,0 +1,126 @@ +import copper from "../../copper.app.mjs"; +import { ConfigurationError } from "@pipedream/platform"; + +export default { + key: "copper-create-update-person", + name: "Create or Update Person", + description: "Creates a new person or updates an existing one based on email address. [See the documentation](https://developer.copper.com/people/create-a-new-person.html)", + version: "0.0.1", + type: "action", + props: { + copper, + email: { + type: "string", + label: "Email", + description: "Email address of the person. If email already exists, the person will be updated", + }, + name: { + type: "string", + label: "Name", + description: "Name of the contact. Required if creating a new person.", + optional: true, + }, + streetAddress: { + type: "string", + label: "Street Address", + description: "Street address of the person", + optional: true, + }, + city: { + type: "string", + label: "City", + description: "City address of the person", + optional: true, + }, + state: { + type: "string", + label: "State", + description: "State address of the person", + optional: true, + }, + postalCode: { + type: "string", + label: "Postal Code", + description: "Postal code of the person", + optional: true, + }, + country: { + type: "string", + label: "Country", + description: "Country of the person", + optional: true, + }, + phone: { + type: "string", + label: "Phone", + description: "Phone number of the person", + optional: true, + }, + }, + async run({ $ }) { + let response; + const hasAddress = this.streetAddress + || this.city + || this.state + || this.postalCode + || this.country; + const data = { + emails: [ + { + email: this.email, + category: "work", + }, + ], + name: this.name, + address: hasAddress && { + street: this.streetAddress, + city: this.city, + state: this.state, + postal_code: this.postalCode, + country: this.country, + }, + phone_numbers: this.phone && [ + { + number: this.phone, + category: "work", + }, + ], + }; + + // search for the person + const person = await this.copper.listObjects({ + $, + objectType: "people", + data: { + emails: [ + this.email, + ], + }, + }); + + if (!person?.length && !this.name) { + throw new ConfigurationError(`Person with email ${this.email} not found. Name is required for creating a new person.`); + } + + // create person if not found + if (!person?.length) { + response = await this.copper.createPerson({ + $, + data, + }); + } + // update person if found + else { + response = await this.copper.updatePerson({ + $, + personId: person[0].id, + data, + }); + } + + $.export("$summary", `Successfully ${person?.length + ? "updated" + : "created"} person with ID: ${response.id}`); + return response; + }, +}; diff --git a/components/copper/actions/create-update-project/create-update-project.mjs b/components/copper/actions/create-update-project/create-update-project.mjs new file mode 100644 index 0000000000000..4c2c75d0da895 --- /dev/null +++ b/components/copper/actions/create-update-project/create-update-project.mjs @@ -0,0 +1,86 @@ +import copper from "../../copper.app.mjs"; + +export default { + key: "copper-create-update-project", + name: "Create or Update Project", + description: "Creates a new project or updates an existing one based on the project name. [See the documentation](https://developer.copper.com/projects/create-a-new-project.html)", + version: "0.0.1", + type: "action", + props: { + copper, + name: { + type: "string", + label: "Name", + description: "Name of the project. If a project with the specified name already exists, it will be updated", + }, + details: { + type: "string", + label: "Details", + description: "Description of the Project", + optional: true, + }, + assigneeId: { + propDefinition: [ + copper, + "objectId", + () => ({ + objectType: "users", + }), + ], + label: "Assignee ID", + description: "The ID of the User that will be the owner of the Project", + optional: true, + }, + status: { + propDefinition: [ + copper, + "status", + ], + }, + tags: { + propDefinition: [ + copper, + "tags", + ], + }, + }, + async run({ $ }) { + let response; + const data = { + name: this.name, + assignee_id: this.assigneeId, + status: this.status, + tags: this.tags, + }; + + // search for the project + const project = await this.copper.listObjects({ + $, + objectType: "projects", + data: { + name: this.name, + }, + }); + + // create project if not found + if (!project?.length) { + response = await this.copper.createProject({ + $, + data, + }); + } + // update project if found + else { + response = await this.copper.updateProject({ + $, + projectId: project[0].id, + data, + }); + } + + $.export("$summary", `Successfully ${project?.length + ? "updated" + : "created"} project with ID: ${response.id}`); + return response; + }, +}; diff --git a/components/copper/actions/get-object/get-object.mjs b/components/copper/actions/get-object/get-object.mjs new file mode 100644 index 0000000000000..bc709b8d39b74 --- /dev/null +++ b/components/copper/actions/get-object/get-object.mjs @@ -0,0 +1,36 @@ +import copper from "../../copper.app.mjs"; + +export default { + key: "copper-get-object", + name: "Get Object", + description: "Retrieves an existing CRM object. [See the documentation](https://developer.copper.com/account-and-users/fetch-user-by-id.html)", + version: "0.0.1", + type: "action", + props: { + copper, + objectType: { + propDefinition: [ + copper, + "objectType", + ], + }, + objectId: { + propDefinition: [ + copper, + "objectId", + (c) => ({ + objectType: c.objectType, + }), + ], + }, + }, + async run({ $ }) { + const response = await this.copper.getObject({ + objectType: this.objectType, + objectId: this.objectId, + $, + }); + $.export("$summary", `Successfully retrieved CRM object with ID ${this.objectId}`); + return response; + }, +}; diff --git a/components/copper/copper.app.mjs b/components/copper/copper.app.mjs index 844ee8264d5f5..58bcaf83985bb 100644 --- a/components/copper/copper.app.mjs +++ b/components/copper/copper.app.mjs @@ -1,11 +1,184 @@ +import { axios } from "@pipedream/platform"; + export default { type: "app", app: "copper", - propDefinitions: {}, + propDefinitions: { + objectId: { + type: "string", + label: "Object ID", + description: "The ID of the CRM object", + async options({ + objectType, page, + }) { + const objects = await this.listObjects({ + objectType, + params: { + page_number: page + 1, + }, + }); + return objects?.map(({ + id: value, name: label, + }) => ({ + value, + label, + })) || []; + }, + }, + tags: { + type: "string[]", + label: "Tags", + description: "An array of the tags associated with the Project", + optional: true, + async options() { + const tags = await this.listTags(); + return tags?.map(({ name }) => name) || []; + }, + }, + status: { + type: "string", + label: "Status", + description: "The status of the Project", + optional: true, + options: [ + "Open", + "Completed", + ], + }, + objectType: { + type: "string", + label: "Object Type", + description: "The type of CRM object", + async options() { + return [ + { + label: "Lead", + value: "leads", + }, + { + label: "Person", + value: "people", + }, + { + label: "Company", + value: "companies", + }, + { + label: "Opportunity", + value: "opportunities", + }, + { + label: "Project", + value: "projects", + }, + { + label: "Task", + value: "tasks", + }, + ]; + }, + }, + }, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + _baseUrl() { + return "https://api.copper.com/developer_api/v1"; + }, + _makeRequest(opts = {}) { + const { + $ = this, + path, + ...otherOpts + } = opts; + return axios($, { + ...otherOpts, + url: `${this._baseUrl()}${path}`, + headers: { + "X-PW-AccessToken": this.$auth.api_key, + "X-PW-Application": "developer_api", + "X-PW-UserEmail": this.$auth.email, + "Content-Type": "application/json", + }, + }); + }, + createWebhook(opts = {}) { + return this._makeRequest({ + method: "POST", + path: "/webhooks", + ...opts, + }); + }, + deleteWebhook({ + hookId, ...opts + }) { + return this._makeRequest({ + method: "DELETE", + path: `/webhooks/${hookId}`, + ...opts, + }); + }, + listObjects({ + objectType, ...opts + }) { + return this._makeRequest({ + method: "POST", + path: `/${objectType}/search`, + ...opts, + }); + }, + listTags(opts = {}) { + return this._makeRequest({ + path: "/tags", + ...opts, + }); + }, + getObject({ + objectType, objectId, ...opts + }) { + return this._makeRequest({ + path: `/${objectType}/${objectId}`, + ...opts, + }); + }, + createPerson(opts = {}) { + return this._makeRequest({ + method: "POST", + path: "/people", + ...opts, + }); + }, + updatePerson({ + personId, ...opts + }) { + return this._makeRequest({ + method: "PUT", + path: `/people/${personId}`, + ...opts, + }); + }, + createProject(opts = {}) { + return this._makeRequest({ + method: "POST", + path: "/projects", + ...opts, + }); + }, + updateProject({ + projectId, ...opts + }) { + return this._makeRequest({ + method: "PUT", + path: `/projects/${projectId}`, + ...opts, + }); + }, + relateProjectToCrmObject({ + objectType, objectId, ...opts + }) { + return this._makeRequest({ + method: "POST", + path: `/${objectType}/${objectId}/related`, + ...opts, + }); }, }, }; diff --git a/components/copper/package.json b/components/copper/package.json new file mode 100644 index 0000000000000..b0eb582b196cb --- /dev/null +++ b/components/copper/package.json @@ -0,0 +1,18 @@ +{ + "name": "@pipedream/copper", + "version": "0.0.1", + "description": "Pipedream Copper Components", + "main": "copper.app.mjs", + "keywords": [ + "pipedream", + "copper" + ], + "homepage": "https://pipedream.com/apps/copper", + "author": "Pipedream (https://pipedream.com/)", + "publishConfig": { + "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^3.0.3" + } +} diff --git a/components/copper/sources/common/base.mjs b/components/copper/sources/common/base.mjs new file mode 100644 index 0000000000000..6a69e9bac4873 --- /dev/null +++ b/components/copper/sources/common/base.mjs @@ -0,0 +1,58 @@ +import copper from "../../copper.app.mjs"; + +export default { + props: { + copper, + db: "$.service.db", + http: "$.interface.http", + }, + hooks: { + async activate() { + const { id } = await this.copper.createWebhook({ + data: { + target: this.http.endpoint, + type: this.getObjectType(), + event: this.getEventType(), + }, + }); + this._setHookId(id); + }, + async deactivate() { + const hookId = this._getHookId(); + if (hookId) { + await this.copper.deleteWebhook({ + hookId, + }); + } + }, + }, + methods: { + _getHookId() { + return this.db.get("hookId"); + }, + _setHookId(hookId) { + this.db.set("hookId", hookId); + }, + getEventType() { + return "new"; + }, + generateMeta(item) { + return { + id: item.ids[0], + summary: this.getSummary(item), + ts: Date.parse(item.timestamp), + }; + }, + getObjectType() { + throw new Error("getObjectType is not implemented"); + }, + getSummary() { + throw new Error("getSummary is not implemented"); + }, + }, + async run(event) { + const { body } = event; + const meta = this.generateMeta(body); + this.$emit(body, meta); + }, +}; diff --git a/components/copper/sources/new-lead-instant/new-lead-instant.mjs b/components/copper/sources/new-lead-instant/new-lead-instant.mjs new file mode 100644 index 0000000000000..9b3a3aee48cff --- /dev/null +++ b/components/copper/sources/new-lead-instant/new-lead-instant.mjs @@ -0,0 +1,22 @@ +import common from "../common/base.mjs"; +import sampleEmit from "./test-event.mjs"; + +export default { + ...common, + key: "copper-new-lead-instant", + name: "New Lead (Instant)", + description: "Emit new event when a new lead is created in Copper", + version: "0.0.1", + type: "source", + dedupe: "unique", + methods: { + ...common.methods, + getObjectType() { + return "lead"; + }, + getSummary(item) { + return `New lead created with ID ${item.ids[0]}`; + }, + }, + sampleEmit, +}; diff --git a/components/copper/sources/new-lead-instant/test-event.mjs b/components/copper/sources/new-lead-instant/test-event.mjs new file mode 100644 index 0000000000000..ea50c83f1924f --- /dev/null +++ b/components/copper/sources/new-lead-instant/test-event.mjs @@ -0,0 +1,10 @@ +export default { + "subscription_id": 395049, + "event": "new", + "type": "lead", + "ids": [ + 89011972 + ], + "updated_attributes": {}, + "timestamp": "2024-10-14T16:15:54.893Z" +} \ No newline at end of file diff --git a/components/copper/sources/new-opportunity-instant/new-opportunity-instant.mjs b/components/copper/sources/new-opportunity-instant/new-opportunity-instant.mjs new file mode 100644 index 0000000000000..f1a78821c4dfa --- /dev/null +++ b/components/copper/sources/new-opportunity-instant/new-opportunity-instant.mjs @@ -0,0 +1,22 @@ +import common from "../common/base.mjs"; +import sampleEmit from "./test-event.mjs"; + +export default { + ...common, + key: "copper-new-opportunity-instant", + name: "New Opportunity (Instant)", + description: "Emit new event when a new opportunity is created in Copper", + version: "0.0.1", + type: "source", + dedupe: "unique", + methods: { + ...common.methods, + getObjectType() { + return "opportunity"; + }, + getSummary(item) { + return `New opportunity created with ID ${item.ids[0]}`; + }, + }, + sampleEmit, +}; diff --git a/components/copper/sources/new-opportunity-instant/test-event.mjs b/components/copper/sources/new-opportunity-instant/test-event.mjs new file mode 100644 index 0000000000000..43a76ff5c6c4f --- /dev/null +++ b/components/copper/sources/new-opportunity-instant/test-event.mjs @@ -0,0 +1,10 @@ +export default { + "subscription_id": 395050, + "event": "new", + "type": "opportunity", + "ids": [ + 32978697 + ], + "updated_attributes": {}, + "timestamp": "2024-10-14T16:22:15.070Z" +} \ No newline at end of file diff --git a/components/copper/sources/new-person-instant/new-person-instant.mjs b/components/copper/sources/new-person-instant/new-person-instant.mjs new file mode 100644 index 0000000000000..0bd763c87bfab --- /dev/null +++ b/components/copper/sources/new-person-instant/new-person-instant.mjs @@ -0,0 +1,22 @@ +import common from "../common/base.mjs"; +import sampleEmit from "./test-event.mjs"; + +export default { + ...common, + key: "copper-new-person-instant", + name: "New Person (Instant)", + description: "Emit new event when a person object is newly created in Copper", + version: "0.0.1", + type: "source", + dedupe: "unique", + methods: { + ...common.methods, + getObjectType() { + return "person"; + }, + getSummary(item) { + return `New person created with ID ${item.ids[0]}`; + }, + }, + sampleEmit, +}; diff --git a/components/copper/sources/new-person-instant/test-event.mjs b/components/copper/sources/new-person-instant/test-event.mjs new file mode 100644 index 0000000000000..ff2c0c257af8d --- /dev/null +++ b/components/copper/sources/new-person-instant/test-event.mjs @@ -0,0 +1,10 @@ +export default { + "subscription_id": 395034, + "event": "new", + "type": "person", + "ids": [ + 167487595 + ], + "updated_attributes": {}, + "timestamp": "2024-10-14T16:07:45.004Z" +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1145af726f4d9..cd7c5c0e9cde0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -60,7 +60,7 @@ importers: pnpm: 7.33.6 putout: 32.2.0_typescript@5.2.2 renamer: 4.0.0 - ts-jest: 29.1.1_py5cyg2l76gggsf4xgc65fzuzq + ts-jest: 29.1.1_s6pp5jfszqvqftxetajx5tybba tsc-esm-fix: 2.20.17 tsc-watch: 5.0.3_typescript@5.2.2 typescript: 5.2.2 @@ -2136,6 +2136,12 @@ importers: dependencies: '@pipedream/platform': 1.5.1 + components/copper: + specifiers: + '@pipedream/platform': ^3.0.3 + dependencies: + '@pipedream/platform': 3.0.3 + components/copperx: specifiers: '@pipedream/platform': ^1.5.1 @@ -13000,55 +13006,6 @@ 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'} @@ -13284,7 +13241,55 @@ packages: dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/client-sso-oidc': 3.600.0_tdq3komn4zwyd65w7klbptsu34 + '@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-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 @@ -13323,6 +13328,7 @@ packages: '@smithy/util-utf8': 3.0.0 tslib: 2.6.3 transitivePeerDependencies: + - '@aws-sdk/client-sso-oidc' - aws-crt dev: false @@ -17618,7 +17624,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 + '@aws-sdk/client-sts': 3.600.0_dseaa2p5u2yk67qiepewcq3hkq '@aws-sdk/s3-request-presigner': 3.609.0 '@pipedream/helper_functions': 0.3.12 '@pipedream/platform': 1.6.6 @@ -34618,7 +34624,7 @@ packages: engines: {node: '>=6'} dev: true - /ts-jest/29.1.1_py5cyg2l76gggsf4xgc65fzuzq: + /ts-jest/29.1.1_s6pp5jfszqvqftxetajx5tybba: resolution: {integrity: sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true @@ -34639,7 +34645,7 @@ packages: esbuild: optional: true dependencies: - '@babel/core': 7.23.0 + '@babel/core': 7.25.2 bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 jest: 29.7.0_@types+node@20.9.2