@solvapay/next 1.0.0-preview.17 → 1.0.0-preview.19

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/index.js CHANGED
@@ -3,6 +3,136 @@ import { NextResponse as NextResponse8 } from "next/server";
3
3
  import { createSolvaPay } from "@solvapay/server";
4
4
  import { SolvaPayError } from "@solvapay/core";
5
5
 
6
+ // src/cache.ts
7
+ function createRequestDeduplicator(options = {}) {
8
+ const { cacheTTL = 2e3, maxCacheSize = 1e3, cacheErrors = true } = options;
9
+ const inFlightRequests = /* @__PURE__ */ new Map();
10
+ const resultCache = /* @__PURE__ */ new Map();
11
+ const cacheInvalidatedAt = /* @__PURE__ */ new Map();
12
+ if (cacheTTL > 0) {
13
+ setInterval(
14
+ () => {
15
+ const now = Date.now();
16
+ const entriesToDelete = [];
17
+ for (const [key, cached] of resultCache.entries()) {
18
+ if (now - cached.timestamp >= cacheTTL) {
19
+ entriesToDelete.push(key);
20
+ }
21
+ }
22
+ for (const key of entriesToDelete) {
23
+ resultCache.delete(key);
24
+ cacheInvalidatedAt.delete(key);
25
+ }
26
+ if (resultCache.size > maxCacheSize) {
27
+ const sortedEntries = Array.from(resultCache.entries()).sort(
28
+ (a, b) => a[1].timestamp - b[1].timestamp
29
+ );
30
+ const toRemove = sortedEntries.slice(0, resultCache.size - maxCacheSize);
31
+ for (const [key] of toRemove) {
32
+ resultCache.delete(key);
33
+ cacheInvalidatedAt.delete(key);
34
+ }
35
+ }
36
+ },
37
+ Math.min(cacheTTL, 1e3)
38
+ );
39
+ }
40
+ const deduplicate = async (key, fn) => {
41
+ if (cacheTTL > 0) {
42
+ const cached = resultCache.get(key);
43
+ if (cached && Date.now() - cached.timestamp < cacheTTL) {
44
+ return cached.data;
45
+ } else if (cached) {
46
+ resultCache.delete(key);
47
+ }
48
+ }
49
+ let requestPromise = inFlightRequests.get(key);
50
+ if (!requestPromise) {
51
+ const requestStartTime = Date.now();
52
+ requestPromise = (async () => {
53
+ try {
54
+ const result = await fn();
55
+ const invalidatedAt = cacheInvalidatedAt.get(key);
56
+ const shouldCache = !invalidatedAt || invalidatedAt < requestStartTime;
57
+ if (cacheTTL > 0 && shouldCache) {
58
+ resultCache.set(key, {
59
+ data: result,
60
+ timestamp: Date.now()
61
+ });
62
+ }
63
+ return result;
64
+ } catch (error) {
65
+ const invalidatedAt = cacheInvalidatedAt.get(key);
66
+ const shouldCache = !invalidatedAt || invalidatedAt < requestStartTime;
67
+ if (cacheTTL > 0 && cacheErrors && shouldCache) {
68
+ resultCache.set(key, {
69
+ data: error,
70
+ timestamp: Date.now()
71
+ });
72
+ }
73
+ throw error;
74
+ } finally {
75
+ inFlightRequests.delete(key);
76
+ }
77
+ })();
78
+ const existingPromise = inFlightRequests.get(key);
79
+ if (existingPromise) {
80
+ requestPromise = existingPromise;
81
+ } else {
82
+ inFlightRequests.set(key, requestPromise);
83
+ }
84
+ }
85
+ return requestPromise;
86
+ };
87
+ const clearCache = (key) => {
88
+ resultCache.delete(key);
89
+ cacheInvalidatedAt.set(key, Date.now());
90
+ inFlightRequests.delete(key);
91
+ };
92
+ const clearAllCache = () => {
93
+ resultCache.clear();
94
+ cacheInvalidatedAt.clear();
95
+ inFlightRequests.clear();
96
+ };
97
+ const getStats = () => ({
98
+ inFlight: inFlightRequests.size,
99
+ cached: resultCache.size
100
+ });
101
+ return {
102
+ deduplicate,
103
+ clearCache,
104
+ clearAllCache,
105
+ getStats
106
+ };
107
+ }
108
+ var sharedSubscriptionDeduplicator = null;
109
+ function getSharedDeduplicator(options) {
110
+ if (!sharedSubscriptionDeduplicator) {
111
+ sharedSubscriptionDeduplicator = createRequestDeduplicator({
112
+ cacheTTL: 2e3,
113
+ // Cache results for 2 seconds
114
+ maxCacheSize: 1e3,
115
+ // Maximum cache entries
116
+ cacheErrors: true,
117
+ // Cache error results too
118
+ ...options
119
+ });
120
+ }
121
+ return sharedSubscriptionDeduplicator;
122
+ }
123
+ function clearSubscriptionCache(userId) {
124
+ const deduplicator = getSharedDeduplicator();
125
+ deduplicator.clearCache(userId);
126
+ }
127
+ function clearAllSubscriptionCache() {
128
+ const deduplicator = getSharedDeduplicator();
129
+ deduplicator.clearAllCache();
130
+ }
131
+ function getSubscriptionCacheStats() {
132
+ const deduplicator = getSharedDeduplicator();
133
+ return deduplicator.getStats();
134
+ }
135
+
6
136
  // src/helpers/auth.ts
