fumadocs-openapi 10.3.15 → 10.3.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/css/generated/shared.css +2 -0
- package/dist/generate-file.d.ts +0 -1
- package/dist/generate-file.d.ts.map +1 -1
- package/dist/generate-file.js +1 -2
- package/dist/generate-file.js.map +1 -1
- package/dist/index.js +1 -2
- package/dist/playground/client.d.ts +4 -3
- package/dist/playground/client.d.ts.map +1 -1
- package/dist/playground/client.js +2 -4
- package/dist/playground/client.js.map +1 -1
- package/dist/playground/components/inputs.js +2 -4
- package/dist/playground/components/inputs.js.map +1 -1
- package/dist/playground/components/oauth-dialog.js +1 -2
- package/dist/playground/components/oauth-dialog.js.map +1 -1
- package/dist/playground/components/server-select.js +2 -4
- package/dist/playground/components/server-select.js.map +1 -1
- package/dist/playground/fetcher.d.ts +0 -2
- package/dist/playground/fetcher.d.ts.map +1 -1
- package/dist/playground/fetcher.js +1 -2
- package/dist/playground/fetcher.js.map +1 -1
- package/dist/playground/index.d.ts +2 -7
- package/dist/playground/index.d.ts.map +1 -1
- package/dist/playground/index.js +23 -3
- package/dist/playground/index.js.map +1 -1
- package/dist/playground/lazy.js +2 -4
- package/dist/playground/lazy.js.map +1 -1
- package/dist/playground/schema.d.ts +0 -3
- package/dist/playground/schema.d.ts.map +1 -1
- package/dist/playground/schema.js +1 -2
- package/dist/playground/schema.js.map +1 -1
- package/dist/playground/status-info.js +1 -2
- package/dist/playground/status-info.js.map +1 -1
- package/dist/requests/generators/all.js +1 -2
- package/dist/requests/generators/all.js.map +1 -1
- package/dist/requests/generators/csharp.js +1 -2
- package/dist/requests/generators/csharp.js.map +1 -1
- package/dist/requests/generators/curl.js +1 -2
- package/dist/requests/generators/curl.js.map +1 -1
- package/dist/requests/generators/go.js +1 -2
- package/dist/requests/generators/go.js.map +1 -1
- package/dist/requests/generators/index.js +1 -1
- package/dist/requests/generators/java.js +1 -2
- package/dist/requests/generators/java.js.map +1 -1
- package/dist/requests/generators/javascript.js +1 -2
- package/dist/requests/generators/javascript.js.map +1 -1
- package/dist/requests/generators/python.js +1 -2
- package/dist/requests/generators/python.js.map +1 -1
- package/dist/requests/media/adapter.js +2 -3
- package/dist/requests/media/adapter.js.map +1 -1
- package/dist/requests/media/encode.d.ts +0 -4
- package/dist/requests/media/encode.d.ts.map +1 -1
- package/dist/requests/media/encode.js +1 -2
- package/dist/requests/media/encode.js.map +1 -1
- package/dist/requests/media/resolve-adapter.js +1 -1
- package/dist/requests/media/resolve-adapter.js.map +1 -1
- package/dist/requests/string-utils.js +1 -2
- package/dist/requests/string-utils.js.map +1 -1
- package/dist/requests/to-python-object.js +1 -1
- package/dist/scalar/client.js +2 -4
- package/dist/scalar/client.js.map +1 -1
- package/dist/scalar/index.d.ts +0 -2
- package/dist/scalar/index.d.ts.map +1 -1
- package/dist/scalar/index.js +1 -2
- package/dist/scalar/index.js.map +1 -1
- package/dist/server/create.js +1 -2
- package/dist/server/create.js.map +1 -1
- package/dist/server/index.js +1 -2
- package/dist/server/proxy.js +1 -1
- package/dist/server/proxy.js.map +1 -1
- package/dist/server/source-api.js +1 -2
- package/dist/server/source-api.js.map +1 -1
- package/dist/types.d.ts +1 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/ui/api-page.d.ts +0 -2
- package/dist/ui/api-page.d.ts.map +1 -1
- package/dist/ui/api-page.js +1 -2
- package/dist/ui/api-page.js.map +1 -1
- package/dist/ui/base.d.ts +8 -4
- package/dist/ui/base.d.ts.map +1 -1
- package/dist/ui/base.js +12 -4
- package/dist/ui/base.js.map +1 -1
- package/dist/ui/client/index.js +2 -3
- package/dist/ui/client/index.js.map +1 -1
- package/dist/ui/client/storage-key.js +1 -2
- package/dist/ui/client/storage-key.js.map +1 -1
- package/dist/ui/components/accordion.js +2 -4
- package/dist/ui/components/accordion.js.map +1 -1
- package/dist/ui/components/dialog.js +3 -5
- package/dist/ui/components/dialog.js.map +1 -1
- package/dist/ui/components/input.js +1 -2
- package/dist/ui/components/input.js.map +1 -1
- package/dist/ui/components/method-label.js +1 -2
- package/dist/ui/components/method-label.js.map +1 -1
- package/dist/ui/components/select.js +2 -3
- package/dist/ui/components/select.js.map +1 -1
- package/dist/ui/contexts/api.js +2 -4
- package/dist/ui/contexts/api.js.map +1 -1
- package/dist/ui/contexts/api.lazy.js +2 -4
- package/dist/ui/contexts/api.lazy.js.map +1 -1
- package/dist/ui/full.client.js +2 -4
- package/dist/ui/full.client.js.map +1 -1
- package/dist/ui/full.d.ts +0 -1
- package/dist/ui/full.d.ts.map +1 -1
- package/dist/ui/full.js +1 -2
- package/dist/ui/full.js.map +1 -1
- package/dist/ui/index.js +1 -2
- package/dist/ui/operation/client.js +2 -4
- package/dist/ui/operation/client.js.map +1 -1
- package/dist/ui/operation/index.js +1 -2
- package/dist/ui/operation/index.js.map +1 -1
- package/dist/ui/operation/request-tabs.d.ts +0 -4
- package/dist/ui/operation/request-tabs.d.ts.map +1 -1
- package/dist/ui/operation/request-tabs.js +1 -2
- package/dist/ui/operation/request-tabs.js.map +1 -1
- package/dist/ui/operation/response-tabs.js +1 -2
- package/dist/ui/operation/response-tabs.js.map +1 -1
- package/dist/ui/operation/usage-tabs/client.js +4 -7
- package/dist/ui/operation/usage-tabs/client.js.map +1 -1
- package/dist/ui/operation/usage-tabs/index.js +1 -2
- package/dist/ui/operation/usage-tabs/index.js.map +1 -1
- package/dist/ui/operation/usage-tabs/lazy.js +2 -4
- package/dist/ui/operation/usage-tabs/lazy.js.map +1 -1
- package/dist/ui/schema/client.d.ts +0 -2
- package/dist/ui/schema/client.d.ts.map +1 -1
- package/dist/ui/schema/client.js +2 -4
- package/dist/ui/schema/client.js.map +1 -1
- package/dist/ui/schema/index.d.ts +0 -3
- package/dist/ui/schema/index.d.ts.map +1 -1
- package/dist/ui/schema/index.js +1 -2
- package/dist/ui/schema/index.js.map +1 -1
- package/dist/ui/schema/lazy.js +2 -4
- package/dist/ui/schema/lazy.js.map +1 -1
- package/dist/utils/cn.js +1 -2
- package/dist/utils/deep-equal.js +1 -1
- package/dist/utils/id-to-title.js +1 -1
- package/dist/utils/lazy.js +1 -2
- package/dist/utils/lazy.js.map +1 -1
- package/dist/utils/merge-schema.js +1 -2
- package/dist/utils/merge-schema.js.map +1 -1
- package/dist/utils/pages/builder.d.ts +0 -1
- package/dist/utils/pages/builder.d.ts.map +1 -1
- package/dist/utils/pages/builder.js +1 -2
- package/dist/utils/pages/builder.js.map +1 -1
- package/dist/utils/pages/preset-auto.js +1 -2
- package/dist/utils/pages/preset-auto.js.map +1 -1
- package/dist/utils/pages/to-body.js +1 -1
- package/dist/utils/pages/to-static-data.js +1 -2
- package/dist/utils/pages/to-static-data.js.map +1 -1
- package/dist/utils/pages/to-text.d.ts +0 -3
- package/dist/utils/pages/to-text.d.ts.map +1 -1
- package/dist/utils/pages/to-text.js +1 -2
- package/dist/utils/pages/to-text.js.map +1 -1
- package/dist/utils/process-document.js +3 -5
- package/dist/utils/process-document.js.map +1 -1
- package/dist/utils/remove-undefined.js +1 -1
- package/dist/utils/remove-undefined.js.map +1 -1
- package/dist/utils/schema-to-string.d.ts +1 -2
- package/dist/utils/schema-to-string.js +1 -1
- package/dist/utils/schema-to-string.js.map +1 -1
- package/dist/utils/schema.js +1 -2
- package/dist/utils/schema.js.map +1 -1
- package/dist/utils/url.js +1 -1
- package/dist/utils/use-query.js +1 -2
- package/dist/utils/use-query.js.map +1 -1
- package/package.json +11 -11
- package/dist/_virtual/_rolldown/runtime.js +0 -5
- package/dist/node_modules/.pnpm/dereference-json-schema@0.2.1/node_modules/dereference-json-schema/dereference.js +0 -43
- package/dist/node_modules/.pnpm/dereference-json-schema@0.2.1/node_modules/dereference-json-schema/dereference.js.map +0 -1
- package/dist/node_modules/.pnpm/dereference-json-schema@0.2.1/node_modules/dereference-json-schema/index.js +0 -29
- package/dist/node_modules/.pnpm/dereference-json-schema@0.2.1/node_modules/dereference-json-schema/index.js.map +0 -1
- package/dist/node_modules/.pnpm/dereference-json-schema@0.2.1/node_modules/dereference-json-schema/klona.js +0 -42
- package/dist/node_modules/.pnpm/dereference-json-schema@0.2.1/node_modules/dereference-json-schema/klona.js.map +0 -1
- package/dist/node_modules/.pnpm/dereference-json-schema@0.2.1/node_modules/dereference-json-schema/resolveRef.js +0 -46
- package/dist/node_modules/.pnpm/dereference-json-schema@0.2.1/node_modules/dereference-json-schema/resolveRef.js.map +0 -1
- package/dist/node_modules/.pnpm/dereference-json-schema@0.2.1/node_modules/dereference-json-schema/types.js +0 -12
- package/dist/node_modules/.pnpm/dereference-json-schema@0.2.1/node_modules/dereference-json-schema/types.js.map +0 -1
package/css/generated/shared.css
CHANGED
|
@@ -226,6 +226,7 @@
|
|
|
226
226
|
@source inline("duration-200");
|
|
227
227
|
@source inline("dynamic");
|
|
228
228
|
@source inline("e");
|
|
229
|
+
@source inline("each");
|
|
229
230
|
@source inline("either");
|
|
230
231
|
@source inline("element");
|
|
231
232
|
@source inline("else");
|
|
@@ -420,6 +421,7 @@
|
|
|
420
421
|
@source inline("json-schema-typed");
|
|
421
422
|
@source inline("justify-between");
|
|
422
423
|
@source inline("justify-center");
|
|
424
|
+
@source inline("k");
|
|
423
425
|
@source inline("key");
|
|
424
426
|
@source inline("keyof");
|
|
425
427
|
@source inline("kind");
|
package/dist/generate-file.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { OpenAPIServer } from "./server/create.js";
|
|
2
2
|
import { OutputEntry } from "./utils/pages/builder.js";
|
|
3
3
|
import { SchemaToPagesOptions } from "./utils/pages/preset-auto.js";
|
|
4
|
-
import "./server/index.js";
|
|
5
4
|
import { ProcessedDocument } from "./utils/process-document.js";
|
|
6
5
|
import { PagesToTextOptions } from "./utils/pages/to-text.js";
|
|
7
6
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate-file.d.ts","names":[],"sources":["../src/generate-file.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"generate-file.d.ts","names":[],"sources":["../src/generate-file.ts"],"mappings":";;;;;;;UASiB,UAAA;EACf,IAAA;EACA,OAAA;AAAA;AAAA,UAGQ,WAAA;EACR,KAAA,EAAO,SAAA,OAAgB,GAAA,EAAK,kBAAA,KAAuB,SAAA;EALnD;;AAED;EAQC,GAAA,IACM,QAAA;IAEA,OAAA;IARC;;;IAYD,UAAA;EAAA;AAAA;AAAA,UAIE,SAAA;EACR,IAAA;EACA,KAAA;EACA,WAAA;EAdA;;;;;EAqBA,IAAA;AAAA;AAAA,UAGQ,mBAAA,SAA4B,kBAAA;;;;EAIpC,KAAA,EAAO,aAAA;EAdP;;;EAmBA,MAAA;EATQ;;;EAcR,KAAA,GAAQ,WAAA;EAAA;;;EAKR,WAAA,IAAe,IAAA,EAAM,kBAAA,EAAoB,KAAA,EAAO,UAAA,cAAwB,OAAA;AAAA;AAAA,KAG9D,MAAA,GAAS,oBAAA,GAAuB,mBAAA;AAAA,UAElC,kBAAA;EAAA,SACC,SAAA,EAAW,MAAA,SAAe,UAAA;EAAA,SAC1B,gBAAA,EAAkB,MAAA,SAAe,WAAA;EAAA,SACjC,SAAA,EAAW,MAAA,SAAe,iBAAA;AAAA;AAAA,iBAGf,aAAA,CAAc,OAAA,EAAS,MAAA,GAAS,OAAA;AAAA,iBAehC,iBAAA,CACpB,OAAA,EAAS,oBAAA,GAAuB,IAAA,CAAK,mBAAA,cACpC,OAAA,CAAQ,UAAA"}
|
package/dist/generate-file.js
CHANGED
|
@@ -4,7 +4,6 @@ import { fromSchema } from "./utils/pages/builder.js";
|
|
|
4
4
|
import { mkdir, writeFile } from "node:fs/promises";
|
|
5
5
|
import * as path from "node:path";
|
|
6
6
|
import { createGetUrl, getSlugs } from "fumadocs-core/source";
|
|
7
|
-
|
|
8
7
|
//#region src/generate-file.ts
|
|
9
8
|
async function generateFiles(options) {
|
|
10
9
|
const files = await generateFilesOnly(options);
|
|
@@ -86,7 +85,7 @@ function writeIndexFiles(files, context, options) {
|
|
|
86
85
|
content: fileContent(item)
|
|
87
86
|
});
|
|
88
87
|
}
|
|
89
|
-
|
|
90
88
|
//#endregion
|
|
91
89
|
export { generateFiles, generateFilesOnly };
|
|
90
|
+
|
|
92
91
|
//# sourceMappingURL=generate-file.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate-file.js","names":[],"sources":["../src/generate-file.ts"],"sourcesContent":["import { mkdir, writeFile } from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { generateDocument, type PagesToTextOptions, toText } from './utils/pages/to-text';\nimport type { ProcessedDocument } from '@/utils/process-document';\nimport type { OpenAPIServer } from '@/server';\nimport { createGetUrl, getSlugs } from 'fumadocs-core/source';\nimport { createAutoPreset, type SchemaToPagesOptions } from '@/utils/pages/preset-auto';\nimport { fromSchema, type OutputEntry } from '@/utils/pages/builder';\n\nexport interface OutputFile {\n path: string;\n content: string;\n}\n\ninterface IndexConfig {\n items: IndexItem[] | ((ctx: BeforeWriteContext) => IndexItem[]);\n\n /**\n * Generate URLs for cards\n */\n url:\n | ((filePath: string) => string)\n | {\n baseUrl: string;\n /**\n * Base content directory\n */\n contentDir: string;\n };\n}\n\ninterface IndexItem {\n path: string;\n title?: string;\n description?: string;\n\n /**\n * Specify linked pages:\n * - items in `inputs` to include all generated pages of a specific schema.\n * - specific Markdown/MDX files.\n */\n only?: string[];\n}\n\ninterface GenerateFilesConfig extends PagesToTextOptions {\n /**\n * the OpenAPI server object\n */\n input: OpenAPIServer;\n\n /**\n * Output directory\n */\n output: string;\n\n /**\n * Generate index files with cards linking to generated pages.\n */\n index?: IndexConfig;\n\n /**\n * Can add/change/remove output files before writing to file system\n **/\n beforeWrite?: (this: BeforeWriteContext, files: OutputFile[]) => void | Promise<void>;\n}\n\nexport type Config = SchemaToPagesOptions & GenerateFilesConfig;\n\ninterface BeforeWriteContext {\n readonly generated: Record<string, OutputFile[]>;\n readonly generatedEntries: Record<string, OutputEntry[]>;\n readonly documents: Record<string, ProcessedDocument>;\n}\n\nexport async function generateFiles(options: Config): Promise<void> {\n const files = await generateFilesOnly(options);\n const { output } = options;\n\n await Promise.all(\n files.map(async (file) => {\n const filePath = path.join(output, file.path);\n\n await mkdir(path.dirname(filePath), { recursive: true });\n await writeFile(filePath, file.content);\n console.log(`Generated: ${filePath}`);\n }),\n );\n}\n\nexport async function generateFilesOnly(\n options: SchemaToPagesOptions & Omit<GenerateFilesConfig, 'output'>,\n): Promise<OutputFile[]> {\n const schemas = await options.input.getSchemas();\n\n const files: OutputFile[] = [];\n const generated: Record<string, OutputFile[]> = {};\n const generatedEntries: Record<string, OutputEntry[]> = {};\n\n const entries = Object.entries(schemas);\n if (entries.length === 0) {\n throw new Error('No input files found.');\n }\n const preset = createAutoPreset(options);\n for (const [id, schema] of entries) {\n const entries = fromSchema(id, schema, preset);\n const schemaFiles = (generated[id] ??= []);\n\n generatedEntries[id] = entries;\n for (const entry of entries) {\n const file: OutputFile = {\n path: entry.path,\n content: toText(entry, schema, options),\n };\n\n schemaFiles.push(file);\n files.push(file);\n }\n }\n\n const context: BeforeWriteContext = {\n generated,\n generatedEntries,\n documents: schemas,\n };\n\n if (options.index) {\n writeIndexFiles(files, context, options);\n }\n\n await options.beforeWrite?.call(context, files);\n return files;\n}\n\nfunction writeIndexFiles(\n files: OutputFile[],\n context: BeforeWriteContext,\n options: SchemaToPagesOptions & Omit<GenerateFilesConfig, 'output'>,\n) {\n const { generatedEntries } = context;\n const { items, url } = options.index!;\n\n let urlFn: (path: string) => string;\n if (typeof url === 'object') {\n const getUrl = createGetUrl(url.baseUrl);\n\n urlFn = (file) => getUrl(getSlugs(path.relative(url.contentDir, file)));\n } else {\n urlFn = url;\n }\n\n function findEntryByPath(path: string) {\n for (const entries of Object.values(generatedEntries)) {\n const match = entries.find((entry) => entry.path === path);\n\n if (match) return match;\n }\n }\n\n function fileContent(index: IndexItem): string {\n const content: string[] = [];\n content.push('<Cards>');\n const pathToEntry = new Map<string, OutputEntry>();\n const only = index.only ?? Object.keys(context.generated);\n\n for (const item of only) {\n if (generatedEntries[item]) {\n for (const entry of generatedEntries[item]) {\n pathToEntry.set(entry.path, entry);\n }\n } else {\n const match = findEntryByPath(item);\n if (!match) {\n throw new Error(\n `${item} does not exist on \"input\", available: ${Object.keys(generatedEntries).join(', ')}.`,\n );\n }\n\n pathToEntry.set(match.path, match);\n }\n }\n\n for (const file of pathToEntry.values()) {\n const descriptionAttr = file.info.description\n ? `description=${JSON.stringify(file.info.description)} `\n : '';\n content.push(\n `<Card href=\"${urlFn(file.path)}\" title=${JSON.stringify(file.info.title)} ${descriptionAttr}/>`,\n );\n }\n\n content.push('</Cards>');\n return generateDocument(\n {\n title: index.title ?? 'Overview',\n description: index.description,\n },\n content.join('\\n'),\n options,\n );\n }\n\n for (const item of typeof items === 'function' ? items(context) : items) {\n files.push({\n path: path.extname(item.path).length === 0 ? `${item.path}.mdx` : item.path,\n content: fileContent(item),\n });\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"generate-file.js","names":[],"sources":["../src/generate-file.ts"],"sourcesContent":["import { mkdir, writeFile } from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { generateDocument, type PagesToTextOptions, toText } from './utils/pages/to-text';\nimport type { ProcessedDocument } from '@/utils/process-document';\nimport type { OpenAPIServer } from '@/server';\nimport { createGetUrl, getSlugs } from 'fumadocs-core/source';\nimport { createAutoPreset, type SchemaToPagesOptions } from '@/utils/pages/preset-auto';\nimport { fromSchema, type OutputEntry } from '@/utils/pages/builder';\n\nexport interface OutputFile {\n path: string;\n content: string;\n}\n\ninterface IndexConfig {\n items: IndexItem[] | ((ctx: BeforeWriteContext) => IndexItem[]);\n\n /**\n * Generate URLs for cards\n */\n url:\n | ((filePath: string) => string)\n | {\n baseUrl: string;\n /**\n * Base content directory\n */\n contentDir: string;\n };\n}\n\ninterface IndexItem {\n path: string;\n title?: string;\n description?: string;\n\n /**\n * Specify linked pages:\n * - items in `inputs` to include all generated pages of a specific schema.\n * - specific Markdown/MDX files.\n */\n only?: string[];\n}\n\ninterface GenerateFilesConfig extends PagesToTextOptions {\n /**\n * the OpenAPI server object\n */\n input: OpenAPIServer;\n\n /**\n * Output directory\n */\n output: string;\n\n /**\n * Generate index files with cards linking to generated pages.\n */\n index?: IndexConfig;\n\n /**\n * Can add/change/remove output files before writing to file system\n **/\n beforeWrite?: (this: BeforeWriteContext, files: OutputFile[]) => void | Promise<void>;\n}\n\nexport type Config = SchemaToPagesOptions & GenerateFilesConfig;\n\ninterface BeforeWriteContext {\n readonly generated: Record<string, OutputFile[]>;\n readonly generatedEntries: Record<string, OutputEntry[]>;\n readonly documents: Record<string, ProcessedDocument>;\n}\n\nexport async function generateFiles(options: Config): Promise<void> {\n const files = await generateFilesOnly(options);\n const { output } = options;\n\n await Promise.all(\n files.map(async (file) => {\n const filePath = path.join(output, file.path);\n\n await mkdir(path.dirname(filePath), { recursive: true });\n await writeFile(filePath, file.content);\n console.log(`Generated: ${filePath}`);\n }),\n );\n}\n\nexport async function generateFilesOnly(\n options: SchemaToPagesOptions & Omit<GenerateFilesConfig, 'output'>,\n): Promise<OutputFile[]> {\n const schemas = await options.input.getSchemas();\n\n const files: OutputFile[] = [];\n const generated: Record<string, OutputFile[]> = {};\n const generatedEntries: Record<string, OutputEntry[]> = {};\n\n const entries = Object.entries(schemas);\n if (entries.length === 0) {\n throw new Error('No input files found.');\n }\n const preset = createAutoPreset(options);\n for (const [id, schema] of entries) {\n const entries = fromSchema(id, schema, preset);\n const schemaFiles = (generated[id] ??= []);\n\n generatedEntries[id] = entries;\n for (const entry of entries) {\n const file: OutputFile = {\n path: entry.path,\n content: toText(entry, schema, options),\n };\n\n schemaFiles.push(file);\n files.push(file);\n }\n }\n\n const context: BeforeWriteContext = {\n generated,\n generatedEntries,\n documents: schemas,\n };\n\n if (options.index) {\n writeIndexFiles(files, context, options);\n }\n\n await options.beforeWrite?.call(context, files);\n return files;\n}\n\nfunction writeIndexFiles(\n files: OutputFile[],\n context: BeforeWriteContext,\n options: SchemaToPagesOptions & Omit<GenerateFilesConfig, 'output'>,\n) {\n const { generatedEntries } = context;\n const { items, url } = options.index!;\n\n let urlFn: (path: string) => string;\n if (typeof url === 'object') {\n const getUrl = createGetUrl(url.baseUrl);\n\n urlFn = (file) => getUrl(getSlugs(path.relative(url.contentDir, file)));\n } else {\n urlFn = url;\n }\n\n function findEntryByPath(path: string) {\n for (const entries of Object.values(generatedEntries)) {\n const match = entries.find((entry) => entry.path === path);\n\n if (match) return match;\n }\n }\n\n function fileContent(index: IndexItem): string {\n const content: string[] = [];\n content.push('<Cards>');\n const pathToEntry = new Map<string, OutputEntry>();\n const only = index.only ?? Object.keys(context.generated);\n\n for (const item of only) {\n if (generatedEntries[item]) {\n for (const entry of generatedEntries[item]) {\n pathToEntry.set(entry.path, entry);\n }\n } else {\n const match = findEntryByPath(item);\n if (!match) {\n throw new Error(\n `${item} does not exist on \"input\", available: ${Object.keys(generatedEntries).join(', ')}.`,\n );\n }\n\n pathToEntry.set(match.path, match);\n }\n }\n\n for (const file of pathToEntry.values()) {\n const descriptionAttr = file.info.description\n ? `description=${JSON.stringify(file.info.description)} `\n : '';\n content.push(\n `<Card href=\"${urlFn(file.path)}\" title=${JSON.stringify(file.info.title)} ${descriptionAttr}/>`,\n );\n }\n\n content.push('</Cards>');\n return generateDocument(\n {\n title: index.title ?? 'Overview',\n description: index.description,\n },\n content.join('\\n'),\n options,\n );\n }\n\n for (const item of typeof items === 'function' ? items(context) : items) {\n files.push({\n path: path.extname(item.path).length === 0 ? `${item.path}.mdx` : item.path,\n content: fileContent(item),\n });\n }\n}\n"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { ParsedSchema } from "../utils/schema.js";
|
|
2
2
|
import { FetchResult } from "./fetcher.js";
|
|
3
|
-
import {
|
|
3
|
+
import { SecurityEntry } from "./index.js";
|
|
4
4
|
import { SchemaScope } from "./schema.js";
|
|
5
|
+
import { ParameterObject } from "../types.js";
|
|
5
6
|
import { ComponentProps, FC, ReactNode } from "react";
|
|
6
7
|
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
7
8
|
import { FieldKey } from "@fumari/stf";
|
|
@@ -17,7 +18,7 @@ interface FormValues extends Record<string, unknown> {
|
|
|
17
18
|
interface PlaygroundClientProps extends ComponentProps<'form'>, SchemaScope {
|
|
18
19
|
route: string;
|
|
19
20
|
method: string;
|
|
20
|
-
parameters?:
|
|
21
|
+
parameters?: ParameterObject[];
|
|
21
22
|
securities: SecurityEntry[][];
|
|
22
23
|
body?: {
|
|
23
24
|
schema: ParsedSchema;
|
|
@@ -51,7 +52,7 @@ interface PlaygroundClientOptions {
|
|
|
51
52
|
*
|
|
52
53
|
* Recommended types packages: `json-schema-typed`, `openapi-types`.
|
|
53
54
|
*/
|
|
54
|
-
renderParameterField?: (fieldName: FieldKey, param:
|
|
55
|
+
renderParameterField?: (fieldName: FieldKey, param: ParameterObject) => ReactNode;
|
|
55
56
|
/**
|
|
56
57
|
* render the input for API endpoint body.
|
|
57
58
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","names":[],"sources":["../../src/playground/client.tsx"],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.d.ts","names":[],"sources":["../../src/playground/client.tsx"],"mappings":";;;;;;;;;;UAuDiB,UAAA,SAAmB,MAAA;EAClC,IAAA,EAAM,MAAA;EACN,KAAA,EAAO,MAAA;EACP,MAAA,EAAQ,MAAA;EACR,MAAA,EAAQ,MAAA;EACR,IAAA;AAAA;AAAA,UAGe,qBAAA,SAA8B,cAAA,UAAwB,WAAA;EACrE,KAAA;EACA,MAAA;EACA,UAAA,GAAa,eAAA;EACb,UAAA,EAAY,aAAA;EACZ,IAAA;IACE,MAAA,EAAQ,YAAA;IACR,SAAA;EAAA;EAbF;;;EAkBA,UAAA,EAAY,MAAA,SAAe,YAAA;EAC3B,QAAA;AAAA;AAAA,UAGe,uBAAA;EAnBX;;AAGN;EAoBE,mBAAA,IAAuB,MAAA,EAAQ,SAAA,OAAgB,SAAA;;;;EAK/C,cAAA;EAEA,UAAA,GAAa,OAAA;IACX,aAAA,EAAe,EAAA;MAAK,IAAA,EAAM,WAAA;IAAA;EAAA;EA5BoD;;;;;;;;EAuChF,oBAAA,IAAwB,SAAA,EAAW,QAAA,EAAU,KAAA,EAAO,eAAA,KAAoB,SAAA;EAlCxE;;;;;EAyCA,eAAA,IACE,SAAA,UACA,IAAA;IACE,MAAA,EAAQ,YAAA;IACR,SAAA;EAAA,MAEC,SAAA;AAAA;AAAA,iBAciB,gBAAA,CAAA;EACtB,KAAA;EACA,MAAA;EACA,UAAA;EACA,UAAA;EACA,IAAA;EACA,UAAA;EACA,QAAA;EACA,SAAA;EACA,QAAA;EAAA,GACG;AAAA,GACF,qBAAA,GAAqB,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,UAiVP,SAAA;EACf,SAAA,EAAW,QAAA;EACX,YAAA;EAEA,QAAA,GAAW,aAAA;EACX,QAAA,EAAU,SAAA;EAEV,SAAA,IAAa,MAAA;AAAA;AAAA,cAuQF,MAAA;2BAEE,QAAA,EAAQ,OAAA;IAEjB,YAAA;EAAA"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
"use client";
|
|
3
2
|
import { joinURL, resolveRequestData, resolveServerUrl, withBase } from "../utils/url.js";
|
|
4
3
|
import { useStorageKey } from "../ui/client/storage-key.js";
|
|
5
4
|
import { useApiContext, useServerContext } from "../ui/contexts/api.js";
|
|
@@ -22,7 +21,6 @@ import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "fumadocs-ui
|
|
|
22
21
|
import { buttonVariants } from "fumadocs-ui/components/ui/button";
|
|
23
22
|
import { StfProvider, useDataEngine, useFieldValue, useListener, useStf } from "@fumari/stf";
|
|
24
23
|
import { objectGet, objectSet, stringifyFieldKey } from "@fumari/stf/lib/utils";
|
|
25
|
-
|
|
26
24
|
//#region src/playground/client.tsx
|
|
27
25
|
const OauthDialog = lazy(() => import("./components/oauth-dialog.js").then((mod) => ({ default: mod.OauthDialog })));
|
|
28
26
|
const OauthDialogTrigger = lazy(() => import("./components/oauth-dialog.js").then((mod) => ({ default: mod.OauthDialogTrigger })));
|
|
@@ -457,7 +455,7 @@ const Custom = { useController(fieldName, options) {
|
|
|
457
455
|
setValue
|
|
458
456
|
};
|
|
459
457
|
} };
|
|
460
|
-
|
|
461
458
|
//#endregion
|
|
462
459
|
export { Custom, PlaygroundClient as default };
|
|
460
|
+
|
|
463
461
|
//# sourceMappingURL=client.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","names":[],"sources":["../../src/playground/client.tsx"],"sourcesContent":["'use client';\nimport {\n type FC,\n Fragment,\n lazy,\n type ReactNode,\n useEffect,\n useMemo,\n useState,\n type ComponentProps,\n useRef,\n} from 'react';\nimport { useApiContext, useServerContext } from '@/ui/contexts/api';\nimport type { FetchResult } from '@/playground/fetcher';\nimport type { ParameterField, SecurityEntry } from '@/playground/index';\nimport { getStatusInfo } from './status-info';\nimport { joinURL, resolveRequestData, resolveServerUrl, withBase } from '@/utils/url';\nimport { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock.core';\nimport { MethodLabel } from '@/ui/components/method-label';\nimport { useQuery } from '@/utils/use-query';\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from 'fumadocs-ui/components/ui/collapsible';\nimport { ChevronDown, LoaderCircle } from 'lucide-react';\nimport { encodeRequestData } from '@/requests/media/encode';\nimport { buttonVariants } from 'fumadocs-ui/components/ui/button';\nimport { cn } from '@/utils/cn';\nimport { SchemaProvider, SchemaScope, useResolvedSchema } from '@/playground/schema';\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/ui/components/select';\nimport { labelVariants } from '@/ui/components/input';\nimport type { ParsedSchema } from '@/utils/schema';\nimport ServerSelect from './components/server-select';\nimport { useStorageKey } from '@/ui/client/storage-key';\nimport { useExampleRequests } from '@/ui/operation/usage-tabs/client';\nimport {\n FieldKey,\n Stf,\n StfProvider,\n useDataEngine,\n useFieldValue,\n useListener,\n useStf,\n} from '@fumari/stf';\nimport { objectGet, objectSet, stringifyFieldKey } from '@fumari/stf/lib/utils';\nimport { FieldInput, FieldSet, JsonInput, ObjectInput } from './components/inputs';\n\nexport interface FormValues extends Record<string, unknown> {\n path: Record<string, unknown>;\n query: Record<string, unknown>;\n header: Record<string, unknown>;\n cookie: Record<string, unknown>;\n body: unknown;\n}\n\nexport interface PlaygroundClientProps extends ComponentProps<'form'>, SchemaScope {\n route: string;\n method: string;\n parameters?: ParameterField[];\n securities: SecurityEntry[][];\n body?: {\n schema: ParsedSchema;\n mediaType: string;\n };\n /**\n * Resolver for $ref schemas you've passed\n */\n references: Record<string, ParsedSchema>;\n proxyUrl?: string;\n}\n\nexport interface PlaygroundClientOptions {\n /**\n * transform fields for auth-specific parameters (e.g. header)\n */\n transformAuthInputs?: (fields: AuthField[]) => AuthField[];\n\n /**\n * Request timeout in seconds (default: 10s)\n */\n requestTimeout?: number;\n\n components?: Partial<{\n ResultDisplay: FC<{ data: FetchResult }>;\n }>;\n\n /**\n * render the paremeter inputs of API endpoint.\n *\n * for updating values, use:\n * - the `Custom.useController()` from `fumadocs-openapi/playground/client`.\n *\n * Recommended types packages: `json-schema-typed`, `openapi-types`.\n */\n renderParameterField?: (fieldName: FieldKey, param: ParameterField) => ReactNode;\n\n /**\n * render the input for API endpoint body.\n *\n * @see renderParameterField for customisation tips\n */\n renderBodyField?: (\n fieldName: 'body',\n info: {\n schema: ParsedSchema;\n mediaType: string;\n },\n ) => ReactNode;\n}\n\nconst OauthDialog = lazy(() =>\n import('./components/oauth-dialog').then((mod) => ({\n default: mod.OauthDialog,\n })),\n);\nconst OauthDialogTrigger = lazy(() =>\n import('./components/oauth-dialog').then((mod) => ({\n default: mod.OauthDialogTrigger,\n })),\n);\n\nexport default function PlaygroundClient({\n route,\n method = 'GET',\n securities,\n parameters = [],\n body,\n references,\n proxyUrl,\n writeOnly,\n readOnly,\n ...rest\n}: PlaygroundClientProps) {\n const { example: exampleId, examples, setExampleData } = useExampleRequests();\n const storageKeys = useStorageKey();\n const {\n mediaAdapters,\n client: {\n playground: {\n components: { ResultDisplay = DefaultResultDisplay } = {},\n requestTimeout = 10,\n transformAuthInputs,\n } = {},\n },\n } = useApiContext();\n const { serverRef } = useServerContext();\n const [securityId, setSecurityId] = useState(() => {\n const idx = securities.findIndex((s) => s.every((entry) => !entry.deprecated));\n return idx === -1 ? 0 : idx;\n });\n const { inputs, mapInputs, initAuthValues } = useAuthInputs(\n securities[securityId],\n transformAuthInputs,\n );\n\n const defaultValues: FormValues = useMemo(() => {\n const requestData = examples.find((example) => example.id === exampleId)?.data;\n\n return {\n path: requestData?.path ?? {},\n query: requestData?.query ?? {},\n header: requestData?.header ?? {},\n body: requestData?.body ?? {},\n cookie: requestData?.cookie ?? {},\n };\n }, [examples, exampleId]);\n\n const stf = useStf({\n // it is fine to modify `defaultValues` in place\n // because we already try to persist the form values via `setExampleData`.\n defaultValues,\n });\n\n const testQuery = useQuery(async (input: FormValues) => {\n const targetServer = serverRef.current;\n const fetcher = await import('./fetcher').then((mod) =>\n mod.createBrowserFetcher(mediaAdapters, requestTimeout),\n );\n const encoded = encodeRequestData(\n { ...mapInputs(input), method, bodyMediaType: body?.mediaType },\n mediaAdapters,\n parameters,\n );\n return fetcher.fetch(\n joinURL(\n withBase(\n targetServer ? resolveServerUrl(targetServer.url, targetServer.variables) : '/',\n window.location.origin,\n ),\n resolveRequestData(route, encoded),\n ),\n {\n proxyUrl,\n ...encoded,\n },\n );\n });\n\n const timerRef = useRef<number | null>(null);\n useListener({\n stf,\n onUpdate() {\n if (timerRef.current) window.clearTimeout(timerRef.current);\n timerRef.current = window.setTimeout(\n () => {\n const values = stf.dataEngine.getData() as FormValues;\n for (const item of inputs) {\n const value = stf.dataEngine.get(item.fieldName);\n\n if (value) {\n localStorage.setItem(storageKeys.AuthField(item), JSON.stringify(value));\n }\n }\n\n const data = {\n ...mapInputs(values),\n method,\n bodyMediaType: body?.mediaType,\n };\n setExampleData(data, encodeRequestData(data, mediaAdapters, parameters));\n },\n timerRef.current ? 400 : 0,\n );\n },\n });\n\n useEffect(() => {\n // same object reference = unchanged\n if (stf.dataEngine.getData() === defaultValues) return;\n\n stf.dataEngine.reset(defaultValues);\n // eslint-disable-next-line react-hooks/exhaustive-deps -- ignore other parts\n }, [defaultValues]);\n\n useEffect(() => {\n return initAuthValues(stf);\n // eslint-disable-next-line react-hooks/exhaustive-deps -- ignore other parts\n }, [defaultValues, inputs]);\n\n return (\n <StfProvider value={stf}>\n <SchemaProvider references={references} writeOnly={writeOnly} readOnly={readOnly}>\n <form\n {...rest}\n className={cn(\n 'not-prose flex flex-col rounded-xl border shadow-md overflow-hidden bg-fd-card text-fd-card-foreground',\n rest.className,\n )}\n onSubmit={(e) => {\n testQuery.start(mapInputs(stf.dataEngine.getData() as FormValues));\n e.preventDefault();\n }}\n >\n <ServerSelect className=\"border-b\" />\n <div className=\"flex flex-row items-center gap-2 text-sm p-3 not-last:pb-0\">\n <MethodLabel>{method}</MethodLabel>\n <Route route={route} className=\"flex-1\" />\n <button\n type=\"submit\"\n className={cn(buttonVariants({ color: 'primary', size: 'sm' }), 'w-14 py-1.5')}\n disabled={testQuery.isLoading}\n >\n {testQuery.isLoading ? <LoaderCircle className=\"size-4 animate-spin\" /> : 'Send'}\n </button>\n </div>\n {testQuery.data ? <ResultDisplay data={testQuery.data} reset={testQuery.reset} /> : null}\n\n {securities.length > 0 && (\n <SecurityTabs\n securities={securities}\n securityId={securityId}\n setSecurityId={setSecurityId}\n >\n {inputs.map((input) => (\n <Fragment key={stringifyFieldKey(input.fieldName)}>{input.children}</Fragment>\n ))}\n </SecurityTabs>\n )}\n <FormBody body={body} parameters={parameters} />\n </form>\n </SchemaProvider>\n </StfProvider>\n );\n}\n\nfunction SecurityTabs({\n securities,\n setSecurityId,\n securityId,\n children,\n}: {\n securities: SecurityEntry[][];\n securityId: number;\n setSecurityId: (value: number) => void;\n children: ReactNode;\n}) {\n const [open, setOpen] = useState(false);\n const engine = useDataEngine();\n\n const result = (\n <CollapsiblePanel title=\"Authorization\">\n <Select value={securityId.toString()} onValueChange={(v) => setSecurityId(Number(v))}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {securities.map((security, i) => (\n <SelectItem key={i} value={i.toString()}>\n {security.map((item) => (\n <div key={item.id} className=\"max-w-[600px]\">\n <p\n className={cn(\n 'font-mono font-medium',\n item.deprecated && 'text-fd-muted-foreground line-through',\n )}\n >\n {item.id}\n </p>\n <p className=\"text-fd-muted-foreground whitespace-pre-wrap\">{item.description}</p>\n </div>\n ))}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {children}\n </CollapsiblePanel>\n );\n\n for (let i = 0; i < securities.length; i++) {\n const security = securities[i];\n\n for (const item of security) {\n if (item.type === 'oauth2') {\n return (\n <OauthDialog\n scheme={item}\n scopes={item.scopes}\n open={open}\n setOpen={(v) => {\n setOpen(v);\n if (v) {\n setSecurityId(i);\n }\n }}\n setToken={(token) => engine.update(['header', 'Authorization'], token)}\n >\n {result}\n </OauthDialog>\n );\n }\n }\n }\n\n return result;\n}\n\nconst ParamTypes = ['path', 'header', 'cookie', 'query'] as const;\n\nfunction FormBody({ parameters = [], body }: Pick<PlaygroundClientProps, 'parameters' | 'body'>) {\n const { renderParameterField, renderBodyField } = useApiContext().client.playground ?? {};\n const panels = useMemo(() => {\n return ParamTypes.map((type) => {\n const items = parameters.filter((v) => v.in === type);\n if (items.length === 0) return;\n\n return (\n <CollapsiblePanel\n key={type}\n title={\n {\n header: 'Header',\n cookie: 'Cookies',\n query: 'Query',\n path: 'Path',\n }[type]\n }\n >\n {items.map((field) => {\n const fieldName: FieldKey = [type, field.name!];\n if (renderParameterField) {\n return renderParameterField(fieldName, field);\n }\n\n const contentTypes = field.content && Object.keys(field.content);\n const schema = (\n field.content && contentTypes && contentTypes.length > 0\n ? field.content[contentTypes[0]].schema\n : field.schema\n ) as ParsedSchema;\n\n return (\n <FieldSet\n key={stringifyFieldKey(fieldName)}\n name={field.name}\n fieldName={fieldName}\n field={schema}\n isRequired={field.required}\n />\n );\n })}\n </CollapsiblePanel>\n );\n });\n }, [parameters, renderParameterField]);\n\n return (\n <>\n {panels}\n {body && (\n <CollapsiblePanel title=\"Body\">\n {renderBodyField ? renderBodyField('body', body) : <BodyInput field={body.schema} />}\n </CollapsiblePanel>\n )}\n </>\n );\n}\n\nfunction BodyInput({ field: _field }: { field: ParsedSchema }) {\n const field = useResolvedSchema(_field);\n const [isJson, setIsJson] = useState(false);\n\n if (field.format === 'binary') return <FieldSet field={field} fieldName={['body']} isRequired />;\n\n if (isJson)\n return (\n <>\n <button\n className={cn(\n buttonVariants({\n color: 'secondary',\n size: 'sm',\n className: 'w-fit font-mono p-2',\n }),\n )}\n onClick={() => setIsJson(false)}\n type=\"button\"\n >\n Close JSON Editor\n </button>\n <JsonInput fieldName={['body']} />\n </>\n );\n\n return (\n <FieldSet\n field={field}\n fieldName={['body']}\n collapsible={false}\n isRequired\n name={\n <button\n type=\"button\"\n className={cn(\n buttonVariants({\n color: 'secondary',\n size: 'sm',\n className: 'p-2',\n }),\n )}\n onClick={() => setIsJson(true)}\n >\n Open JSON Editor\n </button>\n }\n />\n );\n}\n\nexport interface AuthField {\n fieldName: FieldKey;\n defaultValue: unknown;\n\n original?: SecurityEntry;\n children: ReactNode;\n\n mapOutput?: (values: unknown) => unknown;\n}\n\nfunction useAuthInputs(\n securities?: SecurityEntry[],\n transform?: (fields: AuthField[]) => AuthField[],\n) {\n const storageKeys = useStorageKey();\n const inputs = useMemo(() => {\n const result: AuthField[] = [];\n if (!securities) return result;\n\n for (const security of securities) {\n if (security.type === 'http' && security.scheme === 'basic') {\n const fieldName: FieldKey = ['header', 'Authorization'];\n\n result.push({\n fieldName,\n original: security,\n defaultValue: {\n username: '',\n password: '',\n },\n mapOutput(out) {\n if (out && typeof out === 'object') {\n return `Basic ${btoa(`${'username' in out ? out.username : ''}:${'password' in out ? out.password : ''}`)}`;\n }\n\n return out;\n },\n children: (\n <ObjectInput\n field={{\n type: 'object',\n properties: {\n username: {\n type: 'string',\n },\n password: {\n type: 'string',\n },\n },\n required: ['username', 'password'],\n }}\n fieldName={fieldName}\n />\n ),\n });\n } else if (security.type === 'oauth2') {\n const fieldName: FieldKey = ['header', 'Authorization'];\n\n result.push({\n fieldName,\n original: security,\n defaultValue: 'Bearer ',\n children: (\n <fieldset className=\"flex flex-col gap-2\">\n <label htmlFor={stringifyFieldKey(fieldName)} className={cn(labelVariants())}>\n Access Token\n </label>\n <div className=\"flex gap-2\">\n <FieldInput\n fieldName={fieldName}\n isRequired\n field={{\n type: 'string',\n }}\n className=\"flex-1\"\n />\n\n <OauthDialogTrigger\n type=\"button\"\n className={cn(\n buttonVariants({\n size: 'sm',\n color: 'secondary',\n }),\n )}\n >\n Authorize\n </OauthDialogTrigger>\n </div>\n </fieldset>\n ),\n });\n } else if (security.type === 'http') {\n const fieldName: FieldKey = ['header', 'Authorization'];\n\n result.push({\n fieldName,\n original: security,\n defaultValue: 'Bearer ',\n children: (\n <FieldSet\n name=\"Authorization (header)\"\n fieldName={fieldName}\n isRequired\n field={{\n type: 'string',\n }}\n />\n ),\n });\n } else if (security.type === 'apiKey') {\n const fieldName: FieldKey = [security.in!, security.name!];\n\n result.push({\n fieldName,\n defaultValue: '',\n original: security,\n children: (\n <FieldSet\n fieldName={fieldName}\n name={`${security.name} (${security.in})`}\n isRequired\n field={{\n type: 'string',\n }}\n />\n ),\n });\n } else {\n const fieldName: FieldKey = ['header', 'Authorization'];\n\n result.push({\n fieldName,\n defaultValue: '',\n original: security,\n children: (\n <>\n <FieldSet\n name=\"Authorization (header)\"\n isRequired\n fieldName={fieldName}\n field={{\n type: 'string',\n }}\n />\n <p className=\"text-fd-muted-foreground text-xs\">\n OpenID Connect is not supported at the moment, you can still set an access token\n here.\n </p>\n </>\n ),\n });\n }\n }\n\n return transform ? transform(result) : result;\n }, [securities, transform]);\n\n const mapInputs = (values: FormValues) => {\n const cloned = structuredClone(values);\n\n for (const item of inputs) {\n if (!item.mapOutput) continue;\n objectSet(cloned, item.fieldName, item.mapOutput(objectGet(cloned, item.fieldName)));\n }\n\n return cloned;\n };\n\n const initAuthValues = (stf: Stf) => {\n const { dataEngine } = stf;\n for (const item of inputs) {\n const stored = localStorage.getItem(storageKeys.AuthField(item));\n\n if (stored) {\n const parsed = JSON.parse(stored);\n if (typeof parsed === typeof item.defaultValue) {\n dataEngine.init(item.fieldName, parsed);\n continue;\n }\n }\n\n dataEngine.init(item.fieldName, item.defaultValue);\n }\n\n // reset\n return () => {\n for (const item of inputs) {\n stf.dataEngine.delete(item.fieldName);\n }\n };\n };\n\n return { inputs, mapInputs, initAuthValues };\n}\n\nfunction Route({ route, ...props }: ComponentProps<'div'> & { route: string }) {\n return (\n <div\n {...props}\n className={cn(\n 'flex flex-row items-center gap-0.5 overflow-auto text-nowrap',\n props.className,\n )}\n >\n {route.split('/').map((part, index) => (\n <Fragment key={index}>\n {index > 0 && <span className=\"text-fd-muted-foreground\">/</span>}\n {part.startsWith('{') && part.endsWith('}') ? (\n <code className=\"bg-fd-primary/10 text-fd-primary\">{part}</code>\n ) : (\n <code className=\"text-fd-foreground\">{part}</code>\n )}\n </Fragment>\n ))}\n </div>\n );\n}\n\nfunction DefaultResultDisplay({ data, reset }: { data: FetchResult; reset: () => void }) {\n const statusInfo = useMemo(() => getStatusInfo(data.status), [data.status]);\n const { shikiOptions } = useApiContext();\n\n return (\n <div className=\"flex flex-col gap-3 mt-2 px-3 py-2 border-y bg-fd-secondary text-fd-secondary-foreground\">\n <div className=\"flex justify-between items-center\">\n <div className=\"inline-flex items-center gap-1.5 text-sm font-medium\">\n <statusInfo.icon className={cn('size-4', statusInfo.color)} />\n {statusInfo.description}\n </div>\n <button\n type=\"button\"\n className={cn(buttonVariants({ size: 'sm', variant: 'outline' }))}\n onClick={() => reset()}\n >\n Close\n </button>\n </div>\n <p className=\"text-sm text-fd-muted-foreground\">{data.status}</p>\n {data.data !== undefined && (\n <DynamicCodeBlock\n lang={typeof data.data === 'string' && data.data.length > 50000 ? 'text' : data.type}\n code={typeof data.data === 'string' ? data.data : JSON.stringify(data.data, null, 2)}\n options={shikiOptions}\n />\n )}\n </div>\n );\n}\n\nfunction CollapsiblePanel({\n title,\n children,\n ...props\n}: Omit<ComponentProps<'div'>, 'title'> & {\n title: ReactNode;\n}) {\n return (\n <Collapsible {...props} className=\"border-b last:border-b-0\">\n <CollapsibleTrigger className=\"group w-full flex items-center gap-2 p-3 text-sm font-medium\">\n {title}\n <ChevronDown className=\"ms-auto size-3.5 text-fd-muted-foreground group-data-[state=open]:rotate-180\" />\n </CollapsibleTrigger>\n <CollapsibleContent>\n <div className=\"flex flex-col gap-3 p-3 pt-1\">{children}</div>\n </CollapsibleContent>\n </Collapsible>\n );\n}\n\nexport const Custom = {\n useController(\n fieldName: FieldKey,\n options?: {\n defaultValue?: unknown;\n },\n ) {\n const [value, setValue] = useFieldValue(fieldName, options);\n return {\n value,\n setValue,\n };\n },\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"client.js","names":[],"sources":["../../src/playground/client.tsx"],"sourcesContent":["'use client';\nimport {\n type FC,\n Fragment,\n lazy,\n type ReactNode,\n useEffect,\n useMemo,\n useState,\n type ComponentProps,\n useRef,\n} from 'react';\nimport { useApiContext, useServerContext } from '@/ui/contexts/api';\nimport type { FetchResult } from '@/playground/fetcher';\nimport type { SecurityEntry } from '@/playground/index';\nimport { getStatusInfo } from './status-info';\nimport { joinURL, resolveRequestData, resolveServerUrl, withBase } from '@/utils/url';\nimport { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock.core';\nimport { MethodLabel } from '@/ui/components/method-label';\nimport { useQuery } from '@/utils/use-query';\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from 'fumadocs-ui/components/ui/collapsible';\nimport { ChevronDown, LoaderCircle } from 'lucide-react';\nimport { encodeRequestData } from '@/requests/media/encode';\nimport { buttonVariants } from 'fumadocs-ui/components/ui/button';\nimport { cn } from '@/utils/cn';\nimport { SchemaProvider, SchemaScope, useResolvedSchema } from '@/playground/schema';\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/ui/components/select';\nimport { labelVariants } from '@/ui/components/input';\nimport type { ParsedSchema } from '@/utils/schema';\nimport ServerSelect from './components/server-select';\nimport { useStorageKey } from '@/ui/client/storage-key';\nimport { useExampleRequests } from '@/ui/operation/usage-tabs/client';\nimport {\n FieldKey,\n Stf,\n StfProvider,\n useDataEngine,\n useFieldValue,\n useListener,\n useStf,\n} from '@fumari/stf';\nimport { objectGet, objectSet, stringifyFieldKey } from '@fumari/stf/lib/utils';\nimport { FieldInput, FieldSet, JsonInput, ObjectInput } from './components/inputs';\nimport type { ParameterObject } from '@/types';\n\nexport interface FormValues extends Record<string, unknown> {\n path: Record<string, unknown>;\n query: Record<string, unknown>;\n header: Record<string, unknown>;\n cookie: Record<string, unknown>;\n body: unknown;\n}\n\nexport interface PlaygroundClientProps extends ComponentProps<'form'>, SchemaScope {\n route: string;\n method: string;\n parameters?: ParameterObject[];\n securities: SecurityEntry[][];\n body?: {\n schema: ParsedSchema;\n mediaType: string;\n };\n /**\n * Resolver for $ref schemas you've passed\n */\n references: Record<string, ParsedSchema>;\n proxyUrl?: string;\n}\n\nexport interface PlaygroundClientOptions {\n /**\n * transform fields for auth-specific parameters (e.g. header)\n */\n transformAuthInputs?: (fields: AuthField[]) => AuthField[];\n\n /**\n * Request timeout in seconds (default: 10s)\n */\n requestTimeout?: number;\n\n components?: Partial<{\n ResultDisplay: FC<{ data: FetchResult }>;\n }>;\n\n /**\n * render the paremeter inputs of API endpoint.\n *\n * for updating values, use:\n * - the `Custom.useController()` from `fumadocs-openapi/playground/client`.\n *\n * Recommended types packages: `json-schema-typed`, `openapi-types`.\n */\n renderParameterField?: (fieldName: FieldKey, param: ParameterObject) => ReactNode;\n\n /**\n * render the input for API endpoint body.\n *\n * @see renderParameterField for customisation tips\n */\n renderBodyField?: (\n fieldName: 'body',\n info: {\n schema: ParsedSchema;\n mediaType: string;\n },\n ) => ReactNode;\n}\n\nconst OauthDialog = lazy(() =>\n import('./components/oauth-dialog').then((mod) => ({\n default: mod.OauthDialog,\n })),\n);\nconst OauthDialogTrigger = lazy(() =>\n import('./components/oauth-dialog').then((mod) => ({\n default: mod.OauthDialogTrigger,\n })),\n);\n\nexport default function PlaygroundClient({\n route,\n method = 'GET',\n securities,\n parameters = [],\n body,\n references,\n proxyUrl,\n writeOnly,\n readOnly,\n ...rest\n}: PlaygroundClientProps) {\n const { example: exampleId, examples, setExampleData } = useExampleRequests();\n const storageKeys = useStorageKey();\n const {\n mediaAdapters,\n client: {\n playground: {\n components: { ResultDisplay = DefaultResultDisplay } = {},\n requestTimeout = 10,\n transformAuthInputs,\n } = {},\n },\n } = useApiContext();\n const { serverRef } = useServerContext();\n const [securityId, setSecurityId] = useState(() => {\n const idx = securities.findIndex((s) => s.every((entry) => !entry.deprecated));\n return idx === -1 ? 0 : idx;\n });\n const { inputs, mapInputs, initAuthValues } = useAuthInputs(\n securities[securityId],\n transformAuthInputs,\n );\n\n const defaultValues: FormValues = useMemo(() => {\n const requestData = examples.find((example) => example.id === exampleId)?.data;\n\n return {\n path: requestData?.path ?? {},\n query: requestData?.query ?? {},\n header: requestData?.header ?? {},\n body: requestData?.body ?? {},\n cookie: requestData?.cookie ?? {},\n };\n }, [examples, exampleId]);\n\n const stf = useStf({\n // it is fine to modify `defaultValues` in place\n // because we already try to persist the form values via `setExampleData`.\n defaultValues,\n });\n\n const testQuery = useQuery(async (input: FormValues) => {\n const targetServer = serverRef.current;\n const fetcher = await import('./fetcher').then((mod) =>\n mod.createBrowserFetcher(mediaAdapters, requestTimeout),\n );\n const encoded = encodeRequestData(\n { ...mapInputs(input), method, bodyMediaType: body?.mediaType },\n mediaAdapters,\n parameters,\n );\n return fetcher.fetch(\n joinURL(\n withBase(\n targetServer ? resolveServerUrl(targetServer.url, targetServer.variables) : '/',\n window.location.origin,\n ),\n resolveRequestData(route, encoded),\n ),\n {\n proxyUrl,\n ...encoded,\n },\n );\n });\n\n const timerRef = useRef<number | null>(null);\n useListener({\n stf,\n onUpdate() {\n if (timerRef.current) window.clearTimeout(timerRef.current);\n timerRef.current = window.setTimeout(\n () => {\n const values = stf.dataEngine.getData() as FormValues;\n for (const item of inputs) {\n const value = stf.dataEngine.get(item.fieldName);\n\n if (value) {\n localStorage.setItem(storageKeys.AuthField(item), JSON.stringify(value));\n }\n }\n\n const data = {\n ...mapInputs(values),\n method,\n bodyMediaType: body?.mediaType,\n };\n setExampleData(data, encodeRequestData(data, mediaAdapters, parameters));\n },\n timerRef.current ? 400 : 0,\n );\n },\n });\n\n useEffect(() => {\n // same object reference = unchanged\n if (stf.dataEngine.getData() === defaultValues) return;\n\n stf.dataEngine.reset(defaultValues);\n // eslint-disable-next-line react-hooks/exhaustive-deps -- ignore other parts\n }, [defaultValues]);\n\n useEffect(() => {\n return initAuthValues(stf);\n // eslint-disable-next-line react-hooks/exhaustive-deps -- ignore other parts\n }, [defaultValues, inputs]);\n\n return (\n <StfProvider value={stf}>\n <SchemaProvider references={references} writeOnly={writeOnly} readOnly={readOnly}>\n <form\n {...rest}\n className={cn(\n 'not-prose flex flex-col rounded-xl border shadow-md overflow-hidden bg-fd-card text-fd-card-foreground',\n rest.className,\n )}\n onSubmit={(e) => {\n testQuery.start(mapInputs(stf.dataEngine.getData() as FormValues));\n e.preventDefault();\n }}\n >\n <ServerSelect className=\"border-b\" />\n <div className=\"flex flex-row items-center gap-2 text-sm p-3 not-last:pb-0\">\n <MethodLabel>{method}</MethodLabel>\n <Route route={route} className=\"flex-1\" />\n <button\n type=\"submit\"\n className={cn(buttonVariants({ color: 'primary', size: 'sm' }), 'w-14 py-1.5')}\n disabled={testQuery.isLoading}\n >\n {testQuery.isLoading ? <LoaderCircle className=\"size-4 animate-spin\" /> : 'Send'}\n </button>\n </div>\n {testQuery.data ? <ResultDisplay data={testQuery.data} reset={testQuery.reset} /> : null}\n\n {securities.length > 0 && (\n <SecurityTabs\n securities={securities}\n securityId={securityId}\n setSecurityId={setSecurityId}\n >\n {inputs.map((input) => (\n <Fragment key={stringifyFieldKey(input.fieldName)}>{input.children}</Fragment>\n ))}\n </SecurityTabs>\n )}\n <FormBody body={body} parameters={parameters} />\n </form>\n </SchemaProvider>\n </StfProvider>\n );\n}\n\nfunction SecurityTabs({\n securities,\n setSecurityId,\n securityId,\n children,\n}: {\n securities: SecurityEntry[][];\n securityId: number;\n setSecurityId: (value: number) => void;\n children: ReactNode;\n}) {\n const [open, setOpen] = useState(false);\n const engine = useDataEngine();\n\n const result = (\n <CollapsiblePanel title=\"Authorization\">\n <Select value={securityId.toString()} onValueChange={(v) => setSecurityId(Number(v))}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {securities.map((security, i) => (\n <SelectItem key={i} value={i.toString()}>\n {security.map((item) => (\n <div key={item.id} className=\"max-w-[600px]\">\n <p\n className={cn(\n 'font-mono font-medium',\n item.deprecated && 'text-fd-muted-foreground line-through',\n )}\n >\n {item.id}\n </p>\n <p className=\"text-fd-muted-foreground whitespace-pre-wrap\">{item.description}</p>\n </div>\n ))}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {children}\n </CollapsiblePanel>\n );\n\n for (let i = 0; i < securities.length; i++) {\n const security = securities[i];\n\n for (const item of security) {\n if (item.type === 'oauth2') {\n return (\n <OauthDialog\n scheme={item}\n scopes={item.scopes}\n open={open}\n setOpen={(v) => {\n setOpen(v);\n if (v) {\n setSecurityId(i);\n }\n }}\n setToken={(token) => engine.update(['header', 'Authorization'], token)}\n >\n {result}\n </OauthDialog>\n );\n }\n }\n }\n\n return result;\n}\n\nconst ParamTypes = ['path', 'header', 'cookie', 'query'] as const;\n\nfunction FormBody({ parameters = [], body }: Pick<PlaygroundClientProps, 'parameters' | 'body'>) {\n const { renderParameterField, renderBodyField } = useApiContext().client.playground ?? {};\n const panels = useMemo(() => {\n return ParamTypes.map((type) => {\n const items = parameters.filter((v) => v.in === type);\n if (items.length === 0) return;\n\n return (\n <CollapsiblePanel\n key={type}\n title={\n {\n header: 'Header',\n cookie: 'Cookies',\n query: 'Query',\n path: 'Path',\n }[type]\n }\n >\n {items.map((field) => {\n const fieldName: FieldKey = [type, field.name!];\n if (renderParameterField) {\n return renderParameterField(fieldName, field);\n }\n\n const contentTypes = field.content && Object.keys(field.content);\n const schema = (\n field.content && contentTypes && contentTypes.length > 0\n ? field.content[contentTypes[0]].schema\n : field.schema\n ) as ParsedSchema;\n\n return (\n <FieldSet\n key={stringifyFieldKey(fieldName)}\n name={field.name}\n fieldName={fieldName}\n field={schema}\n isRequired={field.required}\n />\n );\n })}\n </CollapsiblePanel>\n );\n });\n }, [parameters, renderParameterField]);\n\n return (\n <>\n {panels}\n {body && (\n <CollapsiblePanel title=\"Body\">\n {renderBodyField ? renderBodyField('body', body) : <BodyInput field={body.schema} />}\n </CollapsiblePanel>\n )}\n </>\n );\n}\n\nfunction BodyInput({ field: _field }: { field: ParsedSchema }) {\n const field = useResolvedSchema(_field);\n const [isJson, setIsJson] = useState(false);\n\n if (field.format === 'binary') return <FieldSet field={field} fieldName={['body']} isRequired />;\n\n if (isJson)\n return (\n <>\n <button\n className={cn(\n buttonVariants({\n color: 'secondary',\n size: 'sm',\n className: 'w-fit font-mono p-2',\n }),\n )}\n onClick={() => setIsJson(false)}\n type=\"button\"\n >\n Close JSON Editor\n </button>\n <JsonInput fieldName={['body']} />\n </>\n );\n\n return (\n <FieldSet\n field={field}\n fieldName={['body']}\n collapsible={false}\n isRequired\n name={\n <button\n type=\"button\"\n className={cn(\n buttonVariants({\n color: 'secondary',\n size: 'sm',\n className: 'p-2',\n }),\n )}\n onClick={() => setIsJson(true)}\n >\n Open JSON Editor\n </button>\n }\n />\n );\n}\n\nexport interface AuthField {\n fieldName: FieldKey;\n defaultValue: unknown;\n\n original?: SecurityEntry;\n children: ReactNode;\n\n mapOutput?: (values: unknown) => unknown;\n}\n\nfunction useAuthInputs(\n securities?: SecurityEntry[],\n transform?: (fields: AuthField[]) => AuthField[],\n) {\n const storageKeys = useStorageKey();\n const inputs = useMemo(() => {\n const result: AuthField[] = [];\n if (!securities) return result;\n\n for (const security of securities) {\n if (security.type === 'http' && security.scheme === 'basic') {\n const fieldName: FieldKey = ['header', 'Authorization'];\n\n result.push({\n fieldName,\n original: security,\n defaultValue: {\n username: '',\n password: '',\n },\n mapOutput(out) {\n if (out && typeof out === 'object') {\n return `Basic ${btoa(`${'username' in out ? out.username : ''}:${'password' in out ? out.password : ''}`)}`;\n }\n\n return out;\n },\n children: (\n <ObjectInput\n field={{\n type: 'object',\n properties: {\n username: {\n type: 'string',\n },\n password: {\n type: 'string',\n },\n },\n required: ['username', 'password'],\n }}\n fieldName={fieldName}\n />\n ),\n });\n } else if (security.type === 'oauth2') {\n const fieldName: FieldKey = ['header', 'Authorization'];\n\n result.push({\n fieldName,\n original: security,\n defaultValue: 'Bearer ',\n children: (\n <fieldset className=\"flex flex-col gap-2\">\n <label htmlFor={stringifyFieldKey(fieldName)} className={cn(labelVariants())}>\n Access Token\n </label>\n <div className=\"flex gap-2\">\n <FieldInput\n fieldName={fieldName}\n isRequired\n field={{\n type: 'string',\n }}\n className=\"flex-1\"\n />\n\n <OauthDialogTrigger\n type=\"button\"\n className={cn(\n buttonVariants({\n size: 'sm',\n color: 'secondary',\n }),\n )}\n >\n Authorize\n </OauthDialogTrigger>\n </div>\n </fieldset>\n ),\n });\n } else if (security.type === 'http') {\n const fieldName: FieldKey = ['header', 'Authorization'];\n\n result.push({\n fieldName,\n original: security,\n defaultValue: 'Bearer ',\n children: (\n <FieldSet\n name=\"Authorization (header)\"\n fieldName={fieldName}\n isRequired\n field={{\n type: 'string',\n }}\n />\n ),\n });\n } else if (security.type === 'apiKey') {\n const fieldName: FieldKey = [security.in!, security.name!];\n\n result.push({\n fieldName,\n defaultValue: '',\n original: security,\n children: (\n <FieldSet\n fieldName={fieldName}\n name={`${security.name} (${security.in})`}\n isRequired\n field={{\n type: 'string',\n }}\n />\n ),\n });\n } else {\n const fieldName: FieldKey = ['header', 'Authorization'];\n\n result.push({\n fieldName,\n defaultValue: '',\n original: security,\n children: (\n <>\n <FieldSet\n name=\"Authorization (header)\"\n isRequired\n fieldName={fieldName}\n field={{\n type: 'string',\n }}\n />\n <p className=\"text-fd-muted-foreground text-xs\">\n OpenID Connect is not supported at the moment, you can still set an access token\n here.\n </p>\n </>\n ),\n });\n }\n }\n\n return transform ? transform(result) : result;\n }, [securities, transform]);\n\n const mapInputs = (values: FormValues) => {\n const cloned = structuredClone(values);\n\n for (const item of inputs) {\n if (!item.mapOutput) continue;\n objectSet(cloned, item.fieldName, item.mapOutput(objectGet(cloned, item.fieldName)));\n }\n\n return cloned;\n };\n\n const initAuthValues = (stf: Stf) => {\n const { dataEngine } = stf;\n for (const item of inputs) {\n const stored = localStorage.getItem(storageKeys.AuthField(item));\n\n if (stored) {\n const parsed = JSON.parse(stored);\n if (typeof parsed === typeof item.defaultValue) {\n dataEngine.init(item.fieldName, parsed);\n continue;\n }\n }\n\n dataEngine.init(item.fieldName, item.defaultValue);\n }\n\n // reset\n return () => {\n for (const item of inputs) {\n stf.dataEngine.delete(item.fieldName);\n }\n };\n };\n\n return { inputs, mapInputs, initAuthValues };\n}\n\nfunction Route({ route, ...props }: ComponentProps<'div'> & { route: string }) {\n return (\n <div\n {...props}\n className={cn(\n 'flex flex-row items-center gap-0.5 overflow-auto text-nowrap',\n props.className,\n )}\n >\n {route.split('/').map((part, index) => (\n <Fragment key={index}>\n {index > 0 && <span className=\"text-fd-muted-foreground\">/</span>}\n {part.startsWith('{') && part.endsWith('}') ? (\n <code className=\"bg-fd-primary/10 text-fd-primary\">{part}</code>\n ) : (\n <code className=\"text-fd-foreground\">{part}</code>\n )}\n </Fragment>\n ))}\n </div>\n );\n}\n\nfunction DefaultResultDisplay({ data, reset }: { data: FetchResult; reset: () => void }) {\n const statusInfo = useMemo(() => getStatusInfo(data.status), [data.status]);\n const { shikiOptions } = useApiContext();\n\n return (\n <div className=\"flex flex-col gap-3 mt-2 px-3 py-2 border-y bg-fd-secondary text-fd-secondary-foreground\">\n <div className=\"flex justify-between items-center\">\n <div className=\"inline-flex items-center gap-1.5 text-sm font-medium\">\n <statusInfo.icon className={cn('size-4', statusInfo.color)} />\n {statusInfo.description}\n </div>\n <button\n type=\"button\"\n className={cn(buttonVariants({ size: 'sm', variant: 'outline' }))}\n onClick={() => reset()}\n >\n Close\n </button>\n </div>\n <p className=\"text-sm text-fd-muted-foreground\">{data.status}</p>\n {data.data !== undefined && (\n <DynamicCodeBlock\n lang={typeof data.data === 'string' && data.data.length > 50000 ? 'text' : data.type}\n code={typeof data.data === 'string' ? data.data : JSON.stringify(data.data, null, 2)}\n options={shikiOptions}\n />\n )}\n </div>\n );\n}\n\nfunction CollapsiblePanel({\n title,\n children,\n ...props\n}: Omit<ComponentProps<'div'>, 'title'> & {\n title: ReactNode;\n}) {\n return (\n <Collapsible {...props} className=\"border-b last:border-b-0\">\n <CollapsibleTrigger className=\"group w-full flex items-center gap-2 p-3 text-sm font-medium\">\n {title}\n <ChevronDown className=\"ms-auto size-3.5 text-fd-muted-foreground group-data-[state=open]:rotate-180\" />\n </CollapsibleTrigger>\n <CollapsibleContent>\n <div className=\"flex flex-col gap-3 p-3 pt-1\">{children}</div>\n </CollapsibleContent>\n </Collapsible>\n );\n}\n\nexport const Custom = {\n useController(\n fieldName: FieldKey,\n options?: {\n defaultValue?: unknown;\n },\n ) {\n const [value, setValue] = useFieldValue(fieldName, options);\n return {\n value,\n setValue,\n };\n },\n};\n"],"mappings":"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"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
"use client";
|
|
3
2
|
import { cn } from "../../utils/cn.js";
|
|
4
3
|
import { FormatFlags } from "../../utils/schema-to-string.js";
|
|
5
4
|
import { anyFields, useFieldInfo, useResolvedSchema, useSchemaScope, useSchemaUtils } from "../schema.js";
|
|
@@ -12,7 +11,6 @@ import { cva } from "class-variance-authority";
|
|
|
12
11
|
import { buttonVariants } from "fumadocs-ui/components/ui/button";
|
|
13
12
|
import { useArray, useDataEngine, useFieldValue, useObject } from "@fumari/stf";
|
|
14
13
|
import { stringifyFieldKey } from "@fumari/stf/lib/utils";
|
|
15
|
-
|
|
16
14
|
//#region src/playground/components/inputs.tsx
|
|
17
15
|
const fieldLabelVariants = cva("w-full inline-flex items-center gap-0.5");
|
|
18
16
|
function FieldLabelType(props) {
|
|
@@ -414,7 +412,7 @@ function ArrayInput({ fieldName, items: itemSchema, ...props }) {
|
|
|
414
412
|
})]
|
|
415
413
|
});
|
|
416
414
|
}
|
|
417
|
-
|
|
418
415
|
//#endregion
|
|
419
416
|
export { FieldInput, FieldSet, JsonInput, ObjectInput };
|
|
417
|
+
|
|
420
418
|
//# sourceMappingURL=inputs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inputs.js","names":[],"sources":["../../../src/playground/components/inputs.tsx"],"sourcesContent":["'use client';\nimport { type ComponentProps, type HTMLAttributes, type ReactNode, useState } from 'react';\nimport { ChevronRight, Plus, Trash2, X } from 'lucide-react';\nimport { FieldKey, useArray, useDataEngine, useFieldValue, useObject } from '@fumari/stf';\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/ui/components/select';\nimport { Input, labelVariants } from '@/ui/components/input';\nimport { cn } from '@/utils/cn';\nimport { buttonVariants } from 'fumadocs-ui/components/ui/button';\nimport { FormatFlags } from '@/utils/schema-to-string';\nimport {\n anyFields,\n useFieldInfo,\n useSchemaUtils,\n useSchemaScope,\n useResolvedSchema,\n} from '@/playground/schema';\nimport type { ParsedSchema } from '@/utils/schema';\nimport { stringifyFieldKey } from '@fumari/stf/lib/utils';\nimport { cva } from 'class-variance-authority';\n\nconst fieldLabelVariants = cva('w-full inline-flex items-center gap-0.5');\n\nfunction FieldLabelType(props: ComponentProps<'code'>) {\n return (\n <code {...props} className={cn('text-xs text-fd-muted-foreground', props.className)}>\n {props.children}\n </code>\n );\n}\n\nexport function ObjectInput({\n field: _field,\n fieldName,\n ...props\n}: {\n field: Exclude<ParsedSchema, boolean>;\n fieldName: FieldKey;\n} & ComponentProps<'div'>) {\n const { generateDefault } = useSchemaUtils();\n const field = useResolvedSchema(_field);\n const schemaPropKeys = field.properties ? Object.keys(field.properties) : [];\n const {\n patternProperties = {},\n additionalProperties,\n 'x-playground-lazy': isLazy = schemaPropKeys.length > 100,\n } = field;\n const isDynamic = Object.keys(patternProperties).length > 0 || additionalProperties;\n\n const [nextName, setNextName] = useState('');\n const { properties, onAppend, onDelete, _objectKeys } = useObject(fieldName, {\n lazy: isLazy,\n defaultValue: () => generateDefault(field) as object,\n properties: field.properties ?? {},\n fallback: additionalProperties,\n patternProperties: patternProperties,\n });\n\n const hiddenProperties = isLazy ? schemaPropKeys.filter((key) => !_objectKeys.includes(key)) : [];\n\n return (\n <div\n {...props}\n className={cn(\n 'grid grid-cols-1 gap-4 @md:grid-cols-2 *:data-[collapsible=true]:order-last',\n props.className,\n )}\n >\n {isLazy && hiddenProperties.length > 0 && (\n <Select value=\"\" onValueChange={onAppend}>\n <SelectTrigger className=\"col-span-full\">\n <SelectValue placeholder=\"Show Property\" />\n </SelectTrigger>\n <SelectContent>\n {hiddenProperties.map((key) => (\n <SelectItem key={key} value={key}>\n {key}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )}\n\n {properties.map((child) => {\n let toolbar: ReactNode = null;\n if (child.kind === 'pattern' || child.kind === 'fallback') {\n toolbar = (\n <button\n type=\"button\"\n aria-label=\"Remove Item\"\n className={cn(\n buttonVariants({\n color: 'outline',\n size: 'icon-xs',\n }),\n )}\n onClick={() => {\n onDelete(child.key);\n }}\n >\n <Trash2 />\n </button>\n );\n }\n\n return (\n <FieldSet\n key={child.key}\n name={child.key}\n field={child.info}\n fieldName={child.field}\n isRequired={field.required?.includes(child.key)}\n toolbar={toolbar}\n />\n );\n })}\n {isDynamic && (\n <div className=\"flex gap-2 order-last col-span-full\">\n <Input\n value={nextName}\n placeholder=\"Enter Property Name\"\n onChange={(e) => setNextName(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n setNextName('');\n onAppend(nextName);\n e.preventDefault();\n }\n }}\n />\n <button\n type=\"button\"\n className={cn(buttonVariants({ color: 'secondary', size: 'sm' }), 'px-4')}\n onClick={() => {\n onAppend(nextName);\n setNextName('');\n }}\n >\n New\n </button>\n </div>\n )}\n </div>\n );\n}\n\nexport function JsonInput({ fieldName }: { fieldName: FieldKey }) {\n const engine = useDataEngine();\n const [error, setError] = useState<string | null>(null);\n const [value, setValue] = useState(() => JSON.stringify(engine.init(fieldName, {}), null, 2));\n\n return (\n <div className=\"flex flex-col bg-fd-secondary text-fd-secondary-foreground overflow-hidden border rounded-lg\">\n <textarea\n value={value}\n className=\"p-2 h-[240px] text-sm font-mono resize-none focus-visible:outline-none\"\n onChange={(v) => {\n setValue(v.target.value);\n try {\n engine.update(fieldName, JSON.parse(v.target.value));\n setError(null);\n } catch (e) {\n if (e instanceof Error) setError(e.message);\n }\n }}\n />\n <p className=\"p-2 text-xs font-mono border-t text-red-400 empty:hidden\">{error}</p>\n </div>\n );\n}\n\nexport function FieldInput({\n field,\n fieldName,\n isRequired,\n ...props\n}: HTMLAttributes<HTMLElement> & {\n field: Exclude<ParsedSchema, boolean>;\n isRequired?: boolean;\n fieldName: FieldKey;\n}) {\n const [value, setValue] = useFieldValue(fieldName);\n const id = stringifyFieldKey(fieldName);\n if (field.type === 'null') return;\n\n if (field.type === 'string' && field.format === 'binary') {\n return (\n <>\n <label\n htmlFor={id}\n className={cn(\n buttonVariants({\n color: 'secondary',\n className: 'w-full h-9 gap-2 truncate',\n }),\n )}\n >\n {value instanceof File ? (\n <>\n <span className=\"text-fd-muted-foreground text-xs\">Selected</span>\n <span className=\"truncate w-0 flex-1 text-end\">{value.name}</span>\n </>\n ) : (\n <span className=\"text-fd-muted-foreground\">Upload</span>\n )}\n </label>\n <input\n id={id}\n type=\"file\"\n multiple={false}\n onChange={(e) => {\n if (!e.target.files || e.target.files.length === 0) return;\n setValue(e.target.files.item(0));\n }}\n hidden\n />\n </>\n );\n }\n\n if (field.enum && field.enum.length > 0) {\n const idx = field.enum.indexOf(value);\n\n return (\n <Select\n value={idx === -1 && isRequired ? '' : String(idx)}\n onValueChange={(v) => setValue(field.enum![Number(v)])}\n >\n <SelectTrigger id={id} {...props}>\n <SelectValue placeholder=\"Select\" />\n </SelectTrigger>\n <SelectContent>\n {field.enum.map((item, i) => (\n <SelectItem key={i} value={String(i)}>\n {typeof item === 'string' ? item : JSON.stringify(item, null, 2)}\n </SelectItem>\n ))}\n {!isRequired && <SelectItem value=\"-1\">Unset</SelectItem>}\n </SelectContent>\n </Select>\n );\n }\n\n if (field.type === 'boolean') {\n return (\n <Select\n value={String(value)}\n onValueChange={(value) => setValue(value === 'undefined' ? undefined : value === 'true')}\n >\n <SelectTrigger id={id} {...props}>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"true\">True</SelectItem>\n <SelectItem value=\"false\">False</SelectItem>\n {!isRequired && <SelectItem value=\"undefined\">Unset</SelectItem>}\n </SelectContent>\n </Select>\n );\n }\n\n const isNumber = field.type === 'integer' || field.type === 'number';\n return (\n <Input\n id={id}\n placeholder=\"Enter value\"\n type={isNumber ? 'number' : 'text'}\n step={field.type === 'integer' ? 1 : undefined}\n value={String(value ?? '')}\n onChange={(e) => {\n if (isNumber) {\n setValue(Number.isNaN(e.target.valueAsNumber) ? undefined : e.target.valueAsNumber);\n } else if (!isNumber) {\n setValue(e.target.value);\n }\n }}\n />\n );\n}\n\nexport function FieldSet({\n field: _field,\n fieldName,\n toolbar,\n name,\n isRequired,\n depth = 0,\n slotType,\n collapsible = true,\n ...props\n}: HTMLAttributes<HTMLElement> & {\n isRequired?: boolean;\n name?: ReactNode;\n field: ParsedSchema;\n fieldName: FieldKey;\n depth?: number;\n\n slotType?: ReactNode;\n toolbar?: ReactNode;\n collapsible?: boolean;\n}) {\n const { readOnly, writeOnly } = useSchemaScope();\n const { generateDefault, schemaToString } = useSchemaUtils();\n const field = useResolvedSchema(_field);\n const [show, setShow] = useState(!collapsible);\n const { info, updateInfo } = useFieldInfo(fieldName, field, depth);\n const id = stringifyFieldKey(fieldName);\n const dataEngine = useDataEngine();\n const [isDefined] = useFieldValue(fieldName, {\n compute(currentValue) {\n return currentValue !== undefined;\n },\n });\n\n if (_field === false) return;\n if (field.readOnly && !readOnly) return;\n if (field.writeOnly && !writeOnly) return;\n\n if (collapsible && !isDefined && show) setShow(false);\n\n function renderLabelTrigger(schema = field) {\n if (!collapsible) return renderLabelName();\n\n return (\n <button\n type=\"button\"\n className={cn(labelVariants(), 'inline-flex items-center gap-1 font-mono me-auto')}\n onClick={() => {\n dataEngine.init(fieldName, generateDefault(schema));\n setShow((prev) => !prev);\n }}\n >\n <ChevronRight className={cn('size-3.5 text-fd-muted-foreground', show && 'rotate-90')} />\n {name}\n {isRequired && <span className=\"text-red-400/80\">*</span>}\n </button>\n );\n }\n\n function renderLabelName() {\n return (\n <span className={cn(labelVariants(), 'font-mono me-auto')}>\n {name}\n {isRequired && <span className=\"text-red-400/80 mx-1\">*</span>}\n </span>\n );\n }\n\n function renderUnsetButton() {\n return (\n <button\n type=\"button\"\n onClick={() => dataEngine.delete(fieldName)}\n className=\"text-fd-muted-foreground hover:text-fd-accent-foreground\"\n >\n <X className=\"size-3.5\" />\n </button>\n );\n }\n\n if (info.unionField && field[info.unionField]) {\n const union = field[info.unionField]!;\n const showSelect = union.length > 1;\n\n return (\n <FieldSet\n {...props}\n name={name}\n fieldName={fieldName}\n isRequired={isRequired}\n field={union[info.oneOf]}\n depth={depth + 1}\n slotType={showSelect ? false : slotType}\n collapsible={collapsible}\n toolbar={\n <>\n {showSelect && (\n <select\n className=\"text-xs font-mono\"\n value={info.oneOf}\n onChange={(e) => {\n updateInfo({\n oneOf: Number(e.target.value),\n });\n }}\n >\n {union.map((item, i) => (\n <option key={i} value={i} className=\"bg-fd-popover text-fd-popover-foreground\">\n {schemaToString(item, FormatFlags.UseAlias)}\n </option>\n ))}\n </select>\n )}\n {toolbar}\n </>\n }\n />\n );\n }\n\n if (Array.isArray(field.type)) {\n const showSelect = field.type.length > 1;\n\n return (\n <FieldSet\n {...props}\n name={name}\n fieldName={fieldName}\n isRequired={isRequired}\n field={{\n ...field,\n type: info.selectedType,\n }}\n collapsible={collapsible}\n depth={depth + 1}\n slotType={showSelect ? false : slotType}\n toolbar={\n <>\n {showSelect && (\n <select\n className=\"text-xs font-mono\"\n value={info.selectedType}\n onChange={(e) => {\n updateInfo({\n selectedType: e.target.value,\n });\n }}\n >\n {field.type.map((item) => (\n <option\n key={item}\n value={item}\n className=\"bg-fd-popover text-fd-popover-foreground\"\n >\n {item}\n </option>\n ))}\n </select>\n )}\n {toolbar}\n </>\n }\n />\n );\n }\n\n if (field.type === 'object') {\n return (\n <fieldset\n {...props}\n data-collapsible={collapsible}\n className={cn('flex flex-col gap-1.5 col-span-full @container', props.className)}\n >\n <div className={fieldLabelVariants()}>\n {renderLabelTrigger(field)}\n {slotType ?? <FieldLabelType>{schemaToString(field)}</FieldLabelType>}\n {toolbar}\n {!isRequired && isDefined && renderUnsetButton()}\n </div>\n {show && (\n <ObjectInput\n field={field}\n fieldName={fieldName}\n className=\"rounded-lg border border-fd-primary/20 bg-fd-background/50 p-2 shadow-sm\"\n />\n )}\n </fieldset>\n );\n }\n\n if (field.type === 'array') {\n return (\n <fieldset\n {...props}\n data-collapsible={collapsible}\n className={cn('flex flex-col gap-1.5 col-span-full', props.className)}\n >\n <div className={fieldLabelVariants()}>\n {renderLabelTrigger()}\n {slotType ?? <FieldLabelType>{schemaToString(field)}</FieldLabelType>}\n {toolbar}\n {!isRequired && isDefined && renderUnsetButton()}\n </div>\n {show && (\n <ArrayInput\n fieldName={fieldName}\n items={field.items ?? anyFields}\n className=\"rounded-lg border border-fd-primary/20 bg-fd-background/50 p-2 shadow-sm\"\n />\n )}\n </fieldset>\n );\n }\n\n return (\n <fieldset {...props} className={cn('flex flex-col gap-1.5', props.className)}>\n <label className={fieldLabelVariants()} htmlFor={id}>\n {renderLabelName()}\n {slotType ?? <FieldLabelType>{schemaToString(field)}</FieldLabelType>}\n {toolbar}\n {!isRequired && isDefined && renderUnsetButton()}\n </label>\n <FieldInput field={field} fieldName={fieldName} isRequired={isRequired} />\n </fieldset>\n );\n}\n\nfunction ArrayInput({\n fieldName,\n items: itemSchema,\n ...props\n}: {\n fieldName: FieldKey;\n items: ParsedSchema;\n} & ComponentProps<'div'>) {\n const name = fieldName.at(-1) ?? '';\n const { generateDefault } = useSchemaUtils();\n const { items, insertItem, removeItem } = useArray(fieldName);\n\n return (\n <div {...props} className={cn('flex flex-col gap-2', props.className)}>\n {items.map((item) => (\n <FieldSet\n key={item.index}\n name={\n <span className=\"text-fd-muted-foreground\">\n {name}[{item.index}]\n </span>\n }\n field={itemSchema}\n isRequired\n fieldName={item.field}\n toolbar={\n <button\n type=\"button\"\n aria-label=\"Remove Item\"\n className={cn(\n buttonVariants({\n color: 'outline',\n size: 'icon-xs',\n }),\n )}\n onClick={() => removeItem(item.index)}\n >\n <Trash2 />\n </button>\n }\n />\n ))}\n <button\n type=\"button\"\n className={cn(\n buttonVariants({\n color: 'secondary',\n className: 'gap-1.5 py-2',\n size: 'sm',\n }),\n )}\n onClick={() => {\n insertItem(generateDefault(itemSchema));\n }}\n >\n <Plus className=\"size-4\" />\n New Item\n </button>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"inputs.js","names":[],"sources":["../../../src/playground/components/inputs.tsx"],"sourcesContent":["'use client';\nimport { type ComponentProps, type HTMLAttributes, type ReactNode, useState } from 'react';\nimport { ChevronRight, Plus, Trash2, X } from 'lucide-react';\nimport { FieldKey, useArray, useDataEngine, useFieldValue, useObject } from '@fumari/stf';\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/ui/components/select';\nimport { Input, labelVariants } from '@/ui/components/input';\nimport { cn } from '@/utils/cn';\nimport { buttonVariants } from 'fumadocs-ui/components/ui/button';\nimport { FormatFlags } from '@/utils/schema-to-string';\nimport {\n anyFields,\n useFieldInfo,\n useSchemaUtils,\n useSchemaScope,\n useResolvedSchema,\n} from '@/playground/schema';\nimport type { ParsedSchema } from '@/utils/schema';\nimport { stringifyFieldKey } from '@fumari/stf/lib/utils';\nimport { cva } from 'class-variance-authority';\n\nconst fieldLabelVariants = cva('w-full inline-flex items-center gap-0.5');\n\nfunction FieldLabelType(props: ComponentProps<'code'>) {\n return (\n <code {...props} className={cn('text-xs text-fd-muted-foreground', props.className)}>\n {props.children}\n </code>\n );\n}\n\nexport function ObjectInput({\n field: _field,\n fieldName,\n ...props\n}: {\n field: Exclude<ParsedSchema, boolean>;\n fieldName: FieldKey;\n} & ComponentProps<'div'>) {\n const { generateDefault } = useSchemaUtils();\n const field = useResolvedSchema(_field);\n const schemaPropKeys = field.properties ? Object.keys(field.properties) : [];\n const {\n patternProperties = {},\n additionalProperties,\n 'x-playground-lazy': isLazy = schemaPropKeys.length > 100,\n } = field;\n const isDynamic = Object.keys(patternProperties).length > 0 || additionalProperties;\n\n const [nextName, setNextName] = useState('');\n const { properties, onAppend, onDelete, _objectKeys } = useObject(fieldName, {\n lazy: isLazy,\n defaultValue: () => generateDefault(field) as object,\n properties: field.properties ?? {},\n fallback: additionalProperties,\n patternProperties: patternProperties,\n });\n\n const hiddenProperties = isLazy ? schemaPropKeys.filter((key) => !_objectKeys.includes(key)) : [];\n\n return (\n <div\n {...props}\n className={cn(\n 'grid grid-cols-1 gap-4 @md:grid-cols-2 *:data-[collapsible=true]:order-last',\n props.className,\n )}\n >\n {isLazy && hiddenProperties.length > 0 && (\n <Select value=\"\" onValueChange={onAppend}>\n <SelectTrigger className=\"col-span-full\">\n <SelectValue placeholder=\"Show Property\" />\n </SelectTrigger>\n <SelectContent>\n {hiddenProperties.map((key) => (\n <SelectItem key={key} value={key}>\n {key}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )}\n\n {properties.map((child) => {\n let toolbar: ReactNode = null;\n if (child.kind === 'pattern' || child.kind === 'fallback') {\n toolbar = (\n <button\n type=\"button\"\n aria-label=\"Remove Item\"\n className={cn(\n buttonVariants({\n color: 'outline',\n size: 'icon-xs',\n }),\n )}\n onClick={() => {\n onDelete(child.key);\n }}\n >\n <Trash2 />\n </button>\n );\n }\n\n return (\n <FieldSet\n key={child.key}\n name={child.key}\n field={child.info}\n fieldName={child.field}\n isRequired={field.required?.includes(child.key)}\n toolbar={toolbar}\n />\n );\n })}\n {isDynamic && (\n <div className=\"flex gap-2 order-last col-span-full\">\n <Input\n value={nextName}\n placeholder=\"Enter Property Name\"\n onChange={(e) => setNextName(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n setNextName('');\n onAppend(nextName);\n e.preventDefault();\n }\n }}\n />\n <button\n type=\"button\"\n className={cn(buttonVariants({ color: 'secondary', size: 'sm' }), 'px-4')}\n onClick={() => {\n onAppend(nextName);\n setNextName('');\n }}\n >\n New\n </button>\n </div>\n )}\n </div>\n );\n}\n\nexport function JsonInput({ fieldName }: { fieldName: FieldKey }) {\n const engine = useDataEngine();\n const [error, setError] = useState<string | null>(null);\n const [value, setValue] = useState(() => JSON.stringify(engine.init(fieldName, {}), null, 2));\n\n return (\n <div className=\"flex flex-col bg-fd-secondary text-fd-secondary-foreground overflow-hidden border rounded-lg\">\n <textarea\n value={value}\n className=\"p-2 h-[240px] text-sm font-mono resize-none focus-visible:outline-none\"\n onChange={(v) => {\n setValue(v.target.value);\n try {\n engine.update(fieldName, JSON.parse(v.target.value));\n setError(null);\n } catch (e) {\n if (e instanceof Error) setError(e.message);\n }\n }}\n />\n <p className=\"p-2 text-xs font-mono border-t text-red-400 empty:hidden\">{error}</p>\n </div>\n );\n}\n\nexport function FieldInput({\n field,\n fieldName,\n isRequired,\n ...props\n}: HTMLAttributes<HTMLElement> & {\n field: Exclude<ParsedSchema, boolean>;\n isRequired?: boolean;\n fieldName: FieldKey;\n}) {\n const [value, setValue] = useFieldValue(fieldName);\n const id = stringifyFieldKey(fieldName);\n if (field.type === 'null') return;\n\n if (field.type === 'string' && field.format === 'binary') {\n return (\n <>\n <label\n htmlFor={id}\n className={cn(\n buttonVariants({\n color: 'secondary',\n className: 'w-full h-9 gap-2 truncate',\n }),\n )}\n >\n {value instanceof File ? (\n <>\n <span className=\"text-fd-muted-foreground text-xs\">Selected</span>\n <span className=\"truncate w-0 flex-1 text-end\">{value.name}</span>\n </>\n ) : (\n <span className=\"text-fd-muted-foreground\">Upload</span>\n )}\n </label>\n <input\n id={id}\n type=\"file\"\n multiple={false}\n onChange={(e) => {\n if (!e.target.files || e.target.files.length === 0) return;\n setValue(e.target.files.item(0));\n }}\n hidden\n />\n </>\n );\n }\n\n if (field.enum && field.enum.length > 0) {\n const idx = field.enum.indexOf(value);\n\n return (\n <Select\n value={idx === -1 && isRequired ? '' : String(idx)}\n onValueChange={(v) => setValue(field.enum![Number(v)])}\n >\n <SelectTrigger id={id} {...props}>\n <SelectValue placeholder=\"Select\" />\n </SelectTrigger>\n <SelectContent>\n {field.enum.map((item, i) => (\n <SelectItem key={i} value={String(i)}>\n {typeof item === 'string' ? item : JSON.stringify(item, null, 2)}\n </SelectItem>\n ))}\n {!isRequired && <SelectItem value=\"-1\">Unset</SelectItem>}\n </SelectContent>\n </Select>\n );\n }\n\n if (field.type === 'boolean') {\n return (\n <Select\n value={String(value)}\n onValueChange={(value) => setValue(value === 'undefined' ? undefined : value === 'true')}\n >\n <SelectTrigger id={id} {...props}>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"true\">True</SelectItem>\n <SelectItem value=\"false\">False</SelectItem>\n {!isRequired && <SelectItem value=\"undefined\">Unset</SelectItem>}\n </SelectContent>\n </Select>\n );\n }\n\n const isNumber = field.type === 'integer' || field.type === 'number';\n return (\n <Input\n id={id}\n placeholder=\"Enter value\"\n type={isNumber ? 'number' : 'text'}\n step={field.type === 'integer' ? 1 : undefined}\n value={String(value ?? '')}\n onChange={(e) => {\n if (isNumber) {\n setValue(Number.isNaN(e.target.valueAsNumber) ? undefined : e.target.valueAsNumber);\n } else if (!isNumber) {\n setValue(e.target.value);\n }\n }}\n />\n );\n}\n\nexport function FieldSet({\n field: _field,\n fieldName,\n toolbar,\n name,\n isRequired,\n depth = 0,\n slotType,\n collapsible = true,\n ...props\n}: HTMLAttributes<HTMLElement> & {\n isRequired?: boolean;\n name?: ReactNode;\n field: ParsedSchema;\n fieldName: FieldKey;\n depth?: number;\n\n slotType?: ReactNode;\n toolbar?: ReactNode;\n collapsible?: boolean;\n}) {\n const { readOnly, writeOnly } = useSchemaScope();\n const { generateDefault, schemaToString } = useSchemaUtils();\n const field = useResolvedSchema(_field);\n const [show, setShow] = useState(!collapsible);\n const { info, updateInfo } = useFieldInfo(fieldName, field, depth);\n const id = stringifyFieldKey(fieldName);\n const dataEngine = useDataEngine();\n const [isDefined] = useFieldValue(fieldName, {\n compute(currentValue) {\n return currentValue !== undefined;\n },\n });\n\n if (_field === false) return;\n if (field.readOnly && !readOnly) return;\n if (field.writeOnly && !writeOnly) return;\n\n if (collapsible && !isDefined && show) setShow(false);\n\n function renderLabelTrigger(schema = field) {\n if (!collapsible) return renderLabelName();\n\n return (\n <button\n type=\"button\"\n className={cn(labelVariants(), 'inline-flex items-center gap-1 font-mono me-auto')}\n onClick={() => {\n dataEngine.init(fieldName, generateDefault(schema));\n setShow((prev) => !prev);\n }}\n >\n <ChevronRight className={cn('size-3.5 text-fd-muted-foreground', show && 'rotate-90')} />\n {name}\n {isRequired && <span className=\"text-red-400/80\">*</span>}\n </button>\n );\n }\n\n function renderLabelName() {\n return (\n <span className={cn(labelVariants(), 'font-mono me-auto')}>\n {name}\n {isRequired && <span className=\"text-red-400/80 mx-1\">*</span>}\n </span>\n );\n }\n\n function renderUnsetButton() {\n return (\n <button\n type=\"button\"\n onClick={() => dataEngine.delete(fieldName)}\n className=\"text-fd-muted-foreground hover:text-fd-accent-foreground\"\n >\n <X className=\"size-3.5\" />\n </button>\n );\n }\n\n if (info.unionField && field[info.unionField]) {\n const union = field[info.unionField]!;\n const showSelect = union.length > 1;\n\n return (\n <FieldSet\n {...props}\n name={name}\n fieldName={fieldName}\n isRequired={isRequired}\n field={union[info.oneOf]}\n depth={depth + 1}\n slotType={showSelect ? false : slotType}\n collapsible={collapsible}\n toolbar={\n <>\n {showSelect && (\n <select\n className=\"text-xs font-mono\"\n value={info.oneOf}\n onChange={(e) => {\n updateInfo({\n oneOf: Number(e.target.value),\n });\n }}\n >\n {union.map((item, i) => (\n <option key={i} value={i} className=\"bg-fd-popover text-fd-popover-foreground\">\n {schemaToString(item, FormatFlags.UseAlias)}\n </option>\n ))}\n </select>\n )}\n {toolbar}\n </>\n }\n />\n );\n }\n\n if (Array.isArray(field.type)) {\n const showSelect = field.type.length > 1;\n\n return (\n <FieldSet\n {...props}\n name={name}\n fieldName={fieldName}\n isRequired={isRequired}\n field={{\n ...field,\n type: info.selectedType,\n }}\n collapsible={collapsible}\n depth={depth + 1}\n slotType={showSelect ? false : slotType}\n toolbar={\n <>\n {showSelect && (\n <select\n className=\"text-xs font-mono\"\n value={info.selectedType}\n onChange={(e) => {\n updateInfo({\n selectedType: e.target.value,\n });\n }}\n >\n {field.type.map((item) => (\n <option\n key={item}\n value={item}\n className=\"bg-fd-popover text-fd-popover-foreground\"\n >\n {item}\n </option>\n ))}\n </select>\n )}\n {toolbar}\n </>\n }\n />\n );\n }\n\n if (field.type === 'object') {\n return (\n <fieldset\n {...props}\n data-collapsible={collapsible}\n className={cn('flex flex-col gap-1.5 col-span-full @container', props.className)}\n >\n <div className={fieldLabelVariants()}>\n {renderLabelTrigger(field)}\n {slotType ?? <FieldLabelType>{schemaToString(field)}</FieldLabelType>}\n {toolbar}\n {!isRequired && isDefined && renderUnsetButton()}\n </div>\n {show && (\n <ObjectInput\n field={field}\n fieldName={fieldName}\n className=\"rounded-lg border border-fd-primary/20 bg-fd-background/50 p-2 shadow-sm\"\n />\n )}\n </fieldset>\n );\n }\n\n if (field.type === 'array') {\n return (\n <fieldset\n {...props}\n data-collapsible={collapsible}\n className={cn('flex flex-col gap-1.5 col-span-full', props.className)}\n >\n <div className={fieldLabelVariants()}>\n {renderLabelTrigger()}\n {slotType ?? <FieldLabelType>{schemaToString(field)}</FieldLabelType>}\n {toolbar}\n {!isRequired && isDefined && renderUnsetButton()}\n </div>\n {show && (\n <ArrayInput\n fieldName={fieldName}\n items={field.items ?? anyFields}\n className=\"rounded-lg border border-fd-primary/20 bg-fd-background/50 p-2 shadow-sm\"\n />\n )}\n </fieldset>\n );\n }\n\n return (\n <fieldset {...props} className={cn('flex flex-col gap-1.5', props.className)}>\n <label className={fieldLabelVariants()} htmlFor={id}>\n {renderLabelName()}\n {slotType ?? <FieldLabelType>{schemaToString(field)}</FieldLabelType>}\n {toolbar}\n {!isRequired && isDefined && renderUnsetButton()}\n </label>\n <FieldInput field={field} fieldName={fieldName} isRequired={isRequired} />\n </fieldset>\n );\n}\n\nfunction ArrayInput({\n fieldName,\n items: itemSchema,\n ...props\n}: {\n fieldName: FieldKey;\n items: ParsedSchema;\n} & ComponentProps<'div'>) {\n const name = fieldName.at(-1) ?? '';\n const { generateDefault } = useSchemaUtils();\n const { items, insertItem, removeItem } = useArray(fieldName);\n\n return (\n <div {...props} className={cn('flex flex-col gap-2', props.className)}>\n {items.map((item) => (\n <FieldSet\n key={item.index}\n name={\n <span className=\"text-fd-muted-foreground\">\n {name}[{item.index}]\n </span>\n }\n field={itemSchema}\n isRequired\n fieldName={item.field}\n toolbar={\n <button\n type=\"button\"\n aria-label=\"Remove Item\"\n className={cn(\n buttonVariants({\n color: 'outline',\n size: 'icon-xs',\n }),\n )}\n onClick={() => removeItem(item.index)}\n >\n <Trash2 />\n </button>\n }\n />\n ))}\n <button\n type=\"button\"\n className={cn(\n buttonVariants({\n color: 'secondary',\n className: 'gap-1.5 py-2',\n size: 'sm',\n }),\n )}\n onClick={() => {\n insertItem(generateDefault(itemSchema));\n }}\n >\n <Plus className=\"size-4\" />\n New Item\n </button>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -7,7 +7,6 @@ import { useEffect, useState } from "react";
|
|
|
7
7
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
8
8
|
import { buttonVariants } from "fumadocs-ui/components/ui/button";
|
|
9
9
|
import { useForm } from "react-hook-form";
|
|
10
|
-
|
|
11
10
|
//#region src/playground/components/oauth-dialog.tsx
|
|
12
11
|
const FlowTypes = {
|
|
13
12
|
password: {
|
|
@@ -279,7 +278,7 @@ function OauthDialog({ scheme, scopes, setToken, children, open, setOpen }) {
|
|
|
279
278
|
});
|
|
280
279
|
}
|
|
281
280
|
const OauthDialogTrigger = DialogTrigger;
|
|
282
|
-
|
|
283
281
|
//#endregion
|
|
284
282
|
export { OauthDialog, OauthDialogTrigger };
|
|
283
|
+
|
|
285
284
|
//# sourceMappingURL=oauth-dialog.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-dialog.js","names":[],"sources":["../../../src/playground/components/oauth-dialog.tsx"],"sourcesContent":["import {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from '@/ui/components/dialog';\nimport { useForm } from 'react-hook-form';\nimport { Input, labelVariants } from '@/ui/components/input';\nimport { useQuery } from '@/utils/use-query';\nimport { type ReactNode, useEffect, useState } from 'react';\nimport { cn } from '@/utils/cn';\nimport { buttonVariants } from 'fumadocs-ui/components/ui/button';\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/ui/components/select';\nimport type { OAuth2SecurityScheme } from '@/types';\n\ntype FlowType = keyof NonNullable<OAuth2SecurityScheme['flows']>;\n\nexport interface AuthDialogProps {\n scheme: OAuth2SecurityScheme;\n scopes: string[];\n\n open: boolean;\n setOpen: (v: boolean) => void;\n setToken: (token: string) => void;\n children: ReactNode;\n}\n\ninterface FormValues {\n clientId: string;\n clientSecret: string;\n username: string;\n password: string;\n}\n\ninterface AuthCodeState {\n redirect_uri: string;\n client_id: string;\n client_secret: string;\n}\n\ninterface ImplicitState {\n redirect_uri: string;\n client_id: string;\n}\n\nconst FlowTypes = {\n password: {\n name: 'Resource Owner Password Flow',\n description: 'Authenticate using username and password.',\n supported: true,\n },\n clientCredentials: {\n name: 'Client Credentials',\n description: 'Intended for the server-to-server authentication.',\n supported: true,\n },\n authorizationCode: {\n name: 'Authorization code',\n description: 'Authenticate with 3rd party services',\n supported: true,\n },\n implicit: {\n name: 'Implicit',\n description: 'Retrieve the access token directly.',\n supported: true,\n },\n deviceAuthorization: {\n name: 'Device Authorization',\n description: 'Authenticate with device.',\n supported: false,\n },\n} as const;\n\nexport function OauthDialog({\n scheme,\n scopes,\n setToken,\n children,\n open,\n setOpen,\n}: AuthDialogProps) {\n const [type, setType] = useState(() => {\n return Object.keys(scheme.flows!)[0] as FlowType;\n });\n const { supported } = FlowTypes[type];\n const form = useForm<FormValues>({\n defaultValues: {\n clientId: '',\n clientSecret: '',\n username: '',\n password: '',\n },\n });\n\n const authCodeCallback = useQuery(async (code: string, state: AuthCodeState) => {\n const value = scheme.flows!.authorizationCode!;\n\n const res = await fetch(value.tokenUrl!, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: new URLSearchParams({\n grant_type: 'authorization_code',\n code,\n // note: `state` could be invalid, but server will check it\n redirect_uri: state.redirect_uri,\n client_id: state.client_id,\n client_secret: state.client_secret,\n }),\n });\n\n if (!res.ok) throw new Error(await res.text());\n const { access_token, token_type = 'Bearer' } = (await res.json()) as {\n access_token: string;\n token_type?: string;\n };\n\n setToken(`${token_type} ${access_token}`);\n setOpen(false);\n });\n\n useEffect(() => {\n if (scheme.flows!.authorizationCode) {\n const params = new URLSearchParams(window.location.search);\n const state = params.get('state');\n const code = params.get('code');\n\n if (state && code) {\n const parsedState = JSON.parse(state) as AuthCodeState;\n setOpen(true);\n\n form.setValue('clientId', parsedState.client_id);\n form.setValue('clientSecret', parsedState.client_secret);\n authCodeCallback.start(code, parsedState);\n window.history.replaceState(null, '', window.location.pathname);\n return;\n }\n }\n\n if (scheme.flows!.implicit && window.location.hash.length > 1) {\n const params = new URLSearchParams(window.location.hash.slice(1));\n const state = params.get('state');\n const token = params.get('access_token');\n const type = params.get('token_type') ?? 'Bearer';\n\n if (state && token) {\n const parsedState = JSON.parse(state) as ImplicitState;\n\n form.setValue('clientId', parsedState.client_id);\n setToken(`${type} ${token}`);\n window.history.replaceState(null, '', window.location.pathname);\n }\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps -- first page load only\n }, []);\n\n const authorize = useQuery(async (values: FormValues) => {\n if (type === 'implicit') {\n const value = scheme.flows![type]!;\n\n const params = new URLSearchParams();\n params.set('response_type', 'token');\n params.set('client_id', values.clientId);\n params.set('redirect_uri', window.location.href);\n params.set('scope', scopes.join('+'));\n params.set(\n 'state',\n JSON.stringify({\n client_id: values.clientId,\n redirect_uri: window.location.href,\n } satisfies ImplicitState),\n );\n\n window.location.replace(`${value.authorizationUrl}?${params.toString()}`);\n return;\n }\n if (type === 'authorizationCode') {\n const value = scheme.flows![type]!;\n\n const params = new URLSearchParams();\n params.set('response_type', 'code');\n params.set('client_id', values.clientId);\n params.set('redirect_uri', window.location.href);\n params.set('scope', scopes.join('+'));\n params.set(\n 'state',\n JSON.stringify({\n client_id: values.clientId,\n client_secret: values.clientSecret,\n redirect_uri: window.location.href,\n } satisfies AuthCodeState),\n );\n\n window.location.replace(`${value.authorizationUrl}?${params.toString()}`);\n return;\n }\n\n let res;\n if (type === 'password') {\n const value = scheme.flows![type]!;\n\n res = await fetch(value.tokenUrl!, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: new URLSearchParams({\n grant_type: 'password',\n username: values.username,\n password: values.password,\n scope: scopes.join('+'),\n }),\n });\n }\n\n if (type === 'clientCredentials') {\n const value = scheme.flows![type]!;\n\n res = await fetch(value.tokenUrl!, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: new URLSearchParams({\n grant_type: 'client_credentials',\n client_id: values.clientId,\n client_secret: values.clientSecret,\n scope: scopes.join('+'),\n }),\n });\n }\n\n if (res) {\n if (!res.ok) throw new Error(await res.text());\n\n const { access_token, token_type = 'Bearer' } = (await res.json()) as {\n access_token: string;\n token_type?: string;\n };\n\n setToken(`${token_type} ${access_token}`);\n setOpen(false);\n }\n });\n\n const onSubmit = form.handleSubmit((values) => {\n return authorize.start(values);\n });\n\n const isLoading = authorize.isLoading || authCodeCallback.isLoading;\n const error = authCodeCallback.error ?? authorize.error;\n\n return (\n <Dialog open={open} onOpenChange={setOpen}>\n {children}\n <DialogContent>\n <DialogHeader>\n <DialogTitle>Authorization</DialogTitle>\n <DialogDescription>Obtain the access token for API.</DialogDescription>\n </DialogHeader>\n <form\n className=\"flex flex-col gap-6\"\n onSubmit={(e) => {\n void onSubmit(e);\n e.stopPropagation();\n }}\n >\n <Select value={type} onValueChange={setType as (s: string) => void}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {Object.keys(scheme.flows!).map((key) => {\n const { name, description } = FlowTypes[key as FlowType];\n\n return (\n <SelectItem key={key} value={key}>\n <p className=\"font-medium\">{name}</p>\n <p className=\"text-fd-muted-foreground\">{description}</p>\n </SelectItem>\n );\n })}\n </SelectContent>\n </Select>\n\n {(type === 'authorizationCode' ||\n type === 'clientCredentials' ||\n type === 'implicit') && (\n <fieldset className=\"flex flex-col gap-1.5\">\n <label htmlFor=\"client_id\" className={cn(labelVariants())}>\n Client ID\n </label>\n <p className=\"text-fd-muted-foreground text-sm\">\n The client ID of your OAuth application.\n </p>\n <Input\n id=\"client_id\"\n placeholder=\"Enter value\"\n type=\"text\"\n autoComplete=\"off\"\n disabled={isLoading}\n {...form.register('clientId', { required: true })}\n />\n </fieldset>\n )}\n {(type === 'authorizationCode' || type === 'clientCredentials') && (\n <fieldset className=\"flex flex-col gap-1.5\">\n <label htmlFor=\"client_secret\" className={cn(labelVariants())}>\n Client Secret\n </label>\n <p className=\"text-fd-muted-foreground text-sm\">\n The client secret of your OAuth application.\n </p>\n <Input\n id=\"client_secret\"\n placeholder=\"Enter value\"\n type=\"password\"\n autoComplete=\"off\"\n disabled={isLoading}\n {...form.register('clientSecret', { required: true })}\n />\n </fieldset>\n )}\n {type === 'password' && (\n <>\n <fieldset className=\"flex flex-col gap-1.5\">\n <label htmlFor=\"username\" className={cn(labelVariants())}>\n Username\n </label>\n <Input\n id=\"username\"\n placeholder=\"Enter value\"\n type=\"text\"\n disabled={isLoading}\n autoComplete=\"off\"\n {...form.register('username', { required: true })}\n />\n </fieldset>\n <fieldset className=\"flex flex-col gap-1.5\">\n <label htmlFor=\"password\" className={cn(labelVariants())}>\n Client Secret\n </label>\n <Input\n id=\"password\"\n placeholder=\"Enter value\"\n type=\"password\"\n autoComplete=\"off\"\n disabled={isLoading}\n {...form.register('password', { required: true })}\n />\n </fieldset>\n </>\n )}\n {supported ? (\n <>\n {error ? <p className=\"text-red-400 font-medium text-sm\">{String(error)}</p> : null}\n <button\n type=\"submit\"\n disabled={isLoading}\n className={cn(\n buttonVariants({\n color: 'primary',\n }),\n )}\n >\n {authCodeCallback.isLoading ? 'Fetching token...' : 'Submit'}\n </button>\n </>\n ) : (\n <p className=\"text-fd-muted-foreground bg-fd-muted p-2 rounded-lg border\">\n Unsupported\n </p>\n )}\n </form>\n </DialogContent>\n </Dialog>\n );\n}\n\nexport const OauthDialogTrigger = DialogTrigger;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"oauth-dialog.js","names":[],"sources":["../../../src/playground/components/oauth-dialog.tsx"],"sourcesContent":["import {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from '@/ui/components/dialog';\nimport { useForm } from 'react-hook-form';\nimport { Input, labelVariants } from '@/ui/components/input';\nimport { useQuery } from '@/utils/use-query';\nimport { type ReactNode, useEffect, useState } from 'react';\nimport { cn } from '@/utils/cn';\nimport { buttonVariants } from 'fumadocs-ui/components/ui/button';\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/ui/components/select';\nimport type { OAuth2SecurityScheme } from '@/types';\n\ntype FlowType = keyof NonNullable<OAuth2SecurityScheme['flows']>;\n\nexport interface AuthDialogProps {\n scheme: OAuth2SecurityScheme;\n scopes: string[];\n\n open: boolean;\n setOpen: (v: boolean) => void;\n setToken: (token: string) => void;\n children: ReactNode;\n}\n\ninterface FormValues {\n clientId: string;\n clientSecret: string;\n username: string;\n password: string;\n}\n\ninterface AuthCodeState {\n redirect_uri: string;\n client_id: string;\n client_secret: string;\n}\n\ninterface ImplicitState {\n redirect_uri: string;\n client_id: string;\n}\n\nconst FlowTypes = {\n password: {\n name: 'Resource Owner Password Flow',\n description: 'Authenticate using username and password.',\n supported: true,\n },\n clientCredentials: {\n name: 'Client Credentials',\n description: 'Intended for the server-to-server authentication.',\n supported: true,\n },\n authorizationCode: {\n name: 'Authorization code',\n description: 'Authenticate with 3rd party services',\n supported: true,\n },\n implicit: {\n name: 'Implicit',\n description: 'Retrieve the access token directly.',\n supported: true,\n },\n deviceAuthorization: {\n name: 'Device Authorization',\n description: 'Authenticate with device.',\n supported: false,\n },\n} as const;\n\nexport function OauthDialog({\n scheme,\n scopes,\n setToken,\n children,\n open,\n setOpen,\n}: AuthDialogProps) {\n const [type, setType] = useState(() => {\n return Object.keys(scheme.flows!)[0] as FlowType;\n });\n const { supported } = FlowTypes[type];\n const form = useForm<FormValues>({\n defaultValues: {\n clientId: '',\n clientSecret: '',\n username: '',\n password: '',\n },\n });\n\n const authCodeCallback = useQuery(async (code: string, state: AuthCodeState) => {\n const value = scheme.flows!.authorizationCode!;\n\n const res = await fetch(value.tokenUrl!, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: new URLSearchParams({\n grant_type: 'authorization_code',\n code,\n // note: `state` could be invalid, but server will check it\n redirect_uri: state.redirect_uri,\n client_id: state.client_id,\n client_secret: state.client_secret,\n }),\n });\n\n if (!res.ok) throw new Error(await res.text());\n const { access_token, token_type = 'Bearer' } = (await res.json()) as {\n access_token: string;\n token_type?: string;\n };\n\n setToken(`${token_type} ${access_token}`);\n setOpen(false);\n });\n\n useEffect(() => {\n if (scheme.flows!.authorizationCode) {\n const params = new URLSearchParams(window.location.search);\n const state = params.get('state');\n const code = params.get('code');\n\n if (state && code) {\n const parsedState = JSON.parse(state) as AuthCodeState;\n setOpen(true);\n\n form.setValue('clientId', parsedState.client_id);\n form.setValue('clientSecret', parsedState.client_secret);\n authCodeCallback.start(code, parsedState);\n window.history.replaceState(null, '', window.location.pathname);\n return;\n }\n }\n\n if (scheme.flows!.implicit && window.location.hash.length > 1) {\n const params = new URLSearchParams(window.location.hash.slice(1));\n const state = params.get('state');\n const token = params.get('access_token');\n const type = params.get('token_type') ?? 'Bearer';\n\n if (state && token) {\n const parsedState = JSON.parse(state) as ImplicitState;\n\n form.setValue('clientId', parsedState.client_id);\n setToken(`${type} ${token}`);\n window.history.replaceState(null, '', window.location.pathname);\n }\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps -- first page load only\n }, []);\n\n const authorize = useQuery(async (values: FormValues) => {\n if (type === 'implicit') {\n const value = scheme.flows![type]!;\n\n const params = new URLSearchParams();\n params.set('response_type', 'token');\n params.set('client_id', values.clientId);\n params.set('redirect_uri', window.location.href);\n params.set('scope', scopes.join('+'));\n params.set(\n 'state',\n JSON.stringify({\n client_id: values.clientId,\n redirect_uri: window.location.href,\n } satisfies ImplicitState),\n );\n\n window.location.replace(`${value.authorizationUrl}?${params.toString()}`);\n return;\n }\n if (type === 'authorizationCode') {\n const value = scheme.flows![type]!;\n\n const params = new URLSearchParams();\n params.set('response_type', 'code');\n params.set('client_id', values.clientId);\n params.set('redirect_uri', window.location.href);\n params.set('scope', scopes.join('+'));\n params.set(\n 'state',\n JSON.stringify({\n client_id: values.clientId,\n client_secret: values.clientSecret,\n redirect_uri: window.location.href,\n } satisfies AuthCodeState),\n );\n\n window.location.replace(`${value.authorizationUrl}?${params.toString()}`);\n return;\n }\n\n let res;\n if (type === 'password') {\n const value = scheme.flows![type]!;\n\n res = await fetch(value.tokenUrl!, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: new URLSearchParams({\n grant_type: 'password',\n username: values.username,\n password: values.password,\n scope: scopes.join('+'),\n }),\n });\n }\n\n if (type === 'clientCredentials') {\n const value = scheme.flows![type]!;\n\n res = await fetch(value.tokenUrl!, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: new URLSearchParams({\n grant_type: 'client_credentials',\n client_id: values.clientId,\n client_secret: values.clientSecret,\n scope: scopes.join('+'),\n }),\n });\n }\n\n if (res) {\n if (!res.ok) throw new Error(await res.text());\n\n const { access_token, token_type = 'Bearer' } = (await res.json()) as {\n access_token: string;\n token_type?: string;\n };\n\n setToken(`${token_type} ${access_token}`);\n setOpen(false);\n }\n });\n\n const onSubmit = form.handleSubmit((values) => {\n return authorize.start(values);\n });\n\n const isLoading = authorize.isLoading || authCodeCallback.isLoading;\n const error = authCodeCallback.error ?? authorize.error;\n\n return (\n <Dialog open={open} onOpenChange={setOpen}>\n {children}\n <DialogContent>\n <DialogHeader>\n <DialogTitle>Authorization</DialogTitle>\n <DialogDescription>Obtain the access token for API.</DialogDescription>\n </DialogHeader>\n <form\n className=\"flex flex-col gap-6\"\n onSubmit={(e) => {\n void onSubmit(e);\n e.stopPropagation();\n }}\n >\n <Select value={type} onValueChange={setType as (s: string) => void}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {Object.keys(scheme.flows!).map((key) => {\n const { name, description } = FlowTypes[key as FlowType];\n\n return (\n <SelectItem key={key} value={key}>\n <p className=\"font-medium\">{name}</p>\n <p className=\"text-fd-muted-foreground\">{description}</p>\n </SelectItem>\n );\n })}\n </SelectContent>\n </Select>\n\n {(type === 'authorizationCode' ||\n type === 'clientCredentials' ||\n type === 'implicit') && (\n <fieldset className=\"flex flex-col gap-1.5\">\n <label htmlFor=\"client_id\" className={cn(labelVariants())}>\n Client ID\n </label>\n <p className=\"text-fd-muted-foreground text-sm\">\n The client ID of your OAuth application.\n </p>\n <Input\n id=\"client_id\"\n placeholder=\"Enter value\"\n type=\"text\"\n autoComplete=\"off\"\n disabled={isLoading}\n {...form.register('clientId', { required: true })}\n />\n </fieldset>\n )}\n {(type === 'authorizationCode' || type === 'clientCredentials') && (\n <fieldset className=\"flex flex-col gap-1.5\">\n <label htmlFor=\"client_secret\" className={cn(labelVariants())}>\n Client Secret\n </label>\n <p className=\"text-fd-muted-foreground text-sm\">\n The client secret of your OAuth application.\n </p>\n <Input\n id=\"client_secret\"\n placeholder=\"Enter value\"\n type=\"password\"\n autoComplete=\"off\"\n disabled={isLoading}\n {...form.register('clientSecret', { required: true })}\n />\n </fieldset>\n )}\n {type === 'password' && (\n <>\n <fieldset className=\"flex flex-col gap-1.5\">\n <label htmlFor=\"username\" className={cn(labelVariants())}>\n Username\n </label>\n <Input\n id=\"username\"\n placeholder=\"Enter value\"\n type=\"text\"\n disabled={isLoading}\n autoComplete=\"off\"\n {...form.register('username', { required: true })}\n />\n </fieldset>\n <fieldset className=\"flex flex-col gap-1.5\">\n <label htmlFor=\"password\" className={cn(labelVariants())}>\n Client Secret\n </label>\n <Input\n id=\"password\"\n placeholder=\"Enter value\"\n type=\"password\"\n autoComplete=\"off\"\n disabled={isLoading}\n {...form.register('password', { required: true })}\n />\n </fieldset>\n </>\n )}\n {supported ? (\n <>\n {error ? <p className=\"text-red-400 font-medium text-sm\">{String(error)}</p> : null}\n <button\n type=\"submit\"\n disabled={isLoading}\n className={cn(\n buttonVariants({\n color: 'primary',\n }),\n )}\n >\n {authCodeCallback.isLoading ? 'Fetching token...' : 'Submit'}\n </button>\n </>\n ) : (\n <p className=\"text-fd-muted-foreground bg-fd-muted p-2 rounded-lg border\">\n Unsupported\n </p>\n )}\n </form>\n </DialogContent>\n </Dialog>\n );\n}\n\nexport const OauthDialogTrigger = DialogTrigger;\n"],"mappings":"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"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
"use client";
|
|
3
2
|
import { resolveServerUrl, withBase } from "../../utils/url.js";
|
|
4
3
|
import { useServerContext, useServerSelectContext } from "../../ui/contexts/api.js";
|
|
5
4
|
import { cn } from "../../utils/cn.js";
|
|
@@ -10,7 +9,6 @@ import { useEffect, useRef, useState } from "react";
|
|
|
10
9
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
10
|
import { EditIcon } from "lucide-react";
|
|
12
11
|
import { StfProvider, useFieldValue, useListener, useStf } from "@fumari/stf";
|
|
13
|
-
|
|
14
12
|
//#region src/playground/components/server-select.tsx
|
|
15
13
|
function ServerSelect(props) {
|
|
16
14
|
const { servers } = useServerContext();
|
|
@@ -122,7 +120,7 @@ function Field({ fieldName, variable }) {
|
|
|
122
120
|
placeholder: "Enter Value"
|
|
123
121
|
});
|
|
124
122
|
}
|
|
125
|
-
|
|
126
123
|
//#endregion
|
|
127
124
|
export { ServerSelect as default };
|
|
125
|
+
|
|
128
126
|
//# sourceMappingURL=server-select.js.map
|