diff --git a/package-lock.json b/package-lock.json index ed9d32c5..46b803a2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1787,9 +1787,6 @@ "cpu": [ "arm" ], - "libc": [ - "glibc" - ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -1806,9 +1803,6 @@ "cpu": [ "arm64" ], - "libc": [ - "glibc" - ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -1825,9 +1819,6 @@ "cpu": [ "ppc64" ], - "libc": [ - "glibc" - ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -1844,9 +1835,6 @@ "cpu": [ "riscv64" ], - "libc": [ - "glibc" - ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -1863,9 +1851,6 @@ "cpu": [ "s390x" ], - "libc": [ - "glibc" - ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -1882,9 +1867,6 @@ "cpu": [ "x64" ], - "libc": [ - "glibc" - ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -1901,9 +1883,6 @@ "cpu": [ "arm64" ], - "libc": [ - "musl" - ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -1920,9 +1899,6 @@ "cpu": [ "x64" ], - "libc": [ - "musl" - ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -1939,9 +1915,6 @@ "cpu": [ "arm" ], - "libc": [ - "glibc" - ], "license": "Apache-2.0", "optional": true, "os": [ @@ -1964,9 +1937,6 @@ "cpu": [ "arm64" ], - "libc": [ - "glibc" - ], "license": "Apache-2.0", "optional": true, "os": [ @@ -1989,9 +1959,6 @@ "cpu": [ "ppc64" ], - "libc": [ - "glibc" - ], "license": "Apache-2.0", "optional": true, "os": [ @@ -2014,9 +1981,6 @@ "cpu": [ "riscv64" ], - "libc": [ - "glibc" - ], "license": "Apache-2.0", "optional": true, "os": [ @@ -2039,9 +2003,6 @@ "cpu": [ "s390x" ], - "libc": [ - "glibc" - ], "license": "Apache-2.0", "optional": true, "os": [ @@ -2064,9 +2025,6 @@ "cpu": [ "x64" ], - "libc": [ - "glibc" - ], "license": "Apache-2.0", "optional": true, "os": [ @@ -2089,9 +2047,6 @@ "cpu": [ "arm64" ], - "libc": [ - "musl" - ], "license": "Apache-2.0", "optional": true, "os": [ @@ -2114,9 +2069,6 @@ "cpu": [ "x64" ], - "libc": [ - "musl" - ], "license": "Apache-2.0", "optional": true, "os": [ @@ -2362,9 +2314,6 @@ "cpu": [ "arm64" ], - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -2381,9 +2330,6 @@ "cpu": [ "arm64" ], - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -2400,9 +2346,6 @@ "cpu": [ "x64" ], - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -2419,9 +2362,6 @@ "cpu": [ "x64" ], - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -5626,9 +5566,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -5646,9 +5583,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -5666,9 +5600,6 @@ "ppc64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -5686,9 +5617,6 @@ "s390x" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -5706,9 +5634,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -5726,9 +5651,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -6102,9 +6024,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -6122,9 +6041,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -6142,9 +6058,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -6162,9 +6075,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -7043,9 +6953,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -7060,9 +6967,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -7077,9 +6981,6 @@ "ppc64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -7094,9 +6995,6 @@ "riscv64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -7111,9 +7009,6 @@ "riscv64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -7128,9 +7023,6 @@ "s390x" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -7145,9 +7037,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -7162,9 +7051,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -11959,9 +11845,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -11983,9 +11866,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -12007,9 +11887,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -12031,9 +11908,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MPL-2.0", "optional": true, "os": [ diff --git a/src/app/api/inventory/route.ts b/src/app/api/inventory/route.ts index c8c588cd..efea8d4a 100644 --- a/src/app/api/inventory/route.ts +++ b/src/app/api/inventory/route.ts @@ -179,9 +179,7 @@ async function handleReserve(body: unknown, user: InventorySessionUser) { /** * Handle confirm action */ -async function handleConfirm(body: unknown, user: InventorySessionUser) { - void user; - +async function handleConfirm(body: unknown, _user: InventorySessionUser) { const validated = confirmSchema.parse(body); const { prisma } = await import('@/lib/prisma'); @@ -215,9 +213,7 @@ async function handleConfirm(body: unknown, user: InventorySessionUser) { /** * Handle release action */ -async function handleRelease(body: unknown, user: InventorySessionUser) { - void user; - +async function handleRelease(body: unknown, _user: InventorySessionUser) { const validated = releaseSchema.parse(body); const { prisma } = await import('@/lib/prisma'); @@ -252,9 +248,7 @@ async function handleRelease(body: unknown, user: InventorySessionUser) { /** * Handle check action */ -async function handleCheck(body: unknown, user: InventorySessionUser) { - void user; - +async function handleCheck(body: unknown, _user: InventorySessionUser) { const validated = checkSchema.parse(body); const trustedStoreId = await getAuthorizedStoreId(validated.storeId); diff --git a/src/lib/services/landing-page-service.ts b/src/lib/services/landing-page-service.ts index 23f125ce..40f31626 100644 --- a/src/lib/services/landing-page-service.ts +++ b/src/lib/services/landing-page-service.ts @@ -20,7 +20,7 @@ import type { LandingPageDetail, LandingPageCategory, } from "@/lib/landing-pages/types"; -import { sanitizeRichText as sanitizeRichHtml } from "@/lib/security/xss-protection"; +import { sanitizeRichText as sanitizeRichTextFromXssProtection } from "@/lib/security/xss-protection"; // --------------------------------------------------------------------------- // Helpers @@ -58,9 +58,10 @@ function toListItem( const RICH_TEXT_FIELD_PATTERN = /(content|body|text|html)$/i; const MAX_CUSTOM_CSS_LENGTH = 20_000; +const MAX_RICH_TEXT_LENGTH = 10_000; function sanitizeRichText(value: string): string { - return sanitizeRichHtml(value, 10000); + return sanitizeRichTextFromXssProtection(value, MAX_RICH_TEXT_LENGTH); } function sanitizeCustomData( @@ -254,7 +255,11 @@ export async function createLandingPage( }, }); - return getLandingPage(storeId, p.id) as Promise; + const page = await getLandingPage(storeId, p.id); + if (!page) { + throw new Error(`Failed to load landing page after creation: storeId=${storeId}, pageId=${p.id}`); + } + return page; } // --------------------------------------------------------------------------- @@ -302,7 +307,11 @@ export async function updateLandingPage( data: updateData, }); - return getLandingPage(storeId, pageId) as Promise; + const result = await getLandingPage(storeId, pageId); + if (!result) { + throw new Error(`Landing page not found: storeId=${storeId}, pageId=${pageId}`); + } + return result; } // --------------------------------------------------------------------------- @@ -345,7 +354,11 @@ export async function publishLandingPage( }, }); - return getLandingPage(storeId, pageId) as Promise; + const updated = await getLandingPage(storeId, pageId); + if (!updated) { + throw new Error(`Landing page not found: storeId=${storeId}, pageId=${pageId}`); + } + return updated; } // --------------------------------------------------------------------------- @@ -367,7 +380,11 @@ export async function unpublishLandingPage( data: { status: "DRAFT", publishedAt: null, publishedUrl: null }, }); - return getLandingPage(storeId, pageId) as Promise; + const updated = await getLandingPage(storeId, pageId); + if (!updated) { + throw new Error(`Landing page not found: storeId=${storeId}, pageId=${pageId}`); + } + return updated; } // --------------------------------------------------------------------------- diff --git a/src/lib/subscription/feature-enforcer.ts b/src/lib/subscription/feature-enforcer.ts index 80ce0813..f1fcd241 100644 --- a/src/lib/subscription/feature-enforcer.ts +++ b/src/lib/subscription/feature-enforcer.ts @@ -8,6 +8,8 @@ import { prisma } from '@/lib/prisma'; import type { FeatureLimits, SubscriptionWithPlan } from './types'; +type FeatureFlag = 'posEnabled' | 'accountingEnabled' | 'customDomainEnabled' | 'apiAccessEnabled'; + function parseFeatureOverrides(rawOverrides: string | null): Partial { if (!rawOverrides) { return {}; @@ -63,6 +65,13 @@ function getFreeTierLimits(): FeatureLimits { }; } +function getStartOfMonth(): Date { + const startOfMonth = new Date(); + startOfMonth.setDate(1); + startOfMonth.setHours(0, 0, 0, 0); + return startOfMonth; +} + export interface FeatureCheckResult { allowed: boolean; currentUsage: number; @@ -110,9 +119,7 @@ export async function canCreateOrder( storeId: string, limits: FeatureLimits ): Promise { - const startOfMonth = new Date(); - startOfMonth.setDate(1); - startOfMonth.setHours(0, 0, 0, 0); + const startOfMonth = getStartOfMonth(); const count = await prisma.order.count({ where: { @@ -133,10 +140,10 @@ export async function canCreateOrder( } export function canUseFeature( - feature: keyof Pick, + feature: FeatureFlag, limits: FeatureLimits ): { allowed: boolean; message?: string } { - const featureNames: Record = { + const featureNames: Record = { posEnabled: 'Point of Sale', accountingEnabled: 'Accounting', customDomainEnabled: 'Custom Domain', @@ -152,9 +159,7 @@ export function canUseFeature( } export async function getUsageStats(storeId: string) { - const startOfMonth = new Date(); - startOfMonth.setDate(1); - startOfMonth.setHours(0, 0, 0, 0); + const startOfMonth = getStartOfMonth(); const [productsUsed, staffUsed, ordersUsed] = await Promise.all([ prisma.product.count({ where: { storeId, deletedAt: null } }), diff --git a/src/test/services/search.service.test.ts b/src/test/services/search.service.test.ts index a1b0cb1d..b188166d 100644 --- a/src/test/services/search.service.test.ts +++ b/src/test/services/search.service.test.ts @@ -16,7 +16,7 @@ vi.mock('@/lib/prisma', () => ({ }, })); -// Mock elasticsearch client to force Postgres fallback +// Mock search engine client to force Postgres fallback vi.mock('@/lib/search/elasticsearch-client', () => ({ isSearchEngineHealthy: () => Promise.resolve(false), getSearchEngine: () => 'postgres',