diff --git a/apps/builder/next.config.mjs b/apps/builder/next.config.mjs index def99c9ceb..bbe2629d76 100644 --- a/apps/builder/next.config.mjs +++ b/apps/builder/next.config.mjs @@ -49,21 +49,14 @@ const nextConfig = { }, experimental: { outputFileTracingRoot: join(__dirname, '../../'), + serverComponentsExternalPackages: ['isolated-vm'], }, - webpack: (config, { nextRuntime }) => { - if (nextRuntime === 'nodejs') return config + webpack: (config, { isServer }) => { + if (isServer) return config - if (nextRuntime === 'edge') { - config.resolve.alias['minio'] = false - config.resolve.alias['got'] = false - config.resolve.alias['qrcode'] = false - return config - } - // These packages are imports from the integrations definition files that can be ignored for the client. config.resolve.alias['minio'] = false - config.resolve.alias['got'] = false - config.resolve.alias['openai'] = false config.resolve.alias['qrcode'] = false + config.resolve.alias['isolated-vm'] = false return config }, headers: async () => { diff --git a/apps/builder/package.json b/apps/builder/package.json index 2a89219a2a..b2d54beb38 100644 --- a/apps/builder/package.json +++ b/apps/builder/package.json @@ -13,7 +13,6 @@ "format:check": "prettier --check ./src --ignore-path ../../.prettierignore" }, "dependencies": { - "@typebot.io/theme": "workspace:*", "@braintree/sanitize-url": "7.0.1", "@chakra-ui/anatomy": "2.1.1", "@chakra-ui/react": "2.7.1", @@ -45,6 +44,7 @@ "@typebot.io/env": "workspace:*", "@typebot.io/js": "workspace:*", "@typebot.io/nextjs": "workspace:*", + "@typebot.io/theme": "workspace:*", "@udecode/cn": "29.0.1", "@udecode/plate-basic-marks": "30.5.3", "@udecode/plate-common": "30.4.5", @@ -68,9 +68,10 @@ "framer-motion": "10.3.0", "google-auth-library": "8.9.0", "google-spreadsheet": "4.1.1", - "ky": "1.2.3", "immer": "10.0.2", + "isolated-vm": "4.7.2", "jsonwebtoken": "9.0.1", + "ky": "1.2.3", "libphonenumber-js": "1.10.37", "micro": "10.0.1", "micro-cors": "0.1.1", @@ -123,13 +124,13 @@ "@types/qs": "6.9.7", "@types/react": "18.2.15", "@types/tinycolor2": "1.4.3", + "dotenv": "16.4.5", "dotenv-cli": "7.4.1", "eslint": "8.44.0", "eslint-config-custom": "workspace:*", "next-runtime-env": "1.6.2", "superjson": "1.12.4", "typescript": "5.4.5", - "zod": "3.22.4", - "dotenv": "16.4.5" + "zod": "3.22.4" } } diff --git a/apps/docs/editor/blocks/integrations/openai.mdx b/apps/docs/editor/blocks/integrations/openai.mdx index 1d1ac47233..d73cd8c317 100644 --- a/apps/docs/editor/blocks/integrations/openai.mdx +++ b/apps/docs/editor/blocks/integrations/openai.mdx @@ -47,6 +47,11 @@ As you can see, the code block expects the body of the Javascript function. You If you'd like to set variables directly in this code block, you can use the [`setVariable` function](../logic/script#setvariable-function). + + A function is executed on the server so it comes with [some limitations listed + here](../logic/script#limitations-on-scripts-executed-on-server). + + ## Ask assistant This action allows you to talk with your [OpenAI assistant](https://platform.openai.com/assistants). All you have to do is to provide its ID. diff --git a/apps/docs/editor/blocks/logic/script.mdx b/apps/docs/editor/blocks/logic/script.mdx index bc9e2468c6..429e6eda34 100644 --- a/apps/docs/editor/blocks/logic/script.mdx +++ b/apps/docs/editor/blocks/logic/script.mdx @@ -22,7 +22,7 @@ You need to write `console.log({{My variable}})` instead of `console.log("{{My v If you want to set a variable value with Javascript, the [Set variable block](./set-variable) is more appropriate for most cases. -However, if you'd like to set variables with the script blocks, you can use the `setVariable` function in your script: +However, if you'd like to set variables in a Script block, you can use the `setVariable` function in your script: ```js if({{My variable}} === 'foo') { @@ -34,6 +34,37 @@ if({{My variable}} === 'foo') { The `setVariable` function is only available in script executed on the server, so it won't work if the `Execute on client?` is checked. +## Limitations on scripts executed on server + +Because the script is executed on a isolated and secured environment, there are some limitations. + +- Global functions like `console.log`, `setTimeout`, `setInterval`, etc. are not available +- The `fetch` function behavior is slightly different from the native `fetch` function. You just have to skip the `await response.text()` or `await response.json()` part. + + ```js + // ❌ This throws an error + const response = await fetch('https://jsonplaceholder.typicode.com/todos/1') + const data = await response.text() + + // ✅ This works + const data = await fetch('https://jsonplaceholder.typicode.com/todos/1') + ``` + + `response` will always be a `string` even if the the request returns a JSON object. If you know that the response is a JSON object, you can parse it using `JSON.parse(response)`. + + ```js + // ❌ This throws an error + const response = await fetch('https://jsonplaceholder.typicode.com/todos/1') + const data = await response.json() + + // ✅ This works + const response = await fetch('https://jsonplaceholder.typicode.com/todos/1') + const data = JSON.parse(response) + ``` + +- You can't use `import` or `require` to import external libraries +- You don't have access to browser APIs like `window`, `document`, `localStorage`, etc. If you need to use browser APIs, you should check the `Execute on client?` option so that the script is executed on the user's browser. + ## Examples ### Reload page diff --git a/apps/viewer/next.config.mjs b/apps/viewer/next.config.mjs index 6a53414189..3100691259 100644 --- a/apps/viewer/next.config.mjs +++ b/apps/viewer/next.config.mjs @@ -50,21 +50,14 @@ const nextConfig = { output: 'standalone', experimental: { outputFileTracingRoot: join(__dirname, '../../'), + serverComponentsExternalPackages: ['isolated-vm'], }, - webpack: (config, { nextRuntime }) => { - if (nextRuntime === 'nodejs') return config + webpack: (config, { isServer }) => { + if (isServer) return config - if (nextRuntime === 'edge') { - config.resolve.alias['minio'] = false - config.resolve.alias['got'] = false - config.resolve.alias['qrcode'] = false - return config - } - // These packages are imports from the integrations definition files that can be ignored for the client. config.resolve.alias['minio'] = false - config.resolve.alias['got'] = false - config.resolve.alias['openai'] = false config.resolve.alias['qrcode'] = false + config.resolve.alias['isolated-vm'] = false return config }, async redirects() { diff --git a/apps/viewer/package.json b/apps/viewer/package.json index 49b61a6018..cd88ac0c1a 100644 --- a/apps/viewer/package.json +++ b/apps/viewer/package.json @@ -26,6 +26,7 @@ "cors": "2.8.5", "google-spreadsheet": "4.1.1", "got": "12.6.0", + "isolated-vm": "4.7.2", "ky": "1.2.3", "next": "14.1.0", "nextjs-cors": "2.1.2", @@ -37,7 +38,6 @@ "stripe": "12.13.0" }, "devDependencies": { - "dotenv": "16.4.5", "@faire/mjml-react": "3.3.0", "@paralleldrive/cuid2": "2.2.1", "@playwright/test": "1.43.1", @@ -46,6 +46,8 @@ "@typebot.io/forge": "workspace:*", "@typebot.io/forge-repository": "workspace:*", "@typebot.io/lib": "workspace:*", + "@typebot.io/playwright": "workspace:*", + "@typebot.io/results": "workspace:*", "@typebot.io/schemas": "workspace:*", "@typebot.io/tsconfig": "workspace:*", "@typebot.io/variables": "workspace:*", @@ -55,8 +57,8 @@ "@types/papaparse": "5.3.7", "@types/qs": "6.9.7", "@types/react": "18.2.15", - "dotenv-cli": "7.4.1", "dotenv": "16.4.5", + "dotenv-cli": "7.4.1", "eslint": "8.44.0", "eslint-config-custom": "workspace:*", "google-auth-library": "8.9.0", @@ -64,8 +66,6 @@ "papaparse": "5.4.1", "superjson": "1.12.4", "typescript": "5.4.5", - "zod": "3.22.4", - "@typebot.io/playwright": "workspace:*", - "@typebot.io/results": "workspace:*" + "zod": "3.22.4" } } diff --git a/packages/bot-engine/blocks/integrations/webhook/resumeWebhookExecution.ts b/packages/bot-engine/blocks/integrations/webhook/resumeWebhookExecution.ts index cbad413b7e..459939bb66 100644 --- a/packages/bot-engine/blocks/integrations/webhook/resumeWebhookExecution.ts +++ b/packages/bot-engine/blocks/integrations/webhook/resumeWebhookExecution.ts @@ -11,7 +11,7 @@ import { SessionState } from '@typebot.io/schemas/features/chat/sessionState' import { ExecuteIntegrationResponse } from '../../../types' import { parseVariables } from '@typebot.io/variables/parseVariables' import { updateVariablesInSession } from '@typebot.io/variables/updateVariablesInSession' -import vm from 'vm' +import { createHttpReqResponseMappingRunner } from '@typebot.io/variables/codeRunners' type Props = { state: SessionState @@ -50,19 +50,21 @@ export const resumeWebhookExecution = ({ } ) + let run: (varMapping: string) => unknown + if (block.options?.responseVariableMapping) { + run = createHttpReqResponseMappingRunner(response) + } const newVariables = block.options?.responseVariableMapping?.reduce< VariableWithUnknowValue[] >((newVariables, varMapping) => { - if (!varMapping?.bodyPath || !varMapping.variableId) return newVariables + if (!varMapping?.bodyPath || !varMapping.variableId || !run) + return newVariables const existingVariable = typebot.variables.find(byId(varMapping.variableId)) if (!existingVariable) return newVariables - const sandbox = vm.createContext({ - data: response, - }) + try { - const value: unknown = vm.runInContext( - `data.${parseVariables(typebot.variables)(varMapping?.bodyPath)}`, - sandbox + const value: unknown = run( + parseVariables(typebot.variables)(varMapping?.bodyPath) ) return [...newVariables, { ...existingVariable, value }] } catch (err) { diff --git a/packages/bot-engine/blocks/logic/setVariable/executeSetVariable.ts b/packages/bot-engine/blocks/logic/setVariable/executeSetVariable.ts index 8e6fcd7271..36def21c19 100644 --- a/packages/bot-engine/blocks/logic/setVariable/executeSetVariable.ts +++ b/packages/bot-engine/blocks/logic/setVariable/executeSetVariable.ts @@ -8,7 +8,6 @@ import { import { byId, isEmpty } from '@typebot.io/lib' import { ExecuteLogicResponse } from '../../../types' import { parseScriptToExecuteClientSideAction } from '../script/executeScript' -import { parseGuessedValueType } from '@typebot.io/variables/parseGuessedValueType' import { parseVariables } from '@typebot.io/variables/parseVariables' import { updateVariablesInSession } from '@typebot.io/variables/updateVariablesInSession' import { createId } from '@paralleldrive/cuid2' @@ -19,7 +18,7 @@ import { } from '@typebot.io/logic/computeResultTranscript' import prisma from '@typebot.io/lib/prisma' import { sessionOnlySetVariableOptions } from '@typebot.io/schemas/features/blocks/logic/setVariable/constants' -import vm from 'vm' +import { createCodeRunner } from '@typebot.io/variables/codeRunners' export const executeSetVariable = async ( state: SessionState, @@ -97,17 +96,11 @@ const evaluateSetVariableExpression = if (isSingleVariable) return parseVariables(variables)(str) // To avoid octal number evaluation if (!isNaN(str as unknown as number) && /0[^.].+/.test(str)) return str - const evaluating = parseVariables(variables, { fieldToParse: 'id' })( - `(function() {${str.includes('return ') ? str : 'return ' + str}})()` - ) try { - const sandbox = vm.createContext({ - ...Object.fromEntries( - variables.map((v) => [v.id, parseGuessedValueType(v.value)]) - ), - fetch, - }) - return vm.runInContext(evaluating, sandbox) + const body = parseVariables(variables, { fieldToParse: 'id' })(str) + return createCodeRunner({ variables })( + body.includes('return ') ? body : `return ${body}` + ) } catch (err) { return parseVariables(variables)(str) } diff --git a/packages/bot-engine/package.json b/packages/bot-engine/package.json index 3e9a95067e..5136c0ae68 100644 --- a/packages/bot-engine/package.json +++ b/packages/bot-engine/package.json @@ -32,7 +32,8 @@ "nodemailer": "6.9.8", "openai": "4.47.1", "qs": "6.11.2", - "stripe": "12.13.0" + "stripe": "12.13.0", + "isolated-vm": "4.7.2" }, "devDependencies": { "@typebot.io/forge": "workspace:*", diff --git a/packages/variables/codeRunners.ts b/packages/variables/codeRunners.ts new file mode 100644 index 0000000000..c2a1d1975f --- /dev/null +++ b/packages/variables/codeRunners.ts @@ -0,0 +1,55 @@ +import { Variable } from './types' +import ivm from 'isolated-vm' +import { parseGuessedValueType } from './parseGuessedValueType' + +export const createCodeRunner = ({ variables }: { variables: Variable[] }) => { + const isolate = new ivm.Isolate() + const context = isolate.createContextSync() + const jail = context.global + jail.setSync('global', jail.derefInto()) + variables.forEach((v) => { + jail.setSync(v.id, parseTransferrableValue(parseGuessedValueType(v.value))) + }) + return (code: string) => + context.evalClosureSync( + `return (function() { + return new Function($0)(); + }())`, + [code], + { result: { copy: true }, timeout: 10000 } + ) +} + +export const createHttpReqResponseMappingRunner = (response: any) => { + const isolate = new ivm.Isolate() + const context = isolate.createContextSync() + const jail = context.global + jail.setSync('global', jail.derefInto()) + jail.setSync('response', new ivm.ExternalCopy(response).copyInto()) + return (expression: string) => { + return context.evalClosureSync( + `globalThis.evaluateExpression = function(expression) { + try { + // Use Function to safely evaluate the expression + const func = new Function('statusCode', 'data', 'return (' + expression + ')'); + return func(response.statusCode, response.data); + } catch (err) { + throw new Error('Invalid expression: ' + err.message); + } + }; + return evaluateExpression.apply(null, arguments);`, + [expression], + { + result: { copy: true }, + timeout: 10000, + } + ) + } +} + +const parseTransferrableValue = (value: unknown) => { + if (typeof value === 'object') { + return new ivm.ExternalCopy(value).copyInto() + } + return value +} diff --git a/packages/variables/executeFunction.ts b/packages/variables/executeFunction.ts index 21b513dc7f..7055b78890 100644 --- a/packages/variables/executeFunction.ts +++ b/packages/variables/executeFunction.ts @@ -4,9 +4,9 @@ import { parseGuessedValueType } from './parseGuessedValueType' import { isDefined } from '@typebot.io/lib' import { safeStringify } from '@typebot.io/lib/safeStringify' import { Variable } from './types' -import vm from 'vm' +import ivm from 'isolated-vm' -const defaultTimeout = 10 +const defaultTimeout = 10 * 1000 type Props = { variables: Variable[] @@ -19,9 +19,9 @@ export const executeFunction = async ({ body, args: initialArgs, }: Props) => { - const parsedBody = `(async function() {${parseVariables(variables, { + const parsedBody = parseVariables(variables, { fieldToParse: 'id', - })(body)}})()` + })(body) const args = ( extractVariablesFromText(variables)(body).map((variable) => ({ @@ -40,21 +40,40 @@ export const executeFunction = async ({ updatedVariables[key] = value } - const context = vm.createContext({ - ...Object.fromEntries(args.map(({ id, value }) => [id, value])), - setVariable, - fetch, - setTimeout, + const isolate = new ivm.Isolate() + const context = isolate.createContextSync() + const jail = context.global + jail.setSync('global', jail.derefInto()) + context.evalClosure( + 'globalThis.setVariable = (...args) => $0.apply(undefined, args, { arguments: { copy: true }, promise: true, result: { copy: true, promise: true } })', + [new ivm.Reference(setVariable)] + ) + context.evalClosure( + 'globalThis.fetch = (...args) => $0.apply(undefined, args, { arguments: { copy: true }, promise: true, result: { copy: true, promise: true } })', + [ + new ivm.Reference(async (...args: any[]) => { + // @ts-ignore + const response = await fetch(...args) + return response.text() + }), + ] + ) + args.forEach(({ id, value }) => { + jail.setSync(id, value) }) - - const timeout = new Timeout() + const run = (code: string) => + context.evalClosure( + `return (async function() { + const AsyncFunction = async function () {}.constructor; + return new AsyncFunction($0)(); + }())`, + [code], + { result: { copy: true, promise: true }, timeout: defaultTimeout } + ) try { - const output: unknown = await timeout.wrap( - await vm.runInContext(parsedBody, context), - defaultTimeout * 1000 - ) - timeout.clear() + const output = await run(parsedBody) + console.log('Output', output) return { output: safeStringify(output) ?? '', newVariables: Object.entries(updatedVariables) @@ -86,33 +105,3 @@ export const executeFunction = async ({ } } } - -class Timeout { - private ids: NodeJS.Timeout[] - - constructor() { - this.ids = [] - } - - private set = (delay: number) => - new Promise((_, reject) => { - const id = setTimeout(() => { - reject(`Script ${defaultTimeout}s timeout reached`) - this.clear(id) - }, delay) - this.ids.push(id) - }) - - wrap = (promise: Promise, delay: number) => - Promise.race([promise, this.set(delay)]) - - clear = (...ids: NodeJS.Timeout[]) => { - this.ids = this.ids.filter((id) => { - if (ids.includes(id)) { - clearTimeout(id) - return false - } - return true - }) - } -} diff --git a/packages/variables/package.json b/packages/variables/package.json index ef827e564b..8bad3edf46 100644 --- a/packages/variables/package.json +++ b/packages/variables/package.json @@ -5,6 +5,7 @@ "private": true, "dependencies": { "@typebot.io/lib": "workspace:*", - "@typebot.io/tsconfig": "workspace:*" + "@typebot.io/tsconfig": "workspace:*", + "isolated-vm": "4.7.2" } } diff --git a/packages/variables/parseVariables.ts b/packages/variables/parseVariables.ts index 7f511bce1d..f4ec2b786a 100644 --- a/packages/variables/parseVariables.ts +++ b/packages/variables/parseVariables.ts @@ -1,8 +1,7 @@ import { safeStringify } from '@typebot.io/lib/safeStringify' import { isDefined, isNotDefined } from '@typebot.io/lib/utils' -import { parseGuessedValueType } from './parseGuessedValueType' import { Variable, VariableWithValue } from './types' -import vm from 'vm' +import { createCodeRunner } from './codeRunners' export type ParseVariablesOptions = { fieldToParse?: 'value' | 'id' @@ -73,18 +72,10 @@ const evaluateInlineCode = ( code: string, { variables }: { variables: Variable[] } ) => { - const evaluating = parseVariables(variables, { fieldToParse: 'id' })( - `(function() { - ${code.includes('return ') ? code : 'return ' + code} - })()` - ) try { - const sandbox = vm.createContext({ - ...Object.fromEntries( - variables.map((v) => [v.id, parseGuessedValueType(v.value)]) - ), - }) - return vm.runInContext(evaluating, sandbox) + return createCodeRunner({ variables })( + parseVariables(variables, { fieldToParse: 'id' })(code) + ) } catch (err) { return parseVariables(variables)(code) } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e0e6798b9c..1a3e32e20e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -197,6 +197,9 @@ importers: immer: specifier: 10.0.2 version: 10.0.2 + isolated-vm: + specifier: 4.7.2 + version: 4.7.2 jsonwebtoken: specifier: 9.0.1 version: 9.0.1 @@ -550,6 +553,9 @@ importers: got: specifier: 12.6.0 version: 12.6.0 + isolated-vm: + specifier: 4.7.2 + version: 4.7.2 ky: specifier: 1.2.3 version: 1.2.3 @@ -744,6 +750,9 @@ importers: google-spreadsheet: specifier: 4.1.1 version: 4.1.1(google-auth-library@8.9.0) + isolated-vm: + specifier: 4.7.2 + version: 4.7.2 ky: specifier: 1.2.3 version: 1.2.3 @@ -1948,6 +1957,9 @@ importers: '@typebot.io/tsconfig': specifier: workspace:* version: link:../tsconfig + isolated-vm: + specifier: 4.7.2 + version: 4.7.2 packages: @@ -11994,6 +12006,10 @@ packages: optionalDependencies: fsevents: 2.3.3 + /chownr@1.1.4: + resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} + dev: false + /chownr@2.0.0: resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} engines: {node: '>=10'} @@ -12778,6 +12794,11 @@ packages: optional: true dev: true + /deep-extend@0.6.0: + resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} + engines: {node: '>=4.0.0'} + dev: false + /deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} @@ -12875,7 +12896,6 @@ packages: /detect-libc@2.0.2: resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==} engines: {node: '>=8'} - dev: true /detect-newline@3.1.0: resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} @@ -13125,6 +13145,12 @@ packages: resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} engines: {node: '>= 0.8'} + /end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + dependencies: + once: 1.4.0 + dev: false + /engine.io-client@6.5.3: resolution: {integrity: sha512-9Z0qLB0NIisTRt1DZ/8U2k12RJn8yls/nXMZLn+/N8hANT3TcYjKFKcwbw5zFQiN4NTde3TSY9zb79e1ij6j9Q==} dependencies: @@ -14196,6 +14222,11 @@ packages: engines: {node: '>= 0.8.0'} dev: true + /expand-template@2.0.3: + resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} + engines: {node: '>=6'} + dev: false + /expect@29.7.0: resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -14541,6 +14572,10 @@ packages: resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} engines: {node: '>= 0.6'} + /fs-constants@1.0.0: + resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + dev: false + /fs-extra@11.2.0: resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} engines: {node: '>=14.14'} @@ -14676,6 +14711,10 @@ packages: dependencies: resolve-pkg-maps: 1.0.0 + /github-from-package@0.0.0: + resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} + dev: false + /glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -15773,6 +15812,14 @@ packages: /isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + /isolated-vm@4.7.2: + resolution: {integrity: sha512-JVEs5gzWObzZK5+OlBplCdYSpokMcdhLSs/xWYYxmYWVfOOFF4oZJsYh7E/FmfX8e7gMioXMpMMeEyX1afuKrg==} + engines: {node: '>=16.0.0'} + requiresBuild: true + dependencies: + prebuild-install: 7.1.2 + dev: false + /isomorphic-fetch@3.0.0: resolution: {integrity: sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==} dependencies: @@ -18227,6 +18274,10 @@ packages: transitivePeerDependencies: - encoding + /mkdirp-classic@0.5.3: + resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} + dev: false + /mkdirp@0.5.6: resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} hasBin: true @@ -18292,6 +18343,10 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + /napi-build-utils@1.0.2: + resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==} + dev: false + /natural-compare-lite@1.4.0: resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} dev: true @@ -18453,6 +18508,13 @@ packages: dependencies: lower-case: 1.1.4 + /node-abi@3.62.0: + resolution: {integrity: sha512-CPMcGa+y33xuL1E0TcNIu4YyaZCxnnvkVaEXrsosR3FxN+fV8xvb7Mzpb7IgKler10qeMkE6+Dp8qJhpzdq35g==} + engines: {node: '>=10'} + dependencies: + semver: 7.6.0 + dev: false + /node-domexception@1.0.0: resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} engines: {node: '>=10.5.0'} @@ -19587,6 +19649,25 @@ packages: resolution: {integrity: sha512-gympg+T2Z1fG1unB8NH29yHJwnEaCH37Z32diPDku316OTnRPeMbiRV9kTrfZpocXjdfnWuFUl/Mj4BHaf6gnw==} dev: false + /prebuild-install@7.1.2: + resolution: {integrity: sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==} + engines: {node: '>=10'} + hasBin: true + dependencies: + detect-libc: 2.0.2 + expand-template: 2.0.3 + github-from-package: 0.0.0 + minimist: 1.2.8 + mkdirp-classic: 0.5.3 + napi-build-utils: 1.0.2 + node-abi: 3.62.0 + pump: 3.0.0 + rc: 1.2.8 + simple-get: 4.0.1 + tar-fs: 2.1.1 + tunnel-agent: 0.6.0 + dev: false + /prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -19721,6 +19802,13 @@ packages: is-ip: 3.1.0 dev: true + /pump@3.0.0: + resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + dev: false + /punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -19819,6 +19907,16 @@ packages: iconv-lite: 0.4.24 unpipe: 1.0.0 + /rc@1.2.8: + resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} + hasBin: true + dependencies: + deep-extend: 0.6.0 + ini: 1.3.8 + minimist: 1.2.8 + strip-json-comments: 2.0.1 + dev: false + /react-clientside-effect@1.2.6(react@18.2.0): resolution: {integrity: sha512-XGGGRQAKY+q25Lz9a/4EPqom7WRjz3z9R2k4jhVKA/puQFH/5Nt27vFZYql4m4NVNdUvX8PS3O7r/Zzm7cjUlg==} peerDependencies: @@ -20874,6 +20972,18 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} + /simple-concat@1.0.1: + resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} + dev: false + + /simple-get@4.0.1: + resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} + dependencies: + decompress-response: 6.0.0 + once: 1.4.0 + simple-concat: 1.0.1 + dev: false + /simple-swizzle@0.2.2: resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} dependencies: @@ -21353,6 +21463,11 @@ packages: min-indent: 1.0.1 dev: false + /strip-json-comments@2.0.1: + resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} + engines: {node: '>=0.10.0'} + dev: false + /strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} @@ -21684,6 +21799,26 @@ packages: resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} engines: {node: '>=6'} + /tar-fs@2.1.1: + resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==} + dependencies: + chownr: 1.1.4 + mkdirp-classic: 0.5.3 + pump: 3.0.0 + tar-stream: 2.2.0 + dev: false + + /tar-stream@2.2.0: + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} + engines: {node: '>=6'} + dependencies: + bl: 4.1.0 + end-of-stream: 1.4.4 + fs-constants: 1.0.0 + inherits: 2.0.4 + readable-stream: 3.6.2 + dev: false + /tar@6.2.0: resolution: {integrity: sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==} engines: {node: '>=10'} @@ -22065,6 +22200,12 @@ packages: fsevents: 2.3.3 dev: true + /tunnel-agent@0.6.0: + resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} + dependencies: + safe-buffer: 5.2.1 + dev: false + /turbo-darwin-64@1.11.3: resolution: {integrity: sha512-IsOOg2bVbIt3o/X8Ew9fbQp5t1hTHN3fGNQYrPQwMR2W1kIAC6RfbVD4A9OeibPGyEPUpwOH79hZ9ydFH5kifw==} cpu: [x64]