@clidey/dory 0.23.0 → 0.27.0

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.
Files changed (37) hide show
  1. package/bin/dist/dory.d.ts +3 -0
  2. package/bin/dist/dory.d.ts.map +1 -0
  3. package/bin/dist/dory.js +375 -0
  4. package/bin/dist/dory.js.map +1 -0
  5. package/bin/dory.ts +314 -121
  6. package/dist/index.html +2 -2
  7. package/package.json +6 -4
  8. package/src/components/search.tsx +5 -5
  9. package/src/components/store.ts +1 -1
  10. package/src/mdx/card.tsx +7 -7
  11. package/src/mdx/step.tsx +6 -4
  12. package/src/plugins/docs-assets.ts +79 -0
  13. package/src/theme.scss +5 -1
  14. package/src/ui/header.tsx +1 -1
  15. package/src/ui/table-of-content.tsx +1 -1
  16. package/src/utils/colors.ts +1 -1
  17. package/src/utils/fonts.ts +1 -1
  18. package/tsconfig.app.json +2 -1
  19. package/tsconfig.bin.json +11 -7
  20. package/tsconfig.node.json +2 -1
  21. package/vite.config.ts +6 -1
  22. package/dist/api-playground-demo.mdx +0 -119
  23. package/dist/api-reference/asyncapi.json +0 -324
  24. package/dist/api-reference/openapi.json +0 -366
  25. package/dist/api-reference/operations/create.mdx +0 -5
  26. package/dist/api-reference/operations/delete.mdx +0 -5
  27. package/dist/api-reference/operations/get.mdx +0 -5
  28. package/dist/api-reference/operations/update.mdx +0 -5
  29. package/dist/api-reference/websocket-operations/receive-chat-message.mdx +0 -5
  30. package/dist/api-reference/websocket-operations/receive-notifications.mdx +0 -5
  31. package/dist/api-reference/websocket-operations/receive-presence-update.mdx +0 -5
  32. package/dist/api-reference/websocket-operations/send-chat-message.mdx +0 -5
  33. package/dist/api-reference/websocket-operations/send-presence-update.mdx +0 -5
  34. package/dist/dory.json +0 -64
  35. package/dist/features.mdx +0 -440
  36. package/dist/introduction.mdx +0 -44
  37. package/dist/websocket-playground-demo.mdx +0 -135
@@ -0,0 +1,79 @@
1
+ import type { Plugin } from 'vite';
2
+ import { cpSync, existsSync, readdirSync, statSync } from 'fs';
3
+ import { resolve, extname } from 'path';
4
+
5
+ /**
6
+ * Plugin to copy docs assets to the build output
7
+ * Since we can't use publicDir for docs (we need to import from it),
8
+ * this plugin manually copies asset files during build
9
+ */
10
+ export function docsAssetsPlugin(): Plugin {
11
+ return {
12
+ name: 'docs-assets',
13
+ apply: 'build', // Only run during build
14
+ closeBundle() {
15
+ const docsDir = resolve(process.cwd(), 'docs');
16
+ const outDir = resolve(process.cwd(), 'dist');
17
+
18
+ if (!existsSync(docsDir)) {
19
+ console.warn('[docs-assets] docs directory not found, skipping asset copy');
20
+ return;
21
+ }
22
+
23
+ // Define asset extensions to copy
24
+ const assetExtensions = new Set([
25
+ '.png', '.jpg', '.jpeg', '.gif', '.svg', '.webp', '.ico',
26
+ '.pdf', '.mp4', '.webm', '.mp3', '.wav',
27
+ '.woff', '.woff2', '.ttf', '.eot',
28
+ ]);
29
+
30
+ // Define file/folder patterns to skip
31
+ const skipPatterns = new Set([
32
+ 'dory.json',
33
+ 'node_modules',
34
+ '.DS_Store',
35
+ ]);
36
+
37
+ const shouldSkip = (name: string) => {
38
+ if (skipPatterns.has(name)) return true;
39
+ const ext = extname(name).toLowerCase();
40
+ // Skip MDX and JSON files (they're processed by Vite)
41
+ if (ext === '.mdx' || ext === '.md' || ext === '.json') return true;
42
+ return false;
43
+ };
44
+
45
+ const copyAssets = (srcDir: string, destDir: string, relativePath: string = '') => {
46
+ const items = readdirSync(srcDir);
47
+
48
+ for (const item of items) {
49
+ if (shouldSkip(item)) continue;
50
+
51
+ const srcPath = resolve(srcDir, item);
52
+ const destPath = resolve(destDir, item);
53
+ const itemRelativePath = relativePath ? `${relativePath}/${item}` : item;
54
+
55
+ try {
56
+ const stats = statSync(srcPath);
57
+
58
+ if (stats.isDirectory()) {
59
+ // Recursively copy directories
60
+ copyAssets(srcPath, destPath, itemRelativePath);
61
+ } else if (stats.isFile()) {
62
+ const ext = extname(item).toLowerCase();
63
+ // Copy if it's an asset file
64
+ if (assetExtensions.has(ext)) {
65
+ cpSync(srcPath, destPath, { force: true });
66
+ console.log(`[docs-assets] Copied ${itemRelativePath}`);
67
+ }
68
+ }
69
+ } catch (error) {
70
+ console.warn(`[docs-assets] Failed to copy ${itemRelativePath}:`, error);
71
+ }
72
+ }
73
+ };
74
+
75
+ console.log('[docs-assets] Copying assets from docs to dist...');
76
+ copyAssets(docsDir, outDir);
77
+ },
78
+ };
79
+ }
package/src/theme.scss CHANGED
@@ -21,6 +21,8 @@
21
21
  // Using light color for light mode
