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]