zuplo 6.70.68 → 6.70.70

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 (50) hide show
  1. package/docs/ai-gateway/getting-started.mdx +12 -8
  2. package/docs/ai-gateway/introduction.mdx +11 -9
  3. package/docs/articles/api-key-buckets.mdx +4 -2
  4. package/docs/articles/archiving-requests-to-storage.mdx +4 -4
  5. package/docs/articles/branch-based-deployments.mdx +10 -8
  6. package/docs/articles/ci-cd-github/cleanup-on-branch-delete.mdx +52 -31
  7. package/docs/articles/ci-cd-github/pr-preview-environments.mdx +17 -6
  8. package/docs/articles/custom-ci-cd-azure.mdx +1 -1
  9. package/docs/articles/custom-ci-cd-bitbucket.mdx +1 -1
  10. package/docs/articles/custom-ci-cd-circleci.mdx +1 -1
  11. package/docs/articles/custom-ci-cd-github.mdx +1 -1
  12. package/docs/articles/custom-ci-cd-gitlab.mdx +1 -1
  13. package/docs/articles/graphql.mdx +276 -0
  14. package/docs/articles/monorepo-deployment.mdx +17 -3
  15. package/docs/articles/opentelemetry.mdx +5 -2
  16. package/docs/articles/per-user-rate-limits-using-db.mdx +5 -6
  17. package/docs/articles/securing-the-gateway-with-client-mtls.mdx +68 -43
  18. package/docs/articles/step-1-setup-basic-gateway.mdx +1 -3
  19. package/docs/articles/step-2-add-rate-limiting.mdx +1 -1
  20. package/docs/articles/testing.mdx +1 -1
  21. package/docs/articles/troubleshooting.md +7 -3
  22. package/docs/articles/waf-ddos-akamai.md +35 -16
  23. package/docs/articles/waf-ddos-aws-waf-shield.mdx +35 -16
  24. package/docs/articles/waf-ddos-fastly.mdx +10 -7
  25. package/docs/cli/deploy.mdx +13 -10
  26. package/docs/cli/deploy.partial.mdx +13 -10
  27. package/docs/dev-portal/zudoku/components/sidecar-box.mdx +131 -0
  28. package/docs/dev-portal/zudoku/configuration/api-catalog.md +62 -42
  29. package/docs/dev-portal/zudoku/configuration/api-reference.md +5 -4
  30. package/docs/dev-portal/zudoku/configuration/navigation.mdx +70 -7
  31. package/docs/guides/canary-routing-for-employees.mdx +103 -39
  32. package/docs/guides/modify-openapi-paths.mdx +3 -3
  33. package/docs/handlers/legacy-dev-portal-handler.mdx +1 -1
  34. package/docs/handlers/mcp-server.mdx +13 -11
  35. package/docs/handlers/url-forward.mdx +5 -1
  36. package/docs/handlers/url-rewrite.mdx +7 -2
  37. package/docs/handlers/websocket-handler.mdx +5 -1
  38. package/docs/mcp-gateway/observability/logging.mdx +19 -12
  39. package/docs/mcp-server/resources.mdx +27 -15
  40. package/docs/mcp-server/testing.mdx +0 -2
  41. package/docs/policies/archive-request-azure-storage-inbound/doc.md +1 -1
  42. package/docs/policies/archive-response-azure-storage-outbound/doc.md +1 -1
  43. package/docs/policies/ip-restriction-inbound/policy.ts +1 -1
  44. package/docs/programmable-api/http-problems.mdx +0 -18
  45. package/docs/programmable-api/jwt-service-plugin.mdx +131 -109
  46. package/docs/programmable-api/runtime-behaviors.mdx +4 -2
  47. package/docs/programmable-api/streaming-zone-cache.mdx +4 -6
  48. package/docs/programmable-api/web-crypto-apis.mdx +10 -6
  49. package/package.json +4 -4
  50. package/docs/errors/get-head-body-error.mdx +0 -41
