
Security News
Browserslist-rs Gets Major Refactor, Cutting Binary Size by Over 1MB
Browserslist-rs now uses static data to reduce binary size by over 1MB, improving memory use and performance for Rust-based frontend tools.
Bad Magic is a Swagger-UI alternative that allows developers to visualize and test their API resources from a convenient web interface.
yarn add badmagic
You will also need to include the TailwindCSS stylesheet on the page you plan to use Bad Magic
<link
href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css"
rel="stylesheet"
/>
Clone badmagic
, then run the following commands:
cd example
yarn
yarn start
In the root badmagic directory
run the following commands:
yarn
yarn link
yarn start
In the example directory
run the follow commands:
yarn
to install node modules in the example folderyarn link "badmagic"
yarn start
(to start the example that will be running on port 3000 by default)import { BadMagic } from "badmagic";
import { Method } from "badmagic/dist/types";
export function BadMagicClient() {
const superheroWorkspace = {
id: "superheroes",
name: "Superheroes",
config: {
baseUrl: `${window.location.origin}/api`,
},
routes: [
{
name: "Search Superheroes",
path: "/v1/superheroes",
},
{
name: "Fetch Superhero",
path: "/v1/superheroes/:superhero_id",
},
{
name: "Create Superhero",
path: "/v1/superheroes",
method: "POST",
body: [
{ name: "first_name", required: true },
{ name: "last_name" },
{ name: "phone", placeholder: "Some digits to reach this superhero" },
{ name: "superpowers", type: "textarea" },
{
name: "age",
options: [
{ label: "6", value: 6 },
{ label: "18", value: 18 },
{ label: "60", value: 60 },
],
},
],
},
{
name: "Update Superhero",
path: "/v1/superheroes/:superhero_id",
method: "PATCH",
body: [
{ name: "first_name", required: true },
{ name: "last_name" },
{ name: "phone", placeholder: "Some digits to reach this superhero" },
{ name: "superpowers", type: "textarea" },
{
name: "age",
options: [
{ label: "6", value: 6 },
{ label: "18", value: 18 },
{ label: "60", value: 60 },
],
},
],
},
{
name: "Delete Superhero",
path: "/v1/superheroes/:superhero_id",
method: "DELETE",
},
],
};
return <BadMagic basename="/dev/api" workspaces={[superheroWorkspace]} />;
}
badmagic
uses Axios as the API library and Axios has Interceptors which make it easy to intercept requests or responses to do tasks like injecting auth headers.
Here is an example of injecting a Bearer auth header where the function getAccessToken()
is a way on your frontend to fetch the current user's access token.
export const applyAxiosInterceptors = ({ axios }) => {
axios.interceptors.request.use((config: AxiosRequestConfig) => {
return {
...config,
headers: {
Authorization: `Bearer ${getAccessToken()}`,
},
};
});
return axios;
};
Usage:
<BadMagic
applyAxiosInterceptors={applyAxiosInterceptors}
basename="/dev/api"
workspaces={workspaces}
/>
If needed, you can prompt the end-user to enter auth credentials and/or to generate access tokens, etc., by using a
form that can be injected and rendered above the Route
component called AuthForm
.
workspaceConfig
is passed in as an argument so if you have multiple workspaces with different auth strategies, you
can use the information in workspaceConfig
to determine which form to render.
Here's some pseudocode to give you an idea:
export function AuthForm({
workspaceConfig,
}) {
return (
<div>
<TextInput name="email" />
<TextInput name="password" />
<Button onClick={() => {
// axios request to login user, fetch access token, and store access token in state or local storage
// then in the `applyAxiosInterceptors`, the `getAccessToken()` function can fetch the token from state or
// local storage
}}>
</div>
);
};
Usage:
<BadMagic
AuthForm={AuthForm}
applyAxiosInterceptors={applyAxiosInterceptors}
workspaces={workspaces}
/>
badmagic
can also use Axios Interceptors to intercept the response to append the request/response to local storage
so that you can see prior API requests you made.
Here's an example:
export const applyAxiosInterceptors = ({ axios, storeHistoricResponse }) => {
axios.interceptors.response.use(
(response: AxiosResponse) => {
storeHistoricResponse({
metadata: getMetadata() // Metadata can store any data you want like which access token was used, etc.
response,
error: null,
}); // Adds success response to BadMagic's `History` tab
return response;
},
(error: AxiosError) => {
storeHistoricResponse({
metadata: getMetadata() // Metadata can store any data you want like which access token was used, etc.
response: null,
error,
}); // Adds error response to BadMagic's `History` tab
return Promise.reject(error);
}
);
return axios;
};
Usage:
<BadMagic
applyAxiosInterceptors={applyAxiosInterceptors}
workspaces={workspaces}
/>
badmagic
allows rendering a custom subsection in the History
section for each historic API request where you can
take the metadata
you stored using the axios intercepter and display it in any custom way you'd like.
Note: By default, insertedAt
is stored on metadata
.
Example:
export function HistoryMetadata({
metadata,
}: {
metadata: Record<string, any>,
}) {
if (!metadata?.accessToken) {
return null;
}
return (
<div className="flex justify-between">
<div>Access Token: {metadata.accessToken}</div>
<div>{new Date(metadata.insertedAt).toLocaleString()}</div>
</div>
);
}
Usage:
<BadMagic
HistoryMetadata={HistoryMetadata}
applyAxiosInterceptors={applyAxiosInterceptors}
basename="/dev/api"
workspaces={workspaces}
/>
documentation
key to the object.documentation
accepts a string literal template that will render into markdown.badmagic-markdown
<link
href="https://unpkg.com/badmagic@^0.0.40/dist/css/markdown.min.css"
rel="stylesheet"
/>
Usage:
import SuperHero Documentation from "./docs/superheroes.md";
const superheroes = {
id: "superheroes",
name: "Superheroes",
config: {
baseUrl: `${window.location.origin}/api`,
},
routes: [
{
name: "Search Superheroes",
path: "/v1/superheroes",
documentation: SuperHeroDocumentation,
},
{
name: "Fetch Superhero",
path: "/v1/superheroes/:superhero_id",
},
],
};
deprecated
key to the object.deprecated
accepts a boolean and will by default is set to false
Usage:
const superheroes = {
id: "superheroes",
name: "Superheroes",
routes: [
{
name: "Fetch Superhero",
path: "/v1/superheroes/:superhero_id",
deprecated: true,
},
],
};
description
attribute will generate the on-hover icon and it will pull the text from the description
as wellUsage:
const superheroes = {
id: "superheroes",
name: "Superheroes",
routes: [
{
name: "Update Superhero",
path: "/v1/superheroes/:superhero_id",
method: "PATCH",
body: [
{
name: "first_name",
required: true,
description: "The first name of the hero you want to update to"
},
},
],
};
Why did you name this
badmagic
?
Right before a production deploy, I was contemplating an easy to implement API interface that can be consumed by engineers during local testing and by QA teams during the QA phase of the SDLC and is pluggable. As the deploy was kicked off, my Macbook crashed and when I rebooted, my crash report said "Bad magic! Kernel panic!" and in that moment, the package name had been decided.
The below assumes you have wml
installed:
yarn
to get dependencies for badmagic
badmagic
in the CWD run wml add . ../path/to/your/project/node_modules/badmagic
wml start
badmagic
in the CWD run yarn start
badmagic
installedRunning the example
in your browser:
badmagic
root folder, run yarn
then yarn link
then yarn start
example
folder, run yarn
, then yarn link badmagic
then yarn start
yarn publish
FAQs
Swagger UI alternative written in React
The npm package badmagic receives a total of 70 weekly downloads. As such, badmagic popularity was classified as not popular.
We found that badmagic demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 7 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Browserslist-rs now uses static data to reduce binary size by over 1MB, improving memory use and performance for Rust-based frontend tools.
Research
Security News
Eight new malicious Firefox extensions impersonate games, steal OAuth tokens, hijack sessions, and exploit browser permissions to spy on users.
Security News
The official Go SDK for the Model Context Protocol is in development, with a stable, production-ready release expected by August 2025.