@solvapay/next 1.0.0-preview.9 → 1.0.1-preview.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.
- package/LICENSE.md +21 -0
- package/README.md +271 -20
- package/dist/index.cjs +303 -76
- package/dist/index.d.cts +458 -53
- package/dist/index.d.ts +458 -53
- package/dist/index.js +299 -71
- package/package.json +10 -9
package/dist/index.js
CHANGED
|
@@ -1,39 +1,41 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
import { NextResponse } from "next/server";
|
|
2
|
+
import { NextResponse as NextResponse8 } from "next/server";
|
|
3
3
|
import { createSolvaPay } from "@solvapay/server";
|
|
4
4
|
import { SolvaPayError } from "@solvapay/core";
|
|
5
|
+
|
|
6
|
+
// src/cache.ts
|
|
5
7
|
function createRequestDeduplicator(options = {}) {
|
|
6
|
-
const {
|
|
7
|
-
cacheTTL = 2e3,
|
|
8
|
-
maxCacheSize = 1e3,
|
|
9
|
-
cacheErrors = true
|
|
10
|
-
} = options;
|
|
8
|
+
const { cacheTTL = 2e3, maxCacheSize = 1e3, cacheErrors = true } = options;
|
|
11
9
|
const inFlightRequests = /* @__PURE__ */ new Map();
|
|
12
10
|
const resultCache = /* @__PURE__ */ new Map();
|
|
13
11
|
const cacheInvalidatedAt = /* @__PURE__ */ new Map();
|
|
14
|
-
let cleanupInterval = null;
|
|
15
12
|
if (cacheTTL > 0) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
+
}
|
|
22
21
|
}
|
|
23
|
-
|
|
24
|
-
for (const key of entriesToDelete) {
|
|
25
|
-
resultCache.delete(key);
|
|
26
|
-
cacheInvalidatedAt.delete(key);
|
|
27
|
-
}
|
|
28
|
-
if (resultCache.size > maxCacheSize) {
|
|
29
|
-
const sortedEntries = Array.from(resultCache.entries()).sort((a, b) => a[1].timestamp - b[1].timestamp);
|
|
30
|
-
const toRemove = sortedEntries.slice(0, resultCache.size - maxCacheSize);
|
|
31
|
-
for (const [key] of toRemove) {
|
|
22
|
+
for (const key of entriesToDelete) {
|
|
32
23
|
resultCache.delete(key);
|
|
33
24
|
cacheInvalidatedAt.delete(key);
|
|
34
25
|
}
|
|
35
|
-
|
|
36
|
-
|
|
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
|
+
);
|
|
37
39
|
}
|
|
38
40
|
const deduplicate = async (key, fn) => {
|
|
39
41
|
if (cacheTTL > 0) {
|
|
@@ -103,10 +105,10 @@ function createRequestDeduplicator(options = {}) {
|
|
|
103
105
|
getStats
|
|
104
106
|
};
|
|
105
107
|
}
|
|
106
|
-
var
|
|
108
|
+
var sharedPurchaseDeduplicator = null;
|
|
107
109
|
function getSharedDeduplicator(options) {
|
|
108
|
-
if (!
|
|
109
|
-
|
|
110
|
+
if (!sharedPurchaseDeduplicator) {
|
|
111
|
+
sharedPurchaseDeduplicator = createRequestDeduplicator({
|
|
110
112
|
cacheTTL: 2e3,
|
|
111
113
|
// Cache results for 2 seconds
|
|
112
114
|
maxCacheSize: 1e3,
|
|
@@ -116,89 +118,315 @@ function getSharedDeduplicator(options) {
|
|
|
116
118
|
...options
|
|
117
119
|
});
|
|
118
120
|
}
|
|
119
|
-
return
|
|
121
|
+
return sharedPurchaseDeduplicator;
|
|
122
|
+
}
|
|
123
|
+
function clearPurchaseCache(userId) {
|
|
124
|
+
const deduplicator = getSharedDeduplicator();
|
|
125
|
+
deduplicator.clearCache(userId);
|
|
126
|
+
}
|
|
127
|
+
function clearAllPurchaseCache() {
|
|
128
|
+
const deduplicator = getSharedDeduplicator();
|
|
129
|
+
deduplicator.clearAllCache();
|
|
130
|
+
}
|
|
131
|
+
function getPurchaseCacheStats() {
|
|
132
|
+
const deduplicator = getSharedDeduplicator();
|
|
133
|
+
return deduplicator.getStats();
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// src/helpers/auth.ts
|
|
137
|
+
import { NextResponse } from "next/server";
|
|
138
|
+
import {
|
|
139
|
+
getAuthenticatedUserCore,
|
|
140
|
+
isErrorResult
|
|
141
|
+
} from "@solvapay/server";
|
|
142
|
+
async function getAuthenticatedUser(request, options = {}) {
|
|
143
|
+
const result = await getAuthenticatedUserCore(request, options);
|
|
144
|
+
if (isErrorResult(result)) {
|
|
145
|
+
return NextResponse.json(
|
|
146
|
+
{ error: result.error, details: result.details },
|
|
147
|
+
{ status: result.status }
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
return result;
|
|
120
151
|
}
|
|
121
|
-
|
|
152
|
+
|
|
153
|
+
// src/helpers/customer.ts
|
|
154
|
+
import { NextResponse as NextResponse2 } from "next/server";
|
|
155
|
+
import { syncCustomerCore, isErrorResult as isErrorResult2 } from "@solvapay/server";
|
|
156
|
+
async function syncCustomer(request, options = {}) {
|
|
157
|
+
const result = await syncCustomerCore(request, options);
|
|
158
|
+
if (isErrorResult2(result)) {
|
|
159
|
+
return NextResponse2.json(
|
|
160
|
+
{ error: result.error, details: result.details },
|
|
161
|
+
{ status: result.status }
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
return result;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// src/helpers/payment.ts
|
|
168
|
+
import { NextResponse as NextResponse3 } from "next/server";
|
|
169
|
+
import {
|
|
170
|
+
createPaymentIntentCore,
|
|
171
|
+
processPaymentIntentCore,
|
|
172
|
+
isErrorResult as isErrorResult3
|
|
173
|
+
} from "@solvapay/server";
|
|
174
|
+
import { getAuthenticatedUserCore as getAuthenticatedUserCore2 } from "@solvapay/server";
|
|
175
|
+
async function createPaymentIntent(request, body, options = {}) {
|
|
176
|
+
const result = await createPaymentIntentCore(request, body, options);
|
|
177
|
+
if (isErrorResult3(result)) {
|
|
178
|
+
return NextResponse3.json(
|
|
179
|
+
{ error: result.error, details: result.details },
|
|
180
|
+
{ status: result.status }
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
try {
|
|
184
|
+
const userResult = await getAuthenticatedUserCore2(request);
|
|
185
|
+
if (!isErrorResult3(userResult)) {
|
|
186
|
+
clearPurchaseCache(userResult.userId);
|
|
187
|
+
}
|
|
188
|
+
} catch {
|
|
189
|
+
}
|
|
190
|
+
return result;
|
|
191
|
+
}
|
|
192
|
+
async function processPaymentIntent(request, body, options = {}) {
|
|
193
|
+
const result = await processPaymentIntentCore(request, body, options);
|
|
194
|
+
if (isErrorResult3(result)) {
|
|
195
|
+
return NextResponse3.json(
|
|
196
|
+
{ error: result.error, details: result.details },
|
|
197
|
+
{ status: result.status }
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
try {
|
|
201
|
+
const userResult = await getAuthenticatedUserCore2(request);
|
|
202
|
+
if (!isErrorResult3(userResult)) {
|
|
203
|
+
clearPurchaseCache(userResult.userId);
|
|
204
|
+
}
|
|
205
|
+
} catch {
|
|
206
|
+
}
|
|
207
|
+
return result;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// src/helpers/checkout.ts
|
|
211
|
+
import { NextResponse as NextResponse4 } from "next/server";
|
|
212
|
+
import {
|
|
213
|
+
createCheckoutSessionCore,
|
|
214
|
+
createCustomerSessionCore,
|
|
215
|
+
isErrorResult as isErrorResult4
|
|
216
|
+
} from "@solvapay/server";
|
|
217
|
+
async function createCheckoutSession(request, body, options = {}) {
|
|
218
|
+
const result = await createCheckoutSessionCore(request, body, options);
|
|
219
|
+
if (isErrorResult4(result)) {
|
|
220
|
+
return NextResponse4.json(
|
|
221
|
+
{ error: result.error, details: result.details },
|
|
222
|
+
{ status: result.status }
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
return result;
|
|
226
|
+
}
|
|
227
|
+
async function createCustomerSession(request, options = {}) {
|
|
228
|
+
const result = await createCustomerSessionCore(request, options);
|
|
229
|
+
if (isErrorResult4(result)) {
|
|
230
|
+
return NextResponse4.json(
|
|
231
|
+
{ error: result.error, details: result.details },
|
|
232
|
+
{ status: result.status }
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
return result;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// src/helpers/renewal.ts
|
|
239
|
+
import { NextResponse as NextResponse5 } from "next/server";
|
|
240
|
+
import { cancelPurchaseCore, isErrorResult as isErrorResult5 } from "@solvapay/server";
|
|
241
|
+
import { getAuthenticatedUserCore as getAuthenticatedUserCore3 } from "@solvapay/server";
|
|
242
|
+
async function cancelRenewal(request, body, options = {}) {
|
|
243
|
+
const result = await cancelPurchaseCore(request, body, options);
|
|
244
|
+
if (isErrorResult5(result)) {
|
|
245
|
+
return NextResponse5.json(
|
|
246
|
+
{ error: result.error, details: result.details },
|
|
247
|
+
{ status: result.status }
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
try {
|
|
251
|
+
const userResult = await getAuthenticatedUserCore3(request);
|
|
252
|
+
if (!isErrorResult5(userResult)) {
|
|
253
|
+
clearPurchaseCache(userResult.userId);
|
|
254
|
+
}
|
|
255
|
+
} catch {
|
|
256
|
+
}
|
|
257
|
+
return result;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// src/helpers/plans.ts
|
|
261
|
+
import { NextResponse as NextResponse6 } from "next/server";
|
|
262
|
+
import { listPlansCore, isErrorResult as isErrorResult6 } from "@solvapay/server";
|
|
263
|
+
async function listPlans(request) {
|
|
264
|
+
const result = await listPlansCore(request);
|
|
265
|
+
if (isErrorResult6(result)) {
|
|
266
|
+
return NextResponse6.json(
|
|
267
|
+
{ error: result.error, details: result.details },
|
|
268
|
+
{ status: result.status }
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
return result;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// src/helpers/middleware.ts
|
|
275
|
+
import { NextResponse as NextResponse7 } from "next/server";
|
|
276
|
+
function createAuthMiddleware(options) {
|
|
277
|
+
const { adapter, publicRoutes = [], userIdHeader = "x-user-id" } = options;
|
|
278
|
+
return async function middleware(request) {
|
|
279
|
+
const req = request;
|
|
280
|
+
const { pathname } = req.nextUrl;
|
|
281
|
+
if (!pathname.startsWith("/api")) {
|
|
282
|
+
return NextResponse7.next();
|
|
283
|
+
}
|
|
284
|
+
const isPublicRoute = publicRoutes.some((route) => pathname.startsWith(route));
|
|
285
|
+
const userId = await adapter.getUserIdFromRequest(req);
|
|
286
|
+
if (isPublicRoute) {
|
|
287
|
+
const requestHeaders2 = new Headers(req.headers);
|
|
288
|
+
if (userId) {
|
|
289
|
+
requestHeaders2.set(userIdHeader, userId);
|
|
290
|
+
}
|
|
291
|
+
return NextResponse7.next({
|
|
292
|
+
request: {
|
|
293
|
+
headers: requestHeaders2
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
if (!userId) {
|
|
298
|
+
return NextResponse7.json(
|
|
299
|
+
{ error: "Unauthorized", details: "Valid authentication required" },
|
|
300
|
+
{ status: 401 }
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
const requestHeaders = new Headers(req.headers);
|
|
304
|
+
requestHeaders.set(userIdHeader, userId);
|
|
305
|
+
return NextResponse7.next({
|
|
306
|
+
request: {
|
|
307
|
+
headers: requestHeaders
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
function createSupabaseAuthMiddleware(options = {}) {
|
|
313
|
+
const { jwtSecret, publicRoutes = [], userIdHeader = "x-user-id" } = options;
|
|
314
|
+
let authAdapter = null;
|
|
315
|
+
let adapterPromise = null;
|
|
316
|
+
const lazyAdapter = {
|
|
317
|
+
async getUserIdFromRequest(req) {
|
|
318
|
+
if (!authAdapter) {
|
|
319
|
+
if (!adapterPromise) {
|
|
320
|
+
adapterPromise = (async () => {
|
|
321
|
+
const secret = jwtSecret || process.env.SUPABASE_JWT_SECRET;
|
|
322
|
+
if (!secret) {
|
|
323
|
+
throw new Error(
|
|
324
|
+
"SUPABASE_JWT_SECRET environment variable is required. Please set it in your .env.local file. Get it from: Supabase Dashboard \u2192 Settings \u2192 API \u2192 JWT Secret"
|
|
325
|
+
);
|
|
326
|
+
}
|
|
327
|
+
const { SupabaseAuthAdapter } = await import("@solvapay/auth/supabase");
|
|
328
|
+
authAdapter = new SupabaseAuthAdapter({ jwtSecret: secret });
|
|
329
|
+
return authAdapter;
|
|
330
|
+
})();
|
|
331
|
+
}
|
|
332
|
+
authAdapter = await adapterPromise;
|
|
333
|
+
}
|
|
334
|
+
return authAdapter.getUserIdFromRequest(req);
|
|
335
|
+
}
|
|
336
|
+
};
|
|
337
|
+
return createAuthMiddleware({
|
|
338
|
+
adapter: lazyAdapter,
|
|
339
|
+
publicRoutes,
|
|
340
|
+
userIdHeader
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// src/index.ts
|
|
345
|
+
async function checkPurchase(request, options = {}) {
|
|
122
346
|
try {
|
|
123
347
|
const { requireUserId, getUserEmailFromRequest, getUserNameFromRequest } = await import("@solvapay/auth");
|
|
124
348
|
const userIdOrError = requireUserId(request);
|
|
125
349
|
if (userIdOrError instanceof Response) {
|
|
126
350
|
const clonedResponse = userIdOrError.clone();
|
|
127
351
|
const body = await clonedResponse.json().catch(() => ({ error: "Unauthorized" }));
|
|
128
|
-
return
|
|
352
|
+
return NextResponse8.json(body, { status: userIdOrError.status });
|
|
129
353
|
}
|
|
130
354
|
const userId = userIdOrError;
|
|
131
355
|
const email = options.includeEmail !== false ? await getUserEmailFromRequest(request) : null;
|
|
132
356
|
const name = options.includeName !== false ? await getUserNameFromRequest(request) : null;
|
|
357
|
+
const cachedCustomerRef = request.headers.get("x-solvapay-customer-ref");
|
|
358
|
+
const solvaPay = options.solvaPay || createSolvaPay();
|
|
359
|
+
if (cachedCustomerRef) {
|
|
360
|
+
try {
|
|
361
|
+
const customer = await solvaPay.getCustomer({ customerRef: cachedCustomerRef });
|
|
362
|
+
if (customer && customer.customerRef) {
|
|
363
|
+
if (customer.externalRef && customer.externalRef === userId) {
|
|
364
|
+
const filteredPurchases = (customer.purchases || []).filter(
|
|
365
|
+
(p) => p.status === "active"
|
|
366
|
+
);
|
|
367
|
+
return {
|
|
368
|
+
customerRef: customer.customerRef,
|
|
369
|
+
email: customer.email,
|
|
370
|
+
name: customer.name,
|
|
371
|
+
purchases: filteredPurchases
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
} catch {
|
|
376
|
+
}
|
|
377
|
+
}
|
|
133
378
|
const deduplicator = getSharedDeduplicator(options.deduplication);
|
|
134
379
|
const response = await deduplicator.deduplicate(userId, async () => {
|
|
135
380
|
try {
|
|
136
|
-
const solvaPay = options.solvaPay || createSolvaPay();
|
|
137
381
|
const ensuredCustomerRef = await solvaPay.ensureCustomer(userId, userId, {
|
|
138
382
|
email: email || void 0,
|
|
139
383
|
name: name || void 0
|
|
140
384
|
});
|
|
141
385
|
const customer = await solvaPay.getCustomer({ customerRef: ensuredCustomerRef });
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
const isCancelled = sub.status === "cancelled" || subAny.cancelledAt;
|
|
146
|
-
if (!isCancelled) {
|
|
147
|
-
return true;
|
|
148
|
-
}
|
|
149
|
-
if (isCancelled && subAny.endDate) {
|
|
150
|
-
const endDate = new Date(subAny.endDate);
|
|
151
|
-
const isFuture = endDate > now;
|
|
152
|
-
return isFuture;
|
|
153
|
-
}
|
|
154
|
-
return false;
|
|
155
|
-
});
|
|
386
|
+
const filteredPurchases = (customer.purchases || []).filter(
|
|
387
|
+
(p) => p.status === "active"
|
|
388
|
+
);
|
|
156
389
|
const result = {
|
|
157
390
|
customerRef: customer.customerRef || userId,
|
|
158
391
|
email: customer.email,
|
|
159
392
|
name: customer.name,
|
|
160
|
-
|
|
393
|
+
purchases: filteredPurchases
|
|
161
394
|
};
|
|
162
395
|
return result;
|
|
163
396
|
} catch (error) {
|
|
164
|
-
console.error("[
|
|
397
|
+
console.error("[checkPurchase] Error fetching customer:", error);
|
|
165
398
|
return {
|
|
166
399
|
customerRef: userId,
|
|
167
|
-
|
|
400
|
+
purchases: []
|
|
168
401
|
};
|
|
169
402
|
}
|
|
170
403
|
});
|
|
171
404
|
return response;
|
|
172
405
|
} catch (error) {
|
|
173
|
-
console.error("Check
|
|
406
|
+
console.error("Check purchase failed:", error);
|
|
174
407
|
if (error instanceof SolvaPayError) {
|
|
175
|
-
return
|
|
176
|
-
{ error: error.message },
|
|
177
|
-
{ status: 500 }
|
|
178
|
-
);
|
|
408
|
+
return NextResponse8.json({ error: error.message }, { status: 500 });
|
|
179
409
|
}
|
|
180
410
|
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
181
|
-
return
|
|
182
|
-
{ error: "Failed to check
|
|
411
|
+
return NextResponse8.json(
|
|
412
|
+
{ error: "Failed to check purchase", details: errorMessage },
|
|
183
413
|
{ status: 500 }
|
|
184
414
|
);
|
|
185
415
|
}
|
|
186
416
|
}
|
|
187
|
-
function clearSubscriptionCache(userId) {
|
|
188
|
-
const deduplicator = getSharedDeduplicator();
|
|
189
|
-
deduplicator.clearCache(userId);
|
|
190
|
-
}
|
|
191
|
-
function clearAllSubscriptionCache() {
|
|
192
|
-
const deduplicator = getSharedDeduplicator();
|
|
193
|
-
deduplicator.clearAllCache();
|
|
194
|
-
}
|
|
195
|
-
function getSubscriptionCacheStats() {
|
|
196
|
-
const deduplicator = getSharedDeduplicator();
|
|
197
|
-
return deduplicator.getStats();
|
|
198
|
-
}
|
|
199
417
|
export {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
418
|
+
cancelRenewal,
|
|
419
|
+
checkPurchase,
|
|
420
|
+
clearAllPurchaseCache,
|
|
421
|
+
clearPurchaseCache,
|
|
422
|
+
createAuthMiddleware,
|
|
423
|
+
createCheckoutSession,
|
|
424
|
+
createCustomerSession,
|
|
425
|
+
createPaymentIntent,
|
|
426
|
+
createSupabaseAuthMiddleware,
|
|
427
|
+
getAuthenticatedUser,
|
|
428
|
+
getPurchaseCacheStats,
|
|
429
|
+
listPlans,
|
|
430
|
+
processPaymentIntent,
|
|
431
|
+
syncCustomer
|
|
204
432
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solvapay/next",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1-preview.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -29,24 +29,25 @@
|
|
|
29
29
|
},
|
|
30
30
|
"sideEffects": false,
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@solvapay/
|
|
33
|
-
"@solvapay/
|
|
34
|
-
"@solvapay/
|
|
32
|
+
"@solvapay/server": "1.0.1-preview.1",
|
|
33
|
+
"@solvapay/auth": "1.0.1-preview.1",
|
|
34
|
+
"@solvapay/core": "1.0.1-preview.1"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
37
|
"next": ">=13.0.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"next": "^
|
|
41
|
-
"tsup": "^8.
|
|
42
|
-
"typescript": "^5.
|
|
43
|
-
"vitest": "^
|
|
40
|
+
"next": "^16.2.1",
|
|
41
|
+
"tsup": "^8.5.1",
|
|
42
|
+
"typescript": "^5.9.3",
|
|
43
|
+
"vitest": "^4.1.2",
|
|
44
44
|
"@solvapay/test-utils": "0.0.0"
|
|
45
45
|
},
|
|
46
46
|
"scripts": {
|
|
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": "
|
|
50
|
+
"lint": "eslint src",
|
|
51
|
+
"lint:fix": "eslint src --fix"
|
|
51
52
|
}
|
|
52
53
|
}
|