feat: initial new openapi importer implementation
This commit is contained in:
8
packages/hoppscotch-app/globals.d.ts
vendored
Normal file
8
packages/hoppscotch-app/globals.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
/*
|
||||
* Some helpful type definitions to help with type checking
|
||||
*/
|
||||
|
||||
interface Object {
|
||||
// Allows for TypeScript to know this field now exist
|
||||
hasOwnProperty<K extends PropertyKey>(key: K): this is Record<K, unknown>
|
||||
}
|
||||
@@ -1,3 +1,7 @@
|
||||
import HoppRESTCollImporter from "./hopp"
|
||||
import NewOpenAPIImporter from "./newopenapi"
|
||||
|
||||
export const RESTCollectionImporters = [HoppRESTCollImporter] as const
|
||||
export const RESTCollectionImporters = [
|
||||
HoppRESTCollImporter,
|
||||
NewOpenAPIImporter,
|
||||
] as const
|
||||
|
||||
@@ -0,0 +1,491 @@
|
||||
import {
|
||||
OpenAPI,
|
||||
OpenAPIV2,
|
||||
OpenAPIV3,
|
||||
OpenAPIV3_1 as OpenAPIV31,
|
||||
} from "openapi-types"
|
||||
import SwaggerParser from "@apidevtools/swagger-parser"
|
||||
import {
|
||||
FormDataKeyValue,
|
||||
HoppRESTAuth,
|
||||
HoppRESTHeader,
|
||||
HoppRESTParam,
|
||||
HoppRESTReqBody,
|
||||
HoppRESTRequest,
|
||||
knownContentTypes,
|
||||
makeRESTRequest,
|
||||
} from "@hoppscotch/data"
|
||||
import { pipe, flow } from "fp-ts/function"
|
||||
import * as A from "fp-ts/Array"
|
||||
import * as S from "fp-ts/string"
|
||||
import * as O from "fp-ts/Option"
|
||||
import * as TE from "fp-ts/TaskEither"
|
||||
import * as RA from "fp-ts/ReadonlyArray"
|
||||
import { step } from "../steps"
|
||||
import { defineImporter, IMPORTER_INVALID_FILE_FORMAT } from "."
|
||||
import { Collection, makeCollection } from "~/newstore/collections"
|
||||
|
||||
const OPENAPI_DEREF_ERROR = "openapi/deref_error" as const
|
||||
|
||||
// TODO: YAMLLLLLLL import support!!!!!
|
||||
// TODO: Oauth!
|
||||
|
||||
const safeParseJSON = (str: string) => O.tryCatch(() => JSON.parse(str))
|
||||
|
||||
const objectHasProperty = <T extends string>(
|
||||
obj: unknown,
|
||||
propName: T
|
||||
// eslint-disable-next-line
|
||||
): obj is { [propName in T]: unknown } =>
|
||||
!!obj &&
|
||||
typeof obj === "object" &&
|
||||
Object.prototype.hasOwnProperty.call(obj, propName)
|
||||
|
||||
type OpenAPIPathInfoType =
|
||||
| OpenAPIV2.PathItemObject<{}>
|
||||
| OpenAPIV3.PathItemObject<{}>
|
||||
| OpenAPIV31.PathItemObject<{}>
|
||||
|
||||
type OpenAPIParamsType =
|
||||
| OpenAPIV2.ParameterObject
|
||||
| OpenAPIV3.ParameterObject
|
||||
| OpenAPIV31.ParameterObject
|
||||
|
||||
type OpenAPIOperationType =
|
||||
| OpenAPIV2.OperationObject
|
||||
| OpenAPIV3.OperationObject
|
||||
| OpenAPIV31.OperationObject
|
||||
|
||||
// Removes the OpenAPI Path Templating to the Hoppscotch Templating (<< ? >>)
|
||||
const replaceOpenApiPathTemplating = flow(
|
||||
S.replace(/{/g, "<<"),
|
||||
S.replace(/}/g, ">>")
|
||||
)
|
||||
|
||||
const parseOpenAPIParams = (params: OpenAPIParamsType[]): HoppRESTParam[] =>
|
||||
pipe(
|
||||
params,
|
||||
|
||||
A.filterMap(
|
||||
flow(
|
||||
O.fromPredicate((param) => param.in === "query"),
|
||||
O.map(
|
||||
(param) =>
|
||||
<HoppRESTParam>{
|
||||
key: param.name,
|
||||
value: "", // TODO: Can we do anything more ? (parse default values maybe)
|
||||
active: true,
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
const parseOpenAPIHeaders = (params: OpenAPIParamsType[]): HoppRESTHeader[] =>
|
||||
pipe(
|
||||
params,
|
||||
|
||||
A.filterMap(
|
||||
flow(
|
||||
O.fromPredicate((param) => param.in === "header"),
|
||||
O.map(
|
||||
(header) =>
|
||||
<HoppRESTParam>{
|
||||
key: header.name,
|
||||
value: "", // TODO: Can we do anything more ? (parse default values maybe)
|
||||
active: true,
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
const parseOpenAPIV2Body = (op: OpenAPIV2.OperationObject): HoppRESTReqBody => {
|
||||
const obj = (op.consumes ?? [])[0] as string | undefined
|
||||
|
||||
// Not a content-type Hoppscotch supports
|
||||
if (!obj || !(obj in knownContentTypes))
|
||||
return { contentType: null, body: null }
|
||||
|
||||
// Textual Content Types, so we just parse it and keep
|
||||
if (
|
||||
obj !== "multipart/form-data" &&
|
||||
obj !== "application/x-www-form-urlencoded"
|
||||
)
|
||||
return { contentType: obj as any, body: "" }
|
||||
|
||||
const formDataValues = pipe(
|
||||
(op.parameters ?? []) as OpenAPIV2.Parameter[],
|
||||
|
||||
A.filterMap(
|
||||
flow(
|
||||
O.fromPredicate((param) => param.in === "body"),
|
||||
O.map(
|
||||
(param) =>
|
||||
<FormDataKeyValue>{
|
||||
key: param.name,
|
||||
isFile: false,
|
||||
value: "",
|
||||
active: true,
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
return obj === "application/x-www-form-urlencoded"
|
||||
? {
|
||||
contentType: obj,
|
||||
body: formDataValues.map(({ key }) => `${key}: `).join("\n"),
|
||||
}
|
||||
: { contentType: obj, body: formDataValues }
|
||||
}
|
||||
|
||||
const parseOpenAPIV3BodyFormData = (
|
||||
contentType: "multipart/form-data" | "application/x-www-form-urlencoded",
|
||||
mediaObj: OpenAPIV3.MediaTypeObject | OpenAPIV31.MediaTypeObject
|
||||
): HoppRESTReqBody => {
|
||||
const schema = mediaObj.schema as
|
||||
| OpenAPIV3.SchemaObject
|
||||
| OpenAPIV31.SchemaObject
|
||||
| undefined
|
||||
|
||||
if (!schema || schema.type !== "object") {
|
||||
return contentType === "application/x-www-form-urlencoded"
|
||||
? { contentType, body: "" }
|
||||
: { contentType, body: [] }
|
||||
}
|
||||
|
||||
const keys = Object.keys(schema.properties ?? {})
|
||||
|
||||
if (contentType === "application/x-www-form-urlencoded") {
|
||||
return {
|
||||
contentType,
|
||||
body: keys.map((key) => `${key}: `).join("\n"),
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
contentType,
|
||||
body: keys.map(
|
||||
(key) =>
|
||||
<FormDataKeyValue>{ key, value: "", isFile: false, active: true }
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const parseOpenAPIV3Body = (
|
||||
op: OpenAPIV3.OperationObject | OpenAPIV31.OperationObject
|
||||
): HoppRESTReqBody => {
|
||||
const objs = Object.entries(
|
||||
(
|
||||
op.requestBody as
|
||||
| OpenAPIV3.RequestBodyObject
|
||||
| OpenAPIV31.RequestBodyObject
|
||||
| undefined
|
||||
)?.content ?? {}
|
||||
)
|
||||
|
||||
if (objs.length === 0) return { contentType: null, body: null }
|
||||
|
||||
// We only take the first definition
|
||||
const [contentType, media]: [
|
||||
string,
|
||||
OpenAPIV3.MediaTypeObject | OpenAPIV31.MediaTypeObject
|
||||
] = objs[0]
|
||||
|
||||
return contentType in knownContentTypes
|
||||
? contentType === "multipart/form-data" ||
|
||||
contentType === "application/x-www-form-urlencoded"
|
||||
? parseOpenAPIV3BodyFormData(contentType, media)
|
||||
: { contentType: contentType as any, body: "" }
|
||||
: { contentType: null, body: null }
|
||||
}
|
||||
|
||||
const isOpenAPIV3Operation = (
|
||||
doc: OpenAPI.Document,
|
||||
op: OpenAPIOperationType
|
||||
): op is OpenAPIV3.OperationObject | OpenAPIV31.OperationObject =>
|
||||
objectHasProperty(doc, "openapi") &&
|
||||
typeof doc.openapi === "string" &&
|
||||
doc.openapi.startsWith("3.")
|
||||
|
||||
const parseOpenAPIBody = (
|
||||
doc: OpenAPI.Document,
|
||||
op: OpenAPIOperationType
|
||||
): HoppRESTReqBody =>
|
||||
isOpenAPIV3Operation(doc, op)
|
||||
? parseOpenAPIV3Body(op)
|
||||
: parseOpenAPIV2Body(op)
|
||||
|
||||
const resolveOpenAPIV3SecurityObj = (
|
||||
scheme: OpenAPIV3.SecuritySchemeObject | OpenAPIV31.SecuritySchemeObject,
|
||||
_schemeData: string[] // Used for OAuth to pass params
|
||||
): HoppRESTAuth => {
|
||||
if (scheme.type === "http") {
|
||||
if (scheme.scheme === "basic") {
|
||||
// Basic
|
||||
return { authType: "basic", authActive: true, username: "", password: "" }
|
||||
} else if (scheme.scheme === "bearer") {
|
||||
// Bearer
|
||||
return { authType: "bearer", authActive: true, token: "" }
|
||||
} else {
|
||||
// Unknown/Unsupported Scheme
|
||||
return { authType: "none", authActive: true }
|
||||
}
|
||||
} else if (scheme.type === "apiKey") {
|
||||
if (scheme.in === "header") {
|
||||
return {
|
||||
authType: "api-key",
|
||||
authActive: true,
|
||||
addTo: "Headers",
|
||||
key: scheme.name,
|
||||
value: "",
|
||||
}
|
||||
} else if (scheme.in === "query") {
|
||||
return {
|
||||
authType: "api-key",
|
||||
authActive: true,
|
||||
addTo: "Query params",
|
||||
key: scheme.in,
|
||||
value: "",
|
||||
}
|
||||
}
|
||||
} else if (scheme.type === "oauth2") {
|
||||
// TODO: Implement Oauth
|
||||
}
|
||||
|
||||
return { authType: "none", authActive: true }
|
||||
}
|
||||
|
||||
const resolveOpenAPIV3SecurityScheme = (
|
||||
doc: OpenAPIV3.Document | OpenAPIV31.Document,
|
||||
schemeName: string,
|
||||
schemeData: string[]
|
||||
): HoppRESTAuth => {
|
||||
const scheme = doc.components?.securitySchemes?.[schemeName] as
|
||||
| OpenAPIV3.SecuritySchemeObject
|
||||
| undefined
|
||||
|
||||
if (!scheme) return { authType: "none", authActive: true }
|
||||
else return resolveOpenAPIV3SecurityObj(scheme, schemeData)
|
||||
}
|
||||
|
||||
const resolveOpenAPIV3Security = (
|
||||
doc: OpenAPIV3.Document | OpenAPIV31.Document,
|
||||
security:
|
||||
| OpenAPIV3.SecurityRequirementObject[]
|
||||
| OpenAPIV31.SecurityRequirementObject[]
|
||||
): HoppRESTAuth => {
|
||||
// NOTE: Hoppscotch only considers the first security requirement
|
||||
const sec = security[0] as OpenAPIV3.SecurityRequirementObject | undefined
|
||||
|
||||
if (!sec) return { authType: "none", authActive: true }
|
||||
|
||||
// NOTE: We only consider the first security condition within the first condition
|
||||
const [schemeName, schemeData] = (Object.entries(sec)[0] ?? [
|
||||
undefined,
|
||||
undefined,
|
||||
]) as [string | undefined, string[] | undefined]
|
||||
|
||||
if (!schemeName || !schemeData) return { authType: "none", authActive: true }
|
||||
|
||||
return resolveOpenAPIV3SecurityScheme(doc, schemeName, schemeData)
|
||||
}
|
||||
|
||||
const parseOpenAPIV3Auth = (
|
||||
doc: OpenAPIV3.Document | OpenAPIV31.Document,
|
||||
op: OpenAPIV3.OperationObject | OpenAPIV31.OperationObject
|
||||
): HoppRESTAuth => {
|
||||
const rootAuth = doc.security
|
||||
? resolveOpenAPIV3Security(doc, doc.security)
|
||||
: undefined
|
||||
const opAuth = op.security
|
||||
? resolveOpenAPIV3Security(doc, op.security)
|
||||
: undefined
|
||||
|
||||
return opAuth ?? rootAuth ?? { authType: "none", authActive: true }
|
||||
}
|
||||
|
||||
const resolveOpenAPIV2SecurityScheme = (
|
||||
scheme: OpenAPIV2.SecuritySchemeObject,
|
||||
_schemeData: string[]
|
||||
): HoppRESTAuth => {
|
||||
if (scheme.type === "basic") {
|
||||
return { authType: "basic", authActive: true, username: "", password: "" }
|
||||
} else if (scheme.type === "apiKey") {
|
||||
// V2 only supports in: header and in: query
|
||||
return {
|
||||
authType: "api-key",
|
||||
addTo: scheme.in === "header" ? "Headers" : "Query params",
|
||||
authActive: true,
|
||||
key: scheme.name,
|
||||
value: "",
|
||||
}
|
||||
} else if (scheme.type === "oauth2") {
|
||||
// TODO: Implement OAuth2
|
||||
}
|
||||
|
||||
return { authType: "none", authActive: true }
|
||||
}
|
||||
|
||||
const resolveOpenAPIV2SecurityDef = (
|
||||
doc: OpenAPIV2.Document,
|
||||
schemeName: string,
|
||||
schemeData: string[]
|
||||
): HoppRESTAuth => {
|
||||
const scheme = Object.entries(doc.securityDefinitions ?? {}).find(
|
||||
([name]) => schemeName === name
|
||||
)
|
||||
|
||||
if (!scheme) return { authType: "none", authActive: true }
|
||||
|
||||
const schemeObj = scheme[1]
|
||||
|
||||
return resolveOpenAPIV2SecurityScheme(schemeObj, schemeData)
|
||||
}
|
||||
|
||||
const resolveOpenAPIV2Security = (
|
||||
doc: OpenAPIV2.Document,
|
||||
security: OpenAPIV2.SecurityRequirementObject[]
|
||||
): HoppRESTAuth => {
|
||||
// NOTE: Hoppscotch only considers the first security requirement
|
||||
const sec = security[0] as OpenAPIV2.SecurityRequirementObject | undefined
|
||||
|
||||
if (!sec) return { authType: "none", authActive: true }
|
||||
|
||||
// NOTE: We only consider the first security condition within the first condition
|
||||
const [schemeName, schemeData] = (Object.entries(sec)[0] ?? [
|
||||
undefined,
|
||||
undefined,
|
||||
]) as [string | undefined, string[] | undefined]
|
||||
|
||||
if (!schemeName || !schemeData) return { authType: "none", authActive: true }
|
||||
|
||||
return resolveOpenAPIV2SecurityDef(doc, schemeName, schemeData)
|
||||
}
|
||||
|
||||
const parseOpenAPIV2Auth = (
|
||||
doc: OpenAPIV2.Document,
|
||||
op: OpenAPIV2.OperationObject
|
||||
): HoppRESTAuth => {
|
||||
const rootAuth = doc.security
|
||||
? resolveOpenAPIV2Security(doc, doc.security)
|
||||
: undefined
|
||||
const opAuth = op.security
|
||||
? resolveOpenAPIV2Security(doc, op.security)
|
||||
: undefined
|
||||
|
||||
return opAuth ?? rootAuth ?? { authType: "none", authActive: true }
|
||||
}
|
||||
|
||||
const parseOpenAPIAuth = (
|
||||
doc: OpenAPI.Document,
|
||||
op: OpenAPIOperationType
|
||||
): HoppRESTAuth =>
|
||||
isOpenAPIV3Operation(doc, op)
|
||||
? parseOpenAPIV3Auth(doc as OpenAPIV3.Document | OpenAPIV31.Document, op)
|
||||
: parseOpenAPIV2Auth(doc as OpenAPIV2.Document, op)
|
||||
|
||||
const convertPathToHoppReqs = (
|
||||
doc: OpenAPI.Document,
|
||||
pathName: string,
|
||||
pathObj: OpenAPIPathInfoType
|
||||
) =>
|
||||
pipe(
|
||||
["get", "head", "post", "put", "delete", "options"] as const,
|
||||
|
||||
// Filter and map out path info
|
||||
RA.filterMap(
|
||||
flow(
|
||||
O.fromPredicate((method) => !!pathObj[method]),
|
||||
O.map((method) => ({ method, info: pathObj[method]! }))
|
||||
)
|
||||
),
|
||||
|
||||
// Construct request object
|
||||
RA.map(({ method, info }) =>
|
||||
makeRESTRequest({
|
||||
name: info.operationId ?? "Untitled Request",
|
||||
method,
|
||||
endpoint: `<<baseUrl>>${replaceOpenApiPathTemplating(pathName)}`, // TODO: Make this proper
|
||||
|
||||
// We don't need to worry about reference types as the Dereferencing pass should remove them
|
||||
params: parseOpenAPIParams(
|
||||
(info.parameters as OpenAPIParamsType[]) ?? []
|
||||
),
|
||||
headers: parseOpenAPIHeaders(
|
||||
(info.parameters as OpenAPIParamsType[]) ?? []
|
||||
),
|
||||
|
||||
auth: parseOpenAPIAuth(doc, info),
|
||||
|
||||
body: parseOpenAPIBody(doc, info),
|
||||
|
||||
preRequestScript: "",
|
||||
testScript: "",
|
||||
})
|
||||
),
|
||||
|
||||
// Disable Readonly
|
||||
RA.toArray
|
||||
)
|
||||
|
||||
const convertOpenApiDocToHopp = (
|
||||
doc: OpenAPI.Document
|
||||
): TE.TaskEither<never, Collection<HoppRESTRequest>> => {
|
||||
const name = doc.info.title
|
||||
|
||||
const paths = Object.entries(doc.paths ?? {})
|
||||
.map(([pathName, pathObj]) => convertPathToHoppReqs(doc, pathName, pathObj))
|
||||
.flat()
|
||||
|
||||
return TE.of(
|
||||
makeCollection<HoppRESTRequest>({
|
||||
name,
|
||||
folders: [],
|
||||
requests: paths,
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
export default defineImporter({
|
||||
name: "Swagger/OpenAPI v3 Schema",
|
||||
steps: [
|
||||
step({
|
||||
stepName: "FILE_OR_URL_IMPORT",
|
||||
metadata: {
|
||||
acceptedFileTypes: "application/json",
|
||||
},
|
||||
}),
|
||||
] as const,
|
||||
importer: ([fileContent]) =>
|
||||
pipe(
|
||||
// See if we can parse JSON properly
|
||||
fileContent,
|
||||
safeParseJSON,
|
||||
TE.fromOption(() => IMPORTER_INVALID_FILE_FORMAT),
|
||||
|
||||
// Try validating, else the importer is invalid file format
|
||||
TE.chainW((obj) =>
|
||||
pipe(
|
||||
TE.tryCatch(
|
||||
() => SwaggerParser.validate(obj),
|
||||
() => IMPORTER_INVALID_FILE_FORMAT
|
||||
)
|
||||
)
|
||||
),
|
||||
|
||||
// Deference the references
|
||||
TE.chainW((obj) =>
|
||||
pipe(
|
||||
TE.tryCatch(
|
||||
() => SwaggerParser.dereference(obj),
|
||||
() => OPENAPI_DEREF_ERROR
|
||||
)
|
||||
)
|
||||
),
|
||||
|
||||
TE.chainW(convertOpenApiDocToHopp)
|
||||
),
|
||||
})
|
||||
@@ -33,6 +33,7 @@
|
||||
"gql-codegen": "graphql-codegen --config gql-codegen.yml"
|
||||
},
|
||||
"dependencies": {
|
||||
"@apidevtools/swagger-parser": "^10.0.3",
|
||||
"@apollo/client": "^3.5.6",
|
||||
"@codemirror/autocomplete": "^0.19.9",
|
||||
"@codemirror/closebrackets": "^0.19.0",
|
||||
@@ -88,6 +89,7 @@
|
||||
"mustache": "^4.2.0",
|
||||
"node-interval-tree": "^1.3.3",
|
||||
"nuxt": "^2.15.8",
|
||||
"openapi-types": "^10.0.0",
|
||||
"paho-mqtt": "^1.1.0",
|
||||
"rxjs": "^7.5.1",
|
||||
"socket.io-client-v2": "npm:socket.io-client@^2.4.0",
|
||||
|
||||
83
pnpm-lock.yaml
generated
83
pnpm-lock.yaml
generated
@@ -42,6 +42,7 @@ importers:
|
||||
|
||||
packages/hoppscotch-app:
|
||||
specifiers:
|
||||
'@apidevtools/swagger-parser': ^10.0.3
|
||||
'@apollo/client': ^3.5.6
|
||||
'@babel/core': ^7.16.7
|
||||
'@babel/preset-env': ^7.16.7
|
||||
@@ -144,6 +145,7 @@ importers:
|
||||
npm-run-all: ^4.1.5
|
||||
nuxt: ^2.15.8
|
||||
nuxt-windicss: ^2.2.2
|
||||
openapi-types: ^10.0.0
|
||||
paho-mqtt: ^1.1.0
|
||||
prettier: ^2.5.1
|
||||
raw-loader: ^4.0.2
|
||||
@@ -177,6 +179,7 @@ importers:
|
||||
worker-loader: ^3.0.8
|
||||
yargs-parser: ^21.0.0
|
||||
dependencies:
|
||||
'@apidevtools/swagger-parser': 10.0.3_openapi-types@10.0.0
|
||||
'@apollo/client': 3.5.6_f3f7eb5e21785ef7d5faca94c1a68824
|
||||
'@codemirror/autocomplete': 0.19.9
|
||||
'@codemirror/closebrackets': 0.19.0
|
||||
@@ -232,6 +235,7 @@ importers:
|
||||
mustache: 4.2.0
|
||||
node-interval-tree: 1.3.3
|
||||
nuxt: 2.15.8_typescript@4.5.4
|
||||
openapi-types: 10.0.0
|
||||
paho-mqtt: 1.1.0
|
||||
rxjs: 7.5.1
|
||||
socket.io-client-v2: /socket.io-client/2.4.0
|
||||
@@ -372,6 +376,38 @@ packages:
|
||||
dependencies:
|
||||
'@types/throttle-debounce': 2.1.0
|
||||
|
||||
/@apidevtools/json-schema-ref-parser/9.0.9:
|
||||
resolution: {integrity: sha512-GBD2Le9w2+lVFoc4vswGI/TjkNIZSVp7+9xPf+X3uidBfWnAeUWmquteSyt0+VCrhNMWj/FTABISQrD3Z/YA+w==}
|
||||
dependencies:
|
||||
'@jsdevtools/ono': 7.1.3
|
||||
'@types/json-schema': 7.0.9
|
||||
call-me-maybe: 1.0.1
|
||||
js-yaml: 4.1.0
|
||||
dev: false
|
||||
|
||||
/@apidevtools/openapi-schemas/2.1.0:
|
||||
resolution: {integrity: sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==}
|
||||
engines: {node: '>=10'}
|
||||
dev: false
|
||||
|
||||
/@apidevtools/swagger-methods/3.0.2:
|
||||
resolution: {integrity: sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==}
|
||||
dev: false
|
||||
|
||||
/@apidevtools/swagger-parser/10.0.3_openapi-types@10.0.0:
|
||||
resolution: {integrity: sha512-sNiLY51vZOmSPFZA5TF35KZ2HbgYklQnTSDnkghamzLb3EkNtcQnrBQEj5AOCxHpTtXpqMCRM1CrmV2rG6nw4g==}
|
||||
peerDependencies:
|
||||
openapi-types: '>=7'
|
||||
dependencies:
|
||||
'@apidevtools/json-schema-ref-parser': 9.0.9
|
||||
'@apidevtools/openapi-schemas': 2.1.0
|
||||
'@apidevtools/swagger-methods': 3.0.2
|
||||
'@jsdevtools/ono': 7.1.3
|
||||
call-me-maybe: 1.0.1
|
||||
openapi-types: 10.0.0
|
||||
z-schema: 5.0.2
|
||||
dev: false
|
||||
|
||||
/@apollo/client/3.5.6_f3f7eb5e21785ef7d5faca94c1a68824:
|
||||
resolution: {integrity: sha512-XHoouuEJ4L37mtfftcHHO1caCRrKKAofAwqRoq28UQIPMJk+e7n3X9OtRRNXKk/9tmhNkwelSary+EilfPwI7A==}
|
||||
peerDependencies:
|
||||
@@ -3413,6 +3449,10 @@ packages:
|
||||
chalk: 4.1.2
|
||||
dev: true
|
||||
|
||||
/@jsdevtools/ono/7.1.3:
|
||||
resolution: {integrity: sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==}
|
||||
dev: false
|
||||
|
||||
/@lezer/common/0.15.10:
|
||||
resolution: {integrity: sha512-vlr+be73zTDoQBIknBVOh/633tmbQcjxUu9PIeVeYESeBK3V6TuBW96RRFg93Y2cyK9lglz241gOgSn452HFvA==}
|
||||
dev: false
|
||||
@@ -3662,11 +3702,11 @@ packages:
|
||||
ufo: 0.7.9
|
||||
dev: false
|
||||
|
||||
/@nuxt/kit-edge/3.0.0-27338323.1e98259:
|
||||
resolution: {integrity: sha512-lABruok/JkKOoEJNpkZ2M6YMSKBgOaWAyWjDq+Ekk4Ga/FZgok+epTcN3cQBOP/MpH3PXsM2L3zdM8DoEMxeug==}
|
||||
/@nuxt/kit-edge/3.0.0-27356801.e9128f3:
|
||||
resolution: {integrity: sha512-hGiqZydtMiK+UhHBsdD0WC+fHeI3xyJixhY2rNPGwFrzdeTrbUy8YH451SbRPOJ8TS0RYQ+cUT6JfMr0YTpnfg==}
|
||||
engines: {node: ^14.16.0 || ^16.11.0 || ^17.0.0}
|
||||
dependencies:
|
||||
'@nuxt/schema': /@nuxt/schema-edge/3.0.0-27338323.1e98259
|
||||
'@nuxt/schema': /@nuxt/schema-edge/3.0.0-27356801.e9128f3
|
||||
consola: 2.15.3
|
||||
defu: 5.0.0
|
||||
dotenv: 10.0.0
|
||||
@@ -3704,8 +3744,8 @@ packages:
|
||||
node-fetch: 2.6.6
|
||||
dev: false
|
||||
|
||||
/@nuxt/schema-edge/3.0.0-27338323.1e98259:
|
||||
resolution: {integrity: sha512-TV8HMFEkD2cMLnsYBE0+wQcOSwElw6SW4rnDOFoDhHI61GeflpGZOfXLQRJS2FLAyMv/QVeBHdd+PWWOxDqGgA==}
|
||||
/@nuxt/schema-edge/3.0.0-27356801.e9128f3:
|
||||
resolution: {integrity: sha512-LOi5OLFzxrHL7t/a7sn2+fnkNN8y9ipnLG6l6McI+vEuzXi11YeHCYt7PmoqqySXx411hd6lISmYd/aZzBgYkg==}
|
||||
engines: {node: ^14.16.0 || ^16.11.0 || ^17.0.0}
|
||||
dependencies:
|
||||
create-require: 1.1.1
|
||||
@@ -5843,7 +5883,6 @@ packages:
|
||||
|
||||
/argparse/2.0.1:
|
||||
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
|
||||
dev: true
|
||||
|
||||
/aria-query/5.0.0:
|
||||
resolution: {integrity: sha512-V+SM7AbUwJ+EBnB8+DXs0hPZHO0W6pqBcc0dW90OwtVG02PswOu/teuARoLQjdDOH+t9pJgGnW5/Qmouf3gPJg==}
|
||||
@@ -6702,6 +6741,10 @@ packages:
|
||||
function-bind: 1.1.1
|
||||
get-intrinsic: 1.1.1
|
||||
|
||||
/call-me-maybe/1.0.1:
|
||||
resolution: {integrity: sha1-JtII6onje1y95gJQoV8DHBak1ms=}
|
||||
dev: false
|
||||
|
||||
/caller-callsite/2.0.0:
|
||||
resolution: {integrity: sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=}
|
||||
engines: {node: '>=4'}
|
||||
@@ -11875,7 +11918,6 @@ packages:
|
||||
hasBin: true
|
||||
dependencies:
|
||||
argparse: 2.0.1
|
||||
dev: true
|
||||
|
||||
/jsdom/16.7.0:
|
||||
resolution: {integrity: sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==}
|
||||
@@ -12374,6 +12416,10 @@ packages:
|
||||
resolution: {integrity: sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=}
|
||||
dev: true
|
||||
|
||||
/lodash.isequal/4.5.0:
|
||||
resolution: {integrity: sha1-QVxEePK8wwEgwizhDtMib30+GOA=}
|
||||
dev: false
|
||||
|
||||
/lodash.isinteger/4.0.4:
|
||||
resolution: {integrity: sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=}
|
||||
dev: true
|
||||
@@ -13320,7 +13366,7 @@ packages:
|
||||
/nuxt-windicss/2.2.2:
|
||||
resolution: {integrity: sha512-4tvzk9d2TUFxloty187D+wmO8ZNAvpSmRJ5HQO3/AvZdMMhAl4gomXR9fCgFKQe7Fxcj9nIKNInOx8TWowjiqA==}
|
||||
dependencies:
|
||||
'@nuxt/kit': /@nuxt/kit-edge/3.0.0-27338323.1e98259
|
||||
'@nuxt/kit': /@nuxt/kit-edge/3.0.0-27356801.e9128f3
|
||||
'@windicss/plugin-utils': 1.6.1
|
||||
consola: 2.15.3
|
||||
defu: 5.0.0
|
||||
@@ -13475,6 +13521,10 @@ packages:
|
||||
is-wsl: 2.2.0
|
||||
dev: true
|
||||
|
||||
/openapi-types/10.0.0:
|
||||
resolution: {integrity: sha512-Y8xOCT2eiKGYDzMW9R4x5cmfc3vGaaI4EL2pwhDmodWw1HlK18YcZ4uJxc7Rdp7/gGzAygzH9SXr6GKYIXbRcQ==}
|
||||
dev: false
|
||||
|
||||
/opener/1.5.2:
|
||||
resolution: {integrity: sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==}
|
||||
hasBin: true
|
||||
@@ -17666,6 +17716,11 @@ packages:
|
||||
spdx-expression-parse: 3.0.1
|
||||
dev: true
|
||||
|
||||
/validator/13.7.0:
|
||||
resolution: {integrity: sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==}
|
||||
engines: {node: '>= 0.10'}
|
||||
dev: false
|
||||
|
||||
/value-or-promise/1.0.11:
|
||||
resolution: {integrity: sha512-41BrgH+dIbCFXClcSapVs5M6GkENd3gQOJpEfPDNa71LsUGMXDL0jMWpI/Rh7WhX+Aalfz2TTS3Zt5pUsbnhLg==}
|
||||
engines: {node: '>=12'}
|
||||
@@ -18502,6 +18557,18 @@ packages:
|
||||
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
/z-schema/5.0.2:
|
||||
resolution: {integrity: sha512-40TH47ukMHq5HrzkeVE40Ad7eIDKaRV2b+Qpi2prLc9X9eFJFzV7tMe5aH12e6avaSS/u5l653EQOv+J9PirPw==}
|
||||
engines: {node: '>=8.0.0'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
lodash.get: 4.4.2
|
||||
lodash.isequal: 4.5.0
|
||||
validator: 13.7.0
|
||||
optionalDependencies:
|
||||
commander: 2.20.3
|
||||
dev: false
|
||||
|
||||
/zen-observable-ts/1.2.3:
|
||||
resolution: {integrity: sha512-hc/TGiPkAWpByykMwDcem3SdUgA4We+0Qb36bItSuJC9xD0XVBZoFHYoadAomDSNf64CG8Ydj0Qb8Od8BUWz5g==}
|
||||
dependencies:
|
||||
|
||||
Reference in New Issue
Block a user