7
137
  import { NextResponse } from "next/server";
8
138
  import {
@@ -22,10 +152,7 @@ async function getAuthenticatedUser(request, options = {}) {
22
152
 
23
153
  // src/helpers/customer.ts
24
154
  import { NextResponse as NextResponse2 } from "next/server";
25
- import {
26
- syncCustomerCore,
27
- isErrorResult as isErrorResult2
28
- } from "@solvapay/server";
155
+ import { syncCustomerCore, isErrorResult as isErrorResult2 } from "@solvapay/server";
29
156
  async function syncCustomer(request, options = {}) {
30
157
  const result = await syncCustomerCore(request, options);
31
158
  if (isErrorResult2(result)) {
@@ -110,10 +237,7 @@ async function createCustomerSession(request, options = {}) {
110
237
 
111
238
  // src/helpers/subscription.ts
112
239
  import { NextResponse as NextResponse5 } from "next/server";
113
- import {
114
- cancelSubscriptionCore,
115
- isErrorResult as isErrorResult5
116
- } from "@solvapay/server";
240
+ import { cancelSubscriptionCore, isErrorResult as isErrorResult5 } from "@solvapay/server";
117
241
  import { getAuthenticatedUserCore as getAuthenticatedUserCore3 } from "@solvapay/server";
118
242
  async function cancelSubscription(request, body, options = {}) {
119
243
  const result = await cancelSubscriptionCore(request, body, options);
@@ -135,10 +259,7 @@ async function cancelSubscription(request, body, options = {}) {
135
259
 
136
260
  // src/helpers/plans.ts
137
261
  import { NextResponse as NextResponse6 } from "next/server";
138
- import {
139
- listPlansCore,
140
- isErrorResult as isErrorResult6
141
- } from "@solvapay/server";
262
+ import { listPlansCore, isErrorResult as isErrorResult6 } from "@solvapay/server";
142
263
  async function listPlans(request) {
143
264
  const result = await listPlansCore(request);
144
265
  if (isErrorResult6(result)) {
@@ -153,20 +274,17 @@ async function listPlans(request) {
153
274
  // src/helpers/middleware.ts
154
275
  import { NextResponse as NextResponse7 } from "next/server";
155
276
  function createAuthMiddleware(options) {
156
- const {
157
- adapter,
158
- publicRoutes = [],
159
- userIdHeader = "x-user-id"
160
- } = options;
277
+ const { adapter, publicRoutes = [], userIdHeader = "x-user-id" } = options;
161
278
  return async function middleware(request) {
162
- const { pathname } = request.nextUrl;
279
+ const req = request;
280
+ const { pathname } = req.nextUrl;
163
281
  if (!pathname.startsWith("/api")) {
164
282
  return NextResponse7.next();
165
283
  }
166
284
  const isPublicRoute = publicRoutes.some((route) => pathname.startsWith(route));
167
- const userId = await adapter.getUserIdFromRequest(request);
285
+ const userId = await adapter.getUserIdFromRequest(req);
168
286
  if (isPublicRoute) {
169
- const requestHeaders2 = new Headers(request.headers);
287
+ const requestHeaders2 = new Headers(req.headers);
170
288
  if (userId) {
171
289
  requestHeaders2.set(userIdHeader, userId);
172
290
  }
@@ -182,7 +300,7 @@ function createAuthMiddleware(options) {
182
300
  { status: 401 }
183
301
  );
184
302
  }
185
- const requestHeaders = new Headers(request.headers);
303
+ const requestHeaders = new Headers(req.headers);
186
304
  requestHeaders.set(userIdHeader, userId);
187
305
  return NextResponse7.next({
188
306
  request: {
@@ -192,11 +310,7 @@ function createAuthMiddleware(options) {
192
310
  };
193
311
  }
194
312
  function createSupabaseAuthMiddleware(options = {}) {
195
- const {
196
- jwtSecret,
197
- publicRoutes = [],
198
- userIdHeader = "x-user-id"
199
- } = options;
313
+ const { jwtSecret, publicRoutes = [], userIdHeader = "x-user-id" } = options;
200
314
  let authAdapter = null;
201
315
  let adapterPromise = null;
202
316
  const lazyAdapter = {
@@ -228,122 +342,6 @@ function createSupabaseAuthMiddleware(options = {}) {
228
342
  }
229
343
 
230
344
  // src/index.ts
231
- function createRequestDeduplicator(options = {}) {
232
- const {
233
- cacheTTL = 2e3,
234
- maxCacheSize = 1e3,
235
- cacheErrors = true
236
- } = options;
237
- const inFlightRequests = /* @__PURE__ */ new Map();
238
- const resultCache = /* @__PURE__ */ new Map();
239
- const cacheInvalidatedAt = /* @__PURE__ */ new Map();
240
- let cleanupInterval = null;
241
- if (cacheTTL > 0) {
242
- cleanupInterval = setInterval(() => {
243
- const now = Date.now();
244
- const entriesToDelete = [];
245
- for (const [key, cached] of resultCache.entries()) {
246
- if (now - cached.timestamp >= cacheTTL) {
247
- entriesToDelete.push(key);
248
- }
249
- }
250
- for (const key of entriesToDelete) {
251
- resultCache.delete(key);
252
- cacheInvalidatedAt.delete(key);
253
- }
254
- if (resultCache.size > maxCacheSize) {
255
- const sortedEntries = Array.from(resultCache.entries()).sort((a, b) => a[1].timestamp - b[1].timestamp);
256
- const toRemove = sortedEntries.slice(0, resultCache.size - maxCacheSize);
257
- for (const [key] of toRemove) {
258
- resultCache.delete(key);
259
- cacheInvalidatedAt.delete(key);
260
- }
261
- }
262
- }, Math.min(cacheTTL, 1e3));
263
- }
264
- const deduplicate = async (key, fn) => {
265
- if (cacheTTL > 0) {
266
- const cached = resultCache.get(key);
267
- if (cached && Date.now() - cached.timestamp < cacheTTL) {
268
- return cached.data;
269
- } else if (cached) {
270
- resultCache.delete(key);
271
- }
272
- }
273
- let requestPromise = inFlightRequests.get(key);
274
- if (!requestPromise) {
275
- const requestStartTime = Date.now();
276
- requestPromise = (async () => {
277
- try {
278
- const result = await fn();
279
- const invalidatedAt = cacheInvalidatedAt.get(key);
280
- const shouldCache = !invalidatedAt || invalidatedAt < requestStartTime;
281
- if (cacheTTL > 0 && shouldCache) {
282
- resultCache.set(key, {
283
- data: result,
284
- timestamp: Date.now()
285
- });
286
- }
287
- return result;
288
- } catch (error) {
289
- const invalidatedAt = cacheInvalidatedAt.get(key);
290
- const shouldCache = !invalidatedAt || invalidatedAt < requestStartTime;
291
- if (cacheTTL > 0 && cacheErrors && shouldCache) {
292
- resultCache.set(key, {
293
- data: error,
294
- timestamp: Date.now()
295
- });
296
- }
297
- throw error;
298
- } finally {
299
- inFlightRequests.delete(key);
300
- }
301
- })();
302
- const existingPromise = inFlightRequests.get(key);
303
- if (existingPromise) {
304
- requestPromise = existingPromise;
305
- } else {
306
- inFlightRequests.set(key, requestPromise);
307
- }
308
- }
309
- return requestPromise;
310
- };
311
- const clearCache = (key) => {
312
- resultCache.delete(key);
313
- cacheInvalidatedAt.set(key, Date.now());
314
- inFlightRequests.delete(key);
315
- };
316
- const clearAllCache = () => {
317
- resultCache.clear();
318
- cacheInvalidatedAt.clear();
319
- inFlightRequests.clear();
320
- };
321
- const getStats = () => ({
322
- inFlight: inFlightRequests.size,
323
- cached: resultCache.size
324
- });
325
- return {
326
- deduplicate,
327
- clearCache,
328
- clearAllCache,
329
- getStats
330
- };
331
- }
332
- var sharedSubscriptionDeduplicator = null;
333
- function getSharedDeduplicator(options) {
334
- if (!sharedSubscriptionDeduplicator) {
335
- sharedSubscriptionDeduplicator = createRequestDeduplicator({
336
- cacheTTL: 2e3,
337
- // Cache results for 2 seconds
338
- maxCacheSize: 1e3,
339
- // Maximum cache entries
340
- cacheErrors: true,
341
- // Cache error results too
342
- ...options
343
- });
344
- }
345
- return sharedSubscriptionDeduplicator;
346
- }
347
345
  async function checkSubscription(request, options = {}) {
348
346
  try {
349
347
  const { requireUserId, getUserEmailFromRequest, getUserNameFromRequest } = await import("@solvapay/auth");
@@ -374,7 +372,7 @@ async function checkSubscription(request, options = {}) {
374
372
  };
375
373
  }
376
374
  }
377
- } catch (error) {
375
+ } catch {
378
376
  }
379
377
  }
380
378
  const deduplicator = getSharedDeduplicator(options.deduplication);
@@ -407,10 +405,7 @@ async function checkSubscription(request, options = {}) {
407
405
  } catch (error) {
408
406
  console.error("Check subscription failed:", error);
409
407
  if (error instanceof SolvaPayError) {
410
- return NextResponse8.json(
411
- { error: error.message },
412
- { status: 500 }
413
- );
408
+ return NextResponse8.json({ error: error.message }, { status: 500 });
414
409
  }
415
410
  const errorMessage = error instanceof Error ? error.message : "Unknown error";
416
411
  return NextResponse8.json(
@@ -419,18 +414,6 @@ async function checkSubscription(request, options = {}) {
419
414
  );
420
415
  }
421
416
  }
422
- function clearSubscriptionCache(userId) {
423
- const deduplicator = getSharedDeduplicator();
424
- deduplicator.clearCache(userId);
425
- }
426
- function clearAllSubscriptionCache() {
427
- const deduplicator = getSharedDeduplicator();
428
- deduplicator.clearAllCache();
429
- }
430
- function getSubscriptionCacheStats() {
431
- const deduplicator = getSharedDeduplicator();
432
- return deduplicator.getStats();
433
- }
434
417
  export {
435
418
  cancelSubscription,
436
419
  checkSubscription,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solvapay/next",
3
- "version": "1.0.0-preview.17",
3
+ "version": "1.0.0-preview.19",
4
4
  "type": "module",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
@@ -29,15 +29,15 @@
29
29
  },
30
30
  "sideEffects": false,
31
31
  "dependencies": {
32
- "@solvapay/auth": "1.0.0-preview.17",
33
- "@solvapay/core": "1.0.0-preview.17",
34
- "@solvapay/server": "1.0.0-preview.17"
32
+ "@solvapay/auth": "1.0.0-preview.19",
33
+ "@solvapay/core": "1.0.0-preview.19",
34
+ "@solvapay/server": "1.0.0-preview.19"
35
35
  },
36
36
  "peerDependencies": {
37
37
  "next": ">=13.0.0"
38
38
  },
39
39
  "devDependencies": {
40
- "next": "^14.0.0",
40
+ "next": "^15.5.7",
41
41
  "tsup": "^8.0.1",
42
42
  "typescript": "^5.5.4",
43
43
  "vitest": "^2.0.5",
@@ -47,6 +47,7 @@
47
47
  "build": "tsup src/index.ts --format esm,cjs --dts --tsconfig tsconfig.build.json --external next",
48
48
  "test": "vitest run || exit 0",
49
49
  "test:watch": "vitest",
50
- "lint": "echo 'no lint yet'"
50
+ "lint": "eslint src",
51
+ "lint:fix": "eslint src --fix"
51
52
  }
52
53
  }