diff --git a/.idea/dictionaries/fuxing.xml b/.idea/dictionaries/fuxing.xml
index 414c529..88c1aab 100644
--- a/.idea/dictionaries/fuxing.xml
+++ b/.idea/dictionaries/fuxing.xml
@@ -5,6 +5,7 @@
contentedjs
fuxing
fuxingloh
+ jsonrpc
karfia
testcontainers
diff --git a/definitions/bip122-0f9188f13cb7b2c71f2a335e3a4fc328/bitcoind.json b/definitions/bip122-0f9188f13cb7b2c71f2a335e3a4fc328/bitcoind.json
index 93a9490..999dcf7 100644
--- a/definitions/bip122-0f9188f13cb7b2c71f2a335e3a4fc328/bitcoind.json
+++ b/definitions/bip122-0f9188f13cb7b2c71f2a335e3a4fc328/bitcoind.json
@@ -5,14 +5,12 @@
"name": "Bitcoin Regtest",
"environment": {
"RPC_USER": {
- "type": "RandomBytes",
- "length": 16,
- "encoding": "hex"
+ "type": "Value",
+ "value": "karfia"
},
"RPC_PASSWORD": {
- "type": "RandomBytes",
- "length": 16,
- "encoding": "hex"
+ "type": "Value",
+ "value": "karfia"
}
},
"containers": {
diff --git a/packages/karfia-agent/package.json b/packages/karfia-agent/package.json
index 9471cfb..f7daff1 100644
--- a/packages/karfia-agent/package.json
+++ b/packages/karfia-agent/package.json
@@ -11,8 +11,7 @@
"build:docker": "docker buildx build --progress=plain -t ghcr.io/fuxingloh/karfia-agent:$(node -p \"require('./package.json').version\") -f Dockerfile ../../",
"clean": "tsc --build --clean",
"lint": "eslint .",
- "push:docker": "docker buildx build --progress=plain -t ghcr.io/fuxingloh/karfia-agent:$(node -p \"require('./package.json').version\") -f Dockerfile ../../ --output type=registry --platform linux/amd64,linux/arm64",
- "test": "jest --passWithNoTests"
+ "push:docker": "docker buildx build --progress=plain -t ghcr.io/fuxingloh/karfia-agent:$(node -p \"require('./package.json').version\") -f Dockerfile ../../ --output type=registry --platform linux/amd64,linux/arm64"
},
"lint-staged": {
"*": [
@@ -23,9 +22,6 @@
"prettier --write"
]
},
- "jest": {
- "preset": "@workspace/jest-preset"
- },
"dependencies": {
"@trpc/server": "^10.45.2",
"ajv": "^8.12.0",
@@ -35,7 +31,6 @@
"zod": "^3.22.5"
},
"devDependencies": {
- "@workspace/jest-preset": "workspace:*",
"@workspace/tsconfig": "workspace:*"
}
}
diff --git a/packages/karfia-definition/environment.ts b/packages/karfia-definition/environment.ts
new file mode 100644
index 0000000..493e1e6
--- /dev/null
+++ b/packages/karfia-definition/environment.ts
@@ -0,0 +1,98 @@
+import { randomBytes } from 'node:crypto';
+
+import { Environment } from './index';
+
+// Dotenv Expansion Implementation
+//
+// Copyright (c) 2016, Scott Motte
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+const dotenv = {
+ INTERPOLATE_SUBSTITUTION_REGEX:
+ /(\\)?(\$)(?!\()(\{?)([\w.]+)(?::?-((?:\$\{(?:\$\{(?:\$\{[^}]*\}|[^}])*}|[^}])*}|[^}])+))?(\}?)/gi,
+ resolveEscapeSequences: (value: string): string => {
+ return value.replace(/\\\$/g, '$');
+ },
+ interpolate: (value: string, parsed: Record): string => {
+ return value.replace(
+ dotenv.INTERPOLATE_SUBSTITUTION_REGEX,
+ (match, escaped, dollarSign, openBrace, key, defaultValue) => {
+ if (escaped === '\\') return match.slice(1);
+
+ if (parsed[key]) {
+ // avoid recursion from EXPAND_SELF=$EXPAND_SELF
+ if (parsed[key] === value) {
+ return parsed[key];
+ } else {
+ return dotenv.interpolate(parsed[key], parsed);
+ }
+ }
+
+ if (defaultValue) {
+ if (defaultValue.startsWith('$')) {
+ return dotenv.interpolate(defaultValue, parsed);
+ } else {
+ return defaultValue;
+ }
+ }
+
+ return '';
+ },
+ );
+ },
+ expand: (env: Record): Record => {
+ const copied = { ...env };
+
+ for (const key in copied) {
+ const value = dotenv.interpolate(copied[key], copied);
+ copied[key] = dotenv.resolveEscapeSequences(value);
+ }
+
+ return copied;
+ },
+};
+
+export function synthEnv(environment: Environment): Record {
+ return dotenv.expand(
+ Object.entries(environment).reduce(
+ (env, [key, factory]) => {
+ if (factory.type === 'RandomBytes') {
+ env[key] = randomBytes(factory.length).toString(factory.encoding);
+ return env;
+ }
+ if (factory.type === 'Value') {
+ env[key] = factory.value;
+ return env;
+ }
+
+ // if (factory.type === 'Injection') {
+ // TODO: Prompt if CLI, inject if constructs.
+ // To allow for simple configuration, e.g. Masternode Keys.
+
+ // @ts-expect-error so that we error out if we forget to handle a new factory type
+ throw new Error(`Unsupported Environment Factory: ${factory.type}`);
+ },
+ {} as Record,
+ ),
+ );
+}
diff --git a/packages/karfia-definition/environment.unit.ts b/packages/karfia-definition/environment.unit.ts
new file mode 100644
index 0000000..520e9e8
--- /dev/null
+++ b/packages/karfia-definition/environment.unit.ts
@@ -0,0 +1,34 @@
+import { expect, it } from '@jest/globals';
+
+import { Environment } from '.';
+import { synthEnv } from './environment';
+
+it('should expand environment', async () => {
+ const environment: Environment = {
+ USER: {
+ type: 'RandomBytes',
+ length: 8,
+ encoding: 'hex',
+ },
+ PASS: {
+ type: 'RandomBytes',
+ length: 16,
+ encoding: 'hex',
+ },
+ URL: {
+ type: 'Value',
+ value: `http://$USER:$PASS@localhost:3000000`,
+ },
+ DEBUG: {
+ type: 'Value',
+ value: 'karfia:*',
+ },
+ };
+
+ expect(synthEnv(environment)).toStrictEqual({
+ USER: expect.stringMatching(/[0-9a-f]{16}/),
+ PASS: expect.stringMatching(/[0-9a-f]{32}/),
+ URL: expect.stringMatching(/http:\/\/[0-9a-f]{16}:[0-9a-f]{32}@localhost:3000000/),
+ DEBUG: 'karfia:*',
+ });
+});
diff --git a/packages/karfia-definition/index.json b/packages/karfia-definition/index.json
index c09a84c..0463eeb 100644
--- a/packages/karfia-definition/index.json
+++ b/packages/karfia-definition/index.json
@@ -273,7 +273,7 @@
]
},
"body": {
- "$ref": "http://json-schema.org/draft-07/schema"
+ "$ref": "http://json-schema.org/draft-07/schema#"
}
},
"required": ["status"]
diff --git a/packages/karfia-definition/package.json b/packages/karfia-definition/package.json
index 4ffd289..18b267c 100644
--- a/packages/karfia-definition/package.json
+++ b/packages/karfia-definition/package.json
@@ -14,12 +14,16 @@
"index.d.ts",
"schema.js",
"schema.d.ts",
- "schema.d.ts.map"
+ "schema.d.ts.map",
+ "environment.js",
+ "environment.d.ts",
+ "environment.d.ts.map"
],
"scripts": {
"build": "json2ts index.json > index.d.ts && tsc --project tsconfig.build.json",
"clean": "rm -f index.d.ts && tsc --build --clean",
- "lint": "eslint ."
+ "lint": "eslint .",
+ "test": "jest"
},
"lint-staged": {
"*": [
@@ -30,12 +34,16 @@
"prettier --write"
]
},
+ "jest": {
+ "preset": "@workspace/jest-preset"
+ },
"dependencies": {
"ajv": "^8.12.0",
"ajv-formats": "^3.0.1"
},
"devDependencies": {
+ "@workspace/jest-preset": "workspace:*",
"@workspace/tsconfig": "workspace:*",
- "json-schema-to-typescript": "^13.1.2"
+ "json-schema-to-typescript": "^14.0.0"
}
}
diff --git a/packages/karfia-docker-compose/environment.ts b/packages/karfia-docker-compose/environment.ts
deleted file mode 100644
index 5abb84a..0000000
--- a/packages/karfia-docker-compose/environment.ts
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (c) 2016, Scott Motte
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// * Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// * Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-const INTERPOLATE_SUBSTITUTION_REGEX =
- /(\\)?(\$)(?!\()(\{?)([\w.]+)(?::?-((?:\$\{(?:\$\{(?:\$\{[^}]*\}|[^}])*}|[^}])*}|[^}])+))?(\}?)/gi;
-
-function resolveEscapeSequences(value: string) {
- return value.replace(/\\\$/g, '$');
-}
-
-function interpolate(value: string, parsed: Record): string {
- return value.replace(INTERPOLATE_SUBSTITUTION_REGEX, (match, escaped, dollarSign, openBrace, key, defaultValue) => {
- if (escaped === '\\') return match.slice(1);
-
- if (parsed[key]) {
- // avoid recursion from EXPAND_SELF=$EXPAND_SELF
- if (parsed[key] === value) {
- return parsed[key];
- } else {
- return interpolate(parsed[key], parsed);
- }
- }
-
- if (defaultValue) {
- if (defaultValue.startsWith('$')) {
- return interpolate(defaultValue, parsed);
- } else {
- return defaultValue;
- }
- }
-
- return '';
- });
-}
-
-export function expand(env: Record) {
- const copied = { ...env };
-
- for (const key in copied) {
- const value = interpolate(copied[key], copied);
- copied[key] = resolveEscapeSequences(value);
- }
-
- return copied;
-}
diff --git a/packages/karfia-docker-compose/synthesizer.ts b/packages/karfia-docker-compose/synthesizer.ts
index 62db081..cfbfda2 100644
--- a/packages/karfia-docker-compose/synthesizer.ts
+++ b/packages/karfia-docker-compose/synthesizer.ts
@@ -2,9 +2,9 @@ import { randomBytes } from 'node:crypto';
import yaml from 'js-yaml';
import { Container, KarfiaDefinition } from 'karfia-definition';
+import { synthEnv } from 'karfia-definition/environment';
import { validate } from 'karfia-definition/schema';
-import { expand } from './environment';
import { version } from './package.json';
/**
@@ -23,31 +23,10 @@ export class Synthesizer {
}
public synthEnv(): string {
- const env = expand({
+ return Object.entries({
+ ...synthEnv(this.definition.environment ?? {}),
KARFIA_DEPLOYMENT_ID: this.deploymentId,
- ...Object.entries(this.definition.environment ?? {}).reduce(
- (env, [key, factory]) => {
- if (factory.type === 'RandomBytes') {
- env[key] = randomBytes(factory.length).toString(factory.encoding);
- return env;
- }
- if (factory.type === 'Value') {
- env[key] = factory.value;
- return env;
- }
-
- // if (factory.type === 'Injection') {
- // TODO: Prompt if CLI, inject if constructs.
- // To allow for simple configuration, e.g. Masternode Keys.
-
- // @ts-expect-error so that we error if we forget to handle a new factory type
- throw new Error(`Unsupported Environment Factory: ${factory.type}`);
- },
- {} as Record,
- ),
- });
-
- return Object.entries(env ?? {})
+ })
.map(([key, value]) => `${key}=${value}`)
.join('\n');
}
diff --git a/packages/karfia-docker-compose/synthesizer.unit.ts b/packages/karfia-docker-compose/synthesizer.unit.ts
index 4a30865..19ffe23 100644
--- a/packages/karfia-docker-compose/synthesizer.unit.ts
+++ b/packages/karfia-docker-compose/synthesizer.unit.ts
@@ -93,10 +93,10 @@ it('should synthesize with valid definition', async () => {
const synthesizer = new Synthesizer(definition);
expect(synthesizer.synthCompose()).toMatchSnapshot();
expect(synthesizer.synthEnv().split('\n')).toStrictEqual([
- expect.stringMatching(/^KARFIA_DEPLOYMENT_ID=[0-9a-f]{16}$/),
expect.stringMatching(/^RPC_USER=[0-9a-f]{32}$/),
expect.stringMatching(/^RPC_PASSWORD=[0-9a-f]{32}$/),
expect.stringMatching(/^URL=http:\/\/[0-9a-f]{32}:[0-9a-f]{32}@ganache:8554$/),
+ expect.stringMatching(/^KARFIA_DEPLOYMENT_ID=[0-9a-f]{16}$/),
]);
});
diff --git a/packages/karfia-testcontainers/index.ts b/packages/karfia-testcontainers/index.ts
index cbd401e..3f8578b 100644
--- a/packages/karfia-testcontainers/index.ts
+++ b/packages/karfia-testcontainers/index.ts
@@ -65,6 +65,10 @@ export class KarfiaTestcontainers {
return this.deploymentId;
}
+ getEnvironment(): Record {
+ return this.environment;
+ }
+
getContainer(name: string): KarfiaContainer {
const containerDef = this.definition.containers[name];
if (containerDef === undefined) {
diff --git a/packages/karfia-testcontainers/karfia-container.ts b/packages/karfia-testcontainers/karfia-container.ts
index 9161a8e..1149e8a 100644
--- a/packages/karfia-testcontainers/karfia-container.ts
+++ b/packages/karfia-testcontainers/karfia-container.ts
@@ -3,6 +3,7 @@ import { randomInt } from 'node:crypto';
import {
Container,
+ ContainerEndpoint,
ContainerEndpointHttpAuthorization,
ContainerEndpointHttpJsonRpc,
ContainerEndpointHttpRest,
@@ -19,6 +20,12 @@ export class KarfiaContainer extends AbstractStartedContainer {
super(started);
}
+ /**
+ * Get the host port for a given endpoint name.
+ * To make a request to the container, you need to use the host and the port.
+ * The port is the port on the host machine that is mapped to the container port.
+ * @param name of the endpoint to get
+ */
getHostPort(name: string): number {
const endpoint = this.container.endpoints[name];
if (endpoint === undefined) {
@@ -27,33 +34,97 @@ export class KarfiaContainer extends AbstractStartedContainer {
return this.getMappedPort(endpoint.port);
}
+ private getEndpoint(name: string): E {
+ const endpoint = this.container.endpoints?.[name];
+ if (endpoint === undefined) {
+ throw new Error(`Endpoint: '${name}' not found.`);
+ }
+ return endpoint as E;
+ }
+
/**
- * Get the host endpoint for a given name.
- * @param {string} name of the endpoint to get
- * @param {string} host to use, defaults to the container host,
+ * Get the host endpoint for a given endpoint name.
+ * @param name of the endpoint to get
+ * @param host to use, defaults to the container host,
* use `host.docker.internal` if you need to access the host from a container
*/
getHostEndpoint(name: string, host = this.getHost()): string {
- const endpoint = this.container.endpoints?.[name];
- if (endpoint === undefined) {
- throw new Error(`Endpoint not found, please define a '${name}' endpoint to use rpc()`);
+ const endpoint = this.getEndpoint(name);
+ const port = this.getMappedPort(endpoint.port);
+ switch (endpoint.protocol) {
+ case 'HTTP JSON-RPC 1.0':
+ case 'HTTP JSON-RPC 2.0':
+ return `http://${host}:${port}/${endpoint.path ?? ''}`;
+ case 'HTTPS JSON-RPC 1.0':
+ case 'HTTPS JSON-RPC 2.0':
+ return `https://${host}:${port}/${endpoint.path ?? ''}`;
+ case 'HTTP REST':
+ return `http://${host}:${port}`;
+ case 'HTTPS REST':
+ return `https://${host}:${port}`;
+ default:
+ throw new Error(`Endpoint: '${name}' does not support getHostEndpoint()`);
}
+ }
- const protocol = (endpoint as any).protocol;
- switch (protocol) {
- default:
- throw new Error(`Unsupported protocol: ${protocol} for rpc()`);
+ /**
+ * Get the authorization headers for a given endpoint name.
+ *
+ * ### Usage Example
+ *
+ * Given you want to call a rpc method on a container that requires authorization:
+ *
+ * ```ts
+ * const endpoint = container.getHostEndpoint('rpc');
+ * const headers = container.getAuthorizationHeaders('rpc');
+ * const response = await fetch(endpoint, {
+ * method: 'POST',
+ * headers: headers,
+ * body: JSON.stringify({
+ * jsonrpc: '2.0',
+ * method: 'rpc_method',
+ * })
+ * })
+ * ```
+ *
+ * @param name of the endpoint to get
+ */
+ getAuthHeaders(name: string): Record {
+ const endpoint = this.getEndpoint(name);
+
+ const getHttpAuthHeaders = (auth?: ContainerEndpointHttpAuthorization): Record => {
+ if (auth === undefined) {
+ return {};
+ }
+
+ const type = auth.type;
+ if (type === 'HttpBasic') {
+ const username = this.resolveValue(auth.username);
+ const password = this.resolveValue(auth.password);
+ return {
+ Authorization: `Basic ${Buffer.from(`${username}:${password}`).toString('base64')}`,
+ };
+ } else if (type === 'HttpBearer') {
+ const token = this.resolveValue(auth.token);
+ return {
+ Authorization: `Bearer ${token}`,
+ };
+ } else {
+ throw new Error(`Unknown authorization type: ${type}`);
+ }
+ };
+
+ switch (endpoint.protocol) {
case 'HTTP JSON-RPC 1.0':
case 'HTTPS JSON-RPC 1.0':
case 'HTTP JSON-RPC 2.0':
case 'HTTPS JSON-RPC 2.0':
+ case 'HTTP REST':
+ case 'HTTPS REST':
+ return getHttpAuthHeaders(endpoint.authorization);
+ default:
+ throw new Error(`Endpoint: '${name}' does not support getAuthHeaders()`);
}
-
- const jsonRpc = endpoint as ContainerEndpointHttpJsonRpc;
- const scheme = jsonRpc.protocol.startsWith('HTTPS') ? 'https' : 'http';
-
- const hostPort = this.getMappedPort(endpoint.port);
- return `${scheme}://${host}:${hostPort}${jsonRpc.path ?? ''}`;
}
async rpc(options: {
@@ -63,17 +134,24 @@ export class KarfiaContainer extends AbstractStartedContainer {
endpoint?: string;
}): Promise {
const name = options.endpoint ?? 'rpc';
- const hostEndpoint = this.getHostEndpoint(name);
-
const endpoint = this.container.endpoints?.[name];
- const jsonRpc = endpoint as ContainerEndpointHttpJsonRpc;
- const jsonRpcVersion = jsonRpc.protocol.endsWith('2.0') ? '2.0' : '1.0';
+ const protocol = (endpoint as ContainerEndpointHttpJsonRpc).protocol;
+ switch (protocol) {
+ default:
+ throw new Error(`Unsupported protocol: ${protocol} for rpc()`);
+ case 'HTTP JSON-RPC 1.0':
+ case 'HTTPS JSON-RPC 1.0':
+ case 'HTTP JSON-RPC 2.0':
+ case 'HTTPS JSON-RPC 2.0':
+ }
+
+ const jsonRpcVersion = protocol.endsWith('2.0') ? '2.0' : '1.0';
- return await fetch(hostEndpoint, {
+ return await fetch(this.getHostEndpoint(name), {
method: 'POST',
headers: {
'Content-Type': 'application/json',
- ...(jsonRpc.authorization ? this.getHttpAuthorizationHeaders(jsonRpc.authorization) : {}),
+ ...this.getAuthHeaders(name),
...(options.headers ?? {}),
},
body: JSON.stringify({
@@ -94,10 +172,10 @@ export class KarfiaContainer extends AbstractStartedContainer {
}): Promise {
const endpoint = this.container.endpoints?.[options.endpoint];
if (endpoint === undefined) {
- throw new Error(`Endpoint not found, please define a '${options.endpoint}' endpoint to use api()`);
+ throw new Error(`Endpoint not found, please define a '${options.endpoint}' endpoint to use fetch()`);
}
- const protocol = (endpoint as any).protocol;
+ const protocol = (endpoint as ContainerEndpointHttpRest).protocol;
switch (protocol) {
default:
throw new Error(`Unsupported protocol: ${protocol} for fetch()`);
@@ -105,41 +183,19 @@ export class KarfiaContainer extends AbstractStartedContainer {
case 'HTTPS REST':
}
- const rest = endpoint as ContainerEndpointHttpRest;
- const scheme = rest.protocol.startsWith('HTTPS') ? 'https' : 'http';
-
- const hostPort = this.getMappedPort(endpoint.port);
- const hostEndpoint = `${scheme}://${this.getHost()}:${hostPort}${options.path}`;
- const headers: Record = {
- ...(rest.authorization ? this.getHttpAuthorizationHeaders(rest.authorization) : {}),
- ...(options.headers ?? {}),
- };
-
- return await fetch(hostEndpoint, {
+ const scheme = protocol.startsWith('HTTPS') ? 'https' : 'http';
+ const host = this.getHost();
+ const port = this.getMappedPort(endpoint.port);
+ return await fetch(`${scheme}://${host}:${port}${options.path}`, {
method: options.method,
- headers: headers,
+ headers: {
+ ...this.getAuthHeaders(options.endpoint),
+ ...(options.headers ?? {}),
+ },
body: options.body,
});
}
- private getHttpAuthorizationHeaders(auth: ContainerEndpointHttpAuthorization): Record {
- const type = auth.type;
- if (type === 'HttpBasic') {
- const username = this.resolveValue(auth.username);
- const password = this.resolveValue(auth.password);
- return {
- Authorization: `Basic ${Buffer.from(`${username}:${password}`).toString('base64')}`,
- };
- } else if (type === 'HttpBearer') {
- const token = this.resolveValue(auth.token);
- return {
- Authorization: `Bearer ${token}`,
- };
- } else {
- throw new Error(`Unknown authorization type: ${type}`);
- }
- }
-
private resolveValue(value: string | EnvironmentReference): string {
if (typeof value === 'string') {
return value;
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 2826a18..4ec52f4 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -177,9 +177,6 @@ importers:
specifier: ^3.22.5
version: 3.22.5
devDependencies:
- '@workspace/jest-preset':
- specifier: workspace:*
- version: link:../../workspace/jest-preset
'@workspace/tsconfig':
specifier: workspace:*
version: link:../../workspace/tsconfig
@@ -193,12 +190,15 @@ importers:
specifier: ^3.0.1
version: 3.0.1(ajv@8.12.0)
devDependencies:
+ '@workspace/jest-preset':
+ specifier: workspace:*
+ version: link:../../workspace/jest-preset
'@workspace/tsconfig':
specifier: workspace:*
version: link:../../workspace/tsconfig
json-schema-to-typescript:
- specifier: ^13.1.2
- version: 13.1.2
+ specifier: ^14.0.0
+ version: 14.0.0
packages/karfia-docker-compose:
dependencies:
@@ -295,6 +295,15 @@ packages:
'@jridgewell/trace-mapping': 0.3.25
dev: true
+ /@apidevtools/json-schema-ref-parser@11.5.5:
+ resolution: {integrity: sha512-hv/aXDILyroHioVW27etFMV+IX6FyNn41YwbeGIAt5h/7fUTQvHI5w3ols8qYAT8aQt3kzexq5ZwxFDxNHIhdQ==}
+ engines: {node: '>= 16'}
+ dependencies:
+ '@jsdevtools/ono': 7.1.3
+ '@types/json-schema': 7.0.15
+ js-yaml: 4.1.0
+ dev: true
+
/@babel/code-frame@7.24.2:
resolution: {integrity: sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==}
engines: {node: '>=6.9.0'}
@@ -625,16 +634,6 @@ packages:
resolution: {integrity: sha512-wMue2Sy4GAVTk6Ic4tJVcnfdau+gx2EnG7S+uAEe+TWJFqE4YoWN4/H8MSLj4eYJKxGg26lZwboEniNiNwZQ6Q==}
dev: false
- /@bcherny/json-schema-ref-parser@10.0.5-fork:
- resolution: {integrity: sha512-E/jKbPoca1tfUPj3iSbitDZTGnq6FUFjkH6L8U2oDwSuwK1WhnnVtCG7oFOTg/DDnyoXbQYUiUiGOibHqaGVnw==}
- engines: {node: '>= 16'}
- dependencies:
- '@jsdevtools/ono': 7.1.3
- '@types/json-schema': 7.0.15
- call-me-maybe: 1.0.2
- js-yaml: 4.1.0
- dev: true
-
/@bcoe/v8-coverage@0.2.3:
resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==}
dev: true
@@ -689,6 +688,18 @@ packages:
/@humanwhocodes/object-schema@2.0.3:
resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==}
+ /@isaacs/cliui@8.0.2:
+ resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
+ engines: {node: '>=12'}
+ dependencies:
+ string-width: 5.1.2
+ string-width-cjs: /string-width@4.2.3
+ strip-ansi: 7.1.0
+ strip-ansi-cjs: /strip-ansi@6.0.1
+ wrap-ansi: 8.1.0
+ wrap-ansi-cjs: /wrap-ansi@7.0.0
+ dev: true
+
/@istanbuljs/load-nyc-config@1.1.0:
resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==}
engines: {node: '>=8'}
@@ -978,6 +989,13 @@ packages:
'@nodelib/fs.scandir': 2.1.5
fastq: 1.17.1
+ /@pkgjs/parseargs@0.11.0:
+ resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
+ engines: {node: '>=14'}
+ requiresBuild: true
+ dev: true
+ optional: true
+
/@pkgr/core@0.1.1:
resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==}
engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
@@ -1215,13 +1233,6 @@ packages:
'@types/serve-static': 1.15.7
dev: false
- /@types/glob@7.2.0:
- resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==}
- dependencies:
- '@types/minimatch': 5.1.2
- '@types/node': 20.12.7
- dev: true
-
/@types/graceful-fs@4.1.9:
resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==}
dependencies:
@@ -1267,10 +1278,6 @@ packages:
resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==}
dev: false
- /@types/minimatch@5.1.2:
- resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==}
- dev: true
-
/@types/node@18.19.31:
resolution: {integrity: sha512-ArgCD39YpyyrtFKIqMDvjz79jto5fcI/SVUs2HwB+f0dAzq68yqOdyaSivLiLugSziTpNXLQrVb7RZFmdZzbhA==}
dependencies:
@@ -1282,8 +1289,11 @@ packages:
dependencies:
undici-types: 5.26.5
- /@types/prettier@2.7.3:
- resolution: {integrity: sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==}
+ /@types/prettier@3.0.0:
+ resolution: {integrity: sha512-mFMBfMOz8QxhYVbuINtswBp9VL2b4Y0QqYHwqLz3YbgtfAcat2Dl6Y1o4e22S/OVE6Ebl9m7wWiMT2lSbAs1wA==}
+ deprecated: This is a stub types definition. prettier provides its own type definitions, so you do not need this installed.
+ dependencies:
+ prettier: 3.2.5
dev: true
/@types/qs@6.9.15:
@@ -1868,7 +1878,6 @@ packages:
resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
dependencies:
balanced-match: 1.0.2
- dev: false
/braces@3.0.2:
resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
@@ -1936,10 +1945,6 @@ packages:
set-function-length: 1.2.2
dev: false
- /call-me-maybe@1.0.2:
- resolution: {integrity: sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==}
- dev: true
-
/callsites@3.1.0:
resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
engines: {node: '>=6'}
@@ -2191,6 +2196,11 @@ packages:
type: 2.7.2
dev: true
+ /data-uri-to-buffer@4.0.1:
+ resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==}
+ engines: {node: '>= 12'}
+ dev: true
+
/data-view-buffer@1.0.1:
resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==}
engines: {node: '>= 0.4'}
@@ -2363,6 +2373,10 @@ packages:
dependencies:
esutils: 2.0.3
+ /eastasianwidth@0.2.0:
+ resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
+ dev: true
+
/electron-to-chromium@1.4.744:
resolution: {integrity: sha512-nAGcF0yeKKfrP13LMFr5U1eghfFSvFLg302VUFzWlcjPOnUYd52yU5x6PBYrujhNbc4jYmZFrGZFK+xasaEzVA==}
dev: true
@@ -2380,6 +2394,10 @@ packages:
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
dev: true
+ /emoji-regex@9.2.2:
+ resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
+ dev: true
+
/end-of-stream@1.4.4:
resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==}
dependencies:
@@ -2856,6 +2874,14 @@ packages:
bser: 2.1.1
dev: true
+ /fetch-blob@3.2.0:
+ resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==}
+ engines: {node: ^12.20 || >= 14.13}
+ dependencies:
+ node-domexception: 1.0.0
+ web-streams-polyfill: 3.3.3
+ dev: true
+
/file-entry-cache@6.0.1:
resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
engines: {node: ^10.12.0 || >=12.0.0}
@@ -2900,6 +2926,21 @@ packages:
is-callable: 1.2.7
dev: false
+ /foreground-child@3.1.1:
+ resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==}
+ engines: {node: '>=14'}
+ dependencies:
+ cross-spawn: 7.0.3
+ signal-exit: 4.1.0
+ dev: true
+
+ /formdata-polyfill@4.0.10:
+ resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==}
+ engines: {node: '>=12.20.0'}
+ dependencies:
+ fetch-blob: 3.2.0
+ dev: true
+
/fresh@0.5.2:
resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==}
engines: {node: '>= 0.6'}
@@ -2973,11 +3014,6 @@ packages:
engines: {node: '>=8'}
dev: false
- /get-stdin@8.0.0:
- resolution: {integrity: sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==}
- engines: {node: '>=10'}
- dev: true
-
/get-stdin@9.0.0:
resolution: {integrity: sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==}
engines: {node: '>=12'}
@@ -3019,14 +3055,16 @@ packages:
dependencies:
is-glob: 4.0.3
- /glob-promise@4.2.2(glob@7.2.3):
- resolution: {integrity: sha512-xcUzJ8NWN5bktoTIX7eOclO1Npxd/dyVqUJxlLIDasT4C7KZyqlPIwkdJ0Ypiy3p2ZKahTjK4M9uC3sNSfNMzw==}
- engines: {node: '>=12'}
- peerDependencies:
- glob: ^7.1.6
+ /glob@10.3.12:
+ resolution: {integrity: sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==}
+ engines: {node: '>=16 || 14 >=14.17'}
+ hasBin: true
dependencies:
- '@types/glob': 7.2.0
- glob: 7.2.3
+ foreground-child: 3.1.1
+ jackspeak: 2.3.6
+ minimatch: 9.0.4
+ minipass: 7.0.4
+ path-scurry: 1.10.2
dev: true
/glob@7.2.3:
@@ -3482,6 +3520,15 @@ packages:
istanbul-lib-report: 3.0.1
dev: true
+ /jackspeak@2.3.6:
+ resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==}
+ engines: {node: '>=14'}
+ dependencies:
+ '@isaacs/cliui': 8.0.2
+ optionalDependencies:
+ '@pkgjs/parseargs': 0.11.0
+ dev: true
+
/jest-changed-files@29.7.0:
resolution: {integrity: sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
@@ -3923,25 +3970,25 @@ packages:
resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==}
dev: true
- /json-schema-to-typescript@13.1.2:
- resolution: {integrity: sha512-17G+mjx4nunvOpkPvcz7fdwUwYCEwyH8vR3Ym3rFiQ8uzAL3go+c1306Kk7iGRk8HuXBXqy+JJJmpYl0cvOllw==}
- engines: {node: '>=12.0.0'}
+ /json-schema-to-typescript@14.0.0:
+ resolution: {integrity: sha512-y/Pj93Ggu69LyRPxqpe16t8LA/5ZyJVoqmUf+o+2cBG33dH/GsDn5oDZD3EiOTkHXjVuZg4qWnWzTtS2LcoeiA==}
+ engines: {node: '>=16.0.0'}
hasBin: true
dependencies:
- '@bcherny/json-schema-ref-parser': 10.0.5-fork
+ '@apidevtools/json-schema-ref-parser': 11.5.5
'@types/json-schema': 7.0.15
'@types/lodash': 4.17.0
- '@types/prettier': 2.7.3
+ '@types/prettier': 3.0.0
cli-color: 2.0.4
- get-stdin: 8.0.0
- glob: 7.2.3
- glob-promise: 4.2.2(glob@7.2.3)
+ glob: 10.3.12
is-glob: 4.0.3
+ js-yaml: 4.1.0
lodash: 4.17.21
minimist: 1.2.8
- mkdirp: 1.0.4
+ mkdirp: 3.0.1
mz: 2.7.0
- prettier: 2.8.8
+ node-fetch: 3.3.2
+ prettier: 3.2.5
dev: true
/json-schema-traverse@0.4.1:
@@ -4095,6 +4142,11 @@ packages:
wrap-ansi: 9.0.0
dev: true
+ /lru-cache@10.2.0:
+ resolution: {integrity: sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==}
+ engines: {node: 14 || >=16.14}
+ dev: true
+
/lru-cache@5.1.1:
resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
dependencies:
@@ -4220,11 +4272,15 @@ packages:
engines: {node: '>=16 || 14 >=14.17'}
dependencies:
brace-expansion: 2.0.1
- dev: false
/minimist@1.2.8:
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
+ /minipass@7.0.4:
+ resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==}
+ engines: {node: '>=16 || 14 >=14.17'}
+ dev: true
+
/mkdirp-classic@0.5.3:
resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==}
dev: false
@@ -4233,6 +4289,13 @@ packages:
resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==}
engines: {node: '>=10'}
hasBin: true
+ dev: false
+
+ /mkdirp@3.0.1:
+ resolution: {integrity: sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==}
+ engines: {node: '>=10'}
+ hasBin: true
+ dev: true
/ms@2.1.2:
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
@@ -4267,6 +4330,11 @@ packages:
resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==}
dev: true
+ /node-domexception@1.0.0:
+ resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
+ engines: {node: '>=10.5.0'}
+ dev: true
+
/node-fetch-native@1.6.4:
resolution: {integrity: sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==}
dev: false
@@ -4283,6 +4351,15 @@ packages:
whatwg-url: 5.0.0
dev: false
+ /node-fetch@3.3.2:
+ resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ dependencies:
+ data-uri-to-buffer: 4.0.1
+ fetch-blob: 3.2.0
+ formdata-polyfill: 4.0.10
+ dev: true
+
/node-int64@0.4.0:
resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==}
dev: true
@@ -4489,6 +4566,14 @@ packages:
/path-parse@1.0.7:
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
+ /path-scurry@1.10.2:
+ resolution: {integrity: sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==}
+ engines: {node: '>=16 || 14 >=14.17'}
+ dependencies:
+ lru-cache: 10.2.0
+ minipass: 7.0.4
+ dev: true
+
/path-type@4.0.0:
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
engines: {node: '>=8'}
@@ -4601,12 +4686,6 @@ packages:
prettier: 3.2.5
dev: false
- /prettier@2.8.8:
- resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==}
- engines: {node: '>=10.13.0'}
- hasBin: true
- dev: true
-
/prettier@3.2.5:
resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==}
engines: {node: '>=14'}
@@ -5034,6 +5113,15 @@ packages:
strip-ansi: 6.0.1
dev: true
+ /string-width@5.1.2:
+ resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
+ engines: {node: '>=12'}
+ dependencies:
+ eastasianwidth: 0.2.0
+ emoji-regex: 9.2.2
+ strip-ansi: 7.1.0
+ dev: true
+
/string-width@7.1.0:
resolution: {integrity: sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==}
engines: {node: '>=18'}
@@ -5555,6 +5643,11 @@ packages:
makeerror: 1.0.12
dev: true
+ /web-streams-polyfill@3.3.3:
+ resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==}
+ engines: {node: '>= 8'}
+ dev: true
+
/webidl-conversions@3.0.1:
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
dev: false
@@ -5603,6 +5696,15 @@ packages:
strip-ansi: 6.0.1
dev: true
+ /wrap-ansi@8.1.0:
+ resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
+ engines: {node: '>=12'}
+ dependencies:
+ ansi-styles: 6.2.1
+ string-width: 5.1.2
+ strip-ansi: 7.1.0
+ dev: true
+
/wrap-ansi@9.0.0:
resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==}
engines: {node: '>=18'}