diff --git a/.tool-versions b/.tool-versions index ec76e1a7..b8867a43 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1 +1 @@ -nodejs 22.13.1 \ No newline at end of file +nodejs 22.13.1 diff --git a/docs/articles/cloudflare-settings.md b/docs/articles/cloudflare-settings.md index 93db2438..9ce7a61b 100644 --- a/docs/articles/cloudflare-settings.md +++ b/docs/articles/cloudflare-settings.md @@ -3,11 +3,11 @@ title: Zuplo and Cloudflare Settings sidebar_label: Cloudflare Settings --- -Most fully managed Zuplo environemnts are deployed behind Cloudflare's Web Application -Firewall, DDoS protection, Bot Detection, and SSL termination. The combination -of Cloudflare's network infrastructure and Zuplo's API Gateway help provide -critical security and performance capabilities to your API all with zero custom -configuration. +Zuplo environments are mostly deployed behind Cloudflare's Web +Application Firewall, DDoS protection, Bot Detection, and SSL termination. The +combination of Cloudflare's network infrastructure and Zuplo's API Gateway help +provide critical security and performance capabilities to your API all with zero +custom configuration. ## Web Application Firewall Rules diff --git a/docs/articles/dev-portal-setup.md b/docs/articles/dev-portal-setup.md index 9a508b80..4a47e7cd 100644 --- a/docs/articles/dev-portal-setup.md +++ b/docs/articles/dev-portal-setup.md @@ -39,6 +39,10 @@ my-project/ - **docs/dev-portal.json** - This is the primary configuration for your developer portal with customization for the favicon, authentication settings, etc. [Documentation](./dev-portal-json.md) +- **ZUPLO_LOG_LEVEL** - This environment variable configures the log level in + your Zuplo portal to control which logs display. To show only errors or + warnings, set ZUPLO_LOG_LEVEL to error or warn in the Settings tab under the + Environment Variables section. :::caution diff --git a/docs/articles/log-plugin-azure-blob.md b/docs/articles/log-plugin-azure-blob.md index 9904c7c9..45b2f6e6 100644 --- a/docs/articles/log-plugin-azure-blob.md +++ b/docs/articles/log-plugin-azure-blob.md @@ -17,7 +17,6 @@ The plugin is configured in the [Runtime Extensions](./runtime-extensions.md) file `zuplo.runtime.ts`: ```ts - // The interface that describes the rows // in the output interface AzureBlobLogEntry { @@ -31,7 +30,11 @@ interface AzureBlobLogEntry { } // The function that creates an entry -async function generateLogEntry(response: Response, request: ZuploRequest, context: ZuploContext) { +async function generateLogEntry( + response: Response, + request: ZuploRequest, + context: ZuploContext, +) { const entry: AzureBlobLogEntry = { timestamp: new Date().toISOString(), url: request.url, @@ -39,7 +42,7 @@ async function generateLogEntry(response: Response, request: ZuploRequest, conte status: response.status, statusText: response.statusText, sub: request.user?.sub ?? null, - contentLength: request.headers.get("content-length") + contentLength: request.headers.get("content-length"), }; return entry; } @@ -47,12 +50,12 @@ async function generateLogEntry(response: Response, request: ZuploRequest, conte // Add the plugin - use a SAS URL runtime.addPlugin( new AzureBlobPlugin({ - sasUrl: "https://YOUR_ACCOUNT.blob.core.windows.net/YOUR_CONTAINER?sv=2022-11-02&ss=b&srt=co&sp=wactfx&se=2045-11-17T13:50:53Z&st=2024-11-17T05:50:53Z&spr=https&sig=YOUR_SIG", + sasUrl: + "https://YOUR_ACCOUNT.blob.core.windows.net/YOUR_CONTAINER?sv=2022-11-02&ss=b&srt=co&sp=wactfx&se=2045-11-17T13:50:53Z&st=2024-11-17T05:50:53Z&spr=https&sig=YOUR_SIG", batchPeriodSeconds: 1, generateLogEntry, - }) + }), ); - ``` The plugin writes Block Blobs using SAS signatures. Ensure that your SAS URL has diff --git a/docs/articles/rick-and-morty-api-developer-portal-example.md b/docs/articles/rick-and-morty-api-developer-portal-example.md index ce7a71cc..33e78dea 100644 --- a/docs/articles/rick-and-morty-api-developer-portal-example.md +++ b/docs/articles/rick-and-morty-api-developer-portal-example.md @@ -9,7 +9,8 @@ gateway configuration. for the Rick and Morty API. The Rick and Morty API is a REST(ish) API based on the television show Rick and Morty. It provides access to hundreds of characters, images, locations and episodes. The Rick and Morty API is filled with canonical information as seen on -the TV show. Full credit to the original and upstream API, which is available at rickandmortyapi.com. +the TV show. Full credit to the original and upstream API, which is available at +rickandmortyapi.com. > "I'm A Scientist; Because I Invent, Transform, Create, And Destroy For A > Living, And When I Don't Like Something About The World, I Change It." diff --git a/public/styles/diagrams.css b/public/styles/diagrams.css index 39bfffe2..4c3e4e1b 100644 --- a/public/styles/diagrams.css +++ b/public/styles/diagrams.css @@ -24,7 +24,10 @@ --xy-background-pattern-dots-color-default: #91919a; --xy-background-pattern-lines-color-default: #eee; --xy-background-pattern-cross-color-default: #e2e2e2; - background-color: var(--xy-background-color, var(--xy-background-color-default)); + background-color: var( + --xy-background-color, + var(--xy-background-color-default) + ); --xy-node-color-default: inherit; --xy-node-border-default: 1px solid #1a192b; --xy-node-background-color-default: #fff; @@ -96,7 +99,10 @@ --xy-edge-label-color-default: #f8f8f8; } .react-flow__background { - background-color: var(--xy-background-color, var(--xy-background-color-props, var(--xy-background-color-default))); + background-color: var( + --xy-background-color, + var(--xy-background-color-props, var(--xy-background-color-default)) + ); pointer-events: none; z-index: -1; } @@ -111,14 +117,14 @@ z-index: 1; } .react-flow__pane.draggable { - cursor: grab; - } + cursor: grab; +} .react-flow__pane.dragging { - cursor: grabbing; - } + cursor: grabbing; +} .react-flow__pane.selection { - cursor: pointer; - } + cursor: pointer; +} .react-flow__viewport { transform-origin: 0 0; z-index: 2; @@ -136,65 +142,77 @@ } .react-flow__edge-path { stroke: var(--xy-edge-stroke, var(--xy-edge-stroke-default)); - stroke-width: var(--xy-edge-stroke-width, var(--xy-edge-stroke-width-default)); + stroke-width: var( + --xy-edge-stroke-width, + var(--xy-edge-stroke-width-default) + ); fill: none; } .react-flow__connection-path { - stroke: var(--xy-connectionline-stroke, var(--xy-connectionline-stroke-default)); - stroke-width: var(--xy-connectionline-stroke-width, var(--xy-connectionline-stroke-width-default)); + stroke: var( + --xy-connectionline-stroke, + var(--xy-connectionline-stroke-default) + ); + stroke-width: var( + --xy-connectionline-stroke-width, + var(--xy-connectionline-stroke-width-default) + ); fill: none; } .react-flow .react-flow__edges { position: absolute; } .react-flow .react-flow__edges svg { - overflow: visible; - position: absolute; - pointer-events: none; - } + overflow: visible; + position: absolute; + pointer-events: none; +} .react-flow__edge { pointer-events: visibleStroke; } .react-flow__edge.selectable { - cursor: pointer; - } + cursor: pointer; +} .react-flow__edge.animated path { - stroke-dasharray: 5; - animation: dashdraw 0.5s linear infinite; - } + stroke-dasharray: 5; + animation: dashdraw 0.5s linear infinite; +} .react-flow__edge.animated path.react-flow__edge-interaction { - stroke-dasharray: none; - animation: none; - } + stroke-dasharray: none; + animation: none; +} .react-flow__edge.inactive { - pointer-events: none; - } + pointer-events: none; +} .react-flow__edge.selected, - .react-flow__edge:focus, - .react-flow__edge:focus-visible { - outline: none; - } +.react-flow__edge:focus, +.react-flow__edge:focus-visible { + outline: none; +} .react-flow__edge.selected .react-flow__edge-path, - .react-flow__edge.selectable:focus .react-flow__edge-path, - .react-flow__edge.selectable:focus-visible .react-flow__edge-path { - stroke: var(--xy-edge-stroke-selected, var(--xy-edge-stroke-selected-default)); - } +.react-flow__edge.selectable:focus .react-flow__edge-path, +.react-flow__edge.selectable:focus-visible .react-flow__edge-path { + stroke: var( + --xy-edge-stroke-selected, + var(--xy-edge-stroke-selected-default) + ); +} .react-flow__edge-textwrapper { - pointer-events: all; - } + pointer-events: all; +} .react-flow__edge .react-flow__edge-text { - pointer-events: none; - -webkit-user-select: none; - -moz-user-select: none; - user-select: none; - } + pointer-events: none; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; +} .react-flow__connection { pointer-events: none; } .react-flow__connection .animated { - stroke-dasharray: 5; - animation: dashdraw 0.5s linear infinite; - } + stroke-dasharray: 5; + animation: dashdraw 0.5s linear infinite; +} svg.react-flow__connectionline { z-index: 1001; overflow: visible; @@ -207,33 +225,33 @@ svg.react-flow__connectionline { .react-flow__node { position: absolute; -webkit-user-select: none; - -moz-user-select: none; - user-select: none; + -moz-user-select: none; + user-select: none; pointer-events: all; transform-origin: 0 0; box-sizing: border-box; cursor: default; } .react-flow__node.selectable { - cursor: pointer; - } + cursor: pointer; +} .react-flow__node.draggable { - cursor: grab; - pointer-events: all; - } + cursor: grab; + pointer-events: all; +} .react-flow__node.draggable.dragging { - cursor: grabbing; - } + cursor: grabbing; +} .react-flow__nodesselection { z-index: 3; transform-origin: left top; pointer-events: none; } .react-flow__nodesselection-rect { - position: absolute; - pointer-events: all; - cursor: grab; - } + position: absolute; + pointer-events: all; + cursor: grab; +} .react-flow__handle { position: absolute; pointer-events: none; @@ -241,38 +259,42 @@ svg.react-flow__connectionline { min-height: 5px; width: 6px; height: 6px; - background-color: var(--xy-handle-background-color, var(--xy-handle-background-color-default)); - border: 1px solid var(--xy-handle-border-color, var(--xy-handle-border-color-default)); + background-color: var( + --xy-handle-background-color, + var(--xy-handle-background-color-default) + ); + border: 1px solid + var(--xy-handle-border-color, var(--xy-handle-border-color-default)); border-radius: 100%; } .react-flow__handle.connectingfrom { - pointer-events: all; - } + pointer-events: all; +} .react-flow__handle.connectionindicator { - pointer-events: all; - cursor: crosshair; - } + pointer-events: all; + cursor: crosshair; +} .react-flow__handle-bottom { - top: auto; - left: 50%; - bottom: 0; - transform: translate(-50%, 50%); - } + top: auto; + left: 50%; + bottom: 0; + transform: translate(-50%, 50%); +} .react-flow__handle-top { - top: 0; - left: 50%; - transform: translate(-50%, -50%); - } + top: 0; + left: 50%; + transform: translate(-50%, -50%); +} .react-flow__handle-left { - top: 50%; - left: 0; - transform: translate(-50%, -50%); - } + top: 50%; + left: 0; + transform: translate(-50%, -50%); +} .react-flow__handle-right { - top: 50%; - right: 0; - transform: translate(50%, -50%); - } + top: 50%; + right: 0; + transform: translate(50%, -50%); +} .react-flow__edgeupdater { cursor: move; pointer-events: all; @@ -283,31 +305,34 @@ svg.react-flow__connectionline { margin: 15px; } .react-flow__panel.top { - top: 0; - } + top: 0; +} .react-flow__panel.bottom { - bottom: 0; - } + bottom: 0; +} .react-flow__panel.left { - left: 0; - } + left: 0; +} .react-flow__panel.right { - right: 0; - } + right: 0; +} .react-flow__panel.center { - left: 50%; - transform: translateX(-50%); - } + left: 50%; + transform: translateX(-50%); +} .react-flow__attribution { font-size: 10px; - background: var(--xy-attribution-background-color, var(--xy-attribution-background-color-default)); + background: var( + --xy-attribution-background-color, + var(--xy-attribution-background-color-default) + ); padding: 2px 3px; margin: 0; } .react-flow__attribution a { - text-decoration: none; - color: #999; - } + text-decoration: none; + color: #999; +} @keyframes dashdraw { from { stroke-dashoffset: 10; @@ -319,8 +344,8 @@ svg.react-flow__connectionline { height: 100%; pointer-events: none; -webkit-user-select: none; - -moz-user-select: none; - user-select: none; + -moz-user-select: none; + user-select: none; left: 0; top: 0; } @@ -331,174 +356,240 @@ svg.react-flow__connectionline { left: 0; top: 0; -webkit-user-select: none; - -moz-user-select: none; - user-select: none; + -moz-user-select: none; + user-select: none; } .react-flow__minimap { background: var( --xy-minimap-background-color-props, - var(--xy-minimap-background-color, var(--xy-minimap-background-color-default)) + var( + --xy-minimap-background-color, + var(--xy-minimap-background-color-default) + ) ); } .react-flow__minimap-svg { - display: block; - } + display: block; +} .react-flow__minimap-mask { - fill: var( - --xy-minimap-mask-background-color-props, - var(--xy-minimap-mask-background-color, var(--xy-minimap-mask-background-color-default)) - ); - stroke: var( - --xy-minimap-mask-stroke-color-props, - var(--xy-minimap-mask-stroke-color, var(--xy-minimap-mask-stroke-color-default)) - ); - stroke-width: var( - --xy-minimap-mask-stroke-width-props, - var(--xy-minimap-mask-stroke-width, var(--xy-minimap-mask-stroke-width-default)) - ); - } + fill: var( + --xy-minimap-mask-background-color-props, + var( + --xy-minimap-mask-background-color, + var(--xy-minimap-mask-background-color-default) + ) + ); + stroke: var( + --xy-minimap-mask-stroke-color-props, + var( + --xy-minimap-mask-stroke-color, + var(--xy-minimap-mask-stroke-color-default) + ) + ); + stroke-width: var( + --xy-minimap-mask-stroke-width-props, + var( + --xy-minimap-mask-stroke-width, + var(--xy-minimap-mask-stroke-width-default) + ) + ); +} .react-flow__minimap-node { - fill: var( - --xy-minimap-node-background-color-props, - var(--xy-minimap-node-background-color, var(--xy-minimap-node-background-color-default)) - ); - stroke: var( - --xy-minimap-node-stroke-color-props, - var(--xy-minimap-node-stroke-color, var(--xy-minimap-node-stroke-color-default)) - ); - stroke-width: var( - --xy-minimap-node-stroke-width-props, - var(--xy-minimap-node-stroke-width, var(--xy-minimap-node-stroke-width-default)) - ); - } + fill: var( + --xy-minimap-node-background-color-props, + var( + --xy-minimap-node-background-color, + var(--xy-minimap-node-background-color-default) + ) + ); + stroke: var( + --xy-minimap-node-stroke-color-props, + var( + --xy-minimap-node-stroke-color, + var(--xy-minimap-node-stroke-color-default) + ) + ); + stroke-width: var( + --xy-minimap-node-stroke-width-props, + var( + --xy-minimap-node-stroke-width, + var(--xy-minimap-node-stroke-width-default) + ) + ); +} .react-flow__background-pattern.dots { - fill: var( - --xy-background-pattern-color-props, - var(--xy-background-pattern-color, var(--xy-background-pattern-dots-color-default)) - ); - } + fill: var( + --xy-background-pattern-color-props, + var( + --xy-background-pattern-color, + var(--xy-background-pattern-dots-color-default) + ) + ); +} .react-flow__background-pattern.lines { - stroke: var( - --xy-background-pattern-color-props, - var(--xy-background-pattern-color, var(--xy-background-pattern-lines-color-default)) - ); - } + stroke: var( + --xy-background-pattern-color-props, + var( + --xy-background-pattern-color, + var(--xy-background-pattern-lines-color-default) + ) + ); +} .react-flow__background-pattern.cross { - stroke: var( - --xy-background-pattern-color-props, - var(--xy-background-pattern-color, var(--xy-background-pattern-cross-color-default)) - ); - } + stroke: var( + --xy-background-pattern-color-props, + var( + --xy-background-pattern-color, + var(--xy-background-pattern-cross-color-default) + ) + ); +} .react-flow__controls { display: flex; flex-direction: column; - box-shadow: var(--xy-controls-box-shadow, var(--xy-controls-box-shadow-default)); + box-shadow: var( + --xy-controls-box-shadow, + var(--xy-controls-box-shadow-default) + ); } .react-flow__controls.horizontal { - flex-direction: row; - } + flex-direction: row; +} .react-flow__controls-button { - display: flex; - justify-content: center; - align-items: center; - height: 26px; - width: 26px; - padding: 4px; - border: none; - background: var(--xy-controls-button-background-color, var(--xy-controls-button-background-color-default)); - border-bottom: 1px solid + display: flex; + justify-content: center; + align-items: center; + height: 26px; + width: 26px; + padding: 4px; + border: none; + background: var( + --xy-controls-button-background-color, + var(--xy-controls-button-background-color-default) + ); + border-bottom: 1px solid + var( + --xy-controls-button-border-color-props, var( - --xy-controls-button-border-color-props, - var(--xy-controls-button-border-color, var(--xy-controls-button-border-color-default)) - ); - color: var( - --xy-controls-button-color-props, - var(--xy-controls-button-color, var(--xy-controls-button-color-default)) + --xy-controls-button-border-color, + var(--xy-controls-button-border-color-default) + ) ); - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - user-select: none; - } + color: var( + --xy-controls-button-color-props, + var(--xy-controls-button-color, var(--xy-controls-button-color-default)) + ); + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; +} .react-flow__controls-button svg { - width: 100%; - max-width: 12px; - max-height: 12px; - fill: currentColor; - } + width: 100%; + max-width: 12px; + max-height: 12px; + fill: currentColor; +} .react-flow__edge.updating .react-flow__edge-path { - stroke: #777; - } + stroke: #777; +} .react-flow__edge-text { - font-size: 10px; - } + font-size: 10px; +} .react-flow__node.selectable:focus, - .react-flow__node.selectable:focus-visible { - outline: none; - } +.react-flow__node.selectable:focus-visible { + outline: none; +} .react-flow__node-input, .react-flow__node-default, .react-flow__node-output, .react-flow__node-group { padding: 10px; - border-radius: var(--xy-node-border-radius, var(--xy-node-border-radius-default)); + border-radius: var( + --xy-node-border-radius, + var(--xy-node-border-radius-default) + ); width: 150px; font-size: 12px; color: var(--xy-node-color, var(--xy-node-color-default)); text-align: center; border: var(--xy-node-border, var(--xy-node-border-default)); - background-color: var(--xy-node-background-color, var(--xy-node-background-color-default)); + background-color: var( + --xy-node-background-color, + var(--xy-node-background-color-default) + ); +} +.react-flow__node-input.selectable:hover, +.react-flow__node-default.selectable:hover, +.react-flow__node-output.selectable:hover, +.react-flow__node-group.selectable:hover { + box-shadow: var( + --xy-node-boxshadow-hover, + var(--xy-node-boxshadow-hover-default) + ); } -.react-flow__node-input.selectable:hover, .react-flow__node-default.selectable:hover, .react-flow__node-output.selectable:hover, .react-flow__node-group.selectable:hover { - box-shadow: var(--xy-node-boxshadow-hover, var(--xy-node-boxshadow-hover-default)); - } .react-flow__node-input.selectable.selected, - .react-flow__node-input.selectable:focus, - .react-flow__node-input.selectable:focus-visible, - .react-flow__node-default.selectable.selected, - .react-flow__node-default.selectable:focus, - .react-flow__node-default.selectable:focus-visible, - .react-flow__node-output.selectable.selected, - .react-flow__node-output.selectable:focus, - .react-flow__node-output.selectable:focus-visible, - .react-flow__node-group.selectable.selected, - .react-flow__node-group.selectable:focus, - .react-flow__node-group.selectable:focus-visible { - box-shadow: var(--xy-node-boxshadow-selected, var(--xy-node-boxshadow-selected-default)); - } +.react-flow__node-input.selectable:focus, +.react-flow__node-input.selectable:focus-visible, +.react-flow__node-default.selectable.selected, +.react-flow__node-default.selectable:focus, +.react-flow__node-default.selectable:focus-visible, +.react-flow__node-output.selectable.selected, +.react-flow__node-output.selectable:focus, +.react-flow__node-output.selectable:focus-visible, +.react-flow__node-group.selectable.selected, +.react-flow__node-group.selectable:focus, +.react-flow__node-group.selectable:focus-visible { + box-shadow: var( + --xy-node-boxshadow-selected, + var(--xy-node-boxshadow-selected-default) + ); +} .react-flow__node-group { - background-color: var(--xy-node-group-background-color, var(--xy-node-group-background-color-default)); + background-color: var( + --xy-node-group-background-color, + var(--xy-node-group-background-color-default) + ); } .react-flow__nodesselection-rect, .react-flow__selection { - background: var(--xy-selection-background-color, var(--xy-selection-background-color-default)); + background: var( + --xy-selection-background-color, + var(--xy-selection-background-color-default) + ); border: var(--xy-selection-border, var(--xy-selection-border-default)); } .react-flow__nodesselection-rect:focus, - .react-flow__nodesselection-rect:focus-visible, - .react-flow__selection:focus, - .react-flow__selection:focus-visible { - outline: none; - } +.react-flow__nodesselection-rect:focus-visible, +.react-flow__selection:focus, +.react-flow__selection:focus-visible { + outline: none; +} .react-flow__controls-button:hover { - background: var( - --xy-controls-button-background-color-hover-props, - var(--xy-controls-button-background-color-hover, var(--xy-controls-button-background-color-hover-default)) - ); - color: var( - --xy-controls-button-color-hover-props, - var(--xy-controls-button-color-hover, var(--xy-controls-button-color-hover-default)) - ); - } + background: var( + --xy-controls-button-background-color-hover-props, + var( + --xy-controls-button-background-color-hover, + var(--xy-controls-button-background-color-hover-default) + ) + ); + color: var( + --xy-controls-button-color-hover-props, + var( + --xy-controls-button-color-hover, + var(--xy-controls-button-color-hover-default) + ) + ); +} .react-flow__controls-button:disabled { - pointer-events: none; - } + pointer-events: none; +} .react-flow__controls-button:disabled svg { - fill-opacity: 0.4; - } + fill-opacity: 0.4; +} .react-flow__controls-button:last-child { - border-bottom: none; - } + border-bottom: none; +} .react-flow__resize-control { position: absolute; } @@ -524,7 +615,10 @@ svg.react-flow__connectionline { height: 4px; border: 1px solid #fff; border-radius: 1px; - background-color: var(--xy-resize-background-color, var(--xy-resize-background-color-default)); + background-color: var( + --xy-resize-background-color, + var(--xy-resize-background-color-default) + ); transform: translate(-50%, -50%); } .react-flow__resize-control.handle.left { @@ -557,7 +651,10 @@ svg.react-flow__connectionline { } /* line styles */ .react-flow__resize-control.line { - border-color: var(--xy-resize-background-color, var(--xy-resize-background-color-default)); + border-color: var( + --xy-resize-background-color, + var(--xy-resize-background-color-default) + ); border-width: 0; border-style: solid; } @@ -592,7 +689,10 @@ svg.react-flow__connectionline { top: 100%; } .react-flow__edge-textbg { - fill: var(--xy-edge-label-background-color, var(--xy-edge-label-background-color-default)); + fill: var( + --xy-edge-label-background-color, + var(--xy-edge-label-background-color-default) + ); } .react-flow__edge-text { fill: var(--xy-edge-label-color, var(--xy-edge-label-color-default)); diff --git a/sidebar.zudoku.json b/sidebar.zudoku.json index 740223c0..1fc1264c 100644 --- a/sidebar.zudoku.json +++ b/sidebar.zudoku.json @@ -68,4 +68,4 @@ "dev-portal/zudoku/components/shadcn" ] } -] \ No newline at end of file +] diff --git a/src/BundlesTable.tsx b/src/BundlesTable.tsx index 50a1e6e4..a002ef16 100644 --- a/src/BundlesTable.tsx +++ b/src/BundlesTable.tsx @@ -10,13 +10,13 @@ type BundlesFile = { description: string; isPublic: boolean; }[]; -} +}; export const BundlesTable = () => { const [data, setData] = useState(null); useEffect(() => { - const response = fetch( + const response = fetch( "https://cdn.zuplo.com/types/@zuplo/bundled/bundles.v2.json", ); response.then((res) => res.json()).then(setData); @@ -48,4 +48,4 @@ export const BundlesTable = () => { ))} ); -} \ No newline at end of file +};