22
22
  --primary: var(--brand-light);
23
23
  --primary-rgb: var(--brand-light-rgb);
24
+
25
+ --ring: rgba(0, 0, 0, 0.1);
24
26
  }
25
27
 
26
28
  // Dark mode overrides
@@ -28,6 +30,8 @@
28
30
  // Use dark color for dark mode
29
31
  --primary: var(--brand-dark);
30
32
  --primary-rgb: var(--brand-dark-rgb);
33
+
34
+ --ring: rgba(255, 255, 255, 0.1);
31
35
  }
32
36
 
33
37
  article h2:first-of-type {
@@ -45,7 +49,7 @@ article img {
45
49
 
46
50
  [data-testid="header-actions"] button,
47
51
  [data-slot="dropdown-menu-content"] {
48
- border-color: rgba(0, 0, 0, 0.1);
52
+ border-color: var(--ring);
49
53
  }
50
54
 
51
55
  [data-slot="search-input-wrapper"] {
package/src/ui/header.tsx CHANGED
@@ -2,7 +2,7 @@ import classNames from 'classnames';
2
2
  import { useEffect, useMemo, useState } from 'preact/hooks';
3
3
  import { Link } from 'wouter-preact';
4
4
  import { usePathname } from 'wouter-preact/use-browser-location';
5
- import docsConfig from '../../docs/dory.json';
5
+ import docsConfig from '../../docs/dory.json' with { type: 'json' };
6
6
  import type { DoryConfig } from '../types/config';
7
7
  import { MobileSearch, Search } from '../components/search';
8
8
  import { ALL_NAVIGATION } from '../components/store';
@@ -114,7 +114,7 @@ export function TableOfContents() {
114
114
  }
115
115
 
116
116
  return (
117
- <div className="hidden xl:sticky xl:top-[4.75rem] xl:-mr-6 xl:block xl:h-[calc(100vh-4.75rem)] xl:flex-none xl:overflow-y-auto xl:py-16 xl:pr-6 pl-4">
117
+ <div className="hidden xl:sticky xl:top-[4.75rem] xl:-mr-6 xl:block xl:h-[calc(100vh-4.75rem)] xl:flex-none xl:overflow-y-auto xl:py-16 xl:pr-6 pl-8">
118
118
  <nav aria-labelledby="on-this-page-title" className="w-56">
119
119
  {sections.length > 0 && (
120
120
  <>
@@ -1,4 +1,4 @@
1
- import docsConfig from '../../docs/dory.json';
1
+ import docsConfig from '../../docs/dory.json' with { type: 'json' };
2
2
  import type { DoryConfig } from '../types/config';
3
3
 
4
4
  const config = docsConfig as DoryConfig;
@@ -1,4 +1,4 @@
1
- import docsConfig from '../../docs/dory.json';
1
+ import docsConfig from '../../docs/dory.json' with { type: 'json' };
2
2
  import type { DoryConfig } from '../types/config';
3
3
 
4
4
  const config = docsConfig as DoryConfig;
package/tsconfig.app.json CHANGED
@@ -28,5 +28,6 @@
28
28
  "noFallthroughCasesInSwitch": true,
29
29
  "noUncheckedSideEffectImports": true
30
30
  },
31
- "include": ["src"]
31
+ "include": ["src"],
32
+ "exclude": ["src/plugins"]
32
33
  }
package/tsconfig.bin.json CHANGED
@@ -4,17 +4,21 @@
4
4
  "lib": ["ES2023"],
5
5
  "module": "ESNext",
6
6
  "moduleResolution": "node",
7
- "allowImportingTsExtensions": true,
8
7
  "skipLibCheck": true,
9
- "strict": false,
8
+ "strict": true,
10
9
  "esModuleInterop": true,
11
10
  "allowSyntheticDefaultImports": true,
12
- "noEmit": true,
13
- "noImplicitAny": false,
14
- "noImplicitReturns": false,
15
- "noImplicitThis": false
11
+ "noEmit": false,
12
+ "outDir": "./bin/dist",
13
+ "rootDir": "./bin",
14
+ "declaration": true,
15
+ "declarationMap": true,
16
+ "sourceMap": true
16
17
  },
17
18
  "include": [
18
- "bin/dory.ts"
19
+ "bin/**/*.ts"
20
+ ],
21
+ "exclude": [
22
+ "bin/dist"
19
23
  ]
20
24
  }
@@ -5,6 +5,7 @@
5
5
  "lib": ["ES2023"],
6
6
  "module": "ESNext",
7
7
  "skipLibCheck": true,
8
+ "types": ["node"],
8
9
 
9
10
  /* Bundler mode */
10
11
  "moduleResolution": "bundler",
@@ -21,5 +22,5 @@
21
22
  "noFallthroughCasesInSwitch": true,
22
23
  "noUncheckedSideEffectImports": true
23
24
  },
24
- "include": ["vite.config.ts"]
25
+ "include": ["vite.config.ts", "src/plugins/**/*.ts", "bin/**/*.ts"]
25
26
  }
