@easydocs/dashboard 0.4.2 → 0.5.2

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/next.config.ts CHANGED
@@ -3,21 +3,7 @@ import type { NextConfig } from 'next'
3
3
  const config: NextConfig = {
4
4
  transpilePackages: ['@easydocs/core'],
5
5
  serverExternalPackages: ['@libsql/client', 'libsql', 'better-sqlite3'],
6
- webpack(webpackConfig, { isServer }) {
7
- if (isServer) {
8
- const existing = Array.isArray(webpackConfig.externals) ? webpackConfig.externals : []
9
- webpackConfig.externals = [
10
- ...existing,
11
- ({ request }: { request?: string }, callback: (err?: Error | null, result?: string) => void) => {
12
- if (request && /^(libsql|@libsql\/)/.test(request)) {
13
- return callback(null, `commonjs ${request}`)
14
- }
15
- callback()
16
- },
17
- ]
18
- }
19
- return webpackConfig
20
- },
6
+ turbopack: {},
21
7
  }
22
8
 
23
9
  export default config
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@easydocs/dashboard",
3
- "version": "0.4.2",
3
+ "version": "0.5.2",
4
4
  "description": "EasyDocs docs dashboard — view and export AI-generated OpenAPI specs",
5
5
  "files": [
6
6
  "src",
@@ -15,11 +15,11 @@
15
15
  "@codemirror/theme-one-dark": "^6.1.3",
16
16
  "@uiw/react-codemirror": "^4.25.9",
17
17
  "js-yaml": "^4.1.0",
18
- "next": "15.1.6",
18
+ "next": "16.2.6",
19
19
  "react": "^19.0.0",
20
- "react-dom": "^19.0.0",
20
+ "react-dom": "^19.2.6",
21
21
  "zod": "^3.25.76",
22
- "@easydocs/core": "0.4.2"
22
+ "@easydocs/core": "0.5.2"
23
23
  },
24
24
  "devDependencies": {
25
25
  "@types/js-yaml": "^4.0.9",
@@ -27,16 +27,21 @@
27
27
  "@types/react": "^19",
28
28
  "@types/react-dom": "^19",
29
29
  "eslint": "^9",
30
- "eslint-config-next": "15.1.6",
30
+ "eslint-config-next": "16.2.6",
31
31
  "postcss": "^8",
32
32
  "tailwindcss": "^3.4.1",
33
33
  "typescript": "^5"
34
34
  },
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "https://github.com/RubenGlez/easydocs",
38
+ "directory": ""
39
+ },
35
40
  "scripts": {
36
41
  "dev": "next dev --port 4999",
37
42
  "build": "next build",
38
43
  "start": "next start --port 4999",
39
44
  "typecheck": "tsc --noEmit",
40
- "lint": "next lint"
45
+ "lint": "eslint ."
41
46
  }
42
47
  }
