@uniforge/testing 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.
- package/dist/auth/index.d.cts +177 -0
- package/dist/auth/index.d.ts +177 -0
- package/dist/auth/index.js +459 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/index.mjs +418 -0
- package/dist/auth/index.mjs.map +1 -0
- package/dist/billing/index.d.cts +27 -0
- package/dist/billing/index.d.ts +27 -0
- package/dist/billing/index.js +208 -0
- package/dist/billing/index.js.map +1 -0
- package/dist/billing/index.mjs +178 -0
- package/dist/billing/index.mjs.map +1 -0
- package/dist/database/index.d.cts +399 -0
- package/dist/database/index.d.ts +399 -0
- package/dist/database/index.js +19054 -0
- package/dist/database/index.js.map +1 -0
- package/dist/database/index.mjs +19046 -0
- package/dist/database/index.mjs.map +1 -0
- package/dist/graphql/index.d.cts +23 -0
- package/dist/graphql/index.d.ts +23 -0
- package/dist/graphql/index.js +18511 -0
- package/dist/graphql/index.js.map +1 -0
- package/dist/graphql/index.mjs +18505 -0
- package/dist/graphql/index.mjs.map +1 -0
- package/dist/index.d.cts +10 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +6 -0
- package/dist/index.mjs.map +1 -0
- package/dist/multi-store/index.d.cts +66 -0
- package/dist/multi-store/index.d.ts +66 -0
- package/dist/multi-store/index.js +319 -0
- package/dist/multi-store/index.js.map +1 -0
- package/dist/multi-store/index.mjs +287 -0
- package/dist/multi-store/index.mjs.map +1 -0
- package/dist/multi-tenant/index.d.cts +15 -0
- package/dist/multi-tenant/index.d.ts +15 -0
- package/dist/multi-tenant/index.js +87 -0
- package/dist/multi-tenant/index.js.map +1 -0
- package/dist/multi-tenant/index.mjs +57 -0
- package/dist/multi-tenant/index.mjs.map +1 -0
- package/dist/performance/index.d.cts +60 -0
- package/dist/performance/index.d.ts +60 -0
- package/dist/performance/index.js +280 -0
- package/dist/performance/index.js.map +1 -0
- package/dist/performance/index.mjs +246 -0
- package/dist/performance/index.mjs.map +1 -0
- package/dist/platform/index.d.cts +71 -0
- package/dist/platform/index.d.ts +71 -0
- package/dist/platform/index.js +435 -0
- package/dist/platform/index.js.map +1 -0
- package/dist/platform/index.mjs +396 -0
- package/dist/platform/index.mjs.map +1 -0
- package/dist/rbac/index.d.cts +21 -0
- package/dist/rbac/index.d.ts +21 -0
- package/dist/rbac/index.js +178 -0
- package/dist/rbac/index.js.map +1 -0
- package/dist/rbac/index.mjs +150 -0
- package/dist/rbac/index.mjs.map +1 -0
- package/dist/security/index.d.cts +73 -0
- package/dist/security/index.d.ts +73 -0
- package/dist/security/index.js +246 -0
- package/dist/security/index.js.map +1 -0
- package/dist/security/index.mjs +211 -0
- package/dist/security/index.mjs.map +1 -0
- package/dist/shopify-api/index.d.cts +139 -0
- package/dist/shopify-api/index.d.ts +139 -0
- package/dist/shopify-api/index.js +469 -0
- package/dist/shopify-api/index.js.map +1 -0
- package/dist/shopify-api/index.mjs +439 -0
- package/dist/shopify-api/index.mjs.map +1 -0
- package/dist/shopify-compliance/index.d.cts +85 -0
- package/dist/shopify-compliance/index.d.ts +85 -0
- package/dist/shopify-compliance/index.js +287 -0
- package/dist/shopify-compliance/index.js.map +1 -0
- package/dist/shopify-compliance/index.mjs +259 -0
- package/dist/shopify-compliance/index.mjs.map +1 -0
- package/dist/webhooks/index.d.cts +127 -0
- package/dist/webhooks/index.d.ts +127 -0
- package/dist/webhooks/index.js +18934 -0
- package/dist/webhooks/index.js.map +1 -0
- package/dist/webhooks/index.mjs +18916 -0
- package/dist/webhooks/index.mjs.map +1 -0
- package/package.json +112 -0
|
@@ -0,0 +1,208 @@
|
|
|
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
|
+
createMockBillingService: () => createMockBillingService,
|
|
24
|
+
createTestPlan: () => createTestPlan,
|
|
25
|
+
createTestSubscription: () => createTestSubscription,
|
|
26
|
+
createTestUsageRecord: () => createTestUsageRecord
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(billing_exports);
|
|
29
|
+
|
|
30
|
+
// src/billing/mock-billing-service.ts
|
|
31
|
+
function createMockBillingService() {
|
|
32
|
+
const _subscriptions = /* @__PURE__ */ new Map();
|
|
33
|
+
const _usageRecords = /* @__PURE__ */ new Map();
|
|
34
|
+
function _reset() {
|
|
35
|
+
_subscriptions.clear();
|
|
36
|
+
_usageRecords.clear();
|
|
37
|
+
}
|
|
38
|
+
async function createSubscription(input) {
|
|
39
|
+
const id = `mock-sub-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
40
|
+
const now = /* @__PURE__ */ new Date();
|
|
41
|
+
const sub = {
|
|
42
|
+
id,
|
|
43
|
+
shopDomain: input.shopDomain,
|
|
44
|
+
shopifySubscriptionId: null,
|
|
45
|
+
planName: input.planName,
|
|
46
|
+
status: "PENDING",
|
|
47
|
+
currentPeriodEnd: null,
|
|
48
|
+
trialEndsAt: null,
|
|
49
|
+
confirmationUrl: null,
|
|
50
|
+
createdAt: now,
|
|
51
|
+
updatedAt: now
|
|
52
|
+
};
|
|
53
|
+
if (input.shopifySubscriptionId) {
|
|
54
|
+
sub.shopifySubscriptionId = input.shopifySubscriptionId;
|
|
55
|
+
}
|
|
56
|
+
if (input.confirmationUrl) {
|
|
57
|
+
sub.confirmationUrl = input.confirmationUrl;
|
|
58
|
+
}
|
|
59
|
+
_subscriptions.set(id, sub);
|
|
60
|
+
return sub;
|
|
61
|
+
}
|
|
62
|
+
async function getSubscription(id) {
|
|
63
|
+
return _subscriptions.get(id) ?? null;
|
|
64
|
+
}
|
|
65
|
+
async function getActiveSubscription(shopDomain) {
|
|
66
|
+
for (const sub of _subscriptions.values()) {
|
|
67
|
+
if (sub.shopDomain === shopDomain && sub.status === "ACTIVE") {
|
|
68
|
+
return sub;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
async function listSubscriptions(shopDomain) {
|
|
74
|
+
const result = [];
|
|
75
|
+
for (const sub of _subscriptions.values()) {
|
|
76
|
+
if (sub.shopDomain === shopDomain) {
|
|
77
|
+
result.push(sub);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return result;
|
|
81
|
+
}
|
|
82
|
+
async function updateSubscriptionStatus(id, status) {
|
|
83
|
+
const sub = _subscriptions.get(id);
|
|
84
|
+
if (!sub) {
|
|
85
|
+
throw new Error(`Subscription not found: ${id}`);
|
|
86
|
+
}
|
|
87
|
+
sub.status = status;
|
|
88
|
+
sub.updatedAt = /* @__PURE__ */ new Date();
|
|
89
|
+
return sub;
|
|
90
|
+
}
|
|
91
|
+
async function updateSubscriptionByShopifyId(shopifySubscriptionId, updates) {
|
|
92
|
+
for (const sub of _subscriptions.values()) {
|
|
93
|
+
if (sub.shopifySubscriptionId === shopifySubscriptionId) {
|
|
94
|
+
if (updates.status) {
|
|
95
|
+
sub.status = updates.status;
|
|
96
|
+
}
|
|
97
|
+
if (updates.currentPeriodEnd) {
|
|
98
|
+
sub.currentPeriodEnd = updates.currentPeriodEnd;
|
|
99
|
+
}
|
|
100
|
+
sub.updatedAt = /* @__PURE__ */ new Date();
|
|
101
|
+
return sub;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
async function cancelSubscription(id) {
|
|
107
|
+
const sub = _subscriptions.get(id);
|
|
108
|
+
if (!sub) {
|
|
109
|
+
throw new Error(`Subscription not found: ${id}`);
|
|
110
|
+
}
|
|
111
|
+
sub.status = "CANCELLED";
|
|
112
|
+
sub.updatedAt = /* @__PURE__ */ new Date();
|
|
113
|
+
return sub;
|
|
114
|
+
}
|
|
115
|
+
async function createUsageRecord(input) {
|
|
116
|
+
const id = `mock-usage-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
117
|
+
const record = {
|
|
118
|
+
id,
|
|
119
|
+
subscriptionId: input.subscriptionId,
|
|
120
|
+
description: input.description,
|
|
121
|
+
amount: input.amount,
|
|
122
|
+
currencyCode: input.currencyCode ?? "USD",
|
|
123
|
+
idempotencyKey: input.idempotencyKey ?? null,
|
|
124
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
125
|
+
};
|
|
126
|
+
const existing = _usageRecords.get(input.subscriptionId) ?? [];
|
|
127
|
+
existing.push(record);
|
|
128
|
+
_usageRecords.set(input.subscriptionId, existing);
|
|
129
|
+
return record;
|
|
130
|
+
}
|
|
131
|
+
async function getUsageRecords(filter) {
|
|
132
|
+
const records = _usageRecords.get(filter.subscriptionId) ?? [];
|
|
133
|
+
return records.filter((r) => {
|
|
134
|
+
if (filter.startDate && r.createdAt < filter.startDate) return false;
|
|
135
|
+
if (filter.endDate && r.createdAt > filter.endDate) return false;
|
|
136
|
+
return true;
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
async function calculateTotalUsage(filter) {
|
|
140
|
+
const records = await getUsageRecords(filter);
|
|
141
|
+
const total = records.reduce((sum, r) => sum + parseFloat(r.amount), 0);
|
|
142
|
+
return total.toString();
|
|
143
|
+
}
|
|
144
|
+
return {
|
|
145
|
+
_subscriptions,
|
|
146
|
+
_usageRecords,
|
|
147
|
+
_reset,
|
|
148
|
+
createSubscription,
|
|
149
|
+
getSubscription,
|
|
150
|
+
getActiveSubscription,
|
|
151
|
+
listSubscriptions,
|
|
152
|
+
updateSubscriptionStatus,
|
|
153
|
+
updateSubscriptionByShopifyId,
|
|
154
|
+
cancelSubscription,
|
|
155
|
+
createUsageRecord,
|
|
156
|
+
getUsageRecords,
|
|
157
|
+
calculateTotalUsage
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// src/billing/factories.ts
|
|
162
|
+
function createTestPlan(overrides) {
|
|
163
|
+
const defaults = {
|
|
164
|
+
name: "Basic",
|
|
165
|
+
description: "Basic plan for testing",
|
|
166
|
+
lineItems: [
|
|
167
|
+
{ type: "recurring", price: { amount: "9.99", currencyCode: "USD" }, interval: "EVERY_30_DAYS" }
|
|
168
|
+
],
|
|
169
|
+
features: ["feature-a", "feature-b"]
|
|
170
|
+
};
|
|
171
|
+
return { ...defaults, ...overrides };
|
|
172
|
+
}
|
|
173
|
+
function createTestSubscription(overrides) {
|
|
174
|
+
const now = /* @__PURE__ */ new Date();
|
|
175
|
+
const defaults = {
|
|
176
|
+
id: `sub-${Date.now()}`,
|
|
177
|
+
shopDomain: "test-shop.myshopify.com",
|
|
178
|
+
shopifySubscriptionId: null,
|
|
179
|
+
planName: "Basic",
|
|
180
|
+
status: "ACTIVE",
|
|
181
|
+
currentPeriodEnd: null,
|
|
182
|
+
trialEndsAt: null,
|
|
183
|
+
confirmationUrl: null,
|
|
184
|
+
createdAt: now,
|
|
185
|
+
updatedAt: now
|
|
186
|
+
};
|
|
187
|
+
return { ...defaults, ...overrides };
|
|
188
|
+
}
|
|
189
|
+
function createTestUsageRecord(overrides) {
|
|
190
|
+
const defaults = {
|
|
191
|
+
id: `usage-${Date.now()}`,
|
|
192
|
+
subscriptionId: "sub-test",
|
|
193
|
+
description: "Test usage record",
|
|
194
|
+
amount: "1.50",
|
|
195
|
+
currencyCode: "USD",
|
|
196
|
+
idempotencyKey: null,
|
|
197
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
198
|
+
};
|
|
199
|
+
return { ...defaults, ...overrides };
|
|
200
|
+
}
|
|
201
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
202
|
+
0 && (module.exports = {
|
|
203
|
+
createMockBillingService,
|
|
204
|
+
createTestPlan,
|
|
205
|
+
createTestSubscription,
|
|
206
|
+
createTestUsageRecord
|
|
207
|
+
});
|
|
208
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/billing/index.ts","../../src/billing/mock-billing-service.ts","../../src/billing/factories.ts"],"sourcesContent":["/**\n * @uniforge/testing - Billing\n *\n * Mock billing service and test data factories for billing testing.\n */\n\nexport { createMockBillingService } from './mock-billing-service';\nexport type { MockBillingService } from './mock-billing-service';\nexport {\n createTestPlan,\n createTestSubscription,\n createTestUsageRecord,\n} from './factories';\n","/**\n * Mock BillingService for unit testing.\n *\n * Provides an in-memory implementation of BillingService with\n * internal maps for subscriptions and usage records.\n */\n\nimport type {\n BillingService,\n Subscription,\n SubscriptionStatus,\n UsageRecord,\n CreateSubscriptionInput,\n CreateUsageRecordInput,\n UsageRecordFilter,\n} from '@uniforge/platform-core/billing';\n\nexport type MockBillingService = BillingService & {\n _subscriptions: Map<string, Subscription>;\n _usageRecords: Map<string, UsageRecord[]>;\n _reset(): void;\n};\n\nexport function createMockBillingService(): MockBillingService {\n const _subscriptions = new Map<string, Subscription>();\n const _usageRecords = new Map<string, UsageRecord[]>();\n\n function _reset(): void {\n _subscriptions.clear();\n _usageRecords.clear();\n }\n\n async function createSubscription(input: CreateSubscriptionInput): Promise<Subscription> {\n const id = `mock-sub-${Date.now()}-${Math.random().toString(36).slice(2)}`;\n const now = new Date();\n const sub: Subscription = {\n id,\n shopDomain: input.shopDomain,\n shopifySubscriptionId: null,\n planName: input.planName,\n status: 'PENDING',\n currentPeriodEnd: null,\n trialEndsAt: null,\n confirmationUrl: null,\n createdAt: now,\n updatedAt: now,\n };\n if (input.shopifySubscriptionId) {\n sub.shopifySubscriptionId = input.shopifySubscriptionId;\n }\n if (input.confirmationUrl) {\n sub.confirmationUrl = input.confirmationUrl;\n }\n _subscriptions.set(id, sub);\n return sub;\n }\n\n async function getSubscription(id: string): Promise<Subscription | null> {\n return _subscriptions.get(id) ?? null;\n }\n\n async function getActiveSubscription(shopDomain: string): Promise<Subscription | null> {\n for (const sub of _subscriptions.values()) {\n if (sub.shopDomain === shopDomain && sub.status === 'ACTIVE') {\n return sub;\n }\n }\n return null;\n }\n\n async function listSubscriptions(shopDomain: string): Promise<Subscription[]> {\n const result: Subscription[] = [];\n for (const sub of _subscriptions.values()) {\n if (sub.shopDomain === shopDomain) {\n result.push(sub);\n }\n }\n return result;\n }\n\n async function updateSubscriptionStatus(\n id: string,\n status: SubscriptionStatus,\n ): Promise<Subscription> {\n const sub = _subscriptions.get(id);\n if (!sub) {\n throw new Error(`Subscription not found: ${id}`);\n }\n sub.status = status;\n sub.updatedAt = new Date();\n return sub;\n }\n\n async function updateSubscriptionByShopifyId(\n shopifySubscriptionId: string,\n updates: Partial<Pick<Subscription, 'status' | 'currentPeriodEnd'>>,\n ): Promise<Subscription | null> {\n for (const sub of _subscriptions.values()) {\n if (sub.shopifySubscriptionId === shopifySubscriptionId) {\n if (updates.status) {\n sub.status = updates.status;\n }\n if (updates.currentPeriodEnd) {\n sub.currentPeriodEnd = updates.currentPeriodEnd;\n }\n sub.updatedAt = new Date();\n return sub;\n }\n }\n return null;\n }\n\n async function cancelSubscription(id: string): Promise<Subscription> {\n const sub = _subscriptions.get(id);\n if (!sub) {\n throw new Error(`Subscription not found: ${id}`);\n }\n sub.status = 'CANCELLED';\n sub.updatedAt = new Date();\n return sub;\n }\n\n async function createUsageRecord(input: CreateUsageRecordInput): Promise<UsageRecord> {\n const id = `mock-usage-${Date.now()}-${Math.random().toString(36).slice(2)}`;\n const record: UsageRecord = {\n id,\n subscriptionId: input.subscriptionId,\n description: input.description,\n amount: input.amount,\n currencyCode: input.currencyCode ?? 'USD',\n idempotencyKey: input.idempotencyKey ?? null,\n createdAt: new Date(),\n };\n const existing = _usageRecords.get(input.subscriptionId) ?? [];\n existing.push(record);\n _usageRecords.set(input.subscriptionId, existing);\n return record;\n }\n\n async function getUsageRecords(filter: UsageRecordFilter): Promise<UsageRecord[]> {\n const records = _usageRecords.get(filter.subscriptionId) ?? [];\n return records.filter((r) => {\n if (filter.startDate && r.createdAt < filter.startDate) return false;\n if (filter.endDate && r.createdAt > filter.endDate) return false;\n return true;\n });\n }\n\n async function calculateTotalUsage(filter: UsageRecordFilter): Promise<string> {\n const records = await getUsageRecords(filter);\n const total = records.reduce((sum, r) => sum + parseFloat(r.amount), 0);\n return total.toString();\n }\n\n return {\n _subscriptions,\n _usageRecords,\n _reset,\n createSubscription,\n getSubscription,\n getActiveSubscription,\n listSubscriptions,\n updateSubscriptionStatus,\n updateSubscriptionByShopifyId,\n cancelSubscription,\n createUsageRecord,\n getUsageRecords,\n calculateTotalUsage,\n };\n}\n","/**\n * Test data factories for billing types.\n *\n * Each factory provides sensible defaults that can be overridden.\n */\n\nimport type {\n BillingPlan,\n Subscription,\n UsageRecord,\n} from '@uniforge/platform-core/billing';\n\nexport function createTestPlan(overrides?: Partial<BillingPlan>): BillingPlan {\n const defaults: BillingPlan = {\n name: 'Basic',\n description: 'Basic plan for testing',\n lineItems: [\n { type: 'recurring', price: { amount: '9.99', currencyCode: 'USD' }, interval: 'EVERY_30_DAYS' },\n ],\n features: ['feature-a', 'feature-b'],\n };\n return { ...defaults, ...overrides };\n}\n\nexport function createTestSubscription(overrides?: Partial<Subscription>): Subscription {\n const now = new Date();\n const defaults: Subscription = {\n id: `sub-${Date.now()}`,\n shopDomain: 'test-shop.myshopify.com',\n shopifySubscriptionId: null,\n planName: 'Basic',\n status: 'ACTIVE',\n currentPeriodEnd: null,\n trialEndsAt: null,\n confirmationUrl: null,\n createdAt: now,\n updatedAt: now,\n };\n return { ...defaults, ...overrides };\n}\n\nexport function createTestUsageRecord(overrides?: Partial<UsageRecord>): UsageRecord {\n const defaults: UsageRecord = {\n id: `usage-${Date.now()}`,\n subscriptionId: 'sub-test',\n description: 'Test usage record',\n amount: '1.50',\n currencyCode: 'USD',\n idempotencyKey: null,\n createdAt: new Date(),\n };\n return { ...defaults, ...overrides };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
// src/billing/mock-billing-service.ts
|
|
2
|
+
function createMockBillingService() {
|
|
3
|
+
const _subscriptions = /* @__PURE__ */ new Map();
|
|
4
|
+
const _usageRecords = /* @__PURE__ */ new Map();
|
|
5
|
+
function _reset() {
|
|
6
|
+
_subscriptions.clear();
|
|
7
|
+
_usageRecords.clear();
|
|
8
|
+
}
|
|
9
|
+
async function createSubscription(input) {
|
|
10
|
+
const id = `mock-sub-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
11
|
+
const now = /* @__PURE__ */ new Date();
|
|
12
|
+
const sub = {
|
|
13
|
+
id,
|
|
14
|
+
shopDomain: input.shopDomain,
|
|
15
|
+
shopifySubscriptionId: null,
|
|
16
|
+
planName: input.planName,
|
|
17
|
+
status: "PENDING",
|
|
18
|
+
currentPeriodEnd: null,
|
|
19
|
+
trialEndsAt: null,
|
|
20
|
+
confirmationUrl: null,
|
|
21
|
+
createdAt: now,
|
|
22
|
+
updatedAt: now
|
|
23
|
+
};
|
|
24
|
+
if (input.shopifySubscriptionId) {
|
|
25
|
+
sub.shopifySubscriptionId = input.shopifySubscriptionId;
|
|
26
|
+
}
|
|
27
|
+
if (input.confirmationUrl) {
|
|
28
|
+
sub.confirmationUrl = input.confirmationUrl;
|
|
29
|
+
}
|
|
30
|
+
_subscriptions.set(id, sub);
|
|
31
|
+
return sub;
|
|
32
|
+
}
|
|
33
|
+
async function getSubscription(id) {
|
|
34
|
+
return _subscriptions.get(id) ?? null;
|
|
35
|
+
}
|
|
36
|
+
async function getActiveSubscription(shopDomain) {
|
|
37
|
+
for (const sub of _subscriptions.values()) {
|
|
38
|
+
if (sub.shopDomain === shopDomain && sub.status === "ACTIVE") {
|
|
39
|
+
return sub;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
async function listSubscriptions(shopDomain) {
|
|
45
|
+
const result = [];
|
|
46
|
+
for (const sub of _subscriptions.values()) {
|
|
47
|
+
if (sub.shopDomain === shopDomain) {
|
|
48
|
+
result.push(sub);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
async function updateSubscriptionStatus(id, status) {
|
|
54
|
+
const sub = _subscriptions.get(id);
|
|
55
|
+
if (!sub) {
|
|
56
|
+
throw new Error(`Subscription not found: ${id}`);
|
|
57
|
+
}
|
|
58
|
+
sub.status = status;
|
|
59
|
+
sub.updatedAt = /* @__PURE__ */ new Date();
|
|
60
|
+
return sub;
|
|
61
|
+
}
|
|
62
|
+
async function updateSubscriptionByShopifyId(shopifySubscriptionId, updates) {
|
|
63
|
+
for (const sub of _subscriptions.values()) {
|
|
64
|
+
if (sub.shopifySubscriptionId === shopifySubscriptionId) {
|
|
65
|
+
if (updates.status) {
|
|
66
|
+
sub.status = updates.status;
|
|
67
|
+
}
|
|
68
|
+
if (updates.currentPeriodEnd) {
|
|
69
|
+
sub.currentPeriodEnd = updates.currentPeriodEnd;
|
|
70
|
+
}
|
|
71
|
+
sub.updatedAt = /* @__PURE__ */ new Date();
|
|
72
|
+
return sub;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
async function cancelSubscription(id) {
|
|
78
|
+
const sub = _subscriptions.get(id);
|
|
79
|
+
if (!sub) {
|
|
80
|
+
throw new Error(`Subscription not found: ${id}`);
|
|
81
|
+
}
|
|
82
|
+
sub.status = "CANCELLED";
|
|
83
|
+
sub.updatedAt = /* @__PURE__ */ new Date();
|
|
84
|
+
return sub;
|
|
85
|
+
}
|
|
86
|
+
async function createUsageRecord(input) {
|
|
87
|
+
const id = `mock-usage-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
88
|
+
const record = {
|
|
89
|
+
id,
|
|
90
|
+
subscriptionId: input.subscriptionId,
|
|
91
|
+
description: input.description,
|
|
92
|
+
amount: input.amount,
|
|
93
|
+
currencyCode: input.currencyCode ?? "USD",
|
|
94
|
+
idempotencyKey: input.idempotencyKey ?? null,
|
|
95
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
96
|
+
};
|
|
97
|
+
const existing = _usageRecords.get(input.subscriptionId) ?? [];
|
|
98
|
+
existing.push(record);
|
|
99
|
+
_usageRecords.set(input.subscriptionId, existing);
|
|
100
|
+
return record;
|
|
101
|
+
}
|
|
102
|
+
async function getUsageRecords(filter) {
|
|
103
|
+
const records = _usageRecords.get(filter.subscriptionId) ?? [];
|
|
104
|
+
return records.filter((r) => {
|
|
105
|
+
if (filter.startDate && r.createdAt < filter.startDate) return false;
|
|
106
|
+
if (filter.endDate && r.createdAt > filter.endDate) return false;
|
|
107
|
+
return true;
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
async function calculateTotalUsage(filter) {
|
|
111
|
+
const records = await getUsageRecords(filter);
|
|
112
|
+
const total = records.reduce((sum, r) => sum + parseFloat(r.amount), 0);
|
|
113
|
+
return total.toString();
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
_subscriptions,
|
|
117
|
+
_usageRecords,
|
|
118
|
+
_reset,
|
|
119
|
+
createSubscription,
|
|
120
|
+
getSubscription,
|
|
121
|
+
getActiveSubscription,
|
|
122
|
+
listSubscriptions,
|
|
123
|
+
updateSubscriptionStatus,
|
|
124
|
+
updateSubscriptionByShopifyId,
|
|
125
|
+
cancelSubscription,
|
|
126
|
+
createUsageRecord,
|
|
127
|
+
getUsageRecords,
|
|
128
|
+
calculateTotalUsage
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// src/billing/factories.ts
|
|
133
|
+
function createTestPlan(overrides) {
|
|
134
|
+
const defaults = {
|
|
135
|
+
name: "Basic",
|
|
136
|
+
description: "Basic plan for testing",
|
|
137
|
+
lineItems: [
|
|
138
|
+
{ type: "recurring", price: { amount: "9.99", currencyCode: "USD" }, interval: "EVERY_30_DAYS" }
|
|
139
|
+
],
|
|
140
|
+
features: ["feature-a", "feature-b"]
|
|
141
|
+
};
|
|
142
|
+
return { ...defaults, ...overrides };
|
|
143
|
+
}
|
|
144
|
+
function createTestSubscription(overrides) {
|
|
145
|
+
const now = /* @__PURE__ */ new Date();
|
|
146
|
+
const defaults = {
|
|
147
|
+
id: `sub-${Date.now()}`,
|
|
148
|
+
shopDomain: "test-shop.myshopify.com",
|
|
149
|
+
shopifySubscriptionId: null,
|
|
150
|
+
planName: "Basic",
|
|
151
|
+
status: "ACTIVE",
|
|
152
|
+
currentPeriodEnd: null,
|
|
153
|
+
trialEndsAt: null,
|
|
154
|
+
confirmationUrl: null,
|
|
155
|
+
createdAt: now,
|
|
156
|
+
updatedAt: now
|
|
157
|
+
};
|
|
158
|
+
return { ...defaults, ...overrides };
|
|
159
|
+
}
|
|
160
|
+
function createTestUsageRecord(overrides) {
|
|
161
|
+
const defaults = {
|
|
162
|
+
id: `usage-${Date.now()}`,
|
|
163
|
+
subscriptionId: "sub-test",
|
|
164
|
+
description: "Test usage record",
|
|
165
|
+
amount: "1.50",
|
|
166
|
+
currencyCode: "USD",
|
|
167
|
+
idempotencyKey: null,
|
|
168
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
169
|
+
};
|
|
170
|
+
return { ...defaults, ...overrides };
|
|
171
|
+
}
|
|
172
|
+
export {
|
|
173
|
+
createMockBillingService,
|
|
174
|
+
createTestPlan,
|
|
175
|
+
createTestSubscription,
|
|
176
|
+
createTestUsageRecord
|
|
177
|
+
};
|
|
178
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/billing/mock-billing-service.ts","../../src/billing/factories.ts"],"sourcesContent":["/**\n * Mock BillingService for unit testing.\n *\n * Provides an in-memory implementation of BillingService with\n * internal maps for subscriptions and usage records.\n */\n\nimport type {\n BillingService,\n Subscription,\n SubscriptionStatus,\n UsageRecord,\n CreateSubscriptionInput,\n CreateUsageRecordInput,\n UsageRecordFilter,\n} from '@uniforge/platform-core/billing';\n\nexport type MockBillingService = BillingService & {\n _subscriptions: Map<string, Subscription>;\n _usageRecords: Map<string, UsageRecord[]>;\n _reset(): void;\n};\n\nexport function createMockBillingService(): MockBillingService {\n const _subscriptions = new Map<string, Subscription>();\n const _usageRecords = new Map<string, UsageRecord[]>();\n\n function _reset(): void {\n _subscriptions.clear();\n _usageRecords.clear();\n }\n\n async function createSubscription(input: CreateSubscriptionInput): Promise<Subscription> {\n const id = `mock-sub-${Date.now()}-${Math.random().toString(36).slice(2)}`;\n const now = new Date();\n const sub: Subscription = {\n id,\n shopDomain: input.shopDomain,\n shopifySubscriptionId: null,\n planName: input.planName,\n status: 'PENDING',\n currentPeriodEnd: null,\n trialEndsAt: null,\n confirmationUrl: null,\n createdAt: now,\n updatedAt: now,\n };\n if (input.shopifySubscriptionId) {\n sub.shopifySubscriptionId = input.shopifySubscriptionId;\n }\n if (input.confirmationUrl) {\n sub.confirmationUrl = input.confirmationUrl;\n }\n _subscriptions.set(id, sub);\n return sub;\n }\n\n async function getSubscription(id: string): Promise<Subscription | null> {\n return _subscriptions.get(id) ?? null;\n }\n\n async function getActiveSubscription(shopDomain: string): Promise<Subscription | null> {\n for (const sub of _subscriptions.values()) {\n if (sub.shopDomain === shopDomain && sub.status === 'ACTIVE') {\n return sub;\n }\n }\n return null;\n }\n\n async function listSubscriptions(shopDomain: string): Promise<Subscription[]> {\n const result: Subscription[] = [];\n for (const sub of _subscriptions.values()) {\n if (sub.shopDomain === shopDomain) {\n result.push(sub);\n }\n }\n return result;\n }\n\n async function updateSubscriptionStatus(\n id: string,\n status: SubscriptionStatus,\n ): Promise<Subscription> {\n const sub = _subscriptions.get(id);\n if (!sub) {\n throw new Error(`Subscription not found: ${id}`);\n }\n sub.status = status;\n sub.updatedAt = new Date();\n return sub;\n }\n\n async function updateSubscriptionByShopifyId(\n shopifySubscriptionId: string,\n updates: Partial<Pick<Subscription, 'status' | 'currentPeriodEnd'>>,\n ): Promise<Subscription | null> {\n for (const sub of _subscriptions.values()) {\n if (sub.shopifySubscriptionId === shopifySubscriptionId) {\n if (updates.status) {\n sub.status = updates.status;\n }\n if (updates.currentPeriodEnd) {\n sub.currentPeriodEnd = updates.currentPeriodEnd;\n }\n sub.updatedAt = new Date();\n return sub;\n }\n }\n return null;\n }\n\n async function cancelSubscription(id: string): Promise<Subscription> {\n const sub = _subscriptions.get(id);\n if (!sub) {\n throw new Error(`Subscription not found: ${id}`);\n }\n sub.status = 'CANCELLED';\n sub.updatedAt = new Date();\n return sub;\n }\n\n async function createUsageRecord(input: CreateUsageRecordInput): Promise<UsageRecord> {\n const id = `mock-usage-${Date.now()}-${Math.random().toString(36).slice(2)}`;\n const record: UsageRecord = {\n id,\n subscriptionId: input.subscriptionId,\n description: input.description,\n amount: input.amount,\n currencyCode: input.currencyCode ?? 'USD',\n idempotencyKey: input.idempotencyKey ?? null,\n createdAt: new Date(),\n };\n const existing = _usageRecords.get(input.subscriptionId) ?? [];\n existing.push(record);\n _usageRecords.set(input.subscriptionId, existing);\n return record;\n }\n\n async function getUsageRecords(filter: UsageRecordFilter): Promise<UsageRecord[]> {\n const records = _usageRecords.get(filter.subscriptionId) ?? [];\n return records.filter((r) => {\n if (filter.startDate && r.createdAt < filter.startDate) return false;\n if (filter.endDate && r.createdAt > filter.endDate) return false;\n return true;\n });\n }\n\n async function calculateTotalUsage(filter: UsageRecordFilter): Promise<string> {\n const records = await getUsageRecords(filter);\n const total = records.reduce((sum, r) => sum + parseFloat(r.amount), 0);\n return total.toString();\n }\n\n return {\n _subscriptions,\n _usageRecords,\n _reset,\n createSubscription,\n getSubscription,\n getActiveSubscription,\n listSubscriptions,\n updateSubscriptionStatus,\n updateSubscriptionByShopifyId,\n cancelSubscription,\n createUsageRecord,\n getUsageRecords,\n calculateTotalUsage,\n };\n}\n","/**\n * Test data factories for billing types.\n *\n * Each factory provides sensible defaults that can be overridden.\n */\n\nimport type {\n BillingPlan,\n Subscription,\n UsageRecord,\n} from '@uniforge/platform-core/billing';\n\nexport function createTestPlan(overrides?: Partial<BillingPlan>): BillingPlan {\n const defaults: BillingPlan = {\n name: 'Basic',\n description: 'Basic plan for testing',\n lineItems: [\n { type: 'recurring', price: { amount: '9.99', currencyCode: 'USD' }, interval: 'EVERY_30_DAYS' },\n ],\n features: ['feature-a', 'feature-b'],\n };\n return { ...defaults, ...overrides };\n}\n\nexport function createTestSubscription(overrides?: Partial<Subscription>): Subscription {\n const now = new Date();\n const defaults: Subscription = {\n id: `sub-${Date.now()}`,\n shopDomain: 'test-shop.myshopify.com',\n shopifySubscriptionId: null,\n planName: 'Basic',\n status: 'ACTIVE',\n currentPeriodEnd: null,\n trialEndsAt: null,\n confirmationUrl: null,\n createdAt: now,\n updatedAt: now,\n };\n return { ...defaults, ...overrides };\n}\n\nexport function createTestUsageRecord(overrides?: Partial<UsageRecord>): UsageRecord {\n const defaults: UsageRecord = {\n id: `usage-${Date.now()}`,\n subscriptionId: 'sub-test',\n description: 'Test usage record',\n amount: '1.50',\n currencyCode: 'USD',\n idempotencyKey: null,\n createdAt: new Date(),\n };\n return { ...defaults, ...overrides };\n}\n"],"mappings":"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","names":[]}
|