@uniforge/platform-core 0.1.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/dist/auth/index.d.cts +184 -0
  2. package/dist/auth/index.d.ts +184 -0
  3. package/dist/auth/index.js +62 -0
  4. package/dist/auth/index.js.map +1 -0
  5. package/dist/auth/index.mjs +33 -0
  6. package/dist/auth/index.mjs.map +1 -0
  7. package/dist/billing/index.d.cts +213 -0
  8. package/dist/billing/index.d.ts +213 -0
  9. package/dist/billing/index.js +43 -0
  10. package/dist/billing/index.js.map +1 -0
  11. package/dist/billing/index.mjs +16 -0
  12. package/dist/billing/index.mjs.map +1 -0
  13. package/dist/graphql/index.d.cts +100 -0
  14. package/dist/graphql/index.d.ts +100 -0
  15. package/dist/graphql/index.js +19 -0
  16. package/dist/graphql/index.js.map +1 -0
  17. package/dist/graphql/index.mjs +1 -0
  18. package/dist/graphql/index.mjs.map +1 -0
  19. package/dist/index.d.cts +19 -0
  20. package/dist/index.d.ts +19 -0
  21. package/dist/index.js +31 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/index.mjs +6 -0
  24. package/dist/index.mjs.map +1 -0
  25. package/dist/multi-store/index.d.cts +242 -0
  26. package/dist/multi-store/index.d.ts +242 -0
  27. package/dist/multi-store/index.js +53 -0
  28. package/dist/multi-store/index.js.map +1 -0
  29. package/dist/multi-store/index.mjs +23 -0
  30. package/dist/multi-store/index.mjs.map +1 -0
  31. package/dist/multi-tenant/index.d.cts +64 -0
  32. package/dist/multi-tenant/index.d.ts +64 -0
  33. package/dist/multi-tenant/index.js +19 -0
  34. package/dist/multi-tenant/index.js.map +1 -0
  35. package/dist/multi-tenant/index.mjs +1 -0
  36. package/dist/multi-tenant/index.mjs.map +1 -0
  37. package/dist/performance/index.d.cts +118 -0
  38. package/dist/performance/index.d.ts +118 -0
  39. package/dist/performance/index.js +19 -0
  40. package/dist/performance/index.js.map +1 -0
  41. package/dist/performance/index.mjs +1 -0
  42. package/dist/performance/index.mjs.map +1 -0
  43. package/dist/platform/index.d.cts +156 -0
  44. package/dist/platform/index.d.ts +156 -0
  45. package/dist/platform/index.js +64 -0
  46. package/dist/platform/index.js.map +1 -0
  47. package/dist/platform/index.mjs +37 -0
  48. package/dist/platform/index.mjs.map +1 -0
  49. package/dist/rbac/index.d.cts +140 -0
  50. package/dist/rbac/index.d.ts +140 -0
  51. package/dist/rbac/index.js +55 -0
  52. package/dist/rbac/index.js.map +1 -0
  53. package/dist/rbac/index.mjs +27 -0
  54. package/dist/rbac/index.mjs.map +1 -0
  55. package/dist/registry-efvajmOd.d.cts +118 -0
  56. package/dist/registry-efvajmOd.d.ts +118 -0
  57. package/dist/security/index.d.cts +148 -0
  58. package/dist/security/index.d.ts +148 -0
  59. package/dist/security/index.js +40 -0
  60. package/dist/security/index.js.map +1 -0
  61. package/dist/security/index.mjs +13 -0
  62. package/dist/security/index.mjs.map +1 -0
  63. package/dist/types-CgnJiK8Z.d.cts +74 -0
  64. package/dist/types-CgnJiK8Z.d.ts +74 -0
  65. package/dist/webhooks/index.d.cts +114 -0
  66. package/dist/webhooks/index.d.ts +114 -0
  67. package/dist/webhooks/index.js +19 -0
  68. package/dist/webhooks/index.js.map +1 -0
  69. package/dist/webhooks/index.mjs +1 -0
  70. package/dist/webhooks/index.mjs.map +1 -0
  71. package/package.json +94 -0
