@onesub/server 0.12.1 → 0.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/dist/__tests__/admin-customer-detail.test.js +146 -0
  2. package/dist/__tests__/admin-customer-detail.test.js.map +1 -0
  3. package/dist/__tests__/admin-list-subscriptions.test.js +192 -0
  4. package/dist/__tests__/admin-list-subscriptions.test.js.map +1 -0
  5. package/dist/__tests__/admin-subscription-detail.test.js +112 -0
  6. package/dist/__tests__/admin-subscription-detail.test.js.map +1 -0
  7. package/dist/__tests__/apple-root-ca.test.js +41 -0
  8. package/dist/__tests__/apple-root-ca.test.js.map +1 -0
  9. package/dist/__tests__/apple-status-api.test.js +345 -0
  10. package/dist/__tests__/apple-status-api.test.js.map +1 -0
  11. package/dist/__tests__/cache.test.js +34 -0
  12. package/dist/__tests__/cache.test.js.map +1 -0
  13. package/dist/__tests__/entitlements.test.js +268 -0
  14. package/dist/__tests__/entitlements.test.js.map +1 -0
  15. package/dist/__tests__/error-codes.test.js +173 -0
  16. package/dist/__tests__/error-codes.test.js.map +1 -0
  17. package/dist/__tests__/fetch-hardening.test.js +192 -0
  18. package/dist/__tests__/fetch-hardening.test.js.map +1 -0
  19. package/dist/__tests__/google-paused.test.js +126 -0
  20. package/dist/__tests__/google-paused.test.js.map +1 -0
  21. package/dist/__tests__/google-price-change.test.js +186 -0
  22. package/dist/__tests__/google-price-change.test.js.map +1 -0
  23. package/dist/__tests__/google-subscriptions-v2.test.js +206 -0
  24. package/dist/__tests__/google-subscriptions-v2.test.js.map +1 -0
  25. package/dist/__tests__/lifecycle-scenarios.test.js +579 -0
  26. package/dist/__tests__/lifecycle-scenarios.test.js.map +1 -0
  27. package/dist/__tests__/lifecycle-states.test.js +423 -0
  28. package/dist/__tests__/lifecycle-states.test.js.map +1 -0
  29. package/dist/__tests__/linked-purchase-token.test.js +227 -0
  30. package/dist/__tests__/linked-purchase-token.test.js.map +1 -0
  31. package/dist/__tests__/metrics.test.js +340 -0
  32. package/dist/__tests__/metrics.test.js.map +1 -0
  33. package/dist/__tests__/mock-provider.test.js +188 -0
  34. package/dist/__tests__/mock-provider.test.js.map +1 -0
  35. package/dist/__tests__/openapi.test.js +32 -0
  36. package/dist/__tests__/openapi.test.js.map +1 -0
  37. package/dist/__tests__/paused-auto-resume.test.js +162 -0
  38. package/dist/__tests__/paused-auto-resume.test.js.map +1 -0
  39. package/dist/__tests__/providers.test.js +321 -0
  40. package/dist/__tests__/providers.test.js.map +1 -0
  41. package/dist/__tests__/redis-store.test.js +166 -0
  42. package/dist/__tests__/redis-store.test.js.map +1 -0
  43. package/dist/__tests__/refund-policy.test.js +317 -0
  44. package/dist/__tests__/refund-policy.test.js.map +1 -0
  45. package/dist/__tests__/schema.test.js +46 -0
  46. package/dist/__tests__/schema.test.js.map +1 -0
  47. package/dist/__tests__/store.test.js +172 -0
  48. package/dist/__tests__/store.test.js.map +1 -0
  49. package/dist/__tests__/test-utils.js +30 -0
  50. package/dist/__tests__/test-utils.js.map +1 -0
  51. package/dist/__tests__/webhook-apple.test.js +247 -0
  52. package/dist/__tests__/webhook-apple.test.js.map +1 -0
  53. package/dist/__tests__/webhook-events.test.js +36 -0
  54. package/dist/__tests__/webhook-events.test.js.map +1 -0
  55. package/dist/__tests__/webhook-google.test.js +255 -0
  56. package/dist/__tests__/webhook-google.test.js.map +1 -0
  57. package/dist/__tests__/webhook-queue.test.js +26 -0
  58. package/dist/__tests__/webhook-queue.test.js.map +1 -0
  59. package/dist/__tests__/webhook-refund.test.js +313 -0
  60. package/dist/__tests__/webhook-refund.test.js.map +1 -0
  61. package/dist/cache.js +39 -0
  62. package/dist/cache.js.map +1 -0
  63. package/dist/errors.js +19 -0
  64. package/dist/errors.js.map +1 -0
  65. package/dist/http.js +36 -0
  66. package/dist/http.js.map +1 -0
  67. package/dist/index.cjs +241 -9
  68. package/dist/index.cjs.map +1 -1
  69. package/dist/index.d.ts +1 -1
  70. package/dist/index.d.ts.map +1 -1
  71. package/dist/index.js +241 -11
  72. package/dist/index.js.map +1 -1
  73. package/dist/logger.js +20 -0
  74. package/dist/logger.js.map +1 -0
  75. package/dist/openapi.js +196 -0
  76. package/dist/openapi.js.map +1 -0
  77. package/dist/providers/apple-root-ca.js +38 -0
  78. package/dist/providers/apple-root-ca.js.map +1 -0
  79. package/dist/providers/apple.d.ts +76 -0
  80. package/dist/providers/apple.d.ts.map +1 -1
  81. package/dist/providers/apple.js +630 -0
  82. package/dist/providers/apple.js.map +1 -0
  83. package/dist/providers/google.d.ts +25 -0
  84. package/dist/providers/google.d.ts.map +1 -1
  85. package/dist/providers/google.js +564 -0
  86. package/dist/providers/google.js.map +1 -0
  87. package/dist/providers/mock.js +93 -0
  88. package/dist/providers/mock.js.map +1 -0
  89. package/dist/routes/admin.d.ts.map +1 -1
  90. package/dist/routes/admin.js +327 -0
  91. package/dist/routes/admin.js.map +1 -0
  92. package/dist/routes/apple-offer.d.ts +21 -0
  93. package/dist/routes/apple-offer.d.ts.map +1 -0
  94. package/dist/routes/apple-offer.js +72 -0
  95. package/dist/routes/apple-offer.js.map +1 -0
  96. package/dist/routes/entitlements.js +130 -0
  97. package/dist/routes/entitlements.js.map +1 -0
  98. package/dist/routes/metrics.js +281 -0
  99. package/dist/routes/metrics.js.map +1 -0
  100. package/dist/routes/purchase.d.ts.map +1 -1
  101. package/dist/routes/purchase.js +204 -0
  102. package/dist/routes/purchase.js.map +1 -0
  103. package/dist/routes/status.js +55 -0
  104. package/dist/routes/status.js.map +1 -0
  105. package/dist/routes/validate.js +70 -0
  106. package/dist/routes/validate.js.map +1 -0
  107. package/dist/routes/webhook-apple.d.ts.map +1 -1
  108. package/dist/routes/webhook-apple.js +145 -0
  109. package/dist/routes/webhook-apple.js.map +1 -0
  110. package/dist/routes/webhook-google.d.ts.map +1 -1
  111. package/dist/routes/webhook-google.js +204 -0
  112. package/dist/routes/webhook-google.js.map +1 -0
  113. package/dist/routes/webhook.js +19 -0
  114. package/dist/routes/webhook.js.map +1 -0
  115. package/dist/store.js +145 -0
  116. package/dist/store.js.map +1 -0
  117. package/dist/stores/postgres.js +329 -0
  118. package/dist/stores/postgres.js.map +1 -0
  119. package/dist/stores/redis.js +297 -0
  120. package/dist/stores/redis.js.map +1 -0
  121. package/dist/stores/schema.js +67 -0
  122. package/dist/stores/schema.js.map +1 -0
  123. package/dist/tracing.js +74 -0
  124. package/dist/tracing.js.map +1 -0
  125. package/dist/webhook-events.js +58 -0
  126. package/dist/webhook-events.js.map +1 -0
  127. package/dist/webhook-queue.js +108 -0
  128. package/dist/webhook-queue.js.map +1 -0
  129. package/package.json +4 -4
