mirror of
https://github.com/twentyhq/twenty.git
synced 2025-01-03 17:53:58 +03:00
feat: dynamic graphQL schema generation based on user workspace (#1725)
* wip: refacto and start creating custom resolver * feat: findMany & findUnique of a custom entity * feat: wip pagination * feat: initial metadata migration * feat: universal findAll with pagination * fix: clean small stuff in pagination * fix: test * fix: miss file * feat: rename custom into universal * feat: create metadata schema in default database * Multi-tenant db schemas POC fix tests and use query builders remove synchronize restore updatedAt remove unnecessary import use queryRunner fix camelcase add migrations for standard objects Multi-tenant db schemas POC fix tests and use query builders remove synchronize restore updatedAt remove unnecessary import use queryRunner fix camelcase add migrations for standard objects poc: conditional schema at runtime wip: try to create resolver in Nest.JS context fix * feat: wip add pg_graphql * feat: setup pg_graphql during database init * wip: dynamic resolver * poc: dynamic resolver and query using pg_graphql * feat: pg_graphql use ARG in Dockerfile * feat: clean findMany & findOne dynamic resolver * feat: get correct schema based on access token * fix: remove old file * fix: tests * fix: better comment * fix: e2e test not working, error format change due to yoga * remove typeorm entity generation + fix jwt + fix search_path + remove anon * fix conflict --------- Co-authored-by: Charles Bochet <charles@twenty.com> Co-authored-by: corentin <corentin@twenty.com>
This commit is contained in:
parent
485bc64b4f
commit
629bdbbf50
@ -28,7 +28,9 @@ services:
|
||||
volumes:
|
||||
- db_data:/var/lib/postgresql/data
|
||||
environment:
|
||||
POSTGRES_PASSWORD: twenty
|
||||
- POSTGRES_USER=twenty
|
||||
- POSTGRES_PASSWORD=twenty
|
||||
- POSTGRES_DB=default
|
||||
ports:
|
||||
- "5432:5432"
|
||||
volumes:
|
||||
|
@ -1,5 +1,15 @@
|
||||
FROM postgres:13.7 as postgres
|
||||
ARG PG_MAIN_VERSION=14
|
||||
|
||||
FROM postgres:${PG_MAIN_VERSION} as postgres
|
||||
|
||||
ARG PG_MAIN_VERSION
|
||||
ARG PG_GRAPHQL_VERSION=1.3.0
|
||||
ARG TARGETARCH=arm64
|
||||
|
||||
RUN apt update && apt install -y curl
|
||||
|
||||
# Install precompiled pg_graphql extensions
|
||||
RUN curl -L "https://github.com/supabase/pg_graphql/releases/download/v${PG_GRAPHQL_VERSION}/pg_graphql-v${PG_GRAPHQL_VERSION}-pg${PG_MAIN_VERSION}-${TARGETARCH}-linux-gnu.deb" -o pg_graphql.deb
|
||||
RUN dpkg --install pg_graphql.deb
|
||||
|
||||
COPY init.sql /docker-entrypoint-initdb.d/
|
||||
|
@ -1,25 +1,46 @@
|
||||
-- Create the default database for development
|
||||
CREATE DATABASE "default";
|
||||
|
||||
-- Create the tests database for e2e testing
|
||||
CREATE DATABASE "test";
|
||||
|
||||
-- Create a twenty user
|
||||
CREATE USER twenty PASSWORD 'twenty';
|
||||
ALTER USER twenty CREATEDB;
|
||||
-- Inflect names for pg_graphql
|
||||
COMMENT ON SCHEMA "public" IS '@graphql({"inflect_names": true})';
|
||||
|
||||
-- Connect to the "default" database
|
||||
\c "default";
|
||||
|
||||
-- Create extension
|
||||
CREATE EXTENSION IF NOT EXISTS pg_graphql;
|
||||
|
||||
-- Create the metadata schema if it doesn't exist
|
||||
CREATE SCHEMA IF NOT EXISTS "metadata";
|
||||
GRANT ALL ON SCHEMA metadata TO twenty;
|
||||
|
||||
-- Create extension uuid-ossp
|
||||
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
||||
|
||||
-- Connect to the "default" database
|
||||
-- Create GraphQL Entrypoint
|
||||
create function graphql(
|
||||
"operationName" text default null,
|
||||
query text default null,
|
||||
variables jsonb default null,
|
||||
extensions jsonb default null
|
||||
)
|
||||
returns jsonb
|
||||
language sql
|
||||
as $$
|
||||
select graphql.resolve(
|
||||
query := query,
|
||||
variables := coalesce(variables, '{}'),
|
||||
"operationName" := "operationName",
|
||||
extensions := extensions
|
||||
);
|
||||
$$;
|
||||
|
||||
-- Create the tests database for e2e testing
|
||||
CREATE DATABASE "test";
|
||||
|
||||
-- Connect to the "test" database for e2e testing
|
||||
\c "test";
|
||||
|
||||
-- Create the metadata schema if it doesn't exist
|
||||
CREATE SCHEMA IF NOT EXISTS "metadata";
|
||||
GRANT ALL ON SCHEMA metadata TO twenty;
|
||||
|
||||
-- Create extension uuid-ossp
|
||||
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
||||
|
@ -6,6 +6,7 @@
|
||||
"private": true,
|
||||
"license": "UNLICENSED",
|
||||
"scripts": {
|
||||
"postinstall": "patch-package",
|
||||
"prebuild": "rimraf dist",
|
||||
"build": "nest build",
|
||||
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
|
||||
@ -35,11 +36,12 @@
|
||||
"@aws-sdk/credential-providers": "^3.363.0",
|
||||
"@casl/ability": "^6.5.0",
|
||||
"@casl/prisma": "1.4.0",
|
||||
"@graphql-yoga/nestjs": "^2.1.0",
|
||||
"@nestjs/apollo": "^11.0.5",
|
||||
"@nestjs/common": "^9.0.0",
|
||||
"@nestjs/config": "^2.3.2",
|
||||
"@nestjs/core": "^9.0.0",
|
||||
"@nestjs/graphql": "^11.0.6",
|
||||
"@nestjs/graphql": "^12.0.8",
|
||||
"@nestjs/jwt": "^10.0.3",
|
||||
"@nestjs/passport": "^9.0.3",
|
||||
"@nestjs/platform-express": "^9.0.0",
|
||||
@ -62,12 +64,15 @@
|
||||
"class-validator": "^0.14.0",
|
||||
"date-fns": "^2.30.0",
|
||||
"file-type": "16.5.4",
|
||||
"graphql": "^16.7.1",
|
||||
"graphql": "^16.8.0",
|
||||
"graphql-fields": "^2.0.3",
|
||||
"graphql-type-json": "^0.3.2",
|
||||
"graphql-upload": "^13.0.0",
|
||||
"graphql-yoga": "^4.0.4",
|
||||
"jest-mock-extended": "^3.0.4",
|
||||
"jsonwebtoken": "^9.0.0",
|
||||
"lodash.camelcase": "^4.3.0",
|
||||
"lodash.isempty": "^4.4.0",
|
||||
"lodash.isobject": "^3.0.2",
|
||||
"lodash.kebabcase": "^4.1.1",
|
||||
"lodash.merge": "^4.6.2",
|
||||
@ -77,7 +82,9 @@
|
||||
"passport-google-oauth20": "^2.0.0",
|
||||
"passport-jwt": "^4.0.1",
|
||||
"passport-local": "^1.0.0",
|
||||
"patch-package": "^8.0.0",
|
||||
"pg": "^8.11.3",
|
||||
"postinstall-postinstall": "^2.1.0",
|
||||
"prisma-graphql-type-decimal": "^3.0.0",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rimraf": "^3.0.2",
|
||||
@ -96,8 +103,10 @@
|
||||
"@types/bytes": "^3.1.1",
|
||||
"@types/date-fns": "^2.6.0",
|
||||
"@types/express": "^4.17.13",
|
||||
"@types/graphql-fields": "^1.3.6",
|
||||
"@types/graphql-upload": "^8.0.12",
|
||||
"@types/jest": "28.1.8",
|
||||
"@types/lodash.isempty": "^4.4.7",
|
||||
"@types/lodash.isobject": "^3.0.7",
|
||||
"@types/lodash.kebabcase": "^4.1.7",
|
||||
"@types/lodash.snakecase": "^4.1.7",
|
||||
@ -127,6 +136,9 @@
|
||||
"tsconfig-paths": "4.1.0",
|
||||
"typescript": "^4.9.4"
|
||||
},
|
||||
"resolutions": {
|
||||
"graphql": "16.8.0"
|
||||
},
|
||||
"prisma": {
|
||||
"schema": "src/database/schema.prisma",
|
||||
"seed": "ts-node src/database/seeds/index.ts"
|
||||
|
329
server/patches/@graphql-yoga+nestjs+2.1.0.patch
Normal file
329
server/patches/@graphql-yoga+nestjs+2.1.0.patch
Normal file
@ -0,0 +1,329 @@
|
||||
diff --git a/node_modules/@graphql-yoga/nestjs/dist/cjs/index.js b/node_modules/@graphql-yoga/nestjs/dist/cjs/index.js
|
||||
index 1684394..8a92c3c 100644
|
||||
--- a/node_modules/@graphql-yoga/nestjs/dist/cjs/index.js
|
||||
+++ b/node_modules/@graphql-yoga/nestjs/dist/cjs/index.js
|
||||
@@ -5,6 +5,7 @@ const tslib_1 = require("tslib");
|
||||
const graphql_1 = require("graphql");
|
||||
const graphql_yoga_1 = require("graphql-yoga");
|
||||
const common_1 = require("@nestjs/common");
|
||||
+const schema_1 = require("@graphql-tools/schema");
|
||||
const graphql_2 = require("@nestjs/graphql");
|
||||
class AbstractYogaDriver extends graphql_2.AbstractGraphQLDriver {
|
||||
async start(options) {
|
||||
@@ -27,7 +28,7 @@ class AbstractYogaDriver extends graphql_2.AbstractGraphQLDriver {
|
||||
async stop() {
|
||||
// noop
|
||||
}
|
||||
- registerExpress(options, { preStartHook } = {}) {
|
||||
+ registerExpress({ conditionalSchema, ...options }, { preStartHook } = {}) {
|
||||
const app = this.httpAdapterHost.httpAdapter.getInstance();
|
||||
preStartHook?.(app);
|
||||
// nest's logger doesnt have the info method
|
||||
@@ -42,6 +43,21 @@ class AbstractYogaDriver extends graphql_2.AbstractGraphQLDriver {
|
||||
}
|
||||
const yoga = (0, graphql_yoga_1.createYoga)({
|
||||
...options,
|
||||
+ schema: async (request) => {
|
||||
+ const schemas = [];
|
||||
+ if (options.schema) {
|
||||
+ schemas.push(options.schema);
|
||||
+ }
|
||||
+ if (conditionalSchema) {
|
||||
+ const conditionalSchemaResult = typeof conditionalSchema === 'function' ? await conditionalSchema(request) : await conditionalSchema;
|
||||
+ if (conditionalSchemaResult) {
|
||||
+ schemas.push(conditionalSchemaResult);
|
||||
+ }
|
||||
+ }
|
||||
+ return (0, schema_1.mergeSchemas)({
|
||||
+ schemas,
|
||||
+ });
|
||||
+ },
|
||||
graphqlEndpoint: options.path,
|
||||
// disable logging by default
|
||||
// however, if `true` use nest logger
|
||||
@@ -54,11 +70,26 @@ class AbstractYogaDriver extends graphql_2.AbstractGraphQLDriver {
|
||||
this.yoga = yoga;
|
||||
app.use(yoga.graphqlEndpoint, (req, res) => yoga(req, res, { req, res }));
|
||||
}
|
||||
- registerFastify(options, { preStartHook } = {}) {
|
||||
+ registerFastify({ conditionalSchema, ...options }, { preStartHook } = {}) {
|
||||
const app = this.httpAdapterHost.httpAdapter.getInstance();
|
||||
preStartHook?.(app);
|
||||
const yoga = (0, graphql_yoga_1.createYoga)({
|
||||
...options,
|
||||
+ schema: async (request) => {
|
||||
+ const schemas = [];
|
||||
+ if (options.schema) {
|
||||
+ schemas.push(options.schema);
|
||||
+ }
|
||||
+ if (conditionalSchema) {
|
||||
+ const conditionalSchemaResult = typeof conditionalSchema === 'function' ? await conditionalSchema(request) : await conditionalSchema;
|
||||
+ if (conditionalSchemaResult) {
|
||||
+ schemas.push(conditionalSchemaResult);
|
||||
+ }
|
||||
+ }
|
||||
+ return (0, schema_1.mergeSchemas)({
|
||||
+ schemas,
|
||||
+ });
|
||||
+ },
|
||||
graphqlEndpoint: options.path,
|
||||
// disable logging by default
|
||||
// however, if `true` use fastify logger
|
||||
diff --git a/node_modules/@graphql-yoga/nestjs/dist/esm/index.js b/node_modules/@graphql-yoga/nestjs/dist/esm/index.js
|
||||
index 7068c51..8ba5d2a 100644
|
||||
--- a/node_modules/@graphql-yoga/nestjs/dist/esm/index.js
|
||||
+++ b/node_modules/@graphql-yoga/nestjs/dist/esm/index.js
|
||||
@@ -2,6 +2,7 @@ import { __decorate } from "tslib";
|
||||
import { printSchema } from 'graphql';
|
||||
import { createYoga, filter, pipe } from 'graphql-yoga';
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
+import { mergeSchemas } from '@graphql-tools/schema';
|
||||
import { AbstractGraphQLDriver, GqlSubscriptionService, } from '@nestjs/graphql';
|
||||
export class AbstractYogaDriver extends AbstractGraphQLDriver {
|
||||
async start(options) {
|
||||
@@ -24,7 +25,7 @@ export class AbstractYogaDriver extends AbstractGraphQLDriver {
|
||||
async stop() {
|
||||
// noop
|
||||
}
|
||||
- registerExpress(options, { preStartHook } = {}) {
|
||||
+ registerExpress({ conditionalSchema, ...options }, { preStartHook } = {}) {
|
||||
const app = this.httpAdapterHost.httpAdapter.getInstance();
|
||||
preStartHook?.(app);
|
||||
// nest's logger doesnt have the info method
|
||||
@@ -39,6 +40,21 @@ export class AbstractYogaDriver extends AbstractGraphQLDriver {
|
||||
}
|
||||
const yoga = createYoga({
|
||||
...options,
|
||||
+ schema: async (request) => {
|
||||
+ const schemas = [];
|
||||
+ if (options.schema) {
|
||||
+ schemas.push(options.schema);
|
||||
+ }
|
||||
+ if (conditionalSchema) {
|
||||
+ const conditionalSchemaResult = typeof conditionalSchema === 'function' ? await conditionalSchema(request) : await conditionalSchema;
|
||||
+ if (conditionalSchemaResult) {
|
||||
+ schemas.push(conditionalSchemaResult);
|
||||
+ }
|
||||
+ }
|
||||
+ return mergeSchemas({
|
||||
+ schemas,
|
||||
+ });
|
||||
+ },
|
||||
graphqlEndpoint: options.path,
|
||||
// disable logging by default
|
||||
// however, if `true` use nest logger
|
||||
@@ -51,11 +67,26 @@ export class AbstractYogaDriver extends AbstractGraphQLDriver {
|
||||
this.yoga = yoga;
|
||||
app.use(yoga.graphqlEndpoint, (req, res) => yoga(req, res, { req, res }));
|
||||
}
|
||||
- registerFastify(options, { preStartHook } = {}) {
|
||||
+ registerFastify({ conditionalSchema, ...options }, { preStartHook } = {}) {
|
||||
const app = this.httpAdapterHost.httpAdapter.getInstance();
|
||||
preStartHook?.(app);
|
||||
const yoga = createYoga({
|
||||
...options,
|
||||
+ schema: async (request) => {
|
||||
+ const schemas = [];
|
||||
+ if (options.schema) {
|
||||
+ schemas.push(options.schema);
|
||||
+ }
|
||||
+ if (conditionalSchema) {
|
||||
+ const conditionalSchemaResult = typeof conditionalSchema === 'function' ? await conditionalSchema(request) : await conditionalSchema;
|
||||
+ if (conditionalSchemaResult) {
|
||||
+ schemas.push(conditionalSchemaResult);
|
||||
+ }
|
||||
+ }
|
||||
+ return mergeSchemas({
|
||||
+ schemas,
|
||||
+ });
|
||||
+ },
|
||||
graphqlEndpoint: options.path,
|
||||
// disable logging by default
|
||||
// however, if `true` use fastify logger
|
||||
diff --git a/node_modules/@graphql-yoga/nestjs/dist/typings/index.d.cts b/node_modules/@graphql-yoga/nestjs/dist/typings/index.d.cts
|
||||
index 2c6a965..fd86dac 100644
|
||||
--- a/node_modules/@graphql-yoga/nestjs/dist/typings/index.d.cts
|
||||
+++ b/node_modules/@graphql-yoga/nestjs/dist/typings/index.d.cts
|
||||
@@ -1,7 +1,8 @@
|
||||
import type { Express, Request as ExpressRequest, Response as ExpressResponse } from 'express';
|
||||
import type { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify';
|
||||
-import { YogaServerInstance, YogaServerOptions } from 'graphql-yoga';
|
||||
+import { YogaServerInstance, YogaServerOptions, GraphQLSchemaWithContext, PromiseOrValue, YogaInitialContext } from 'graphql-yoga';
|
||||
import { AbstractGraphQLDriver, GqlModuleOptions, SubscriptionConfig } from '@nestjs/graphql';
|
||||
+export type YogaSchemaDefinition<TContext> = PromiseOrValue<GraphQLSchemaWithContext<TContext>> | ((context: TContext & YogaInitialContext) => PromiseOrValue<GraphQLSchemaWithContext<TContext>>);
|
||||
export type YogaDriverPlatform = 'express' | 'fastify';
|
||||
export type YogaDriverServerContext<Platform extends YogaDriverPlatform> = Platform extends 'fastify' ? {
|
||||
req: FastifyRequest;
|
||||
@@ -10,7 +11,9 @@ export type YogaDriverServerContext<Platform extends YogaDriverPlatform> = Platf
|
||||
req: ExpressRequest;
|
||||
res: ExpressResponse;
|
||||
};
|
||||
-export type YogaDriverServerOptions<Platform extends YogaDriverPlatform> = Omit<YogaServerOptions<YogaDriverServerContext<Platform>, never>, 'context' | 'schema'>;
|
||||
+export type YogaDriverServerOptions<Platform extends YogaDriverPlatform> = Omit<YogaServerOptions<YogaDriverServerContext<Platform>, never>, 'context' | 'schema'> & {
|
||||
+ conditionalSchema?: YogaSchemaDefinition<YogaDriverServerContext<Platform>> | undefined;
|
||||
+};
|
||||
export type YogaDriverServerInstance<Platform extends YogaDriverPlatform> = YogaServerInstance<YogaDriverServerContext<Platform>, never>;
|
||||
export type YogaDriverConfig<Platform extends YogaDriverPlatform = 'express'> = GqlModuleOptions & YogaDriverServerOptions<Platform> & {
|
||||
/**
|
||||
@@ -26,10 +29,10 @@ export declare abstract class AbstractYogaDriver<Platform extends YogaDriverPlat
|
||||
protected yoga: YogaDriverServerInstance<Platform>;
|
||||
start(options: YogaDriverConfig<Platform>): Promise<void>;
|
||||
stop(): Promise<void>;
|
||||
- protected registerExpress(options: YogaDriverConfig<'express'>, { preStartHook }?: {
|
||||
+ protected registerExpress({ conditionalSchema, ...options }: YogaDriverConfig<'express'>, { preStartHook }?: {
|
||||
preStartHook?: (app: Express) => void;
|
||||
}): void;
|
||||
- protected registerFastify(options: YogaDriverConfig<'fastify'>, { preStartHook }?: {
|
||||
+ protected registerFastify({ conditionalSchema, ...options }: YogaDriverConfig<'fastify'>, { preStartHook }?: {
|
||||
preStartHook?: (app: FastifyInstance) => void;
|
||||
}): void;
|
||||
subscriptionWithFilter<TPayload, TVariables, TContext>(instanceRef: unknown, filterFn: (payload: TPayload, variables: TVariables, context: TContext) => boolean | Promise<boolean>, createSubscribeContext: Function): (args_0: TPayload, args_1: TVariables, args_2: TContext) => Promise<import("graphql-yoga").Repeater<TPayload, void, unknown>>;
|
||||
diff --git a/node_modules/@graphql-yoga/nestjs/dist/typings/index.d.ts b/node_modules/@graphql-yoga/nestjs/dist/typings/index.d.ts
|
||||
index 2c6a965..fd86dac 100644
|
||||
--- a/node_modules/@graphql-yoga/nestjs/dist/typings/index.d.ts
|
||||
+++ b/node_modules/@graphql-yoga/nestjs/dist/typings/index.d.ts
|
||||
@@ -1,7 +1,8 @@
|
||||
import type { Express, Request as ExpressRequest, Response as ExpressResponse } from 'express';
|
||||
import type { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify';
|
||||
-import { YogaServerInstance, YogaServerOptions } from 'graphql-yoga';
|
||||
+import { YogaServerInstance, YogaServerOptions, GraphQLSchemaWithContext, PromiseOrValue, YogaInitialContext } from 'graphql-yoga';
|
||||
import { AbstractGraphQLDriver, GqlModuleOptions, SubscriptionConfig } from '@nestjs/graphql';
|
||||
+export type YogaSchemaDefinition<TContext> = PromiseOrValue<GraphQLSchemaWithContext<TContext>> | ((context: TContext & YogaInitialContext) => PromiseOrValue<GraphQLSchemaWithContext<TContext>>);
|
||||
export type YogaDriverPlatform = 'express' | 'fastify';
|
||||
export type YogaDriverServerContext<Platform extends YogaDriverPlatform> = Platform extends 'fastify' ? {
|
||||
req: FastifyRequest;
|
||||
@@ -10,7 +11,9 @@ export type YogaDriverServerContext<Platform extends YogaDriverPlatform> = Platf
|
||||
req: ExpressRequest;
|
||||
res: ExpressResponse;
|
||||
};
|
||||
-export type YogaDriverServerOptions<Platform extends YogaDriverPlatform> = Omit<YogaServerOptions<YogaDriverServerContext<Platform>, never>, 'context' | 'schema'>;
|
||||
+export type YogaDriverServerOptions<Platform extends YogaDriverPlatform> = Omit<YogaServerOptions<YogaDriverServerContext<Platform>, never>, 'context' | 'schema'> & {
|
||||
+ conditionalSchema?: YogaSchemaDefinition<YogaDriverServerContext<Platform>> | undefined;
|
||||
+};
|
||||
export type YogaDriverServerInstance<Platform extends YogaDriverPlatform> = YogaServerInstance<YogaDriverServerContext<Platform>, never>;
|
||||
export type YogaDriverConfig<Platform extends YogaDriverPlatform = 'express'> = GqlModuleOptions & YogaDriverServerOptions<Platform> & {
|
||||
/**
|
||||
@@ -26,10 +29,10 @@ export declare abstract class AbstractYogaDriver<Platform extends YogaDriverPlat
|
||||
protected yoga: YogaDriverServerInstance<Platform>;
|
||||
start(options: YogaDriverConfig<Platform>): Promise<void>;
|
||||
stop(): Promise<void>;
|
||||
- protected registerExpress(options: YogaDriverConfig<'express'>, { preStartHook }?: {
|
||||
+ protected registerExpress({ conditionalSchema, ...options }: YogaDriverConfig<'express'>, { preStartHook }?: {
|
||||
preStartHook?: (app: Express) => void;
|
||||
}): void;
|
||||
- protected registerFastify(options: YogaDriverConfig<'fastify'>, { preStartHook }?: {
|
||||
+ protected registerFastify({ conditionalSchema, ...options }: YogaDriverConfig<'fastify'>, { preStartHook }?: {
|
||||
preStartHook?: (app: FastifyInstance) => void;
|
||||
}): void;
|
||||
subscriptionWithFilter<TPayload, TVariables, TContext>(instanceRef: unknown, filterFn: (payload: TPayload, variables: TVariables, context: TContext) => boolean | Promise<boolean>, createSubscribeContext: Function): (args_0: TPayload, args_1: TVariables, args_2: TContext) => Promise<import("graphql-yoga").Repeater<TPayload, void, unknown>>;
|
||||
diff --git a/node_modules/@graphql-yoga/nestjs/src/index.ts b/node_modules/@graphql-yoga/nestjs/src/index.ts
|
||||
index ce142f6..cda4117 100644
|
||||
--- a/node_modules/@graphql-yoga/nestjs/src/index.ts
|
||||
+++ b/node_modules/@graphql-yoga/nestjs/src/index.ts
|
||||
@@ -1,9 +1,10 @@
|
||||
import type { Express, Request as ExpressRequest, Response as ExpressResponse } from 'express';
|
||||
import type { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify';
|
||||
-import { printSchema } from 'graphql';
|
||||
-import { createYoga, filter, pipe, YogaServerInstance, YogaServerOptions } from 'graphql-yoga';
|
||||
+import { GraphQLSchema, printSchema } from 'graphql';
|
||||
+import { createYoga, filter, pipe, YogaServerInstance, YogaServerOptions, GraphQLSchemaWithContext, PromiseOrValue, YogaInitialContext } from 'graphql-yoga';
|
||||
import type { ExecutionParams } from 'subscriptions-transport-ws';
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
+import { mergeSchemas } from '@graphql-tools/schema';
|
||||
import {
|
||||
AbstractGraphQLDriver,
|
||||
GqlModuleOptions,
|
||||
@@ -11,6 +12,12 @@ import {
|
||||
SubscriptionConfig,
|
||||
} from '@nestjs/graphql';
|
||||
|
||||
+export type YogaSchemaDefinition<TContext> =
|
||||
+ | PromiseOrValue<GraphQLSchemaWithContext<TContext>>
|
||||
+ | ((
|
||||
+ context: TContext & YogaInitialContext,
|
||||
+ ) => PromiseOrValue<GraphQLSchemaWithContext<TContext>>);
|
||||
+
|
||||
export type YogaDriverPlatform = 'express' | 'fastify';
|
||||
|
||||
export type YogaDriverServerContext<Platform extends YogaDriverPlatform> =
|
||||
@@ -27,7 +34,9 @@ export type YogaDriverServerContext<Platform extends YogaDriverPlatform> =
|
||||
export type YogaDriverServerOptions<Platform extends YogaDriverPlatform> = Omit<
|
||||
YogaServerOptions<YogaDriverServerContext<Platform>, never>,
|
||||
'context' | 'schema'
|
||||
->;
|
||||
+> & {
|
||||
+ conditionalSchema?: YogaSchemaDefinition<YogaDriverServerContext<Platform>> | undefined;
|
||||
+};
|
||||
|
||||
export type YogaDriverServerInstance<Platform extends YogaDriverPlatform> = YogaServerInstance<
|
||||
YogaDriverServerContext<Platform>,
|
||||
@@ -78,7 +87,7 @@ export abstract class AbstractYogaDriver<
|
||||
}
|
||||
|
||||
protected registerExpress(
|
||||
- options: YogaDriverConfig<'express'>,
|
||||
+ { conditionalSchema, ...options}: YogaDriverConfig<'express'>,
|
||||
{ preStartHook }: { preStartHook?: (app: Express) => void } = {},
|
||||
) {
|
||||
const app: Express = this.httpAdapterHost.httpAdapter.getInstance();
|
||||
@@ -98,6 +107,25 @@ export abstract class AbstractYogaDriver<
|
||||
|
||||
const yoga = createYoga<YogaDriverServerContext<'express'>>({
|
||||
...options,
|
||||
+ schema: async request => {
|
||||
+ const schemas: GraphQLSchema[] = [];
|
||||
+
|
||||
+ if (options.schema) {
|
||||
+ schemas.push(options.schema);
|
||||
+ }
|
||||
+
|
||||
+ if (conditionalSchema) {
|
||||
+ const conditionalSchemaResult = typeof conditionalSchema === 'function' ? await conditionalSchema(request) : await conditionalSchema;
|
||||
+
|
||||
+ if (conditionalSchemaResult) {
|
||||
+ schemas.push(conditionalSchemaResult);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return mergeSchemas({
|
||||
+ schemas,
|
||||
+ });
|
||||
+ },
|
||||
graphqlEndpoint: options.path,
|
||||
// disable logging by default
|
||||
// however, if `true` use nest logger
|
||||
@@ -115,7 +143,7 @@ export abstract class AbstractYogaDriver<
|
||||
}
|
||||
|
||||
protected registerFastify(
|
||||
- options: YogaDriverConfig<'fastify'>,
|
||||
+ { conditionalSchema, ...options }: YogaDriverConfig<'fastify'>,
|
||||
{ preStartHook }: { preStartHook?: (app: FastifyInstance) => void } = {},
|
||||
) {
|
||||
const app: FastifyInstance = this.httpAdapterHost.httpAdapter.getInstance();
|
||||
@@ -124,6 +152,25 @@ export abstract class AbstractYogaDriver<
|
||||
|
||||
const yoga = createYoga<YogaDriverServerContext<'fastify'>>({
|
||||
...options,
|
||||
+ schema: async request => {
|
||||
+ const schemas: GraphQLSchema[] = [];
|
||||
+
|
||||
+ if (options.schema) {
|
||||
+ schemas.push(options.schema);
|
||||
+ }
|
||||
+
|
||||
+ if (conditionalSchema) {
|
||||
+ const conditionalSchemaResult = typeof conditionalSchema === 'function' ? await conditionalSchema(request) : await conditionalSchema;
|
||||
+
|
||||
+ if (conditionalSchemaResult) {
|
||||
+ schemas.push(conditionalSchemaResult);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return mergeSchemas({
|
||||
+ schemas,
|
||||
+ });
|
||||
+ },
|
||||
graphqlEndpoint: options.path,
|
||||
// disable logging by default
|
||||
// however, if `true` use fastify logger
|
@ -1,11 +1,13 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { GraphQLModule } from '@nestjs/graphql';
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
|
||||
import { ModuleRef } from '@nestjs/core';
|
||||
|
||||
import { ApolloServerPluginLandingPageLocalDefault } from '@apollo/server/plugin/landingPage/default';
|
||||
import { GraphQLError } from 'graphql';
|
||||
import { YogaDriver, YogaDriverConfig } from '@graphql-yoga/nestjs';
|
||||
import GraphQLJSON from 'graphql-type-json';
|
||||
import { GraphQLError, GraphQLSchema } from 'graphql';
|
||||
import { ExtractJwt } from 'passport-jwt';
|
||||
import { TokenExpiredError, verify } from 'jsonwebtoken';
|
||||
|
||||
import { AppService } from './app.service';
|
||||
|
||||
@ -15,24 +17,77 @@ import { PrismaModule } from './database/prisma.module';
|
||||
import { HealthModule } from './health/health.module';
|
||||
import { AbilityModule } from './ability/ability.module';
|
||||
import { TenantModule } from './tenant/tenant.module';
|
||||
import { SchemaGenerationService } from './tenant/schema-generation/schema-generation.service';
|
||||
import { EnvironmentService } from './integrations/environment/environment.service';
|
||||
import {
|
||||
JwtAuthStrategy,
|
||||
JwtPayload,
|
||||
} from './core/auth/strategies/jwt.auth.strategy';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
ConfigModule.forRoot({
|
||||
isGlobal: true,
|
||||
}),
|
||||
GraphQLModule.forRoot<ApolloDriverConfig>({
|
||||
playground: false,
|
||||
GraphQLModule.forRoot<YogaDriverConfig>({
|
||||
context: ({ req }) => ({ req }),
|
||||
driver: ApolloDriver,
|
||||
driver: YogaDriver,
|
||||
autoSchemaFile: true,
|
||||
resolvers: { JSON: GraphQLJSON },
|
||||
plugins: [ApolloServerPluginLandingPageLocalDefault()],
|
||||
formatError: (error: GraphQLError) => {
|
||||
error.extensions.stacktrace = undefined;
|
||||
return error;
|
||||
conditionalSchema: async (request) => {
|
||||
try {
|
||||
// Get the SchemaGenerationService from the AppModule
|
||||
const service = AppModule.moduleRef.get(SchemaGenerationService, {
|
||||
strict: false,
|
||||
});
|
||||
|
||||
// Get the JwtAuthStrategy from the AppModule
|
||||
const jwtStrategy = AppModule.moduleRef.get(JwtAuthStrategy, {
|
||||
strict: false,
|
||||
});
|
||||
|
||||
// Get the EnvironmentService from the AppModule
|
||||
const environmentService = AppModule.moduleRef.get(
|
||||
EnvironmentService,
|
||||
{
|
||||
strict: false,
|
||||
},
|
||||
);
|
||||
|
||||
// Extract JWT from the request
|
||||
const token = ExtractJwt.fromAuthHeaderAsBearerToken()(request.req);
|
||||
|
||||
// If there is no token, return an empty schema
|
||||
if (!token) {
|
||||
return new GraphQLSchema({});
|
||||
}
|
||||
|
||||
// Verify and decode JWT
|
||||
const decoded = verify(
|
||||
token,
|
||||
environmentService.getAccessTokenSecret(),
|
||||
);
|
||||
|
||||
// Validate JWT
|
||||
const { workspace } = await jwtStrategy.validate(
|
||||
decoded as JwtPayload,
|
||||
);
|
||||
|
||||
const conditionalSchema = await service.generateSchema(workspace.id);
|
||||
|
||||
return conditionalSchema;
|
||||
} catch (error) {
|
||||
if (error instanceof TokenExpiredError) {
|
||||
throw new GraphQLError('Unauthenticated', {
|
||||
extensions: {
|
||||
code: 'UNAUTHENTICATED',
|
||||
},
|
||||
});
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
csrfPrevention: false,
|
||||
resolvers: { JSON: GraphQLJSON },
|
||||
plugins: [],
|
||||
}),
|
||||
PrismaModule,
|
||||
HealthModule,
|
||||
@ -43,4 +98,10 @@ import { TenantModule } from './tenant/tenant.module';
|
||||
],
|
||||
providers: [AppService],
|
||||
})
|
||||
export class AppModule {}
|
||||
export class AppModule {
|
||||
static moduleRef: ModuleRef;
|
||||
|
||||
constructor(private moduleRef: ModuleRef) {
|
||||
AppModule.moduleRef = this.moduleRef;
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import { PersonService } from 'src/core/person/person.service';
|
||||
import { CompanyService } from 'src/core/company/company.service';
|
||||
import { PipelineProgressService } from 'src/core/pipeline/services/pipeline-progress.service';
|
||||
import { ViewService } from 'src/core/view/services/view.service';
|
||||
import { DataSourceService } from 'src/tenant/metadata/data-source/data-source.service';
|
||||
|
||||
import { WorkspaceService } from './workspace.service';
|
||||
|
||||
@ -46,6 +47,10 @@ describe('WorkspaceService', () => {
|
||||
provide: ViewService,
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: DataSourceService,
|
||||
useValue: {},
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
|
@ -11,6 +11,7 @@ import { PipelineService } from 'src/core/pipeline/services/pipeline.service';
|
||||
import { ViewService } from 'src/core/view/services/view.service';
|
||||
import { PrismaService } from 'src/database/prisma.service';
|
||||
import { assert } from 'src/utils/assert';
|
||||
import { DataSourceService } from 'src/tenant/metadata/data-source/data-source.service';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceService {
|
||||
@ -22,6 +23,7 @@ export class WorkspaceService {
|
||||
private readonly pipelineStageService: PipelineStageService,
|
||||
private readonly pipelineProgressService: PipelineProgressService,
|
||||
private readonly viewService: ViewService,
|
||||
private readonly dataSourceService: DataSourceService,
|
||||
) {}
|
||||
|
||||
// Find
|
||||
@ -63,6 +65,9 @@ export class WorkspaceService {
|
||||
},
|
||||
});
|
||||
|
||||
// Create workspace schema
|
||||
await this.dataSourceService.createWorkspaceSchema(workspace.id);
|
||||
|
||||
// Create default companies
|
||||
const companies = await this.companyService.createDefaultCompanies({
|
||||
workspaceId: workspace.id,
|
||||
|
@ -5,6 +5,7 @@ import { PipelineModule } from 'src/core/pipeline/pipeline.module';
|
||||
import { CompanyModule } from 'src/core/company/company.module';
|
||||
import { PersonModule } from 'src/core/person/person.module';
|
||||
import { ViewModule } from 'src/core/view/view.module';
|
||||
import { DataSourceModule } from 'src/tenant/metadata/data-source/data-source.module';
|
||||
|
||||
import { WorkspaceService } from './services/workspace.service';
|
||||
import { WorkspaceMemberService } from './services/workspace-member.service';
|
||||
@ -12,7 +13,13 @@ import { WorkspaceMemberResolver } from './resolvers/workspace-member.resolver';
|
||||
import { WorkspaceResolver } from './resolvers/workspace.resolver';
|
||||
|
||||
@Module({
|
||||
imports: [PipelineModule, CompanyModule, PersonModule, ViewModule],
|
||||
imports: [
|
||||
PipelineModule,
|
||||
CompanyModule,
|
||||
PersonModule,
|
||||
ViewModule,
|
||||
DataSourceModule,
|
||||
],
|
||||
providers: [
|
||||
WorkspaceService,
|
||||
FileUploadService,
|
||||
|
@ -17,9 +17,7 @@ export class JwtAuthGuard extends AuthGuard(['jwt']) {
|
||||
}
|
||||
|
||||
getRequest(context: ExecutionContext) {
|
||||
const request = getRequest(context);
|
||||
|
||||
return request;
|
||||
return getRequest(context);
|
||||
}
|
||||
|
||||
handleRequest(err: any, user: any, info: any) {
|
||||
|
12
server/src/tenant/entity-resolver/entity-resolver.module.ts
Normal file
12
server/src/tenant/entity-resolver/entity-resolver.module.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
|
||||
import { DataSourceModule } from 'src/tenant/metadata/data-source/data-source.module';
|
||||
|
||||
import { EntityResolverService } from './entity-resolver.service';
|
||||
|
||||
@Module({
|
||||
imports: [DataSourceModule],
|
||||
providers: [EntityResolverService],
|
||||
exports: [EntityResolverService],
|
||||
})
|
||||
export class EntityResolverModule {}
|
@ -0,0 +1,27 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
|
||||
import { DataSourceService } from 'src/tenant/metadata/data-source/data-source.service';
|
||||
|
||||
import { EntityResolverService } from './entity-resolver.service';
|
||||
|
||||
describe('EntityResolverService', () => {
|
||||
let service: EntityResolverService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [
|
||||
EntityResolverService,
|
||||
{
|
||||
provide: DataSourceService,
|
||||
useValue: {},
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
service = module.get<EntityResolverService>(EntityResolverService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
111
server/src/tenant/entity-resolver/entity-resolver.service.ts
Normal file
111
server/src/tenant/entity-resolver/entity-resolver.service.ts
Normal file
@ -0,0 +1,111 @@
|
||||
import { BadRequestException, Injectable } from '@nestjs/common';
|
||||
|
||||
import { GraphQLResolveInfo } from 'graphql';
|
||||
import graphqlFields from 'graphql-fields';
|
||||
|
||||
import { DataSourceService } from 'src/tenant/metadata/data-source/data-source.service';
|
||||
|
||||
import { convertFieldsToGraphQL } from './entity-resolver.util';
|
||||
|
||||
@Injectable()
|
||||
export class EntityResolverService {
|
||||
constructor(private readonly dataSourceService: DataSourceService) {}
|
||||
|
||||
async findAll(
|
||||
entityName: string,
|
||||
tableName: string,
|
||||
workspaceId: string,
|
||||
info: GraphQLResolveInfo,
|
||||
fieldAliases: Record<string, string>,
|
||||
) {
|
||||
const workspaceDataSource =
|
||||
await this.dataSourceService.connectToWorkspaceDataSource(workspaceId);
|
||||
|
||||
const graphqlQuery = await this.prepareGrapQLQuery(
|
||||
workspaceId,
|
||||
info,
|
||||
fieldAliases,
|
||||
);
|
||||
|
||||
/* TODO: This is a temporary solution to set the schema before each raw query.
|
||||
getSchemaName is used to avoid a call to metadata.data_source table,
|
||||
this won't work when we won't be able to dynamically recompute the schema name from its workspace_id only (remote schemas for example)
|
||||
*/
|
||||
await workspaceDataSource?.query(`
|
||||
SET search_path TO ${this.dataSourceService.getSchemaName(workspaceId)};
|
||||
`);
|
||||
const graphqlResult = await workspaceDataSource?.query(`
|
||||
SELECT graphql.resolve($$
|
||||
{
|
||||
${entityName}Collection: ${tableName}Collection {
|
||||
${graphqlQuery}
|
||||
}
|
||||
}
|
||||
$$);
|
||||
`);
|
||||
|
||||
const result =
|
||||
graphqlResult?.[0]?.resolve?.data?.[`${entityName}Collection`];
|
||||
|
||||
if (!result) {
|
||||
throw new BadRequestException('Malformed result from GraphQL query');
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
async findOne(
|
||||
entityName: string,
|
||||
tableName: string,
|
||||
args: { id: string },
|
||||
workspaceId: string,
|
||||
info: GraphQLResolveInfo,
|
||||
fieldAliases: Record<string, string>,
|
||||
) {
|
||||
const workspaceDataSource =
|
||||
await this.dataSourceService.connectToWorkspaceDataSource(workspaceId);
|
||||
|
||||
const graphqlQuery = await this.prepareGrapQLQuery(
|
||||
workspaceId,
|
||||
info,
|
||||
fieldAliases,
|
||||
);
|
||||
|
||||
await workspaceDataSource?.query(`
|
||||
SET search_path TO ${this.dataSourceService.getSchemaName(workspaceId)};
|
||||
`);
|
||||
const graphqlResult = await workspaceDataSource?.query(`
|
||||
SELECT graphql.resolve($$
|
||||
{
|
||||
${entityName}Collection: : ${tableName}Collection(filter: { id: { eq: "${args.id}" } }) {
|
||||
${graphqlQuery}
|
||||
}
|
||||
}
|
||||
$$);
|
||||
`);
|
||||
|
||||
const result =
|
||||
graphqlResult?.[0]?.resolve?.data?.[`${entityName}Collection`];
|
||||
|
||||
if (!result) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private async prepareGrapQLQuery(
|
||||
workspaceId: string,
|
||||
info: GraphQLResolveInfo,
|
||||
fieldAliases: Record<string, string>,
|
||||
): Promise<string> {
|
||||
// Extract requested fields from GraphQL resolve info
|
||||
const fields = graphqlFields(info);
|
||||
|
||||
await this.dataSourceService.createWorkspaceSchema(workspaceId);
|
||||
|
||||
const graphqlQuery = convertFieldsToGraphQL(fields, fieldAliases);
|
||||
|
||||
return graphqlQuery;
|
||||
}
|
||||
}
|
23
server/src/tenant/entity-resolver/entity-resolver.util.ts
Normal file
23
server/src/tenant/entity-resolver/entity-resolver.util.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import isEmpty from 'lodash.isempty';
|
||||
|
||||
export const convertFieldsToGraphQL = (
|
||||
fields: any,
|
||||
fieldAliases: Record<string, string>,
|
||||
acc = '',
|
||||
) => {
|
||||
for (const [key, value] of Object.entries(fields)) {
|
||||
if (value && !isEmpty(value)) {
|
||||
acc += `${key} {\n`;
|
||||
acc = convertFieldsToGraphQL(value, fieldAliases, acc);
|
||||
acc += `}\n`;
|
||||
} else {
|
||||
if (fieldAliases[key]) {
|
||||
acc += `${key}: ${fieldAliases[key]}\n`;
|
||||
} else {
|
||||
acc += `${key}\n`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return acc;
|
||||
};
|
@ -28,10 +28,17 @@ export class DataSourceMetadataService {
|
||||
});
|
||||
}
|
||||
|
||||
getDataSourcesMetadataFromWorkspaceId(workspaceId: string) {
|
||||
async getDataSourcesMetadataFromWorkspaceId(workspaceId: string) {
|
||||
return this.dataSourceMetadataRepository.find({
|
||||
where: { workspaceId },
|
||||
order: { createdAt: 'DESC' },
|
||||
});
|
||||
}
|
||||
|
||||
async getLastDataSourceMetadataFromWorkspaceIdOrFail(workspaceId: string) {
|
||||
return this.dataSourceMetadataRepository.findOneOrFail({
|
||||
where: { workspaceId },
|
||||
order: { createdAt: 'DESC' },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,4 @@
|
||||
import {
|
||||
Injectable,
|
||||
NotFoundException,
|
||||
OnModuleDestroy,
|
||||
OnModuleInit,
|
||||
} from '@nestjs/common';
|
||||
import { Injectable, OnModuleDestroy, OnModuleInit } from '@nestjs/common';
|
||||
|
||||
import { DataSource, QueryRunner, Table } from 'typeorm';
|
||||
|
||||
@ -37,15 +32,14 @@ export class DataSourceService implements OnModuleInit, OnModuleDestroy {
|
||||
* @param workspaceId
|
||||
* @returns Promise<void>
|
||||
*/
|
||||
public async createWorkspaceSchema(workspaceId: string): Promise<void> {
|
||||
public async createWorkspaceSchema(workspaceId: string): Promise<string> {
|
||||
const schemaName = this.getSchemaName(workspaceId);
|
||||
|
||||
const queryRunner = this.mainDataSource.createQueryRunner();
|
||||
const schemaAlreadyExists = await queryRunner.hasSchema(schemaName);
|
||||
|
||||
if (schemaAlreadyExists) {
|
||||
throw new Error(
|
||||
`Schema ${schemaName} already exists for workspace ${workspaceId}`,
|
||||
);
|
||||
return schemaName;
|
||||
}
|
||||
|
||||
await queryRunner.createSchema(schemaName, true);
|
||||
@ -56,6 +50,8 @@ export class DataSourceService implements OnModuleInit, OnModuleDestroy {
|
||||
workspaceId,
|
||||
schemaName,
|
||||
);
|
||||
|
||||
return schemaName;
|
||||
}
|
||||
|
||||
private async createMigrationTable(
|
||||
@ -105,20 +101,12 @@ export class DataSourceService implements OnModuleInit, OnModuleDestroy {
|
||||
return cachedDataSource;
|
||||
}
|
||||
|
||||
const dataSourcesMetadata =
|
||||
await this.dataSourceMetadataService.getDataSourcesMetadataFromWorkspaceId(
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
if (dataSourcesMetadata.length === 0) {
|
||||
throw new NotFoundException(
|
||||
`We can't find any data source for this workspace id (${workspaceId}).`,
|
||||
);
|
||||
}
|
||||
|
||||
// We only want the first one for now, we will handle multiple data sources later with remote datasources.
|
||||
// However, we will need to differentiate the data sources because we won't run migrations on remote data sources for example.
|
||||
const dataSourceMetadata = dataSourcesMetadata[0];
|
||||
const dataSourceMetadata =
|
||||
await this.dataSourceMetadataService.getLastDataSourceMetadataFromWorkspaceIdOrFail(
|
||||
workspaceId,
|
||||
);
|
||||
const schema = dataSourceMetadata.schema;
|
||||
|
||||
// Probably not needed as we will ask for the schema name OR store public by default if it's remote
|
||||
@ -128,11 +116,6 @@ export class DataSourceService implements OnModuleInit, OnModuleDestroy {
|
||||
);
|
||||
}
|
||||
|
||||
const entities =
|
||||
await this.entitySchemaGeneratorService.getTypeORMEntitiesByDataSourceId(
|
||||
dataSourceMetadata.id,
|
||||
);
|
||||
|
||||
const workspaceDataSource = new DataSource({
|
||||
// TODO: We should use later dataSourceMetadata.type and use a switch case condition to create the right data source
|
||||
url: dataSourceMetadata.url ?? this.environmentService.getPGDatabaseUrl(),
|
||||
@ -141,15 +124,17 @@ export class DataSourceService implements OnModuleInit, OnModuleDestroy {
|
||||
schema,
|
||||
entities: {
|
||||
TenantMigration,
|
||||
...entities,
|
||||
},
|
||||
});
|
||||
|
||||
await workspaceDataSource.initialize();
|
||||
|
||||
// Set search path to workspace schema for raw queries
|
||||
await workspaceDataSource?.query(`SET search_path TO ${schema};`);
|
||||
|
||||
this.dataSources.set(workspaceId, workspaceDataSource);
|
||||
|
||||
return this.dataSources.get(workspaceId);
|
||||
return workspaceDataSource;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -31,7 +31,6 @@ export const sanitizeColumnName = (columnName: string): string =>
|
||||
export const convertFieldTypeToPostgresType = (fieldType: string): string => {
|
||||
switch (fieldType) {
|
||||
case 'text':
|
||||
return 'text';
|
||||
case 'url':
|
||||
return 'text';
|
||||
case 'number':
|
||||
|
@ -27,9 +27,15 @@ export class FieldMetadata {
|
||||
@Column({ nullable: false, name: 'target_column_name' })
|
||||
targetColumnName: string;
|
||||
|
||||
@Column('text', { nullable: true, array: true })
|
||||
enums: string[];
|
||||
|
||||
@Column({ default: false, name: 'is_custom' })
|
||||
isCustom: boolean;
|
||||
|
||||
@Column({ nullable: true, default: true, name: 'is_nullable' })
|
||||
isNullable: boolean;
|
||||
|
||||
@Column({ nullable: false, name: 'workspace_id' })
|
||||
workspaceId: string;
|
||||
|
||||
|
@ -41,6 +41,8 @@ export class MetadataController {
|
||||
entities.push(...dataSourceEntities);
|
||||
}
|
||||
|
||||
this.dataSourceService.createWorkspaceSchema(workspace.id);
|
||||
|
||||
await this.migrationGenerator.executeMigrationFromPendingMigrations(
|
||||
workspace.id,
|
||||
);
|
||||
|
@ -58,11 +58,6 @@ export class MigrationGeneratorService {
|
||||
);
|
||||
});
|
||||
|
||||
await queryRunner.release();
|
||||
// We want to destroy all connections to the workspace data source and invalidate the cache
|
||||
// so that the next request will create a new connection and get the latest entities
|
||||
await this.dataSourceService.disconnectFromWorkspaceDataSource(workspaceId);
|
||||
|
||||
return flattenedPendingMigrations;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,61 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
|
||||
export class AlterFieldMetadataTable1695717691800
|
||||
implements MigrationInterface
|
||||
{
|
||||
name = 'AlterFieldMetadataTable1695717691800';
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "metadata"."field_metadata" ADD "enums" text array`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "metadata"."field_metadata" ADD "is_nullable" boolean DEFAULT true`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TYPE "metadata"."data_source_metadata_type_enum" RENAME TO "data_source_metadata_type_enum_old"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE TYPE "metadata"."data_source_metadata_type_enum" AS ENUM('postgres')`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "metadata"."data_source_metadata" ALTER COLUMN "type" DROP DEFAULT`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "metadata"."data_source_metadata" ALTER COLUMN "type" TYPE "metadata"."data_source_metadata_type_enum" USING "type"::"text"::"metadata"."data_source_metadata_type_enum"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "metadata"."data_source_metadata" ALTER COLUMN "type" SET DEFAULT 'postgres'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP TYPE "metadata"."data_source_metadata_type_enum_old"`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`CREATE TYPE "metadata"."data_source_metadata_type_enum_old" AS ENUM('postgres', 'mysql')`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "metadata"."data_source_metadata" ALTER COLUMN "type" DROP DEFAULT`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "metadata"."data_source_metadata" ALTER COLUMN "type" TYPE "metadata"."data_source_metadata_type_enum_old" USING "type"::"text"::"metadata"."data_source_metadata_type_enum_old"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "metadata"."data_source_metadata" ALTER COLUMN "type" SET DEFAULT 'postgres'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP TYPE "metadata"."data_source_metadata_type_enum"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TYPE "metadata"."data_source_metadata_type_enum_old" RENAME TO "data_source_metadata_type_enum"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "metadata"."field_metadata" DROP COLUMN "is_nullable"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "metadata"."field_metadata" DROP COLUMN "enums"`,
|
||||
);
|
||||
}
|
||||
}
|
@ -1,7 +1,9 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { TenantMigrationService } from './tenant-migration.service';
|
||||
|
||||
import { DataSourceService } from 'src/tenant/metadata/data-source/data-source.service';
|
||||
|
||||
import { TenantMigrationService } from './tenant-migration.service';
|
||||
|
||||
describe('TenantMigrationService', () => {
|
||||
let service: TenantMigrationService;
|
||||
|
||||
|
@ -0,0 +1,24 @@
|
||||
import { GraphQLList, GraphQLNonNull, GraphQLObjectType } from 'graphql';
|
||||
|
||||
import { PageInfoType } from './page-info.graphql-type';
|
||||
|
||||
/**
|
||||
* Generate a GraphQL connection type based on the EdgeType.
|
||||
* @param EdgeType Edge type to be used in the connection.
|
||||
* @returns GraphQL connection type.
|
||||
*/
|
||||
export const generateConnectionType = <T extends GraphQLObjectType>(
|
||||
EdgeType: T,
|
||||
): GraphQLObjectType<any, any> => {
|
||||
return new GraphQLObjectType({
|
||||
name: `${EdgeType.name.slice(0, -4)}Connection`, // Removing 'Edge' from the name
|
||||
fields: {
|
||||
edges: {
|
||||
type: new GraphQLList(EdgeType),
|
||||
},
|
||||
pageInfo: {
|
||||
type: new GraphQLNonNull(PageInfoType),
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
@ -0,0 +1,22 @@
|
||||
import { GraphQLNonNull, GraphQLObjectType, GraphQLString } from 'graphql';
|
||||
|
||||
/**
|
||||
* Generate a GraphQL edge type based on the ObjectType.
|
||||
* @param ObjectType Object type to be used in the Edge.
|
||||
* @returns GraphQL edge type.
|
||||
*/
|
||||
export const generateEdgeType = <T extends GraphQLObjectType>(
|
||||
ObjectType: T,
|
||||
): GraphQLObjectType<any, any> => {
|
||||
return new GraphQLObjectType({
|
||||
name: `${ObjectType.name}Edge`,
|
||||
fields: {
|
||||
node: {
|
||||
type: ObjectType,
|
||||
},
|
||||
cursor: {
|
||||
type: new GraphQLNonNull(GraphQLString),
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
@ -0,0 +1,99 @@
|
||||
import {
|
||||
GraphQLBoolean,
|
||||
GraphQLEnumType,
|
||||
GraphQLID,
|
||||
GraphQLInt,
|
||||
GraphQLNonNull,
|
||||
GraphQLObjectType,
|
||||
GraphQLString,
|
||||
} from 'graphql';
|
||||
|
||||
import { FieldMetadata } from 'src/tenant/metadata/field-metadata/field-metadata.entity';
|
||||
import { ObjectMetadata } from 'src/tenant/metadata/object-metadata/object-metadata.entity';
|
||||
import { pascalCase } from 'src/utils/pascal-case';
|
||||
|
||||
/**
|
||||
* Map the column type from field-metadata to its corresponding GraphQL type.
|
||||
* @param columnType Type of the column in the database.
|
||||
*/
|
||||
const mapColumnTypeToGraphQLType = (column: FieldMetadata): any => {
|
||||
switch (column.type) {
|
||||
case 'uuid':
|
||||
return GraphQLID;
|
||||
case 'text':
|
||||
case 'url':
|
||||
case 'date':
|
||||
return GraphQLString;
|
||||
case 'boolean':
|
||||
return GraphQLBoolean;
|
||||
case 'number':
|
||||
return GraphQLInt;
|
||||
case 'enum': {
|
||||
if (column.enums && column.enums.length > 0) {
|
||||
const enumName = `${pascalCase(column.objectId)}${pascalCase(
|
||||
column.displayName,
|
||||
)}Enum`;
|
||||
|
||||
return new GraphQLEnumType({
|
||||
name: enumName,
|
||||
values: Object.fromEntries(
|
||||
column.enums.map((value) => [value, { value }]),
|
||||
),
|
||||
});
|
||||
}
|
||||
}
|
||||
default:
|
||||
return GraphQLString;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate a GraphQL object type based on the name and columns.
|
||||
* @param name Name for the GraphQL object.
|
||||
* @param columns Array of FieldMetadata columns.
|
||||
*/
|
||||
export const generateObjectType = <TSource = any, TContext = any>(
|
||||
name: string,
|
||||
columns: FieldMetadata[],
|
||||
): GraphQLObjectType<TSource, TContext> => {
|
||||
const fields: Record<string, any> = {
|
||||
// Default fields
|
||||
id: { type: new GraphQLNonNull(GraphQLID) },
|
||||
createdAt: { type: new GraphQLNonNull(GraphQLString) },
|
||||
updatedAt: { type: new GraphQLNonNull(GraphQLString) },
|
||||
};
|
||||
|
||||
columns.forEach((column) => {
|
||||
let graphqlType = mapColumnTypeToGraphQLType(column);
|
||||
|
||||
if (!column.isNullable) {
|
||||
graphqlType = new GraphQLNonNull(graphqlType);
|
||||
}
|
||||
|
||||
fields[column.displayName] = {
|
||||
type: graphqlType,
|
||||
description: column.targetColumnName,
|
||||
};
|
||||
});
|
||||
|
||||
return new GraphQLObjectType({
|
||||
name: pascalCase(name),
|
||||
fields,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate multiple GraphQL object types based on an array of object metadata.
|
||||
* @param objectMetadata Array of ObjectMetadata.
|
||||
*/
|
||||
export const generateObjectTypes = (objectMetadata: ObjectMetadata[]) => {
|
||||
const objectTypes: Record<string, GraphQLObjectType> = {};
|
||||
|
||||
for (const object of objectMetadata) {
|
||||
const ObjectType = generateObjectType(object.displayName, object.fields);
|
||||
|
||||
objectTypes[object.displayName] = ObjectType;
|
||||
}
|
||||
|
||||
return objectTypes;
|
||||
};
|
@ -0,0 +1,19 @@
|
||||
import {
|
||||
GraphQLBoolean,
|
||||
GraphQLNonNull,
|
||||
GraphQLObjectType,
|
||||
GraphQLString,
|
||||
} from 'graphql';
|
||||
|
||||
/**
|
||||
* GraphQL PageInfo type.
|
||||
*/
|
||||
export const PageInfoType = new GraphQLObjectType({
|
||||
name: 'PageInfo',
|
||||
fields: {
|
||||
startCursor: { type: GraphQLString },
|
||||
endCursor: { type: GraphQLString },
|
||||
hasNextPage: { type: new GraphQLNonNull(GraphQLBoolean) },
|
||||
hasPreviousPage: { type: new GraphQLNonNull(GraphQLBoolean) },
|
||||
},
|
||||
});
|
@ -0,0 +1,21 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
|
||||
import { EntityResolverModule } from 'src/tenant/entity-resolver/entity-resolver.module';
|
||||
import { JwtAuthGuard } from 'src/guards/jwt.auth.guard';
|
||||
import { DataSourceMetadataModule } from 'src/tenant/metadata/data-source-metadata/data-source-metadata.module';
|
||||
import { EntitySchemaGeneratorModule } from 'src/tenant/metadata/entity-schema-generator/entity-schema-generator.module';
|
||||
import { ObjectMetadataModule } from 'src/tenant/metadata/object-metadata/object-metadata.module';
|
||||
|
||||
import { SchemaGenerationService } from './schema-generation.service';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
EntityResolverModule,
|
||||
DataSourceMetadataModule,
|
||||
EntitySchemaGeneratorModule,
|
||||
ObjectMetadataModule,
|
||||
],
|
||||
providers: [SchemaGenerationService, JwtAuthGuard],
|
||||
exports: [SchemaGenerationService],
|
||||
})
|
||||
export class SchemaGenerationModule {}
|
@ -0,0 +1,37 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
|
||||
import { DataSourceMetadataService } from 'src/tenant/metadata/data-source-metadata/data-source-metadata.service';
|
||||
import { ObjectMetadataService } from 'src/tenant/metadata/object-metadata/object-metadata.service';
|
||||
import { EntityResolverService } from 'src/tenant/entity-resolver/entity-resolver.service';
|
||||
|
||||
import { SchemaGenerationService } from './schema-generation.service';
|
||||
|
||||
describe('SchemaGenerationService', () => {
|
||||
let service: SchemaGenerationService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [
|
||||
SchemaGenerationService,
|
||||
{
|
||||
provide: DataSourceMetadataService,
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: ObjectMetadataService,
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: EntityResolverService,
|
||||
useValue: {},
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
service = module.get<SchemaGenerationService>(SchemaGenerationService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
150
server/src/tenant/schema-generation/schema-generation.service.ts
Normal file
150
server/src/tenant/schema-generation/schema-generation.service.ts
Normal file
@ -0,0 +1,150 @@
|
||||
import { Injectable, InternalServerErrorException } from '@nestjs/common';
|
||||
|
||||
import {
|
||||
GraphQLID,
|
||||
GraphQLNonNull,
|
||||
GraphQLObjectType,
|
||||
GraphQLResolveInfo,
|
||||
GraphQLSchema,
|
||||
} from 'graphql';
|
||||
|
||||
import { EntityResolverService } from 'src/tenant/entity-resolver/entity-resolver.service';
|
||||
import { DataSourceMetadataService } from 'src/tenant/metadata/data-source-metadata/data-source-metadata.service';
|
||||
import { pascalCase } from 'src/utils/pascal-case';
|
||||
import { ObjectMetadataService } from 'src/tenant/metadata/object-metadata/object-metadata.service';
|
||||
import { ObjectMetadata } from 'src/tenant/metadata/object-metadata/object-metadata.entity';
|
||||
|
||||
import { generateEdgeType } from './graphql-types/edge.graphql-type';
|
||||
import { generateConnectionType } from './graphql-types/connection.graphql-type';
|
||||
import { generateObjectTypes } from './graphql-types/object.graphql-type';
|
||||
|
||||
@Injectable()
|
||||
export class SchemaGenerationService {
|
||||
constructor(
|
||||
private readonly dataSourceMetadataService: DataSourceMetadataService,
|
||||
private readonly objectMetadataService: ObjectMetadataService,
|
||||
private readonly entityResolverService: EntityResolverService,
|
||||
) {}
|
||||
|
||||
private generateQueryFieldForEntity(
|
||||
entityName: string,
|
||||
tableName: string,
|
||||
ObjectType: GraphQLObjectType,
|
||||
objectDefinition: ObjectMetadata,
|
||||
workspaceId: string,
|
||||
) {
|
||||
const fieldAliases =
|
||||
objectDefinition?.fields.reduce(
|
||||
(acc, field) => ({
|
||||
...acc,
|
||||
[field.displayName]: field.targetColumnName,
|
||||
}),
|
||||
{},
|
||||
) || {};
|
||||
|
||||
const EdgeType = generateEdgeType(ObjectType);
|
||||
const ConnectionType = generateConnectionType(EdgeType);
|
||||
|
||||
return {
|
||||
[`findAll${pascalCase(entityName)}`]: {
|
||||
type: ConnectionType,
|
||||
resolve: async (root, args, context, info: GraphQLResolveInfo) => {
|
||||
return this.entityResolverService.findAll(
|
||||
entityName,
|
||||
tableName,
|
||||
workspaceId,
|
||||
info,
|
||||
fieldAliases,
|
||||
);
|
||||
},
|
||||
},
|
||||
[`findOne${pascalCase(entityName)}`]: {
|
||||
type: ObjectType,
|
||||
args: {
|
||||
id: { type: new GraphQLNonNull(GraphQLID) },
|
||||
},
|
||||
resolve: (root, args, context, info) => {
|
||||
return this.entityResolverService.findOne(
|
||||
entityName,
|
||||
tableName,
|
||||
args,
|
||||
workspaceId,
|
||||
info,
|
||||
fieldAliases,
|
||||
);
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
private generateQueryType(
|
||||
ObjectTypes: Record<string, GraphQLObjectType>,
|
||||
objectMetadata: ObjectMetadata[],
|
||||
workspaceId: string,
|
||||
): GraphQLObjectType {
|
||||
const fields: any = {};
|
||||
|
||||
for (const [entityName, ObjectType] of Object.entries(ObjectTypes)) {
|
||||
const objectDefinition = objectMetadata.find(
|
||||
(object) => object.displayName === entityName,
|
||||
);
|
||||
const tableName = objectDefinition?.targetTableName ?? '';
|
||||
|
||||
if (!objectDefinition) {
|
||||
throw new InternalServerErrorException('Object definition not found');
|
||||
}
|
||||
|
||||
Object.assign(
|
||||
fields,
|
||||
this.generateQueryFieldForEntity(
|
||||
entityName,
|
||||
tableName,
|
||||
ObjectType,
|
||||
objectDefinition,
|
||||
workspaceId,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return new GraphQLObjectType({
|
||||
name: 'Query',
|
||||
fields,
|
||||
});
|
||||
}
|
||||
|
||||
async generateSchema(
|
||||
workspaceId: string | undefined,
|
||||
): Promise<GraphQLSchema> {
|
||||
if (!workspaceId) {
|
||||
return new GraphQLSchema({});
|
||||
}
|
||||
|
||||
const dataSourcesMetadata =
|
||||
await this.dataSourceMetadataService.getDataSourcesMetadataFromWorkspaceId(
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
// Can'f find any data sources for this workspace
|
||||
if (!dataSourcesMetadata || dataSourcesMetadata.length === 0) {
|
||||
return new GraphQLSchema({});
|
||||
}
|
||||
|
||||
const dataSourceMetadata = dataSourcesMetadata[0];
|
||||
|
||||
const objectMetadata =
|
||||
await this.objectMetadataService.getObjectMetadataFromDataSourceId(
|
||||
dataSourceMetadata.id,
|
||||
);
|
||||
|
||||
const ObjectTypes = generateObjectTypes(objectMetadata);
|
||||
const QueryType = this.generateQueryType(
|
||||
ObjectTypes,
|
||||
objectMetadata,
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
return new GraphQLSchema({
|
||||
query: QueryType,
|
||||
});
|
||||
}
|
||||
}
|
@ -2,8 +2,9 @@ import { Module } from '@nestjs/common';
|
||||
|
||||
import { MetadataModule } from './metadata/metadata.module';
|
||||
import { UniversalModule } from './universal/universal.module';
|
||||
import { SchemaGenerationModule } from './schema-generation/schema-generation.module';
|
||||
|
||||
@Module({
|
||||
imports: [MetadataModule, UniversalModule],
|
||||
imports: [MetadataModule, UniversalModule, SchemaGenerationModule],
|
||||
})
|
||||
export class TenantModule {}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Type } from '@nestjs/common';
|
||||
import { ArgsType, Directive, Field, ObjectType } from '@nestjs/graphql';
|
||||
import { ArgsType, Field, ObjectType } from '@nestjs/graphql';
|
||||
|
||||
import { IsNumber, IsOptional, IsString } from 'class-validator';
|
||||
|
||||
@ -50,7 +50,6 @@ export function Paginated<T>(classRef: Type<T>): Type<IConnection<T>> {
|
||||
public cursor!: ConnectionCursor;
|
||||
|
||||
@Field(() => classRef, { nullable: true })
|
||||
@Directive(`@cacheControl(inheritMaxAge: true)`)
|
||||
public node!: T;
|
||||
}
|
||||
|
||||
@ -59,11 +58,9 @@ export function Paginated<T>(classRef: Type<T>): Type<IConnection<T>> {
|
||||
public name = `${classRef.name}Connection`;
|
||||
|
||||
@Field(() => [Edge], { nullable: true })
|
||||
@Directive(`@cacheControl(inheritMaxAge: true)`)
|
||||
public edges!: IEdge<T>[];
|
||||
|
||||
@Field(() => PageInfo, { nullable: true })
|
||||
@Directive(`@cacheControl(inheritMaxAge: true)`)
|
||||
public pageInfo!: IPageInfo;
|
||||
|
||||
@Field()
|
||||
|
32
server/src/utils/pascal-case.ts
Normal file
32
server/src/utils/pascal-case.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import isObject from 'lodash.isobject';
|
||||
import lodashCamelCase from 'lodash.camelcase';
|
||||
import { PascalCase, PascalCasedPropertiesDeep } from 'type-fest';
|
||||
|
||||
export const capitalizeFirstLetter = (str: string) => {
|
||||
return str.charAt(0).toUpperCase() + str.slice(1);
|
||||
};
|
||||
|
||||
export const pascalCase = <T>(text: T) =>
|
||||
capitalizeFirstLetter(
|
||||
lodashCamelCase(text as unknown as string),
|
||||
) as PascalCase<T>;
|
||||
|
||||
export const pascalCaseDeep = <T>(value: T): PascalCasedPropertiesDeep<T> => {
|
||||
// Check if it's an array
|
||||
if (Array.isArray(value)) {
|
||||
return value.map(pascalCaseDeep) as PascalCasedPropertiesDeep<T>;
|
||||
}
|
||||
|
||||
// Check if it's an object
|
||||
if (isObject(value)) {
|
||||
const result: Record<string, any> = {};
|
||||
|
||||
for (const key in value) {
|
||||
result[pascalCase(key)] = pascalCaseDeep(value[key]);
|
||||
}
|
||||
|
||||
return result as PascalCasedPropertiesDeep<T>;
|
||||
}
|
||||
|
||||
return value as PascalCasedPropertiesDeep<T>;
|
||||
};
|
@ -160,8 +160,7 @@ describe('CompanyResolver (e2e)', () => {
|
||||
const error = errors?.[0];
|
||||
|
||||
expect(error).toBeDefined();
|
||||
expect(error.extensions.code).toBe('FORBIDDEN');
|
||||
expect(error.extensions.originalError.statusCode).toBe(403);
|
||||
expect(error.message).toBe('Forbidden resource');
|
||||
});
|
||||
});
|
||||
|
||||
@ -235,8 +234,7 @@ describe('CompanyResolver (e2e)', () => {
|
||||
const error = errors?.[0];
|
||||
|
||||
expect(error).toBeDefined();
|
||||
expect(error.extensions.code).toBe('FORBIDDEN');
|
||||
expect(error.extensions.originalError.statusCode).toBe(403);
|
||||
expect(error.message).toBe('Forbidden resource');
|
||||
});
|
||||
});
|
||||
|
||||
@ -291,8 +289,7 @@ describe('CompanyResolver (e2e)', () => {
|
||||
const error = errors?.[0];
|
||||
|
||||
expect(error).toBeDefined();
|
||||
expect(error.extensions.code).toBe('FORBIDDEN');
|
||||
expect(error.extensions.originalError.statusCode).toBe(403);
|
||||
expect(error.message).toBe('Forbidden resource');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
351
server/yarn.lock
351
server/yarn.lock
@ -1282,6 +1282,21 @@
|
||||
dependencies:
|
||||
"@jridgewell/trace-mapping" "0.3.9"
|
||||
|
||||
"@envelop/core@^4.0.0":
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@envelop/core/-/core-4.0.1.tgz#0f3eb33a396e9f4527d7fa8079055ec151eb73aa"
|
||||
integrity sha512-uBLI7ql3hZopz7vMi9UDAb9HWzKw4STKiqg4QT+lb+tu5ZNaeuJ4fom2rrmgITz38B85QZOhZrGyVrlJXxfDzw==
|
||||
dependencies:
|
||||
"@envelop/types" "4.0.1"
|
||||
tslib "^2.5.0"
|
||||
|
||||
"@envelop/types@4.0.1":
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@envelop/types/-/types-4.0.1.tgz#145690d8266a003cdb06dd58fa1236e3c80050a9"
|
||||
integrity sha512-ULo27/doEsP7uUhm2iTnElx13qTO6I5FKvmLoX41cpfuw8x6e0NUFknoqhEsLzAbgz8xVS5mjwcxGCXh4lDYzg==
|
||||
dependencies:
|
||||
tslib "^2.5.0"
|
||||
|
||||
"@eslint-community/eslint-utils@^4.2.0":
|
||||
version "4.4.0"
|
||||
resolved "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz"
|
||||
@ -1314,6 +1329,17 @@
|
||||
resolved "https://registry.npmjs.org/@eslint/js/-/js-8.42.0.tgz"
|
||||
integrity sha512-6SWlXpWU5AvId8Ac7zjzmIOqMOba/JWY8XZ4A7q7Gn1Vlfg/SFFIlrtHXt9nPn4op9ZPAkl91Jao+QQv3r/ukw==
|
||||
|
||||
"@graphql-tools/executor@^1.0.0":
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@graphql-tools/executor/-/executor-1.2.0.tgz#6c45f4add765769d9820c4c4405b76957ba39c79"
|
||||
integrity sha512-SKlIcMA71Dha5JnEWlw4XxcaJ+YupuXg0QCZgl2TOLFz4SkGCwU/geAsJvUJFwK2RbVLpQv/UMq67lOaBuwDtg==
|
||||
dependencies:
|
||||
"@graphql-tools/utils" "^10.0.0"
|
||||
"@graphql-typed-document-node/core" "3.2.0"
|
||||
"@repeaterjs/repeater" "^3.0.4"
|
||||
tslib "^2.4.0"
|
||||
value-or-promise "^1.0.12"
|
||||
|
||||
"@graphql-tools/merge@8.3.1":
|
||||
version "8.3.1"
|
||||
resolved "https://registry.npmjs.org/@graphql-tools/merge/-/merge-8.3.1.tgz"
|
||||
@ -1348,7 +1374,7 @@
|
||||
fast-json-stable-stringify "^2.1.0"
|
||||
tslib "^2.4.0"
|
||||
|
||||
"@graphql-tools/schema@10.0.0":
|
||||
"@graphql-tools/schema@10.0.0", "@graphql-tools/schema@^10.0.0":
|
||||
version "10.0.0"
|
||||
resolved "https://registry.npmjs.org/@graphql-tools/schema/-/schema-10.0.0.tgz"
|
||||
integrity sha512-kf3qOXMFcMs2f/S8Y3A8fm/2w+GaHAkfr3Gnhh2LOug/JgpY/ywgFVxO3jOeSpSEdoYcDKLcXVjMigNbY4AdQg==
|
||||
@ -1378,10 +1404,10 @@
|
||||
tslib "^2.4.0"
|
||||
value-or-promise "^1.0.12"
|
||||
|
||||
"@graphql-tools/utils@10.0.0":
|
||||
version "10.0.0"
|
||||
resolved "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.0.0.tgz"
|
||||
integrity sha512-ndBPc6zgR+eGU/jHLpuojrs61kYN3Z89JyMLwK3GCRkPv4EQn9EOr1UWqF1JO0iM+/jAVHY0mvfUxyrFFN9DUQ==
|
||||
"@graphql-tools/utils@10.0.1", "@graphql-tools/utils@^10.0.0":
|
||||
version "10.0.1"
|
||||
resolved "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.0.1.tgz"
|
||||
integrity sha512-i1FozbDGHgdsFA47V/JvQZ0FE8NAy0Eiz7HGCJO2MkNdZAKNnwei66gOq0JWYVFztwpwbVQ09GkKhq7Kjcq5Cw==
|
||||
dependencies:
|
||||
"@graphql-typed-document-node/core" "^3.1.1"
|
||||
tslib "^2.4.0"
|
||||
@ -1393,14 +1419,6 @@
|
||||
dependencies:
|
||||
tslib "^2.4.0"
|
||||
|
||||
"@graphql-tools/utils@^10.0.0":
|
||||
version "10.0.1"
|
||||
resolved "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.0.1.tgz"
|
||||
integrity sha512-i1FozbDGHgdsFA47V/JvQZ0FE8NAy0Eiz7HGCJO2MkNdZAKNnwei66gOq0JWYVFztwpwbVQ09GkKhq7Kjcq5Cw==
|
||||
dependencies:
|
||||
"@graphql-typed-document-node/core" "^3.1.1"
|
||||
tslib "^2.4.0"
|
||||
|
||||
"@graphql-tools/utils@^9.2.1":
|
||||
version "9.2.1"
|
||||
resolved "https://registry.npmjs.org/@graphql-tools/utils/-/utils-9.2.1.tgz"
|
||||
@ -1409,11 +1427,41 @@
|
||||
"@graphql-typed-document-node/core" "^3.1.1"
|
||||
tslib "^2.4.0"
|
||||
|
||||
"@graphql-typed-document-node/core@^3.1.1":
|
||||
"@graphql-typed-document-node/core@3.2.0", "@graphql-typed-document-node/core@^3.1.1":
|
||||
version "3.2.0"
|
||||
resolved "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz"
|
||||
integrity sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==
|
||||
|
||||
"@graphql-yoga/logger@^1.0.0":
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@graphql-yoga/logger/-/logger-1.0.0.tgz#0fba12edd8c4b0b9c0f0a74b0d101f1646c3780e"
|
||||
integrity sha512-JYoxwnPggH2BfO+dWlWZkDeFhyFZqaTRGLvFhy+Pjp2UxitEW6nDrw+pEDw/K9tJwMjIFMmTT9VfTqrnESmBHg==
|
||||
dependencies:
|
||||
tslib "^2.5.2"
|
||||
|
||||
"@graphql-yoga/nestjs@^2.1.0":
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@graphql-yoga/nestjs/-/nestjs-2.1.0.tgz#e429906f84a391a9d7bcfd4661987425896938b2"
|
||||
integrity sha512-LaKdPJrLSG8QLNm8Xp7f6xWO8tGLfHZyPrNKNpqClvk4X9DByraeMHArwEyP1YDScFbsIEKkLxTaM7JoLkLkpg==
|
||||
|
||||
"@graphql-yoga/subscription@^4.0.0":
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@graphql-yoga/subscription/-/subscription-4.0.0.tgz#2bf5844ce8aeff46332650ad642218250201dcc5"
|
||||
integrity sha512-0qsN/BPPZNMoC2CZ8i+P6PgiJyHh1H35aKDt37qARBDaIOKDQuvEOq7+4txUKElcmXi7DYFo109FkhSQoEajrg==
|
||||
dependencies:
|
||||
"@graphql-yoga/typed-event-target" "^2.0.0"
|
||||
"@repeaterjs/repeater" "^3.0.4"
|
||||
"@whatwg-node/events" "^0.1.0"
|
||||
tslib "^2.5.2"
|
||||
|
||||
"@graphql-yoga/typed-event-target@^2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@graphql-yoga/typed-event-target/-/typed-event-target-2.0.0.tgz#41809fc8c101c27c61a5427d74e0d0ce824044db"
|
||||
integrity sha512-oA/VGxGmaSDym1glOHrltw43qZsFwLLjBwvh57B79UKX/vo3+UQcRgOyE44c5RP7DCYjkrC2tuArZmb6jCzysw==
|
||||
dependencies:
|
||||
"@repeaterjs/repeater" "^3.0.4"
|
||||
tslib "^2.5.2"
|
||||
|
||||
"@humanwhocodes/config-array@^0.11.10":
|
||||
version "0.11.10"
|
||||
resolved "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz"
|
||||
@ -1794,23 +1842,23 @@
|
||||
path-to-regexp "3.2.0"
|
||||
tslib "2.5.3"
|
||||
|
||||
"@nestjs/graphql@^11.0.6":
|
||||
version "11.0.6"
|
||||
resolved "https://registry.npmjs.org/@nestjs/graphql/-/graphql-11.0.6.tgz"
|
||||
integrity sha512-EGE4fhLHrQLPAAgER+AwIa034IM9FNJto3xg49cZmI6c7s1yo6pLw/JULCn2jE2hUDbg5Q3IORZMMG8EUiUyMw==
|
||||
"@nestjs/graphql@^12.0.8":
|
||||
version "12.0.8"
|
||||
resolved "https://registry.yarnpkg.com/@nestjs/graphql/-/graphql-12.0.8.tgz#15143b76dfb5fa4dc880d68a1bf2f7159ea077b6"
|
||||
integrity sha512-odYDHUdLOMCxjC5VSEmF/23r8cY40N1KCwBkWaCmI1IF76Ffe3srWRDv8HS9tcai9eSmOeSWuyLBEg2OSru0cQ==
|
||||
dependencies:
|
||||
"@graphql-tools/merge" "9.0.0"
|
||||
"@graphql-tools/schema" "10.0.0"
|
||||
"@graphql-tools/utils" "10.0.0"
|
||||
"@nestjs/mapped-types" "1.2.2"
|
||||
"@graphql-tools/utils" "10.0.1"
|
||||
"@nestjs/mapped-types" "2.0.2"
|
||||
chokidar "3.5.3"
|
||||
fast-glob "3.2.12"
|
||||
graphql-tag "2.12.6"
|
||||
graphql-ws "5.13.1"
|
||||
graphql-ws "5.14.0"
|
||||
lodash "4.17.21"
|
||||
normalize-path "3.0.0"
|
||||
subscriptions-transport-ws "0.11.0"
|
||||
tslib "2.5.2"
|
||||
tslib "2.6.0"
|
||||
uuid "9.0.0"
|
||||
ws "8.13.0"
|
||||
|
||||
@ -1822,10 +1870,10 @@
|
||||
"@types/jsonwebtoken" "9.0.1"
|
||||
jsonwebtoken "9.0.0"
|
||||
|
||||
"@nestjs/mapped-types@1.2.2":
|
||||
version "1.2.2"
|
||||
resolved "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-1.2.2.tgz"
|
||||
integrity sha512-3dHxLXs3M0GPiriAcCFFJQHoDFUuzTD5w6JDhE7TyfT89YKpe6tcCCIqOZWdXmt9AZjjK30RkHRSFF+QEnWFQg==
|
||||
"@nestjs/mapped-types@2.0.2":
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@nestjs/mapped-types/-/mapped-types-2.0.2.tgz#c8a090a8d22145b85ed977414c158534210f2e4f"
|
||||
integrity sha512-V0izw6tWs6fTp9+KiiPUbGHWALy563Frn8X6Bm87ANLRuE46iuBMD5acKBDP5lKL/75QFvrzSJT7HkCbB0jTpg==
|
||||
|
||||
"@nestjs/passport@^9.0.3":
|
||||
version "9.0.3"
|
||||
@ -2158,6 +2206,11 @@
|
||||
resolved "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz"
|
||||
integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==
|
||||
|
||||
"@repeaterjs/repeater@^3.0.4":
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@repeaterjs/repeater/-/repeater-3.0.4.tgz#a04d63f4d1bf5540a41b01a921c9a7fddc3bd1ca"
|
||||
integrity sha512-AW8PKd6iX3vAZ0vA43nOUOnbq/X5ihgU+mSXXqunMkeQADGiqw/PY0JNeYtD5sr0PAy51YPgAPbDoeapv9r8WA==
|
||||
|
||||
"@sentry-internal/tracing@7.66.0":
|
||||
version "7.66.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry-internal/tracing/-/tracing-7.66.0.tgz#45ea607917d55a5bcaa3229341387ff6ed9b3a2b"
|
||||
@ -2834,6 +2887,13 @@
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/graphql-fields@^1.3.6":
|
||||
version "1.3.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/graphql-fields/-/graphql-fields-1.3.6.tgz#fc73326082f142ac63394f8167d272c21604f74e"
|
||||
integrity sha512-tLiskj9g5ftYgiVxq8VlvBEYDRow23IwY/LMnhljXfWvBhi+LIo9YEMa6AACjgIa3rG+edS9xh3v6Rja2UPbDg==
|
||||
dependencies:
|
||||
graphql "*"
|
||||
|
||||
"@types/graphql-upload@^8.0.12":
|
||||
version "8.0.12"
|
||||
resolved "https://registry.yarnpkg.com/@types/graphql-upload/-/graphql-upload-8.0.12.tgz#224738b8885bad8d50fb690b67bbe10bbcdef032"
|
||||
@ -2938,6 +2998,13 @@
|
||||
dependencies:
|
||||
"@types/lodash" "*"
|
||||
|
||||
"@types/lodash.isempty@^4.4.7":
|
||||
version "4.4.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/lodash.isempty/-/lodash.isempty-4.4.7.tgz#b1015d1adba560daf560ad04f294848939e75317"
|
||||
integrity sha512-YOzlpoIn9jrfHzjIukKnu9Le3tmi+0PhUdOt2rMpJW/4J6jX7s0HeBatXdh9QckLga8qt4EKBxVIEqtEq6pzLg==
|
||||
dependencies:
|
||||
"@types/lodash" "*"
|
||||
|
||||
"@types/lodash.isobject@^3.0.7":
|
||||
version "3.0.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/lodash.isobject/-/lodash.isobject-3.0.7.tgz#8a37beea56512f0ae86f8d48ea01e2ea9b79c185"
|
||||
@ -3384,6 +3451,38 @@
|
||||
"@webassemblyjs/ast" "1.11.6"
|
||||
"@xtuc/long" "4.2.2"
|
||||
|
||||
"@whatwg-node/events@^0.1.0":
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@whatwg-node/events/-/events-0.1.1.tgz#0ca718508249419587e130da26d40e29d99b5356"
|
||||
integrity sha512-AyQEn5hIPV7Ze+xFoXVU3QTHXVbWPrzaOkxtENMPMuNL6VVHrp4hHfDt9nrQpjO7BgvuM95dMtkycX5M/DZR3w==
|
||||
|
||||
"@whatwg-node/fetch@^0.9.10", "@whatwg-node/fetch@^0.9.7":
|
||||
version "0.9.12"
|
||||
resolved "https://registry.yarnpkg.com/@whatwg-node/fetch/-/fetch-0.9.12.tgz#3b20ac8f286a2196003976b6f1452c2c513fad00"
|
||||
integrity sha512-zNUkPJNfM1v9Jhy3Vmi2a7lQxaNIDTSiAb1NKO5eMsSdo05XoddBEj/CHj1xu4IOMU68VerDvuBVwzPjxBl12g==
|
||||
dependencies:
|
||||
"@whatwg-node/node-fetch" "^0.4.17"
|
||||
urlpattern-polyfill "^9.0.0"
|
||||
|
||||
"@whatwg-node/node-fetch@^0.4.17":
|
||||
version "0.4.18"
|
||||
resolved "https://registry.yarnpkg.com/@whatwg-node/node-fetch/-/node-fetch-0.4.18.tgz#ff15beb1ecd03eb7428286435674c8bd583f159a"
|
||||
integrity sha512-zdey6buMKCqDVDq+tMqcjopO75Fb6iLqWo+g6cWwN5kiwctEHtVcbws2lJUFhCbo+TLZeH6bMDRUXEo5bkPtcQ==
|
||||
dependencies:
|
||||
"@whatwg-node/events" "^0.1.0"
|
||||
busboy "^1.6.0"
|
||||
fast-querystring "^1.1.1"
|
||||
fast-url-parser "^1.1.3"
|
||||
tslib "^2.3.1"
|
||||
|
||||
"@whatwg-node/server@^0.9.1":
|
||||
version "0.9.14"
|
||||
resolved "https://registry.yarnpkg.com/@whatwg-node/server/-/server-0.9.14.tgz#54c47b50c370e46fabdcbbed06be3d84686b8a91"
|
||||
integrity sha512-I8TT0NoCP+xThLBuGlU6dgq5wpExkphNMo2geZwQW0vAmEPtc3MNMZMIYqg5GyNmpv5Nf7fnxb8tVOIHbDvuDA==
|
||||
dependencies:
|
||||
"@whatwg-node/fetch" "^0.9.10"
|
||||
tslib "^2.3.1"
|
||||
|
||||
"@xtuc/ieee754@^1.2.0":
|
||||
version "1.2.0"
|
||||
resolved "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz"
|
||||
@ -3394,6 +3493,11 @@
|
||||
resolved "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz"
|
||||
integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==
|
||||
|
||||
"@yarnpkg/lockfile@^1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31"
|
||||
integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==
|
||||
|
||||
abbrev@1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
|
||||
@ -3794,6 +3898,11 @@ asynckit@^0.4.0:
|
||||
resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz"
|
||||
integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
|
||||
|
||||
at-least-node@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2"
|
||||
integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==
|
||||
|
||||
available-typed-arrays@^1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7"
|
||||
@ -4061,7 +4170,7 @@ busboy@^0.3.1:
|
||||
dependencies:
|
||||
dicer "0.3.0"
|
||||
|
||||
busboy@^1.0.0:
|
||||
busboy@^1.0.0, busboy@^1.6.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz"
|
||||
integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==
|
||||
@ -4176,7 +4285,7 @@ chrome-trace-event@^1.0.2:
|
||||
resolved "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz"
|
||||
integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==
|
||||
|
||||
ci-info@3.8.0, ci-info@^3.2.0:
|
||||
ci-info@3.8.0, ci-info@^3.2.0, ci-info@^3.7.0:
|
||||
version "3.8.0"
|
||||
resolved "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz"
|
||||
integrity sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==
|
||||
@ -4684,6 +4793,11 @@ dotenv@^16.0.3:
|
||||
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.3.1.tgz#369034de7d7e5b120972693352a3bf112172cc3e"
|
||||
integrity sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==
|
||||
|
||||
dset@^3.1.1:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/dset/-/dset-3.1.2.tgz#89c436ca6450398396dc6538ea00abc0c54cd45a"
|
||||
integrity sha512-g/M9sqy3oHe477Ar4voQxWtaPIFw1jTdKZuomOjhCcBx9nHUNn0pu6NopuFFrTh/TRZIKEj+76vLWFu9BNKk+Q==
|
||||
|
||||
ecdsa-sig-formatter@1.0.11:
|
||||
version "1.0.11"
|
||||
resolved "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz"
|
||||
@ -5130,6 +5244,11 @@ external-editor@^3.0.3:
|
||||
iconv-lite "^0.4.24"
|
||||
tmp "^0.0.33"
|
||||
|
||||
fast-decode-uri-component@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz#46f8b6c22b30ff7a81357d4f59abfae938202543"
|
||||
integrity sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==
|
||||
|
||||
fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
|
||||
version "3.1.3"
|
||||
resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz"
|
||||
@ -5161,11 +5280,25 @@ fast-levenshtein@^2.0.6:
|
||||
resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz"
|
||||
integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==
|
||||
|
||||
fast-querystring@^1.1.1:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/fast-querystring/-/fast-querystring-1.1.2.tgz#a6d24937b4fc6f791b4ee31dcb6f53aeafb89f53"
|
||||
integrity sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==
|
||||
dependencies:
|
||||
fast-decode-uri-component "^1.0.1"
|
||||
|
||||
fast-safe-stringify@2.1.1, fast-safe-stringify@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz"
|
||||
integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==
|
||||
|
||||
fast-url-parser@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/fast-url-parser/-/fast-url-parser-1.1.3.tgz#f4af3ea9f34d8a271cf58ad2b3759f431f0b318d"
|
||||
integrity sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==
|
||||
dependencies:
|
||||
punycode "^1.3.2"
|
||||
|
||||
fast-write-atomic@0.2.1:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.npmjs.org/fast-write-atomic/-/fast-write-atomic-0.2.1.tgz"
|
||||
@ -5274,6 +5407,13 @@ find-up@^4.0.0, find-up@^4.1.0:
|
||||
locate-path "^5.0.0"
|
||||
path-exists "^4.0.0"
|
||||
|
||||
find-yarn-workspace-root@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz#f47fb8d239c900eb78179aa81b66673eac88f7bd"
|
||||
integrity sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==
|
||||
dependencies:
|
||||
micromatch "^4.0.2"
|
||||
|
||||
flat-cache@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz"
|
||||
@ -5398,6 +5538,16 @@ fs-extra@^10.0.0:
|
||||
jsonfile "^6.0.1"
|
||||
universalify "^2.0.0"
|
||||
|
||||
fs-extra@^9.0.0:
|
||||
version "9.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d"
|
||||
integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==
|
||||
dependencies:
|
||||
at-least-node "^1.0.0"
|
||||
graceful-fs "^4.2.0"
|
||||
jsonfile "^6.0.1"
|
||||
universalify "^2.0.0"
|
||||
|
||||
fs-jetpack@5.1.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.npmjs.org/fs-jetpack/-/fs-jetpack-5.1.0.tgz"
|
||||
@ -5614,7 +5764,7 @@ gopd@^1.0.1:
|
||||
dependencies:
|
||||
get-intrinsic "^1.1.3"
|
||||
|
||||
graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.9:
|
||||
graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.9:
|
||||
version "4.2.11"
|
||||
resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz"
|
||||
integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
|
||||
@ -5629,6 +5779,11 @@ graphemer@^1.4.0:
|
||||
resolved "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz"
|
||||
integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==
|
||||
|
||||
graphql-fields@^2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/graphql-fields/-/graphql-fields-2.0.3.tgz#5e68dff7afbb202be4f4f40623e983b22c96ab8f"
|
||||
integrity sha512-x3VE5lUcR4XCOxPIqaO4CE+bTK8u6gVouOdpQX9+EKHr+scqtK5Pp/l8nIGqIpN1TUlkKE6jDCCycm/WtLRAwA==
|
||||
|
||||
graphql-parse-resolve-info@^4.13.0:
|
||||
version "4.13.0"
|
||||
resolved "https://registry.npmjs.org/graphql-parse-resolve-info/-/graphql-parse-resolve-info-4.13.0.tgz"
|
||||
@ -5659,15 +5814,32 @@ graphql-upload@^13.0.0:
|
||||
http-errors "^1.8.1"
|
||||
object-path "^0.11.8"
|
||||
|
||||
graphql-ws@5.13.1:
|
||||
version "5.13.1"
|
||||
resolved "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.13.1.tgz"
|
||||
integrity sha512-eiX7ES/ZQr0q7hSM5UBOEIFfaAUmAY9/CSDyAnsETuybByU7l/v46drRg9DQoTvVABEHp3QnrvwgTRMhqy7zxQ==
|
||||
graphql-ws@5.14.0:
|
||||
version "5.14.0"
|
||||
resolved "https://registry.yarnpkg.com/graphql-ws/-/graphql-ws-5.14.0.tgz#766f249f3974fc2c48fae0d1fb20c2c4c79cd591"
|
||||
integrity sha512-itrUTQZP/TgswR4GSSYuwWUzrE/w5GhbwM2GX3ic2U7aw33jgEsayfIlvaj7/GcIvZgNMzsPTrE5hqPuFUiE5g==
|
||||
|
||||
"graphql@0.13.1 - 16", graphql@^16.7.1:
|
||||
version "16.7.1"
|
||||
resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.7.1.tgz#11475b74a7bff2aefd4691df52a0eca0abd9b642"
|
||||
integrity sha512-DRYR9tf+UGU0KOsMcKAlXeFfX89UiiIZ0dRU3mR0yJfu6OjZqUcp68NnFLnqQU5RexygFoDy1EW+ccOYcPfmHg==
|
||||
graphql-yoga@^4.0.4:
|
||||
version "4.0.4"
|
||||
resolved "https://registry.yarnpkg.com/graphql-yoga/-/graphql-yoga-4.0.4.tgz#00f388b6c38560ad4e5662c66cd2671befb58229"
|
||||
integrity sha512-MvCLhFecYNIKuxAZisPjpIL9lxRYbpgPSNKENDO/8CV3oiFlsLJHZb5dp2sVAeLafXHeZ9TgkijLthUBc1+Jag==
|
||||
dependencies:
|
||||
"@envelop/core" "^4.0.0"
|
||||
"@graphql-tools/executor" "^1.0.0"
|
||||
"@graphql-tools/schema" "^10.0.0"
|
||||
"@graphql-tools/utils" "^10.0.0"
|
||||
"@graphql-yoga/logger" "^1.0.0"
|
||||
"@graphql-yoga/subscription" "^4.0.0"
|
||||
"@whatwg-node/fetch" "^0.9.7"
|
||||
"@whatwg-node/server" "^0.9.1"
|
||||
dset "^3.1.1"
|
||||
lru-cache "^10.0.0"
|
||||
tslib "^2.5.2"
|
||||
|
||||
graphql@*, "graphql@0.13.1 - 16", graphql@16.8.0, graphql@^16.8.0:
|
||||
version "16.8.0"
|
||||
resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.8.0.tgz#374478b7f27b2dc6153c8f42c1b80157f79d79d4"
|
||||
integrity sha512-0oKGaR+y3qcS5mCu1vb7KG+a89vjn06C7Ihq/dDl3jA+A8B3TKomvi3CiEcVLJQGalbu8F52LxkOym7U5sSfbg==
|
||||
|
||||
has-bigints@^1.0.1, has-bigints@^1.0.2:
|
||||
version "1.0.2"
|
||||
@ -6613,6 +6785,13 @@ json-stable-stringify-without-jsonify@^1.0.1:
|
||||
resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz"
|
||||
integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==
|
||||
|
||||
json-stable-stringify@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.2.tgz#e06f23128e0bbe342dc996ed5a19e28b57b580e0"
|
||||
integrity sha512-eunSSaEnxV12z+Z73y/j5N37/In40GK4GmsSy+tEHJMxknvqnA7/djeYtAgW0GsWHUfg+847WJjKaEylk2y09g==
|
||||
dependencies:
|
||||
jsonify "^0.0.1"
|
||||
|
||||
json5@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593"
|
||||
@ -6639,6 +6818,11 @@ jsonfile@^6.0.1:
|
||||
optionalDependencies:
|
||||
graceful-fs "^4.1.6"
|
||||
|
||||
jsonify@^0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.1.tgz#2aa3111dae3d34a0f151c63f3a45d995d9420978"
|
||||
integrity sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==
|
||||
|
||||
jsonwebtoken@9.0.0, jsonwebtoken@^9.0.0:
|
||||
version "9.0.0"
|
||||
resolved "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz"
|
||||
@ -6666,6 +6850,13 @@ jws@^3.2.2:
|
||||
jwa "^1.4.1"
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
klaw-sync@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/klaw-sync/-/klaw-sync-6.0.0.tgz#1fd2cfd56ebb6250181114f0a581167099c2b28c"
|
||||
integrity sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==
|
||||
dependencies:
|
||||
graceful-fs "^4.1.11"
|
||||
|
||||
kleur@4.1.5:
|
||||
version "4.1.5"
|
||||
resolved "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz"
|
||||
@ -6745,6 +6936,11 @@ lodash.flatten@^4.4.0:
|
||||
resolved "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz"
|
||||
integrity sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==
|
||||
|
||||
lodash.isempty@^4.4.0:
|
||||
version "4.4.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isempty/-/lodash.isempty-4.4.0.tgz#6f86cbedd8be4ec987be9aaf33c9684db1b31e7e"
|
||||
integrity sha512-oKMuF3xEeqDltrGMfDxAPGIVMSSRv8tbRSODbrs4KGsRRLEhrW8N8Rd4DRgB2+621hY8A8XwwrTVhXWpxFvMzg==
|
||||
|
||||
lodash.isobject@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isobject/-/lodash.isobject-3.0.2.tgz#3c8fb8d5b5bf4bf90ae06e14f2a530a4ed935e1d"
|
||||
@ -6818,6 +7014,11 @@ long@^4.0.0:
|
||||
resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-7.13.1.tgz"
|
||||
integrity sha512-CHqbAq7NFlW3RSnoWXLJBxCWaZVBrfa9UEHId2M3AW8iEBurbqduNexEUCGc3SHc6iCYXNJCDi903LajSVAEPQ==
|
||||
|
||||
lru-cache@^10.0.0:
|
||||
version "10.0.1"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.0.1.tgz#0a3be479df549cca0e5d693ac402ff19537a6b7a"
|
||||
integrity sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==
|
||||
|
||||
lru-cache@^5.1.1:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz"
|
||||
@ -6910,7 +7111,7 @@ methods@^1.1.2, methods@~1.1.2:
|
||||
resolved "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz"
|
||||
integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==
|
||||
|
||||
micromatch@^4.0.0, micromatch@^4.0.4:
|
||||
micromatch@^4.0.0, micromatch@^4.0.2, micromatch@^4.0.4:
|
||||
version "4.0.5"
|
||||
resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz"
|
||||
integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==
|
||||
@ -7277,7 +7478,7 @@ onetime@^5.1.0, onetime@^5.1.2:
|
||||
dependencies:
|
||||
mimic-fn "^2.1.0"
|
||||
|
||||
open@7.4.2:
|
||||
open@7.4.2, open@^7.4.2:
|
||||
version "7.4.2"
|
||||
resolved "https://registry.npmjs.org/open/-/open-7.4.2.tgz"
|
||||
integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==
|
||||
@ -7481,6 +7682,27 @@ passport@^0.6.0:
|
||||
pause "0.0.1"
|
||||
utils-merge "^1.0.1"
|
||||
|
||||
patch-package@^8.0.0:
|
||||
version "8.0.0"
|
||||
resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-8.0.0.tgz#d191e2f1b6e06a4624a0116bcb88edd6714ede61"
|
||||
integrity sha512-da8BVIhzjtgScwDJ2TtKsfT5JFWz1hYoBl9rUQ1f38MC2HwnEIkK8VN3dKMKcP7P7bvvgzNDbfNHtx3MsQb5vA==
|
||||
dependencies:
|
||||
"@yarnpkg/lockfile" "^1.1.0"
|
||||
chalk "^4.1.2"
|
||||
ci-info "^3.7.0"
|
||||
cross-spawn "^7.0.3"
|
||||
find-yarn-workspace-root "^2.0.0"
|
||||
fs-extra "^9.0.0"
|
||||
json-stable-stringify "^1.0.2"
|
||||
klaw-sync "^6.0.0"
|
||||
minimist "^1.2.6"
|
||||
open "^7.4.2"
|
||||
rimraf "^2.6.3"
|
||||
semver "^7.5.3"
|
||||
slash "^2.0.0"
|
||||
tmp "^0.0.33"
|
||||
yaml "^2.2.2"
|
||||
|
||||
path-browserify@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz"
|
||||
@ -7651,6 +7873,11 @@ postgres-interval@^1.1.0:
|
||||
dependencies:
|
||||
xtend "^4.0.0"
|
||||
|
||||
postinstall-postinstall@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/postinstall-postinstall/-/postinstall-postinstall-2.1.0.tgz#4f7f77441ef539d1512c40bd04c71b06a4704ca3"
|
||||
integrity sha512-7hQX6ZlZXIoRiWNrbMQaLzUUfH+sSx39u8EJ9HYuDc1kLo9IXKWjM5RSquZN1ad5GnH8CGFM78fsAAQi3OKEEQ==
|
||||
|
||||
prebuild-install@^7.1.1:
|
||||
version "7.1.1"
|
||||
resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-7.1.1.tgz#de97d5b34a70a0c81334fd24641f2a1702352e45"
|
||||
@ -7772,6 +7999,11 @@ pump@^3.0.0:
|
||||
end-of-stream "^1.1.0"
|
||||
once "^1.3.1"
|
||||
|
||||
punycode@^1.3.2:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
|
||||
integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==
|
||||
|
||||
punycode@^2.1.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz"
|
||||
@ -8021,6 +8253,13 @@ rimraf@4.4.1:
|
||||
dependencies:
|
||||
glob "^9.2.0"
|
||||
|
||||
rimraf@^2.6.3:
|
||||
version "2.7.1"
|
||||
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
|
||||
integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
|
||||
dependencies:
|
||||
glob "^7.1.3"
|
||||
|
||||
run-async@^2.4.0:
|
||||
version "2.4.1"
|
||||
resolved "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz"
|
||||
@ -8107,6 +8346,13 @@ semver@^7.5.0:
|
||||
dependencies:
|
||||
lru-cache "^6.0.0"
|
||||
|
||||
semver@^7.5.3:
|
||||
version "7.5.4"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e"
|
||||
integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==
|
||||
dependencies:
|
||||
lru-cache "^6.0.0"
|
||||
|
||||
send@0.18.0:
|
||||
version "0.18.0"
|
||||
resolved "https://registry.npmjs.org/send/-/send-0.18.0.tgz"
|
||||
@ -8236,6 +8482,11 @@ sisteransi@^1.0.5:
|
||||
resolved "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz"
|
||||
integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==
|
||||
|
||||
slash@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44"
|
||||
integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==
|
||||
|
||||
slash@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz"
|
||||
@ -8836,17 +9087,17 @@ tslib@2.5.3, tslib@^2.0.1, tslib@^2.1.0, tslib@^2.4.0:
|
||||
resolved "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz"
|
||||
integrity sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==
|
||||
|
||||
tslib@2.6.0, tslib@^2.3.1, tslib@^2.5.0:
|
||||
version "2.6.0"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.0.tgz#b295854684dbda164e181d259a22cd779dcd7bc3"
|
||||
integrity sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==
|
||||
|
||||
tslib@^1.11.1, tslib@^1.8.1:
|
||||
version "1.14.1"
|
||||
resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz"
|
||||
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
|
||||
|
||||
tslib@^2.3.1, tslib@^2.5.0:
|
||||
version "2.6.0"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.0.tgz#b295854684dbda164e181d259a22cd779dcd7bc3"
|
||||
integrity sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==
|
||||
|
||||
"tslib@^2.4.1 || ^1.9.3":
|
||||
"tslib@^2.4.1 || ^1.9.3", tslib@^2.5.2:
|
||||
version "2.6.2"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae"
|
||||
integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==
|
||||
@ -9039,6 +9290,11 @@ uri-js@^4.2.2:
|
||||
dependencies:
|
||||
punycode "^2.1.0"
|
||||
|
||||
urlpattern-polyfill@^9.0.0:
|
||||
version "9.0.0"
|
||||
resolved "https://registry.yarnpkg.com/urlpattern-polyfill/-/urlpattern-polyfill-9.0.0.tgz#bc7e386bb12fd7898b58d1509df21d3c29ab3460"
|
||||
integrity sha512-WHN8KDQblxd32odxeIgo83rdVDE2bvdkb86it7bMhYZwWKJz0+O0RK/eZiHYnM+zgt/U7hAHOlCQGfjjvSkw2g==
|
||||
|
||||
util-deprecate@^1.0.1, util-deprecate@~1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz"
|
||||
@ -9306,6 +9562,11 @@ yaml@^1.10.0:
|
||||
resolved "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz"
|
||||
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
|
||||
|
||||
yaml@^2.2.2:
|
||||
version "2.3.2"
|
||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.2.tgz#f522db4313c671a0ca963a75670f1c12ea909144"
|
||||
integrity sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg==
|
||||
|
||||
yargs-parser@21.1.1, yargs-parser@^21.0.1, yargs-parser@^21.1.1:
|
||||
version "21.1.1"
|
||||
resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz"
|
||||
|
396
yarn.lock
Normal file
396
yarn.lock
Normal file
@ -0,0 +1,396 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@mapbox/node-pre-gyp@^1.0.11":
|
||||
version "1.0.11"
|
||||
resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz#417db42b7f5323d79e93b34a6d7a2a12c0df43fa"
|
||||
integrity sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==
|
||||
dependencies:
|
||||
detect-libc "^2.0.0"
|
||||
https-proxy-agent "^5.0.0"
|
||||
make-dir "^3.1.0"
|
||||
node-fetch "^2.6.7"
|
||||
nopt "^5.0.0"
|
||||
npmlog "^5.0.1"
|
||||
rimraf "^3.0.2"
|
||||
semver "^7.3.5"
|
||||
tar "^6.1.11"
|
||||
|
||||
abbrev@1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
|
||||
integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
|
||||
|
||||
agent-base@6:
|
||||
version "6.0.2"
|
||||
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
|
||||
integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
|
||||
dependencies:
|
||||
debug "4"
|
||||
|
||||
ansi-regex@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
|
||||
integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
|
||||
|
||||
"aproba@^1.0.3 || ^2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc"
|
||||
integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==
|
||||
|
||||
are-we-there-yet@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz#372e0e7bd279d8e94c653aaa1f67200884bf3e1c"
|
||||
integrity sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==
|
||||
dependencies:
|
||||
delegates "^1.0.0"
|
||||
readable-stream "^3.6.0"
|
||||
|
||||
balanced-match@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
|
||||
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
|
||||
|
||||
bcrypt@^5.1.1:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/bcrypt/-/bcrypt-5.1.1.tgz#0f732c6dcb4e12e5b70a25e326a72965879ba6e2"
|
||||
integrity sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==
|
||||
dependencies:
|
||||
"@mapbox/node-pre-gyp" "^1.0.11"
|
||||
node-addon-api "^5.0.0"
|
||||
|
||||
brace-expansion@^1.1.7:
|
||||
version "1.1.11"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
|
||||
integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
|
||||
dependencies:
|
||||
balanced-match "^1.0.0"
|
||||
concat-map "0.0.1"
|
||||
|
||||
chownr@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece"
|
||||
integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==
|
||||
|
||||
color-support@^1.1.2:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2"
|
||||
integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==
|
||||
|
||||
concat-map@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
|
||||
|
||||
console-control-strings@^1.0.0, console-control-strings@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
|
||||
integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==
|
||||
|
||||
debug@4:
|
||||
version "4.3.4"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
|
||||
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
|
||||
dependencies:
|
||||
ms "2.1.2"
|
||||
|
||||
delegates@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
|
||||
integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==
|
||||
|
||||
detect-libc@^2.0.0:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.2.tgz#8ccf2ba9315350e1241b88d0ac3b0e1fbd99605d"
|
||||
integrity sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==
|
||||
|
||||
emoji-regex@^8.0.0:
|
||||
version "8.0.0"
|
||||
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
|
||||
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
|
||||
|
||||
fs-minipass@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
|
||||
integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==
|
||||
dependencies:
|
||||
minipass "^3.0.0"
|
||||
|
||||
fs.realpath@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
|
||||
|
||||
gauge@^3.0.0:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/gauge/-/gauge-3.0.2.tgz#03bf4441c044383908bcfa0656ad91803259b395"
|
||||
integrity sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==
|
||||
dependencies:
|
||||
aproba "^1.0.3 || ^2.0.0"
|
||||
color-support "^1.1.2"
|
||||
console-control-strings "^1.0.0"
|
||||
has-unicode "^2.0.1"
|
||||
object-assign "^4.1.1"
|
||||
signal-exit "^3.0.0"
|
||||
string-width "^4.2.3"
|
||||
strip-ansi "^6.0.1"
|
||||
wide-align "^1.1.2"
|
||||
|
||||
glob@^7.1.3:
|
||||
version "7.2.3"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
|
||||
integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
|
||||
dependencies:
|
||||
fs.realpath "^1.0.0"
|
||||
inflight "^1.0.4"
|
||||
inherits "2"
|
||||
minimatch "^3.1.1"
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
has-unicode@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
|
||||
integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==
|
||||
|
||||
https-proxy-agent@^5.0.0:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6"
|
||||
integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==
|
||||
dependencies:
|
||||
agent-base "6"
|
||||
debug "4"
|
||||
|
||||
inflight@^1.0.4:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
|
||||
integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==
|
||||
dependencies:
|
||||
once "^1.3.0"
|
||||
wrappy "1"
|
||||
|
||||
inherits@2, inherits@^2.0.3:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||
|
||||
is-fullwidth-code-point@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
|
||||
integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
|
||||
|
||||
lru-cache@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
|
||||
integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
|
||||
dependencies:
|
||||
yallist "^4.0.0"
|
||||
|
||||
make-dir@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f"
|
||||
integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==
|
||||
dependencies:
|
||||
semver "^6.0.0"
|
||||
|
||||
minimatch@^3.1.1:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
||||
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minipass@^3.0.0:
|
||||
version "3.3.6"
|
||||
resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a"
|
||||
integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==
|
||||
dependencies:
|
||||
yallist "^4.0.0"
|
||||
|
||||
minipass@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d"
|
||||
integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==
|
||||
|
||||
minizlib@^2.1.1:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931"
|
||||
integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==
|
||||
dependencies:
|
||||
minipass "^3.0.0"
|
||||
yallist "^4.0.0"
|
||||
|
||||
mkdirp@^1.0.3:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
|
||||
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
|
||||
|
||||
ms@2.1.2:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||
|
||||
node-addon-api@^5.0.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-5.1.0.tgz#49da1ca055e109a23d537e9de43c09cca21eb762"
|
||||
integrity sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==
|
||||
|
||||
node-fetch@^2.6.7:
|
||||
version "2.7.0"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d"
|
||||
integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==
|
||||
dependencies:
|
||||
whatwg-url "^5.0.0"
|
||||
|
||||
nopt@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88"
|
||||
integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==
|
||||
dependencies:
|
||||
abbrev "1"
|
||||
|
||||
npmlog@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-5.0.1.tgz#f06678e80e29419ad67ab964e0fa69959c1eb8b0"
|
||||
integrity sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==
|
||||
dependencies:
|
||||
are-we-there-yet "^2.0.0"
|
||||
console-control-strings "^1.1.0"
|
||||
gauge "^3.0.0"
|
||||
set-blocking "^2.0.0"
|
||||
|
||||
object-assign@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
|
||||
|
||||
once@^1.3.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
||||
integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
|
||||
dependencies:
|
||||
wrappy "1"
|
||||
|
||||
path-is-absolute@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
||||
integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==
|
||||
|
||||
readable-stream@^3.6.0:
|
||||
version "3.6.2"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967"
|
||||
integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==
|
||||
dependencies:
|
||||
inherits "^2.0.3"
|
||||
string_decoder "^1.1.1"
|
||||
util-deprecate "^1.0.1"
|
||||
|
||||
rimraf@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
|
||||
integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
|
||||
dependencies:
|
||||
glob "^7.1.3"
|
||||
|
||||
safe-buffer@~5.2.0:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
||||
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
||||
|
||||
semver@^6.0.0:
|
||||
version "6.3.1"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
|
||||
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
|
||||
|
||||
semver@^7.3.5:
|
||||
version "7.5.4"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e"
|
||||
integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==
|
||||
dependencies:
|
||||
lru-cache "^6.0.0"
|
||||
|
||||
set-blocking@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
|
||||
integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==
|
||||
|
||||
signal-exit@^3.0.0:
|
||||
version "3.0.7"
|
||||
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
|
||||
integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
|
||||
|
||||
"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.2.3:
|
||||
version "4.2.3"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
||||
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
||||
dependencies:
|
||||
emoji-regex "^8.0.0"
|
||||
is-fullwidth-code-point "^3.0.0"
|
||||
strip-ansi "^6.0.1"
|
||||
|
||||
string_decoder@^1.1.1:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
|
||||
integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
|
||||
dependencies:
|
||||
safe-buffer "~5.2.0"
|
||||
|
||||
strip-ansi@^6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
|
||||
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
||||
dependencies:
|
||||
ansi-regex "^5.0.1"
|
||||
|
||||
tar@^6.1.11:
|
||||
version "6.2.0"
|
||||
resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.0.tgz#b14ce49a79cb1cd23bc9b016302dea5474493f73"
|
||||
integrity sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==
|
||||
dependencies:
|
||||
chownr "^2.0.0"
|
||||
fs-minipass "^2.0.0"
|
||||
minipass "^5.0.0"
|
||||
minizlib "^2.1.1"
|
||||
mkdirp "^1.0.3"
|
||||
yallist "^4.0.0"
|
||||
|
||||
tr46@~0.0.3:
|
||||
version "0.0.3"
|
||||
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
|
||||
integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==
|
||||
|
||||
util-deprecate@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||
integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
|
||||
|
||||
webidl-conversions@^3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
|
||||
integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==
|
||||
|
||||
whatwg-url@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
|
||||
integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==
|
||||
dependencies:
|
||||
tr46 "~0.0.3"
|
||||
webidl-conversions "^3.0.0"
|
||||
|
||||
wide-align@^1.1.2:
|
||||
version "1.1.5"
|
||||
resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3"
|
||||
integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==
|
||||
dependencies:
|
||||
string-width "^1.0.2 || 2 || 3 || 4"
|
||||
|
||||
wrappy@1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
||||
integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
|
||||
|
||||
yallist@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
|
||||
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
|
Loading…
Reference in New Issue
Block a user