@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.
Files changed (111) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +243 -0
  3. package/dist/adapters/workos-org.d.ts +80 -0
  4. package/dist/adapters/workos-org.d.ts.map +1 -0
  5. package/dist/adapters/workos-org.js +176 -0
  6. package/dist/adapters/workos-org.js.map +1 -0
  7. package/dist/agent-auth/claim-store.d.ts +37 -0
  8. package/dist/agent-auth/claim-store.d.ts.map +1 -0
  9. package/dist/agent-auth/claim-store.js +64 -0
  10. package/dist/agent-auth/claim-store.js.map +1 -0
  11. package/dist/agent-auth/index.d.ts +65 -0
  12. package/dist/agent-auth/index.d.ts.map +1 -0
  13. package/dist/agent-auth/index.js +365 -0
  14. package/dist/agent-auth/index.js.map +1 -0
  15. package/dist/auth.d.ts +16 -0
  16. package/dist/auth.d.ts.map +1 -0
  17. package/dist/auth.js +80 -0
  18. package/dist/auth.js.map +1 -0
  19. package/dist/billing.d.ts +59 -0
  20. package/dist/billing.d.ts.map +1 -0
  21. package/dist/billing.js +258 -0
  22. package/dist/billing.js.map +1 -0
  23. package/dist/cli/client.d.ts +10 -0
  24. package/dist/cli/client.d.ts.map +1 -0
  25. package/dist/cli/client.js +22 -0
  26. package/dist/cli/client.js.map +1 -0
  27. package/dist/cli/commands.d.ts +4 -0
  28. package/dist/cli/commands.d.ts.map +1 -0
  29. package/dist/cli/commands.js +94 -0
  30. package/dist/cli/commands.js.map +1 -0
  31. package/dist/cli/config.d.ts +16 -0
  32. package/dist/cli/config.d.ts.map +1 -0
  33. package/dist/cli/config.js +40 -0
  34. package/dist/cli/config.js.map +1 -0
  35. package/dist/create-billing.d.ts +78 -0
  36. package/dist/create-billing.d.ts.map +1 -0
  37. package/dist/create-billing.js +59 -0
  38. package/dist/create-billing.js.map +1 -0
  39. package/dist/dispatch.d.ts +9 -0
  40. package/dist/dispatch.d.ts.map +1 -0
  41. package/dist/dispatch.js +73 -0
  42. package/dist/dispatch.js.map +1 -0
  43. package/dist/events.d.ts +26 -0
  44. package/dist/events.d.ts.map +1 -0
  45. package/dist/events.js +72 -0
  46. package/dist/events.js.map +1 -0
  47. package/dist/index.d.ts +24 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +40 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/invitations.d.ts +56 -0
  52. package/dist/invitations.d.ts.map +1 -0
  53. package/dist/invitations.js +117 -0
  54. package/dist/invitations.js.map +1 -0
  55. package/dist/machine-payment/index.d.ts +57 -0
  56. package/dist/machine-payment/index.d.ts.map +1 -0
  57. package/dist/machine-payment/index.js +117 -0
  58. package/dist/machine-payment/index.js.map +1 -0
  59. package/dist/magic-auth.d.ts +4 -0
  60. package/dist/magic-auth.d.ts.map +1 -0
  61. package/dist/magic-auth.js +30 -0
  62. package/dist/magic-auth.js.map +1 -0
  63. package/dist/mirror.d.ts +35 -0
  64. package/dist/mirror.d.ts.map +1 -0
  65. package/dist/mirror.js +63 -0
  66. package/dist/mirror.js.map +1 -0
  67. package/dist/plans.d.ts +38 -0
  68. package/dist/plans.d.ts.map +1 -0
  69. package/dist/plans.js +132 -0
  70. package/dist/plans.js.map +1 -0
  71. package/dist/routes/mcp.d.ts +19 -0
  72. package/dist/routes/mcp.d.ts.map +1 -0
  73. package/dist/routes/mcp.js +39 -0
  74. package/dist/routes/mcp.js.map +1 -0
  75. package/dist/routes/rest.d.ts +20 -0
  76. package/dist/routes/rest.d.ts.map +1 -0
  77. package/dist/routes/rest.js +66 -0
  78. package/dist/routes/rest.js.map +1 -0
  79. package/dist/routes/webhook.d.ts +8 -0
  80. package/dist/routes/webhook.d.ts.map +1 -0
  81. package/dist/routes/webhook.js +39 -0
  82. package/dist/routes/webhook.js.map +1 -0
  83. package/dist/sync.d.ts +58 -0
  84. package/dist/sync.d.ts.map +1 -0
  85. package/dist/sync.js +202 -0
  86. package/dist/sync.js.map +1 -0
  87. package/dist/tools/billing.d.ts +4 -0
  88. package/dist/tools/billing.d.ts.map +1 -0
  89. package/dist/tools/billing.js +125 -0
  90. package/dist/tools/billing.js.map +1 -0
  91. package/dist/tools/keys.d.ts +4 -0
  92. package/dist/tools/keys.d.ts.map +1 -0
  93. package/dist/tools/keys.js +107 -0
  94. package/dist/tools/keys.js.map +1 -0
  95. package/dist/tools/register.d.ts +20 -0
  96. package/dist/tools/register.d.ts.map +1 -0
  97. package/dist/tools/register.js +87 -0
  98. package/dist/tools/register.js.map +1 -0
  99. package/dist/types.d.ts +90 -0
  100. package/dist/types.d.ts.map +1 -0
  101. package/dist/types.js +28 -0
  102. package/dist/types.js.map +1 -0
  103. package/dist/util/clearout.d.ts +5 -0
  104. package/dist/util/clearout.d.ts.map +1 -0
  105. package/dist/util/clearout.js +18 -0
  106. package/dist/util/clearout.js.map +1 -0
  107. package/dist/workos.d.ts +6 -0
  108. package/dist/workos.d.ts.map +1 -0
  109. package/dist/workos.js +24 -0
  110. package/dist/workos.js.map +1 -0
  111. 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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"}
@@ -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,5 @@
1
+ export declare function lookupCompany(domain: string): Promise<{
2
+ name: string;
3
+ logoUrl: string;
4
+ } | null>;
5
+ //# sourceMappingURL=clearout.d.ts.map
@@ -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"}
@@ -0,0 +1,6 @@
1
+ import { WorkOS } from "@workos-inc/node";
2
+ export declare function getWorkOS(opts?: {
3
+ apiKey?: string;
4
+ clientId?: string;
5
+ }): WorkOS;
6
+ //# sourceMappingURL=workos.d.ts.map
@@ -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
+ }