@@ -0,0 +1,213 @@
1
+ /**
2
+ * Platform-agnostic billing types.
3
+ *
4
+ * These types define the billing model used across all platform adapters.
5
+ * Platform-specific adapters implement the BillingService interface with
6
+ * their own GraphQL mutations and API calls.
7
+ */
8
+ /** Billing interval for recurring charges. */
9
+ type PlanInterval = 'EVERY_30_DAYS' | 'ANNUAL';
10
+ /** Subscription status lifecycle values. */
11
+ type SubscriptionStatus = 'PENDING' | 'ACTIVE' | 'CANCELLED' | 'EXPIRED' | 'FROZEN' | 'DECLINED';
12
+ /** Monetary value with currency code. */
13
+ interface Money {
14
+ amount: string;
15
+ currencyCode: string;
16
+ }
17
+ /** Pricing configuration for a recurring plan charge. */
18
+ interface RecurringPricing {
19
+ type: 'recurring';
20
+ price: Money;
21
+ interval: PlanInterval;
22
+ }
23
+ /** Pricing configuration for a usage-based charge. */
24
+ interface UsagePricing {
25
+ type: 'usage';
26
+ cappedAmount: Money;
27
+ terms: string;
28
+ }
29
+ /** Union of pricing detail types. */
30
+ type PlanPricing = RecurringPricing | UsagePricing;
31
+ /** A line item within a subscription (one plan can have recurring + usage lines). */
32
+ interface SubscriptionLineItem {
33
+ id: string;
34
+ plan: {
35
+ pricingDetails: PlanPricing;
36
+ };
37
+ }
38
+ /** Billing plan definition. */
39
+ interface BillingPlan {
40
+ name: string;
41
+ description: string;
42
+ lineItems: PlanPricing[];
43
+ features: string[];
44
+ trialDays?: number;
45
+ isDefault?: boolean;
46
+ sortOrder?: number;
47
+ }
48
+ /** A subscription record stored in the database. */
49
+ interface Subscription {
50
+ id: string;
51
+ shopDomain: string;
52
+ shopifySubscriptionId: string | null;
53
+ planName: string;
54
+ status: SubscriptionStatus;
55
+ currentPeriodEnd: Date | null;
56
+ trialEndsAt: Date | null;
57
+ confirmationUrl: string | null;
58
+ createdAt: Date;
59
+ updatedAt: Date;
60
+ }
61
+ /** Input for creating a new subscription. */
62
+ interface CreateSubscriptionInput {
63
+ shopDomain: string;
64
+ planName: string;
65
+ returnUrl: string;
66
+ trialDays?: number;
67
+ shopifySubscriptionId?: string;
68
+ confirmationUrl?: string;
69
+ }
70
+ /** Input for creating a usage record. */
71
+ interface CreateUsageRecordInput {
72
+ subscriptionId: string;
73
+ description: string;
74
+ amount: string;
75
+ currencyCode?: string;
76
+ idempotencyKey?: string;
77
+ }
78
+ /** A usage record stored in the database. */
79
+ interface UsageRecord {
80
+ id: string;
81
+ subscriptionId: string;
82
+ description: string;
83
+ amount: string;
84
+ currencyCode: string;
85
+ idempotencyKey: string | null;
86
+ createdAt: Date;
87
+ }
88
+ /** Filter options for querying usage records. */
89
+ interface UsageRecordFilter {
90
+ subscriptionId: string;
91
+ startDate?: Date;
92
+ endDate?: Date;
93
+ }
94
+
95
+ /**
96
+ * Platform-agnostic billing service interface.
97
+ *
98
+ * Defines the contract for billing operations that platform adapters
99
+ * must implement. Core billing service provides the base implementation
100
+ * with Prisma persistence.
101
+ */
102
+
103
+ /** Core billing service for subscription and usage management. */
104
+ interface BillingService {
105
+ /** Create a new subscription record in the database. */
106
+ createSubscription(input: CreateSubscriptionInput): Promise<Subscription>;
107
+ /** Get a subscription by its internal ID. */
108
+ getSubscription(id: string): Promise<Subscription | null>;
109
+ /** Get the currently active subscription for a shop. */
110
+ getActiveSubscription(shopDomain: string): Promise<Subscription | null>;
111
+ /** List all subscriptions for a shop. */
112
+ listSubscriptions(shopDomain: string): Promise<Subscription[]>;
113
+ /** Update subscription status (e.g., from webhook callback). */
114
+ updateSubscriptionStatus(id: string, status: SubscriptionStatus): Promise<Subscription>;
115
+ /** Update a subscription by its Shopify subscription ID. */
116
+ updateSubscriptionByShopifyId(shopifySubscriptionId: string, updates: Partial<Pick<Subscription, 'status' | 'currentPeriodEnd'>>): Promise<Subscription | null>;
117
+ /** Cancel a subscription. */
118
+ cancelSubscription(id: string): Promise<Subscription>;
119
+ /** Create a usage record against a subscription. */
120
+ createUsageRecord(input: CreateUsageRecordInput): Promise<UsageRecord>;
121
+ /** Get usage records with optional date range filtering. */
122
+ getUsageRecords(filter: UsageRecordFilter): Promise<UsageRecord[]>;
123
+ /** Calculate total usage amount for a subscription within a date range. */
124
+ calculateTotalUsage(filter: UsageRecordFilter): Promise<string>;
125
+ }
126
+ /** Plan registry for managing available billing plans. */
127
+ interface PlanRegistry {
128
+ /** Register a billing plan. */
129
+ register(plan: BillingPlan): void;
130
+ /** Get a plan by name. */
131
+ get(name: string): BillingPlan | undefined;
132
+ /** List all registered plans (sorted by sortOrder). */
133
+ list(): BillingPlan[];
134
+ /** Get the default plan (if any). */
135
+ getDefault(): BillingPlan | undefined;
136
+ }
137
+ /** Platform-specific billing adapter for GraphQL operations. */
138
+ interface PlatformBillingAdapter {
139
+ /** Create a subscription via the platform's API (e.g., Shopify GraphQL). */
140
+ createPlatformSubscription(input: {
141
+ shop: string;
142
+ accessToken: string;
143
+ planName: string;
144
+ lineItems: BillingPlan['lineItems'];
145
+ returnUrl: string;
146
+ trialDays?: number;
147
+ }): Promise<{
148
+ shopifySubscriptionId: string;
149
+ confirmationUrl: string;
150
+ }>;
151
+ /** Create a usage record via the platform's API. */
152
+ createPlatformUsageRecord(input: {
153
+ shop: string;
154
+ accessToken: string;
155
+ subscriptionLineItemId: string;
156
+ amount: string;
157
+ currencyCode: string;
158
+ description: string;
159
+ }): Promise<{
160
+ id: string;
161
+ }>;
162
+ /** Cancel a subscription via the platform's API. */
163
+ cancelPlatformSubscription(input: {
164
+ shop: string;
165
+ accessToken: string;
166
+ subscriptionId: string;
167
+ }): Promise<void>;
168
+ }
169
+
170
+ /**
171
+ * Feature gate interfaces for plan-based feature gating.
172
+ *
173
+ * Provides a way to restrict features based on the merchant's
174
+ * active billing plan. Used by route middleware to enforce
175
+ * plan-level access control.
176
+ */
177
+
178
+ /** Maps plan names to the features they include. */
179
+ type PlanFeatureMap = Record<string, string[]>;
180
+ /** Definition of a gated feature. */
181
+ interface FeatureDefinition {
182
+ name: string;
183
+ description: string;
184
+ requiredPlan?: string;
185
+ }
186
+ /** Configuration for the feature gate middleware. */
187
+ interface FeatureGateConfig {
188
+ /** Map of plan names to their included features. */
189
+ planFeatures: PlanFeatureMap;
190
+ /** Function to retrieve the active subscription's plan for a shop. */
191
+ getPlanForShop: (shopDomain: string) => Promise<BillingPlan | null>;
192
+ /** Features available to all shops regardless of plan (free tier). */
193
+ freeFeatures?: string[];
194
+ }
195
+ /** Feature gate middleware for checking plan-based access. */
196
+ interface FeatureGateMiddleware {
197
+ /** Check if a shop has access to a feature. */
198
+ hasFeature(shopDomain: string, featureName: string): Promise<boolean>;
199
+ /** Require a feature — throws FeatureGateError if not available. */
200
+ requireFeature(shopDomain: string, featureName: string): Promise<void>;
201
+ /** Get all available features for a shop based on their plan. */
202
+ getAvailableFeatures(shopDomain: string): Promise<string[]>;
203
+ /** Get the current plan name for a shop (null if no active subscription). */
204
+ getCurrentPlanName(shopDomain: string): Promise<string | null>;
205
+ }
206
+ /** Error thrown when a feature is not available for the current plan. */
207
+ declare class FeatureGateError extends Error {
208
+ readonly featureName: string;
209
+ readonly currentPlan: string | null;
210
+ constructor(featureName: string, currentPlan: string | null);
211
+ }
212
+
213
+ export { type BillingPlan, type BillingService, type CreateSubscriptionInput, type CreateUsageRecordInput, type FeatureDefinition, type FeatureGateConfig, FeatureGateError, type FeatureGateMiddleware, type Money, type PlanFeatureMap, type PlanInterval, type PlanPricing, type PlanRegistry, type PlatformBillingAdapter, type RecurringPricing, type Subscription, type SubscriptionLineItem, type SubscriptionStatus, type UsagePricing, type UsageRecord, type UsageRecordFilter };
@@ -0,0 +1,213 @@
1
+ /**
2
+ * Platform-agnostic billing types.
3
+ *
4
+ * These types define the billing model used across all platform adapters.
5
+ * Platform-specific adapters implement the BillingService interface with
6
+ * their own GraphQL mutations and API calls.
7
+ */
8
+ /** Billing interval for recurring charges. */
9
+ type PlanInterval = 'EVERY_30_DAYS' | 'ANNUAL';
10
+ /** Subscription status lifecycle values. */
11
+ type SubscriptionStatus = 'PENDING' | 'ACTIVE' | 'CANCELLED' | 'EXPIRED' | 'FROZEN' | 'DECLINED';
12
+ /** Monetary value with currency code. */
13
+ interface Money {
14
+ amount: string;
15
+ currencyCode: string;
16
+ }
17
+ /** Pricing configuration for a recurring plan charge. */
18
+ interface RecurringPricing {
19
+ type: 'recurring';
20
+ price: Money;
21
+ interval: PlanInterval;
22
+ }
23
+ /** Pricing configuration for a usage-based charge. */
24
+ interface UsagePricing {
25
+ type: 'usage';
26
+ cappedAmount: Money;
27
+ terms: string;
28
+ }
29
+ /** Union of pricing detail types. */
30
+ type PlanPricing = RecurringPricing | UsagePricing;
31
+ /** A line item within a subscription (one plan can have recurring + usage lines). */
32
+ interface SubscriptionLineItem {
33
+ id: string;
34
+ plan: {
35
+ pricingDetails: PlanPricing;
36
+ };
37
+ }
38
+ /** Billing plan definition. */
39
+ interface BillingPlan {
40
+ name: string;
41
+ description: string;
42
+ lineItems: PlanPricing[];
43
+ features: string[];
44
+ trialDays?: number;
45
+ isDefault?: boolean;
46
+ sortOrder?: number;
47
+ }
48
+ /** A subscription record stored in the database. */
49
+ interface Subscription {
50
+ id: string;
51
+ shopDomain: string;
52
+ shopifySubscriptionId: string | null;
53
+ planName: string;
54
+ status: SubscriptionStatus;
55
+ currentPeriodEnd: Date | null;
56
+ trialEndsAt: Date | null;
57
+ confirmationUrl: string | null;
58
+ createdAt: Date;
59
+ updatedAt: Date;
60
+ }
61
+ /** Input for creating a new subscription. */
62
+ interface CreateSubscriptionInput {
63
+ shopDomain: string;
64
+ planName: string;
65
+ returnUrl: string;
66
+ trialDays?: number;
67
+ shopifySubscriptionId?: string;
68
+ confirmationUrl?: string;
69
+ }
70
+ /** Input for creating a usage record. */
71
+ interface CreateUsageRecordInput {
72
+ subscriptionId: string;
73
+ description: string;
74
+ amount: string;
75
+ currencyCode?: string;
76
+ idempotencyKey?: string;
77
+ }
78
+ /** A usage record stored in the database. */
79
+ interface UsageRecord {
80
+ id: string;
81
+ subscriptionId: string;
82
+ description: string;
83
+ amount: string;
84
+ currencyCode: string;
85
+ idempotencyKey: string | null;
86
+ createdAt: Date;
87
+ }
88
+ /** Filter options for querying usage records. */
89
+ interface UsageRecordFilter {
90
+ subscriptionId: string;
91
+ startDate?: Date;
92
+ endDate?: Date;
93
+ }
94
+
95
+ /**
96
+ * Platform-agnostic billing service interface.
97
+ *
98
+ * Defines the contract for billing operations that platform adapters
99
+ * must implement. Core billing service provides the base implementation
100
+ * with Prisma persistence.
101
+ */
102
+
103
+ /** Core billing service for subscription and usage management. */
104
+ interface BillingService {
105
+ /** Create a new subscription record in the database. */
106
+ createSubscription(input: CreateSubscriptionInput): Promise<Subscription>;
107
+ /** Get a subscription by its internal ID. */
108
+ getSubscription(id: string): Promise<Subscription | null>;
109
+ /** Get the currently active subscription for a shop. */
110
+ getActiveSubscription(shopDomain: string): Promise<Subscription | null>;
111
+ /** List all subscriptions for a shop. */
112
+ listSubscriptions(shopDomain: string): Promise<Subscription[]>;
113
+ /** Update subscription status (e.g., from webhook callback). */
114
+ updateSubscriptionStatus(id: string, status: SubscriptionStatus): Promise<Subscription>;
115
+ /** Update a subscription by its Shopify subscription ID. */
116
+ updateSubscriptionByShopifyId(shopifySubscriptionId: string, updates: Partial<Pick<Subscription, 'status' | 'currentPeriodEnd'>>): Promise<Subscription | null>;
117
+ /** Cancel a subscription. */
118
+ cancelSubscription(id: string): Promise<Subscription>;
119
+ /** Create a usage record against a subscription. */
120
+ createUsageRecord(input: CreateUsageRecordInput): Promise<UsageRecord>;
121
+ /** Get usage records with optional date range filtering. */
122
+ getUsageRecords(filter: UsageRecordFilter): Promise<UsageRecord[]>;
123
+ /** Calculate total usage amount for a subscription within a date range. */
124
+ calculateTotalUsage(filter: UsageRecordFilter): Promise<string>;
125
+ }
126
+ /** Plan registry for managing available billing plans. */
127
+ interface PlanRegistry {
128
+ /** Register a billing plan. */
129
+ register(plan: BillingPlan): void;
130
+ /** Get a plan by name. */
131
+ get(name: string): BillingPlan | undefined;
132
+ /** List all registered plans (sorted by sortOrder). */
133
+ list(): BillingPlan[];
134
+ /** Get the default plan (if any). */
135
+ getDefault(): BillingPlan | undefined;
136
+ }
137
+ /** Platform-specific billing adapter for GraphQL operations. */
138
+ interface PlatformBillingAdapter {
139
+ /** Create a subscription via the platform's API (e.g., Shopify GraphQL). */
140
+ createPlatformSubscription(input: {
141
+ shop: string;
142
+ accessToken: string;
143
+ planName: string;
144
+ lineItems: BillingPlan['lineItems'];
145
+ returnUrl: string;
146
+ trialDays?: number;
147
+ }): Promise<{
148
+ shopifySubscriptionId: string;
149
+ confirmationUrl: string;
150
+ }>;
151
+ /** Create a usage record via the platform's API. */
152
+ createPlatformUsageRecord(input: {
153
+ shop: string;
154
+ accessToken: string;
155
+ subscriptionLineItemId: string;
156
+ amount: string;
157
+ currencyCode: string;
158
+ description: string;
159
+ }): Promise<{
160
+ id: string;
161
+ }>;
162
+ /** Cancel a subscription via the platform's API. */
163
+ cancelPlatformSubscription(input: {
164
+ shop: string;
165
+ accessToken: string;
166
+ subscriptionId: string;
167
+ }): Promise<void>;
168
+ }
169
+
170
+ /**
171
+ * Feature gate interfaces for plan-based feature gating.
172
+ *
173
+ * Provides a way to restrict features based on the merchant's
174
+ * active billing plan. Used by route middleware to enforce
175
+ * plan-level access control.
176
+ */
177
+
178
+ /** Maps plan names to the features they include. */
179
+ type PlanFeatureMap = Record<string, string[]>;
180
+ /** Definition of a gated feature. */
181
+ interface FeatureDefinition {
182
+ name: string;
183
+ description: string;
184
+ requiredPlan?: string;
185
+ }
186
+ /** Configuration for the feature gate middleware. */
187
+ interface FeatureGateConfig {
188
+ /** Map of plan names to their included features. */
189
+ planFeatures: PlanFeatureMap;
190
+ /** Function to retrieve the active subscription's plan for a shop. */
191
+ getPlanForShop: (shopDomain: string) => Promise<BillingPlan | null>;
192
+ /** Features available to all shops regardless of plan (free tier). */
193
+ freeFeatures?: string[];
194
+ }
195
+ /** Feature gate middleware for checking plan-based access. */
196
+ interface FeatureGateMiddleware {
197
+ /** Check if a shop has access to a feature. */
198
+ hasFeature(shopDomain: string, featureName: string): Promise<boolean>;
199
+ /** Require a feature — throws FeatureGateError if not available. */
200
+ requireFeature(shopDomain: string, featureName: string): Promise<void>;
201
+ /** Get all available features for a shop based on their plan. */
202
+ getAvailableFeatures(shopDomain: string): Promise<string[]>;
203
+ /** Get the current plan name for a shop (null if no active subscription). */
204
+ getCurrentPlanName(shopDomain: string): Promise<string | null>;
205
+ }
206
+ /** Error thrown when a feature is not available for the current plan. */
207
+ declare class FeatureGateError extends Error {
208
+ readonly featureName: string;
209
+ readonly currentPlan: string | null;
210
+ constructor(featureName: string, currentPlan: string | null);
211
+ }
212
+
213
+ export { type BillingPlan, type BillingService, type CreateSubscriptionInput, type CreateUsageRecordInput, type FeatureDefinition, type FeatureGateConfig, FeatureGateError, type FeatureGateMiddleware, type Money, type PlanFeatureMap, type PlanInterval, type PlanPricing, type PlanRegistry, type PlatformBillingAdapter, type RecurringPricing, type Subscription, type SubscriptionLineItem, type SubscriptionStatus, type UsagePricing, type UsageRecord, type UsageRecordFilter };
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/billing/index.ts
21
+ var billing_exports = {};
22
+ __export(billing_exports, {
23
+ FeatureGateError: () => FeatureGateError
24
+ });
25
+ module.exports = __toCommonJS(billing_exports);
26
+
27
+ // src/billing/feature-gate.ts
28
+ var FeatureGateError = class extends Error {
29
+ featureName;
30
+ currentPlan;
31
+ constructor(featureName, currentPlan) {
32
+ const planInfo = currentPlan ? `plan "${currentPlan}"` : "no active plan";
33
+ super(`Feature "${featureName}" is not available with ${planInfo}`);
34
+ this.name = "FeatureGateError";
35
+ this.featureName = featureName;
36
+ this.currentPlan = currentPlan;
37
+ }
38
+ };
39
+ // Annotate the CommonJS export names for ESM import in node:
40
+ 0 && (module.exports = {
41
+ FeatureGateError
42
+ });
43
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/billing/index.ts","../../src/billing/feature-gate.ts"],"sourcesContent":["/**\n * @uniforge/platform-core/billing\n *\n * Platform-agnostic billing interfaces for subscription management,\n * usage billing, plan definitions, and feature gating.\n */\n\nexport type {\n PlanInterval,\n SubscriptionStatus,\n Money,\n RecurringPricing,\n UsagePricing,\n PlanPricing,\n SubscriptionLineItem,\n BillingPlan,\n Subscription,\n CreateSubscriptionInput,\n CreateUsageRecordInput,\n UsageRecord,\n UsageRecordFilter,\n} from './types.js';\n\nexport type {\n BillingService,\n PlanRegistry,\n PlatformBillingAdapter,\n} from './service.js';\n\nexport type {\n PlanFeatureMap,\n FeatureDefinition,\n FeatureGateConfig,\n FeatureGateMiddleware,\n} from './feature-gate.js';\n\nexport { FeatureGateError } from './feature-gate.js';\n","/**\n * Feature gate interfaces for plan-based feature gating.\n *\n * Provides a way to restrict features based on the merchant's\n * active billing plan. Used by route middleware to enforce\n * plan-level access control.\n */\n\nimport type { BillingPlan } from './types.js';\n\n/** Maps plan names to the features they include. */\nexport type PlanFeatureMap = Record<string, string[]>;\n\n/** Definition of a gated feature. */\nexport interface FeatureDefinition {\n name: string;\n description: string;\n requiredPlan?: string;\n}\n\n/** Configuration for the feature gate middleware. */\nexport interface FeatureGateConfig {\n /** Map of plan names to their included features. */\n planFeatures: PlanFeatureMap;\n\n /** Function to retrieve the active subscription's plan for a shop. */\n getPlanForShop: (shopDomain: string) => Promise<BillingPlan | null>;\n\n /** Features available to all shops regardless of plan (free tier). */\n freeFeatures?: string[];\n}\n\n/** Feature gate middleware for checking plan-based access. */\nexport interface FeatureGateMiddleware {\n /** Check if a shop has access to a feature. */\n hasFeature(shopDomain: string, featureName: string): Promise<boolean>;\n\n /** Require a feature — throws FeatureGateError if not available. */\n requireFeature(shopDomain: string, featureName: string): Promise<void>;\n\n /** Get all available features for a shop based on their plan. */\n getAvailableFeatures(shopDomain: string): Promise<string[]>;\n\n /** Get the current plan name for a shop (null if no active subscription). */\n getCurrentPlanName(shopDomain: string): Promise<string | null>;\n}\n\n/** Error thrown when a feature is not available for the current plan. */\nexport class FeatureGateError extends Error {\n public readonly featureName: string;\n public readonly currentPlan: string | null;\n\n constructor(featureName: string, currentPlan: string | null) {\n const planInfo = currentPlan ? `plan \"${currentPlan}\"` : 'no active plan';\n super(`Feature \"${featureName}\" is not available with ${planInfo}`);\n this.name = 'FeatureGateError';\n this.featureName = featureName;\n this.currentPlan = currentPlan;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACgDO,IAAM,mBAAN,cAA+B,MAAM;AAAA,EAC1B;AAAA,EACA;AAAA,EAEhB,YAAY,aAAqB,aAA4B;AAC3D,UAAM,WAAW,cAAc,SAAS,WAAW,MAAM;AACzD,UAAM,YAAY,WAAW,2BAA2B,QAAQ,EAAE;AAClE,SAAK,OAAO;AACZ,SAAK,cAAc;AACnB,SAAK,cAAc;AAAA,EACrB;AACF;","names":[]}
@@ -0,0 +1,16 @@
1
+ // src/billing/feature-gate.ts
2
+ var FeatureGateError = class extends Error {
3
+ featureName;
4
+ currentPlan;
5
+ constructor(featureName, currentPlan) {
6
+ const planInfo = currentPlan ? `plan "${currentPlan}"` : "no active plan";
7
+ super(`Feature "${featureName}" is not available with ${planInfo}`);
8
+ this.name = "FeatureGateError";
9
+ this.featureName = featureName;
10
+ this.currentPlan = currentPlan;
11
+ }
12
+ };
13
+ export {
14
+ FeatureGateError
15
+ };
16
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/billing/feature-gate.ts"],"sourcesContent":["/**\n * Feature gate interfaces for plan-based feature gating.\n *\n * Provides a way to restrict features based on the merchant's\n * active billing plan. Used by route middleware to enforce\n * plan-level access control.\n */\n\nimport type { BillingPlan } from './types.js';\n\n/** Maps plan names to the features they include. */\nexport type PlanFeatureMap = Record<string, string[]>;\n\n/** Definition of a gated feature. */\nexport interface FeatureDefinition {\n name: string;\n description: string;\n requiredPlan?: string;\n}\n\n/** Configuration for the feature gate middleware. */\nexport interface FeatureGateConfig {\n /** Map of plan names to their included features. */\n planFeatures: PlanFeatureMap;\n\n /** Function to retrieve the active subscription's plan for a shop. */\n getPlanForShop: (shopDomain: string) => Promise<BillingPlan | null>;\n\n /** Features available to all shops regardless of plan (free tier). */\n freeFeatures?: string[];\n}\n\n/** Feature gate middleware for checking plan-based access. */\nexport interface FeatureGateMiddleware {\n /** Check if a shop has access to a feature. */\n hasFeature(shopDomain: string, featureName: string): Promise<boolean>;\n\n /** Require a feature — throws FeatureGateError if not available. */\n requireFeature(shopDomain: string, featureName: string): Promise<void>;\n\n /** Get all available features for a shop based on their plan. */\n getAvailableFeatures(shopDomain: string): Promise<string[]>;\n\n /** Get the current plan name for a shop (null if no active subscription). */\n getCurrentPlanName(shopDomain: string): Promise<string | null>;\n}\n\n/** Error thrown when a feature is not available for the current plan. */\nexport class FeatureGateError extends Error {\n public readonly featureName: string;\n public readonly currentPlan: string | null;\n\n constructor(featureName: string, currentPlan: string | null) {\n const planInfo = currentPlan ? `plan \"${currentPlan}\"` : 'no active plan';\n super(`Feature \"${featureName}\" is not available with ${planInfo}`);\n this.name = 'FeatureGateError';\n this.featureName = featureName;\n this.currentPlan = currentPlan;\n }\n}\n"],"mappings":";AAgDO,IAAM,mBAAN,cAA+B,MAAM;AAAA,EAC1B;AAAA,EACA;AAAA,EAEhB,YAAY,aAAqB,aAA4B;AAC3D,UAAM,WAAW,cAAc,SAAS,WAAW,MAAM;AACzD,UAAM,YAAY,WAAW,2BAA2B,QAAQ,EAAE;AAClE,SAAK,OAAO;AACZ,SAAK,cAAc;AACnB,SAAK,cAAc;AAAA,EACrB;AACF;","names":[]}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Platform-agnostic GraphQL client types.
3
+ *
4
+ * These types define the GraphQL client interface used across all platform adapters.
5
+ * Platform-specific adapters wrap the base client with features like rate limiting
6
+ * and caching.
7
+ */
8
+ /** Platform-agnostic GraphQL client interface. */
9
+ interface GraphQLClient {
10
+ query<T = unknown>(query: string, variables?: Record<string, unknown>): Promise<GraphQLResponse<T>>;
11
+ mutate<T = unknown>(mutation: string, variables?: Record<string, unknown>): Promise<GraphQLResponse<T>>;
12
+ }
13
+ /** Response from a GraphQL operation. */
14
+ interface GraphQLResponse<T = unknown> {
15
+ data?: T;
16
+ errors?: GraphQLError[];
17
+ extensions?: GraphQLExtensions;
18
+ }
19
+ /** A single GraphQL error. */
20
+ interface GraphQLError {
21
+ message: string;
22
+ locations?: Array<{
23
+ line: number;
24
+ column: number;
25
+ }>;
26
+ path?: Array<string | number>;
27
+ extensions?: Record<string, unknown>;
28
+ }
29
+ /** GraphQL response extensions including query cost information. */
30
+ interface GraphQLExtensions {
31
+ cost?: QueryCost;
32
+ [key: string]: unknown;
33
+ }
34
+ /** Shopify query cost information returned in response extensions. */
35
+ interface QueryCost {
36
+ requestedQueryCost: number;
37
+ actualQueryCost: number;
38
+ throttleStatus: ThrottleStatus;
39
+ }
40
+ /** Shopify API throttle status from query cost extensions. */
41
+ interface ThrottleStatus {
42
+ maximumAvailable: number;
43
+ currentlyAvailable: number;
44
+ restoreRate: number;
45
+ }
46
+ /** Configuration for creating a GraphQL client. */
47
+ interface GraphQLClientConfig {
48
+ shop: string;
49
+ accessToken: string;
50
+ apiVersion: string;
51
+ maxRetries?: number;
52
+ timeoutMs?: number;
53
+ }
54
+
55
+ /**
56
+ * Platform-agnostic rate limiting interfaces for GraphQL clients.
57
+ *
58
+ * Supports leaky bucket rate limiting based on Shopify's query cost system.
59
+ */
60
+
61
+ /** Rate limiter that controls GraphQL request throughput. */
62
+ interface RateLimiter {
63
+ acquire(): Promise<void>;
64
+ getStatus(): RateLimitStatus;
65
+ updateFromResponse(cost?: QueryCost): void;
66
+ }
67
+ /** Current rate limit status. */
68
+ interface RateLimitStatus {
69
+ available: number;
70
+ maximum: number;
71
+ restoreRate: number;
72
+ }
73
+ /** Configuration for rate limiter creation. */
74
+ interface RateLimitConfig {
75
+ maxAvailable?: number;
76
+ restoreRatePerSecond?: number;
77
+ minimumAvailable?: number;
78
+ }
79
+
80
+ /**
81
+ * Platform-agnostic GraphQL caching interfaces.
82
+ *
83
+ * Provides a cache layer for GraphQL query results to reduce API calls
84
+ * and improve response times.
85
+ */
86
+ /** Cache for GraphQL query results. */
87
+ interface GraphQLCache {
88
+ get<T = unknown>(key: string): Promise<T | undefined>;
89
+ set<T = unknown>(key: string, value: T, ttlSeconds?: number): Promise<void>;
90
+ invalidate(pattern: string): Promise<void>;
91
+ clear(): Promise<void>;
92
+ }
93
+ /** Configuration for GraphQL cache creation. */
94
+ interface CacheConfig {
95
+ enabled?: boolean;
96
+ defaultTtlSeconds?: number;
97
+ keyPrefix?: string;
98
+ }
99
+
100
+ export type { CacheConfig, GraphQLCache, GraphQLClient, GraphQLClientConfig, GraphQLError, GraphQLExtensions, GraphQLResponse, QueryCost, RateLimitConfig, RateLimitStatus, RateLimiter, ThrottleStatus };