@@ -0,0 +1,131 @@
1
+ ---
2
+ title: Sidecar Box
3
+ sidebar_icon: panel-right
4
+ ---
5
+
6
+ import * as SidecarBox from "zudoku/ui/SidecarBox";
7
+ import { SyntaxHighlight } from "zudoku/ui/SyntaxHighlight";
8
+ import { Badge } from "zudoku/ui/Badge";
9
+
10
+ A framed panel with an optional head, body, and footer. The OpenAPI plugin builds its sidecar with
11
+ it (the request body, response, and example boxes), so reaching for it in custom plugin pages or MDX
12
+ gives you content that matches that look.
13
+
14
+ ## Import
15
+
16
+ ```tsx
17
+ import * as SidecarBox from "zudoku/ui/SidecarBox";
18
+ import { SyntaxHighlight } from "zudoku/ui/SyntaxHighlight";
19
+ ```
20
+
21
+ ## Components
22
+
23
+ - `SidecarBox.Root` - The outer framed container
24
+ - `SidecarBox.Head` - Header row, typically a title or controls
25
+ - `SidecarBox.Body` - Main content area with its own inner border
26
+ - `SidecarBox.Footer` - Footer row for notes or actions
27
+
28
+ `Head`, `Body`, and `Footer` are all optional. Use just `Root` and `Body` for a plain framed panel.
29
+
30
+ ## With a status badge
31
+
32
+ The head is a plain flex row, so `justify-between` aligns a title on the left and a status badge (or
33
+ any control) on the right, above an embedded code body.
34
+
35
+ <SidecarBox.Root className="not-prose max-w-sm">
36
+ <SidecarBox.Head className="text-xs flex justify-between items-center">
37
+ <span className="font-medium">GET /users/{`{id}`}</span>
38
+ <Badge variant="muted">200</Badge>
39
+ </SidecarBox.Head>
40
+ <SidecarBox.Body className="p-0">
41
+ <SyntaxHighlight
42
+ embedded
43
+ language="bash"
44
+ className="rounded-none text-xs"
45
+ code={`curl https://api.example.com/users/usr_123 \\
46
+ -H "Authorization: Bearer $TOKEN"`}
47
+ />
48
+ </SidecarBox.Body>
49
+ </SidecarBox.Root>
50
+
51
+ ```tsx
52
+ <SidecarBox.Root>
53
+ <SidecarBox.Head className="text-xs flex justify-between items-center">
54
+ <span className="font-medium">GET /users/{id}</span>
55
+ <Badge variant="muted">200</Badge>
56
+ </SidecarBox.Head>
57
+ <SidecarBox.Body className="p-0">
58
+ <SyntaxHighlight embedded language="bash" className="rounded-none text-xs" code={curlExample} />
59
+ </SidecarBox.Body>
60
+ </SidecarBox.Root>
61
+ ```
62
+
63
+ ## Anatomy
64
+
65
+ All four parts together. The head and footer sit flush against the framed body in the middle.
66
+
67
+ <SidecarBox.Root className="not-prose max-w-sm">
68
+ <SidecarBox.Head className="font-medium">Response</SidecarBox.Head>
69
+ <SidecarBox.Body className="p-3">A 200 response returns the user object.</SidecarBox.Body>
70
+ <SidecarBox.Footer className="text-muted-foreground text-xs">application/json</SidecarBox.Footer>
71
+ </SidecarBox.Root>
72
+
73
+ ```tsx
74
+ <SidecarBox.Root>
75
+ <SidecarBox.Head className="font-medium">Response</SidecarBox.Head>
76
+ <SidecarBox.Body className="p-3">A 200 response returns the user object.</SidecarBox.Body>
77
+ <SidecarBox.Footer className="text-muted-foreground text-xs">application/json</SidecarBox.Footer>
78
+ </SidecarBox.Root>
79
+ ```
80
+
81
+ ## With a code block
82
+
83
+ For code or JSON, drop the body padding with `className="p-0"` and let an embedded `SyntaxHighlight`
84
+ own the spacing. This is the pattern the OpenAPI plugin uses for its example boxes.
85
+
86
+ <SidecarBox.Root className="not-prose max-w-sm">
87
+ <SidecarBox.Head className="text-xs font-medium">Example response</SidecarBox.Head>
88
+ <SidecarBox.Body className="p-0">
89
+ <SyntaxHighlight
90
+ embedded
91
+ language="json"
92
+ className="rounded-none text-xs"
93
+ code={`{
94
+ "id": "usr_123",
95
+ "name": "Ada Lovelace",
96
+ "active": true
97
+ }`}
98
+ />
99
+ </SidecarBox.Body>
100
+ <SidecarBox.Footer className="text-muted-foreground text-xs">200 OK</SidecarBox.Footer>
101
+ </SidecarBox.Root>
102
+
103
+ ```tsx
104
+ <SidecarBox.Root>
105
+ <SidecarBox.Head className="text-xs font-medium">Example response</SidecarBox.Head>
106
+ <SidecarBox.Body className="p-0">
107
+ <SyntaxHighlight
108
+ embedded
109
+ language="json"
110
+ className="rounded-none text-xs"
111
+ code={`{
112
+ "id": "usr_123",
113
+ "name": "Ada Lovelace",
114
+ "active": true
115
+ }`}
116
+ />
117
+ </SidecarBox.Body>
118
+ <SidecarBox.Footer className="text-muted-foreground text-xs">200 OK</SidecarBox.Footer>
119
+ </SidecarBox.Root>
120
+ ```
121
+
122
+ ## Props
123
+
124
+ Each part accepts `children` and an optional `className` to extend or override its styling.
125
+
126
+ | Component | Description |
127
+ | ------------------- | ------------------------------------------------------------------ |
128
+ | `SidecarBox.Root` | Outer frame. Sets the rounded border, background, and shadow. |
129
+ | `SidecarBox.Head` | Top row. A flex container, so layout utilities apply directly. |
130
+ | `SidecarBox.Body` | Content area with its own inner border. Use `p-0` for code blocks. |
131
+ | `SidecarBox.Footer` | Bottom row for notes or actions. |
@@ -8,9 +8,9 @@ creates an overview of all your APIs and lets you organize them into categories
8
8
 
