@arnaudjnn/billing-tools 0.14.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.
- package/LICENSE +21 -0
- package/README.md +243 -0
- package/dist/adapters/workos-org.d.ts +80 -0
- package/dist/adapters/workos-org.d.ts.map +1 -0
- package/dist/adapters/workos-org.js +176 -0
- package/dist/adapters/workos-org.js.map +1 -0
- package/dist/agent-auth/claim-store.d.ts +37 -0
- package/dist/agent-auth/claim-store.d.ts.map +1 -0
- package/dist/agent-auth/claim-store.js +64 -0
- package/dist/agent-auth/claim-store.js.map +1 -0
- package/dist/agent-auth/index.d.ts +65 -0
- package/dist/agent-auth/index.d.ts.map +1 -0
- package/dist/agent-auth/index.js +365 -0
- package/dist/agent-auth/index.js.map +1 -0
- package/dist/auth.d.ts +16 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +80 -0
- package/dist/auth.js.map +1 -0
- package/dist/billing.d.ts +59 -0
- package/dist/billing.d.ts.map +1 -0
- package/dist/billing.js +258 -0
- package/dist/billing.js.map +1 -0
- package/dist/cli/client.d.ts +10 -0
- package/dist/cli/client.d.ts.map +1 -0
- package/dist/cli/client.js +22 -0
- package/dist/cli/client.js.map +1 -0
- package/dist/cli/commands.d.ts +4 -0
- package/dist/cli/commands.d.ts.map +1 -0
- package/dist/cli/commands.js +94 -0
- package/dist/cli/commands.js.map +1 -0
- package/dist/cli/config.d.ts +16 -0
- package/dist/cli/config.d.ts.map +1 -0
- package/dist/cli/config.js +40 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/create-billing.d.ts +78 -0
- package/dist/create-billing.d.ts.map +1 -0
- package/dist/create-billing.js +59 -0
- package/dist/create-billing.js.map +1 -0
- package/dist/dispatch.d.ts +9 -0
- package/dist/dispatch.d.ts.map +1 -0
- package/dist/dispatch.js +73 -0
- package/dist/dispatch.js.map +1 -0
- package/dist/events.d.ts +26 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +72 -0
- package/dist/events.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +40 -0
- package/dist/index.js.map +1 -0
- package/dist/invitations.d.ts +56 -0
- package/dist/invitations.d.ts.map +1 -0
- package/dist/invitations.js +117 -0
- package/dist/invitations.js.map +1 -0
- package/dist/machine-payment/index.d.ts +57 -0
- package/dist/machine-payment/index.d.ts.map +1 -0
- package/dist/machine-payment/index.js +117 -0
- package/dist/machine-payment/index.js.map +1 -0
- package/dist/magic-auth.d.ts +4 -0
- package/dist/magic-auth.d.ts.map +1 -0
- package/dist/magic-auth.js +30 -0
- package/dist/magic-auth.js.map +1 -0
- package/dist/mirror.d.ts +35 -0
- package/dist/mirror.d.ts.map +1 -0
- package/dist/mirror.js +63 -0
- package/dist/mirror.js.map +1 -0
- package/dist/plans.d.ts +38 -0
- package/dist/plans.d.ts.map +1 -0
- package/dist/plans.js +132 -0
- package/dist/plans.js.map +1 -0
- package/dist/routes/mcp.d.ts +19 -0
- package/dist/routes/mcp.d.ts.map +1 -0
- package/dist/routes/mcp.js +39 -0
- package/dist/routes/mcp.js.map +1 -0
- package/dist/routes/rest.d.ts +20 -0
- package/dist/routes/rest.d.ts.map +1 -0
- package/dist/routes/rest.js +66 -0
- package/dist/routes/rest.js.map +1 -0
- package/dist/routes/webhook.d.ts +8 -0
- package/dist/routes/webhook.d.ts.map +1 -0
- package/dist/routes/webhook.js +39 -0
- package/dist/routes/webhook.js.map +1 -0
- package/dist/sync.d.ts +58 -0
- package/dist/sync.d.ts.map +1 -0
- package/dist/sync.js +202 -0
- package/dist/sync.js.map +1 -0
- package/dist/tools/billing.d.ts +4 -0
- package/dist/tools/billing.d.ts.map +1 -0
- package/dist/tools/billing.js +125 -0
- package/dist/tools/billing.js.map +1 -0
- package/dist/tools/keys.d.ts +4 -0
- package/dist/tools/keys.d.ts.map +1 -0
- package/dist/tools/keys.js +107 -0
- package/dist/tools/keys.js.map +1 -0
- package/dist/tools/register.d.ts +20 -0
- package/dist/tools/register.d.ts.map +1 -0
- package/dist/tools/register.js +87 -0
- package/dist/tools/register.js.map +1 -0
- package/dist/types.d.ts +90 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +28 -0
- package/dist/types.js.map +1 -0
- package/dist/util/clearout.d.ts +5 -0
- package/dist/util/clearout.d.ts.map +1 -0
- package/dist/util/clearout.js +18 -0
- package/dist/util/clearout.js.map +1 -0
- package/dist/workos.d.ts +6 -0
- package/dist/workos.d.ts.map +1 -0
- package/dist/workos.js +24 -0
- package/dist/workos.js.map +1 -0
- package/package.json +81 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { resolveConfig } from "../types.js";
|
|
2
|
+
import { registerKeyTools } from "./keys.js";
|
|
3
|
+
import { registerBillingOnlyTools } from "./billing.js";
|
|
4
|
+
import { ensurePlans } from "../plans.js";
|
|
5
|
+
// Keys whose values must never hit the logs (magic-auth codes, API keys, etc.).
|
|
6
|
+
const SENSITIVE_KEY_RE = /cookie|token|secret|password|passwd|authorization|api[_-]?key|session|credential|code/i;
|
|
7
|
+
function redactForLog(value, depth = 0) {
|
|
8
|
+
if (value === null || typeof value !== "object") {
|
|
9
|
+
if (typeof value === "string" && value.length > 300) {
|
|
10
|
+
return `${value.slice(0, 300)}…(${value.length} chars)`;
|
|
11
|
+
}
|
|
12
|
+
return value;
|
|
13
|
+
}
|
|
14
|
+
if (depth > 4)
|
|
15
|
+
return "[…]";
|
|
16
|
+
if (Array.isArray(value))
|
|
17
|
+
return value.map((v) => redactForLog(v, depth + 1));
|
|
18
|
+
const out = {};
|
|
19
|
+
for (const [k, v] of Object.entries(value)) {
|
|
20
|
+
out[k] = SENSITIVE_KEY_RE.test(k) ? "[redacted]" : redactForLog(v, depth + 1);
|
|
21
|
+
}
|
|
22
|
+
return out;
|
|
23
|
+
}
|
|
24
|
+
// Wrap server.tool so every handler logs its (redacted) input. Call before
|
|
25
|
+
// registering tools so both the live MCP server and the REST dispatch shadow
|
|
26
|
+
// server emit uniform [tool-input] lines.
|
|
27
|
+
export function installInputLogging(server) {
|
|
28
|
+
const orig = server.tool.bind(server);
|
|
29
|
+
server.tool = function (...args) {
|
|
30
|
+
const name = args[0];
|
|
31
|
+
const cbIdx = args.length - 1;
|
|
32
|
+
const cb = args[cbIdx];
|
|
33
|
+
if (typeof cb === "function" && typeof name === "string") {
|
|
34
|
+
args[cbIdx] = async (toolArgs, extra) => {
|
|
35
|
+
try {
|
|
36
|
+
console.log(`[tool-input] ${name} ${JSON.stringify(redactForLog(toolArgs))}`);
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
console.log(`[tool-input] ${name} (unserializable args)`);
|
|
40
|
+
}
|
|
41
|
+
return cb(toolArgs, extra);
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
return orig(...args);
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
// Register the billing-tools surface (auth/key management + token billing) on
|
|
48
|
+
// an MCP server. Host apps call this, then register their own product tools.
|
|
49
|
+
export function registerBillingTools(server, opts) {
|
|
50
|
+
const config = resolveConfig(opts.config);
|
|
51
|
+
if (opts.installLogging !== false)
|
|
52
|
+
installInputLogging(server);
|
|
53
|
+
registerKeyTools(server, opts.adapter, config);
|
|
54
|
+
registerBillingOnlyTools(server, opts.adapter, config, opts.toolCosts ?? {});
|
|
55
|
+
if (opts.plans)
|
|
56
|
+
registerPlanTools(server, opts.plans, opts.defaultPlan, config.currency);
|
|
57
|
+
}
|
|
58
|
+
// list_plans: returns the configured plans + live Stripe prices, provisioning
|
|
59
|
+
// the Stripe products/prices on first call (idempotent). Zero dashboard setup.
|
|
60
|
+
function registerPlanTools(server, plans, defaultPlan, currency) {
|
|
61
|
+
server.tool("list_plans", "List the available subscription plans (seats, included tokens, and monthly/yearly prices). Prices are provisioned in Stripe automatically.", {}, async () => {
|
|
62
|
+
const ensured = await ensurePlans(plans, { currency });
|
|
63
|
+
const priceOf = (plan, interval) => ensured.find((e) => e.plan === plan && e.interval === interval) ?? null;
|
|
64
|
+
const out = Object.entries(plans).map(([key, def]) => ({
|
|
65
|
+
plan: key,
|
|
66
|
+
default: key === defaultPlan,
|
|
67
|
+
seats: def.seats,
|
|
68
|
+
tokens_per_seat: def.tokensPerSeat,
|
|
69
|
+
prices: {
|
|
70
|
+
monthly: { amount: def.price.monthly, currency, price_id: priceOf(key, "monthly")?.priceId ?? null },
|
|
71
|
+
yearly: { amount: def.price.yearly, currency, price_id: priceOf(key, "yearly")?.priceId ?? null },
|
|
72
|
+
},
|
|
73
|
+
}));
|
|
74
|
+
return { content: [{ type: "text", text: JSON.stringify({ plans: out }, null, 2) }] };
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
export const BILLING_TOOL_NAMES = [
|
|
78
|
+
"get_api_key",
|
|
79
|
+
"list_api_keys",
|
|
80
|
+
"revoke_api_key",
|
|
81
|
+
"get_token_balance",
|
|
82
|
+
"buy_tokens",
|
|
83
|
+
"set_auto_reload",
|
|
84
|
+
"get_billing_portal",
|
|
85
|
+
"list_invoices",
|
|
86
|
+
];
|
|
87
|
+
//# sourceMappingURL=register.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register.js","sourceRoot":"","sources":["../../src/tools/register.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
export interface BillingUser {
|
|
2
|
+
id: string;
|
|
3
|
+
email: string;
|
|
4
|
+
firstName?: string | null;
|
|
5
|
+
lastName?: string | null;
|
|
6
|
+
profilePictureUrl?: string | null;
|
|
7
|
+
}
|
|
8
|
+
export interface ApiKeyInfo {
|
|
9
|
+
id: string;
|
|
10
|
+
name: string;
|
|
11
|
+
obfuscatedValue: string;
|
|
12
|
+
}
|
|
13
|
+
export interface BillingAdapter {
|
|
14
|
+
/** Resolve a raw Bearer API key → org, or null if invalid/revoked. */
|
|
15
|
+
validateApiKey(token: string): Promise<{
|
|
16
|
+
orgId: string;
|
|
17
|
+
} | null>;
|
|
18
|
+
/** Optional: resolve an OAuth bearer (JWT) → org id. Omit if no OAuth. */
|
|
19
|
+
resolveOauthOrg?(token: string): Promise<string | null>;
|
|
20
|
+
/** Verified domains for the org (used for the internal-org unmetered check). */
|
|
21
|
+
getOrgDomains(orgId: string): Promise<string[]>;
|
|
22
|
+
/** Read the Stripe customer id pointer for the org (null if none yet). */
|
|
23
|
+
getBillingCustomerId(orgId: string): Promise<string | null>;
|
|
24
|
+
/** Persist the Stripe customer id pointer for the org. */
|
|
25
|
+
setBillingCustomerId(orgId: string, customerId: string): Promise<void>;
|
|
26
|
+
/** After magic-auth: find or create the org/workspace for this user. */
|
|
27
|
+
ensureOrgForUser(user: BillingUser): Promise<{
|
|
28
|
+
orgId: string;
|
|
29
|
+
}>;
|
|
30
|
+
/** Mint a new API key for the org. `createdBy` (the acting user id) is
|
|
31
|
+
* passed when available; adapters that don't track it may ignore it.
|
|
32
|
+
* Returns the raw value (shown once). */
|
|
33
|
+
mintApiKey(orgId: string, name: string, createdBy?: string): Promise<{
|
|
34
|
+
id: string;
|
|
35
|
+
value: string;
|
|
36
|
+
}>;
|
|
37
|
+
/** List the org's (non-revoked) keys, obfuscated. */
|
|
38
|
+
listApiKeys(orgId: string): Promise<ApiKeyInfo[]>;
|
|
39
|
+
/** Revoke a key by id, scoped to the org (belongs-to check inside). */
|
|
40
|
+
revokeApiKey(orgId: string, id: string): Promise<{
|
|
41
|
+
id: string;
|
|
42
|
+
name: string;
|
|
43
|
+
} | null>;
|
|
44
|
+
/** Revoke an API key by its raw value — for the RFC 7009 /oauth/revoke
|
|
45
|
+
* endpoint, where only the token (not the org/id) is known. Optional. */
|
|
46
|
+
revokeApiKeyByToken?(token: string): Promise<boolean>;
|
|
47
|
+
/** Create an org with NO associated user (auth.md `anonymous` registration).
|
|
48
|
+
* Optional — if absent, anonymous registration reports `anonymous_not_enabled`. */
|
|
49
|
+
createAnonymousOrg?(opts: {
|
|
50
|
+
name: string;
|
|
51
|
+
metadata?: Record<string, string>;
|
|
52
|
+
}): Promise<{
|
|
53
|
+
orgId: string;
|
|
54
|
+
}>;
|
|
55
|
+
}
|
|
56
|
+
export interface BillingConfig {
|
|
57
|
+
/** Welcome credit granted on first Stripe customer creation. Default 100. */
|
|
58
|
+
freeTokens?: number;
|
|
59
|
+
/** Stripe currency, e.g. "usd" | "eur". Default "usd". */
|
|
60
|
+
currency?: string;
|
|
61
|
+
/** Base URL for Checkout success/cancel + billing-portal return. */
|
|
62
|
+
baseUrl: string;
|
|
63
|
+
/** Domains whose orgs are unmetered (internal). Default []. */
|
|
64
|
+
internalDomains?: string[];
|
|
65
|
+
}
|
|
66
|
+
export type ResolvedConfig = Required<BillingConfig>;
|
|
67
|
+
export declare function resolveConfig(c: BillingConfig): ResolvedConfig;
|
|
68
|
+
/** Build the `internalDomains` allowlist from the environment: an optional
|
|
69
|
+
* deployment root domain (whatever your host exposes — pass it if you want the
|
|
70
|
+
* deployment's own domain treated as internal) plus a comma-separated env var
|
|
71
|
+
* (default `INTERNAL_ORG_DOMAINS`). Orgs with a verified WorkOS domain matching
|
|
72
|
+
* any entry get unmetered access (see enforceTokens → isInternalOrg). Result is
|
|
73
|
+
* lowercased + de-duplicated. Host-agnostic: the caller supplies the root
|
|
74
|
+
* domain (or nothing); the env var is generic. */
|
|
75
|
+
export declare function internalDomainsFromEnv(rootDomain?: string | null, envVar?: string): string[];
|
|
76
|
+
export type ToolResult = {
|
|
77
|
+
content: Array<{
|
|
78
|
+
type: "text";
|
|
79
|
+
text: string;
|
|
80
|
+
}>;
|
|
81
|
+
isError?: boolean;
|
|
82
|
+
};
|
|
83
|
+
export type ToolErrorResult = {
|
|
84
|
+
isError: true;
|
|
85
|
+
content: Array<{
|
|
86
|
+
type: "text";
|
|
87
|
+
text: string;
|
|
88
|
+
}>;
|
|
89
|
+
};
|
|
90
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// The storage seam. `orgId` is an opaque string — a WorkOS org id, a Postgres
|
|
2
|
+
// workspace id ("ws_…"), whatever the host uses. Implement this and the rest of
|
|
3
|
+
// billing-tools (auth flow, metering, all Stripe math, tool/route/CLI surfaces)
|
|
4
|
+
// works unchanged.
|
|
5
|
+
export function resolveConfig(c) {
|
|
6
|
+
return {
|
|
7
|
+
freeTokens: c.freeTokens ?? 100,
|
|
8
|
+
currency: c.currency ?? "usd",
|
|
9
|
+
baseUrl: c.baseUrl,
|
|
10
|
+
internalDomains: c.internalDomains ?? [],
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
/** Build the `internalDomains` allowlist from the environment: an optional
|
|
14
|
+
* deployment root domain (whatever your host exposes — pass it if you want the
|
|
15
|
+
* deployment's own domain treated as internal) plus a comma-separated env var
|
|
16
|
+
* (default `INTERNAL_ORG_DOMAINS`). Orgs with a verified WorkOS domain matching
|
|
17
|
+
* any entry get unmetered access (see enforceTokens → isInternalOrg). Result is
|
|
18
|
+
* lowercased + de-duplicated. Host-agnostic: the caller supplies the root
|
|
19
|
+
* domain (or nothing); the env var is generic. */
|
|
20
|
+
export function internalDomainsFromEnv(rootDomain, envVar = "INTERNAL_ORG_DOMAINS") {
|
|
21
|
+
const extras = (process.env[envVar] ?? "")
|
|
22
|
+
.split(",")
|
|
23
|
+
.map((s) => s.trim().toLowerCase())
|
|
24
|
+
.filter(Boolean);
|
|
25
|
+
const root = rootDomain?.trim().toLowerCase();
|
|
26
|
+
return Array.from(new Set([...(root ? [root] : []), ...extras]));
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,gFAAgF;AAChF,gFAAgF;AAChF,mBAAmB;AA0DnB,MAAM,UAAU,aAAa,CAAC,CAAgB;IAC5C,OAAO;QACL,UAAU,EAAE,CAAC,CAAC,UAAU,IAAI,GAAG;QAC/B,QAAQ,EAAE,CAAC,CAAC,QAAQ,IAAI,KAAK;QAC7B,OAAO,EAAE,CAAC,CAAC,OAAO;QAClB,eAAe,EAAE,CAAC,CAAC,eAAe,IAAI,EAAE;KACzC,CAAC;AACJ,CAAC;AAED;;;;;;mDAMmD;AACnD,MAAM,UAAU,sBAAsB,CACpC,UAA0B,EAC1B,MAAM,GAAG,sBAAsB;IAE/B,MAAM,MAAM,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;SACvC,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;SAClC,MAAM,CAAC,OAAO,CAAC,CAAC;IACnB,MAAM,IAAI,GAAG,UAAU,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC9C,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;AACnE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clearout.d.ts","sourceRoot":"","sources":["../../src/util/clearout.ts"],"names":[],"mappings":"AAEA,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,GACb,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAenD"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Best-effort company enrichment from a domain (name + logo), used by the
|
|
2
|
+
// WorkOS-org adapter when creating an org. Never throws.
|
|
3
|
+
export async function lookupCompany(domain) {
|
|
4
|
+
try {
|
|
5
|
+
const res = await fetch(`https://api.clearout.io/public/companies/autocomplete?query=${encodeURIComponent(domain)}`);
|
|
6
|
+
if (!res.ok)
|
|
7
|
+
return null;
|
|
8
|
+
const data = (await res.json());
|
|
9
|
+
const match = data.data?.find((c) => c.domain.toLowerCase() === domain.toLowerCase());
|
|
10
|
+
if (!match)
|
|
11
|
+
return null;
|
|
12
|
+
return { name: match.name, logoUrl: match.logo_url };
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=clearout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clearout.js","sourceRoot":"","sources":["../../src/util/clearout.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,yDAAyD;AACzD,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAAc;IAEd,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CACrB,+DAA+D,kBAAkB,CAAC,MAAM,CAAC,EAAE,CAC5F,CAAC;QACF,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,OAAO,IAAI,CAAC;QACzB,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAE7B,CAAC;QACF,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;QACtF,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QACxB,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
package/dist/workos.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workos.d.ts","sourceRoot":"","sources":["../src/workos.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAgB1C,wBAAgB,SAAS,CAAC,IAAI,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAS/E"}
|
package/dist/workos.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { WorkOS } from "@workos-inc/node";
|
|
2
|
+
// The ONE WorkOS client bootstrap for the whole lib. Every module (adapter,
|
|
3
|
+
// invitations, magic-auth, events) goes through here so there's a single
|
|
4
|
+
// lifecycle + one place that reads the env.
|
|
5
|
+
//
|
|
6
|
+
// Lazy + memoized: constructing WorkOS eagerly throws when WORKOS_API_KEY is
|
|
7
|
+
// unset, which must never break app boot (adapters/services are built at module
|
|
8
|
+
// load) — so the client is created on first actual use (the v0.4.1 rule).
|
|
9
|
+
//
|
|
10
|
+
// The env-based client is a shared singleton. Explicit per-instance credentials
|
|
11
|
+
// (rare — an app running >1 WorkOS env in one process) get their own client so
|
|
12
|
+
// they never collide with the shared one.
|
|
13
|
+
let _default = null;
|
|
14
|
+
export function getWorkOS(opts) {
|
|
15
|
+
if (opts?.apiKey || opts?.clientId) {
|
|
16
|
+
return new WorkOS(opts.apiKey ?? process.env.WORKOS_API_KEY, {
|
|
17
|
+
clientId: opts.clientId ?? process.env.WORKOS_CLIENT_ID ?? "",
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
return (_default ??= new WorkOS(process.env.WORKOS_API_KEY, {
|
|
21
|
+
clientId: process.env.WORKOS_CLIENT_ID ?? "",
|
|
22
|
+
}));
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=workos.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workos.js","sourceRoot":"","sources":["../src/workos.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,4EAA4E;AAC5E,yEAAyE;AACzE,4CAA4C;AAC5C,EAAE;AACF,6EAA6E;AAC7E,gFAAgF;AAChF,0EAA0E;AAC1E,EAAE;AACF,gFAAgF;AAChF,+EAA+E;AAC/E,0CAA0C;AAE1C,IAAI,QAAQ,GAAkB,IAAI,CAAC;AAEnC,MAAM,UAAU,SAAS,CAAC,IAA6C;IACrE,IAAI,IAAI,EAAE,MAAM,IAAI,IAAI,EAAE,QAAQ,EAAE,CAAC;QACnC,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE;YAC3D,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,EAAE;SAC9D,CAAC,CAAC;IACL,CAAC;IACD,OAAO,CAAC,QAAQ,KAAK,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE;QAC1D,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,EAAE;KAC7C,CAAC,CAAC,CAAC;AACN,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@arnaudjnn/billing-tools",
|
|
3
|
+
"version": "0.14.0",
|
|
4
|
+
"description": "The get-paid engine for Stripe + WorkOS apps, for humans and AI agents. Drop-in API-key auth, token/credit + subscription billing, auth.md agent registration, and MPP machine payments, as MCP tools, a REST API, and a CLI. Framework-agnostic, storage-pluggable.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Arnaud Jeannin",
|
|
7
|
+
"homepage": "https://github.com/arnaudjnn/billing-tools#readme",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/arnaudjnn/billing-tools.git"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/arnaudjnn/billing-tools/issues"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"stripe",
|
|
17
|
+
"workos",
|
|
18
|
+
"billing",
|
|
19
|
+
"payments",
|
|
20
|
+
"auth",
|
|
21
|
+
"api-keys",
|
|
22
|
+
"mcp",
|
|
23
|
+
"auth.md",
|
|
24
|
+
"mpp",
|
|
25
|
+
"ai-agents",
|
|
26
|
+
"agentic-commerce",
|
|
27
|
+
"subscriptions",
|
|
28
|
+
"saas",
|
|
29
|
+
"usage-based-billing"
|
|
30
|
+
],
|
|
31
|
+
"type": "module",
|
|
32
|
+
"exports": {
|
|
33
|
+
".": {
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
35
|
+
"import": "./dist/index.js",
|
|
36
|
+
"default": "./dist/index.js"
|
|
37
|
+
},
|
|
38
|
+
"./adapters/workos-org": {
|
|
39
|
+
"types": "./dist/adapters/workos-org.d.ts",
|
|
40
|
+
"import": "./dist/adapters/workos-org.js",
|
|
41
|
+
"default": "./dist/adapters/workos-org.js"
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"files": [
|
|
45
|
+
"dist",
|
|
46
|
+
"README.md",
|
|
47
|
+
"LICENSE"
|
|
48
|
+
],
|
|
49
|
+
"publishConfig": {
|
|
50
|
+
"access": "public"
|
|
51
|
+
},
|
|
52
|
+
"scripts": {
|
|
53
|
+
"build": "tsc",
|
|
54
|
+
"typecheck": "tsc --noEmit",
|
|
55
|
+
"clean": "rm -rf dist",
|
|
56
|
+
"prepublishOnly": "npm run build"
|
|
57
|
+
},
|
|
58
|
+
"dependencies": {
|
|
59
|
+
"@workos-inc/node": "^10.7.0",
|
|
60
|
+
"commander": "^13.1.0",
|
|
61
|
+
"stripe": "^20.3.1"
|
|
62
|
+
},
|
|
63
|
+
"peerDependencies": {
|
|
64
|
+
"@modelcontextprotocol/sdk": ">=1.25.0",
|
|
65
|
+
"mcp-handler": ">=1.1.0",
|
|
66
|
+
"zod": "^3.25.0"
|
|
67
|
+
},
|
|
68
|
+
"peerDependenciesMeta": {
|
|
69
|
+
"mcp-handler": {
|
|
70
|
+
"optional": true
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
"devDependencies": {
|
|
74
|
+
"@modelcontextprotocol/sdk": "1.25.2",
|
|
75
|
+
"@types/node": "^20",
|
|
76
|
+
"mcp-handler": "^1.1.0",
|
|
77
|
+
"typescript": "^5",
|
|
78
|
+
"zod": "^3.25.76"
|
|
79
|
+
},
|
|
80
|
+
"main": "./dist/index.js"
|
|
81
|
+
}
|