paykitjs 0.0.1-alpha.1
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/dist/_virtual/_rolldown/runtime.js +14 -0
- package/dist/api/define-route.d.ts +94 -0
- package/dist/api/define-route.js +153 -0
- package/dist/api/methods.d.ts +422 -0
- package/dist/api/methods.js +67 -0
- package/dist/cli/commands/init.js +264 -0
- package/dist/cli/commands/push.js +71 -0
- package/dist/cli/commands/status.js +84 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +45 -0
- package/dist/cli/templates/index.js +64 -0
- package/dist/cli/utils/detect.js +73 -0
- package/dist/cli/utils/format.js +58 -0
- package/dist/cli/utils/get-config.js +117 -0
- package/dist/cli/utils/shared.js +81 -0
- package/dist/cli/utils/telemetry.js +63 -0
- package/dist/client/index.d.ts +25 -0
- package/dist/client/index.js +27 -0
- package/dist/core/context.d.ts +17 -0
- package/dist/core/context.js +23 -0
- package/dist/core/create-paykit.d.ts +7 -0
- package/dist/core/create-paykit.js +67 -0
- package/dist/core/error-codes.d.ts +12 -0
- package/dist/core/error-codes.js +10 -0
- package/dist/core/errors.d.ts +41 -0
- package/dist/core/errors.js +47 -0
- package/dist/core/logger.d.ts +11 -0
- package/dist/core/logger.js +51 -0
- package/dist/core/utils.js +21 -0
- package/dist/customer/customer.api.js +47 -0
- package/dist/customer/customer.service.js +342 -0
- package/dist/customer/customer.types.d.ts +31 -0
- package/dist/database/index.d.ts +8 -0
- package/dist/database/index.js +32 -0
- package/dist/database/migrations/0000_init.sql +157 -0
- package/dist/database/migrations/meta/0000_snapshot.json +1222 -0
- package/dist/database/migrations/meta/_journal.json +13 -0
- package/dist/database/schema.d.ts +1767 -0
- package/dist/database/schema.js +150 -0
- package/dist/entitlement/entitlement.api.js +33 -0
- package/dist/entitlement/entitlement.service.d.ts +17 -0
- package/dist/entitlement/entitlement.service.js +123 -0
- package/dist/handlers/next.d.ts +9 -0
- package/dist/handlers/next.js +9 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +6 -0
- package/dist/invoice/invoice.service.js +54 -0
- package/dist/payment/payment.service.js +49 -0
- package/dist/payment-method/payment-method.service.js +78 -0
- package/dist/product/product-sync.service.js +111 -0
- package/dist/product/product.service.js +127 -0
- package/dist/providers/provider.d.ts +159 -0
- package/dist/providers/stripe.js +547 -0
- package/dist/subscription/subscription.api.js +24 -0
- package/dist/subscription/subscription.service.js +896 -0
- package/dist/subscription/subscription.types.d.ts +18 -0
- package/dist/subscription/subscription.types.js +11 -0
- package/dist/testing/testing.api.js +29 -0
- package/dist/testing/testing.service.js +49 -0
- package/dist/types/events.d.ts +181 -0
- package/dist/types/instance.d.ts +88 -0
- package/dist/types/models.d.ts +11 -0
- package/dist/types/options.d.ts +32 -0
- package/dist/types/plugin.d.ts +11 -0
- package/dist/types/schema.d.ts +99 -0
- package/dist/types/schema.js +192 -0
- package/dist/utilities/dependencies/check-dependencies.js +16 -0
- package/dist/utilities/dependencies/get-dependencies.js +68 -0
- package/dist/utilities/dependencies/index.js +8 -0
- package/dist/utilities/dependencies/paykit-package-list.js +8 -0
- package/dist/webhook/webhook.api.js +29 -0
- package/dist/webhook/webhook.service.js +143 -0
- package/package.json +76 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
//#region src/subscription/subscription.types.d.ts
|
|
2
|
+
interface SubscribeResult {
|
|
3
|
+
invoice?: {
|
|
4
|
+
currency: string;
|
|
5
|
+
hostedUrl: string | null;
|
|
6
|
+
providerInvoiceId: string;
|
|
7
|
+
status: string | null;
|
|
8
|
+
totalAmount: number;
|
|
9
|
+
};
|
|
10
|
+
paymentUrl: string | null;
|
|
11
|
+
requiredAction?: {
|
|
12
|
+
clientSecret?: string;
|
|
13
|
+
paymentIntentId?: string;
|
|
14
|
+
type: string;
|
|
15
|
+
} | null;
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
export { SubscribeResult };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { returnUrl } from "../api/define-route.js";
|
|
2
|
+
import * as z from "zod";
|
|
3
|
+
//#region src/subscription/subscription.types.ts
|
|
4
|
+
const subscribeBodySchema = z.object({
|
|
5
|
+
planId: z.string(),
|
|
6
|
+
forceCheckout: z.boolean().optional(),
|
|
7
|
+
successUrl: returnUrl(),
|
|
8
|
+
cancelUrl: returnUrl().optional()
|
|
9
|
+
});
|
|
10
|
+
//#endregion
|
|
11
|
+
export { subscribeBodySchema };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { definePayKitMethod } from "../api/define-route.js";
|
|
2
|
+
import { advanceCustomerTestClock, getCustomerTestClock } from "./testing.service.js";
|
|
3
|
+
import * as z from "zod";
|
|
4
|
+
//#region src/testing/testing.api.ts
|
|
5
|
+
const customerTestClockSchema = z.object({});
|
|
6
|
+
const advanceCustomerTestClockSchema = z.object({ frozenTime: z.coerce.date() });
|
|
7
|
+
const getTestClock = definePayKitMethod({
|
|
8
|
+
input: customerTestClockSchema,
|
|
9
|
+
requireCustomer: true,
|
|
10
|
+
route: {
|
|
11
|
+
client: true,
|
|
12
|
+
method: "POST",
|
|
13
|
+
path: "/get-test-clock"
|
|
14
|
+
}
|
|
15
|
+
}, async (ctx) => getCustomerTestClock(ctx.paykit, ctx.customer.id));
|
|
16
|
+
const advanceTestClock = definePayKitMethod({
|
|
17
|
+
input: advanceCustomerTestClockSchema,
|
|
18
|
+
requireCustomer: true,
|
|
19
|
+
route: {
|
|
20
|
+
client: true,
|
|
21
|
+
method: "POST",
|
|
22
|
+
path: "/advance-test-clock"
|
|
23
|
+
}
|
|
24
|
+
}, async (ctx) => advanceCustomerTestClock(ctx.paykit, {
|
|
25
|
+
customerId: ctx.customer.id,
|
|
26
|
+
frozenTime: ctx.input.frozenTime
|
|
27
|
+
}));
|
|
28
|
+
//#endregion
|
|
29
|
+
export { advanceTestClock, getTestClock };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { PAYKIT_ERROR_CODES, PayKitError } from "../core/errors.js";
|
|
2
|
+
import { getCustomerByIdOrThrow, getProviderCustomer, setProviderCustomer } from "../customer/customer.service.js";
|
|
3
|
+
//#region src/testing/testing.service.ts
|
|
4
|
+
function assertTestingEnabled(ctx) {
|
|
5
|
+
if (ctx.options.testing?.enabled !== true) throw PayKitError.from("BAD_REQUEST", PAYKIT_ERROR_CODES.TESTING_NOT_ENABLED);
|
|
6
|
+
}
|
|
7
|
+
async function getCustomerTestClock(ctx, customerId) {
|
|
8
|
+
assertTestingEnabled(ctx);
|
|
9
|
+
const providerCustomer = getProviderCustomer(await getCustomerByIdOrThrow(ctx.database, customerId), ctx.provider.id);
|
|
10
|
+
if (!providerCustomer) throw PayKitError.from("NOT_FOUND", PAYKIT_ERROR_CODES.PROVIDER_CUSTOMER_NOT_FOUND);
|
|
11
|
+
if (!providerCustomer.testClockId) throw PayKitError.from("NOT_FOUND", PAYKIT_ERROR_CODES.TEST_CLOCK_NOT_FOUND);
|
|
12
|
+
const testClock = await ctx.stripe.getTestClock({ testClockId: providerCustomer.testClockId });
|
|
13
|
+
await setProviderCustomer(ctx.database, {
|
|
14
|
+
customerId,
|
|
15
|
+
providerCustomer: {
|
|
16
|
+
...providerCustomer,
|
|
17
|
+
frozenTime: testClock.frozenTime.toISOString()
|
|
18
|
+
},
|
|
19
|
+
providerId: ctx.provider.id
|
|
20
|
+
});
|
|
21
|
+
return testClock;
|
|
22
|
+
}
|
|
23
|
+
function getCustomerCurrentTime(ctx, customer) {
|
|
24
|
+
if (ctx.options.testing?.enabled !== true) return /* @__PURE__ */ new Date();
|
|
25
|
+
const providerCustomer = getProviderCustomer(customer, ctx.provider.id);
|
|
26
|
+
if (!providerCustomer?.frozenTime) return /* @__PURE__ */ new Date();
|
|
27
|
+
return new Date(providerCustomer.frozenTime);
|
|
28
|
+
}
|
|
29
|
+
async function advanceCustomerTestClock(ctx, input) {
|
|
30
|
+
assertTestingEnabled(ctx);
|
|
31
|
+
const providerCustomer = getProviderCustomer(await getCustomerByIdOrThrow(ctx.database, input.customerId), ctx.provider.id);
|
|
32
|
+
if (!providerCustomer) throw PayKitError.from("NOT_FOUND", PAYKIT_ERROR_CODES.PROVIDER_CUSTOMER_NOT_FOUND);
|
|
33
|
+
if (!providerCustomer.testClockId) throw PayKitError.from("NOT_FOUND", PAYKIT_ERROR_CODES.TEST_CLOCK_NOT_FOUND);
|
|
34
|
+
const testClock = await ctx.stripe.advanceTestClock({
|
|
35
|
+
frozenTime: input.frozenTime,
|
|
36
|
+
testClockId: providerCustomer.testClockId
|
|
37
|
+
});
|
|
38
|
+
await setProviderCustomer(ctx.database, {
|
|
39
|
+
customerId: input.customerId,
|
|
40
|
+
providerCustomer: {
|
|
41
|
+
...providerCustomer,
|
|
42
|
+
frozenTime: testClock.frozenTime.toISOString()
|
|
43
|
+
},
|
|
44
|
+
providerId: ctx.provider.id
|
|
45
|
+
});
|
|
46
|
+
return testClock;
|
|
47
|
+
}
|
|
48
|
+
//#endregion
|
|
49
|
+
export { advanceCustomerTestClock, getCustomerCurrentTime, getCustomerTestClock };
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
//#region src/types/events.d.ts
|
|
2
|
+
interface NormalizedPaymentMethod {
|
|
3
|
+
expiryMonth?: number;
|
|
4
|
+
expiryYear?: number;
|
|
5
|
+
isDefault?: boolean;
|
|
6
|
+
last4?: string;
|
|
7
|
+
providerMethodId: string;
|
|
8
|
+
type: string;
|
|
9
|
+
}
|
|
10
|
+
interface NormalizedPayment {
|
|
11
|
+
amount: number;
|
|
12
|
+
createdAt: Date;
|
|
13
|
+
currency: string;
|
|
14
|
+
description?: string | null;
|
|
15
|
+
metadata?: Record<string, string>;
|
|
16
|
+
providerMethodId?: string | null;
|
|
17
|
+
providerPaymentId: string;
|
|
18
|
+
status: string;
|
|
19
|
+
}
|
|
20
|
+
interface NormalizedSubscription {
|
|
21
|
+
cancelAtPeriodEnd: boolean;
|
|
22
|
+
canceledAt?: Date | null;
|
|
23
|
+
currentPeriodEndAt?: Date | null;
|
|
24
|
+
currentPeriodStartAt?: Date | null;
|
|
25
|
+
endedAt?: Date | null;
|
|
26
|
+
providerPriceId?: string | null;
|
|
27
|
+
providerSubscriptionId: string;
|
|
28
|
+
providerSubscriptionScheduleId?: string | null;
|
|
29
|
+
status: string;
|
|
30
|
+
}
|
|
31
|
+
interface NormalizedInvoice {
|
|
32
|
+
currency: string;
|
|
33
|
+
hostedUrl?: string | null;
|
|
34
|
+
periodEndAt?: Date | null;
|
|
35
|
+
periodStartAt?: Date | null;
|
|
36
|
+
providerInvoiceId: string;
|
|
37
|
+
status: string | null;
|
|
38
|
+
totalAmount: number;
|
|
39
|
+
}
|
|
40
|
+
interface CheckoutCompletedSubscription extends NormalizedSubscription {}
|
|
41
|
+
interface CheckoutCompletedInvoice extends NormalizedInvoice {}
|
|
42
|
+
interface UpsertCustomerAction {
|
|
43
|
+
type: "customer.upsert";
|
|
44
|
+
data: {
|
|
45
|
+
id: string;
|
|
46
|
+
email?: string;
|
|
47
|
+
name?: string;
|
|
48
|
+
metadata?: Record<string, string>;
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
interface DeleteCustomerAction {
|
|
52
|
+
type: "customer.delete";
|
|
53
|
+
data: {
|
|
54
|
+
id: string;
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
interface UpsertPaymentMethodAction {
|
|
58
|
+
type: "payment_method.upsert";
|
|
59
|
+
data: {
|
|
60
|
+
paymentMethod: NormalizedPaymentMethod;
|
|
61
|
+
providerCustomerId: string;
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
interface DeletePaymentMethodAction {
|
|
65
|
+
type: "payment_method.delete";
|
|
66
|
+
data: {
|
|
67
|
+
providerMethodId: string;
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
interface UpsertPaymentAction {
|
|
71
|
+
type: "payment.upsert";
|
|
72
|
+
data: {
|
|
73
|
+
payment: NormalizedPayment;
|
|
74
|
+
providerCustomerId: string;
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
interface UpsertSubscriptionAction {
|
|
78
|
+
type: "subscription.upsert";
|
|
79
|
+
data: {
|
|
80
|
+
providerCustomerId: string;
|
|
81
|
+
subscription: NormalizedSubscription;
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
interface DeleteSubscriptionAction {
|
|
85
|
+
type: "subscription.delete";
|
|
86
|
+
data: {
|
|
87
|
+
providerCustomerId: string;
|
|
88
|
+
providerSubscriptionId: string;
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
interface UpsertInvoiceAction {
|
|
92
|
+
type: "invoice.upsert";
|
|
93
|
+
data: {
|
|
94
|
+
invoice: NormalizedInvoice;
|
|
95
|
+
providerCustomerId: string;
|
|
96
|
+
providerSubscriptionId?: string | null;
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
type WebhookApplyAction = UpsertCustomerAction | DeleteCustomerAction | UpsertPaymentMethodAction | DeletePaymentMethodAction | UpsertPaymentAction | UpsertSubscriptionAction | DeleteSubscriptionAction | UpsertInvoiceAction;
|
|
100
|
+
type EventByName<TEventMap extends object, TName extends keyof TEventMap> = {
|
|
101
|
+
name: TName;
|
|
102
|
+
payload: TEventMap[TName];
|
|
103
|
+
};
|
|
104
|
+
interface NormalizedWebhookEventMap {
|
|
105
|
+
"checkout.completed": {
|
|
106
|
+
checkoutSessionId: string;
|
|
107
|
+
invoice?: CheckoutCompletedInvoice;
|
|
108
|
+
metadata?: Record<string, string>;
|
|
109
|
+
mode?: "payment" | "setup" | "subscription";
|
|
110
|
+
providerInvoiceId?: string;
|
|
111
|
+
providerSubscriptionId?: string;
|
|
112
|
+
paymentStatus: string | null;
|
|
113
|
+
providerCustomerId: string;
|
|
114
|
+
providerEventId?: string;
|
|
115
|
+
status: string | null;
|
|
116
|
+
subscription?: CheckoutCompletedSubscription;
|
|
117
|
+
};
|
|
118
|
+
"payment_method.attached": {
|
|
119
|
+
paymentMethod: NormalizedPaymentMethod;
|
|
120
|
+
providerCustomerId: string;
|
|
121
|
+
providerEventId?: string;
|
|
122
|
+
};
|
|
123
|
+
"payment.succeeded": {
|
|
124
|
+
payment: NormalizedPayment;
|
|
125
|
+
providerCustomerId: string;
|
|
126
|
+
providerEventId?: string;
|
|
127
|
+
};
|
|
128
|
+
"subscription.updated": {
|
|
129
|
+
providerCustomerId: string;
|
|
130
|
+
providerEventId?: string;
|
|
131
|
+
subscription: NormalizedSubscription;
|
|
132
|
+
};
|
|
133
|
+
"subscription.deleted": {
|
|
134
|
+
providerCustomerId: string;
|
|
135
|
+
providerEventId?: string;
|
|
136
|
+
providerSubscriptionId: string;
|
|
137
|
+
};
|
|
138
|
+
"invoice.updated": {
|
|
139
|
+
invoice: NormalizedInvoice;
|
|
140
|
+
providerCustomerId: string;
|
|
141
|
+
providerEventId?: string;
|
|
142
|
+
providerSubscriptionId?: string | null;
|
|
143
|
+
};
|
|
144
|
+
"payment_method.detached": {
|
|
145
|
+
providerEventId?: string;
|
|
146
|
+
providerMethodId: string;
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
type NormalizedWebhookEventName = keyof NormalizedWebhookEventMap;
|
|
150
|
+
type AnyNormalizedWebhookEvent = { [TName in NormalizedWebhookEventName]: EventByName<NormalizedWebhookEventMap, TName> & {
|
|
151
|
+
actions?: WebhookApplyAction[];
|
|
152
|
+
} }[NormalizedWebhookEventName];
|
|
153
|
+
type NormalizedWebhookEvent<TName extends NormalizedWebhookEventName = NormalizedWebhookEventName> = Extract<AnyNormalizedWebhookEvent, {
|
|
154
|
+
name: TName;
|
|
155
|
+
}>;
|
|
156
|
+
interface PayKitEventMap {
|
|
157
|
+
"customer.updated": {
|
|
158
|
+
customerId: string;
|
|
159
|
+
subscriptions: readonly {
|
|
160
|
+
currentPeriodEndAt: Date | null;
|
|
161
|
+
endedAt: Date | null;
|
|
162
|
+
id: string;
|
|
163
|
+
startedAt: Date | null;
|
|
164
|
+
status: string;
|
|
165
|
+
}[];
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
type PayKitEventName = keyof PayKitEventMap;
|
|
169
|
+
type PayKitEventHandlers = { [TName in PayKitEventName]?: (event: {
|
|
170
|
+
name: TName;
|
|
171
|
+
payload: PayKitEventMap[TName];
|
|
172
|
+
}) => Promise<void> | void } & {
|
|
173
|
+
"*"?: (input: {
|
|
174
|
+
event: {
|
|
175
|
+
name: PayKitEventName;
|
|
176
|
+
payload: PayKitEventMap[PayKitEventName];
|
|
177
|
+
};
|
|
178
|
+
}) => Promise<void> | void;
|
|
179
|
+
};
|
|
180
|
+
//#endregion
|
|
181
|
+
export { NormalizedInvoice, NormalizedPayment, NormalizedPaymentMethod, NormalizedSubscription, NormalizedWebhookEvent, NormalizedWebhookEventMap, NormalizedWebhookEventName, PayKitEventHandlers, PayKitEventMap, PayKitEventName, WebhookApplyAction };
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { FeatureIdFromPlans, PlanIdFromPlans } from "./schema.js";
|
|
2
|
+
import { PayKitOptions } from "./options.js";
|
|
3
|
+
import { PayKitContext } from "../core/context.js";
|
|
4
|
+
import { PayKitMethod as PayKitMethod$1 } from "../api/define-route.js";
|
|
5
|
+
import { CustomerEntitlement, CustomerSubscription, CustomerWithDetails, ListCustomersResult } from "../customer/customer.types.js";
|
|
6
|
+
import { methods, testingMethods } from "../api/methods.js";
|
|
7
|
+
|
|
8
|
+
//#region src/types/instance.d.ts
|
|
9
|
+
type RegisteredMethods = typeof methods;
|
|
10
|
+
type RegisteredMethodKey = keyof RegisteredMethods;
|
|
11
|
+
type RegisteredTestingMethodKey = keyof typeof testingMethods;
|
|
12
|
+
type PlanIdFromOptions<TOptions extends PayKitOptions> = [PlanIdFromPlans<TOptions["plans"]>] extends [never] ? string : PlanIdFromPlans<TOptions["plans"]>;
|
|
13
|
+
type FeatureIdFromOptions<TOptions extends PayKitOptions> = [FeatureIdFromPlans<TOptions["plans"]>] extends [never] ? string : FeatureIdFromPlans<TOptions["plans"]>;
|
|
14
|
+
type InferMethodInput<TMethod> = TMethod extends PayKitMethod$1<infer TInput, unknown> ? TInput : never;
|
|
15
|
+
type InferMethodResult<TMethod> = TMethod extends PayKitMethod$1<infer _TInput, infer TResult> ? TResult : never;
|
|
16
|
+
type InferMethodPath<TMethod> = TMethod extends {
|
|
17
|
+
endpoint: {
|
|
18
|
+
path: infer TPath extends string;
|
|
19
|
+
};
|
|
20
|
+
} ? TPath : never;
|
|
21
|
+
type OmitCustomerId<TInput> = TInput extends undefined ? undefined : TInput extends object ? Omit<TInput, "customerId"> : TInput;
|
|
22
|
+
type RefineServerMethodInput<TOptions extends PayKitOptions, TKey extends RegisteredMethodKey, TInput> = TKey extends "subscribe" ? TInput extends {
|
|
23
|
+
cancelUrl?: string;
|
|
24
|
+
forceCheckout?: boolean;
|
|
25
|
+
successUrl?: string;
|
|
26
|
+
} ? TInput & {
|
|
27
|
+
customerId: string;
|
|
28
|
+
planId: PlanIdFromOptions<TOptions>;
|
|
29
|
+
successUrl: string;
|
|
30
|
+
} : TInput : TKey extends "check" | "report" ? TInput extends {
|
|
31
|
+
featureId: string;
|
|
32
|
+
} ? Omit<TInput, "featureId"> & {
|
|
33
|
+
featureId: FeatureIdFromOptions<TOptions>;
|
|
34
|
+
} : TInput : TInput;
|
|
35
|
+
type RefineClientMethodInput<TOptions extends PayKitOptions, TKey extends RegisteredMethodKey, TInput> = TKey extends "subscribe" ? OmitCustomerId<TInput> extends {
|
|
36
|
+
cancelUrl?: string;
|
|
37
|
+
forceCheckout?: boolean;
|
|
38
|
+
successUrl?: string;
|
|
39
|
+
} ? Omit<OmitCustomerId<TInput>, "planId"> & {
|
|
40
|
+
planId: PlanIdFromOptions<TOptions>;
|
|
41
|
+
} : OmitCustomerId<TInput> : TKey extends "customerPortal" ? OmitCustomerId<TInput> extends {
|
|
42
|
+
returnUrl: string;
|
|
43
|
+
} ? Omit<OmitCustomerId<TInput>, "returnUrl"> & {
|
|
44
|
+
returnUrl?: string;
|
|
45
|
+
} : OmitCustomerId<TInput> : OmitCustomerId<TInput>;
|
|
46
|
+
type PayKitClientSubscribeInput<TOptions extends PayKitOptions = PayKitOptions> = RefineClientMethodInput<TOptions, "subscribe", InferMethodInput<RegisteredMethods["subscribe"]>>;
|
|
47
|
+
type PayKitSubscribeInput<TOptions extends PayKitOptions = PayKitOptions> = RefineServerMethodInput<TOptions, "subscribe", InferMethodInput<RegisteredMethods["subscribe"]>>;
|
|
48
|
+
type PayKitSubscribeResult = InferMethodResult<RegisteredMethods["subscribe"]>;
|
|
49
|
+
type PayKitClientCustomerPortalInput = RefineClientMethodInput<PayKitOptions, "customerPortal", InferMethodInput<RegisteredMethods["customerPortal"]>>;
|
|
50
|
+
type PayKitCustomerPortalInput = RefineServerMethodInput<PayKitOptions, "customerPortal", InferMethodInput<RegisteredMethods["customerPortal"]>>;
|
|
51
|
+
type PayKitClientGetTestClockInput = RefineClientMethodInput<PayKitOptions, "getTestClock", InferMethodInput<RegisteredMethods["getTestClock"]>>;
|
|
52
|
+
type PayKitGetTestClockInput = RefineServerMethodInput<PayKitOptions, "getTestClock", InferMethodInput<RegisteredMethods["getTestClock"]>>;
|
|
53
|
+
type PayKitClientAdvanceTestClockInput = RefineClientMethodInput<PayKitOptions, "advanceTestClock", InferMethodInput<RegisteredMethods["advanceTestClock"]>>;
|
|
54
|
+
type PayKitAdvanceTestClockInput = RefineServerMethodInput<PayKitOptions, "advanceTestClock", InferMethodInput<RegisteredMethods["advanceTestClock"]>>;
|
|
55
|
+
type PayKitCheckInput<TOptions extends PayKitOptions = PayKitOptions> = RefineServerMethodInput<TOptions, "check", InferMethodInput<RegisteredMethods["check"]>>;
|
|
56
|
+
type PayKitReportInput<TOptions extends PayKitOptions = PayKitOptions> = RefineServerMethodInput<TOptions, "report", InferMethodInput<RegisteredMethods["report"]>>;
|
|
57
|
+
declare const payKitClientApiBrand: unique symbol;
|
|
58
|
+
type PayKitMethod<TInput, TResult> = (input: TInput) => Promise<TResult>;
|
|
59
|
+
type PayKitClientMethod<TPath extends string, TInput, TResult> = ((input: TInput) => Promise<TResult>) & {
|
|
60
|
+
path: TPath;
|
|
61
|
+
options: unknown;
|
|
62
|
+
};
|
|
63
|
+
type TestingEnabled<TOptions extends PayKitOptions> = TOptions["testing"] extends {
|
|
64
|
+
enabled: true;
|
|
65
|
+
} ? true : false;
|
|
66
|
+
type EnabledMethodKeys<TOptions extends PayKitOptions> = TestingEnabled<TOptions> extends true ? RegisteredMethodKey : Exclude<RegisteredMethodKey, RegisteredTestingMethodKey>;
|
|
67
|
+
type ClientMethodKeys = { [K in RegisteredMethodKey]-?: RegisteredMethods[K] extends {
|
|
68
|
+
client: true;
|
|
69
|
+
} ? K : never }[RegisteredMethodKey];
|
|
70
|
+
type EnabledClientMethodKeys<TOptions extends PayKitOptions> = TestingEnabled<TOptions> extends true ? ClientMethodKeys : Exclude<ClientMethodKeys, RegisteredTestingMethodKey>;
|
|
71
|
+
type GeneratePayKitAPI<TOptions extends PayKitOptions> = { [K in EnabledMethodKeys<TOptions>]: PayKitMethod<RefineServerMethodInput<TOptions, K, InferMethodInput<RegisteredMethods[K]>>, InferMethodResult<RegisteredMethods[K]>> };
|
|
72
|
+
type GeneratePayKitClientAPI<TOptions extends PayKitOptions> = { [K in EnabledClientMethodKeys<TOptions>]: PayKitClientMethod<InferMethodPath<RegisteredMethods[K]>, RefineClientMethodInput<TOptions, K, InferMethodInput<RegisteredMethods[K]>>, InferMethodResult<RegisteredMethods[K]>> };
|
|
73
|
+
interface PayKitClientApiCarrier<TClientApi> {
|
|
74
|
+
readonly [payKitClientApiBrand]?: TClientApi;
|
|
75
|
+
}
|
|
76
|
+
type PayKitClientAPI<TOptions extends PayKitOptions = PayKitOptions> = GeneratePayKitClientAPI<TOptions>;
|
|
77
|
+
type PayKitAPI<TOptions extends PayKitOptions = PayKitOptions> = GeneratePayKitAPI<TOptions>;
|
|
78
|
+
type PayKitInstance<TOptions extends PayKitOptions = PayKitOptions> = PayKitAPI<TOptions> & PayKitClientApiCarrier<PayKitClientAPI<TOptions>> & {
|
|
79
|
+
options: TOptions;
|
|
80
|
+
handler: (request: Request) => Promise<Response>;
|
|
81
|
+
$context: Promise<PayKitContext>;
|
|
82
|
+
$infer: {
|
|
83
|
+
planId: PlanIdFromOptions<TOptions>;
|
|
84
|
+
featureId: FeatureIdFromOptions<TOptions>;
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
//#endregion
|
|
88
|
+
export { PayKitAdvanceTestClockInput, PayKitCheckInput, PayKitClientAdvanceTestClockInput, PayKitClientApiCarrier, PayKitClientCustomerPortalInput, PayKitClientGetTestClockInput, PayKitClientSubscribeInput, PayKitCustomerPortalInput, PayKitGetTestClockInput, PayKitInstance, PayKitReportInput, PayKitSubscribeInput, PayKitSubscribeResult };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { customer, feature, invoice, product, productFeature, subscription } from "../database/schema.js";
|
|
2
|
+
|
|
3
|
+
//#region src/types/models.d.ts
|
|
4
|
+
type Customer = typeof customer.$inferSelect;
|
|
5
|
+
type StoredFeature = typeof feature.$inferSelect;
|
|
6
|
+
type StoredProduct = typeof product.$inferSelect;
|
|
7
|
+
type StoredProductFeature = typeof productFeature.$inferSelect;
|
|
8
|
+
type StoredSubscription = typeof subscription.$inferSelect;
|
|
9
|
+
type StoredInvoice = typeof invoice.$inferSelect;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { Customer, StoredFeature, StoredInvoice, StoredProduct, StoredProductFeature, StoredSubscription };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { PayKitEventHandlers } from "./events.js";
|
|
2
|
+
import { StripeProviderConfig } from "../providers/provider.js";
|
|
3
|
+
import { PayKitPlugin } from "./plugin.js";
|
|
4
|
+
import { PayKitPlansModule } from "./schema.js";
|
|
5
|
+
import { Pool } from "pg";
|
|
6
|
+
import { LevelWithSilent, Logger } from "pino";
|
|
7
|
+
|
|
8
|
+
//#region src/types/options.d.ts
|
|
9
|
+
interface PayKitLoggingOptions {
|
|
10
|
+
level?: LevelWithSilent;
|
|
11
|
+
logger?: Logger;
|
|
12
|
+
}
|
|
13
|
+
interface PayKitTestingOptions {
|
|
14
|
+
enabled: true;
|
|
15
|
+
}
|
|
16
|
+
interface PayKitOptions {
|
|
17
|
+
database: Pool | string;
|
|
18
|
+
provider: StripeProviderConfig;
|
|
19
|
+
plans?: PayKitPlansModule;
|
|
20
|
+
basePath?: string;
|
|
21
|
+
identify?: (request: Request) => Promise<{
|
|
22
|
+
customerId: string;
|
|
23
|
+
email?: string;
|
|
24
|
+
name?: string;
|
|
25
|
+
} | null>;
|
|
26
|
+
on?: PayKitEventHandlers;
|
|
27
|
+
plugins?: PayKitPlugin[];
|
|
28
|
+
logging?: PayKitLoggingOptions;
|
|
29
|
+
testing?: PayKitTestingOptions;
|
|
30
|
+
}
|
|
31
|
+
//#endregion
|
|
32
|
+
export { PayKitLoggingOptions, PayKitOptions, PayKitTestingOptions };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/types/plugin.d.ts
|
|
2
|
+
interface PayKitPlugin {
|
|
3
|
+
id: string;
|
|
4
|
+
/**
|
|
5
|
+
* Better-call endpoints to merge into the PayKit router.
|
|
6
|
+
* Paths are relative to the API base path (e.g. "/dash/stats" → "/paykit/api/dash/stats").
|
|
7
|
+
*/
|
|
8
|
+
endpoints?: Record<string, unknown>;
|
|
9
|
+
}
|
|
10
|
+
//#endregion
|
|
11
|
+
export { PayKitPlugin };
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
|
|
3
|
+
//#region src/types/schema.d.ts
|
|
4
|
+
declare const priceSchema: z.ZodObject<{
|
|
5
|
+
amount: z.ZodNumber;
|
|
6
|
+
interval: z.ZodEnum<{
|
|
7
|
+
month: "month";
|
|
8
|
+
year: "year";
|
|
9
|
+
}>;
|
|
10
|
+
}, z.core.$strip>;
|
|
11
|
+
declare const meteredFeatureConfigSchema: z.ZodObject<{
|
|
12
|
+
limit: z.ZodNumber;
|
|
13
|
+
reset: z.ZodEnum<{
|
|
14
|
+
month: "month";
|
|
15
|
+
year: "year";
|
|
16
|
+
day: "day";
|
|
17
|
+
week: "week";
|
|
18
|
+
}>;
|
|
19
|
+
}, z.core.$strip>;
|
|
20
|
+
type FeatureType = "boolean" | "metered";
|
|
21
|
+
type PriceInterval = z.infer<typeof priceSchema>["interval"];
|
|
22
|
+
type MeteredResetInterval = z.infer<typeof meteredFeatureConfigSchema>["reset"];
|
|
23
|
+
type PlanPrice = z.infer<typeof priceSchema>;
|
|
24
|
+
type MeteredFeatureConfig = z.infer<typeof meteredFeatureConfigSchema>;
|
|
25
|
+
interface PayKitFeatureDefinition<TId extends string = string, TType extends FeatureType = FeatureType> {
|
|
26
|
+
id: TId;
|
|
27
|
+
type: TType;
|
|
28
|
+
}
|
|
29
|
+
type BooleanFeatureDefinition<TId extends string = string> = PayKitFeatureDefinition<TId, "boolean">;
|
|
30
|
+
type MeteredFeatureDefinition<TId extends string = string> = PayKitFeatureDefinition<TId, "metered">;
|
|
31
|
+
type BooleanFeatureInclude<TFeature extends BooleanFeatureDefinition = BooleanFeatureDefinition> = Readonly<{
|
|
32
|
+
config: undefined;
|
|
33
|
+
feature: TFeature;
|
|
34
|
+
}>;
|
|
35
|
+
type MeteredFeatureInclude<TFeature extends MeteredFeatureDefinition = MeteredFeatureDefinition> = Readonly<{
|
|
36
|
+
config: MeteredFeatureConfig;
|
|
37
|
+
feature: TFeature;
|
|
38
|
+
}>;
|
|
39
|
+
type PayKitFeatureInclude = BooleanFeatureInclude<BooleanFeatureDefinition> | MeteredFeatureInclude<MeteredFeatureDefinition>;
|
|
40
|
+
type BooleanFeatureCallable<TFeature extends BooleanFeatureDefinition> = (() => BooleanFeatureInclude<TFeature>) & Readonly<TFeature>;
|
|
41
|
+
type MeteredFeatureCallable<TFeature extends MeteredFeatureDefinition> = ((config: MeteredFeatureConfig) => MeteredFeatureInclude<TFeature>) & Readonly<TFeature>;
|
|
42
|
+
type PayKitFeature<TFeature extends PayKitFeatureDefinition = PayKitFeatureDefinition> = TFeature extends BooleanFeatureDefinition ? BooleanFeatureCallable<TFeature> : TFeature extends MeteredFeatureDefinition ? MeteredFeatureCallable<TFeature> : never;
|
|
43
|
+
interface PayKitPlanConfig<TId extends string = string> {
|
|
44
|
+
default?: boolean;
|
|
45
|
+
group?: string;
|
|
46
|
+
id: TId;
|
|
47
|
+
includes?: readonly PayKitFeatureInclude[];
|
|
48
|
+
name?: string;
|
|
49
|
+
price?: PlanPrice;
|
|
50
|
+
}
|
|
51
|
+
type PayKitPlan<TConfig extends PayKitPlanConfig = PayKitPlanConfig> = Readonly<Omit<TConfig, "includes"> & {
|
|
52
|
+
includes: TConfig["includes"] extends readonly PayKitFeatureInclude[] ? TConfig["includes"] : readonly PayKitFeatureInclude[];
|
|
53
|
+
}>;
|
|
54
|
+
interface NormalizedPlanFeature {
|
|
55
|
+
config: Record<string, unknown> | null;
|
|
56
|
+
id: string;
|
|
57
|
+
limit: number | null;
|
|
58
|
+
resetInterval: MeteredResetInterval | null;
|
|
59
|
+
type: FeatureType;
|
|
60
|
+
}
|
|
61
|
+
interface NormalizedPlan {
|
|
62
|
+
group: string;
|
|
63
|
+
hash: string;
|
|
64
|
+
id: string;
|
|
65
|
+
includes: readonly NormalizedPlanFeature[];
|
|
66
|
+
isDefault: boolean;
|
|
67
|
+
name: string;
|
|
68
|
+
priceAmount: number | null;
|
|
69
|
+
priceInterval: PriceInterval | null;
|
|
70
|
+
trialDays: number | null;
|
|
71
|
+
}
|
|
72
|
+
interface NormalizedFeature {
|
|
73
|
+
id: string;
|
|
74
|
+
type: FeatureType;
|
|
75
|
+
}
|
|
76
|
+
interface NormalizedSchema {
|
|
77
|
+
features: readonly NormalizedFeature[];
|
|
78
|
+
plans: readonly NormalizedPlan[];
|
|
79
|
+
planMap: ReadonlyMap<string, NormalizedPlan>;
|
|
80
|
+
}
|
|
81
|
+
type PayKitPlansModule = readonly PayKitPlan[] | Record<string, unknown>;
|
|
82
|
+
type PlanIdFromPlans<TPlans> = TPlans extends readonly (infer TItem)[] ? TItem extends PayKitPlan<PayKitPlanConfig<infer TId>> ? TId : never : TPlans extends Record<PropertyKey, unknown> ? TPlans[keyof TPlans] extends infer TValue ? TValue extends {
|
|
83
|
+
id: infer TId extends string;
|
|
84
|
+
} ? TValue extends PayKitPlan ? TId : never : never : never : never;
|
|
85
|
+
type ExtractFeatureIds<TPlan> = TPlan extends {
|
|
86
|
+
includes: readonly (infer TInclude)[];
|
|
87
|
+
} ? TInclude extends {
|
|
88
|
+
feature: {
|
|
89
|
+
id: infer TId extends string;
|
|
90
|
+
};
|
|
91
|
+
} ? TId : never : never;
|
|
92
|
+
type FeatureIdFromPlans<TPlans> = TPlans extends readonly (infer TItem)[] ? ExtractFeatureIds<TItem> : TPlans extends Record<PropertyKey, unknown> ? ExtractFeatureIds<TPlans[keyof TPlans]> : never;
|
|
93
|
+
declare function feature<const TId extends string, const TType extends FeatureType>(definition: {
|
|
94
|
+
id: TId;
|
|
95
|
+
type: TType;
|
|
96
|
+
}): PayKitFeature<PayKitFeatureDefinition<TId, TType>>;
|
|
97
|
+
declare function plan<const TConfig extends PayKitPlanConfig>(config: TConfig): PayKitPlan<TConfig>;
|
|
98
|
+
//#endregion
|
|
99
|
+
export { FeatureIdFromPlans, FeatureType, MeteredFeatureConfig, MeteredResetInterval, NormalizedPlan, NormalizedPlanFeature, NormalizedSchema, PayKitFeature, PayKitFeatureDefinition, PayKitFeatureInclude, PayKitPlan, PayKitPlanConfig, PayKitPlansModule, PlanIdFromPlans, PlanPrice, PriceInterval, feature, plan };
|