@@ -0,0 +1,345 @@
1
+ /**
2
+ * Tests for fetchAppleSubscriptionStatus + the Apple webhook unknown-tx fallback.
3
+ *
4
+ * Covers:
5
+ * - status code 1..5 → SubscriptionStatus mapping
6
+ * - sandbox vs production host routing
7
+ * - missing API credentials → returns null (no throw)
8
+ * - HTTP error / empty data → returns null
9
+ * - webhook receives notification for unknown originalTransactionId →
10
+ * calls Status API + saves the returned record
11
+ * - webhook unknown tx without API creds → no fetch, just logs
12
+ */
13
+ import { describe, it, expect, beforeAll, beforeEach, vi } from 'vitest';
14
+ import express from 'express';
15
+ import { generateKeyPairSync } from 'crypto';
16
+ import { SUBSCRIPTION_STATUS } from '@onesub/shared';
17
+ import { fetchAppleSubscriptionStatus } from '../providers/apple.js';
18
+ import { createWebhookRouter } from '../routes/webhook.js';
19
+ import { InMemorySubscriptionStore, InMemoryPurchaseStore } from '../store.js';
20
+ import { isLocalhostUrl } from './test-utils.js';
21
+ // ── helpers ─────────────────────────────────────────────────────────────────
22
+ function makeJws(payload) {
23
+ const header = Buffer.from(JSON.stringify({ alg: 'ES256' })).toString('base64url');
24
+ const body = Buffer.from(JSON.stringify(payload)).toString('base64url');
25
+ return `${header}.${body}.fakesig`;
26
+ }
27
+ let testEcKey;
28
+ beforeAll(() => {
29
+ const { privateKey } = generateKeyPairSync('ec', { namedCurve: 'P-256' });
30
+ testEcKey = privateKey.export({ type: 'pkcs8', format: 'pem' });
31
+ });
32
+ beforeEach(() => {
33
+ vi.restoreAllMocks();
34
+ });
35
+ function appleConfigWithApi(overrides) {
36
+ return {
37
+ bundleId: 'com.example.app',
38
+ skipJwsVerification: true,
39
+ keyId: 'TESTKEY1',
40
+ issuerId: '12345678-1234-1234-1234-123456789012',
41
+ privateKey: testEcKey,
42
+ ...overrides,
43
+ };
44
+ }
45
+ /**
46
+ * Mock global fetch with localhost pass-through. Apple Status API requests
47
+ * resolve to the provided body; localhost (our test http server) is forwarded
48
+ * to the real fetch implementation.
49
+ */
50
+ function mockAppleStatusFetch(responseBody, opts) {
51
+ const originalFetch = global.fetch;
52
+ const calls = [];
53
+ vi.spyOn(global, 'fetch').mockImplementation(async (url, init) => {
54
+ if (isLocalhostUrl(url)) {
55
+ return originalFetch(url, init);
56
+ }
57
+ const urlStr = String(url);
58
+ calls.push({
59
+ url: urlStr,
60
+ method: init?.method,
61
+ headers: init?.headers,
62
+ });
63
+ return {
64
+ ok: (opts?.status ?? 200) < 400,
65
+ status: opts?.status ?? 200,
66
+ json: async () => responseBody,
67
+ text: async () => JSON.stringify(responseBody),
68
+ };
69
+ });
70
+ return calls;
71
+ }
72
+ function makeStatusResponse(opts) {
73
+ const tx = makeJws({
74
+ bundleId: 'com.example.app',
75
+ type: 'Auto-Renewable Subscription',
76
+ productId: opts.productId ?? 'pro_monthly',
77
+ transactionId: 'tx_inner',
78
+ originalTransactionId: opts.originalTransactionId,
79
+ purchaseDate: Date.now() - 30 * 86400000,
80
+ originalPurchaseDate: Date.now() - 30 * 86400000,
81
+ expiresDate: opts.expiresDate ?? Date.now() + 86400000,
82
+ });
83
+ const renewal = makeJws({ autoRenewStatus: opts.autoRenewStatus ?? 1 });
84
+ return {
85
+ bundleId: 'com.example.app',
86
+ environment: 'Production',
87
+ data: [{
88
+ subscriptionGroupIdentifier: 'group_a',
89
+ lastTransactions: [{
90
+ originalTransactionId: opts.originalTransactionId,
91
+ status: opts.status,
92
+ signedTransactionInfo: tx,
93
+ signedRenewalInfo: renewal,
94
+ }],
95
+ }],
96
+ };
97
+ }
98
+ // ── fetchAppleSubscriptionStatus unit tests ─────────────────────────────────
99
+ describe('fetchAppleSubscriptionStatus', () => {
100
+ it('returns null when API credentials are missing', async () => {
101
+ const fetchSpy = vi.spyOn(global, 'fetch');
102
+ const result = await fetchAppleSubscriptionStatus('orig_xyz', {
103
+ bundleId: 'com.example.app',
104
+ skipJwsVerification: true,
105
+ });
106
+ expect(result).toBeNull();
107
+ expect(fetchSpy).not.toHaveBeenCalled();
108
+ });
109
+ it('returns null when mockMode is enabled', async () => {
110
+ const fetchSpy = vi.spyOn(global, 'fetch');
111
+ const result = await fetchAppleSubscriptionStatus('orig_xyz', appleConfigWithApi({ mockMode: true }));
112
+ expect(result).toBeNull();
113
+ expect(fetchSpy).not.toHaveBeenCalled();
114
+ });
115
+ it('GET .../inApps/v1/subscriptions/<id> with Bearer JWT', async () => {
116
+ const calls = mockAppleStatusFetch(makeStatusResponse({
117
+ originalTransactionId: 'orig_active',
118
+ status: 1,
119
+ }));
120
+ await fetchAppleSubscriptionStatus('orig_active', appleConfigWithApi());
121
+ expect(calls).toHaveLength(1);
122
+ expect(calls[0].url).toContain('api.storekit.itunes.apple.com');
123
+ expect(calls[0].url).toContain('/inApps/v1/subscriptions/orig_active');
124
+ expect(calls[0].headers?.Authorization).toMatch(/^Bearer /);
125
+ });
126
+ it('routes to sandbox host when options.sandbox is true', async () => {
127
+ const calls = mockAppleStatusFetch(makeStatusResponse({
128
+ originalTransactionId: 'orig_sb',
129
+ status: 1,
130
+ }));
131
+ await fetchAppleSubscriptionStatus('orig_sb', appleConfigWithApi(), { sandbox: true });
132
+ expect(calls[0].url).toContain('api.storekit-sandbox.itunes.apple.com');
133
+ });
134
+ it('maps status code 1 → active', async () => {
135
+ mockAppleStatusFetch(makeStatusResponse({ originalTransactionId: 'o1', status: 1 }));
136
+ const result = await fetchAppleSubscriptionStatus('o1', appleConfigWithApi());
137
+ expect(result?.status).toBe(SUBSCRIPTION_STATUS.ACTIVE);
138
+ });
139
+ it('maps status code 2 → expired', async () => {
140
+ mockAppleStatusFetch(makeStatusResponse({ originalTransactionId: 'o2', status: 2 }));
141
+ const result = await fetchAppleSubscriptionStatus('o2', appleConfigWithApi());
142
+ expect(result?.status).toBe(SUBSCRIPTION_STATUS.EXPIRED);
143
+ });
144
+ it('maps status code 3 → on_hold (billing retry)', async () => {
145
+ mockAppleStatusFetch(makeStatusResponse({ originalTransactionId: 'o3', status: 3 }));
146
+ const result = await fetchAppleSubscriptionStatus('o3', appleConfigWithApi());
147
+ expect(result?.status).toBe(SUBSCRIPTION_STATUS.ON_HOLD);
148
+ });
149
+ it('maps status code 4 → grace_period', async () => {
150
+ mockAppleStatusFetch(makeStatusResponse({ originalTransactionId: 'o4', status: 4 }));
151
+ const result = await fetchAppleSubscriptionStatus('o4', appleConfigWithApi());
152
+ expect(result?.status).toBe(SUBSCRIPTION_STATUS.GRACE_PERIOD);
153
+ });
154
+ it('maps status code 5 → canceled (revoked)', async () => {
155
+ mockAppleStatusFetch(makeStatusResponse({ originalTransactionId: 'o5', status: 5 }));
156
+ const result = await fetchAppleSubscriptionStatus('o5', appleConfigWithApi());
157
+ expect(result?.status).toBe(SUBSCRIPTION_STATUS.CANCELED);
158
+ });
159
+ it('reads autoRenewStatus from signedRenewalInfo for willRenew', async () => {
160
+ mockAppleStatusFetch(makeStatusResponse({
161
+ originalTransactionId: 'o_renew',
162
+ status: 1,
163
+ autoRenewStatus: 0,
164
+ }));
165
+ const result = await fetchAppleSubscriptionStatus('o_renew', appleConfigWithApi());
166
+ expect(result?.willRenew).toBe(false);
167
+ });
168
+ it('returns null on HTTP 404', async () => {
169
+ mockAppleStatusFetch({ errorCode: 4040010 }, { status: 404 });
170
+ const result = await fetchAppleSubscriptionStatus('not_found', appleConfigWithApi());
171
+ expect(result).toBeNull();
172
+ });
173
+ it('returns null when data array is empty', async () => {
174
+ mockAppleStatusFetch({ bundleId: 'com.example.app', environment: 'Production', data: [] });
175
+ const result = await fetchAppleSubscriptionStatus('orig_empty', appleConfigWithApi());
176
+ expect(result).toBeNull();
177
+ });
178
+ it('returns null when matching originalTransactionId not in lastTransactions', async () => {
179
+ mockAppleStatusFetch({
180
+ bundleId: 'com.example.app',
181
+ environment: 'Production',
182
+ data: [{
183
+ subscriptionGroupIdentifier: 'g',
184
+ lastTransactions: [{
185
+ originalTransactionId: 'different_id',
186
+ status: 1,
187
+ signedTransactionInfo: makeJws({ productId: 'p', expiresDate: Date.now() }),
188
+ }],
189
+ }],
190
+ });
191
+ const result = await fetchAppleSubscriptionStatus('expected_id', appleConfigWithApi());
192
+ expect(result).toBeNull();
193
+ });
194
+ it('preserves originalTransactionId from caller (not from inner JWS)', async () => {
195
+ mockAppleStatusFetch(makeStatusResponse({
196
+ originalTransactionId: 'orig_caller',
197
+ status: 1,
198
+ }));
199
+ const result = await fetchAppleSubscriptionStatus('orig_caller', appleConfigWithApi());
200
+ expect(result?.originalTransactionId).toBe('orig_caller');
201
+ });
202
+ });
203
+ function buildAppleWebhookServer(config) {
204
+ const store = new InMemorySubscriptionStore();
205
+ const purchaseStore = new InMemoryPurchaseStore();
206
+ const app = express();
207
+ app.use(express.json());
208
+ app.use(createWebhookRouter(config, store, purchaseStore));
209
+ return {
210
+ store,
211
+ server: {
212
+ async request(path, body) {
213
+ const httpServer = app.listen(0);
214
+ const address = httpServer.address();
215
+ const port = typeof address === 'object' && address ? address.port : 0;
216
+ try {
217
+ const resp = await fetch(`http://127.0.0.1:${port}${path}`, {
218
+ method: 'POST',
219
+ headers: { 'Content-Type': 'application/json' },
220
+ body: JSON.stringify(body),
221
+ });
222
+ const text = await resp.text();
223
+ let parsed = text;
224
+ try {
225
+ parsed = JSON.parse(text);
226
+ }
227
+ catch { /* keep as text */ }
228
+ return { status: resp.status, body: parsed };
229
+ }
230
+ finally {
231
+ await new Promise((resolve) => httpServer.close(() => resolve()));
232
+ }
233
+ },
234
+ },
235
+ };
236
+ }
237
+ function buildUnknownTxNotification(originalTransactionId, opts) {
238
+ const signedTransactionInfo = makeJws({
239
+ bundleId: 'com.example.app',
240
+ type: 'Auto-Renewable Subscription',
241
+ productId: 'pro_monthly',
242
+ transactionId: 'tx_notify',
243
+ originalTransactionId,
244
+ purchaseDate: Date.now(),
245
+ expiresDate: Date.now() + 86400000,
246
+ environment: opts?.sandbox ? 'Sandbox' : 'Production',
247
+ });
248
+ return {
249
+ signedPayload: makeJws({
250
+ notificationType: 'DID_RENEW',
251
+ data: {
252
+ signedTransactionInfo,
253
+ signedRenewalInfo: makeJws({ autoRenewStatus: 1 }),
254
+ },
255
+ }),
256
+ };
257
+ }
258
+ describe('Apple webhook — unknown originalTransactionId fallback', () => {
259
+ it('fetches from Status API and saves a placeholder record when API creds present', async () => {
260
+ mockAppleStatusFetch(makeStatusResponse({
261
+ originalTransactionId: 'orig_unknown',
262
+ status: 1,
263
+ }));
264
+ const config = {
265
+ apple: appleConfigWithApi(),
266
+ database: { url: '' },
267
+ };
268
+ const { store, server } = buildAppleWebhookServer(config);
269
+ const resp = await server.request('/onesub/webhook/apple', buildUnknownTxNotification('orig_unknown'));
270
+ expect(resp.status).toBe(200);
271
+ const saved = await store.getByTransactionId('orig_unknown');
272
+ expect(saved).not.toBeNull();
273
+ expect(saved?.status).toBe(SUBSCRIPTION_STATUS.ACTIVE);
274
+ // userId is unknown at webhook time — placeholder is the originalTransactionId
275
+ expect(saved?.userId).toBe('orig_unknown');
276
+ });
277
+ it('routes to sandbox host when notification environment is Sandbox', async () => {
278
+ const calls = mockAppleStatusFetch(makeStatusResponse({
279
+ originalTransactionId: 'orig_sb_unknown',
280
+ status: 1,
281
+ }));
282
+ const config = {
283
+ apple: appleConfigWithApi(),
284
+ database: { url: '' },
285
+ };
286
+ const { server } = buildAppleWebhookServer(config);
287
+ await server.request('/onesub/webhook/apple', buildUnknownTxNotification('orig_sb_unknown', { sandbox: true }));
288
+ const apiCall = calls.find((c) => c.url.includes('/inApps/v1/subscriptions/'));
289
+ expect(apiCall?.url).toContain('api.storekit-sandbox.itunes.apple.com');
290
+ });
291
+ it('does not call Status API when issuerId/keyId/privateKey are missing', async () => {
292
+ const originalFetch = global.fetch;
293
+ const outboundCalls = [];
294
+ vi.spyOn(global, 'fetch').mockImplementation(async (url, init) => {
295
+ if (isLocalhostUrl(url)) {
296
+ return originalFetch(url, init);
297
+ }
298
+ outboundCalls.push({ url: String(url) });
299
+ return { ok: true, status: 200, json: async () => ({}), text: async () => '' };
300
+ });
301
+ const config = {
302
+ apple: { bundleId: 'com.example.app', skipJwsVerification: true }, // no API creds
303
+ database: { url: '' },
304
+ };
305
+ const { store, server } = buildAppleWebhookServer(config);
306
+ const resp = await server.request('/onesub/webhook/apple', buildUnknownTxNotification('orig_no_creds'));
307
+ expect(resp.status).toBe(200);
308
+ expect(await store.getByTransactionId('orig_no_creds')).toBeNull();
309
+ expect(outboundCalls).toHaveLength(0);
310
+ });
311
+ it('does not overwrite an existing record (still the normal update path)', async () => {
312
+ const originalFetch = global.fetch;
313
+ const outboundCalls = [];
314
+ vi.spyOn(global, 'fetch').mockImplementation(async (url, init) => {
315
+ if (isLocalhostUrl(url)) {
316
+ return originalFetch(url, init);
317
+ }
318
+ outboundCalls.push({ url: String(url) });
319
+ return { ok: true, status: 200, json: async () => ({}), text: async () => '' };
320
+ });
321
+ const config = {
322
+ apple: appleConfigWithApi(),
323
+ database: { url: '' },
324
+ };
325
+ const { store, server } = buildAppleWebhookServer(config);
326
+ const existing = {
327
+ userId: 'real_user',
328
+ productId: 'pro_monthly',
329
+ platform: 'apple',
330
+ status: SUBSCRIPTION_STATUS.ACTIVE,
331
+ expiresAt: '2027-01-01T00:00:00.000Z',
332
+ originalTransactionId: 'orig_known',
333
+ purchasedAt: '2026-01-01T00:00:00.000Z',
334
+ willRenew: true,
335
+ };
336
+ await store.save(existing);
337
+ const resp = await server.request('/onesub/webhook/apple', buildUnknownTxNotification('orig_known'));
338
+ expect(resp.status).toBe(200);
339
+ // Existing record's userId preserved (not replaced with placeholder)
340
+ expect((await store.getByTransactionId('orig_known'))?.userId).toBe('real_user');
341
+ // No outbound Status API call since we already had the record
342
+ expect(outboundCalls.find((c) => c.url.includes('/inApps/v1/subscriptions/'))).toBeUndefined();
343
+ });
344
+ });
345
+ //# sourceMappingURL=apple-status-api.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apple-status-api.test.js","sourceRoot":"","sources":["../../src/__tests__/apple-status-api.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { InMemoryCacheAdapter } from '../cache.js';
3
+ describe('InMemoryCacheAdapter', () => {
4
+ it('returns null for missing keys', async () => {
5
+ const cache = new InMemoryCacheAdapter();
6
+ expect(await cache.get('absent')).toBeNull();
7
+ });
8
+ it('round-trips a value', async () => {
9
+ const cache = new InMemoryCacheAdapter();
10
+ await cache.set('k', { token: 'abc', n: 1 });
11
+ expect(await cache.get('k')).toEqual({ token: 'abc', n: 1 });
12
+ });
13
+ it('expires entries after the TTL elapses', async () => {
14
+ const cache = new InMemoryCacheAdapter();
15
+ await cache.set('k', 'v', 1);
16
+ expect(await cache.get('k')).toBe('v');
17
+ // Force expiry by moving the clock forward via a sleep substitute.
18
+ await new Promise((resolve) => setTimeout(resolve, 1100));
19
+ expect(await cache.get('k')).toBeNull();
20
+ });
21
+ it('treats ttl=0 / undefined as no-expiry', async () => {
22
+ const cache = new InMemoryCacheAdapter();
23
+ await cache.set('forever', 'v');
24
+ await new Promise((resolve) => setTimeout(resolve, 50));
25
+ expect(await cache.get('forever')).toBe('v');
26
+ });
27
+ it('del removes a key', async () => {
28
+ const cache = new InMemoryCacheAdapter();
29
+ await cache.set('k', 'v');
30
+ await cache.del('k');
31
+ expect(await cache.get('k')).toBeNull();
32
+ });
33
+ });
34
+ //# sourceMappingURL=cache.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.test.js","sourceRoot":"","sources":["../../src/__tests__/cache.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAEnD,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,EAAE,CAAC,+BAA+B,EAAE,KAAK,IAAI,EAAE;QAC7C,MAAM,KAAK,GAAG,IAAI,oBAAoB,EAAE,CAAC;QACzC,MAAM,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qBAAqB,EAAE,KAAK,IAAI,EAAE;QACnC,MAAM,KAAK,GAAG,IAAI,oBAAoB,EAAE,CAAC;QACzC,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QAC7C,MAAM,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,KAAK,IAAI,EAAE;QACrD,MAAM,KAAK,GAAG,IAAI,oBAAoB,EAAE,CAAC;QACzC,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;QAC7B,MAAM,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACvC,mEAAmE;QACnE,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;QAC1D,MAAM,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,KAAK,IAAI,EAAE;QACrD,MAAM,KAAK,GAAG,IAAI,oBAAoB,EAAE,CAAC;QACzC,MAAM,KAAK,CAAC,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QAChC,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;QACxD,MAAM,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mBAAmB,EAAE,KAAK,IAAI,EAAE;QACjC,MAAM,KAAK,GAAG,IAAI,oBAAoB,EAAE,CAAC;QACzC,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAC1B,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACrB,MAAM,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC1C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}