@open-mercato/checkout 0.6.5-develop.5309.1.be1df535b3 → 0.6.5-develop.5382.1.f542de69af

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.
@@ -1,5 +1,6 @@
1
1
  import { NextResponse } from "next/server";
2
2
  import { findAndCountWithDecryption } from "@open-mercato/shared/lib/encryption/find";
3
+ import { escapeLikePattern } from "@open-mercato/shared/lib/db/escapeLikePattern";
3
4
  import { CheckoutLink } from "../../data/entities.js";
4
5
  import { serializeLinkRecord } from "../../commands/links.js";
5
6
  import {
@@ -32,9 +33,9 @@ async function GET(req) {
32
33
  const pricingMode = url.searchParams.get("pricingMode");
33
34
  if (search) {
34
35
  where.$or = [
35
- { name: { $ilike: `%${search}%` } },
36
- { title: { $ilike: `%${search}%` } },
37
- { slug: { $ilike: `%${search}%` } }
36
+ { name: { $ilike: `%${escapeLikePattern(search)}%` } },
37
+ { title: { $ilike: `%${escapeLikePattern(search)}%` } },
38
+ { slug: { $ilike: `%${escapeLikePattern(search)}%` } }
38
39
  ];
39
40
  }
40
41
  if (templateId) where.templateId = templateId;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/checkout/api/links/route.ts"],
4
- "sourcesContent": ["import { NextResponse } from 'next/server'\nimport type { FilterQuery } from '@mikro-orm/postgresql'\nimport { findAndCountWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { CheckoutLink } from '../../data/entities'\nimport { serializeLinkRecord } from '../../commands/links'\nimport {\n attachOperationMetadataHeader,\n buildCommandRuntimeContext,\n handleCheckoutRouteError,\n requireAdminContext,\n} from '../helpers'\nimport { checkoutTag } from '../openapi'\n\nexport const metadata = {\n path: '/checkout/links',\n GET: { requireAuth: true, requireFeatures: ['checkout.view'] },\n POST: { requireAuth: true, requireFeatures: ['checkout.create'] },\n}\n\nexport async function GET(req: Request) {\n try {\n const { auth, em } = await requireAdminContext(req)\n const url = new URL(req.url)\n const page = Math.max(1, Number(url.searchParams.get('page') ?? '1'))\n const pageSize = Math.min(100, Math.max(1, Number(url.searchParams.get('pageSize') ?? '25')))\n const search = (url.searchParams.get('search') ?? '').trim()\n const where: FilterQuery<CheckoutLink> = {\n organizationId: auth.orgId,\n tenantId: auth.tenantId,\n deletedAt: null,\n }\n const templateId = url.searchParams.get('templateId')\n const isLocked = url.searchParams.get('isLocked')\n const status = url.searchParams.get('status')\n const pricingMode = url.searchParams.get('pricingMode')\n if (search) {\n where.$or = [\n { name: { $ilike: `%${search}%` } },\n { title: { $ilike: `%${search}%` } },\n { slug: { $ilike: `%${search}%` } },\n ]\n }\n if (templateId) where.templateId = templateId\n if (status === 'draft' || status === 'active' || status === 'inactive') where.status = status\n if (isLocked === 'true' || isLocked === 'false') where.isLocked = isLocked === 'true'\n if (pricingMode === 'fixed' || pricingMode === 'custom_amount' || pricingMode === 'price_list') where.pricingMode = pricingMode\n const [items, total] = await findAndCountWithDecryption(\n em,\n CheckoutLink,\n where,\n {\n orderBy: { createdAt: 'desc' },\n offset: (page - 1) * pageSize,\n limit: pageSize,\n },\n { organizationId: auth.orgId, tenantId: auth.tenantId },\n )\n return NextResponse.json({\n items: items.map((item) => serializeLinkRecord(item)),\n total,\n page,\n pageSize,\n totalPages: Math.max(1, Math.ceil(total / pageSize)),\n })\n } catch (error) {\n return handleCheckoutRouteError(error)\n }\n}\n\nexport async function POST(req: Request) {\n try {\n const { auth, container, commandBus } = await requireAdminContext(req)\n const body = await req.json().catch(() => ({}))\n const { result, logEntry } = await commandBus.execute<Record<string, unknown>, { id: string; slug: string }>('checkout.link.create', {\n input: body,\n ctx: buildCommandRuntimeContext(req, container, auth),\n })\n return attachOperationMetadataHeader(\n NextResponse.json(result, { status: 201 }),\n logEntry,\n { resourceKind: 'checkout.link', resourceId: result.id },\n )\n } catch (error) {\n return handleCheckoutRouteError(error)\n }\n}\n\nexport const openApi = {\n tags: [checkoutTag],\n}\n\nexport default { GET, POST }\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { NextResponse } from 'next/server'\nimport type { FilterQuery } from '@mikro-orm/postgresql'\nimport { findAndCountWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { escapeLikePattern } from '@open-mercato/shared/lib/db/escapeLikePattern'\nimport { CheckoutLink } from '../../data/entities'\nimport { serializeLinkRecord } from '../../commands/links'\nimport {\n attachOperationMetadataHeader,\n buildCommandRuntimeContext,\n handleCheckoutRouteError,\n requireAdminContext,\n} from '../helpers'\nimport { checkoutTag } from '../openapi'\n\nexport const metadata = {\n path: '/checkout/links',\n GET: { requireAuth: true, requireFeatures: ['checkout.view'] },\n POST: { requireAuth: true, requireFeatures: ['checkout.create'] },\n}\n\nexport async function GET(req: Request) {\n try {\n const { auth, em } = await requireAdminContext(req)\n const url = new URL(req.url)\n const page = Math.max(1, Number(url.searchParams.get('page') ?? '1'))\n const pageSize = Math.min(100, Math.max(1, Number(url.searchParams.get('pageSize') ?? '25')))\n const search = (url.searchParams.get('search') ?? '').trim()\n const where: FilterQuery<CheckoutLink> = {\n organizationId: auth.orgId,\n tenantId: auth.tenantId,\n deletedAt: null,\n }\n const templateId = url.searchParams.get('templateId')\n const isLocked = url.searchParams.get('isLocked')\n const status = url.searchParams.get('status')\n const pricingMode = url.searchParams.get('pricingMode')\n if (search) {\n where.$or = [\n { name: { $ilike: `%${escapeLikePattern(search)}%` } },\n { title: { $ilike: `%${escapeLikePattern(search)}%` } },\n { slug: { $ilike: `%${escapeLikePattern(search)}%` } },\n ]\n }\n if (templateId) where.templateId = templateId\n if (status === 'draft' || status === 'active' || status === 'inactive') where.status = status\n if (isLocked === 'true' || isLocked === 'false') where.isLocked = isLocked === 'true'\n if (pricingMode === 'fixed' || pricingMode === 'custom_amount' || pricingMode === 'price_list') where.pricingMode = pricingMode\n const [items, total] = await findAndCountWithDecryption(\n em,\n CheckoutLink,\n where,\n {\n orderBy: { createdAt: 'desc' },\n offset: (page - 1) * pageSize,\n limit: pageSize,\n },\n { organizationId: auth.orgId, tenantId: auth.tenantId },\n )\n return NextResponse.json({\n items: items.map((item) => serializeLinkRecord(item)),\n total,\n page,\n pageSize,\n totalPages: Math.max(1, Math.ceil(total / pageSize)),\n })\n } catch (error) {\n return handleCheckoutRouteError(error)\n }\n}\n\nexport async function POST(req: Request) {\n try {\n const { auth, container, commandBus } = await requireAdminContext(req)\n const body = await req.json().catch(() => ({}))\n const { result, logEntry } = await commandBus.execute<Record<string, unknown>, { id: string; slug: string }>('checkout.link.create', {\n input: body,\n ctx: buildCommandRuntimeContext(req, container, auth),\n })\n return attachOperationMetadataHeader(\n NextResponse.json(result, { status: 201 }),\n logEntry,\n { resourceKind: 'checkout.link', resourceId: result.id },\n )\n } catch (error) {\n return handleCheckoutRouteError(error)\n }\n}\n\nexport const openApi = {\n tags: [checkoutTag],\n}\n\nexport default { GET, POST }\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,5 +1,6 @@
1
1
  import { NextResponse } from "next/server";
2
2
  import { findAndCountWithDecryption } from "@open-mercato/shared/lib/encryption/find";
3
+ import { escapeLikePattern } from "@open-mercato/shared/lib/db/escapeLikePattern";
3
4
  import { CheckoutLinkTemplate } from "../../data/entities.js";
4
5
  import { checkoutTag } from "../openapi.js";
5
6
  import {
@@ -30,8 +31,8 @@ async function GET(req) {
30
31
  };
31
32
  if (search) {
32
33
  where.$or = [
33
- { name: { $ilike: `%${search}%` } },
34
- { title: { $ilike: `%${search}%` } }
34
+ { name: { $ilike: `%${escapeLikePattern(search)}%` } },
35
+ { title: { $ilike: `%${escapeLikePattern(search)}%` } }
35
36
  ];
36
37
  }
37
38
  if (pricingMode === "fixed" || pricingMode === "custom_amount" || pricingMode === "price_list") where.pricingMode = pricingMode;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/checkout/api/templates/route.ts"],
4
- "sourcesContent": ["import { NextResponse } from 'next/server'\nimport type { FilterQuery } from '@mikro-orm/postgresql'\nimport { findAndCountWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { CheckoutLinkTemplate } from '../../data/entities'\nimport { checkoutTag } from '../openapi'\nimport {\n attachOperationMetadataHeader,\n buildCommandRuntimeContext,\n handleCheckoutRouteError,\n requireAdminContext,\n} from '../helpers'\nimport { serializeTemplateRecord } from '../../commands/templates'\n\nexport const metadata = {\n path: '/checkout/templates',\n GET: { requireAuth: true, requireFeatures: ['checkout.view'] },\n POST: { requireAuth: true, requireFeatures: ['checkout.create'] },\n}\n\nexport async function GET(req: Request) {\n try {\n const { auth, em } = await requireAdminContext(req)\n const url = new URL(req.url)\n const page = Math.max(1, Number(url.searchParams.get('page') ?? '1'))\n const pageSize = Math.min(100, Math.max(1, Number(url.searchParams.get('pageSize') ?? '25')))\n const search = (url.searchParams.get('search') ?? '').trim()\n const pricingMode = url.searchParams.get('pricingMode')\n const gatewayProviderKey = url.searchParams.get('gatewayProviderKey')\n const where: FilterQuery<CheckoutLinkTemplate> = {\n organizationId: auth.orgId,\n tenantId: auth.tenantId,\n deletedAt: null,\n }\n if (search) {\n where.$or = [\n { name: { $ilike: `%${search}%` } },\n { title: { $ilike: `%${search}%` } },\n ]\n }\n if (pricingMode === 'fixed' || pricingMode === 'custom_amount' || pricingMode === 'price_list') where.pricingMode = pricingMode\n if (gatewayProviderKey) where.gatewayProviderKey = gatewayProviderKey\n const [items, total] = await findAndCountWithDecryption(\n em,\n CheckoutLinkTemplate,\n where,\n {\n orderBy: { createdAt: 'desc' },\n offset: (page - 1) * pageSize,\n limit: pageSize,\n },\n { organizationId: auth.orgId, tenantId: auth.tenantId },\n )\n return NextResponse.json({\n items: items.map((item) => serializeTemplateRecord(item)),\n total,\n page,\n pageSize,\n totalPages: Math.max(1, Math.ceil(total / pageSize)),\n })\n } catch (error) {\n return handleCheckoutRouteError(error)\n }\n}\n\nexport async function POST(req: Request) {\n try {\n const { auth, container, commandBus } = await requireAdminContext(req)\n const body = await req.json().catch(() => ({}))\n const { result, logEntry } = await commandBus.execute<Record<string, unknown>, { id: string }>('checkout.template.create', {\n input: body,\n ctx: buildCommandRuntimeContext(req, container, auth),\n })\n return attachOperationMetadataHeader(\n NextResponse.json(result, { status: 201 }),\n logEntry,\n { resourceKind: 'checkout.template', resourceId: result.id },\n )\n } catch (error) {\n return handleCheckoutRouteError(error)\n }\n}\n\nexport const openApi = {\n tags: [checkoutTag],\n}\n\nexport default { GET, POST }\n"],
5
- "mappings": "AAAA,SAAS,oBAAoB;AAE7B,SAAS,kCAAkC;AAC3C,SAAS,4BAA4B;AACrC,SAAS,mBAAmB;AAC5B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,+BAA+B;AAEjC,MAAM,WAAW;AAAA,EACtB,MAAM;AAAA,EACN,KAAK,EAAE,aAAa,MAAM,iBAAiB,CAAC,eAAe,EAAE;AAAA,EAC7D,MAAM,EAAE,aAAa,MAAM,iBAAiB,CAAC,iBAAiB,EAAE;AAClE;AAEA,eAAsB,IAAI,KAAc;AACtC,MAAI;AACF,UAAM,EAAE,MAAM,GAAG,IAAI,MAAM,oBAAoB,GAAG;AAClD,UAAM,MAAM,IAAI,IAAI,IAAI,GAAG;AAC3B,UAAM,OAAO,KAAK,IAAI,GAAG,OAAO,IAAI,aAAa,IAAI,MAAM,KAAK,GAAG,CAAC;AACpE,UAAM,WAAW,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,OAAO,IAAI,aAAa,IAAI,UAAU,KAAK,IAAI,CAAC,CAAC;AAC5F,UAAM,UAAU,IAAI,aAAa,IAAI,QAAQ,KAAK,IAAI,KAAK;AAC3D,UAAM,cAAc,IAAI,aAAa,IAAI,aAAa;AACtD,UAAM,qBAAqB,IAAI,aAAa,IAAI,oBAAoB;AACpE,UAAM,QAA2C;AAAA,MAC/C,gBAAgB,KAAK;AAAA,MACrB,UAAU,KAAK;AAAA,MACf,WAAW;AAAA,IACb;AACA,QAAI,QAAQ;AACV,YAAM,MAAM;AAAA,QACV,EAAE,MAAM,EAAE,QAAQ,IAAI,MAAM,IAAI,EAAE;AAAA,QAClC,EAAE,OAAO,EAAE,QAAQ,IAAI,MAAM,IAAI,EAAE;AAAA,MACrC;AAAA,IACF;AACA,QAAI,gBAAgB,WAAW,gBAAgB,mBAAmB,gBAAgB,aAAc,OAAM,cAAc;AACpH,QAAI,mBAAoB,OAAM,qBAAqB;AACnD,UAAM,CAAC,OAAO,KAAK,IAAI,MAAM;AAAA,MAC3B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,QACE,SAAS,EAAE,WAAW,OAAO;AAAA,QAC7B,SAAS,OAAO,KAAK;AAAA,QACrB,OAAO;AAAA,MACT;AAAA,MACA,EAAE,gBAAgB,KAAK,OAAO,UAAU,KAAK,SAAS;AAAA,IACxD;AACA,WAAO,aAAa,KAAK;AAAA,MACvB,OAAO,MAAM,IAAI,CAAC,SAAS,wBAAwB,IAAI,CAAC;AAAA,MACxD;AAAA,MACA;AAAA,MACA;AAAA,MACA,YAAY,KAAK,IAAI,GAAG,KAAK,KAAK,QAAQ,QAAQ,CAAC;AAAA,IACrD,CAAC;AAAA,EACH,SAAS,OAAO;AACd,WAAO,yBAAyB,KAAK;AAAA,EACvC;AACF;AAEA,eAAsB,KAAK,KAAc;AACvC,MAAI;AACF,UAAM,EAAE,MAAM,WAAW,WAAW,IAAI,MAAM,oBAAoB,GAAG;AACrE,UAAM,OAAO,MAAM,IAAI,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAC9C,UAAM,EAAE,QAAQ,SAAS,IAAI,MAAM,WAAW,QAAiD,4BAA4B;AAAA,MACzH,OAAO;AAAA,MACP,KAAK,2BAA2B,KAAK,WAAW,IAAI;AAAA,IACtD,CAAC;AACD,WAAO;AAAA,MACL,aAAa,KAAK,QAAQ,EAAE,QAAQ,IAAI,CAAC;AAAA,MACzC;AAAA,MACA,EAAE,cAAc,qBAAqB,YAAY,OAAO,GAAG;AAAA,IAC7D;AAAA,EACF,SAAS,OAAO;AACd,WAAO,yBAAyB,KAAK;AAAA,EACvC;AACF;AAEO,MAAM,UAAU;AAAA,EACrB,MAAM,CAAC,WAAW;AACpB;AAEA,IAAO,gBAAQ,EAAE,KAAK,KAAK;",
4
+ "sourcesContent": ["import { NextResponse } from 'next/server'\nimport type { FilterQuery } from '@mikro-orm/postgresql'\nimport { findAndCountWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { escapeLikePattern } from '@open-mercato/shared/lib/db/escapeLikePattern'\nimport { CheckoutLinkTemplate } from '../../data/entities'\nimport { checkoutTag } from '../openapi'\nimport {\n attachOperationMetadataHeader,\n buildCommandRuntimeContext,\n handleCheckoutRouteError,\n requireAdminContext,\n} from '../helpers'\nimport { serializeTemplateRecord } from '../../commands/templates'\n\nexport const metadata = {\n path: '/checkout/templates',\n GET: { requireAuth: true, requireFeatures: ['checkout.view'] },\n POST: { requireAuth: true, requireFeatures: ['checkout.create'] },\n}\n\nexport async function GET(req: Request) {\n try {\n const { auth, em } = await requireAdminContext(req)\n const url = new URL(req.url)\n const page = Math.max(1, Number(url.searchParams.get('page') ?? '1'))\n const pageSize = Math.min(100, Math.max(1, Number(url.searchParams.get('pageSize') ?? '25')))\n const search = (url.searchParams.get('search') ?? '').trim()\n const pricingMode = url.searchParams.get('pricingMode')\n const gatewayProviderKey = url.searchParams.get('gatewayProviderKey')\n const where: FilterQuery<CheckoutLinkTemplate> = {\n organizationId: auth.orgId,\n tenantId: auth.tenantId,\n deletedAt: null,\n }\n if (search) {\n where.$or = [\n { name: { $ilike: `%${escapeLikePattern(search)}%` } },\n { title: { $ilike: `%${escapeLikePattern(search)}%` } },\n ]\n }\n if (pricingMode === 'fixed' || pricingMode === 'custom_amount' || pricingMode === 'price_list') where.pricingMode = pricingMode\n if (gatewayProviderKey) where.gatewayProviderKey = gatewayProviderKey\n const [items, total] = await findAndCountWithDecryption(\n em,\n CheckoutLinkTemplate,\n where,\n {\n orderBy: { createdAt: 'desc' },\n offset: (page - 1) * pageSize,\n limit: pageSize,\n },\n { organizationId: auth.orgId, tenantId: auth.tenantId },\n )\n return NextResponse.json({\n items: items.map((item) => serializeTemplateRecord(item)),\n total,\n page,\n pageSize,\n totalPages: Math.max(1, Math.ceil(total / pageSize)),\n })\n } catch (error) {\n return handleCheckoutRouteError(error)\n }\n}\n\nexport async function POST(req: Request) {\n try {\n const { auth, container, commandBus } = await requireAdminContext(req)\n const body = await req.json().catch(() => ({}))\n const { result, logEntry } = await commandBus.execute<Record<string, unknown>, { id: string }>('checkout.template.create', {\n input: body,\n ctx: buildCommandRuntimeContext(req, container, auth),\n })\n return attachOperationMetadataHeader(\n NextResponse.json(result, { status: 201 }),\n logEntry,\n { resourceKind: 'checkout.template', resourceId: result.id },\n )\n } catch (error) {\n return handleCheckoutRouteError(error)\n }\n}\n\nexport const openApi = {\n tags: [checkoutTag],\n}\n\nexport default { GET, POST }\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,5 +1,6 @@
1
1
  import { NextResponse } from "next/server";
2
2
  import { findAndCountWithDecryption, findWithDecryption } from "@open-mercato/shared/lib/encryption/find";
3
+ import { escapeLikePattern } from "@open-mercato/shared/lib/db/escapeLikePattern";
3
4
  import { CheckoutLink, CheckoutTransaction } from "../../data/entities.js";
4
5
  import { handleCheckoutRouteError, requireAdminContext, userHasCheckoutFeature } from "../helpers.js";
5
6
  import { checkoutTag } from "../openapi.js";
@@ -25,10 +26,10 @@ async function GET(req) {
25
26
  if (linkId) where.linkId = linkId;
26
27
  if (status) where.status = status;
27
28
  if (search) where.$or = [
28
- { email: { $ilike: `%${search}%` } },
29
- { firstName: { $ilike: `%${search}%` } },
30
- { lastName: { $ilike: `%${search}%` } },
31
- { id: { $ilike: `%${search}%` } }
29
+ { email: { $ilike: `%${escapeLikePattern(search)}%` } },
30
+ { firstName: { $ilike: `%${escapeLikePattern(search)}%` } },
31
+ { lastName: { $ilike: `%${escapeLikePattern(search)}%` } },
32
+ { id: { $ilike: `%${escapeLikePattern(search)}%` } }
32
33
  ];
33
34
  const [items, total] = await findAndCountWithDecryption(
34
35
  em,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/checkout/api/transactions/route.ts"],
4
- "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { findAndCountWithDecryption, findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { CheckoutLink, CheckoutTransaction } from '../../data/entities'\nimport { handleCheckoutRouteError, requireAdminContext, userHasCheckoutFeature } from '../helpers'\nimport { checkoutTag } from '../openapi'\nimport { serializeTransaction } from '../../lib/utils'\n\nexport const metadata = {\n path: '/checkout/transactions',\n GET: { requireAuth: true, requireFeatures: ['checkout.view'] },\n}\n\nexport async function GET(req: Request) {\n try {\n const { auth, container, em } = await requireAdminContext(req)\n const canViewPii = await userHasCheckoutFeature(container, auth, 'checkout.viewPii')\n const url = new URL(req.url)\n const page = Math.max(1, Number(url.searchParams.get('page') ?? '1'))\n const pageSize = Math.min(100, Math.max(1, Number(url.searchParams.get('pageSize') ?? '25')))\n const search = (url.searchParams.get('search') ?? '').trim()\n const linkId = url.searchParams.get('linkId')\n const status = url.searchParams.get('status')\n const where: Record<string, unknown> = {\n organizationId: auth.orgId,\n tenantId: auth.tenantId,\n }\n if (linkId) where.linkId = linkId\n if (status) where.status = status\n if (search) where.$or = [\n { email: { $ilike: `%${search}%` } },\n { firstName: { $ilike: `%${search}%` } },\n { lastName: { $ilike: `%${search}%` } },\n { id: { $ilike: `%${search}%` } },\n ]\n const [items, total] = await findAndCountWithDecryption(\n em,\n CheckoutTransaction,\n where,\n {\n orderBy: { createdAt: 'desc' },\n offset: (page - 1) * pageSize,\n limit: pageSize,\n },\n { organizationId: auth.orgId, tenantId: auth.tenantId },\n )\n const linkIds = Array.from(new Set(items.map((item) => item.linkId)))\n const links = linkIds.length\n ? await findWithDecryption(em, CheckoutLink, {\n id: { $in: linkIds },\n organizationId: auth.orgId,\n tenantId: auth.tenantId,\n deletedAt: null,\n }, undefined, { organizationId: auth.orgId, tenantId: auth.tenantId })\n : []\n const linkMap = new Map(links.map((link) => [link.id, link]))\n return NextResponse.json({\n items: items.map((item) => serializeTransaction(item, linkMap.get(item.linkId) ?? null, canViewPii)),\n total,\n page,\n pageSize,\n totalPages: Math.max(1, Math.ceil(total / pageSize)),\n canViewPii,\n })\n } catch (error) {\n return handleCheckoutRouteError(error)\n }\n}\n\nexport const openApi = {\n tags: [checkoutTag],\n}\n\nexport default GET\n"],
5
- "mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,4BAA4B,0BAA0B;AAC/D,SAAS,cAAc,2BAA2B;AAClD,SAAS,0BAA0B,qBAAqB,8BAA8B;AACtF,SAAS,mBAAmB;AAC5B,SAAS,4BAA4B;AAE9B,MAAM,WAAW;AAAA,EACtB,MAAM;AAAA,EACN,KAAK,EAAE,aAAa,MAAM,iBAAiB,CAAC,eAAe,EAAE;AAC/D;AAEA,eAAsB,IAAI,KAAc;AACtC,MAAI;AACF,UAAM,EAAE,MAAM,WAAW,GAAG,IAAI,MAAM,oBAAoB,GAAG;AAC7D,UAAM,aAAa,MAAM,uBAAuB,WAAW,MAAM,kBAAkB;AACnF,UAAM,MAAM,IAAI,IAAI,IAAI,GAAG;AAC3B,UAAM,OAAO,KAAK,IAAI,GAAG,OAAO,IAAI,aAAa,IAAI,MAAM,KAAK,GAAG,CAAC;AACpE,UAAM,WAAW,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,OAAO,IAAI,aAAa,IAAI,UAAU,KAAK,IAAI,CAAC,CAAC;AAC5F,UAAM,UAAU,IAAI,aAAa,IAAI,QAAQ,KAAK,IAAI,KAAK;AAC3D,UAAM,SAAS,IAAI,aAAa,IAAI,QAAQ;AAC5C,UAAM,SAAS,IAAI,aAAa,IAAI,QAAQ;AAC5C,UAAM,QAAiC;AAAA,MACrC,gBAAgB,KAAK;AAAA,MACrB,UAAU,KAAK;AAAA,IACjB;AACA,QAAI,OAAQ,OAAM,SAAS;AAC3B,QAAI,OAAQ,OAAM,SAAS;AAC3B,QAAI,OAAQ,OAAM,MAAM;AAAA,MACtB,EAAE,OAAO,EAAE,QAAQ,IAAI,MAAM,IAAI,EAAE;AAAA,MACnC,EAAE,WAAW,EAAE,QAAQ,IAAI,MAAM,IAAI,EAAE;AAAA,MACvC,EAAE,UAAU,EAAE,QAAQ,IAAI,MAAM,IAAI,EAAE;AAAA,MACtC,EAAE,IAAI,EAAE,QAAQ,IAAI,MAAM,IAAI,EAAE;AAAA,IAClC;AACA,UAAM,CAAC,OAAO,KAAK,IAAI,MAAM;AAAA,MAC3B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,QACE,SAAS,EAAE,WAAW,OAAO;AAAA,QAC7B,SAAS,OAAO,KAAK;AAAA,QACrB,OAAO;AAAA,MACT;AAAA,MACA,EAAE,gBAAgB,KAAK,OAAO,UAAU,KAAK,SAAS;AAAA,IACxD;AACA,UAAM,UAAU,MAAM,KAAK,IAAI,IAAI,MAAM,IAAI,CAAC,SAAS,KAAK,MAAM,CAAC,CAAC;AACpE,UAAM,QAAQ,QAAQ,SAClB,MAAM,mBAAmB,IAAI,cAAc;AAAA,MAC3C,IAAI,EAAE,KAAK,QAAQ;AAAA,MACnB,gBAAgB,KAAK;AAAA,MACrB,UAAU,KAAK;AAAA,MACf,WAAW;AAAA,IACb,GAAG,QAAW,EAAE,gBAAgB,KAAK,OAAO,UAAU,KAAK,SAAS,CAAC,IACnE,CAAC;AACL,UAAM,UAAU,IAAI,IAAI,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;AAC5D,WAAO,aAAa,KAAK;AAAA,MACvB,OAAO,MAAM,IAAI,CAAC,SAAS,qBAAqB,MAAM,QAAQ,IAAI,KAAK,MAAM,KAAK,MAAM,UAAU,CAAC;AAAA,MACnG;AAAA,MACA;AAAA,MACA;AAAA,MACA,YAAY,KAAK,IAAI,GAAG,KAAK,KAAK,QAAQ,QAAQ,CAAC;AAAA,MACnD;AAAA,IACF,CAAC;AAAA,EACH,SAAS,OAAO;AACd,WAAO,yBAAyB,KAAK;AAAA,EACvC;AACF;AAEO,MAAM,UAAU;AAAA,EACrB,MAAM,CAAC,WAAW;AACpB;AAEA,IAAO,gBAAQ;",
4
+ "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { findAndCountWithDecryption, findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { escapeLikePattern } from '@open-mercato/shared/lib/db/escapeLikePattern'\nimport { CheckoutLink, CheckoutTransaction } from '../../data/entities'\nimport { handleCheckoutRouteError, requireAdminContext, userHasCheckoutFeature } from '../helpers'\nimport { checkoutTag } from '../openapi'\nimport { serializeTransaction } from '../../lib/utils'\n\nexport const metadata = {\n path: '/checkout/transactions',\n GET: { requireAuth: true, requireFeatures: ['checkout.view'] },\n}\n\nexport async function GET(req: Request) {\n try {\n const { auth, container, em } = await requireAdminContext(req)\n const canViewPii = await userHasCheckoutFeature(container, auth, 'checkout.viewPii')\n const url = new URL(req.url)\n const page = Math.max(1, Number(url.searchParams.get('page') ?? '1'))\n const pageSize = Math.min(100, Math.max(1, Number(url.searchParams.get('pageSize') ?? '25')))\n const search = (url.searchParams.get('search') ?? '').trim()\n const linkId = url.searchParams.get('linkId')\n const status = url.searchParams.get('status')\n const where: Record<string, unknown> = {\n organizationId: auth.orgId,\n tenantId: auth.tenantId,\n }\n if (linkId) where.linkId = linkId\n if (status) where.status = status\n if (search) where.$or = [\n { email: { $ilike: `%${escapeLikePattern(search)}%` } },\n { firstName: { $ilike: `%${escapeLikePattern(search)}%` } },\n { lastName: { $ilike: `%${escapeLikePattern(search)}%` } },\n { id: { $ilike: `%${escapeLikePattern(search)}%` } },\n ]\n const [items, total] = await findAndCountWithDecryption(\n em,\n CheckoutTransaction,\n where,\n {\n orderBy: { createdAt: 'desc' },\n offset: (page - 1) * pageSize,\n limit: pageSize,\n },\n { organizationId: auth.orgId, tenantId: auth.tenantId },\n )\n const linkIds = Array.from(new Set(items.map((item) => item.linkId)))\n const links = linkIds.length\n ? await findWithDecryption(em, CheckoutLink, {\n id: { $in: linkIds },\n organizationId: auth.orgId,\n tenantId: auth.tenantId,\n deletedAt: null,\n }, undefined, { organizationId: auth.orgId, tenantId: auth.tenantId })\n : []\n const linkMap = new Map(links.map((link) => [link.id, link]))\n return NextResponse.json({\n items: items.map((item) => serializeTransaction(item, linkMap.get(item.linkId) ?? null, canViewPii)),\n total,\n page,\n pageSize,\n totalPages: Math.max(1, Math.ceil(total / pageSize)),\n canViewPii,\n })\n } catch (error) {\n return handleCheckoutRouteError(error)\n }\n}\n\nexport const openApi = {\n tags: [checkoutTag],\n}\n\nexport default GET\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-mercato/checkout",
3
- "version": "0.6.5-develop.5309.1.be1df535b3",
3
+ "version": "0.6.5-develop.5382.1.f542de69af",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "scripts": {
@@ -61,18 +61,18 @@
61
61
  }
62
62
  },
63
63
  "dependencies": {
64
- "@open-mercato/core": "0.6.5-develop.5309.1.be1df535b3",
65
- "@open-mercato/ui": "0.6.5-develop.5309.1.be1df535b3",
64
+ "@open-mercato/core": "0.6.5-develop.5382.1.f542de69af",
65
+ "@open-mercato/ui": "0.6.5-develop.5382.1.f542de69af",
66
66
  "bcryptjs": "^3.0.3"
67
67
  },
68
68
  "peerDependencies": {
69
69
  "@mikro-orm/postgresql": "^7.0.14",
70
- "@open-mercato/shared": "0.6.5-develop.5309.1.be1df535b3",
70
+ "@open-mercato/shared": "0.6.5-develop.5382.1.f542de69af",
71
71
  "react": "^19.0.0",
72
72
  "react-dom": "^19.0.0"
73
73
  },
74
74
  "devDependencies": {
75
- "@open-mercato/shared": "0.6.5-develop.5309.1.be1df535b3",
75
+ "@open-mercato/shared": "0.6.5-develop.5382.1.f542de69af",
76
76
  "@types/jest": "^30.0.0",
77
77
  "@types/react": "^19.2.17",
78
78
  "@types/react-dom": "^19.2.3",
@@ -1,6 +1,7 @@
1
1
  import { NextResponse } from 'next/server'
2
2
  import type { FilterQuery } from '@mikro-orm/postgresql'
3
3
  import { findAndCountWithDecryption } from '@open-mercato/shared/lib/encryption/find'
4
+ import { escapeLikePattern } from '@open-mercato/shared/lib/db/escapeLikePattern'
4
5
  import { CheckoutLink } from '../../data/entities'
5
6
  import { serializeLinkRecord } from '../../commands/links'
6
7
  import {
@@ -35,9 +36,9 @@ export async function GET(req: Request) {
35
36
  const pricingMode = url.searchParams.get('pricingMode')
36
37
  if (search) {
37
38
  where.$or = [
38
- { name: { $ilike: `%${search}%` } },
39
- { title: { $ilike: `%${search}%` } },
40
- { slug: { $ilike: `%${search}%` } },
39
+ { name: { $ilike: `%${escapeLikePattern(search)}%` } },
40
+ { title: { $ilike: `%${escapeLikePattern(search)}%` } },
41
+ { slug: { $ilike: `%${escapeLikePattern(search)}%` } },
41
42
  ]
42
43
  }
43
44
  if (templateId) where.templateId = templateId
@@ -1,6 +1,7 @@
1
1
  import { NextResponse } from 'next/server'
2
2
  import type { FilterQuery } from '@mikro-orm/postgresql'
3
3
  import { findAndCountWithDecryption } from '@open-mercato/shared/lib/encryption/find'
4
+ import { escapeLikePattern } from '@open-mercato/shared/lib/db/escapeLikePattern'
4
5
  import { CheckoutLinkTemplate } from '../../data/entities'
5
6
  import { checkoutTag } from '../openapi'
6
7
  import {
@@ -33,8 +34,8 @@ export async function GET(req: Request) {
33
34
  }
34
35
  if (search) {
35
36
  where.$or = [
36
- { name: { $ilike: `%${search}%` } },
37
- { title: { $ilike: `%${search}%` } },
37
+ { name: { $ilike: `%${escapeLikePattern(search)}%` } },
38
+ { title: { $ilike: `%${escapeLikePattern(search)}%` } },
38
39
  ]
39
40
  }
40
41
  if (pricingMode === 'fixed' || pricingMode === 'custom_amount' || pricingMode === 'price_list') where.pricingMode = pricingMode
@@ -1,5 +1,6 @@
1
1
  import { NextResponse } from 'next/server'
2
2
  import { findAndCountWithDecryption, findWithDecryption } from '@open-mercato/shared/lib/encryption/find'
3
+ import { escapeLikePattern } from '@open-mercato/shared/lib/db/escapeLikePattern'
3
4
  import { CheckoutLink, CheckoutTransaction } from '../../data/entities'
4
5
  import { handleCheckoutRouteError, requireAdminContext, userHasCheckoutFeature } from '../helpers'
5
6
  import { checkoutTag } from '../openapi'
@@ -27,10 +28,10 @@ export async function GET(req: Request) {
27
28
  if (linkId) where.linkId = linkId
28
29
  if (status) where.status = status
29
30
  if (search) where.$or = [
30
- { email: { $ilike: `%${search}%` } },
31
- { firstName: { $ilike: `%${search}%` } },
32
- { lastName: { $ilike: `%${search}%` } },
33
- { id: { $ilike: `%${search}%` } },
31
+ { email: { $ilike: `%${escapeLikePattern(search)}%` } },
32
+ { firstName: { $ilike: `%${escapeLikePattern(search)}%` } },
33
+ { lastName: { $ilike: `%${escapeLikePattern(search)}%` } },
34
+ { id: { $ilike: `%${escapeLikePattern(search)}%` } },
34
35
  ]
35
36
  const [items, total] = await findAndCountWithDecryption(
36
37
  em,