@kernhq/module-billing 0.2.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 +662 -0
- package/dist/contract.d.ts +965 -0
- package/dist/contract.d.ts.map +1 -0
- package/dist/contract.js +265 -0
- package/dist/contract.js.map +1 -0
- package/dist/server/index.d.ts +11 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +165 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/router.d.ts +697 -0
- package/dist/server/router.d.ts.map +1 -0
- package/dist/server/router.js +126 -0
- package/dist/server/router.js.map +1 -0
- package/dist/server/schema.d.ts +1030 -0
- package/dist/server/schema.d.ts.map +1 -0
- package/dist/server/schema.js +137 -0
- package/dist/server/schema.js.map +1 -0
- package/dist/server/services/entitlements.d.ts +3 -0
- package/dist/server/services/entitlements.d.ts.map +1 -0
- package/dist/server/services/entitlements.js +68 -0
- package/dist/server/services/entitlements.js.map +1 -0
- package/dist/server/services/plans.d.ts +20 -0
- package/dist/server/services/plans.d.ts.map +1 -0
- package/dist/server/services/plans.js +122 -0
- package/dist/server/services/plans.js.map +1 -0
- package/dist/server/services/stripe.d.ts +42 -0
- package/dist/server/services/stripe.d.ts.map +1 -0
- package/dist/server/services/stripe.js +267 -0
- package/dist/server/services/stripe.js.map +1 -0
- package/dist/server/services/subscriptions.d.ts +35 -0
- package/dist/server/services/subscriptions.d.ts.map +1 -0
- package/dist/server/services/subscriptions.js +193 -0
- package/dist/server/services/subscriptions.js.map +1 -0
- package/dist/server/services/usage.d.ts +40 -0
- package/dist/server/services/usage.d.ts.map +1 -0
- package/dist/server/services/usage.js +98 -0
- package/dist/server/services/usage.js.map +1 -0
- package/migrations/0000_init.sql +82 -0
- package/migrations/0001_rls.sql +18 -0
- package/migrations/meta/0000_snapshot.json +580 -0
- package/migrations/meta/_journal.json +20 -0
- package/package.json +73 -0
- package/src/client/api.ts +15 -0
- package/src/client/format.test.ts +64 -0
- package/src/client/index.ts +81 -0
- package/src/contract.ts +311 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/server/router.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAgC,MAAM,gBAAgB,CAAA;AAgC1E,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsH3C"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { o, requires, workspaceScoped } from '@kernhq/kernel';
|
|
2
|
+
import { implement, ORPCError } from '@orpc/server';
|
|
3
|
+
import { BILLING_PERMISSIONS, billingContract, billingEvents, MODULE_ID, PlanLimits } from '../contract.js';
|
|
4
|
+
import * as entitlements from './services/entitlements.js';
|
|
5
|
+
import * as plansSvc from './services/plans.js';
|
|
6
|
+
import * as stripeSvc from './services/stripe.js';
|
|
7
|
+
import * as subsSvc from './services/subscriptions.js';
|
|
8
|
+
import * as usageSvc from './services/usage.js';
|
|
9
|
+
const os = implement(billingContract).$context();
|
|
10
|
+
/**
|
|
11
|
+
* The instance console's audience.
|
|
12
|
+
*
|
|
13
|
+
* Not `workspaceScoped`: these procedures deliberately cross workspaces, which is the whole point of
|
|
14
|
+
* an operator screen. Membership therefore proves nothing here and the instance-admin flag is the
|
|
15
|
+
* only thing that does.
|
|
16
|
+
*/
|
|
17
|
+
const instanceAdmin = o.middleware(async ({ context, next }) => {
|
|
18
|
+
const { principal } = context;
|
|
19
|
+
if (principal.kind === 'anonymous')
|
|
20
|
+
throw new ORPCError('UNAUTHORIZED');
|
|
21
|
+
if (!principal.instanceAdmin && principal.kind !== 'service')
|
|
22
|
+
throw new ORPCError('FORBIDDEN', { message: 'Instance administrators only' });
|
|
23
|
+
return next();
|
|
24
|
+
});
|
|
25
|
+
/** Any signed-in principal — enough to be shown what the plans cost. */
|
|
26
|
+
const signedIn = o.middleware(async ({ context, next }) => {
|
|
27
|
+
if (context.principal.kind === 'anonymous')
|
|
28
|
+
throw new ORPCError('UNAUTHORIZED');
|
|
29
|
+
return next();
|
|
30
|
+
});
|
|
31
|
+
export function billingRouter(kernel) {
|
|
32
|
+
const scoped = os.use(workspaceScoped(MODULE_ID));
|
|
33
|
+
return os.router({
|
|
34
|
+
plans: {
|
|
35
|
+
list: os.plans.list.use(signedIn).handler(async ({ input, context }) => {
|
|
36
|
+
// an unpublished plan is a draft, and a draft is the operator's business
|
|
37
|
+
if (input.includeUnpublished &&
|
|
38
|
+
!context.principal.instanceAdmin &&
|
|
39
|
+
context.principal.kind !== 'service')
|
|
40
|
+
throw new ORPCError('FORBIDDEN', { message: 'Instance administrators only' });
|
|
41
|
+
return plansSvc.list(kernel, input.includeUnpublished);
|
|
42
|
+
}),
|
|
43
|
+
// No middleware at all: this is what a marketing site reads, and it has no session.
|
|
44
|
+
public: os.plans.public.handler(async () => plansSvc.publicList(kernel)),
|
|
45
|
+
upsert: os.plans.upsert.use(instanceAdmin).handler(async ({ input }) => {
|
|
46
|
+
const plan = await plansSvc.upsert(kernel, input);
|
|
47
|
+
await kernel.emit(billingEvents.catalogueChanged, { planSlug: plan.slug });
|
|
48
|
+
return plan;
|
|
49
|
+
}),
|
|
50
|
+
setPublished: os.plans.setPublished.use(instanceAdmin).handler(async ({ input }) => {
|
|
51
|
+
const plan = await plansSvc.setPublished(kernel, input.id, input.published);
|
|
52
|
+
// what the marketing site shows has changed; whoever rebuilds it listens for this
|
|
53
|
+
await kernel.emit(billingEvents.catalogueChanged, { planSlug: plan.slug });
|
|
54
|
+
return plan;
|
|
55
|
+
}),
|
|
56
|
+
archive: os.plans.archive.use(instanceAdmin).handler(async ({ input }) => {
|
|
57
|
+
await plansSvc.archive(kernel, input.id);
|
|
58
|
+
return { ok: true };
|
|
59
|
+
}),
|
|
60
|
+
},
|
|
61
|
+
subscription: {
|
|
62
|
+
get: scoped.subscription.get.use(requires(BILLING_PERMISSIONS.view)).handler(async ({ input }) => {
|
|
63
|
+
const [subscription, used, limits] = await Promise.all([
|
|
64
|
+
subsSvc.get(kernel, input.workspaceId),
|
|
65
|
+
usageSvc.read(kernel, input.workspaceId),
|
|
66
|
+
entitlements.resolve(kernel, input.workspaceId),
|
|
67
|
+
]);
|
|
68
|
+
return {
|
|
69
|
+
subscription,
|
|
70
|
+
usage: {
|
|
71
|
+
seats: used.seats,
|
|
72
|
+
storageBytes: used.storageBytes,
|
|
73
|
+
updatedAt: used.updatedAt.toISOString(),
|
|
74
|
+
},
|
|
75
|
+
limits: PlanLimits.parse(limits),
|
|
76
|
+
active: limits.active ?? true,
|
|
77
|
+
paymentsEnabled: stripeSvc.paymentsEnabled(),
|
|
78
|
+
};
|
|
79
|
+
}),
|
|
80
|
+
invoices: scoped.subscription.invoices
|
|
81
|
+
.use(requires(BILLING_PERMISSIONS.view))
|
|
82
|
+
.handler(async ({ input }) => ({
|
|
83
|
+
items: await subsSvc.listInvoices(kernel, input.workspaceId, input.limit),
|
|
84
|
+
nextCursor: null,
|
|
85
|
+
})),
|
|
86
|
+
checkout: scoped.subscription.checkout
|
|
87
|
+
.use(requires(BILLING_PERMISSIONS.manage))
|
|
88
|
+
.handler(async ({ input, context }) => stripeSvc.checkout(kernel, {
|
|
89
|
+
workspaceId: input.workspaceId,
|
|
90
|
+
planSlug: input.planSlug,
|
|
91
|
+
seats: input.seats,
|
|
92
|
+
email: context.principal.email ?? undefined,
|
|
93
|
+
baseUrl: kernel.env.KERN_BASE_URL,
|
|
94
|
+
})),
|
|
95
|
+
portal: scoped.subscription.portal
|
|
96
|
+
.use(requires(BILLING_PERMISSIONS.manage))
|
|
97
|
+
.handler(async ({ input }) => stripeSvc.portal(kernel, {
|
|
98
|
+
workspaceId: input.workspaceId,
|
|
99
|
+
returnUrl: `${kernel.env.KERN_BASE_URL.replace(/\/$/, '')}${input.returnPath}`,
|
|
100
|
+
})),
|
|
101
|
+
},
|
|
102
|
+
admin: {
|
|
103
|
+
workspaces: os.admin.workspaces.use(instanceAdmin).handler(async ({ input }) => ({
|
|
104
|
+
items: await subsSvc.adminList(kernel, {
|
|
105
|
+
q: input.q,
|
|
106
|
+
status: input.status,
|
|
107
|
+
limit: input.limit,
|
|
108
|
+
}),
|
|
109
|
+
nextCursor: null,
|
|
110
|
+
})),
|
|
111
|
+
setPlan: os.admin.setPlan
|
|
112
|
+
.use(instanceAdmin)
|
|
113
|
+
.handler(async ({ input }) => subsSvc.setPlan(kernel, input.workspaceId, input.planId, input.seatsPurchased)),
|
|
114
|
+
override: os.admin.override
|
|
115
|
+
.use(instanceAdmin)
|
|
116
|
+
.handler(async ({ input, context }) => subsSvc.setOverride(kernel, input.workspaceId, input.limits, context.principal.userId ?? null)),
|
|
117
|
+
extendTrial: os.admin.extendTrial
|
|
118
|
+
.use(instanceAdmin)
|
|
119
|
+
.handler(async ({ input }) => subsSvc.extendTrial(kernel, input.workspaceId, input.days)),
|
|
120
|
+
setStatus: os.admin.setStatus
|
|
121
|
+
.use(instanceAdmin)
|
|
122
|
+
.handler(async ({ input }) => subsSvc.setStatus(kernel, input.workspaceId, input.status)),
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/server/router.ts"],"names":[],"mappings":"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"}
|