@@ -9,7 +9,7 @@ function ValueNode({ value, depth = 0 }: { value: unknown; depth?: number }) {
9
9
  if (typeof value === 'number')
10
10
  return <span className="text-amber-400">{String(value)}</span>
11
11
  if (typeof value === 'string')
12
- return <span className="text-green-400">"{value}"</span>
12
+ return <span className="text-green-400">&quot;{value}&quot;</span>
13
13
 
14
14
  if (Array.isArray(value)) {
15
15
  if (value.length === 0) return <span className="text-zinc-400">[]</span>
@@ -38,7 +38,7 @@ function ValueNode({ value, depth = 0 }: { value: unknown; depth?: number }) {
38
38
  <div className="ml-4">
39
39
  {entries.map(([k, v], i) => (
40
40
  <div key={k}>
41
- <span className="text-sky-300">"{k}"</span>
41
+ <span className="text-sky-300">&quot;{k}&quot;</span>
42
42
  <span className="text-zinc-400">: </span>
43
43
  <ValueNode value={v} depth={depth + 1} />
44
44
  {i < entries.length - 1 && <span className="text-zinc-600">,</span>}
@@ -1,12 +1,12 @@
1
1
  'use client'
2
2
 
3
- import { useState, useEffect } from 'react'
3
+ import { useState } from 'react'
4
4
  import CodeMirror from '@uiw/react-codemirror'
5
5
  import { json } from '@codemirror/lang-json'
6
6
  import { oneDark } from '@codemirror/theme-one-dark'
7
7
  import type { Endpoint } from '@easydocs/core/schema'
8
- import type { Operation } from '@easydocs/core'
9
- import { OperationSchema } from '@/lib/operation-schema'
8
+ import type { Operation } from '@easydocs/core/spec/schema'
9
+ import { OperationSchema } from '@easydocs/core/spec/schema'
10
10
 
11
11
  interface Props {
12
12
  endpoint: Endpoint
@@ -32,17 +32,12 @@ function validate(raw: string): string | null {
32
32
  export function SpecEditor({ endpoint, onSaved, onCancel }: Props) {
33
33
  const activeSpec = endpoint.isManuallyEdited ? endpoint.manualSpec : endpoint.spec
34
34
  const [value, setValue] = useState(() => JSON.stringify(activeSpec, null, 2))
35
- const [validationError, setValidationError] = useState<string | null>(null)
35
+ const validationError = validate(value)
36
36
  const [saveError, setSaveError] = useState<string | null>(null)
37
37
  const [saving, setSaving] = useState(false)
38
38
 
39
- useEffect(() => {
40
- setValidationError(validate(value))
41
- }, [value])
42
-
43
39
  async function handleSave() {
44
- const err = validate(value)
45
- if (err) { setValidationError(err); return }
40
+ if (validationError) return
46
41
  setSaveError(null)
47
42
  setSaving(true)
48
43
  const parsed = JSON.parse(value) as Operation
package/src/lib/db.ts CHANGED
@@ -4,7 +4,9 @@ import {
4
4
  getEndpointsByProject,
5
5
  getAllProjects,
6
6
  findOrCreateProject,
7
+ buildFullSpec,
7
8
  } from '@easydocs/core'
9
+ export { buildFullSpec }
8
10
  import type { Endpoint, Project } from '@easydocs/core/schema'
9
11
 
10
12
  let db: ReturnType<typeof createDB> | null = null
@@ -24,45 +26,3 @@ export async function fetchEndpoints(projectSlug?: string): Promise<Endpoint[]>
24
26
  const projectId = await findOrCreateProject(db, projectSlug)
25
27
  return getEndpointsByProject(db, projectId)
26
28
  }
27
-
28
- const SECURITY_SCHEME_DEFS: Record<string, unknown> = {
29
- bearerAuth: { type: 'http', scheme: 'bearer', bearerFormat: 'JWT' },
30
- basicAuth: { type: 'http', scheme: 'basic' },
31
- apiKeyHeader: { type: 'apiKey', in: 'header', name: 'X-API-Key' },
32
- apiKeyQuery: { type: 'apiKey', in: 'query', name: 'api_key' },
33
- cookieAuth: { type: 'apiKey', in: 'cookie', name: 'session' },
34
- }
35
-
36
- export function buildFullSpec(endpointList: Endpoint[], projectName?: string) {
37
- const usedSchemes = new Set<string>()
38
- const paths: Record<string, Record<string, unknown>> = {}
39
-
40
- for (const e of endpointList) {
41
- if (!e.path || !e.method) continue
42
- const activeSpec = e.isManuallyEdited && e.manualSpec ? e.manualSpec : e.spec
43
- if (!activeSpec) continue
44
-
45
- if (!paths[e.path]) paths[e.path] = {}
46
- paths[e.path][e.method.toLowerCase()] = activeSpec
47
-
48
- if (activeSpec.security) {
49
- for (const entry of activeSpec.security) {
50
- for (const name of Object.keys(entry)) {
51
- if (SECURITY_SCHEME_DEFS[name]) usedSchemes.add(name)
52
- }
53
- }
54
- }
55
- }
56
-
57
- const securitySchemes =
58
- usedSchemes.size > 0
59
- ? Object.fromEntries([...usedSchemes].map((n) => [n, SECURITY_SCHEME_DEFS[n]]))
60
- : undefined
61
-
62
- return {
63
- openapi: '3.0.3',
64
- info: { title: projectName ?? 'API Documentation', version: '1.0.0' },
65
- paths,
66
- ...(securitySchemes ? { components: { securitySchemes } } : {}),
67
- }
68
- }
package/tsconfig.json CHANGED
@@ -1,7 +1,11 @@
1
1
  {
2
2
  "compilerOptions": {
3
3
  "target": "ES2017",
4
- "lib": ["dom", "dom.iterable", "esnext"],
4
+ "lib": [
5
+ "dom",
6
+ "dom.iterable",
7
+ "esnext"
8
+ ],
5
9
  "allowJs": true,
6
10
  "skipLibCheck": true,
7
11
  "strict": true,
@@ -11,13 +15,27 @@
11
15
  "moduleResolution": "bundler",
12
16
  "resolveJsonModule": true,
13
17
  "isolatedModules": true,
14
- "jsx": "preserve",
18
+ "jsx": "react-jsx",
15
19
  "incremental": true,
16
- "plugins": [{ "name": "next" }],
20
+ "plugins": [
21
+ {
22
+ "name": "next"
23
+ }
24
+ ],
17
25
  "paths": {
18
- "@/*": ["./src/*"]
26
+ "@/*": [
27
+ "./src/*"
28
+ ]
19
29
  }
20
30
  },
21
- "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
22
- "exclude": ["node_modules"]
31
+ "include": [
32
+ "next-env.d.ts",
33
+ "**/*.ts",
34
+ "**/*.tsx",
35
+ ".next/types/**/*.ts",
36
+ ".next/dev/types/**/*.ts"
37
+ ],
38
+ "exclude": [
39
+ "node_modules"
40
+ ]
23
41
  }
@@ -1,44 +0,0 @@
1
- import { z } from 'zod'
2
-
3
- const SchemaObject = z.record(z.any()).optional()
4
-
5
- const MediaTypeSchema = z.object({
6
- schema: SchemaObject,
7
- example: z.any().optional(),
8
- examples: z.record(z.any()).optional(),
9
- })
10
-
11
- const ParameterSchema = z.object({
12
- name: z.string(),
13
- in: z.enum(['query', 'header', 'path', 'cookie']),
14
- description: z.string().optional(),
15
- required: z.boolean().default(false),
16
- deprecated: z.boolean().optional(),
17
- schema: SchemaObject,
18
- example: z.any().optional(),
19
- })
20
-
21
- const ResponseSchema = z.object({
22
- description: z.string(),
23
- headers: z.record(z.any()).optional(),
24
- content: z.record(MediaTypeSchema).optional(),
25
- })
26
-
27
- export const OperationSchema = z.object({
28
- tags: z.array(z.string()).optional(),
29
- summary: z.string().optional(),
30
- description: z.string().optional(),
31
- operationId: z.string().optional(),
32
- parameters: z.array(ParameterSchema).optional(),
33
- requestBody: z
34
- .object({
35
- description: z.string().optional(),
36
- required: z.boolean().optional(),
37
- content: z.record(MediaTypeSchema),
38
- })
39
- .nullable()
40
- .optional(),
41
- responses: z.record(ResponseSchema).default({}),
42
- deprecated: z.boolean().optional(),
43
- security: z.array(z.record(z.array(z.string()))).optional(),
44
- })