@parsrun/payments 0.1.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/README.md +184 -0
- package/dist/billing/index.d.ts +121 -0
- package/dist/billing/index.js +1082 -0
- package/dist/billing/index.js.map +1 -0
- package/dist/billing-service-LsAFesou.d.ts +578 -0
- package/dist/dunning/index.d.ts +310 -0
- package/dist/dunning/index.js +2677 -0
- package/dist/dunning/index.js.map +1 -0
- package/dist/index.d.ts +185 -0
- package/dist/index.js +7698 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/index.d.ts +5 -0
- package/dist/providers/index.js +1396 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/iyzico.d.ts +250 -0
- package/dist/providers/iyzico.js +469 -0
- package/dist/providers/iyzico.js.map +1 -0
- package/dist/providers/paddle.d.ts +66 -0
- package/dist/providers/paddle.js +437 -0
- package/dist/providers/paddle.js.map +1 -0
- package/dist/providers/stripe.d.ts +122 -0
- package/dist/providers/stripe.js +586 -0
- package/dist/providers/stripe.js.map +1 -0
- package/dist/schema-C5Zcju_j.d.ts +4191 -0
- package/dist/types.d.ts +388 -0
- package/dist/types.js +74 -0
- package/dist/types.js.map +1 -0
- package/dist/usage/index.d.ts +2674 -0
- package/dist/usage/index.js +2916 -0
- package/dist/usage/index.js.map +1 -0
- package/dist/webhooks/index.d.ts +89 -0
- package/dist/webhooks/index.js +188 -0
- package/dist/webhooks/index.js.map +1 -0
- package/package.json +91 -0
|
@@ -0,0 +1,2674 @@
|
|
|
1
|
+
import { PaymentProviderType } from '../types.js';
|
|
2
|
+
import { k as BillingLogger$1, n as BillingSubscription, B as BillingService } from '../billing-service-LsAFesou.js';
|
|
3
|
+
import { PostgresJsDatabase } from 'drizzle-orm/postgres-js';
|
|
4
|
+
import { NeonHttpDatabase } from 'drizzle-orm/neon-http';
|
|
5
|
+
import * as drizzle_orm_pg_core from 'drizzle-orm/pg-core';
|
|
6
|
+
import '@parsrun/types';
|
|
7
|
+
import '../webhooks/index.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @parsrun/payments - Usage Types
|
|
11
|
+
* Types for usage-based billing
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
type BillingLogger = BillingLogger$1;
|
|
15
|
+
/**
|
|
16
|
+
* Plan tier levels
|
|
17
|
+
*/
|
|
18
|
+
type PlanTier = 0 | 1 | 2 | 3 | 4;
|
|
19
|
+
/**
|
|
20
|
+
* Billing interval
|
|
21
|
+
*/
|
|
22
|
+
type BillingInterval = "month" | "year";
|
|
23
|
+
/**
|
|
24
|
+
* Limit period for features
|
|
25
|
+
*/
|
|
26
|
+
type LimitPeriod = "hour" | "day" | "month" | null;
|
|
27
|
+
/**
|
|
28
|
+
* Reset period for quotas
|
|
29
|
+
* - monthly: Reset on the 1st of each calendar month
|
|
30
|
+
* - billing_cycle: Reset on subscription renewal date
|
|
31
|
+
*/
|
|
32
|
+
type ResetPeriod = "monthly" | "billing_cycle";
|
|
33
|
+
/**
|
|
34
|
+
* Customer access status
|
|
35
|
+
* - active: Full access, subscription is current
|
|
36
|
+
* - past_due: Limited access, payment failed but grace period active
|
|
37
|
+
* - suspended: No access, multiple payment failures
|
|
38
|
+
* - canceled: No access, subscription canceled
|
|
39
|
+
* - unpaid: No access, subscription unpaid
|
|
40
|
+
*/
|
|
41
|
+
type AccessStatus = "active" | "past_due" | "suspended" | "canceled" | "unpaid";
|
|
42
|
+
/**
|
|
43
|
+
* Access status info for a customer
|
|
44
|
+
*/
|
|
45
|
+
interface AccessStatusInfo {
|
|
46
|
+
status: AccessStatus;
|
|
47
|
+
/** When the status was last updated */
|
|
48
|
+
updatedAt: Date;
|
|
49
|
+
/** Reason for current status */
|
|
50
|
+
reason?: string;
|
|
51
|
+
/** When access will be suspended (for past_due) */
|
|
52
|
+
suspensionDate?: Date;
|
|
53
|
+
/** Number of failed payment attempts */
|
|
54
|
+
failedPaymentAttempts?: number;
|
|
55
|
+
/** Grace period end date */
|
|
56
|
+
gracePeriodEnd?: Date;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Plan definition
|
|
60
|
+
*/
|
|
61
|
+
interface Plan$1 {
|
|
62
|
+
id: string;
|
|
63
|
+
name: string;
|
|
64
|
+
displayName: string;
|
|
65
|
+
description: string | null;
|
|
66
|
+
tier: PlanTier;
|
|
67
|
+
basePrice: number;
|
|
68
|
+
currency: string;
|
|
69
|
+
billingInterval: BillingInterval;
|
|
70
|
+
features: PlanFeature$1[];
|
|
71
|
+
isActive: boolean;
|
|
72
|
+
metadata?: Record<string, unknown>;
|
|
73
|
+
createdAt: Date;
|
|
74
|
+
updatedAt: Date;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Plan feature with limits
|
|
78
|
+
*/
|
|
79
|
+
interface PlanFeature$1 {
|
|
80
|
+
id: string;
|
|
81
|
+
planId: string;
|
|
82
|
+
featureKey: string;
|
|
83
|
+
limitValue: number | null;
|
|
84
|
+
limitPeriod: LimitPeriod;
|
|
85
|
+
isEnabled: boolean;
|
|
86
|
+
metadata?: Record<string, unknown>;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Usage event record
|
|
90
|
+
*/
|
|
91
|
+
interface UsageEvent {
|
|
92
|
+
id: string;
|
|
93
|
+
tenantId: string;
|
|
94
|
+
customerId: string;
|
|
95
|
+
subscriptionId?: string;
|
|
96
|
+
featureKey: string;
|
|
97
|
+
quantity: number;
|
|
98
|
+
timestamp: Date;
|
|
99
|
+
metadata?: Record<string, unknown>;
|
|
100
|
+
idempotencyKey?: string;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Options for tracking usage
|
|
104
|
+
*/
|
|
105
|
+
interface TrackUsageOptions {
|
|
106
|
+
tenantId: string;
|
|
107
|
+
customerId: string;
|
|
108
|
+
subscriptionId?: string;
|
|
109
|
+
featureKey: string;
|
|
110
|
+
quantity?: number;
|
|
111
|
+
metadata?: Record<string, unknown>;
|
|
112
|
+
idempotencyKey?: string;
|
|
113
|
+
timestamp?: Date;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Period type for aggregation
|
|
117
|
+
*/
|
|
118
|
+
type PeriodType = "hour" | "day" | "month";
|
|
119
|
+
/**
|
|
120
|
+
* Usage aggregate record
|
|
121
|
+
*/
|
|
122
|
+
interface UsageAggregate {
|
|
123
|
+
id: string;
|
|
124
|
+
tenantId: string;
|
|
125
|
+
customerId: string;
|
|
126
|
+
subscriptionId?: string;
|
|
127
|
+
featureKey: string;
|
|
128
|
+
periodStart: Date;
|
|
129
|
+
periodEnd: Date;
|
|
130
|
+
periodType: PeriodType;
|
|
131
|
+
totalQuantity: number;
|
|
132
|
+
eventCount: number;
|
|
133
|
+
lastUpdated: Date;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Options for getting usage
|
|
137
|
+
*/
|
|
138
|
+
interface GetUsageOptions {
|
|
139
|
+
featureKey?: string;
|
|
140
|
+
periodType?: PeriodType;
|
|
141
|
+
startDate?: Date;
|
|
142
|
+
endDate?: Date;
|
|
143
|
+
subscriptionId?: string;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Quota status for a feature
|
|
147
|
+
*/
|
|
148
|
+
interface QuotaStatus {
|
|
149
|
+
featureKey: string;
|
|
150
|
+
limit: number | null;
|
|
151
|
+
used: number;
|
|
152
|
+
remaining: number | null;
|
|
153
|
+
percentUsed: number | null;
|
|
154
|
+
periodStart: Date;
|
|
155
|
+
periodEnd: Date;
|
|
156
|
+
isExceeded: boolean;
|
|
157
|
+
isUnlimited: boolean;
|
|
158
|
+
/** Overage amount (used - limit) when soft limits enabled */
|
|
159
|
+
overage?: number;
|
|
160
|
+
/** Whether overage is allowed for this feature */
|
|
161
|
+
overageAllowed?: boolean;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Quota check result
|
|
165
|
+
*/
|
|
166
|
+
interface QuotaCheckResult {
|
|
167
|
+
allowed: boolean;
|
|
168
|
+
currentUsage: number;
|
|
169
|
+
limit: number | null;
|
|
170
|
+
remaining: number | null;
|
|
171
|
+
wouldExceed: boolean;
|
|
172
|
+
percentAfter: number | null;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Alert status
|
|
176
|
+
*/
|
|
177
|
+
type AlertStatus = "pending" | "triggered" | "acknowledged" | "resolved";
|
|
178
|
+
/**
|
|
179
|
+
* Usage alert
|
|
180
|
+
*/
|
|
181
|
+
interface UsageAlert {
|
|
182
|
+
id: string;
|
|
183
|
+
tenantId: string;
|
|
184
|
+
customerId: string;
|
|
185
|
+
subscriptionId?: string;
|
|
186
|
+
featureKey: string;
|
|
187
|
+
thresholdPercent: number;
|
|
188
|
+
status: AlertStatus;
|
|
189
|
+
currentUsage: number;
|
|
190
|
+
limit: number;
|
|
191
|
+
triggeredAt?: Date;
|
|
192
|
+
acknowledgedAt?: Date;
|
|
193
|
+
resolvedAt?: Date;
|
|
194
|
+
metadata?: Record<string, unknown>;
|
|
195
|
+
createdAt: Date;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Subscription lifecycle event types
|
|
199
|
+
*/
|
|
200
|
+
type SubscriptionEventType = "subscription.created" | "subscription.activated" | "subscription.updated" | "subscription.plan_changed" | "subscription.canceled" | "subscription.expired" | "subscription.renewed" | "subscription.trial_started" | "subscription.trial_ended" | "subscription.payment_failed" | "subscription.payment_succeeded" | "subscription.period_reset";
|
|
201
|
+
/**
|
|
202
|
+
* Subscription lifecycle event
|
|
203
|
+
*/
|
|
204
|
+
interface SubscriptionEvent {
|
|
205
|
+
type: SubscriptionEventType;
|
|
206
|
+
subscription: BillingSubscription;
|
|
207
|
+
previousPlan?: Plan$1;
|
|
208
|
+
newPlan?: Plan$1;
|
|
209
|
+
timestamp: Date;
|
|
210
|
+
provider: PaymentProviderType;
|
|
211
|
+
metadata?: Record<string, unknown>;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Subscription event handler
|
|
215
|
+
*/
|
|
216
|
+
type SubscriptionHandler = (event: SubscriptionEvent) => void | Promise<void>;
|
|
217
|
+
/**
|
|
218
|
+
* Usage-specific webhook event types
|
|
219
|
+
*/
|
|
220
|
+
type UsageWebhookEventType = "usage.recorded" | "usage.threshold_reached" | "usage.limit_exceeded" | "usage.limit_reset" | "plan.upgraded" | "plan.downgraded";
|
|
221
|
+
/**
|
|
222
|
+
* Usage storage interface
|
|
223
|
+
* Allows pluggable storage backends (database, in-memory, etc.)
|
|
224
|
+
*/
|
|
225
|
+
interface UsageStorage {
|
|
226
|
+
getPlan(planId: string): Promise<Plan$1 | null>;
|
|
227
|
+
getPlanByName(name: string): Promise<Plan$1 | null>;
|
|
228
|
+
listPlans(options?: {
|
|
229
|
+
activeOnly?: boolean;
|
|
230
|
+
}): Promise<Plan$1[]>;
|
|
231
|
+
getPlanFeatures(planId: string): Promise<PlanFeature$1[]>;
|
|
232
|
+
getFeatureLimit(planId: string, featureKey: string): Promise<PlanFeature$1 | null>;
|
|
233
|
+
getCustomerPlanId(customerId: string): Promise<string | null>;
|
|
234
|
+
setCustomerPlanId(customerId: string, planId: string): Promise<void>;
|
|
235
|
+
recordUsage(event: Omit<UsageEvent, "id">): Promise<UsageEvent>;
|
|
236
|
+
recordUsageBatch(events: Omit<UsageEvent, "id">[]): Promise<UsageEvent[]>;
|
|
237
|
+
getUsageEvents(customerId: string, options: GetUsageOptions): Promise<UsageEvent[]>;
|
|
238
|
+
getAggregate(customerId: string, featureKey: string, periodType: PeriodType, periodStart: Date): Promise<UsageAggregate | null>;
|
|
239
|
+
upsertAggregate(aggregate: Omit<UsageAggregate, "id">): Promise<UsageAggregate>;
|
|
240
|
+
getAggregates(customerId: string, options: GetUsageOptions): Promise<UsageAggregate[]>;
|
|
241
|
+
getCurrentPeriodUsage(customerId: string, featureKey: string, periodStart: Date): Promise<number>;
|
|
242
|
+
createAlert(alert: Omit<UsageAlert, "id" | "createdAt">): Promise<UsageAlert>;
|
|
243
|
+
getActiveAlerts(customerId: string): Promise<UsageAlert[]>;
|
|
244
|
+
updateAlertStatus(alertId: string, status: AlertStatus): Promise<void>;
|
|
245
|
+
/** Reset usage for a customer (all features or specific ones) */
|
|
246
|
+
resetUsage(customerId: string, featureKeys?: string[], periodStart?: Date): Promise<void>;
|
|
247
|
+
/** Reset all aggregates for a customer */
|
|
248
|
+
resetAggregates(customerId: string, featureKeys?: string[]): Promise<void>;
|
|
249
|
+
/** Get customer access status */
|
|
250
|
+
getAccessStatus(customerId: string): Promise<AccessStatusInfo | null>;
|
|
251
|
+
/** Set customer access status */
|
|
252
|
+
setAccessStatus(customerId: string, status: AccessStatusInfo): Promise<void>;
|
|
253
|
+
/** Get customer's current billing cycle dates */
|
|
254
|
+
getBillingCycle(customerId: string): Promise<{
|
|
255
|
+
start: Date;
|
|
256
|
+
end: Date;
|
|
257
|
+
} | null>;
|
|
258
|
+
/** Set customer's billing cycle dates */
|
|
259
|
+
setBillingCycle(customerId: string, start: Date, end: Date): Promise<void>;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Usage service configuration
|
|
263
|
+
*/
|
|
264
|
+
interface UsageServiceConfig {
|
|
265
|
+
/** Storage backend */
|
|
266
|
+
storage: UsageStorage;
|
|
267
|
+
/** Logger */
|
|
268
|
+
logger?: BillingLogger;
|
|
269
|
+
/** Alert thresholds (default: [80, 100]) */
|
|
270
|
+
alertThresholds?: number[];
|
|
271
|
+
/** Aggregate usage immediately (default: false - async) */
|
|
272
|
+
aggregateImmediately?: boolean;
|
|
273
|
+
/**
|
|
274
|
+
* Reset period for quotas
|
|
275
|
+
* - monthly: Reset on the 1st of each calendar month (default)
|
|
276
|
+
* - billing_cycle: Reset on subscription renewal date
|
|
277
|
+
*/
|
|
278
|
+
resetPeriod?: ResetPeriod;
|
|
279
|
+
/**
|
|
280
|
+
* Auto-reset quotas on subscription renewal
|
|
281
|
+
* Default: true
|
|
282
|
+
*/
|
|
283
|
+
autoResetOnRenewal?: boolean;
|
|
284
|
+
/**
|
|
285
|
+
* Grace period in days before access is suspended after payment failure
|
|
286
|
+
* Default: 3 days
|
|
287
|
+
*/
|
|
288
|
+
paymentGraceDays?: number;
|
|
289
|
+
/**
|
|
290
|
+
* Number of failed payments before suspending access
|
|
291
|
+
* Default: 3
|
|
292
|
+
*/
|
|
293
|
+
maxFailedPayments?: number;
|
|
294
|
+
/** Callback when threshold is reached */
|
|
295
|
+
onThresholdReached?: (alert: UsageAlert) => void | Promise<void>;
|
|
296
|
+
/** Callback when limit is exceeded */
|
|
297
|
+
onLimitExceeded?: (quota: QuotaStatus, customerId: string) => void | Promise<void>;
|
|
298
|
+
/** Callback when period resets */
|
|
299
|
+
onPeriodReset?: (customerId: string, featureKey: string) => void | Promise<void>;
|
|
300
|
+
/** Callback when access status changes */
|
|
301
|
+
onAccessStatusChanged?: (customerId: string, status: AccessStatusInfo, previousStatus?: AccessStatus) => void | Promise<void>;
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Quota manager configuration
|
|
305
|
+
*/
|
|
306
|
+
interface QuotaManagerConfig {
|
|
307
|
+
/** Storage backend */
|
|
308
|
+
storage: UsageStorage;
|
|
309
|
+
/** Logger */
|
|
310
|
+
logger?: BillingLogger;
|
|
311
|
+
/** Soft limit behavior - warn but allow (default: false) */
|
|
312
|
+
softLimits?: boolean;
|
|
313
|
+
/** Grace period percentage over limit (default: 0) */
|
|
314
|
+
gracePercent?: number;
|
|
315
|
+
/**
|
|
316
|
+
* Features that allow overage (soft limits)
|
|
317
|
+
* If set, only these features will allow overage.
|
|
318
|
+
* If not set and softLimits=true, all features allow overage.
|
|
319
|
+
*/
|
|
320
|
+
overageAllowedFeatures?: string[];
|
|
321
|
+
/**
|
|
322
|
+
* Callback when overage is recorded
|
|
323
|
+
* Called when usage exceeds limit for a soft-limit feature
|
|
324
|
+
*/
|
|
325
|
+
onOverage?: (customerId: string, featureKey: string, overage: number, limit: number) => void | Promise<void>;
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Usage error codes
|
|
329
|
+
*/
|
|
330
|
+
declare const UsageErrorCodes: {
|
|
331
|
+
readonly QUOTA_EXCEEDED: "QUOTA_EXCEEDED";
|
|
332
|
+
readonly PLAN_NOT_FOUND: "PLAN_NOT_FOUND";
|
|
333
|
+
readonly FEATURE_NOT_FOUND: "FEATURE_NOT_FOUND";
|
|
334
|
+
readonly CUSTOMER_NOT_FOUND: "CUSTOMER_NOT_FOUND";
|
|
335
|
+
readonly DUPLICATE_EVENT: "DUPLICATE_EVENT";
|
|
336
|
+
readonly STORAGE_ERROR: "STORAGE_ERROR";
|
|
337
|
+
readonly INVALID_PERIOD: "INVALID_PERIOD";
|
|
338
|
+
};
|
|
339
|
+
type UsageErrorCode = keyof typeof UsageErrorCodes;
|
|
340
|
+
/**
|
|
341
|
+
* Usage error
|
|
342
|
+
*/
|
|
343
|
+
declare class UsageError extends Error {
|
|
344
|
+
readonly code: UsageErrorCode;
|
|
345
|
+
readonly details?: Record<string, unknown> | undefined;
|
|
346
|
+
constructor(message: string, code: UsageErrorCode, details?: Record<string, unknown> | undefined);
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Quota exceeded error
|
|
350
|
+
*/
|
|
351
|
+
declare class QuotaExceededError extends UsageError {
|
|
352
|
+
readonly featureKey: string;
|
|
353
|
+
readonly limit: number | null;
|
|
354
|
+
readonly currentUsage: number;
|
|
355
|
+
readonly requestedQuantity: number;
|
|
356
|
+
constructor(featureKey: string, limit: number | null, currentUsage: number, requestedQuantity?: number);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* @parsrun/payments - In-Memory Usage Storage
|
|
361
|
+
* Default storage implementation for development and testing
|
|
362
|
+
*/
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* In-memory usage storage
|
|
366
|
+
* For development, testing, and single-instance deployments
|
|
367
|
+
*/
|
|
368
|
+
declare class MemoryUsageStorage implements UsageStorage {
|
|
369
|
+
private plans;
|
|
370
|
+
private planFeatures;
|
|
371
|
+
private customerPlans;
|
|
372
|
+
private usageEvents;
|
|
373
|
+
private usageAggregates;
|
|
374
|
+
private alerts;
|
|
375
|
+
private idempotencyKeys;
|
|
376
|
+
private accessStatuses;
|
|
377
|
+
private billingCycles;
|
|
378
|
+
getPlan(planId: string): Promise<Plan$1 | null>;
|
|
379
|
+
getPlanByName(name: string): Promise<Plan$1 | null>;
|
|
380
|
+
listPlans(options?: {
|
|
381
|
+
activeOnly?: boolean;
|
|
382
|
+
}): Promise<Plan$1[]>;
|
|
383
|
+
/**
|
|
384
|
+
* Add a plan (for testing/setup)
|
|
385
|
+
*/
|
|
386
|
+
addPlan(plan: Plan$1): void;
|
|
387
|
+
getPlanFeatures(planId: string): Promise<PlanFeature$1[]>;
|
|
388
|
+
getFeatureLimit(planId: string, featureKey: string): Promise<PlanFeature$1 | null>;
|
|
389
|
+
/**
|
|
390
|
+
* Add plan features (for testing/setup)
|
|
391
|
+
*/
|
|
392
|
+
addPlanFeatures(planId: string, features: PlanFeature$1[]): void;
|
|
393
|
+
getCustomerPlanId(customerId: string): Promise<string | null>;
|
|
394
|
+
setCustomerPlanId(customerId: string, planId: string): Promise<void>;
|
|
395
|
+
recordUsage(event: Omit<UsageEvent, "id">): Promise<UsageEvent>;
|
|
396
|
+
recordUsageBatch(events: Omit<UsageEvent, "id">[]): Promise<UsageEvent[]>;
|
|
397
|
+
getUsageEvents(customerId: string, options: GetUsageOptions): Promise<UsageEvent[]>;
|
|
398
|
+
private getAggregateKey;
|
|
399
|
+
getAggregate(customerId: string, featureKey: string, periodType: PeriodType, periodStart: Date): Promise<UsageAggregate | null>;
|
|
400
|
+
upsertAggregate(aggregate: Omit<UsageAggregate, "id">): Promise<UsageAggregate>;
|
|
401
|
+
getAggregates(customerId: string, options: GetUsageOptions): Promise<UsageAggregate[]>;
|
|
402
|
+
getCurrentPeriodUsage(customerId: string, featureKey: string, periodStart: Date): Promise<number>;
|
|
403
|
+
createAlert(alert: Omit<UsageAlert, "id" | "createdAt">): Promise<UsageAlert>;
|
|
404
|
+
getActiveAlerts(customerId: string): Promise<UsageAlert[]>;
|
|
405
|
+
updateAlertStatus(alertId: string, status: AlertStatus): Promise<void>;
|
|
406
|
+
resetUsage(customerId: string, featureKeys?: string[], periodStart?: Date): Promise<void>;
|
|
407
|
+
resetAggregates(customerId: string, featureKeys?: string[]): Promise<void>;
|
|
408
|
+
getAccessStatus(customerId: string): Promise<AccessStatusInfo | null>;
|
|
409
|
+
setAccessStatus(customerId: string, status: AccessStatusInfo): Promise<void>;
|
|
410
|
+
getBillingCycle(customerId: string): Promise<{
|
|
411
|
+
start: Date;
|
|
412
|
+
end: Date;
|
|
413
|
+
} | null>;
|
|
414
|
+
setBillingCycle(customerId: string, start: Date, end: Date): Promise<void>;
|
|
415
|
+
/**
|
|
416
|
+
* Clear all data (for testing)
|
|
417
|
+
*/
|
|
418
|
+
clear(): void;
|
|
419
|
+
/**
|
|
420
|
+
* Get stats (for debugging)
|
|
421
|
+
*/
|
|
422
|
+
getStats(): {
|
|
423
|
+
plans: number;
|
|
424
|
+
customers: number;
|
|
425
|
+
events: number;
|
|
426
|
+
aggregates: number;
|
|
427
|
+
alerts: number;
|
|
428
|
+
accessStatuses: number;
|
|
429
|
+
billingCycles: number;
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
/**
|
|
433
|
+
* Create in-memory usage storage
|
|
434
|
+
*/
|
|
435
|
+
declare function createMemoryUsageStorage(): MemoryUsageStorage;
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* @parsrun/payments - Drizzle Usage Storage
|
|
439
|
+
* Database-backed storage implementation using Drizzle ORM
|
|
440
|
+
*
|
|
441
|
+
* @example
|
|
442
|
+
* ```typescript
|
|
443
|
+
* import { createDrizzleUsageStorage } from "@parsrun/payments";
|
|
444
|
+
* import { drizzle } from "drizzle-orm/postgres-js";
|
|
445
|
+
* import postgres from "postgres";
|
|
446
|
+
*
|
|
447
|
+
* const client = postgres(process.env.DATABASE_URL);
|
|
448
|
+
* const db = drizzle(client);
|
|
449
|
+
*
|
|
450
|
+
* const storage = createDrizzleUsageStorage({ db });
|
|
451
|
+
*
|
|
452
|
+
* const usageService = createUsageService({ storage });
|
|
453
|
+
* ```
|
|
454
|
+
*/
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* Supported Drizzle database types
|
|
458
|
+
*/
|
|
459
|
+
type DrizzleDb = PostgresJsDatabase<any> | NeonHttpDatabase<any>;
|
|
460
|
+
/**
|
|
461
|
+
* Drizzle storage configuration
|
|
462
|
+
*/
|
|
463
|
+
interface DrizzleUsageStorageConfig {
|
|
464
|
+
/** Drizzle database instance */
|
|
465
|
+
db: DrizzleDb;
|
|
466
|
+
/** Table prefix (optional, for multi-tenant setups) */
|
|
467
|
+
tablePrefix?: string;
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Drizzle-backed usage storage
|
|
471
|
+
* Persists all usage data to PostgreSQL/Neon database
|
|
472
|
+
*/
|
|
473
|
+
declare class DrizzleUsageStorage implements UsageStorage {
|
|
474
|
+
private readonly db;
|
|
475
|
+
constructor(config: DrizzleUsageStorageConfig);
|
|
476
|
+
getPlan(planId: string): Promise<Plan$1 | null>;
|
|
477
|
+
getPlanByName(name: string): Promise<Plan$1 | null>;
|
|
478
|
+
listPlans(options?: {
|
|
479
|
+
activeOnly?: boolean;
|
|
480
|
+
}): Promise<Plan$1[]>;
|
|
481
|
+
private mapRowToPlan;
|
|
482
|
+
getPlanFeatures(planId: string): Promise<PlanFeature$1[]>;
|
|
483
|
+
getFeatureLimit(planId: string, featureKey: string): Promise<PlanFeature$1 | null>;
|
|
484
|
+
private mapRowToPlanFeature;
|
|
485
|
+
getCustomerPlanId(customerId: string): Promise<string | null>;
|
|
486
|
+
setCustomerPlanId(customerId: string, planId: string): Promise<void>;
|
|
487
|
+
recordUsage(event: Omit<UsageEvent, "id">): Promise<UsageEvent>;
|
|
488
|
+
recordUsageBatch(events: Omit<UsageEvent, "id">[]): Promise<UsageEvent[]>;
|
|
489
|
+
getUsageEvents(customerId: string, options: GetUsageOptions): Promise<UsageEvent[]>;
|
|
490
|
+
private mapRowToUsageEvent;
|
|
491
|
+
getAggregate(customerId: string, featureKey: string, periodType: PeriodType, periodStart: Date): Promise<UsageAggregate | null>;
|
|
492
|
+
upsertAggregate(aggregate: Omit<UsageAggregate, "id">): Promise<UsageAggregate>;
|
|
493
|
+
getAggregates(customerId: string, options: GetUsageOptions): Promise<UsageAggregate[]>;
|
|
494
|
+
getCurrentPeriodUsage(customerId: string, featureKey: string, periodStart: Date): Promise<number>;
|
|
495
|
+
private mapRowToUsageAggregate;
|
|
496
|
+
createAlert(alert: Omit<UsageAlert, "id" | "createdAt">): Promise<UsageAlert>;
|
|
497
|
+
getActiveAlerts(customerId: string): Promise<UsageAlert[]>;
|
|
498
|
+
updateAlertStatus(alertId: string, status: AlertStatus): Promise<void>;
|
|
499
|
+
private mapRowToUsageAlert;
|
|
500
|
+
resetUsage(customerId: string, featureKeys?: string[], periodStart?: Date): Promise<void>;
|
|
501
|
+
resetAggregates(customerId: string, featureKeys?: string[]): Promise<void>;
|
|
502
|
+
getAccessStatus(customerId: string): Promise<AccessStatusInfo | null>;
|
|
503
|
+
setAccessStatus(customerId: string, status: AccessStatusInfo): Promise<void>;
|
|
504
|
+
getBillingCycle(customerId: string): Promise<{
|
|
505
|
+
start: Date;
|
|
506
|
+
end: Date;
|
|
507
|
+
} | null>;
|
|
508
|
+
setBillingCycle(customerId: string, start: Date, end: Date): Promise<void>;
|
|
509
|
+
/**
|
|
510
|
+
* Create or update a plan
|
|
511
|
+
*/
|
|
512
|
+
upsertPlan(plan: Omit<Plan$1, "createdAt" | "updatedAt">): Promise<Plan$1>;
|
|
513
|
+
/**
|
|
514
|
+
* Delete a plan
|
|
515
|
+
*/
|
|
516
|
+
deletePlan(planId: string): Promise<void>;
|
|
517
|
+
}
|
|
518
|
+
/**
|
|
519
|
+
* Create Drizzle-backed usage storage
|
|
520
|
+
*/
|
|
521
|
+
declare function createDrizzleUsageStorage(config: DrizzleUsageStorageConfig): DrizzleUsageStorage;
|
|
522
|
+
|
|
523
|
+
/**
|
|
524
|
+
* @parsrun/payments - Usage Database Schema
|
|
525
|
+
* Drizzle ORM schema for usage-based billing tables
|
|
526
|
+
*
|
|
527
|
+
* These tables store:
|
|
528
|
+
* - Plans and features with limits
|
|
529
|
+
* - Customer plan assignments
|
|
530
|
+
* - Usage events and aggregates
|
|
531
|
+
* - Access status and billing cycles
|
|
532
|
+
* - Usage alerts
|
|
533
|
+
*/
|
|
534
|
+
/**
|
|
535
|
+
* Plans table - defines billing plans with tiers
|
|
536
|
+
*/
|
|
537
|
+
declare const plans: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
538
|
+
name: "usage_plans";
|
|
539
|
+
schema: undefined;
|
|
540
|
+
columns: {
|
|
541
|
+
id: drizzle_orm_pg_core.PgColumn<{
|
|
542
|
+
name: "id";
|
|
543
|
+
tableName: "usage_plans";
|
|
544
|
+
dataType: "string";
|
|
545
|
+
columnType: "PgText";
|
|
546
|
+
data: string;
|
|
547
|
+
driverParam: string;
|
|
548
|
+
notNull: true;
|
|
549
|
+
hasDefault: false;
|
|
550
|
+
isPrimaryKey: true;
|
|
551
|
+
isAutoincrement: false;
|
|
552
|
+
hasRuntimeDefault: false;
|
|
553
|
+
enumValues: [string, ...string[]];
|
|
554
|
+
baseColumn: never;
|
|
555
|
+
identity: undefined;
|
|
556
|
+
generated: undefined;
|
|
557
|
+
}, {}, {}>;
|
|
558
|
+
name: drizzle_orm_pg_core.PgColumn<{
|
|
559
|
+
name: "name";
|
|
560
|
+
tableName: "usage_plans";
|
|
561
|
+
dataType: "string";
|
|
562
|
+
columnType: "PgText";
|
|
563
|
+
data: string;
|
|
564
|
+
driverParam: string;
|
|
565
|
+
notNull: true;
|
|
566
|
+
hasDefault: false;
|
|
567
|
+
isPrimaryKey: false;
|
|
568
|
+
isAutoincrement: false;
|
|
569
|
+
hasRuntimeDefault: false;
|
|
570
|
+
enumValues: [string, ...string[]];
|
|
571
|
+
baseColumn: never;
|
|
572
|
+
identity: undefined;
|
|
573
|
+
generated: undefined;
|
|
574
|
+
}, {}, {}>;
|
|
575
|
+
displayName: drizzle_orm_pg_core.PgColumn<{
|
|
576
|
+
name: "display_name";
|
|
577
|
+
tableName: "usage_plans";
|
|
578
|
+
dataType: "string";
|
|
579
|
+
columnType: "PgText";
|
|
580
|
+
data: string;
|
|
581
|
+
driverParam: string;
|
|
582
|
+
notNull: true;
|
|
583
|
+
hasDefault: false;
|
|
584
|
+
isPrimaryKey: false;
|
|
585
|
+
isAutoincrement: false;
|
|
586
|
+
hasRuntimeDefault: false;
|
|
587
|
+
enumValues: [string, ...string[]];
|
|
588
|
+
baseColumn: never;
|
|
589
|
+
identity: undefined;
|
|
590
|
+
generated: undefined;
|
|
591
|
+
}, {}, {}>;
|
|
592
|
+
description: drizzle_orm_pg_core.PgColumn<{
|
|
593
|
+
name: "description";
|
|
594
|
+
tableName: "usage_plans";
|
|
595
|
+
dataType: "string";
|
|
596
|
+
columnType: "PgText";
|
|
597
|
+
data: string;
|
|
598
|
+
driverParam: string;
|
|
599
|
+
notNull: false;
|
|
600
|
+
hasDefault: false;
|
|
601
|
+
isPrimaryKey: false;
|
|
602
|
+
isAutoincrement: false;
|
|
603
|
+
hasRuntimeDefault: false;
|
|
604
|
+
enumValues: [string, ...string[]];
|
|
605
|
+
baseColumn: never;
|
|
606
|
+
identity: undefined;
|
|
607
|
+
generated: undefined;
|
|
608
|
+
}, {}, {}>;
|
|
609
|
+
tier: drizzle_orm_pg_core.PgColumn<{
|
|
610
|
+
name: "tier";
|
|
611
|
+
tableName: "usage_plans";
|
|
612
|
+
dataType: "number";
|
|
613
|
+
columnType: "PgInteger";
|
|
614
|
+
data: number;
|
|
615
|
+
driverParam: string | number;
|
|
616
|
+
notNull: true;
|
|
617
|
+
hasDefault: true;
|
|
618
|
+
isPrimaryKey: false;
|
|
619
|
+
isAutoincrement: false;
|
|
620
|
+
hasRuntimeDefault: false;
|
|
621
|
+
enumValues: undefined;
|
|
622
|
+
baseColumn: never;
|
|
623
|
+
identity: undefined;
|
|
624
|
+
generated: undefined;
|
|
625
|
+
}, {}, {}>;
|
|
626
|
+
basePrice: drizzle_orm_pg_core.PgColumn<{
|
|
627
|
+
name: "base_price";
|
|
628
|
+
tableName: "usage_plans";
|
|
629
|
+
dataType: "number";
|
|
630
|
+
columnType: "PgInteger";
|
|
631
|
+
data: number;
|
|
632
|
+
driverParam: string | number;
|
|
633
|
+
notNull: true;
|
|
634
|
+
hasDefault: true;
|
|
635
|
+
isPrimaryKey: false;
|
|
636
|
+
isAutoincrement: false;
|
|
637
|
+
hasRuntimeDefault: false;
|
|
638
|
+
enumValues: undefined;
|
|
639
|
+
baseColumn: never;
|
|
640
|
+
identity: undefined;
|
|
641
|
+
generated: undefined;
|
|
642
|
+
}, {}, {}>;
|
|
643
|
+
currency: drizzle_orm_pg_core.PgColumn<{
|
|
644
|
+
name: "currency";
|
|
645
|
+
tableName: "usage_plans";
|
|
646
|
+
dataType: "string";
|
|
647
|
+
columnType: "PgText";
|
|
648
|
+
data: string;
|
|
649
|
+
driverParam: string;
|
|
650
|
+
notNull: true;
|
|
651
|
+
hasDefault: true;
|
|
652
|
+
isPrimaryKey: false;
|
|
653
|
+
isAutoincrement: false;
|
|
654
|
+
hasRuntimeDefault: false;
|
|
655
|
+
enumValues: [string, ...string[]];
|
|
656
|
+
baseColumn: never;
|
|
657
|
+
identity: undefined;
|
|
658
|
+
generated: undefined;
|
|
659
|
+
}, {}, {}>;
|
|
660
|
+
billingInterval: drizzle_orm_pg_core.PgColumn<{
|
|
661
|
+
name: "billing_interval";
|
|
662
|
+
tableName: "usage_plans";
|
|
663
|
+
dataType: "string";
|
|
664
|
+
columnType: "PgText";
|
|
665
|
+
data: string;
|
|
666
|
+
driverParam: string;
|
|
667
|
+
notNull: true;
|
|
668
|
+
hasDefault: true;
|
|
669
|
+
isPrimaryKey: false;
|
|
670
|
+
isAutoincrement: false;
|
|
671
|
+
hasRuntimeDefault: false;
|
|
672
|
+
enumValues: [string, ...string[]];
|
|
673
|
+
baseColumn: never;
|
|
674
|
+
identity: undefined;
|
|
675
|
+
generated: undefined;
|
|
676
|
+
}, {}, {}>;
|
|
677
|
+
isActive: drizzle_orm_pg_core.PgColumn<{
|
|
678
|
+
name: "is_active";
|
|
679
|
+
tableName: "usage_plans";
|
|
680
|
+
dataType: "boolean";
|
|
681
|
+
columnType: "PgBoolean";
|
|
682
|
+
data: boolean;
|
|
683
|
+
driverParam: boolean;
|
|
684
|
+
notNull: true;
|
|
685
|
+
hasDefault: true;
|
|
686
|
+
isPrimaryKey: false;
|
|
687
|
+
isAutoincrement: false;
|
|
688
|
+
hasRuntimeDefault: false;
|
|
689
|
+
enumValues: undefined;
|
|
690
|
+
baseColumn: never;
|
|
691
|
+
identity: undefined;
|
|
692
|
+
generated: undefined;
|
|
693
|
+
}, {}, {}>;
|
|
694
|
+
metadata: drizzle_orm_pg_core.PgColumn<{
|
|
695
|
+
name: "metadata";
|
|
696
|
+
tableName: "usage_plans";
|
|
697
|
+
dataType: "json";
|
|
698
|
+
columnType: "PgJsonb";
|
|
699
|
+
data: Record<string, unknown>;
|
|
700
|
+
driverParam: unknown;
|
|
701
|
+
notNull: false;
|
|
702
|
+
hasDefault: false;
|
|
703
|
+
isPrimaryKey: false;
|
|
704
|
+
isAutoincrement: false;
|
|
705
|
+
hasRuntimeDefault: false;
|
|
706
|
+
enumValues: undefined;
|
|
707
|
+
baseColumn: never;
|
|
708
|
+
identity: undefined;
|
|
709
|
+
generated: undefined;
|
|
710
|
+
}, {}, {
|
|
711
|
+
$type: Record<string, unknown>;
|
|
712
|
+
}>;
|
|
713
|
+
createdAt: drizzle_orm_pg_core.PgColumn<{
|
|
714
|
+
name: "created_at";
|
|
715
|
+
tableName: "usage_plans";
|
|
716
|
+
dataType: "date";
|
|
717
|
+
columnType: "PgTimestamp";
|
|
718
|
+
data: Date;
|
|
719
|
+
driverParam: string;
|
|
720
|
+
notNull: true;
|
|
721
|
+
hasDefault: true;
|
|
722
|
+
isPrimaryKey: false;
|
|
723
|
+
isAutoincrement: false;
|
|
724
|
+
hasRuntimeDefault: false;
|
|
725
|
+
enumValues: undefined;
|
|
726
|
+
baseColumn: never;
|
|
727
|
+
identity: undefined;
|
|
728
|
+
generated: undefined;
|
|
729
|
+
}, {}, {}>;
|
|
730
|
+
updatedAt: drizzle_orm_pg_core.PgColumn<{
|
|
731
|
+
name: "updated_at";
|
|
732
|
+
tableName: "usage_plans";
|
|
733
|
+
dataType: "date";
|
|
734
|
+
columnType: "PgTimestamp";
|
|
735
|
+
data: Date;
|
|
736
|
+
driverParam: string;
|
|
737
|
+
notNull: true;
|
|
738
|
+
hasDefault: true;
|
|
739
|
+
isPrimaryKey: false;
|
|
740
|
+
isAutoincrement: false;
|
|
741
|
+
hasRuntimeDefault: false;
|
|
742
|
+
enumValues: undefined;
|
|
743
|
+
baseColumn: never;
|
|
744
|
+
identity: undefined;
|
|
745
|
+
generated: undefined;
|
|
746
|
+
}, {}, {}>;
|
|
747
|
+
};
|
|
748
|
+
dialect: "pg";
|
|
749
|
+
}>;
|
|
750
|
+
/**
|
|
751
|
+
* Plan features table - defines feature limits for each plan
|
|
752
|
+
*/
|
|
753
|
+
declare const planFeatures: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
754
|
+
name: "usage_plan_features";
|
|
755
|
+
schema: undefined;
|
|
756
|
+
columns: {
|
|
757
|
+
id: drizzle_orm_pg_core.PgColumn<{
|
|
758
|
+
name: "id";
|
|
759
|
+
tableName: "usage_plan_features";
|
|
760
|
+
dataType: "string";
|
|
761
|
+
columnType: "PgText";
|
|
762
|
+
data: string;
|
|
763
|
+
driverParam: string;
|
|
764
|
+
notNull: true;
|
|
765
|
+
hasDefault: false;
|
|
766
|
+
isPrimaryKey: true;
|
|
767
|
+
isAutoincrement: false;
|
|
768
|
+
hasRuntimeDefault: false;
|
|
769
|
+
enumValues: [string, ...string[]];
|
|
770
|
+
baseColumn: never;
|
|
771
|
+
identity: undefined;
|
|
772
|
+
generated: undefined;
|
|
773
|
+
}, {}, {}>;
|
|
774
|
+
planId: drizzle_orm_pg_core.PgColumn<{
|
|
775
|
+
name: "plan_id";
|
|
776
|
+
tableName: "usage_plan_features";
|
|
777
|
+
dataType: "string";
|
|
778
|
+
columnType: "PgText";
|
|
779
|
+
data: string;
|
|
780
|
+
driverParam: string;
|
|
781
|
+
notNull: true;
|
|
782
|
+
hasDefault: false;
|
|
783
|
+
isPrimaryKey: false;
|
|
784
|
+
isAutoincrement: false;
|
|
785
|
+
hasRuntimeDefault: false;
|
|
786
|
+
enumValues: [string, ...string[]];
|
|
787
|
+
baseColumn: never;
|
|
788
|
+
identity: undefined;
|
|
789
|
+
generated: undefined;
|
|
790
|
+
}, {}, {}>;
|
|
791
|
+
featureKey: drizzle_orm_pg_core.PgColumn<{
|
|
792
|
+
name: "feature_key";
|
|
793
|
+
tableName: "usage_plan_features";
|
|
794
|
+
dataType: "string";
|
|
795
|
+
columnType: "PgText";
|
|
796
|
+
data: string;
|
|
797
|
+
driverParam: string;
|
|
798
|
+
notNull: true;
|
|
799
|
+
hasDefault: false;
|
|
800
|
+
isPrimaryKey: false;
|
|
801
|
+
isAutoincrement: false;
|
|
802
|
+
hasRuntimeDefault: false;
|
|
803
|
+
enumValues: [string, ...string[]];
|
|
804
|
+
baseColumn: never;
|
|
805
|
+
identity: undefined;
|
|
806
|
+
generated: undefined;
|
|
807
|
+
}, {}, {}>;
|
|
808
|
+
limitValue: drizzle_orm_pg_core.PgColumn<{
|
|
809
|
+
name: "limit_value";
|
|
810
|
+
tableName: "usage_plan_features";
|
|
811
|
+
dataType: "number";
|
|
812
|
+
columnType: "PgInteger";
|
|
813
|
+
data: number;
|
|
814
|
+
driverParam: string | number;
|
|
815
|
+
notNull: false;
|
|
816
|
+
hasDefault: false;
|
|
817
|
+
isPrimaryKey: false;
|
|
818
|
+
isAutoincrement: false;
|
|
819
|
+
hasRuntimeDefault: false;
|
|
820
|
+
enumValues: undefined;
|
|
821
|
+
baseColumn: never;
|
|
822
|
+
identity: undefined;
|
|
823
|
+
generated: undefined;
|
|
824
|
+
}, {}, {}>;
|
|
825
|
+
limitPeriod: drizzle_orm_pg_core.PgColumn<{
|
|
826
|
+
name: "limit_period";
|
|
827
|
+
tableName: "usage_plan_features";
|
|
828
|
+
dataType: "string";
|
|
829
|
+
columnType: "PgText";
|
|
830
|
+
data: string;
|
|
831
|
+
driverParam: string;
|
|
832
|
+
notNull: false;
|
|
833
|
+
hasDefault: false;
|
|
834
|
+
isPrimaryKey: false;
|
|
835
|
+
isAutoincrement: false;
|
|
836
|
+
hasRuntimeDefault: false;
|
|
837
|
+
enumValues: [string, ...string[]];
|
|
838
|
+
baseColumn: never;
|
|
839
|
+
identity: undefined;
|
|
840
|
+
generated: undefined;
|
|
841
|
+
}, {}, {}>;
|
|
842
|
+
isEnabled: drizzle_orm_pg_core.PgColumn<{
|
|
843
|
+
name: "is_enabled";
|
|
844
|
+
tableName: "usage_plan_features";
|
|
845
|
+
dataType: "boolean";
|
|
846
|
+
columnType: "PgBoolean";
|
|
847
|
+
data: boolean;
|
|
848
|
+
driverParam: boolean;
|
|
849
|
+
notNull: true;
|
|
850
|
+
hasDefault: true;
|
|
851
|
+
isPrimaryKey: false;
|
|
852
|
+
isAutoincrement: false;
|
|
853
|
+
hasRuntimeDefault: false;
|
|
854
|
+
enumValues: undefined;
|
|
855
|
+
baseColumn: never;
|
|
856
|
+
identity: undefined;
|
|
857
|
+
generated: undefined;
|
|
858
|
+
}, {}, {}>;
|
|
859
|
+
metadata: drizzle_orm_pg_core.PgColumn<{
|
|
860
|
+
name: "metadata";
|
|
861
|
+
tableName: "usage_plan_features";
|
|
862
|
+
dataType: "json";
|
|
863
|
+
columnType: "PgJsonb";
|
|
864
|
+
data: Record<string, unknown>;
|
|
865
|
+
driverParam: unknown;
|
|
866
|
+
notNull: false;
|
|
867
|
+
hasDefault: false;
|
|
868
|
+
isPrimaryKey: false;
|
|
869
|
+
isAutoincrement: false;
|
|
870
|
+
hasRuntimeDefault: false;
|
|
871
|
+
enumValues: undefined;
|
|
872
|
+
baseColumn: never;
|
|
873
|
+
identity: undefined;
|
|
874
|
+
generated: undefined;
|
|
875
|
+
}, {}, {
|
|
876
|
+
$type: Record<string, unknown>;
|
|
877
|
+
}>;
|
|
878
|
+
};
|
|
879
|
+
dialect: "pg";
|
|
880
|
+
}>;
|
|
881
|
+
/**
|
|
882
|
+
* Customer plans table - maps customers to their current plan
|
|
883
|
+
*/
|
|
884
|
+
declare const customerPlans: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
885
|
+
name: "usage_customer_plans";
|
|
886
|
+
schema: undefined;
|
|
887
|
+
columns: {
|
|
888
|
+
customerId: drizzle_orm_pg_core.PgColumn<{
|
|
889
|
+
name: "customer_id";
|
|
890
|
+
tableName: "usage_customer_plans";
|
|
891
|
+
dataType: "string";
|
|
892
|
+
columnType: "PgText";
|
|
893
|
+
data: string;
|
|
894
|
+
driverParam: string;
|
|
895
|
+
notNull: true;
|
|
896
|
+
hasDefault: false;
|
|
897
|
+
isPrimaryKey: true;
|
|
898
|
+
isAutoincrement: false;
|
|
899
|
+
hasRuntimeDefault: false;
|
|
900
|
+
enumValues: [string, ...string[]];
|
|
901
|
+
baseColumn: never;
|
|
902
|
+
identity: undefined;
|
|
903
|
+
generated: undefined;
|
|
904
|
+
}, {}, {}>;
|
|
905
|
+
planId: drizzle_orm_pg_core.PgColumn<{
|
|
906
|
+
name: "plan_id";
|
|
907
|
+
tableName: "usage_customer_plans";
|
|
908
|
+
dataType: "string";
|
|
909
|
+
columnType: "PgText";
|
|
910
|
+
data: string;
|
|
911
|
+
driverParam: string;
|
|
912
|
+
notNull: true;
|
|
913
|
+
hasDefault: false;
|
|
914
|
+
isPrimaryKey: false;
|
|
915
|
+
isAutoincrement: false;
|
|
916
|
+
hasRuntimeDefault: false;
|
|
917
|
+
enumValues: [string, ...string[]];
|
|
918
|
+
baseColumn: never;
|
|
919
|
+
identity: undefined;
|
|
920
|
+
generated: undefined;
|
|
921
|
+
}, {}, {}>;
|
|
922
|
+
assignedAt: drizzle_orm_pg_core.PgColumn<{
|
|
923
|
+
name: "assigned_at";
|
|
924
|
+
tableName: "usage_customer_plans";
|
|
925
|
+
dataType: "date";
|
|
926
|
+
columnType: "PgTimestamp";
|
|
927
|
+
data: Date;
|
|
928
|
+
driverParam: string;
|
|
929
|
+
notNull: true;
|
|
930
|
+
hasDefault: true;
|
|
931
|
+
isPrimaryKey: false;
|
|
932
|
+
isAutoincrement: false;
|
|
933
|
+
hasRuntimeDefault: false;
|
|
934
|
+
enumValues: undefined;
|
|
935
|
+
baseColumn: never;
|
|
936
|
+
identity: undefined;
|
|
937
|
+
generated: undefined;
|
|
938
|
+
}, {}, {}>;
|
|
939
|
+
metadata: drizzle_orm_pg_core.PgColumn<{
|
|
940
|
+
name: "metadata";
|
|
941
|
+
tableName: "usage_customer_plans";
|
|
942
|
+
dataType: "json";
|
|
943
|
+
columnType: "PgJsonb";
|
|
944
|
+
data: Record<string, unknown>;
|
|
945
|
+
driverParam: unknown;
|
|
946
|
+
notNull: false;
|
|
947
|
+
hasDefault: false;
|
|
948
|
+
isPrimaryKey: false;
|
|
949
|
+
isAutoincrement: false;
|
|
950
|
+
hasRuntimeDefault: false;
|
|
951
|
+
enumValues: undefined;
|
|
952
|
+
baseColumn: never;
|
|
953
|
+
identity: undefined;
|
|
954
|
+
generated: undefined;
|
|
955
|
+
}, {}, {
|
|
956
|
+
$type: Record<string, unknown>;
|
|
957
|
+
}>;
|
|
958
|
+
};
|
|
959
|
+
dialect: "pg";
|
|
960
|
+
}>;
|
|
961
|
+
/**
|
|
962
|
+
* Customer access status table - tracks access status for each customer
|
|
963
|
+
*/
|
|
964
|
+
declare const customerAccessStatus: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
965
|
+
name: "usage_customer_access_status";
|
|
966
|
+
schema: undefined;
|
|
967
|
+
columns: {
|
|
968
|
+
customerId: drizzle_orm_pg_core.PgColumn<{
|
|
969
|
+
name: "customer_id";
|
|
970
|
+
tableName: "usage_customer_access_status";
|
|
971
|
+
dataType: "string";
|
|
972
|
+
columnType: "PgText";
|
|
973
|
+
data: string;
|
|
974
|
+
driverParam: string;
|
|
975
|
+
notNull: true;
|
|
976
|
+
hasDefault: false;
|
|
977
|
+
isPrimaryKey: true;
|
|
978
|
+
isAutoincrement: false;
|
|
979
|
+
hasRuntimeDefault: false;
|
|
980
|
+
enumValues: [string, ...string[]];
|
|
981
|
+
baseColumn: never;
|
|
982
|
+
identity: undefined;
|
|
983
|
+
generated: undefined;
|
|
984
|
+
}, {}, {}>;
|
|
985
|
+
status: drizzle_orm_pg_core.PgColumn<{
|
|
986
|
+
name: "status";
|
|
987
|
+
tableName: "usage_customer_access_status";
|
|
988
|
+
dataType: "string";
|
|
989
|
+
columnType: "PgText";
|
|
990
|
+
data: string;
|
|
991
|
+
driverParam: string;
|
|
992
|
+
notNull: true;
|
|
993
|
+
hasDefault: true;
|
|
994
|
+
isPrimaryKey: false;
|
|
995
|
+
isAutoincrement: false;
|
|
996
|
+
hasRuntimeDefault: false;
|
|
997
|
+
enumValues: [string, ...string[]];
|
|
998
|
+
baseColumn: never;
|
|
999
|
+
identity: undefined;
|
|
1000
|
+
generated: undefined;
|
|
1001
|
+
}, {}, {}>;
|
|
1002
|
+
reason: drizzle_orm_pg_core.PgColumn<{
|
|
1003
|
+
name: "reason";
|
|
1004
|
+
tableName: "usage_customer_access_status";
|
|
1005
|
+
dataType: "string";
|
|
1006
|
+
columnType: "PgText";
|
|
1007
|
+
data: string;
|
|
1008
|
+
driverParam: string;
|
|
1009
|
+
notNull: false;
|
|
1010
|
+
hasDefault: false;
|
|
1011
|
+
isPrimaryKey: false;
|
|
1012
|
+
isAutoincrement: false;
|
|
1013
|
+
hasRuntimeDefault: false;
|
|
1014
|
+
enumValues: [string, ...string[]];
|
|
1015
|
+
baseColumn: never;
|
|
1016
|
+
identity: undefined;
|
|
1017
|
+
generated: undefined;
|
|
1018
|
+
}, {}, {}>;
|
|
1019
|
+
suspensionDate: drizzle_orm_pg_core.PgColumn<{
|
|
1020
|
+
name: "suspension_date";
|
|
1021
|
+
tableName: "usage_customer_access_status";
|
|
1022
|
+
dataType: "date";
|
|
1023
|
+
columnType: "PgTimestamp";
|
|
1024
|
+
data: Date;
|
|
1025
|
+
driverParam: string;
|
|
1026
|
+
notNull: false;
|
|
1027
|
+
hasDefault: false;
|
|
1028
|
+
isPrimaryKey: false;
|
|
1029
|
+
isAutoincrement: false;
|
|
1030
|
+
hasRuntimeDefault: false;
|
|
1031
|
+
enumValues: undefined;
|
|
1032
|
+
baseColumn: never;
|
|
1033
|
+
identity: undefined;
|
|
1034
|
+
generated: undefined;
|
|
1035
|
+
}, {}, {}>;
|
|
1036
|
+
failedPaymentAttempts: drizzle_orm_pg_core.PgColumn<{
|
|
1037
|
+
name: "failed_payment_attempts";
|
|
1038
|
+
tableName: "usage_customer_access_status";
|
|
1039
|
+
dataType: "number";
|
|
1040
|
+
columnType: "PgInteger";
|
|
1041
|
+
data: number;
|
|
1042
|
+
driverParam: string | number;
|
|
1043
|
+
notNull: false;
|
|
1044
|
+
hasDefault: true;
|
|
1045
|
+
isPrimaryKey: false;
|
|
1046
|
+
isAutoincrement: false;
|
|
1047
|
+
hasRuntimeDefault: false;
|
|
1048
|
+
enumValues: undefined;
|
|
1049
|
+
baseColumn: never;
|
|
1050
|
+
identity: undefined;
|
|
1051
|
+
generated: undefined;
|
|
1052
|
+
}, {}, {}>;
|
|
1053
|
+
gracePeriodEnd: drizzle_orm_pg_core.PgColumn<{
|
|
1054
|
+
name: "grace_period_end";
|
|
1055
|
+
tableName: "usage_customer_access_status";
|
|
1056
|
+
dataType: "date";
|
|
1057
|
+
columnType: "PgTimestamp";
|
|
1058
|
+
data: Date;
|
|
1059
|
+
driverParam: string;
|
|
1060
|
+
notNull: false;
|
|
1061
|
+
hasDefault: false;
|
|
1062
|
+
isPrimaryKey: false;
|
|
1063
|
+
isAutoincrement: false;
|
|
1064
|
+
hasRuntimeDefault: false;
|
|
1065
|
+
enumValues: undefined;
|
|
1066
|
+
baseColumn: never;
|
|
1067
|
+
identity: undefined;
|
|
1068
|
+
generated: undefined;
|
|
1069
|
+
}, {}, {}>;
|
|
1070
|
+
updatedAt: drizzle_orm_pg_core.PgColumn<{
|
|
1071
|
+
name: "updated_at";
|
|
1072
|
+
tableName: "usage_customer_access_status";
|
|
1073
|
+
dataType: "date";
|
|
1074
|
+
columnType: "PgTimestamp";
|
|
1075
|
+
data: Date;
|
|
1076
|
+
driverParam: string;
|
|
1077
|
+
notNull: true;
|
|
1078
|
+
hasDefault: true;
|
|
1079
|
+
isPrimaryKey: false;
|
|
1080
|
+
isAutoincrement: false;
|
|
1081
|
+
hasRuntimeDefault: false;
|
|
1082
|
+
enumValues: undefined;
|
|
1083
|
+
baseColumn: never;
|
|
1084
|
+
identity: undefined;
|
|
1085
|
+
generated: undefined;
|
|
1086
|
+
}, {}, {}>;
|
|
1087
|
+
};
|
|
1088
|
+
dialect: "pg";
|
|
1089
|
+
}>;
|
|
1090
|
+
/**
|
|
1091
|
+
* Customer billing cycles table - tracks billing period for each customer
|
|
1092
|
+
*/
|
|
1093
|
+
declare const customerBillingCycles: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
1094
|
+
name: "usage_customer_billing_cycles";
|
|
1095
|
+
schema: undefined;
|
|
1096
|
+
columns: {
|
|
1097
|
+
customerId: drizzle_orm_pg_core.PgColumn<{
|
|
1098
|
+
name: "customer_id";
|
|
1099
|
+
tableName: "usage_customer_billing_cycles";
|
|
1100
|
+
dataType: "string";
|
|
1101
|
+
columnType: "PgText";
|
|
1102
|
+
data: string;
|
|
1103
|
+
driverParam: string;
|
|
1104
|
+
notNull: true;
|
|
1105
|
+
hasDefault: false;
|
|
1106
|
+
isPrimaryKey: true;
|
|
1107
|
+
isAutoincrement: false;
|
|
1108
|
+
hasRuntimeDefault: false;
|
|
1109
|
+
enumValues: [string, ...string[]];
|
|
1110
|
+
baseColumn: never;
|
|
1111
|
+
identity: undefined;
|
|
1112
|
+
generated: undefined;
|
|
1113
|
+
}, {}, {}>;
|
|
1114
|
+
periodStart: drizzle_orm_pg_core.PgColumn<{
|
|
1115
|
+
name: "period_start";
|
|
1116
|
+
tableName: "usage_customer_billing_cycles";
|
|
1117
|
+
dataType: "date";
|
|
1118
|
+
columnType: "PgTimestamp";
|
|
1119
|
+
data: Date;
|
|
1120
|
+
driverParam: string;
|
|
1121
|
+
notNull: true;
|
|
1122
|
+
hasDefault: false;
|
|
1123
|
+
isPrimaryKey: false;
|
|
1124
|
+
isAutoincrement: false;
|
|
1125
|
+
hasRuntimeDefault: false;
|
|
1126
|
+
enumValues: undefined;
|
|
1127
|
+
baseColumn: never;
|
|
1128
|
+
identity: undefined;
|
|
1129
|
+
generated: undefined;
|
|
1130
|
+
}, {}, {}>;
|
|
1131
|
+
periodEnd: drizzle_orm_pg_core.PgColumn<{
|
|
1132
|
+
name: "period_end";
|
|
1133
|
+
tableName: "usage_customer_billing_cycles";
|
|
1134
|
+
dataType: "date";
|
|
1135
|
+
columnType: "PgTimestamp";
|
|
1136
|
+
data: Date;
|
|
1137
|
+
driverParam: string;
|
|
1138
|
+
notNull: true;
|
|
1139
|
+
hasDefault: false;
|
|
1140
|
+
isPrimaryKey: false;
|
|
1141
|
+
isAutoincrement: false;
|
|
1142
|
+
hasRuntimeDefault: false;
|
|
1143
|
+
enumValues: undefined;
|
|
1144
|
+
baseColumn: never;
|
|
1145
|
+
identity: undefined;
|
|
1146
|
+
generated: undefined;
|
|
1147
|
+
}, {}, {}>;
|
|
1148
|
+
updatedAt: drizzle_orm_pg_core.PgColumn<{
|
|
1149
|
+
name: "updated_at";
|
|
1150
|
+
tableName: "usage_customer_billing_cycles";
|
|
1151
|
+
dataType: "date";
|
|
1152
|
+
columnType: "PgTimestamp";
|
|
1153
|
+
data: Date;
|
|
1154
|
+
driverParam: string;
|
|
1155
|
+
notNull: true;
|
|
1156
|
+
hasDefault: true;
|
|
1157
|
+
isPrimaryKey: false;
|
|
1158
|
+
isAutoincrement: false;
|
|
1159
|
+
hasRuntimeDefault: false;
|
|
1160
|
+
enumValues: undefined;
|
|
1161
|
+
baseColumn: never;
|
|
1162
|
+
identity: undefined;
|
|
1163
|
+
generated: undefined;
|
|
1164
|
+
}, {}, {}>;
|
|
1165
|
+
};
|
|
1166
|
+
dialect: "pg";
|
|
1167
|
+
}>;
|
|
1168
|
+
/**
|
|
1169
|
+
* Usage events table - raw usage event log
|
|
1170
|
+
*/
|
|
1171
|
+
declare const usageEvents: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
1172
|
+
name: "usage_events";
|
|
1173
|
+
schema: undefined;
|
|
1174
|
+
columns: {
|
|
1175
|
+
id: drizzle_orm_pg_core.PgColumn<{
|
|
1176
|
+
name: "id";
|
|
1177
|
+
tableName: "usage_events";
|
|
1178
|
+
dataType: "string";
|
|
1179
|
+
columnType: "PgText";
|
|
1180
|
+
data: string;
|
|
1181
|
+
driverParam: string;
|
|
1182
|
+
notNull: true;
|
|
1183
|
+
hasDefault: false;
|
|
1184
|
+
isPrimaryKey: true;
|
|
1185
|
+
isAutoincrement: false;
|
|
1186
|
+
hasRuntimeDefault: false;
|
|
1187
|
+
enumValues: [string, ...string[]];
|
|
1188
|
+
baseColumn: never;
|
|
1189
|
+
identity: undefined;
|
|
1190
|
+
generated: undefined;
|
|
1191
|
+
}, {}, {}>;
|
|
1192
|
+
tenantId: drizzle_orm_pg_core.PgColumn<{
|
|
1193
|
+
name: "tenant_id";
|
|
1194
|
+
tableName: "usage_events";
|
|
1195
|
+
dataType: "string";
|
|
1196
|
+
columnType: "PgText";
|
|
1197
|
+
data: string;
|
|
1198
|
+
driverParam: string;
|
|
1199
|
+
notNull: true;
|
|
1200
|
+
hasDefault: false;
|
|
1201
|
+
isPrimaryKey: false;
|
|
1202
|
+
isAutoincrement: false;
|
|
1203
|
+
hasRuntimeDefault: false;
|
|
1204
|
+
enumValues: [string, ...string[]];
|
|
1205
|
+
baseColumn: never;
|
|
1206
|
+
identity: undefined;
|
|
1207
|
+
generated: undefined;
|
|
1208
|
+
}, {}, {}>;
|
|
1209
|
+
customerId: drizzle_orm_pg_core.PgColumn<{
|
|
1210
|
+
name: "customer_id";
|
|
1211
|
+
tableName: "usage_events";
|
|
1212
|
+
dataType: "string";
|
|
1213
|
+
columnType: "PgText";
|
|
1214
|
+
data: string;
|
|
1215
|
+
driverParam: string;
|
|
1216
|
+
notNull: true;
|
|
1217
|
+
hasDefault: false;
|
|
1218
|
+
isPrimaryKey: false;
|
|
1219
|
+
isAutoincrement: false;
|
|
1220
|
+
hasRuntimeDefault: false;
|
|
1221
|
+
enumValues: [string, ...string[]];
|
|
1222
|
+
baseColumn: never;
|
|
1223
|
+
identity: undefined;
|
|
1224
|
+
generated: undefined;
|
|
1225
|
+
}, {}, {}>;
|
|
1226
|
+
subscriptionId: drizzle_orm_pg_core.PgColumn<{
|
|
1227
|
+
name: "subscription_id";
|
|
1228
|
+
tableName: "usage_events";
|
|
1229
|
+
dataType: "string";
|
|
1230
|
+
columnType: "PgText";
|
|
1231
|
+
data: string;
|
|
1232
|
+
driverParam: string;
|
|
1233
|
+
notNull: false;
|
|
1234
|
+
hasDefault: false;
|
|
1235
|
+
isPrimaryKey: false;
|
|
1236
|
+
isAutoincrement: false;
|
|
1237
|
+
hasRuntimeDefault: false;
|
|
1238
|
+
enumValues: [string, ...string[]];
|
|
1239
|
+
baseColumn: never;
|
|
1240
|
+
identity: undefined;
|
|
1241
|
+
generated: undefined;
|
|
1242
|
+
}, {}, {}>;
|
|
1243
|
+
featureKey: drizzle_orm_pg_core.PgColumn<{
|
|
1244
|
+
name: "feature_key";
|
|
1245
|
+
tableName: "usage_events";
|
|
1246
|
+
dataType: "string";
|
|
1247
|
+
columnType: "PgText";
|
|
1248
|
+
data: string;
|
|
1249
|
+
driverParam: string;
|
|
1250
|
+
notNull: true;
|
|
1251
|
+
hasDefault: false;
|
|
1252
|
+
isPrimaryKey: false;
|
|
1253
|
+
isAutoincrement: false;
|
|
1254
|
+
hasRuntimeDefault: false;
|
|
1255
|
+
enumValues: [string, ...string[]];
|
|
1256
|
+
baseColumn: never;
|
|
1257
|
+
identity: undefined;
|
|
1258
|
+
generated: undefined;
|
|
1259
|
+
}, {}, {}>;
|
|
1260
|
+
quantity: drizzle_orm_pg_core.PgColumn<{
|
|
1261
|
+
name: "quantity";
|
|
1262
|
+
tableName: "usage_events";
|
|
1263
|
+
dataType: "number";
|
|
1264
|
+
columnType: "PgInteger";
|
|
1265
|
+
data: number;
|
|
1266
|
+
driverParam: string | number;
|
|
1267
|
+
notNull: true;
|
|
1268
|
+
hasDefault: true;
|
|
1269
|
+
isPrimaryKey: false;
|
|
1270
|
+
isAutoincrement: false;
|
|
1271
|
+
hasRuntimeDefault: false;
|
|
1272
|
+
enumValues: undefined;
|
|
1273
|
+
baseColumn: never;
|
|
1274
|
+
identity: undefined;
|
|
1275
|
+
generated: undefined;
|
|
1276
|
+
}, {}, {}>;
|
|
1277
|
+
timestamp: drizzle_orm_pg_core.PgColumn<{
|
|
1278
|
+
name: "timestamp";
|
|
1279
|
+
tableName: "usage_events";
|
|
1280
|
+
dataType: "date";
|
|
1281
|
+
columnType: "PgTimestamp";
|
|
1282
|
+
data: Date;
|
|
1283
|
+
driverParam: string;
|
|
1284
|
+
notNull: true;
|
|
1285
|
+
hasDefault: true;
|
|
1286
|
+
isPrimaryKey: false;
|
|
1287
|
+
isAutoincrement: false;
|
|
1288
|
+
hasRuntimeDefault: false;
|
|
1289
|
+
enumValues: undefined;
|
|
1290
|
+
baseColumn: never;
|
|
1291
|
+
identity: undefined;
|
|
1292
|
+
generated: undefined;
|
|
1293
|
+
}, {}, {}>;
|
|
1294
|
+
metadata: drizzle_orm_pg_core.PgColumn<{
|
|
1295
|
+
name: "metadata";
|
|
1296
|
+
tableName: "usage_events";
|
|
1297
|
+
dataType: "json";
|
|
1298
|
+
columnType: "PgJsonb";
|
|
1299
|
+
data: Record<string, unknown>;
|
|
1300
|
+
driverParam: unknown;
|
|
1301
|
+
notNull: false;
|
|
1302
|
+
hasDefault: false;
|
|
1303
|
+
isPrimaryKey: false;
|
|
1304
|
+
isAutoincrement: false;
|
|
1305
|
+
hasRuntimeDefault: false;
|
|
1306
|
+
enumValues: undefined;
|
|
1307
|
+
baseColumn: never;
|
|
1308
|
+
identity: undefined;
|
|
1309
|
+
generated: undefined;
|
|
1310
|
+
}, {}, {
|
|
1311
|
+
$type: Record<string, unknown>;
|
|
1312
|
+
}>;
|
|
1313
|
+
idempotencyKey: drizzle_orm_pg_core.PgColumn<{
|
|
1314
|
+
name: "idempotency_key";
|
|
1315
|
+
tableName: "usage_events";
|
|
1316
|
+
dataType: "string";
|
|
1317
|
+
columnType: "PgText";
|
|
1318
|
+
data: string;
|
|
1319
|
+
driverParam: string;
|
|
1320
|
+
notNull: false;
|
|
1321
|
+
hasDefault: false;
|
|
1322
|
+
isPrimaryKey: false;
|
|
1323
|
+
isAutoincrement: false;
|
|
1324
|
+
hasRuntimeDefault: false;
|
|
1325
|
+
enumValues: [string, ...string[]];
|
|
1326
|
+
baseColumn: never;
|
|
1327
|
+
identity: undefined;
|
|
1328
|
+
generated: undefined;
|
|
1329
|
+
}, {}, {}>;
|
|
1330
|
+
};
|
|
1331
|
+
dialect: "pg";
|
|
1332
|
+
}>;
|
|
1333
|
+
/**
|
|
1334
|
+
* Usage aggregates table - pre-computed usage summaries for performance
|
|
1335
|
+
*/
|
|
1336
|
+
declare const usageAggregates: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
1337
|
+
name: "usage_aggregates";
|
|
1338
|
+
schema: undefined;
|
|
1339
|
+
columns: {
|
|
1340
|
+
id: drizzle_orm_pg_core.PgColumn<{
|
|
1341
|
+
name: "id";
|
|
1342
|
+
tableName: "usage_aggregates";
|
|
1343
|
+
dataType: "string";
|
|
1344
|
+
columnType: "PgText";
|
|
1345
|
+
data: string;
|
|
1346
|
+
driverParam: string;
|
|
1347
|
+
notNull: true;
|
|
1348
|
+
hasDefault: false;
|
|
1349
|
+
isPrimaryKey: true;
|
|
1350
|
+
isAutoincrement: false;
|
|
1351
|
+
hasRuntimeDefault: false;
|
|
1352
|
+
enumValues: [string, ...string[]];
|
|
1353
|
+
baseColumn: never;
|
|
1354
|
+
identity: undefined;
|
|
1355
|
+
generated: undefined;
|
|
1356
|
+
}, {}, {}>;
|
|
1357
|
+
tenantId: drizzle_orm_pg_core.PgColumn<{
|
|
1358
|
+
name: "tenant_id";
|
|
1359
|
+
tableName: "usage_aggregates";
|
|
1360
|
+
dataType: "string";
|
|
1361
|
+
columnType: "PgText";
|
|
1362
|
+
data: string;
|
|
1363
|
+
driverParam: string;
|
|
1364
|
+
notNull: true;
|
|
1365
|
+
hasDefault: false;
|
|
1366
|
+
isPrimaryKey: false;
|
|
1367
|
+
isAutoincrement: false;
|
|
1368
|
+
hasRuntimeDefault: false;
|
|
1369
|
+
enumValues: [string, ...string[]];
|
|
1370
|
+
baseColumn: never;
|
|
1371
|
+
identity: undefined;
|
|
1372
|
+
generated: undefined;
|
|
1373
|
+
}, {}, {}>;
|
|
1374
|
+
customerId: drizzle_orm_pg_core.PgColumn<{
|
|
1375
|
+
name: "customer_id";
|
|
1376
|
+
tableName: "usage_aggregates";
|
|
1377
|
+
dataType: "string";
|
|
1378
|
+
columnType: "PgText";
|
|
1379
|
+
data: string;
|
|
1380
|
+
driverParam: string;
|
|
1381
|
+
notNull: true;
|
|
1382
|
+
hasDefault: false;
|
|
1383
|
+
isPrimaryKey: false;
|
|
1384
|
+
isAutoincrement: false;
|
|
1385
|
+
hasRuntimeDefault: false;
|
|
1386
|
+
enumValues: [string, ...string[]];
|
|
1387
|
+
baseColumn: never;
|
|
1388
|
+
identity: undefined;
|
|
1389
|
+
generated: undefined;
|
|
1390
|
+
}, {}, {}>;
|
|
1391
|
+
subscriptionId: drizzle_orm_pg_core.PgColumn<{
|
|
1392
|
+
name: "subscription_id";
|
|
1393
|
+
tableName: "usage_aggregates";
|
|
1394
|
+
dataType: "string";
|
|
1395
|
+
columnType: "PgText";
|
|
1396
|
+
data: string;
|
|
1397
|
+
driverParam: string;
|
|
1398
|
+
notNull: false;
|
|
1399
|
+
hasDefault: false;
|
|
1400
|
+
isPrimaryKey: false;
|
|
1401
|
+
isAutoincrement: false;
|
|
1402
|
+
hasRuntimeDefault: false;
|
|
1403
|
+
enumValues: [string, ...string[]];
|
|
1404
|
+
baseColumn: never;
|
|
1405
|
+
identity: undefined;
|
|
1406
|
+
generated: undefined;
|
|
1407
|
+
}, {}, {}>;
|
|
1408
|
+
featureKey: drizzle_orm_pg_core.PgColumn<{
|
|
1409
|
+
name: "feature_key";
|
|
1410
|
+
tableName: "usage_aggregates";
|
|
1411
|
+
dataType: "string";
|
|
1412
|
+
columnType: "PgText";
|
|
1413
|
+
data: string;
|
|
1414
|
+
driverParam: string;
|
|
1415
|
+
notNull: true;
|
|
1416
|
+
hasDefault: false;
|
|
1417
|
+
isPrimaryKey: false;
|
|
1418
|
+
isAutoincrement: false;
|
|
1419
|
+
hasRuntimeDefault: false;
|
|
1420
|
+
enumValues: [string, ...string[]];
|
|
1421
|
+
baseColumn: never;
|
|
1422
|
+
identity: undefined;
|
|
1423
|
+
generated: undefined;
|
|
1424
|
+
}, {}, {}>;
|
|
1425
|
+
periodStart: drizzle_orm_pg_core.PgColumn<{
|
|
1426
|
+
name: "period_start";
|
|
1427
|
+
tableName: "usage_aggregates";
|
|
1428
|
+
dataType: "date";
|
|
1429
|
+
columnType: "PgTimestamp";
|
|
1430
|
+
data: Date;
|
|
1431
|
+
driverParam: string;
|
|
1432
|
+
notNull: true;
|
|
1433
|
+
hasDefault: false;
|
|
1434
|
+
isPrimaryKey: false;
|
|
1435
|
+
isAutoincrement: false;
|
|
1436
|
+
hasRuntimeDefault: false;
|
|
1437
|
+
enumValues: undefined;
|
|
1438
|
+
baseColumn: never;
|
|
1439
|
+
identity: undefined;
|
|
1440
|
+
generated: undefined;
|
|
1441
|
+
}, {}, {}>;
|
|
1442
|
+
periodEnd: drizzle_orm_pg_core.PgColumn<{
|
|
1443
|
+
name: "period_end";
|
|
1444
|
+
tableName: "usage_aggregates";
|
|
1445
|
+
dataType: "date";
|
|
1446
|
+
columnType: "PgTimestamp";
|
|
1447
|
+
data: Date;
|
|
1448
|
+
driverParam: string;
|
|
1449
|
+
notNull: true;
|
|
1450
|
+
hasDefault: false;
|
|
1451
|
+
isPrimaryKey: false;
|
|
1452
|
+
isAutoincrement: false;
|
|
1453
|
+
hasRuntimeDefault: false;
|
|
1454
|
+
enumValues: undefined;
|
|
1455
|
+
baseColumn: never;
|
|
1456
|
+
identity: undefined;
|
|
1457
|
+
generated: undefined;
|
|
1458
|
+
}, {}, {}>;
|
|
1459
|
+
periodType: drizzle_orm_pg_core.PgColumn<{
|
|
1460
|
+
name: "period_type";
|
|
1461
|
+
tableName: "usage_aggregates";
|
|
1462
|
+
dataType: "string";
|
|
1463
|
+
columnType: "PgText";
|
|
1464
|
+
data: string;
|
|
1465
|
+
driverParam: string;
|
|
1466
|
+
notNull: true;
|
|
1467
|
+
hasDefault: false;
|
|
1468
|
+
isPrimaryKey: false;
|
|
1469
|
+
isAutoincrement: false;
|
|
1470
|
+
hasRuntimeDefault: false;
|
|
1471
|
+
enumValues: [string, ...string[]];
|
|
1472
|
+
baseColumn: never;
|
|
1473
|
+
identity: undefined;
|
|
1474
|
+
generated: undefined;
|
|
1475
|
+
}, {}, {}>;
|
|
1476
|
+
totalQuantity: drizzle_orm_pg_core.PgColumn<{
|
|
1477
|
+
name: "total_quantity";
|
|
1478
|
+
tableName: "usage_aggregates";
|
|
1479
|
+
dataType: "number";
|
|
1480
|
+
columnType: "PgInteger";
|
|
1481
|
+
data: number;
|
|
1482
|
+
driverParam: string | number;
|
|
1483
|
+
notNull: true;
|
|
1484
|
+
hasDefault: true;
|
|
1485
|
+
isPrimaryKey: false;
|
|
1486
|
+
isAutoincrement: false;
|
|
1487
|
+
hasRuntimeDefault: false;
|
|
1488
|
+
enumValues: undefined;
|
|
1489
|
+
baseColumn: never;
|
|
1490
|
+
identity: undefined;
|
|
1491
|
+
generated: undefined;
|
|
1492
|
+
}, {}, {}>;
|
|
1493
|
+
eventCount: drizzle_orm_pg_core.PgColumn<{
|
|
1494
|
+
name: "event_count";
|
|
1495
|
+
tableName: "usage_aggregates";
|
|
1496
|
+
dataType: "number";
|
|
1497
|
+
columnType: "PgInteger";
|
|
1498
|
+
data: number;
|
|
1499
|
+
driverParam: string | number;
|
|
1500
|
+
notNull: true;
|
|
1501
|
+
hasDefault: true;
|
|
1502
|
+
isPrimaryKey: false;
|
|
1503
|
+
isAutoincrement: false;
|
|
1504
|
+
hasRuntimeDefault: false;
|
|
1505
|
+
enumValues: undefined;
|
|
1506
|
+
baseColumn: never;
|
|
1507
|
+
identity: undefined;
|
|
1508
|
+
generated: undefined;
|
|
1509
|
+
}, {}, {}>;
|
|
1510
|
+
lastUpdated: drizzle_orm_pg_core.PgColumn<{
|
|
1511
|
+
name: "last_updated";
|
|
1512
|
+
tableName: "usage_aggregates";
|
|
1513
|
+
dataType: "date";
|
|
1514
|
+
columnType: "PgTimestamp";
|
|
1515
|
+
data: Date;
|
|
1516
|
+
driverParam: string;
|
|
1517
|
+
notNull: true;
|
|
1518
|
+
hasDefault: true;
|
|
1519
|
+
isPrimaryKey: false;
|
|
1520
|
+
isAutoincrement: false;
|
|
1521
|
+
hasRuntimeDefault: false;
|
|
1522
|
+
enumValues: undefined;
|
|
1523
|
+
baseColumn: never;
|
|
1524
|
+
identity: undefined;
|
|
1525
|
+
generated: undefined;
|
|
1526
|
+
}, {}, {}>;
|
|
1527
|
+
};
|
|
1528
|
+
dialect: "pg";
|
|
1529
|
+
}>;
|
|
1530
|
+
/**
|
|
1531
|
+
* Usage alerts table - tracks quota threshold alerts
|
|
1532
|
+
*/
|
|
1533
|
+
declare const usageAlerts: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
1534
|
+
name: "usage_alerts";
|
|
1535
|
+
schema: undefined;
|
|
1536
|
+
columns: {
|
|
1537
|
+
id: drizzle_orm_pg_core.PgColumn<{
|
|
1538
|
+
name: "id";
|
|
1539
|
+
tableName: "usage_alerts";
|
|
1540
|
+
dataType: "string";
|
|
1541
|
+
columnType: "PgText";
|
|
1542
|
+
data: string;
|
|
1543
|
+
driverParam: string;
|
|
1544
|
+
notNull: true;
|
|
1545
|
+
hasDefault: false;
|
|
1546
|
+
isPrimaryKey: true;
|
|
1547
|
+
isAutoincrement: false;
|
|
1548
|
+
hasRuntimeDefault: false;
|
|
1549
|
+
enumValues: [string, ...string[]];
|
|
1550
|
+
baseColumn: never;
|
|
1551
|
+
identity: undefined;
|
|
1552
|
+
generated: undefined;
|
|
1553
|
+
}, {}, {}>;
|
|
1554
|
+
tenantId: drizzle_orm_pg_core.PgColumn<{
|
|
1555
|
+
name: "tenant_id";
|
|
1556
|
+
tableName: "usage_alerts";
|
|
1557
|
+
dataType: "string";
|
|
1558
|
+
columnType: "PgText";
|
|
1559
|
+
data: string;
|
|
1560
|
+
driverParam: string;
|
|
1561
|
+
notNull: true;
|
|
1562
|
+
hasDefault: false;
|
|
1563
|
+
isPrimaryKey: false;
|
|
1564
|
+
isAutoincrement: false;
|
|
1565
|
+
hasRuntimeDefault: false;
|
|
1566
|
+
enumValues: [string, ...string[]];
|
|
1567
|
+
baseColumn: never;
|
|
1568
|
+
identity: undefined;
|
|
1569
|
+
generated: undefined;
|
|
1570
|
+
}, {}, {}>;
|
|
1571
|
+
customerId: drizzle_orm_pg_core.PgColumn<{
|
|
1572
|
+
name: "customer_id";
|
|
1573
|
+
tableName: "usage_alerts";
|
|
1574
|
+
dataType: "string";
|
|
1575
|
+
columnType: "PgText";
|
|
1576
|
+
data: string;
|
|
1577
|
+
driverParam: string;
|
|
1578
|
+
notNull: true;
|
|
1579
|
+
hasDefault: false;
|
|
1580
|
+
isPrimaryKey: false;
|
|
1581
|
+
isAutoincrement: false;
|
|
1582
|
+
hasRuntimeDefault: false;
|
|
1583
|
+
enumValues: [string, ...string[]];
|
|
1584
|
+
baseColumn: never;
|
|
1585
|
+
identity: undefined;
|
|
1586
|
+
generated: undefined;
|
|
1587
|
+
}, {}, {}>;
|
|
1588
|
+
subscriptionId: drizzle_orm_pg_core.PgColumn<{
|
|
1589
|
+
name: "subscription_id";
|
|
1590
|
+
tableName: "usage_alerts";
|
|
1591
|
+
dataType: "string";
|
|
1592
|
+
columnType: "PgText";
|
|
1593
|
+
data: string;
|
|
1594
|
+
driverParam: string;
|
|
1595
|
+
notNull: false;
|
|
1596
|
+
hasDefault: false;
|
|
1597
|
+
isPrimaryKey: false;
|
|
1598
|
+
isAutoincrement: false;
|
|
1599
|
+
hasRuntimeDefault: false;
|
|
1600
|
+
enumValues: [string, ...string[]];
|
|
1601
|
+
baseColumn: never;
|
|
1602
|
+
identity: undefined;
|
|
1603
|
+
generated: undefined;
|
|
1604
|
+
}, {}, {}>;
|
|
1605
|
+
featureKey: drizzle_orm_pg_core.PgColumn<{
|
|
1606
|
+
name: "feature_key";
|
|
1607
|
+
tableName: "usage_alerts";
|
|
1608
|
+
dataType: "string";
|
|
1609
|
+
columnType: "PgText";
|
|
1610
|
+
data: string;
|
|
1611
|
+
driverParam: string;
|
|
1612
|
+
notNull: true;
|
|
1613
|
+
hasDefault: false;
|
|
1614
|
+
isPrimaryKey: false;
|
|
1615
|
+
isAutoincrement: false;
|
|
1616
|
+
hasRuntimeDefault: false;
|
|
1617
|
+
enumValues: [string, ...string[]];
|
|
1618
|
+
baseColumn: never;
|
|
1619
|
+
identity: undefined;
|
|
1620
|
+
generated: undefined;
|
|
1621
|
+
}, {}, {}>;
|
|
1622
|
+
thresholdPercent: drizzle_orm_pg_core.PgColumn<{
|
|
1623
|
+
name: "threshold_percent";
|
|
1624
|
+
tableName: "usage_alerts";
|
|
1625
|
+
dataType: "number";
|
|
1626
|
+
columnType: "PgInteger";
|
|
1627
|
+
data: number;
|
|
1628
|
+
driverParam: string | number;
|
|
1629
|
+
notNull: true;
|
|
1630
|
+
hasDefault: false;
|
|
1631
|
+
isPrimaryKey: false;
|
|
1632
|
+
isAutoincrement: false;
|
|
1633
|
+
hasRuntimeDefault: false;
|
|
1634
|
+
enumValues: undefined;
|
|
1635
|
+
baseColumn: never;
|
|
1636
|
+
identity: undefined;
|
|
1637
|
+
generated: undefined;
|
|
1638
|
+
}, {}, {}>;
|
|
1639
|
+
status: drizzle_orm_pg_core.PgColumn<{
|
|
1640
|
+
name: "status";
|
|
1641
|
+
tableName: "usage_alerts";
|
|
1642
|
+
dataType: "string";
|
|
1643
|
+
columnType: "PgText";
|
|
1644
|
+
data: string;
|
|
1645
|
+
driverParam: string;
|
|
1646
|
+
notNull: true;
|
|
1647
|
+
hasDefault: true;
|
|
1648
|
+
isPrimaryKey: false;
|
|
1649
|
+
isAutoincrement: false;
|
|
1650
|
+
hasRuntimeDefault: false;
|
|
1651
|
+
enumValues: [string, ...string[]];
|
|
1652
|
+
baseColumn: never;
|
|
1653
|
+
identity: undefined;
|
|
1654
|
+
generated: undefined;
|
|
1655
|
+
}, {}, {}>;
|
|
1656
|
+
currentUsage: drizzle_orm_pg_core.PgColumn<{
|
|
1657
|
+
name: "current_usage";
|
|
1658
|
+
tableName: "usage_alerts";
|
|
1659
|
+
dataType: "number";
|
|
1660
|
+
columnType: "PgInteger";
|
|
1661
|
+
data: number;
|
|
1662
|
+
driverParam: string | number;
|
|
1663
|
+
notNull: true;
|
|
1664
|
+
hasDefault: false;
|
|
1665
|
+
isPrimaryKey: false;
|
|
1666
|
+
isAutoincrement: false;
|
|
1667
|
+
hasRuntimeDefault: false;
|
|
1668
|
+
enumValues: undefined;
|
|
1669
|
+
baseColumn: never;
|
|
1670
|
+
identity: undefined;
|
|
1671
|
+
generated: undefined;
|
|
1672
|
+
}, {}, {}>;
|
|
1673
|
+
limit: drizzle_orm_pg_core.PgColumn<{
|
|
1674
|
+
name: "limit";
|
|
1675
|
+
tableName: "usage_alerts";
|
|
1676
|
+
dataType: "number";
|
|
1677
|
+
columnType: "PgInteger";
|
|
1678
|
+
data: number;
|
|
1679
|
+
driverParam: string | number;
|
|
1680
|
+
notNull: true;
|
|
1681
|
+
hasDefault: false;
|
|
1682
|
+
isPrimaryKey: false;
|
|
1683
|
+
isAutoincrement: false;
|
|
1684
|
+
hasRuntimeDefault: false;
|
|
1685
|
+
enumValues: undefined;
|
|
1686
|
+
baseColumn: never;
|
|
1687
|
+
identity: undefined;
|
|
1688
|
+
generated: undefined;
|
|
1689
|
+
}, {}, {}>;
|
|
1690
|
+
triggeredAt: drizzle_orm_pg_core.PgColumn<{
|
|
1691
|
+
name: "triggered_at";
|
|
1692
|
+
tableName: "usage_alerts";
|
|
1693
|
+
dataType: "date";
|
|
1694
|
+
columnType: "PgTimestamp";
|
|
1695
|
+
data: Date;
|
|
1696
|
+
driverParam: string;
|
|
1697
|
+
notNull: false;
|
|
1698
|
+
hasDefault: false;
|
|
1699
|
+
isPrimaryKey: false;
|
|
1700
|
+
isAutoincrement: false;
|
|
1701
|
+
hasRuntimeDefault: false;
|
|
1702
|
+
enumValues: undefined;
|
|
1703
|
+
baseColumn: never;
|
|
1704
|
+
identity: undefined;
|
|
1705
|
+
generated: undefined;
|
|
1706
|
+
}, {}, {}>;
|
|
1707
|
+
acknowledgedAt: drizzle_orm_pg_core.PgColumn<{
|
|
1708
|
+
name: "acknowledged_at";
|
|
1709
|
+
tableName: "usage_alerts";
|
|
1710
|
+
dataType: "date";
|
|
1711
|
+
columnType: "PgTimestamp";
|
|
1712
|
+
data: Date;
|
|
1713
|
+
driverParam: string;
|
|
1714
|
+
notNull: false;
|
|
1715
|
+
hasDefault: false;
|
|
1716
|
+
isPrimaryKey: false;
|
|
1717
|
+
isAutoincrement: false;
|
|
1718
|
+
hasRuntimeDefault: false;
|
|
1719
|
+
enumValues: undefined;
|
|
1720
|
+
baseColumn: never;
|
|
1721
|
+
identity: undefined;
|
|
1722
|
+
generated: undefined;
|
|
1723
|
+
}, {}, {}>;
|
|
1724
|
+
resolvedAt: drizzle_orm_pg_core.PgColumn<{
|
|
1725
|
+
name: "resolved_at";
|
|
1726
|
+
tableName: "usage_alerts";
|
|
1727
|
+
dataType: "date";
|
|
1728
|
+
columnType: "PgTimestamp";
|
|
1729
|
+
data: Date;
|
|
1730
|
+
driverParam: string;
|
|
1731
|
+
notNull: false;
|
|
1732
|
+
hasDefault: false;
|
|
1733
|
+
isPrimaryKey: false;
|
|
1734
|
+
isAutoincrement: false;
|
|
1735
|
+
hasRuntimeDefault: false;
|
|
1736
|
+
enumValues: undefined;
|
|
1737
|
+
baseColumn: never;
|
|
1738
|
+
identity: undefined;
|
|
1739
|
+
generated: undefined;
|
|
1740
|
+
}, {}, {}>;
|
|
1741
|
+
metadata: drizzle_orm_pg_core.PgColumn<{
|
|
1742
|
+
name: "metadata";
|
|
1743
|
+
tableName: "usage_alerts";
|
|
1744
|
+
dataType: "json";
|
|
1745
|
+
columnType: "PgJsonb";
|
|
1746
|
+
data: Record<string, unknown>;
|
|
1747
|
+
driverParam: unknown;
|
|
1748
|
+
notNull: false;
|
|
1749
|
+
hasDefault: false;
|
|
1750
|
+
isPrimaryKey: false;
|
|
1751
|
+
isAutoincrement: false;
|
|
1752
|
+
hasRuntimeDefault: false;
|
|
1753
|
+
enumValues: undefined;
|
|
1754
|
+
baseColumn: never;
|
|
1755
|
+
identity: undefined;
|
|
1756
|
+
generated: undefined;
|
|
1757
|
+
}, {}, {
|
|
1758
|
+
$type: Record<string, unknown>;
|
|
1759
|
+
}>;
|
|
1760
|
+
createdAt: drizzle_orm_pg_core.PgColumn<{
|
|
1761
|
+
name: "created_at";
|
|
1762
|
+
tableName: "usage_alerts";
|
|
1763
|
+
dataType: "date";
|
|
1764
|
+
columnType: "PgTimestamp";
|
|
1765
|
+
data: Date;
|
|
1766
|
+
driverParam: string;
|
|
1767
|
+
notNull: true;
|
|
1768
|
+
hasDefault: true;
|
|
1769
|
+
isPrimaryKey: false;
|
|
1770
|
+
isAutoincrement: false;
|
|
1771
|
+
hasRuntimeDefault: false;
|
|
1772
|
+
enumValues: undefined;
|
|
1773
|
+
baseColumn: never;
|
|
1774
|
+
identity: undefined;
|
|
1775
|
+
generated: undefined;
|
|
1776
|
+
}, {}, {}>;
|
|
1777
|
+
};
|
|
1778
|
+
dialect: "pg";
|
|
1779
|
+
}>;
|
|
1780
|
+
type Plan = typeof plans.$inferSelect;
|
|
1781
|
+
type NewPlan = typeof plans.$inferInsert;
|
|
1782
|
+
type PlanFeature = typeof planFeatures.$inferSelect;
|
|
1783
|
+
type NewPlanFeature = typeof planFeatures.$inferInsert;
|
|
1784
|
+
type CustomerPlan = typeof customerPlans.$inferSelect;
|
|
1785
|
+
type NewCustomerPlan = typeof customerPlans.$inferInsert;
|
|
1786
|
+
type CustomerAccessStatusRow = typeof customerAccessStatus.$inferSelect;
|
|
1787
|
+
type NewCustomerAccessStatus = typeof customerAccessStatus.$inferInsert;
|
|
1788
|
+
type CustomerBillingCycle = typeof customerBillingCycles.$inferSelect;
|
|
1789
|
+
type NewCustomerBillingCycle = typeof customerBillingCycles.$inferInsert;
|
|
1790
|
+
type UsageEventRow = typeof usageEvents.$inferSelect;
|
|
1791
|
+
type NewUsageEvent = typeof usageEvents.$inferInsert;
|
|
1792
|
+
type UsageAggregateRow = typeof usageAggregates.$inferSelect;
|
|
1793
|
+
type NewUsageAggregate = typeof usageAggregates.$inferInsert;
|
|
1794
|
+
type UsageAlertRow = typeof usageAlerts.$inferSelect;
|
|
1795
|
+
type NewUsageAlert = typeof usageAlerts.$inferInsert;
|
|
1796
|
+
|
|
1797
|
+
type schema_CustomerAccessStatusRow = CustomerAccessStatusRow;
|
|
1798
|
+
type schema_CustomerBillingCycle = CustomerBillingCycle;
|
|
1799
|
+
type schema_CustomerPlan = CustomerPlan;
|
|
1800
|
+
type schema_NewCustomerAccessStatus = NewCustomerAccessStatus;
|
|
1801
|
+
type schema_NewCustomerBillingCycle = NewCustomerBillingCycle;
|
|
1802
|
+
type schema_NewCustomerPlan = NewCustomerPlan;
|
|
1803
|
+
type schema_NewPlan = NewPlan;
|
|
1804
|
+
type schema_NewPlanFeature = NewPlanFeature;
|
|
1805
|
+
type schema_NewUsageAggregate = NewUsageAggregate;
|
|
1806
|
+
type schema_NewUsageAlert = NewUsageAlert;
|
|
1807
|
+
type schema_NewUsageEvent = NewUsageEvent;
|
|
1808
|
+
type schema_Plan = Plan;
|
|
1809
|
+
type schema_PlanFeature = PlanFeature;
|
|
1810
|
+
type schema_UsageAggregateRow = UsageAggregateRow;
|
|
1811
|
+
type schema_UsageAlertRow = UsageAlertRow;
|
|
1812
|
+
type schema_UsageEventRow = UsageEventRow;
|
|
1813
|
+
declare const schema_customerAccessStatus: typeof customerAccessStatus;
|
|
1814
|
+
declare const schema_customerBillingCycles: typeof customerBillingCycles;
|
|
1815
|
+
declare const schema_customerPlans: typeof customerPlans;
|
|
1816
|
+
declare const schema_planFeatures: typeof planFeatures;
|
|
1817
|
+
declare const schema_plans: typeof plans;
|
|
1818
|
+
declare const schema_usageAggregates: typeof usageAggregates;
|
|
1819
|
+
declare const schema_usageAlerts: typeof usageAlerts;
|
|
1820
|
+
declare const schema_usageEvents: typeof usageEvents;
|
|
1821
|
+
declare namespace schema {
|
|
1822
|
+
export { type schema_CustomerAccessStatusRow as CustomerAccessStatusRow, type schema_CustomerBillingCycle as CustomerBillingCycle, type schema_CustomerPlan as CustomerPlan, type schema_NewCustomerAccessStatus as NewCustomerAccessStatus, type schema_NewCustomerBillingCycle as NewCustomerBillingCycle, type schema_NewCustomerPlan as NewCustomerPlan, type schema_NewPlan as NewPlan, type schema_NewPlanFeature as NewPlanFeature, type schema_NewUsageAggregate as NewUsageAggregate, type schema_NewUsageAlert as NewUsageAlert, type schema_NewUsageEvent as NewUsageEvent, type schema_Plan as Plan, type schema_PlanFeature as PlanFeature, type schema_UsageAggregateRow as UsageAggregateRow, type schema_UsageAlertRow as UsageAlertRow, type schema_UsageEventRow as UsageEventRow, schema_customerAccessStatus as customerAccessStatus, schema_customerBillingCycles as customerBillingCycles, schema_customerPlans as customerPlans, schema_planFeatures as planFeatures, schema_plans as plans, schema_usageAggregates as usageAggregates, schema_usageAlerts as usageAlerts, schema_usageEvents as usageEvents };
|
|
1823
|
+
}
|
|
1824
|
+
|
|
1825
|
+
/**
|
|
1826
|
+
* @parsrun/payments - Quota Manager
|
|
1827
|
+
* Handles quota checking and enforcement
|
|
1828
|
+
*/
|
|
1829
|
+
|
|
1830
|
+
/**
|
|
1831
|
+
* Quota Manager
|
|
1832
|
+
* Handles checking and enforcing usage quotas
|
|
1833
|
+
*/
|
|
1834
|
+
declare class QuotaManager {
|
|
1835
|
+
private readonly storage;
|
|
1836
|
+
private readonly logger;
|
|
1837
|
+
private readonly softLimits;
|
|
1838
|
+
private readonly gracePercent;
|
|
1839
|
+
private readonly overageAllowedFeatures;
|
|
1840
|
+
private readonly onOverage?;
|
|
1841
|
+
constructor(config: QuotaManagerConfig);
|
|
1842
|
+
/**
|
|
1843
|
+
* Check if overage is allowed for a feature
|
|
1844
|
+
*/
|
|
1845
|
+
private isOverageAllowed;
|
|
1846
|
+
/**
|
|
1847
|
+
* Check if quota allows the requested quantity
|
|
1848
|
+
*/
|
|
1849
|
+
checkQuota(customerId: string, featureKey: string, requestedQuantity?: number): Promise<QuotaCheckResult>;
|
|
1850
|
+
/**
|
|
1851
|
+
* Enforce quota - throws if exceeded
|
|
1852
|
+
*/
|
|
1853
|
+
enforceQuota(customerId: string, featureKey: string, requestedQuantity?: number): Promise<void>;
|
|
1854
|
+
/**
|
|
1855
|
+
* Get quota status for a feature
|
|
1856
|
+
*/
|
|
1857
|
+
getQuotaStatus(customerId: string, featureKey: string): Promise<QuotaStatus>;
|
|
1858
|
+
/**
|
|
1859
|
+
* Get all quota statuses for a customer
|
|
1860
|
+
*/
|
|
1861
|
+
getAllQuotas(customerId: string): Promise<QuotaStatus[]>;
|
|
1862
|
+
/**
|
|
1863
|
+
* Check if any quota is exceeded
|
|
1864
|
+
*/
|
|
1865
|
+
hasExceededQuotas(customerId: string): Promise<boolean>;
|
|
1866
|
+
/**
|
|
1867
|
+
* Get exceeded quotas
|
|
1868
|
+
*/
|
|
1869
|
+
getExceededQuotas(customerId: string): Promise<QuotaStatus[]>;
|
|
1870
|
+
}
|
|
1871
|
+
/**
|
|
1872
|
+
* Create quota manager
|
|
1873
|
+
*/
|
|
1874
|
+
declare function createQuotaManager(config: QuotaManagerConfig): QuotaManager;
|
|
1875
|
+
|
|
1876
|
+
/**
|
|
1877
|
+
* @parsrun/payments - Usage Tracker
|
|
1878
|
+
* Handles recording and tracking usage events
|
|
1879
|
+
*/
|
|
1880
|
+
|
|
1881
|
+
/**
|
|
1882
|
+
* Usage tracker configuration
|
|
1883
|
+
*/
|
|
1884
|
+
interface UsageTrackerConfig {
|
|
1885
|
+
storage: UsageStorage;
|
|
1886
|
+
logger?: BillingLogger;
|
|
1887
|
+
/** Update aggregates immediately on each event (default: true) */
|
|
1888
|
+
aggregateOnRecord?: boolean;
|
|
1889
|
+
/** Alert thresholds as percentages (default: [80, 100]) */
|
|
1890
|
+
alertThresholds?: number[];
|
|
1891
|
+
/** Callback when threshold is reached */
|
|
1892
|
+
onThresholdReached?: (alert: UsageAlert) => void | Promise<void>;
|
|
1893
|
+
}
|
|
1894
|
+
/**
|
|
1895
|
+
* Usage Tracker
|
|
1896
|
+
* Records usage events and maintains aggregates
|
|
1897
|
+
*/
|
|
1898
|
+
declare class UsageTracker {
|
|
1899
|
+
private readonly storage;
|
|
1900
|
+
private readonly logger;
|
|
1901
|
+
private readonly aggregateOnRecord;
|
|
1902
|
+
private readonly alertThresholds;
|
|
1903
|
+
private readonly onThresholdReached?;
|
|
1904
|
+
constructor(config: UsageTrackerConfig);
|
|
1905
|
+
/**
|
|
1906
|
+
* Track a usage event
|
|
1907
|
+
*/
|
|
1908
|
+
trackUsage(options: TrackUsageOptions): Promise<UsageEvent>;
|
|
1909
|
+
/**
|
|
1910
|
+
* Track multiple usage events
|
|
1911
|
+
*/
|
|
1912
|
+
trackBatch(events: TrackUsageOptions[]): Promise<UsageEvent[]>;
|
|
1913
|
+
/**
|
|
1914
|
+
* Update aggregates for an event
|
|
1915
|
+
*/
|
|
1916
|
+
private updateAggregates;
|
|
1917
|
+
/**
|
|
1918
|
+
* Check thresholds and create alerts if needed
|
|
1919
|
+
*/
|
|
1920
|
+
private checkThresholds;
|
|
1921
|
+
/**
|
|
1922
|
+
* Get usage for a customer
|
|
1923
|
+
*/
|
|
1924
|
+
getUsage(customerId: string, featureKey: string, periodType?: PeriodType): Promise<number>;
|
|
1925
|
+
/**
|
|
1926
|
+
* Get usage aggregates
|
|
1927
|
+
*/
|
|
1928
|
+
getAggregates(customerId: string, featureKey: string, periodType: PeriodType, startDate?: Date, endDate?: Date): Promise<UsageAggregate[]>;
|
|
1929
|
+
/**
|
|
1930
|
+
* Force aggregate recalculation for a period
|
|
1931
|
+
*/
|
|
1932
|
+
recalculateAggregates(customerId: string, featureKey: string, periodType: PeriodType, periodStart: Date): Promise<UsageAggregate>;
|
|
1933
|
+
}
|
|
1934
|
+
/**
|
|
1935
|
+
* Create usage tracker
|
|
1936
|
+
*/
|
|
1937
|
+
declare function createUsageTracker(config: UsageTrackerConfig): UsageTracker;
|
|
1938
|
+
|
|
1939
|
+
/**
|
|
1940
|
+
* @parsrun/payments - Subscription Lifecycle Hooks
|
|
1941
|
+
* Event-driven subscription lifecycle management
|
|
1942
|
+
*/
|
|
1943
|
+
|
|
1944
|
+
/**
|
|
1945
|
+
* Subscription Lifecycle
|
|
1946
|
+
* Manages subscription event handlers
|
|
1947
|
+
*/
|
|
1948
|
+
declare class SubscriptionLifecycle {
|
|
1949
|
+
private readonly handlers;
|
|
1950
|
+
private readonly logger;
|
|
1951
|
+
constructor(logger?: BillingLogger);
|
|
1952
|
+
/**
|
|
1953
|
+
* Register an event handler
|
|
1954
|
+
*/
|
|
1955
|
+
on(event: SubscriptionEventType | "*", handler: SubscriptionHandler): this;
|
|
1956
|
+
/**
|
|
1957
|
+
* Remove an event handler
|
|
1958
|
+
*/
|
|
1959
|
+
off(event: SubscriptionEventType | "*", handler: SubscriptionHandler): this;
|
|
1960
|
+
/**
|
|
1961
|
+
* Emit an event to all handlers
|
|
1962
|
+
*/
|
|
1963
|
+
emit(event: SubscriptionEvent): Promise<void>;
|
|
1964
|
+
/**
|
|
1965
|
+
* Check if there are handlers for an event
|
|
1966
|
+
*/
|
|
1967
|
+
hasHandlers(event: SubscriptionEventType | "*"): boolean;
|
|
1968
|
+
/**
|
|
1969
|
+
* Get handler count for an event
|
|
1970
|
+
*/
|
|
1971
|
+
handlerCount(event: SubscriptionEventType | "*"): number;
|
|
1972
|
+
/**
|
|
1973
|
+
* Clear all handlers
|
|
1974
|
+
*/
|
|
1975
|
+
clear(): void;
|
|
1976
|
+
/**
|
|
1977
|
+
* Handle subscription created
|
|
1978
|
+
*/
|
|
1979
|
+
onCreated(handler: SubscriptionHandler): this;
|
|
1980
|
+
/**
|
|
1981
|
+
* Handle subscription activated
|
|
1982
|
+
*/
|
|
1983
|
+
onActivated(handler: SubscriptionHandler): this;
|
|
1984
|
+
/**
|
|
1985
|
+
* Handle subscription updated
|
|
1986
|
+
*/
|
|
1987
|
+
onUpdated(handler: SubscriptionHandler): this;
|
|
1988
|
+
/**
|
|
1989
|
+
* Handle plan changed
|
|
1990
|
+
*/
|
|
1991
|
+
onPlanChanged(handler: SubscriptionHandler): this;
|
|
1992
|
+
/**
|
|
1993
|
+
* Handle subscription canceled
|
|
1994
|
+
*/
|
|
1995
|
+
onCanceled(handler: SubscriptionHandler): this;
|
|
1996
|
+
/**
|
|
1997
|
+
* Handle subscription expired
|
|
1998
|
+
*/
|
|
1999
|
+
onExpired(handler: SubscriptionHandler): this;
|
|
2000
|
+
/**
|
|
2001
|
+
* Handle subscription renewed
|
|
2002
|
+
*/
|
|
2003
|
+
onRenewed(handler: SubscriptionHandler): this;
|
|
2004
|
+
/**
|
|
2005
|
+
* Handle trial started
|
|
2006
|
+
*/
|
|
2007
|
+
onTrialStarted(handler: SubscriptionHandler): this;
|
|
2008
|
+
/**
|
|
2009
|
+
* Handle trial ended
|
|
2010
|
+
*/
|
|
2011
|
+
onTrialEnded(handler: SubscriptionHandler): this;
|
|
2012
|
+
/**
|
|
2013
|
+
* Handle payment failed
|
|
2014
|
+
*/
|
|
2015
|
+
onPaymentFailed(handler: SubscriptionHandler): this;
|
|
2016
|
+
/**
|
|
2017
|
+
* Handle payment succeeded
|
|
2018
|
+
*/
|
|
2019
|
+
onPaymentSucceeded(handler: SubscriptionHandler): this;
|
|
2020
|
+
/**
|
|
2021
|
+
* Handle period reset
|
|
2022
|
+
*/
|
|
2023
|
+
onPeriodReset(handler: SubscriptionHandler): this;
|
|
2024
|
+
/**
|
|
2025
|
+
* Handle all events
|
|
2026
|
+
*/
|
|
2027
|
+
onAll(handler: SubscriptionHandler): this;
|
|
2028
|
+
}
|
|
2029
|
+
/**
|
|
2030
|
+
* Create subscription lifecycle manager
|
|
2031
|
+
*/
|
|
2032
|
+
declare function createSubscriptionLifecycle(logger?: BillingLogger): SubscriptionLifecycle;
|
|
2033
|
+
|
|
2034
|
+
/**
|
|
2035
|
+
* Usage Service
|
|
2036
|
+
*
|
|
2037
|
+
* High-level API for usage-based billing:
|
|
2038
|
+
* - Track usage events
|
|
2039
|
+
* - Check and enforce quotas
|
|
2040
|
+
* - Manage subscription lifecycle
|
|
2041
|
+
* - Generate usage reports
|
|
2042
|
+
*
|
|
2043
|
+
* @example
|
|
2044
|
+
* ```typescript
|
|
2045
|
+
* const usageService = createUsageService({
|
|
2046
|
+
* storage: createMemoryUsageStorage(),
|
|
2047
|
+
* alertThresholds: [80, 100],
|
|
2048
|
+
* onThresholdReached: async (alert) => {
|
|
2049
|
+
* await sendEmail(alert.customerId, "usage-warning");
|
|
2050
|
+
* },
|
|
2051
|
+
* });
|
|
2052
|
+
*
|
|
2053
|
+
* // Track usage
|
|
2054
|
+
* await usageService.trackUsage({
|
|
2055
|
+
* tenantId: "tenant_123",
|
|
2056
|
+
* customerId: "cus_456",
|
|
2057
|
+
* featureKey: "api_calls",
|
|
2058
|
+
* quantity: 1,
|
|
2059
|
+
* });
|
|
2060
|
+
*
|
|
2061
|
+
* // Check quota
|
|
2062
|
+
* const quota = await usageService.getQuotaStatus("cus_456", "api_calls");
|
|
2063
|
+
* if (quota.isExceeded) {
|
|
2064
|
+
* throw new Error("Quota exceeded");
|
|
2065
|
+
* }
|
|
2066
|
+
*
|
|
2067
|
+
* // Lifecycle hooks
|
|
2068
|
+
* usageService.onPlanChanged(async (event) => {
|
|
2069
|
+
* console.log(`Plan changed from ${event.previousPlan?.name} to ${event.newPlan?.name}`);
|
|
2070
|
+
* });
|
|
2071
|
+
* ```
|
|
2072
|
+
*/
|
|
2073
|
+
declare class UsageService {
|
|
2074
|
+
private readonly storage;
|
|
2075
|
+
private readonly logger;
|
|
2076
|
+
private readonly quotaManager;
|
|
2077
|
+
private readonly usageTracker;
|
|
2078
|
+
private readonly lifecycle;
|
|
2079
|
+
private readonly limitExceededHandler?;
|
|
2080
|
+
private readonly resetPeriod;
|
|
2081
|
+
private readonly autoResetOnRenewal;
|
|
2082
|
+
private readonly paymentGraceDays;
|
|
2083
|
+
private readonly maxFailedPayments;
|
|
2084
|
+
private readonly accessStatusChangedHandler?;
|
|
2085
|
+
private readonly periodResetHandler?;
|
|
2086
|
+
constructor(config: UsageServiceConfig);
|
|
2087
|
+
/**
|
|
2088
|
+
* Track a usage event
|
|
2089
|
+
*/
|
|
2090
|
+
trackUsage(options: TrackUsageOptions): Promise<UsageEvent>;
|
|
2091
|
+
/**
|
|
2092
|
+
* Track multiple usage events
|
|
2093
|
+
*/
|
|
2094
|
+
trackBatch(events: TrackUsageOptions[]): Promise<UsageEvent[]>;
|
|
2095
|
+
/**
|
|
2096
|
+
* Get current usage for a feature
|
|
2097
|
+
*/
|
|
2098
|
+
getUsage(customerId: string, featureKey: string, periodType?: PeriodType): Promise<number>;
|
|
2099
|
+
/**
|
|
2100
|
+
* Get usage aggregates
|
|
2101
|
+
*/
|
|
2102
|
+
getAggregates(customerId: string, options?: GetUsageOptions): Promise<UsageAggregate[]>;
|
|
2103
|
+
/**
|
|
2104
|
+
* Check if quota allows the requested quantity
|
|
2105
|
+
*/
|
|
2106
|
+
checkQuota(customerId: string, featureKey: string, quantity?: number): Promise<QuotaCheckResult>;
|
|
2107
|
+
/**
|
|
2108
|
+
* Enforce quota - throws if exceeded
|
|
2109
|
+
*/
|
|
2110
|
+
enforceQuota(customerId: string, featureKey: string, quantity?: number): Promise<void>;
|
|
2111
|
+
/**
|
|
2112
|
+
* Get quota status for a feature
|
|
2113
|
+
*/
|
|
2114
|
+
getQuotaStatus(customerId: string, featureKey: string): Promise<QuotaStatus>;
|
|
2115
|
+
/**
|
|
2116
|
+
* Get all quota statuses for a customer
|
|
2117
|
+
*/
|
|
2118
|
+
getAllQuotas(customerId: string): Promise<QuotaStatus[]>;
|
|
2119
|
+
/**
|
|
2120
|
+
* Check if any quota is exceeded
|
|
2121
|
+
*/
|
|
2122
|
+
hasExceededQuotas(customerId: string): Promise<boolean>;
|
|
2123
|
+
/**
|
|
2124
|
+
* Get customer's current plan
|
|
2125
|
+
*/
|
|
2126
|
+
getCustomerPlan(customerId: string): Promise<Plan$1 | null>;
|
|
2127
|
+
/**
|
|
2128
|
+
* Set customer's plan
|
|
2129
|
+
*/
|
|
2130
|
+
setCustomerPlan(customerId: string, planId: string): Promise<void>;
|
|
2131
|
+
/**
|
|
2132
|
+
* Get plan by ID
|
|
2133
|
+
*/
|
|
2134
|
+
getPlan(planId: string): Promise<Plan$1 | null>;
|
|
2135
|
+
/**
|
|
2136
|
+
* Get plan by name
|
|
2137
|
+
*/
|
|
2138
|
+
getPlanByName(name: string): Promise<Plan$1 | null>;
|
|
2139
|
+
/**
|
|
2140
|
+
* List all plans
|
|
2141
|
+
*/
|
|
2142
|
+
listPlans(options?: {
|
|
2143
|
+
activeOnly?: boolean;
|
|
2144
|
+
}): Promise<Plan$1[]>;
|
|
2145
|
+
/**
|
|
2146
|
+
* Get plan features
|
|
2147
|
+
*/
|
|
2148
|
+
getPlanFeatures(planId: string): Promise<PlanFeature$1[]>;
|
|
2149
|
+
/**
|
|
2150
|
+
* Register a subscription event handler
|
|
2151
|
+
*/
|
|
2152
|
+
on(event: SubscriptionEventType | "*", handler: SubscriptionHandler): this;
|
|
2153
|
+
/**
|
|
2154
|
+
* Remove a subscription event handler
|
|
2155
|
+
*/
|
|
2156
|
+
off(event: SubscriptionEventType | "*", handler: SubscriptionHandler): this;
|
|
2157
|
+
/**
|
|
2158
|
+
* Handle subscription created
|
|
2159
|
+
*/
|
|
2160
|
+
onSubscriptionCreated(handler: SubscriptionHandler): this;
|
|
2161
|
+
/**
|
|
2162
|
+
* Handle subscription updated
|
|
2163
|
+
*/
|
|
2164
|
+
onSubscriptionUpdated(handler: SubscriptionHandler): this;
|
|
2165
|
+
/**
|
|
2166
|
+
* Handle subscription canceled
|
|
2167
|
+
*/
|
|
2168
|
+
onSubscriptionCanceled(handler: SubscriptionHandler): this;
|
|
2169
|
+
/**
|
|
2170
|
+
* Handle plan changed
|
|
2171
|
+
*/
|
|
2172
|
+
onPlanChanged(handler: SubscriptionHandler): this;
|
|
2173
|
+
/**
|
|
2174
|
+
* Handle subscription renewed
|
|
2175
|
+
*/
|
|
2176
|
+
onRenewed(handler: SubscriptionHandler): this;
|
|
2177
|
+
/**
|
|
2178
|
+
* Handle payment failed
|
|
2179
|
+
*/
|
|
2180
|
+
onPaymentFailed(handler: SubscriptionHandler): this;
|
|
2181
|
+
/**
|
|
2182
|
+
* Handle period reset
|
|
2183
|
+
*/
|
|
2184
|
+
onPeriodReset(handler: SubscriptionHandler): this;
|
|
2185
|
+
/**
|
|
2186
|
+
* Get the lifecycle manager for advanced usage
|
|
2187
|
+
*/
|
|
2188
|
+
get lifecycleManager(): SubscriptionLifecycle;
|
|
2189
|
+
/**
|
|
2190
|
+
* Get active alerts for a customer
|
|
2191
|
+
*/
|
|
2192
|
+
getActiveAlerts(customerId: string): Promise<UsageAlert[]>;
|
|
2193
|
+
/**
|
|
2194
|
+
* Acknowledge an alert
|
|
2195
|
+
*/
|
|
2196
|
+
acknowledgeAlert(alertId: string): Promise<void>;
|
|
2197
|
+
/**
|
|
2198
|
+
* Resolve an alert
|
|
2199
|
+
*/
|
|
2200
|
+
resolveAlert(alertId: string): Promise<void>;
|
|
2201
|
+
/**
|
|
2202
|
+
* Reset usage for a customer
|
|
2203
|
+
* Typically called on subscription renewal
|
|
2204
|
+
*/
|
|
2205
|
+
resetUsage(customerId: string, featureKeys?: string[]): Promise<void>;
|
|
2206
|
+
/**
|
|
2207
|
+
* Get the period start date based on reset period setting
|
|
2208
|
+
*/
|
|
2209
|
+
private getResetPeriodStart;
|
|
2210
|
+
/**
|
|
2211
|
+
* Get feature keys for a customer's plan
|
|
2212
|
+
*/
|
|
2213
|
+
private getCustomerFeatureKeys;
|
|
2214
|
+
/**
|
|
2215
|
+
* Check if auto-reset on renewal is enabled
|
|
2216
|
+
*/
|
|
2217
|
+
get autoResetEnabled(): boolean;
|
|
2218
|
+
/**
|
|
2219
|
+
* Get current reset period setting
|
|
2220
|
+
*/
|
|
2221
|
+
get currentResetPeriod(): ResetPeriod;
|
|
2222
|
+
/**
|
|
2223
|
+
* Get customer access status
|
|
2224
|
+
*/
|
|
2225
|
+
getAccessStatus(customerId: string): Promise<AccessStatusInfo>;
|
|
2226
|
+
/**
|
|
2227
|
+
* Set customer access status
|
|
2228
|
+
*/
|
|
2229
|
+
setAccessStatus(customerId: string, status: AccessStatus, options?: {
|
|
2230
|
+
reason?: string;
|
|
2231
|
+
suspensionDate?: Date;
|
|
2232
|
+
failedPaymentAttempts?: number;
|
|
2233
|
+
gracePeriodEnd?: Date;
|
|
2234
|
+
}): Promise<void>;
|
|
2235
|
+
/**
|
|
2236
|
+
* Handle payment failure - update access status
|
|
2237
|
+
*/
|
|
2238
|
+
handlePaymentFailure(customerId: string): Promise<void>;
|
|
2239
|
+
/**
|
|
2240
|
+
* Handle successful payment - restore access status
|
|
2241
|
+
*/
|
|
2242
|
+
handlePaymentSuccess(customerId: string): Promise<void>;
|
|
2243
|
+
/**
|
|
2244
|
+
* Check if customer has access (not suspended/canceled)
|
|
2245
|
+
*/
|
|
2246
|
+
hasAccess(customerId: string): Promise<boolean>;
|
|
2247
|
+
/**
|
|
2248
|
+
* Check if customer is in grace period
|
|
2249
|
+
*/
|
|
2250
|
+
isInGracePeriod(customerId: string): Promise<boolean>;
|
|
2251
|
+
/**
|
|
2252
|
+
* Set customer billing cycle
|
|
2253
|
+
*/
|
|
2254
|
+
setBillingCycle(customerId: string, start: Date, end: Date): Promise<void>;
|
|
2255
|
+
/**
|
|
2256
|
+
* Get customer billing cycle
|
|
2257
|
+
*/
|
|
2258
|
+
getBillingCycle(customerId: string): Promise<{
|
|
2259
|
+
start: Date;
|
|
2260
|
+
end: Date;
|
|
2261
|
+
} | null>;
|
|
2262
|
+
/**
|
|
2263
|
+
* Get the underlying storage
|
|
2264
|
+
*/
|
|
2265
|
+
get storageBackend(): UsageStorage;
|
|
2266
|
+
/**
|
|
2267
|
+
* Get the quota manager
|
|
2268
|
+
*/
|
|
2269
|
+
get quotas(): QuotaManager;
|
|
2270
|
+
/**
|
|
2271
|
+
* Get the usage tracker
|
|
2272
|
+
*/
|
|
2273
|
+
get tracker(): UsageTracker;
|
|
2274
|
+
}
|
|
2275
|
+
/**
|
|
2276
|
+
* Create usage service
|
|
2277
|
+
*/
|
|
2278
|
+
declare function createUsageService(config: UsageServiceConfig): UsageService;
|
|
2279
|
+
|
|
2280
|
+
/**
|
|
2281
|
+
* @parsrun/payments - Billing Integration
|
|
2282
|
+
* Connects BillingService webhooks to UsageService lifecycle
|
|
2283
|
+
*/
|
|
2284
|
+
|
|
2285
|
+
/**
|
|
2286
|
+
* Billing integration configuration
|
|
2287
|
+
*/
|
|
2288
|
+
interface BillingIntegrationConfig {
|
|
2289
|
+
/** Billing service instance */
|
|
2290
|
+
billing: BillingService;
|
|
2291
|
+
/** Usage service instance */
|
|
2292
|
+
usage: UsageService;
|
|
2293
|
+
/** Logger */
|
|
2294
|
+
logger?: BillingLogger;
|
|
2295
|
+
/** Auto-initialize customer plan on subscription creation */
|
|
2296
|
+
autoInitializePlan?: boolean;
|
|
2297
|
+
/**
|
|
2298
|
+
* Auto-reset quotas on subscription renewal
|
|
2299
|
+
* Default: true (uses UsageService.autoResetOnRenewal setting)
|
|
2300
|
+
*/
|
|
2301
|
+
autoResetOnRenewal?: boolean;
|
|
2302
|
+
/**
|
|
2303
|
+
* Auto-update access status based on payment events
|
|
2304
|
+
* Default: true
|
|
2305
|
+
*/
|
|
2306
|
+
autoManageAccessStatus?: boolean;
|
|
2307
|
+
/** Plan ID resolver - maps payment provider price IDs to internal plan IDs */
|
|
2308
|
+
resolvePlanId?: (priceId: string, provider: PaymentProviderType) => string | Promise<string>;
|
|
2309
|
+
/** Custom event handlers */
|
|
2310
|
+
onSubscriptionCreated?: (event: SubscriptionEvent) => void | Promise<void>;
|
|
2311
|
+
onSubscriptionCanceled?: (event: SubscriptionEvent) => void | Promise<void>;
|
|
2312
|
+
onSubscriptionRenewed?: (event: SubscriptionEvent) => void | Promise<void>;
|
|
2313
|
+
onPlanChanged?: (event: SubscriptionEvent) => void | Promise<void>;
|
|
2314
|
+
onPaymentFailed?: (event: SubscriptionEvent) => void | Promise<void>;
|
|
2315
|
+
}
|
|
2316
|
+
/**
|
|
2317
|
+
* Billing Integration
|
|
2318
|
+
*
|
|
2319
|
+
* Connects BillingService webhooks to UsageService lifecycle events.
|
|
2320
|
+
* This enables automatic:
|
|
2321
|
+
* - Customer plan initialization on subscription creation
|
|
2322
|
+
* - Plan updates when subscription changes
|
|
2323
|
+
* - Usage reset on subscription renewal
|
|
2324
|
+
* - Lifecycle event emission
|
|
2325
|
+
*
|
|
2326
|
+
* @example
|
|
2327
|
+
* ```typescript
|
|
2328
|
+
* import { createBillingService, createUsageService, integrateBillingWithUsage } from "@parsrun/payments";
|
|
2329
|
+
*
|
|
2330
|
+
* const billing = createBillingService({
|
|
2331
|
+
* providers: { default: stripeProvider },
|
|
2332
|
+
* });
|
|
2333
|
+
*
|
|
2334
|
+
* const usage = createUsageService({
|
|
2335
|
+
* storage: createMemoryUsageStorage(),
|
|
2336
|
+
* });
|
|
2337
|
+
*
|
|
2338
|
+
* // Connect them
|
|
2339
|
+
* const integration = integrateBillingWithUsage({
|
|
2340
|
+
* billing,
|
|
2341
|
+
* usage,
|
|
2342
|
+
* autoInitializePlan: true,
|
|
2343
|
+
* resolvePlanId: (priceId) => {
|
|
2344
|
+
* // Map Stripe price IDs to your internal plan IDs
|
|
2345
|
+
* const mapping: Record<string, string> = {
|
|
2346
|
+
* "price_starter": "starter",
|
|
2347
|
+
* "price_pro": "pro",
|
|
2348
|
+
* "price_enterprise": "enterprise",
|
|
2349
|
+
* };
|
|
2350
|
+
* return mapping[priceId] ?? "free";
|
|
2351
|
+
* },
|
|
2352
|
+
* });
|
|
2353
|
+
*
|
|
2354
|
+
* // Now subscription webhooks automatically update usage quotas
|
|
2355
|
+
* ```
|
|
2356
|
+
*/
|
|
2357
|
+
declare class BillingIntegration {
|
|
2358
|
+
private readonly billing;
|
|
2359
|
+
private readonly usage;
|
|
2360
|
+
private readonly logger;
|
|
2361
|
+
private readonly autoInitializePlan;
|
|
2362
|
+
private readonly autoResetOnRenewal;
|
|
2363
|
+
private readonly autoManageAccessStatus;
|
|
2364
|
+
private readonly resolvePlanId;
|
|
2365
|
+
private readonly config;
|
|
2366
|
+
constructor(config: BillingIntegrationConfig);
|
|
2367
|
+
/**
|
|
2368
|
+
* Setup webhook handlers on billing service
|
|
2369
|
+
*/
|
|
2370
|
+
private setupWebhookHandlers;
|
|
2371
|
+
/**
|
|
2372
|
+
* Handle subscription created webhook
|
|
2373
|
+
*/
|
|
2374
|
+
private handleSubscriptionCreated;
|
|
2375
|
+
/**
|
|
2376
|
+
* Handle subscription updated webhook
|
|
2377
|
+
*/
|
|
2378
|
+
private handleSubscriptionUpdated;
|
|
2379
|
+
/**
|
|
2380
|
+
* Handle subscription canceled webhook
|
|
2381
|
+
*/
|
|
2382
|
+
private handleSubscriptionCanceled;
|
|
2383
|
+
/**
|
|
2384
|
+
* Handle invoice paid webhook (renewal)
|
|
2385
|
+
*/
|
|
2386
|
+
private handleInvoicePaid;
|
|
2387
|
+
/**
|
|
2388
|
+
* Handle payment failed webhook
|
|
2389
|
+
*/
|
|
2390
|
+
private handlePaymentFailed;
|
|
2391
|
+
/**
|
|
2392
|
+
* Manually sync customer plan from billing provider
|
|
2393
|
+
*/
|
|
2394
|
+
syncCustomerPlan(customerId: string, provider?: PaymentProviderType): Promise<Plan$1 | null>;
|
|
2395
|
+
}
|
|
2396
|
+
/**
|
|
2397
|
+
* Create billing integration
|
|
2398
|
+
*
|
|
2399
|
+
* Connects BillingService webhooks to UsageService lifecycle events.
|
|
2400
|
+
*
|
|
2401
|
+
* @example
|
|
2402
|
+
* ```typescript
|
|
2403
|
+
* const integration = integrateBillingWithUsage({
|
|
2404
|
+
* billing,
|
|
2405
|
+
* usage,
|
|
2406
|
+
* autoInitializePlan: true,
|
|
2407
|
+
* resolvePlanId: (priceId) => priceMapping[priceId] ?? "free",
|
|
2408
|
+
* });
|
|
2409
|
+
* ```
|
|
2410
|
+
*/
|
|
2411
|
+
declare function integrateBillingWithUsage(config: BillingIntegrationConfig): BillingIntegration;
|
|
2412
|
+
/**
|
|
2413
|
+
* Alias for integrateBillingWithUsage
|
|
2414
|
+
*/
|
|
2415
|
+
declare const createBillingIntegration: typeof integrateBillingWithUsage;
|
|
2416
|
+
|
|
2417
|
+
/**
|
|
2418
|
+
* @parsrun/payments - Usage Meter
|
|
2419
|
+
* Buffers usage events and syncs to payment provider
|
|
2420
|
+
*
|
|
2421
|
+
* This solves the problem of:
|
|
2422
|
+
* - Not hitting provider API limits with per-request calls
|
|
2423
|
+
* - Reducing latency by batching usage reports
|
|
2424
|
+
* - Ensuring reliable usage reporting with retry logic
|
|
2425
|
+
*/
|
|
2426
|
+
|
|
2427
|
+
/**
|
|
2428
|
+
* Usage record to report to provider
|
|
2429
|
+
*/
|
|
2430
|
+
interface UsageRecord {
|
|
2431
|
+
/** Subscription item ID (Stripe) or subscription ID (Paddle) */
|
|
2432
|
+
subscriptionItemId: string;
|
|
2433
|
+
/** Usage quantity */
|
|
2434
|
+
quantity: number;
|
|
2435
|
+
/** Timestamp of usage (defaults to now) */
|
|
2436
|
+
timestamp?: Date;
|
|
2437
|
+
/** Action: increment (add to existing) or set (replace) */
|
|
2438
|
+
action?: "increment" | "set";
|
|
2439
|
+
/** Idempotency key to prevent duplicates */
|
|
2440
|
+
idempotencyKey?: string;
|
|
2441
|
+
}
|
|
2442
|
+
/**
|
|
2443
|
+
* Buffered usage record with metadata
|
|
2444
|
+
*/
|
|
2445
|
+
interface BufferedRecord {
|
|
2446
|
+
record: UsageRecord;
|
|
2447
|
+
customerId: string;
|
|
2448
|
+
featureKey: string;
|
|
2449
|
+
addedAt: Date;
|
|
2450
|
+
attempts: number;
|
|
2451
|
+
}
|
|
2452
|
+
/**
|
|
2453
|
+
* Usage reporter interface - implemented by providers
|
|
2454
|
+
*/
|
|
2455
|
+
interface UsageReporter {
|
|
2456
|
+
/**
|
|
2457
|
+
* Report usage to the payment provider
|
|
2458
|
+
*/
|
|
2459
|
+
reportUsage(record: UsageRecord): Promise<void>;
|
|
2460
|
+
/**
|
|
2461
|
+
* Report multiple usage records (batch)
|
|
2462
|
+
*/
|
|
2463
|
+
reportUsageBatch?(records: UsageRecord[]): Promise<void>;
|
|
2464
|
+
/**
|
|
2465
|
+
* Get subscription item ID for a subscription and price
|
|
2466
|
+
*/
|
|
2467
|
+
getSubscriptionItemId?(subscriptionId: string, priceId: string): Promise<string | null>;
|
|
2468
|
+
}
|
|
2469
|
+
/**
|
|
2470
|
+
* Sync strategy configuration
|
|
2471
|
+
*/
|
|
2472
|
+
type SyncStrategy = {
|
|
2473
|
+
type: "interval";
|
|
2474
|
+
intervalMs: number;
|
|
2475
|
+
} | {
|
|
2476
|
+
type: "threshold";
|
|
2477
|
+
maxRecords: number;
|
|
2478
|
+
maxAgeMs: number;
|
|
2479
|
+
} | {
|
|
2480
|
+
type: "manual";
|
|
2481
|
+
};
|
|
2482
|
+
/**
|
|
2483
|
+
* Usage meter configuration
|
|
2484
|
+
*/
|
|
2485
|
+
interface UsageMeterConfig {
|
|
2486
|
+
/** Usage reporter (provider with reportUsage method) */
|
|
2487
|
+
reporter: UsageReporter;
|
|
2488
|
+
/** Provider type for logging */
|
|
2489
|
+
providerType: PaymentProviderType;
|
|
2490
|
+
/** Sync strategy */
|
|
2491
|
+
strategy: SyncStrategy;
|
|
2492
|
+
/** Logger */
|
|
2493
|
+
logger?: BillingLogger;
|
|
2494
|
+
/** Max retry attempts for failed syncs */
|
|
2495
|
+
maxRetries?: number;
|
|
2496
|
+
/** Retry delay in ms */
|
|
2497
|
+
retryDelayMs?: number;
|
|
2498
|
+
/** Callback on successful sync */
|
|
2499
|
+
onSyncSuccess?: (count: number) => void;
|
|
2500
|
+
/** Callback on sync failure */
|
|
2501
|
+
onSyncError?: (error: Error, records: BufferedRecord[]) => void;
|
|
2502
|
+
/** Callback when buffer is getting full (>80%) */
|
|
2503
|
+
onBufferWarning?: (size: number, maxSize: number) => void;
|
|
2504
|
+
/** Maximum buffer size before forcing sync */
|
|
2505
|
+
maxBufferSize?: number;
|
|
2506
|
+
}
|
|
2507
|
+
/**
|
|
2508
|
+
* Usage Meter
|
|
2509
|
+
*
|
|
2510
|
+
* Buffers usage events and syncs to payment provider periodically.
|
|
2511
|
+
* Supports multiple sync strategies:
|
|
2512
|
+
* - interval: Sync every N milliseconds
|
|
2513
|
+
* - threshold: Sync when buffer reaches N records or records are older than N ms
|
|
2514
|
+
* - manual: Only sync when explicitly called
|
|
2515
|
+
*
|
|
2516
|
+
* @example
|
|
2517
|
+
* ```typescript
|
|
2518
|
+
* import { createUsageMeter } from "@parsrun/payments";
|
|
2519
|
+
*
|
|
2520
|
+
* const meter = createUsageMeter({
|
|
2521
|
+
* reporter: stripeProvider, // Provider must implement UsageReporter
|
|
2522
|
+
* providerType: "stripe",
|
|
2523
|
+
* strategy: { type: "interval", intervalMs: 60000 }, // Sync every minute
|
|
2524
|
+
* });
|
|
2525
|
+
*
|
|
2526
|
+
* // Record usage (buffered, not sent immediately)
|
|
2527
|
+
* meter.record({
|
|
2528
|
+
* customerId: "cus_123",
|
|
2529
|
+
* featureKey: "api_calls",
|
|
2530
|
+
* subscriptionItemId: "si_xxx",
|
|
2531
|
+
* quantity: 1,
|
|
2532
|
+
* });
|
|
2533
|
+
*
|
|
2534
|
+
* // Force immediate sync
|
|
2535
|
+
* await meter.flush();
|
|
2536
|
+
*
|
|
2537
|
+
* // Cleanup when done
|
|
2538
|
+
* meter.stop();
|
|
2539
|
+
* ```
|
|
2540
|
+
*/
|
|
2541
|
+
declare class UsageMeter {
|
|
2542
|
+
private readonly reporter;
|
|
2543
|
+
private readonly providerType;
|
|
2544
|
+
private readonly logger;
|
|
2545
|
+
private readonly strategy;
|
|
2546
|
+
private readonly maxRetries;
|
|
2547
|
+
private readonly retryDelayMs;
|
|
2548
|
+
private readonly maxBufferSize;
|
|
2549
|
+
private readonly config;
|
|
2550
|
+
private buffer;
|
|
2551
|
+
private intervalId;
|
|
2552
|
+
private isSyncing;
|
|
2553
|
+
private isRunning;
|
|
2554
|
+
constructor(config: UsageMeterConfig);
|
|
2555
|
+
/**
|
|
2556
|
+
* Start the meter (auto-sync based on strategy)
|
|
2557
|
+
*/
|
|
2558
|
+
start(): void;
|
|
2559
|
+
/**
|
|
2560
|
+
* Stop the meter
|
|
2561
|
+
*/
|
|
2562
|
+
stop(): void;
|
|
2563
|
+
/**
|
|
2564
|
+
* Record usage (buffered)
|
|
2565
|
+
*/
|
|
2566
|
+
record(options: {
|
|
2567
|
+
customerId: string;
|
|
2568
|
+
featureKey: string;
|
|
2569
|
+
subscriptionItemId: string;
|
|
2570
|
+
quantity: number;
|
|
2571
|
+
timestamp?: Date;
|
|
2572
|
+
action?: "increment" | "set";
|
|
2573
|
+
idempotencyKey?: string;
|
|
2574
|
+
}): void;
|
|
2575
|
+
/**
|
|
2576
|
+
* Check threshold and trigger sync if needed
|
|
2577
|
+
*/
|
|
2578
|
+
private checkThreshold;
|
|
2579
|
+
/**
|
|
2580
|
+
* Flush buffer to provider
|
|
2581
|
+
*/
|
|
2582
|
+
flush(): Promise<number>;
|
|
2583
|
+
/**
|
|
2584
|
+
* Aggregate records by subscription item ID
|
|
2585
|
+
*/
|
|
2586
|
+
private aggregateRecords;
|
|
2587
|
+
/**
|
|
2588
|
+
* Sync single record with retry
|
|
2589
|
+
*/
|
|
2590
|
+
private syncWithRetry;
|
|
2591
|
+
/**
|
|
2592
|
+
* Delay helper
|
|
2593
|
+
*/
|
|
2594
|
+
private delay;
|
|
2595
|
+
/**
|
|
2596
|
+
* Get buffer size
|
|
2597
|
+
*/
|
|
2598
|
+
get bufferSize(): number;
|
|
2599
|
+
/**
|
|
2600
|
+
* Get sync status
|
|
2601
|
+
*/
|
|
2602
|
+
get syncing(): boolean;
|
|
2603
|
+
/**
|
|
2604
|
+
* Get running status
|
|
2605
|
+
*/
|
|
2606
|
+
get running(): boolean;
|
|
2607
|
+
/**
|
|
2608
|
+
* Get buffer contents (for debugging)
|
|
2609
|
+
*/
|
|
2610
|
+
getBuffer(): ReadonlyArray<BufferedRecord>;
|
|
2611
|
+
}
|
|
2612
|
+
/**
|
|
2613
|
+
* Create usage meter
|
|
2614
|
+
*/
|
|
2615
|
+
declare function createUsageMeter(config: UsageMeterConfig): UsageMeter;
|
|
2616
|
+
/**
|
|
2617
|
+
* Subscription item mapping
|
|
2618
|
+
* Maps (customerId, featureKey) to subscriptionItemId
|
|
2619
|
+
*/
|
|
2620
|
+
interface SubscriptionItemMapping {
|
|
2621
|
+
customerId: string;
|
|
2622
|
+
featureKey: string;
|
|
2623
|
+
subscriptionId: string;
|
|
2624
|
+
subscriptionItemId: string;
|
|
2625
|
+
priceId: string;
|
|
2626
|
+
createdAt: Date;
|
|
2627
|
+
}
|
|
2628
|
+
/**
|
|
2629
|
+
* Subscription item resolver configuration
|
|
2630
|
+
*/
|
|
2631
|
+
interface SubscriptionItemResolverConfig {
|
|
2632
|
+
/** Reporter to fetch subscription items */
|
|
2633
|
+
reporter: UsageReporter;
|
|
2634
|
+
/** Cache TTL in ms (default: 1 hour) */
|
|
2635
|
+
cacheTtlMs?: number;
|
|
2636
|
+
/** Logger */
|
|
2637
|
+
logger?: BillingLogger;
|
|
2638
|
+
}
|
|
2639
|
+
/**
|
|
2640
|
+
* Subscription Item Resolver
|
|
2641
|
+
*
|
|
2642
|
+
* Resolves and caches subscription item IDs.
|
|
2643
|
+
* Stripe requires subscription_item_id for metered billing,
|
|
2644
|
+
* this resolver handles the lookup and caching.
|
|
2645
|
+
*/
|
|
2646
|
+
declare class SubscriptionItemResolver {
|
|
2647
|
+
private readonly reporter;
|
|
2648
|
+
private readonly cacheTtlMs;
|
|
2649
|
+
private readonly logger;
|
|
2650
|
+
private cache;
|
|
2651
|
+
constructor(config: SubscriptionItemResolverConfig);
|
|
2652
|
+
/**
|
|
2653
|
+
* Get subscription item ID
|
|
2654
|
+
*/
|
|
2655
|
+
resolve(subscriptionId: string, priceId: string): Promise<string | null>;
|
|
2656
|
+
/**
|
|
2657
|
+
* Set cache entry manually (useful when creating subscriptions)
|
|
2658
|
+
*/
|
|
2659
|
+
setCache(subscriptionId: string, priceId: string, itemId: string): void;
|
|
2660
|
+
/**
|
|
2661
|
+
* Clear cache
|
|
2662
|
+
*/
|
|
2663
|
+
clearCache(): void;
|
|
2664
|
+
/**
|
|
2665
|
+
* Get cache size
|
|
2666
|
+
*/
|
|
2667
|
+
get cacheSize(): number;
|
|
2668
|
+
}
|
|
2669
|
+
/**
|
|
2670
|
+
* Create subscription item resolver
|
|
2671
|
+
*/
|
|
2672
|
+
declare function createSubscriptionItemResolver(config: SubscriptionItemResolverConfig): SubscriptionItemResolver;
|
|
2673
|
+
|
|
2674
|
+
export { type AccessStatus, type AccessStatusInfo, type AlertStatus, BillingIntegration, type BillingIntegrationConfig, type BillingInterval, type BillingLogger, type DrizzleDb, DrizzleUsageStorage, type DrizzleUsageStorageConfig, type GetUsageOptions, type LimitPeriod, MemoryUsageStorage, type PeriodType, type Plan$1 as Plan, type PlanFeature$1 as PlanFeature, type PlanTier, type QuotaCheckResult, QuotaExceededError, QuotaManager, type QuotaManagerConfig, type QuotaStatus, type ResetPeriod, type SubscriptionEvent, type SubscriptionEventType, type SubscriptionHandler, type SubscriptionItemMapping, SubscriptionItemResolver, type SubscriptionItemResolverConfig, SubscriptionLifecycle, type SyncStrategy, type TrackUsageOptions, type UsageAggregate, type UsageAlert, UsageError, type UsageErrorCode, UsageErrorCodes, type UsageEvent, UsageMeter, type UsageMeterConfig, type UsageRecord, type UsageReporter, UsageService, type UsageServiceConfig, type UsageStorage, UsageTracker, type UsageTrackerConfig, type UsageWebhookEventType, createBillingIntegration, createDrizzleUsageStorage, createMemoryUsageStorage, createQuotaManager, createSubscriptionItemResolver, createSubscriptionLifecycle, createUsageMeter, createUsageService, createUsageTracker, integrateBillingWithUsage, schema as usageSchema };
|