package/vite.config.ts CHANGED
@@ -7,6 +7,7 @@ import { llmTxtGenerator } from './src/plugins/llm-txt-generator';
7
7
  import { llmTxtDevServer } from './src/plugins/llm-txt-dev-server';
8
8
  import { frontmatterGenerator } from './src/plugins/frontmatter-generator';
9
9
  import { frontmatterDevServer } from './src/plugins/frontmatter-dev-server';
10
+ import { docsAssetsPlugin } from './src/plugins/docs-assets';
10
11
  import { getMdxConfig } from './src/config/mdx';
11
12
 
12
13
  export default defineConfig(({ command }) => ({
@@ -20,6 +21,7 @@ export default defineConfig(({ command }) => ({
20
21
  llmTxtDevServer(),
21
22
  frontmatterGenerator(),
22
23
  frontmatterDevServer(),
24
+ docsAssetsPlugin(),
23
25
  ],
24
26
  resolve: {
25
27
  alias: {
@@ -27,10 +29,13 @@ export default defineConfig(({ command }) => ({
27
29
  'react-dom': 'preact/compat'
28
30
  }
29
31
  },
30
- publicDir: "docs",
32
+ publicDir: false, // Don't use a public directory since we need to import from docs
31
33
  server: {
32
34
  allowedHosts: true,
33
35
  port: 3000,
34
36
  strictPort: false,
35
37
  },
38
+ json: {
39
+ stringify: false
40
+ },
36
41
  }));
@@ -1,119 +0,0 @@
1
- ---
2
- title: 'API Playground Demo'
3
- description: 'Interactive API playground for testing HTTP endpoints'
4
- openapi: 'POST /plants'
5
- ---
6
-
7
- # API Playground Demo
8
-
9
- This page demonstrates the new HTTP API playground that allows you to test API endpoints directly from the documentation.
10
-
11
- ## Basic GET Request
12
-
13
- Test a simple GET request with query parameters:
14
-
15
- <APIPlayground
16
- method="GET"
17
- url="/api/users"
18
- title="Get Users"
19
- description="Retrieve a list of users with optional filtering"
20
- parameters={[
21
- {
22
- name: "page",
23
- type: "number",
24
- description: "Page number for pagination",
25
- defaultValue: "1"
26
- },
27
- {
28
- name: "limit",
29
- type: "number",
30
- description: "Number of items per page",
31
- defaultValue: "10"
32
- },
33
- {
34
- name: "search",
35
- type: "string",
36
- description: "Search term to filter users"
37
- }
38
- ]}
39
- baseUrl="https://jsonplaceholder.typicode.com"
40
- />
41
-
42
- ## POST Request with Body
43
-
44
- Test a POST request with a JSON body:
45
-
46
- <APIPlayground
47
- method="POST"
48
- url="/api/users"
49
- title="Create User"
50
- description="Create a new user account"
51
- parameters={[]}
52
- body={{
53
- "name": "John Doe",
54
- "email": "john@example.com",
55
- "username": "johndoe"
56
- }}
57
- headers={{
58
- "Content-Type": "application/json"
59
- }}
60
- authType="bearer"
61
- baseUrl="https://jsonplaceholder.typicode.com"
62
- />
63
-
64
- ## Authenticated Endpoint
65
-
66
- Test an endpoint that requires authentication:
67
-
68
- <APIPlayground
69
- method="GET"
70
- url="/api/profile/{userId}"
71
- title="Get User Profile"
72
- description="Get detailed profile information for a specific user"
73
- parameters={[
74
- {
75
- name: "userId",
76
- type: "string",
77
- required: true,
78
- description: "The ID of the user to retrieve"
79
- }
80
- ]}
81
- authType="bearer"
82
- baseUrl="https://jsonplaceholder.typicode.com"
83
- />
84
-
85
- ## Features
86
-
87
- The API playground provides:
88
-
89
- - **Interactive Request Configuration**: Set parameters, headers, request body, and authentication
90
- - **Multiple Auth Types**: Support for Bearer token, API key, and Basic authentication
91
- - **Real-time Response**: See actual HTTP responses with status codes, headers, and formatted JSON
92
- - **Request Timing**: Monitor request duration for performance analysis
93
- - **Error Handling**: Clear error messages for failed requests
94
- - **Copy-Paste Ready**: Generate curl commands and code examples
95
-
96
- ## Usage in Documentation
97
-
98
- To add a playground to your API documentation, use the `APIPlayground` component:
99
-
100
- ```mdx
101
- <APIPlayground
102
- method="GET"
103
- url="/api/endpoint"
104
- title="Endpoint Title"
105
- description="Description of what this endpoint does"
106
- parameters={[
107
- {
108
- name: "param1",
109
- type: "string",
110
- required: true,
111
- description: "Parameter description"
112
- }
113
- ]}
114
- authType="bearer"
115
- baseUrl="https://api.example.com"
116
- />
117
- ```
118
-
119
- The playground seamlessly integrates with your existing API documentation and provides a Postman-like experience directly in the docs.
@@ -1,324 +0,0 @@
1
- {
2
- "asyncapi": "3.0.0",
3
- "info": {
4
- "title": "Chat WebSocket API",
5
- "version": "1.0.0",
6
- "description": "Real-time chat API using WebSocket for bidirectional communication"
7
- },
8
- "servers": {
9
- "development": {
10
- "host": "localhost:8080",
11
- "pathname": "/ws",
12
- "protocol": "ws",
13
- "description": "Development WebSocket server"
14
- },
15
- "production": {
16
- "host": "api.example.com",
17
- "pathname": "/ws",
18
- "protocol": "wss",
19
- "description": "Production WebSocket server"
20
- }
21
- },
22
- "channels": {
23
- "/chat": {
24
- "address": "/chat",
25
- "title": "Chat Channel",
26
- "description": "Channel for sending and receiving chat messages",
27
- "subscribe": {
28
- "operationId": "receiveChatMessage",
29
- "summary": "Receive chat messages",
30
- "description": "Subscribe to receive chat messages from other users",
31
- "message": {
32
- "$ref": "#/components/messages/ChatMessage"
33
- }
34
- },
35
- "publish": {
36
- "operationId": "sendChatMessage",
37
- "summary": "Send chat message",
38
- "description": "Send a chat message to other users",
39
- "message": {
40
- "$ref": "#/components/messages/ChatMessage"
41
- }
42
- }
43
- },
44
- "/notifications": {
45
- "address": "/notifications",
46
- "title": "Notifications Channel",
47
- "description": "Channel for receiving system notifications",
48
- "subscribe": {
49
- "operationId": "receiveNotification",
50
- "summary": "Receive notifications",
51
- "description": "Subscribe to receive system notifications",
52
- "message": {
53
- "$ref": "#/components/messages/Notification"
54
- }
55
- }
56
- },
57
- "/presence": {
58
- "address": "/presence",
59
- "title": "Presence Channel",
60
- "description": "Channel for user presence updates",
61
- "subscribe": {
62
- "operationId": "receivePresenceUpdate",
63
- "summary": "Receive presence updates",
64
- "description": "Subscribe to receive user presence updates",
65
- "message": {
66
- "$ref": "#/components/messages/PresenceUpdate"
67
- }
68
- },
69
- "publish": {
70
- "operationId": "sendPresenceUpdate",
71
- "summary": "Send presence update",
72
- "description": "Send a presence update",
73
- "message": {
74
- "$ref": "#/components/messages/PresenceUpdate"
75
- }
76
- }
77
- }
78
- },
79
- "components": {
80
- "messages": {
81
- "ChatMessage": {
82
- "name": "ChatMessage",
83
- "title": "Chat Message",
84
- "summary": "Message sent in a chat conversation",
85
- "description": "A message sent by a user in a chat conversation",
86
- "contentType": "application/json",
87
- "payload": {
88
- "$ref": "#/components/schemas/ChatMessagePayload"
89
- },
90
- "headers": {
91
- "$ref": "#/components/schemas/MessageHeaders"
92
- },
93
- "examples": [
94
- {
95
- "id": "msg_123",
96
- "type": "message",
97
- "content": "Hello, how are you?",
98
- "userId": "user_456",
99
- "username": "john_doe",
100
- "timestamp": "2024-01-15T10:30:00Z",
101
- "channel": "general"
102
- }
103
- ]
104
- },
105
- "Notification": {
106
- "name": "Notification",
107
- "title": "System Notification",
108
- "summary": "System-generated notification",
109
- "description": "A notification sent by the system to inform users about events",
110
- "contentType": "application/json",
111
- "payload": {
112
- "$ref": "#/components/schemas/NotificationPayload"
113
- },
114
- "headers": {
115
- "$ref": "#/components/schemas/MessageHeaders"
116
- },
117
- "examples": [
118
- {
119
- "id": "notif_789",
120
- "type": "notification",
121
- "title": "New Message",
122
- "message": "You have a new message from Alice",
123
- "level": "info",
124
- "timestamp": "2024-01-15T10:35:00Z",
125
- "userId": "user_456"
126
- }
127
- ]
128
- },
129
- "PresenceUpdate": {
130
- "name": "PresenceUpdate",
131
- "title": "Presence Update",
132
- "summary": "User presence status update",
133
- "description": "Update about a user's presence status (online, offline, away)",
134
- "contentType": "application/json",
135
- "payload": {
136
- "$ref": "#/components/schemas/PresenceUpdatePayload"
137
- },
138
- "headers": {
139
- "$ref": "#/components/schemas/MessageHeaders"
140
- },
141
- "examples": [
142
- {
143
- "id": "presence_101",
144
- "type": "presence",
145
- "userId": "user_456",
146
- "username": "john_doe",
147
- "status": "online",
148
- "lastSeen": "2024-01-15T10:40:00Z",
149
- "timestamp": "2024-01-15T10:40:00Z"
150
- }
151
- ]
152
- }
153
- },
154
- "schemas": {
155
- "ChatMessagePayload": {
156
- "type": "object",
157
- "required": ["id", "type", "content", "userId", "username", "timestamp"],
158
- "properties": {
159
- "id": {
160
- "type": "string",
161
- "description": "Unique identifier for the message",
162
- "example": "msg_123"
163
- },
164
- "type": {
165
- "type": "string",
166
- "enum": ["message"],
167
- "description": "Message type identifier",
168
- "example": "message"
169
- },
170
- "content": {
171
- "type": "string",
172
- "description": "The message content",
173
- "example": "Hello, how are you?"
174
- },
175
- "userId": {
176
- "type": "string",
177
- "description": "ID of the user who sent the message",
178
- "example": "user_456"
179
- },
180
- "username": {
181
- "type": "string",
182
- "description": "Username of the sender",
183
- "example": "john_doe"
184
- },
185
- "timestamp": {
186
- "type": "string",
187
- "format": "date-time",
188
- "description": "When the message was sent",
189
- "example": "2024-01-15T10:30:00Z"
190
- },
191
- "channel": {
192
- "type": "string",
193
- "description": "Channel where the message was sent",
194
- "example": "general"
195
- },
196
- "replyTo": {
197
- "type": "string",
198
- "description": "ID of the message this is replying to",
199
- "example": "msg_122"
200
- }
201
- }
202
- },
203
- "NotificationPayload": {
204
- "type": "object",
205
- "required": ["id", "type", "title", "message", "timestamp"],
206
- "properties": {
207
- "id": {
208
- "type": "string",
209
- "description": "Unique identifier for the notification",
210
- "example": "notif_789"
211
- },
212
- "type": {
213
- "type": "string",
214
- "enum": ["notification"],
215
- "description": "Message type identifier",
216
- "example": "notification"
217
- },
218
- "title": {
219
- "type": "string",
220
- "description": "Notification title",
221
- "example": "New Message"
222
- },
223
- "message": {
224
- "type": "string",
225
- "description": "Notification message content",
226
- "example": "You have a new message from Alice"
227
- },
228
- "level": {
229
- "type": "string",
230
- "enum": ["info", "warning", "error", "success"],
231
- "description": "Notification level",
232
- "example": "info"
233
- },
234
- "timestamp": {
235
- "type": "string",
236
- "format": "date-time",
237
- "description": "When the notification was created",
238
- "example": "2024-01-15T10:35:00Z"
239
- },
240
- "userId": {
241
- "type": "string",
242
- "description": "ID of the user receiving the notification",
243
- "example": "user_456"
244
- },
245
- "actionUrl": {
246
- "type": "string",
247
- "description": "URL to navigate to when notification is clicked",
248
- "example": "/chat/general"
249
- }
250
- }
251
- },
252
- "PresenceUpdatePayload": {
253
- "type": "object",
254
- "required": ["id", "type", "userId", "username", "status", "timestamp"],
255
- "properties": {
256
- "id": {
257
- "type": "string",
258
- "description": "Unique identifier for the presence update",
259
- "example": "presence_101"
260
- },
261
- "type": {
262
- "type": "string",
263
- "enum": ["presence"],
264
- "description": "Message type identifier",
265
- "example": "presence"
266
- },
267
- "userId": {
268
- "type": "string",
269
- "description": "ID of the user whose presence is being updated",
270
- "example": "user_456"
271
- },
272
- "username": {
273
- "type": "string",
274
- "description": "Username of the user",
275
- "example": "john_doe"
276
- },
277
- "status": {
278
- "type": "string",
279
- "enum": ["online", "offline", "away", "busy"],
280
- "description": "User's presence status",
281
- "example": "online"
282
- },
283
- "lastSeen": {
284
- "type": "string",
285
- "format": "date-time",
286
- "description": "When the user was last seen",
287
- "example": "2024-01-15T10:40:00Z"
288
- },
289
- "timestamp": {
290
- "type": "string",
291
- "format": "date-time",
292
- "description": "When the presence update was sent",
293
- "example": "2024-01-15T10:40:00Z"
294
- }
295
- }
296
- },
297
- "MessageHeaders": {
298
- "type": "object",
299
- "properties": {
300
- "correlation-id": {
301
- "type": "string",
302
- "description": "Correlation ID for request tracking",
303
- "example": "corr_123"
304
- },
305
- "user-id": {
306
- "type": "string",
307
- "description": "ID of the user sending the message",
308
- "example": "user_456"
309
- },
310
- "session-id": {
311
- "type": "string",
312
- "description": "Session ID for the connection",
313
- "example": "sess_789"
314
- },
315
- "client-version": {
316
- "type": "string",
317
- "description": "Version of the client application",
318
- "example": "1.0.0"
319
- }
320
- }
321
- }
322
- }
323
- }
324
- }