9
9
  ## Enable API Catalog
10
10
 
11
- The first step to enable the API Catalog, you need to add a `catalogs` object to your Dev Portal configuration file.
11
+ To enable the API Catalog, add a `catalogs` object to your Dev Portal configuration file.
12
12
 
13
- ```js title=zudoku.config.ts
13
+ ```ts title=zudoku.config.ts
14
14
  const config = {
15
15
  // ...
16
16
  catalogs: {
@@ -24,85 +24,105 @@ const config = {
24
24
  You can then add your APIs to the catalog by adding the `categories` property to your API
25
25
  configuration.
26
26
 
27
- ```js title=zudoku.config.ts
27
+ :::caution{title="Recommendation: nest API paths under the catalog path"}
28
+
29
+ For a consistent user experience, APIs that appear in the catalog should have their `path` prefixed
30
+ with the catalog path. For example, if your catalog is at `/catalog`, an API path should start with
31
+ `/catalog/` (e.g., `/catalog/api-users`). APIs with paths outside the catalog path still appear in
32
+ the catalog, but clicking them navigates the user outside the catalog section.
33
+
34
+ :::
35
+
36
+ ```ts title=zudoku.config.ts
28
37
  const config = {
29
- // ...
38
+ catalogs: {
39
+ path: "/catalog",
40
+ label: "API Catalog",
41
+ },
30
42
  apis: [
31
- // ...
32
43
  {
33
44
  type: "file",
34
45
  input: "./operational.json",
35
- path: "/api-operational",
46
+ path: "/catalog/api-operational", // Must be under /catalog/
36
47
  categories: [{ label: "General", tags: ["Operational"] }],
37
48
  },
38
49
  {
39
50
  type: "file",
40
51
  input: "./enduser.json",
41
- path: "/api-enduser",
52
+ path: "/catalog/api-enduser", // Must be under /catalog/
42
53
  categories: [{ label: "General", tags: ["End-User"] }],
43
54
  },
44
55
  {
45
56
  type: "file",
46
57
  input: "./openapi.json",
47
- path: "/api-auth",
58
+ path: "/catalog/api-auth", // Must be under /catalog/
48
59
  categories: [{ label: "Other", tags: ["Authentication"] }],
49
60
  },
50
- // ...
51
61
  ],
52
- // ...
53
62
  };
54
63
  ```
55
64
 
56
- ## Advanced Configuration
57
-
58
- ### Select APIs to show in the catalog
59
-
60
- You can select which APIs are shown in the catalog by using the `items` property. The `items`
61
- property is an array of navigation IDs of the APIs you want to show in the catalog.
65
+ To add the catalog to your navigation, use a link item:
62
66
 
63
- ```js title=zudoku.config.ts
67
+ ```ts title=zudoku.config.ts
64
68
  const config = {
65
- // ...
66
- catalogs: {
67
- path: "/catalog",
68
- label: "API Catalog",
69
- // Only show the operational API in the catalog
70
- items: ["api-operational"],
71
- },
72
- apis: [
73
- // ...
69
+ navigation: [
74
70
  {
75
- type: "file",
76
- input: "./operational.json",
77
- path: "/api-operational",
78
- categories: [{ label: "General", tags: ["Operational"] }],
79
- },
80
- {
81
- type: "file",
82
- input: "./enduser.json",
83
- path: "/api-enduser",
84
- categories: [{ label: "General", tags: ["End-User"] }],
71
+ type: "link",
72
+ label: "API Catalog",
73
+ to: "/catalog",
74
+ icon: "square-library",
85
75
  },
86
76
  ],
87
- // ...
77
+ // ... catalogs and apis config
88
78
  };
89
79
  ```
90
80
 
81
+ ## Advanced Configuration
82
+
91
83
  ### Filtering catalog items
92
84
 
93
85
  You can filter which APIs are shown in the catalog by using the `filterItems` property. The function
94
- receives the items and context as arguments.
86
+ receives the items and the catalog context (including `auth`) as arguments. Each item has a
87
+ `categories` array where each category has a `label` and `tags`.
95
88
 
96
- ```js title=zudoku.config.ts
89
+ ```ts title=zudoku.config.ts
97
90
  const config = {
98
- // ...
99
91
  catalogs: {
100
92
  path: "/catalog",
101
93
  label: "API Catalog",
102
94
  filterItems: (items, { auth }) => {
103
- return items.filter((item) => item.tags.includes("public"));
95
+ return items.filter((item) =>
96
+ item.categories?.some((category) => category.tags?.includes("public")),
97
+ );
104
98
  },
105
99
  },
106
- // ...
107
100
  };
108
101
  ```
102
+
103
+ ## Standalone APIs (without catalog)
104
+
105
+ APIs that are **not** part of a catalog can use any path and will appear as standalone API reference
106
+ pages. These APIs don't need `categories` and their paths don't need to be nested under a catalog.
107
+
108
+ ```ts title=zudoku.config.ts
109
+ const config = {
110
+ apis: [
111
+ {
112
+ type: "file",
113
+ input: "./openapi.json",
114
+ path: "/api", // standalone, not under a catalog
115
+ },
116
+ ],
117
+ navigation: [
118
+ {
119
+ type: "link",
120
+ label: "API Reference",
121
+ to: "/api",
122
+ },
123
+ ],
124
+ };
125
+ ```
126
+
127
+ See the [API Reference](/dev-portal/zudoku/configuration/api-reference) page for full details on configuring
128
+ individual APIs, including versioning and customization options.
@@ -209,7 +209,7 @@ const config = {
209
209
  disableSecurity: true, // Disable security scheme display and playground auth (default)
210
210
  showVersionSelect: "if-available", // Control version selector visibility
211
211
  expandAllTags: true, // Control initial expanded state of tag categories
212
- showInfoPage: true, // Show API information page as the index route
212
+ showInfoPage: true, // Always show the info page (unset = show only if a description is set)
213
213
  schemaDownload: {
214
214
  enabled: true, // Enable schema download button
215
215
  fileName: "schema", // Set name of the schema file when downloaded
@@ -234,8 +234,9 @@ Available options:
234
234
  - `"always"`: Always show version selector (disabled if only one version)
235
235
  - `"hide"`: Never show version selector
236
236
  - `expandAllTags`: Control initial expanded state of tag categories (default: `true`)
237
- - `showInfoPage`: Show the API information page as the index route (default: `true`). When disabled,
238
- navigating to the API root redirects to the first tag instead
237
+ - `showInfoPage`: Control the API information page shown as the index route. Set to `true` to always
238
+ show it, or `false` to always redirect the API root to the first tag. When unset, the page is
239
+ shown only if the API has a description, otherwise the API root redirects to the first tag
239
240
  - `schemaDownload`: Enable schema download functionality. When enabled, displays a button allowing
240
241
  users to download the OpenAPI schema, copy it to clipboard, or open in a new tab.
241
242
  - `enabled`: Enable or disable the schema download button
@@ -261,7 +262,7 @@ const config = {
261
262
  disableSecurity: true, // Disable security scheme display and playground auth (default)
262
263
  showVersionSelect: "if-available", // Control version selector visibility
263
264
  expandAllTags: false, // Control initial expanded state of tag categories
264
- showInfoPage: true, // Show API information page as the index route
265
+ showInfoPage: true, // Always show the info page (unset = show only if a description is set)
265
266
  schemaDownload: {
266
267
  enabled: true, // Enable schema download button
267
268
  fileName: "schema", // Set name of the schema file when downloaded
@@ -93,6 +93,7 @@ type NavigationLink = {
93
93
  label: string;
94
94
  icon?: string; // Lucide icon name
95
95
  target?: "_self" | "_blank";
96
+ stack?: boolean; // open the destination as a stacked sub-nav
96
97
  badge?: {
97
98
  label: string;
98
99
  color: "green" | "blue" | "yellow" | "red" | "purple" | "indigo" | "gray" | "outline";
@@ -141,6 +142,7 @@ type NavigationCategory = {
141
142
  label: string;
142
143
  collapsible?: boolean;
143
144
  collapsed?: boolean;
145
+ stack?: boolean; // open the category's items as a stacked sub-nav
144
146
  link?: string | { type: "doc"; file: string; label?: string; path?: string };
145
147
  display?:
146
148
  | "auth"
@@ -460,6 +462,67 @@ type NavigationFilter = {
460
462
 
461
463
  </details>
462
464
 
465
+ ## Stacked navigation
466
+
467
+ By default a category expands inline when clicked. Set `stack: true` and it opens as a full panel
468
+ that slides in over the current menu, with a **Back** button to return. Use it for deep sections
469
+ that would otherwise crowd the sidebar.
470
+
471
+ `stack` works on categories and links. The panel content comes from the item itself:
472
+
473
+ - A **category** with `stack: true` shows its own `items`.
474
+ - A **link** with `stack: true` opens the navigation at its destination, such as the sidebar a
475
+ plugin generates at that path.
476
+
477
+ ```tsx title="Stack a category's items"
478
+ {
479
+ type: "category",
480
+ label: "Shipping Guides",
481
+ stack: true,
482
+ items: ["guides/interstellar", "guides/intergalactic"],
483
+ }
484
+ ```
485
+
486
+ ```tsx title="Stack a linked section (e.g. a GraphQL plugin)"
487
+ {
488
+ type: "link",
489
+ label: "Developer API",
490
+ to: "/graphql/dev",
491
+ stack: true,
492
+ }
493
+ ```
494
+
495
+ The **Back** button points to the section the stacked item belongs to (for example "Back to Our
496
+ APIs"), so the page still works when someone opens it directly from a search result or a shared
497
+ link.
498
+
499
+ :::note
500
+
501
+ A stacked link drills into wherever its `to` points, so the destination should be a section with its
502
+ own navigation, such as a plugin route or a category landing page. The slide animation respects the
503
+ user's reduced-motion setting and falls back to an instant swap.
504
+
505
+ :::
506
+
507
+ ### Stacking generated navigation
508
+
509
+ Plugin-generated sidebars (e.g. OpenAPI) can be stacked too, with a
510
+ [navigation rule](#navigation-rules). This is useful for large APIs: instead of one long scroll,
511
+ make each tag drill into its own panel.
512
+
513
+ ```tsx title="Stack an OpenAPI tag"
514
+ navigationRules: [
515
+ {
516
+ type: "modify",
517
+ match: "Shipments/Shipment/Shipment Management",
518
+ set: { stack: true },
519
+ },
520
+ ],
521
+ ```
522
+
523
+ The `match` targets a generated category by label (here, the `Shipment Management` tag under the
524
+ `Shipments` API). See [Navigation Rules](#navigation-rules) for the matching syntax.
525
+
463
526
  ## Display Control
464
527
 
465
528
  All navigation items support a `display` property that controls when the item should be visible:
@@ -671,13 +734,13 @@ For a practical walkthrough with more examples, see the
671
734
 
672
735
  Each rule has a `type` and a `match` property that targets a navigation item.
673
736
 
674
- | Type | Description |
675
- | -------- | ------------------------------------------------------------------------- |
676
- | `insert` | Add items `before` or `after` a matched item |
677
- | `modify` | Change `label`, `icon`, `badge`, `collapsed`, `collapsible`, or `display` |
678
- | `remove` | Remove a matched item from the sidebar |
679
- | `sort` | Sort children of a matched category using a custom comparator |
680
- | `move` | Relocate a matched item `before` or `after` another item |
737
+ | Type | Description |
738
+ | -------- | ---------------------------------------------------------------------------------- |
739
+ | `insert` | Add items `before` or `after` a matched item |
740
+ | `modify` | Change `label`, `icon`, `badge`, `collapsed`, `collapsible`, `display`, or `stack` |
741
+ | `remove` | Remove a matched item from the sidebar |
742
+ | `sort` | Sort children of a matched category using a custom comparator |
743
+ | `move` | Relocate a matched item `before` or `after` another item |
681
744
 
682
745
  ### Match Syntax
683
746