Workflows stay readable, reviewable, and easy to refactor with the rest of your codebase.
Add GraphQL, browser steps, auth helpers, or internal clients without inventing a second system.
Local runs, CI, browser steps, and Cloud all sit on the same runtime and trace model.
The core SDK already gives you the parts most teams need: requests, assertions, secrets, templating, and structured traces. Plugins build on top of that runtime instead of replacing it.
import { test } from "@glubean/sdk";
test("list products", async (ctx) => {
const base = ctx.vars.require("BASE_URL");
const data = await ctx.http
.get(`${base}/products?limit=5`)
.json();
ctx.expect(data.products.length).toBe(5);
ctx.log(`Found ${data.total} products`);
});Use official packages when they fit, then add your own organization-specific capabilities without leaving the workflow system. The point is not a pile of adapters. The point is one runtime that keeps growing with your use case.
@glubean/graphql
Ground GraphQL queries and mutations in the same traced workflow you already use for HTTP.
@glubean/browser
Extend the same workflow into Puppeteer-powered browser steps without losing structure.
Your own plugin
Wrap internal services, auth flows, or domain helpers as reusable capabilities for the whole team.
GraphQL stays inside the same trace model
import { test, configure } from "@glubean/sdk";
import { graphql } from "@glubean/graphql";
const { gql } = configure({
plugins: {
gql: graphql({
endpoint: "{{GRAPHQL_URL}}",
headers: { Authorization: "Bearer {{API_KEY}}" },
}),
},
});
export const getUser = test("get-user", async (ctx) => {
const { data } = await gql.query<{ user: { name: string } }>(`
query GetUser($id: ID!) {
user(id: $id) { name email }
}
`, { variables: { id: "1" } });
ctx.expect(data?.user.name).toBe("Alice");
});Browser steps extend the same workflow into Puppeteer
import { test, configure } from "@glubean/sdk";
import { browser } from "@glubean/browser";
const { chrome } = configure({
plugins: { chrome: browser({ launch: true }) },
});
const ui = test.extend({
page: async (ctx, use) => {
const pg = await chrome.newPage(ctx);
try { await use(pg); }
finally { await pg.close(); }
},
});
export const login = ui("login-flow", async (ctx) => {
await ctx.page.goto("/login");
await ctx.page.type("#email", "user@test.com");
await ctx.page.type("#password", "secret");
await ctx.page.clickAndNavigate('button[type="submit"]');
await ctx.page.expectURL("/dashboard");
await ctx.page.expectText("h1", "Welcome back");
});Wrap an internal service client, auth helper, or domain-specific workflow primitive once, then reuse it everywhere. This is the difference between a convenient test file and a workflow system that compounds.
import { definePlugin, configure, test } from "@glubean/sdk";
const payments = (opts: { baseUrlKey: string }) =>
definePlugin((runtime) => {
const client = runtime.http.extend({
prefixUrl: runtime.requireVar(opts.baseUrlKey),
headers: {
Authorization: `Bearer ${runtime.requireSecret("STRIPE_KEY")}`,
},
});
return {
charge: (amount: number) =>
client.post("charges", { json: { amount } }).json(),
refund: (id: string) =>
client.post(`charges/${id}/refund`).json(),
};
});
const { pay } = configure({
plugins: { pay: payments({ baseUrlKey: "PAYMENTS_URL" }) },
});
export const chargeAndRefund = test("charge-refund", async (ctx) => {
const charge = await pay.charge(2500);
ctx.expect(charge.status).toBe("succeeded");
const refund = await pay.refund(charge.id);
ctx.expect(refund.status).toBe("refunded");
});Official packages and custom plugins join in one configure() call. That keeps the workflow surface consistent across local runs, CI, and Cloud.
const { gql, chrome, pay } = configure({
plugins: {
gql: graphql({ endpoint: "{{GQL_URL}}" }),
chrome: browser({ launch: true }),
pay: payments({ baseUrlKey: "PAY_URL" }),
},
});Glubean runs on Node.js with native TypeScript support — no build step required. The entire npm ecosystem is available, so any package you already use works out of the box. The practical rule is simple: if you can import it, it is a good plugin candidate. When you need heavier browser coverage, keep Playwright where it fits and use Glubean where the shared workflow model matters more.
When you want exact APIs, published packages, or product-specific surfaces, jump to the right layer.
API reference and deeper guides when you want exact surfaces and package details.
Read docsBrowse the published packages directly when you want the install surface and version history.
Open npmSee how the same SDK model shows up in the extension, browser workflows, and Cloud.
See extension