feat(common): add support for post/put body schemas in openapi import (#5322)

Co-authored-by: jamesgeorge007 <25279263+jamesgeorge007@users.noreply.github.com>
This commit is contained in:
Anwarul Islam 2025-08-20 18:13:24 +06:00 committed by GitHub
parent 3994d9e9a0
commit bb25c59942
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 639 additions and 34 deletions

View file

@ -26,6 +26,14 @@ export const safeParseJSON: SafeParseJSON = (str, convertToArray = false) =>
return data
})
/**
* Generates a prettified JSON representation of an object
* @param obj The object to get the representation of
* @returns The prettified JSON string of the object
*/
export const prettyPrintJSON = (obj: unknown): O.Option<string> =>
O.tryCatch(() => JSON.stringify(obj, null, "\t"))
/**
* Checks if given string is a JSON string
* @param str Raw string to be checked

View file

@ -0,0 +1,189 @@
import { OpenAPIV2 } from "openapi-types"
import * as O from "fp-ts/Option"
import { pipe, flow } from "fp-ts/function"
import * as A from "fp-ts/Array"
import { prettyPrintJSON } from "~/helpers/functional/json"
type PrimitiveSchemaType = "string" | "integer" | "number" | "boolean"
type SchemaType = "array" | "object" | PrimitiveSchemaType
type PrimitiveRequestBodyExample = number | string | boolean
type RequestBodyExample =
| { [name: string]: RequestBodyExample }
| Array<RequestBodyExample>
| PrimitiveRequestBodyExample
const getPrimitiveTypePlaceholder = (
schemaType: PrimitiveSchemaType
): PrimitiveRequestBodyExample => {
switch (schemaType) {
case "string":
return "string"
case "integer":
case "number":
return 1
case "boolean":
return true
}
}
const getSchemaTypeFromSchemaObject = (
schema: OpenAPIV2.SchemaObject
): O.Option<SchemaType> =>
pipe(
schema.type,
O.fromNullable,
O.map(
(schemaType) =>
(Array.isArray(schemaType) ? schemaType[0] : schemaType) as SchemaType
)
)
const isSchemaTypePrimitive = (
schemaType: string
): schemaType is PrimitiveSchemaType =>
["string", "integer", "number", "boolean"].includes(schemaType)
const isSchemaTypeArray = (schemaType: string): schemaType is "array" =>
schemaType === "array"
const isSchemaTypeObject = (schemaType: string): schemaType is "object" =>
schemaType === "object"
const getSampleEnumValueOrPlaceholder = (
schema: OpenAPIV2.SchemaObject
): RequestBodyExample =>
pipe(
schema.enum,
O.fromNullable,
O.map((enums) => enums[0] as RequestBodyExample),
O.altW(() =>
pipe(
schema,
getSchemaTypeFromSchemaObject,
O.filter(isSchemaTypePrimitive),
O.map(getPrimitiveTypePlaceholder)
)
),
O.getOrElseW(() => "")
)
const generateExampleArrayFromOpenAPIV2ItemsObject = (
items: OpenAPIV2.ItemsObject
): RequestBodyExample => {
// Guard against undefined items
if (!items || !items.type) {
return []
}
// ItemsObject can not hold type "object"
// https://swagger.io/specification/v2/#itemsObject
// TODO : Handle array of objects
// https://stackoverflow.com/questions/60490974/how-to-define-an-array-of-objects-in-openapi-2-0
return pipe(
items,
O.fromPredicate(
flow((items) => items.type as SchemaType, isSchemaTypePrimitive)
),
O.map(flow(getSampleEnumValueOrPlaceholder, (arrayItem) => [arrayItem])),
O.getOrElse(() =>
// If the type is not primitive, it is "array"
// items property is required if type is array
items.items
? [
generateExampleArrayFromOpenAPIV2ItemsObject(
items.items as OpenAPIV2.ItemsObject
),
]
: []
)
)
}
const generateRequestBodyExampleFromOpenAPIV2BodySchema = (
schema: OpenAPIV2.SchemaObject
): RequestBodyExample => {
if (schema.example) return schema.example as RequestBodyExample
const primitiveTypeExample = pipe(
schema,
O.fromPredicate(
flow(
getSchemaTypeFromSchemaObject,
O.map(isSchemaTypePrimitive),
O.getOrElseW(() => false) // No schema type found in the schema object, assume non-primitive
)
),
O.map(getSampleEnumValueOrPlaceholder) // Use enum or placeholder to populate primitive field
)
if (O.isSome(primitiveTypeExample)) return primitiveTypeExample.value
const arrayTypeExample = pipe(
schema,
O.fromPredicate(
flow(
getSchemaTypeFromSchemaObject,
O.map(isSchemaTypeArray),
O.getOrElseW(() => false) // No schema type found in the schema object, assume type to be different from array
)
),
O.map((schema) => schema.items as OpenAPIV2.ItemsObject),
O.filter((items) => items != null), // Filter out null/undefined items
O.map(generateExampleArrayFromOpenAPIV2ItemsObject)
)
if (O.isSome(arrayTypeExample)) return arrayTypeExample.value
return pipe(
schema,
O.fromPredicate(
flow(
getSchemaTypeFromSchemaObject,
O.map(isSchemaTypeObject),
O.getOrElseW(() => false)
)
),
O.chain((schema) =>
pipe(
schema.properties,
O.fromNullable,
O.map(
(properties) =>
Object.entries(properties) as [string, OpenAPIV2.SchemaObject][]
)
)
),
O.getOrElseW(() => [] as [string, OpenAPIV2.SchemaObject][]),
A.reduce(
{} as { [name: string]: RequestBodyExample },
(aggregatedExample, property) => {
const example = generateRequestBodyExampleFromOpenAPIV2BodySchema(
property[1]
)
aggregatedExample[property[0]] = example
return aggregatedExample
}
)
)
}
export const generateRequestBodyExampleFromOpenAPIV2Body = (
op: OpenAPIV2.OperationObject
): string =>
pipe(
(op.parameters ?? []) as OpenAPIV2.Parameter[],
A.findFirst((param) => param.in === "body"),
O.map(
flow(
(parameter) => parameter.schema,
generateRequestBodyExampleFromOpenAPIV2BodySchema
)
),
O.chain(prettyPrintJSON),
O.getOrElse(() => "")
)

View file

@ -0,0 +1,133 @@
import { OpenAPIV3 } from "openapi-types"
import { pipe } from "fp-ts/function"
import * as O from "fp-ts/Option"
type SchemaType =
| OpenAPIV3.ArraySchemaObjectType
| OpenAPIV3.NonArraySchemaObjectType
type PrimitiveSchemaType = Exclude<SchemaType, "array" | "object">
type PrimitiveRequestBodyExample = string | number | boolean | null
type RequestBodyExample =
| PrimitiveRequestBodyExample
| Array<RequestBodyExample>
| { [name: string]: RequestBodyExample }
const isSchemaTypePrimitive = (
schemaType: SchemaType
): schemaType is PrimitiveSchemaType =>
!["array", "object"].includes(schemaType)
const getPrimitiveTypePlaceholder = (
primitiveType: PrimitiveSchemaType
): PrimitiveRequestBodyExample => {
switch (primitiveType) {
case "number":
return 0.0
case "integer":
return 0
case "string":
return "string"
case "boolean":
return true
}
}
// Use carefully, call only when type is primitive
// TODO(agarwal): Use Enum values, if any
const generatePrimitiveRequestBodyExample = (
schemaObject: OpenAPIV3.NonArraySchemaObject
): RequestBodyExample =>
getPrimitiveTypePlaceholder(schemaObject.type as PrimitiveSchemaType)
// Use carefully, call only when type is object
const generateObjectRequestBodyExample = (
schemaObject: OpenAPIV3.NonArraySchemaObject
): RequestBodyExample =>
pipe(
schemaObject.properties,
O.fromNullable,
O.map(Object.entries),
O.getOrElseW(() => [] as [string, OpenAPIV3.SchemaObject][]),
(entries) =>
entries.reduce(
(acc, [key, propSchema]) => ({
...acc,
[key]: generateRequestBodyExampleFromSchemaObject(
propSchema as OpenAPIV3.SchemaObject
),
}),
{} as Record<string, RequestBodyExample>
)
)
const generateArrayRequestBodyExample = (
schemaObject: OpenAPIV3.ArraySchemaObject
): RequestBodyExample => [
generateRequestBodyExampleFromSchemaObject(
schemaObject.items as OpenAPIV3.SchemaObject
),
]
const generateRequestBodyExampleFromSchemaObject = (
schemaObject: OpenAPIV3.SchemaObject
): RequestBodyExample => {
// TODO: Handle schema objects with allof
if (schemaObject.example) return schemaObject.example as RequestBodyExample
// If request body can be oneof or allof several schema, choose the first schema to generate an example
if (schemaObject.oneOf)
return generateRequestBodyExampleFromSchemaObject(
schemaObject.oneOf[0] as OpenAPIV3.SchemaObject
)
if (schemaObject.anyOf)
return generateRequestBodyExampleFromSchemaObject(
schemaObject.anyOf[0] as OpenAPIV3.SchemaObject
)
if (!schemaObject.type) return ""
if (isSchemaTypePrimitive(schemaObject.type))
return generatePrimitiveRequestBodyExample(
schemaObject as OpenAPIV3.NonArraySchemaObject
)
if (schemaObject.type === "object")
return generateObjectRequestBodyExample(
schemaObject as OpenAPIV3.NonArraySchemaObject
)
return generateArrayRequestBodyExample(
schemaObject as OpenAPIV3.ArraySchemaObject
)
}
export const generateRequestBodyExampleFromMediaObject = (
mediaObject: OpenAPIV3.MediaTypeObject
): RequestBodyExample => {
// First check for direct example
if (mediaObject.example) return mediaObject.example as RequestBodyExample
// Then check for examples object (OpenAPI v3 format)
if (mediaObject.examples) {
const firstExample = Object.values(mediaObject.examples)[0]
if (
firstExample &&
typeof firstExample === "object" &&
"value" in firstExample
) {
return firstExample.value as RequestBodyExample
}
// Fallback if examples doesn't have the expected structure
return Object.values(mediaObject.examples)[0] as RequestBodyExample
}
// Fallback to generating from schema
return mediaObject.schema
? generateRequestBodyExampleFromSchemaObject(
mediaObject.schema as OpenAPIV3.SchemaObject
)
: ""
}

View file

@ -0,0 +1,145 @@
import { OpenAPIV3_1 as OpenAPIV31 } from "openapi-types"
import { pipe } from "fp-ts/function"
import * as O from "fp-ts/Option"
import * as A from "fp-ts/Array"
type MixedArraySchemaType = (
| OpenAPIV31.ArraySchemaObjectType
| OpenAPIV31.NonArraySchemaObjectType
)[]
type SchemaType =
| OpenAPIV31.ArraySchemaObjectType
| OpenAPIV31.NonArraySchemaObjectType
| MixedArraySchemaType
type PrimitiveSchemaType = Exclude<
OpenAPIV31.NonArraySchemaObjectType,
"object"
>
type PrimitiveRequestBodyExample = string | number | boolean | null
type RequestBodyExample =
| PrimitiveRequestBodyExample
| Array<RequestBodyExample>
| { [name: string]: RequestBodyExample }
const isSchemaTypePrimitive = (
schemaType: SchemaType
): schemaType is PrimitiveSchemaType =>
!Array.isArray(schemaType) && !["array", "object"].includes(schemaType)
const getPrimitiveTypePlaceholder = (
primitiveType: PrimitiveSchemaType
): PrimitiveRequestBodyExample => {
switch (primitiveType) {
case "number":
return 0.0
case "integer":
return 0
case "string":
return "string"
case "boolean":
return true
}
return null
}
// Use carefully, the schema type should necessarily be primitive
// TODO(agarwal): Use Enum values, if any
const generatePrimitiveRequestBodyExample = (
schemaObject: OpenAPIV31.NonArraySchemaObject
): RequestBodyExample =>
getPrimitiveTypePlaceholder(schemaObject.type as PrimitiveSchemaType)
// Use carefully, the schema type should necessarily be object
const generateObjectRequestBodyExample = (
schemaObject: OpenAPIV31.NonArraySchemaObject
): RequestBodyExample =>
pipe(
schemaObject.properties,
O.fromNullable,
O.map(
(properties) =>
Object.entries(properties) as [string, OpenAPIV31.SchemaObject][]
),
O.getOrElseW(() => [] as [string, OpenAPIV31.SchemaObject][]),
A.reduce(
{} as { [name: string]: RequestBodyExample },
(aggregatedExample, property) => {
aggregatedExample[property[0]] =
generateRequestBodyExampleFromSchemaObject(property[1])
return aggregatedExample
}
)
)
// Use carefully, the schema type should necessarily be mixed array
const generateMixedArrayRequestBodyExample = (
schemaObject: OpenAPIV31.SchemaObject
): RequestBodyExample =>
pipe(
schemaObject,
(schemaObject) => schemaObject.type as MixedArraySchemaType,
A.reduce([] as Array<RequestBodyExample>, (aggregatedExample, itemType) => {
// TODO: Figure out how to include non-primitive types as well
if (isSchemaTypePrimitive(itemType)) {
aggregatedExample.push(getPrimitiveTypePlaceholder(itemType))
}
return aggregatedExample
})
)
const generateArrayRequestBodyExample = (
schemaObject: OpenAPIV31.ArraySchemaObject
): RequestBodyExample => [
generateRequestBodyExampleFromSchemaObject(
schemaObject.items as OpenAPIV31.SchemaObject
),
]
const generateRequestBodyExampleFromSchemaObject = (
schemaObject: OpenAPIV31.SchemaObject
): RequestBodyExample => {
// TODO: Handle schema objects with oneof or anyof
if (schemaObject.example) return schemaObject.example as RequestBodyExample
if (schemaObject.examples)
return schemaObject.examples[0] as RequestBodyExample
if (!schemaObject.type) return ""
if (isSchemaTypePrimitive(schemaObject.type))
return generatePrimitiveRequestBodyExample(
schemaObject as OpenAPIV31.NonArraySchemaObject
)
if (schemaObject.type === "object")
return generateObjectRequestBodyExample(schemaObject)
if (schemaObject.type === "array")
return generateArrayRequestBodyExample(schemaObject)
return generateMixedArrayRequestBodyExample(schemaObject)
}
export const generateRequestBodyExampleFromMediaObject = (
mediaObject: OpenAPIV31.MediaTypeObject
): RequestBodyExample => {
// First check for direct example
if (mediaObject.example) return mediaObject.example as RequestBodyExample
// Then check for examples object (OpenAPI v3.1 format)
if (mediaObject.examples) {
const firstExample = Object.values(mediaObject.examples)[0]
if (
firstExample &&
typeof firstExample === "object" &&
"value" in firstExample
) {
return firstExample.value as RequestBodyExample
}
// Fallback if examples doesn't have the expected structure
return Object.values(mediaObject.examples)[0] as RequestBodyExample
}
// Fallback to generating from schema
return mediaObject.schema
? generateRequestBodyExampleFromSchemaObject(mediaObject.schema)
: ""
}

View file

@ -29,15 +29,18 @@ import * as O from "fp-ts/Option"
import * as TE from "fp-ts/TaskEither"
import * as RA from "fp-ts/ReadonlyArray"
import * as E from "fp-ts/Either"
import { IMPORTER_INVALID_FILE_FORMAT } from "."
import { IMPORTER_INVALID_FILE_FORMAT } from ".."
import { cloneDeep } from "lodash-es"
import { getStatusCodeReasonPhrase } from "~/helpers/utils/statusCodes"
import { isNumeric } from "~/helpers/utils/number"
import { generateRequestBodyExampleFromOpenAPIV2Body } from "./example-generators/v2"
import { generateRequestBodyExampleFromMediaObject as generateV3Example } from "./example-generators/v3"
import { generateRequestBodyExampleFromMediaObject as generateV31Example } from "./example-generators/v31"
export const OPENAPI_DEREF_ERROR = "openapi/deref_error" as const
const worker = new Worker(
new URL("./workers/openapi-import-worker.ts", import.meta.url),
new URL("../workers/openapi-import-worker.ts", import.meta.url),
{
type: "module",
}
@ -299,38 +302,55 @@ const parseOpenAPIV2Body = (op: OpenAPIV2.OperationObject): HoppRESTReqBody => {
if (!obj || !(obj in knownContentTypes))
return { contentType: null, body: null }
// Textual Content Types, so we just parse it and keep
// For form data types, extract form fields
if (
obj !== "multipart/form-data" &&
obj !== "application/x-www-form-urlencoded"
)
return { contentType: obj as any, body: "" }
obj === "multipart/form-data" ||
obj === "application/x-www-form-urlencoded"
) {
const formDataValues = pipe(
(op.parameters ?? []) as OpenAPIV2.Parameter[],
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,
}
A.filterMap(
flow(
O.fromPredicate((param) => param.in === "formData"),
O.map(
(param) =>
<FormDataKeyValue>{
key: param.name,
isFile: param.type === "file",
value: "",
active: true,
}
)
)
)
)
)
return obj === "application/x-www-form-urlencoded"
? {
contentType: obj,
body: formDataValues.map(({ key }) => `${key}: `).join("\n"),
return obj === "application/x-www-form-urlencoded"
? {
contentType: obj,
body: formDataValues.map(({ key }) => `${key}: `).join("\n"),
}
: { contentType: obj, body: formDataValues }
}
// For other content types (JSON, XML, etc.)
const bodyParam = (op.parameters ?? []).find(
(param) => (param as OpenAPIV2.Parameter).in === "body"
) as OpenAPIV2.InBodyParameterObject | undefined
if (bodyParam) {
const result = generateRequestBodyExampleFromOpenAPIV2Body(op)
if (result) {
return {
contentType: obj as any,
body: result,
}
: { contentType: obj, body: formDataValues }
}
}
// Fallback to empty body for textual content types
return { contentType: obj as any, body: "" }
}
const parseOpenAPIV3BodyFormData = (
@ -365,6 +385,7 @@ const parseOpenAPIV3BodyFormData = (
}
const parseOpenAPIV3Body = (
doc: OpenAPI.Document,
op: OpenAPIV3.OperationObject | OpenAPIV31.OperationObject
): HoppRESTReqBody => {
const objs = Object.entries(
@ -384,12 +405,83 @@ const parseOpenAPIV3Body = (
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 }
if (!(contentType in knownContentTypes))
return { contentType: null, body: null }
// Handle form data types
if (
contentType === "multipart/form-data" ||
contentType === "application/x-www-form-urlencoded"
)
return parseOpenAPIV3BodyFormData(contentType, media)
// For other content types (JSON, XML, etc.), try to generate sample from schema
if (media.schema) {
try {
const docAny = doc as any
const isV31 = docAny.openapi && docAny.openapi.startsWith("3.1")
let sampleBody: any
if (isV31) {
sampleBody = generateV31Example(media as any)
} else {
sampleBody = generateV3Example(media as any)
}
return {
contentType: contentType as any,
body:
typeof sampleBody === "string"
? sampleBody
: JSON.stringify(sampleBody, null, 2),
}
} catch (e) {
// If we can't generate a sample, check for examples
if (media.example !== undefined) {
return {
contentType: contentType as any,
body:
typeof media.example === "string"
? media.example
: JSON.stringify(media.example, null, 2),
}
}
// Fallback to empty body
return { contentType: contentType as any, body: "" }
}
}
// Check for examples if no schema
if (media.example !== undefined) {
return {
contentType: contentType as any,
body:
typeof media.example === "string"
? media.example
: JSON.stringify(media.example, null, 2),
}
}
// Check for examples array (OpenAPI v3 supports multiple examples)
if (media.examples && Object.keys(media.examples).length > 0) {
const firstExampleKey = Object.keys(media.examples)[0]
const firstExample = media.examples[firstExampleKey]
// Handle both Example Object and Reference Object
const exampleValue =
"value" in firstExample ? firstExample.value : firstExample
return {
contentType: contentType as any,
body:
typeof exampleValue === "string"
? exampleValue
: JSON.stringify(exampleValue, null, 2),
}
}
// Fallback to empty body for textual content types
return { contentType: contentType as any, body: "" }
}
const isOpenAPIV3Operation = (
@ -405,7 +497,7 @@ const parseOpenAPIBody = (
op: OpenAPIOperationType
): HoppRESTReqBody =>
isOpenAPIV3Operation(doc, op)
? parseOpenAPIV3Body(op)
? parseOpenAPIV3Body(doc, op)
: parseOpenAPIV2Body(op)
const resolveOpenAPIV3SecurityObj = (
@ -455,6 +547,9 @@ const resolveOpenAPIV3SecurityObj = (
isPKCE: false,
tokenEndpoint: scheme.flows.authorizationCode.tokenUrl ?? "",
clientSecret: "",
authRequestParams: [],
refreshRequestParams: [],
tokenRequestParams: [],
},
addTo: "HEADERS",
}
@ -468,6 +563,8 @@ const resolveOpenAPIV3SecurityObj = (
clientID: "",
token: "",
scopes: _schemeData.join(" "),
authRequestParams: [],
refreshRequestParams: [],
},
addTo: "HEADERS",
}
@ -484,6 +581,8 @@ const resolveOpenAPIV3SecurityObj = (
username: "",
token: "",
scopes: _schemeData.join(" "),
refreshRequestParams: [],
tokenRequestParams: [],
},
addTo: "HEADERS",
}
@ -499,6 +598,8 @@ const resolveOpenAPIV3SecurityObj = (
scopes: _schemeData.join(" "),
token: "",
clientAuthentication: "IN_BODY",
refreshRequestParams: [],
tokenRequestParams: [],
},
addTo: "HEADERS",
}
@ -515,6 +616,9 @@ const resolveOpenAPIV3SecurityObj = (
isPKCE: false,
tokenEndpoint: "",
clientSecret: "",
authRequestParams: [],
refreshRequestParams: [],
tokenRequestParams: [],
},
addTo: "HEADERS",
}
@ -531,6 +635,9 @@ const resolveOpenAPIV3SecurityObj = (
isPKCE: false,
tokenEndpoint: "",
clientSecret: "",
authRequestParams: [],
refreshRequestParams: [],
tokenRequestParams: [],
},
addTo: "HEADERS",
}
@ -618,6 +725,9 @@ const resolveOpenAPIV2SecurityScheme = (
token: "",
isPKCE: false,
tokenEndpoint: scheme.tokenUrl ?? "",
authRequestParams: [],
refreshRequestParams: [],
tokenRequestParams: [],
},
addTo: "HEADERS",
}
@ -631,6 +741,8 @@ const resolveOpenAPIV2SecurityScheme = (
grantType: "IMPLICIT",
scopes: _schemeData.join(" "),
token: "",
authRequestParams: [],
refreshRequestParams: [],
},
addTo: "HEADERS",
}
@ -646,6 +758,8 @@ const resolveOpenAPIV2SecurityScheme = (
scopes: _schemeData.join(" "),
token: "",
clientAuthentication: "IN_BODY",
refreshRequestParams: [],
tokenRequestParams: [],
},
addTo: "HEADERS",
}
@ -662,6 +776,8 @@ const resolveOpenAPIV2SecurityScheme = (
scopes: _schemeData.join(" "),
token: "",
username: "",
refreshRequestParams: [],
tokenRequestParams: [],
},
addTo: "HEADERS",
}
@ -678,6 +794,9 @@ const resolveOpenAPIV2SecurityScheme = (
token: "",
isPKCE: false,
tokenEndpoint: "",
authRequestParams: [],
refreshRequestParams: [],
tokenRequestParams: [],
},
addTo: "HEADERS",
}

View file

@ -33,8 +33,10 @@ declare module 'vue' {
HoppSmartTable: typeof import('@hoppscotch/ui')['HoppSmartTable']
HoppSmartTabs: typeof import('@hoppscotch/ui')['HoppSmartTabs']
HoppSmartToggle: typeof import('@hoppscotch/ui')['HoppSmartToggle']
IconLucideAlertTriangle: typeof import('~icons/lucide/alert-triangle')['default']
IconLucideArrowLeft: typeof import('~icons/lucide/arrow-left')['default']
IconLucideArrowUpRight: typeof import('~icons/lucide/arrow-up-right')['default']
IconLucideBadgeCheck: typeof import('~icons/lucide/badge-check')['default']
IconLucideCheck: typeof import('~icons/lucide/check')['default']
IconLucideChevronDown: typeof import('~icons/lucide/chevron-down')['default']
IconLucideHelpCircle: typeof import('~icons/lucide/help-circle')['default']
@ -42,13 +44,21 @@ declare module 'vue' {
IconLucideInfo: typeof import('~icons/lucide/info')['default']
IconLucideSearch: typeof import('~icons/lucide/search')['default']
IconLucideUser: typeof import('~icons/lucide/user')['default']
OnboardingAuthProviderCard: typeof import('./components/onboarding/AuthProviderCard.vue')['default']
OnboardingAuthSetup: typeof import('./components/onboarding/AuthSetup.vue')['default']
OnboardingCompleteScreen: typeof import('./components/onboarding/CompleteScreen.vue')['default']
OnboardingOAuthSetup: typeof import('./components/onboarding/OAuthSetup.vue')['default']
OnboardingSmtpSetup: typeof import('./components/onboarding/SmtpSetup.vue')['default']
OnboardingWelcomeScreen: typeof import('./components/onboarding/WelcomeScreen.vue')['default']
SettingsAuthConfiguration: typeof import('./components/settings/AuthConfiguration.vue')['default']
SettingsAuthConfigurations: typeof import('./components/settings/AuthConfigurations.vue')['default']
SettingsAuthProvider: typeof import('./components/settings/AuthProvider.vue')['default']
SettingsAuthToken: typeof import('./components/settings/AuthToken.vue')['default']
SettingsConfigurations: typeof import('./components/settings/Configurations.vue')['default']
SettingsDataSharing: typeof import('./components/settings/DataSharing.vue')['default']
SettingsHistoryConfiguration: typeof import('./components/settings/HistoryConfiguration.vue')['default']
SettingsOAuthProviderConfigurations: typeof import('./components/settings/OAuthProviderConfigurations.vue')['default']
SettingsRateLimit: typeof import('./components/settings/RateLimit.vue')['default']
SettingsReset: typeof import('./components/settings/Reset.vue')['default']
SettingsServerRestart: typeof import('./components/settings/ServerRestart.vue')['default']
SettingsSmtpConfiguration: typeof import('./components/settings/SmtpConfiguration.vue')['default']
@ -63,6 +73,7 @@ declare module 'vue' {
TokensGenerateModal: typeof import('./components/tokens/GenerateModal.vue')['default']
TokensList: typeof import('./components/tokens/List.vue')['default']
TokensOverview: typeof import('./components/tokens/Overview.vue')['default']
UiAccordion: typeof import('./components/ui/Accordion.vue')['default']
UiAutoResetIcon: typeof import('./components/ui/AutoResetIcon.vue')['default']
UsersDetails: typeof import('./components/users/Details.vue')['default']
UsersInviteModal: typeof import('./components/users/InviteModal.vue')['default']