mcp-scraper 0.3.20 → 0.3.21

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 (33) hide show
  1. package/dist/bin/api-server.cjs +108 -155
  2. package/dist/bin/api-server.cjs.map +1 -1
  3. package/dist/bin/api-server.js +3 -3
  4. package/dist/bin/mcp-scraper-cli.cjs +1 -1
  5. package/dist/bin/mcp-scraper-cli.cjs.map +1 -1
  6. package/dist/bin/mcp-scraper-cli.js +1 -1
  7. package/dist/bin/mcp-scraper-install.cjs +1 -1
  8. package/dist/bin/mcp-scraper-install.cjs.map +1 -1
  9. package/dist/bin/mcp-scraper-install.js +1 -1
  10. package/dist/bin/mcp-stdio-server.cjs +1 -1
  11. package/dist/bin/mcp-stdio-server.cjs.map +1 -1
  12. package/dist/bin/mcp-stdio-server.js +2 -2
  13. package/dist/{chunk-IORA5BFI.js → chunk-3KYRG7O7.js} +24 -2
  14. package/dist/chunk-3KYRG7O7.js.map +1 -0
  15. package/dist/{chunk-YZAYOFJV.js → chunk-7PQFU7TV.js} +13 -20
  16. package/dist/chunk-7PQFU7TV.js.map +1 -0
  17. package/dist/chunk-J4PSMJNZ.js +7 -0
  18. package/dist/chunk-J4PSMJNZ.js.map +1 -0
  19. package/dist/{chunk-6N6USFMH.js → chunk-UO252634.js} +2 -2
  20. package/dist/{db-ZWV4Y43C.js → db-EG5ETPTY.js} +4 -2
  21. package/dist/{server-NKZW2SEV.js → server-K4UIE2R3.js} +83 -141
  22. package/dist/server-K4UIE2R3.js.map +1 -0
  23. package/dist/{worker-PR7GODIV.js → worker-AITQTXHM.js} +3 -3
  24. package/docs/mcp-tool-manifest.generated.json +1 -1
  25. package/package.json +1 -1
  26. package/dist/chunk-IORA5BFI.js.map +0 -1
  27. package/dist/chunk-XLHBBA3U.js +0 -7
  28. package/dist/chunk-XLHBBA3U.js.map +0 -1
  29. package/dist/chunk-YZAYOFJV.js.map +0 -1
  30. package/dist/server-NKZW2SEV.js.map +0 -1
  31. /package/dist/{chunk-6N6USFMH.js.map → chunk-UO252634.js.map} +0 -0
  32. /package/dist/{db-ZWV4Y43C.js.map → db-EG5ETPTY.js.map} +0 -0
  33. /package/dist/{worker-PR7GODIV.js.map → worker-AITQTXHM.js.map} +0 -0
@@ -21,7 +21,7 @@ import {
21
21
  renderLinkReport,
22
22
  sanitizeAttempts,
23
23
  sanitizeHarvestResult
24
- } from "./chunk-6N6USFMH.js";
24
+ } from "./chunk-UO252634.js";
25
25
  import {
26
26
  csvRecords,
27
27
  listWorkflowDefinitions,
@@ -33,18 +33,16 @@ import {
33
33
  workflowStepCount,
34
34
  workflowSupportsSteps
35
35
  } from "./chunk-H2R232HK.js";
36
- import "./chunk-XLHBBA3U.js";
36
+ import "./chunk-J4PSMJNZ.js";
37
37
  import {
38
- BALANCE_PACK_LABELS,
39
- BALANCE_PRICE_IDS,
40
38
  BROWSER_OPEN_MIN_BALANCE_MC,
41
39
  CONCURRENCY_PRICE_ID,
42
40
  CREDIT_COST_CATALOG,
43
- FREE_MONTHLY_REFRESH_MC,
44
- FREE_SIGNUP_MC,
45
41
  LedgerOperation,
46
42
  MC_COSTS,
47
43
  MC_PER_CREDIT,
44
+ SUBSCRIPTION_TIERS,
45
+ SUBSCRIPTION_TIER_BY_KEY,
48
46
  browserActiveCostMc,
49
47
  classifyHarvestProblem,
50
48
  concurrencySlotBillingInfo,
@@ -52,7 +50,7 @@ import {
52
50
  harvestProblemResponse,
53
51
  insufficientBalanceResponse,
54
52
  serializeHarvestProblem
55
- } from "./chunk-YZAYOFJV.js";
53
+ } from "./chunk-7PQFU7TV.js";
56
54
  import {
57
55
  BrowserDriver,
58
56
  MapsSelectors,
@@ -86,7 +84,6 @@ import {
86
84
  appendWorkflowArtifacts,
87
85
  cancelJob,
88
86
  checkRateLimit,
89
- claimMonthlyFreeRefresh,
90
87
  completeJob,
91
88
  completeWorkflowRunRecord,
92
89
  consumePasswordResetToken,
@@ -140,8 +137,9 @@ import {
140
137
  setExtraConcurrencySlots,
141
138
  setPassword,
142
139
  setStripeCustomerId,
140
+ setSubscriptionTier,
143
141
  verifyPassword
144
- } from "./chunk-IORA5BFI.js";
142
+ } from "./chunk-3KYRG7O7.js";
145
143
 
146
144
  // src/blog/registry.ts
147
145
  var posts = [
@@ -9045,7 +9043,8 @@ var DEFAULT_RETRY_AFTER_SECONDS = 30;
9045
9043
  var MAX_LOCK_TTL_SECONDS = 24 * 60 * 60;
9046
9044
  var schemaReady = null;
9047
9045
  function concurrencyLimitForUser(user) {
9048
- return 1 + Math.max(0, Number(user.extra_concurrency_slots ?? 0));
9046
+ const tier = Math.max(0, Number(user.subscription_concurrency ?? 0));
9047
+ return Math.max(1, tier) + Math.max(0, Number(user.extra_concurrency_slots ?? 0));
9049
9048
  }
9050
9049
  function concurrencyLimitExceededResponse(gate) {
9051
9050
  const upgrade = concurrencySlotBillingInfo();
@@ -16458,49 +16457,58 @@ stripeApp.post("/webhooks", async (c) => {
16458
16457
  }
16459
16458
  const isNew = await recordStripeEvent(event.id);
16460
16459
  if (!isNew) return c.json({ received: true });
16461
- if (event.type === "checkout.session.completed") {
16462
- const session = event.data.object;
16463
- if (session.payment_status !== "paid") return c.json({ received: true });
16464
- const customerId = session.customer;
16465
- const lineItems = await stripe.checkout.sessions.listLineItems(session.id);
16466
- const priceId = lineItems.data[0]?.price?.id;
16467
- if (!priceId) return c.json({ received: true });
16468
- if (priceId in BALANCE_PRICE_IDS) {
16469
- const mc = BALANCE_PRICE_IDS[priceId];
16470
- const label = BALANCE_PACK_LABELS[priceId] ?? "unknown";
16471
- let user = await getUserByStripeCustomerId(customerId);
16472
- if (!user) {
16473
- const email = session.customer_details?.email;
16474
- if (!email) return c.json({ received: true });
16475
- user = await getUserByEmail(email);
16476
- if (!user) return c.json({ received: true });
16477
- await setStripeCustomerId(user.id, customerId);
16460
+ if (event.type === "invoice.paid" || event.type === "invoice.payment_succeeded") {
16461
+ const invoice = event.data.object;
16462
+ const lineTierId = invoice.lines.data.map(linePriceId).find((id) => id && id in SUBSCRIPTION_TIERS);
16463
+ if (lineTierId) {
16464
+ const tier = SUBSCRIPTION_TIERS[lineTierId];
16465
+ const user = await resolveUser(invoice.customer, invoice.customer_email ?? void 0);
16466
+ if (user && invoice.id && !await ledgerExistsForStripePI(invoice.id)) {
16467
+ await creditMc(user.id, tier.credits_mc, LedgerOperation.SUBSCRIPTION, `${tier.label} subscription credits`, invoice.id);
16468
+ await setSubscriptionTier(user.id, tier.tier, tier.concurrency, invoice.subscription ?? user.subscription_id);
16478
16469
  }
16479
- const pi = session.payment_intent;
16480
- if (await ledgerExistsForStripePI(pi)) return c.json({ received: true });
16481
- await creditMc(user.id, mc, LedgerOperation.TOPUP, `${label} balance top-up`, pi);
16482
16470
  }
16483
16471
  }
16484
- if (event.type === "customer.subscription.created") {
16472
+ if (event.type === "customer.subscription.created" || event.type === "customer.subscription.updated") {
16485
16473
  const sub = event.data.object;
16486
16474
  const priceId = sub.items.data[0]?.price?.id;
16487
- if (priceId !== CONCURRENCY_PRICE_ID) return c.json({ received: true });
16488
16475
  const user = await getUserByStripeCustomerId(sub.customer);
16489
16476
  if (!user) return c.json({ received: true });
16490
- await setExtraConcurrencySlots(user.id, user.extra_concurrency_slots + 1);
16491
- await setConcurrencySubId(user.id, sub.id);
16477
+ if (priceId && priceId in SUBSCRIPTION_TIERS) {
16478
+ const tier = SUBSCRIPTION_TIERS[priceId];
16479
+ const live = sub.status === "active" || sub.status === "trialing";
16480
+ await setSubscriptionTier(user.id, live ? tier.tier : null, live ? tier.concurrency : 0, live ? sub.id : null);
16481
+ } else if (priceId === CONCURRENCY_PRICE_ID && event.type === "customer.subscription.created") {
16482
+ await setExtraConcurrencySlots(user.id, user.extra_concurrency_slots + 1);
16483
+ await setConcurrencySubId(user.id, sub.id);
16484
+ }
16492
16485
  }
16493
16486
  if (event.type === "customer.subscription.deleted") {
16494
16487
  const sub = event.data.object;
16495
16488
  const priceId = sub.items.data[0]?.price?.id;
16496
- if (priceId !== CONCURRENCY_PRICE_ID) return c.json({ received: true });
16497
16489
  const user = await getUserByStripeCustomerId(sub.customer);
16498
16490
  if (!user) return c.json({ received: true });
16499
- await setExtraConcurrencySlots(user.id, Math.max(0, user.extra_concurrency_slots - 1));
16500
- await setConcurrencySubId(user.id, null);
16491
+ if (priceId && priceId in SUBSCRIPTION_TIERS) {
16492
+ await setSubscriptionTier(user.id, null, 0, null);
16493
+ } else if (priceId === CONCURRENCY_PRICE_ID) {
16494
+ await setExtraConcurrencySlots(user.id, Math.max(0, user.extra_concurrency_slots - 1));
16495
+ await setConcurrencySubId(user.id, null);
16496
+ }
16501
16497
  }
16502
16498
  return c.json({ received: true });
16503
16499
  });
16500
+ function linePriceId(line) {
16501
+ const l = line;
16502
+ return l?.price?.id ?? l?.pricing?.price_details?.price ?? l?.plan?.id;
16503
+ }
16504
+ async function resolveUser(customerId, emailFallback) {
16505
+ let user = await getUserByStripeCustomerId(customerId);
16506
+ if (user) return user;
16507
+ if (!emailFallback) return void 0;
16508
+ user = await getUserByEmail(emailFallback);
16509
+ if (user) await setStripeCustomerId(user.id, customerId);
16510
+ return user;
16511
+ }
16504
16512
 
16505
16513
  // src/api/site-audit-worker.ts
16506
16514
  var MAX_CONCURRENT_SITE_AUDIT = 1;
@@ -16540,96 +16548,15 @@ import { createMiddleware as createMiddleware3 } from "hono/factory";
16540
16548
  import { getCookie, setCookie, deleteCookie } from "hono/cookie";
16541
16549
  import Stripe2 from "stripe";
16542
16550
 
16543
- // src/api/billing-schemas.ts
16544
- import { z as z19 } from "zod";
16545
- var BillingCheckoutBodySchema = z19.object({
16546
- priceId: z19.string().min(1)
16547
- });
16548
- var FreeCreditBreakdownSchema = z19.object({
16549
- signup_grant_mc: z19.number().int().nonnegative(),
16550
- monthly_refresh_mc: z19.number().int().nonnegative(),
16551
- total_free_mc: z19.number().int().nonnegative(),
16552
- signup_grant_credits: z19.number().nonnegative(),
16553
- monthly_refresh_credits: z19.number().nonnegative(),
16554
- total_free_credits: z19.number().nonnegative()
16555
- });
16556
- var BillingBalanceResponseSchema = z19.object({
16557
- balance_mc: z19.number().int().nonnegative(),
16558
- balance_credits: z19.number().nonnegative(),
16559
- free_credits: FreeCreditBreakdownSchema,
16560
- ledger: z19.array(z19.any())
16561
- });
16562
- var MonthlyRefreshSweepResultSchema = z19.object({
16563
- usersRefreshed: z19.number().int().nonnegative(),
16564
- totalMcGranted: z19.number().int().nonnegative()
16565
- });
16566
-
16567
16551
  // src/api/credit-operations.ts
16568
- function monthKey(value = /* @__PURE__ */ new Date()) {
16569
- return value.toISOString().slice(0, 7);
16570
- }
16571
- function userCreatedBeforeThisMonth(user) {
16572
- return user.created_at.slice(0, 7) < monthKey();
16573
- }
16574
- async function grantSignupCredit(userId) {
16575
- if (await ledgerExistsForOperation(userId, LedgerOperation.SIGNUP_GRANT)) return;
16576
- await creditMc(userId, FREE_SIGNUP_MC, LedgerOperation.SIGNUP_GRANT, "Welcome to MCP Scraper");
16552
+ async function grantSignupCredit(_userId) {
16553
+ return;
16577
16554
  }
16578
16555
  async function applyMonthlyFreeRefresh(user) {
16579
- if (!userCreatedBeforeThisMonth(user)) return user;
16580
- const claimed = await claimMonthlyFreeRefresh(user.id, monthKey());
16581
- if (!claimed) return user;
16582
- const balance = await creditMc(
16583
- user.id,
16584
- FREE_MONTHLY_REFRESH_MC,
16585
- LedgerOperation.MONTHLY_REFRESH,
16586
- "Monthly free credits"
16587
- );
16588
- return { ...user, balance_mc: balance };
16556
+ return user;
16589
16557
  }
16590
16558
  async function runMonthlyRefreshSweep() {
16591
- const db = getDb();
16592
- const monthStart = /* @__PURE__ */ new Date();
16593
- monthStart.setUTCDate(1);
16594
- monthStart.setUTCHours(0, 0, 0, 0);
16595
- const monthStartIso = monthStart.toISOString();
16596
- const currentMonth = monthKey();
16597
- const res = await db.execute({
16598
- sql: `
16599
- SELECT * FROM users
16600
- WHERE created_at < ?
16601
- AND active = 1
16602
- AND id NOT IN (
16603
- SELECT user_id FROM free_credit_refreshes WHERE month = ?
16604
- )
16605
- `,
16606
- args: [monthStartIso, currentMonth]
16607
- });
16608
- const users = res.rows.map((r) => ({
16609
- id: Number(r.id),
16610
- email: String(r.email),
16611
- name: r.name != null ? String(r.name) : null,
16612
- api_key: String(r.api_key ?? ""),
16613
- key_active: Number(r.key_active ?? 1),
16614
- password_hash: r.password_hash != null ? String(r.password_hash) : null,
16615
- created_at: String(r.created_at),
16616
- active: Number(r.active),
16617
- stripe_customer_id: r.stripe_customer_id != null ? String(r.stripe_customer_id) : null,
16618
- balance_mc: Number(r.balance_mc ?? 0),
16619
- extra_concurrency_slots: Number(r.extra_concurrency_slots ?? 0),
16620
- concurrency_stripe_sub_id: r.concurrency_stripe_sub_id != null ? String(r.concurrency_stripe_sub_id) : null
16621
- }));
16622
- let usersRefreshed = 0;
16623
- let totalMcGranted = 0;
16624
- for (const user of users) {
16625
- const before = user.balance_mc;
16626
- const after = await applyMonthlyFreeRefresh(user);
16627
- if (after.balance_mc !== before) {
16628
- usersRefreshed++;
16629
- totalMcGranted += FREE_MONTHLY_REFRESH_MC;
16630
- }
16631
- }
16632
- return { usersRefreshed, totalMcGranted };
16559
+ return { usersRefreshed: 0, totalMcGranted: 0 };
16633
16560
  }
16634
16561
  async function getFreeCreditBreakdown(userId) {
16635
16562
  const res = await getDb().execute({
@@ -16933,8 +16860,10 @@ app.get("/me", async (c) => {
16933
16860
  balance_mc: user.balance_mc,
16934
16861
  balance_credits: user.balance_mc / 1e3,
16935
16862
  extra_concurrency_slots: user.extra_concurrency_slots,
16936
- concurrency_limit: 1 + user.extra_concurrency_slots,
16863
+ concurrency_limit: concurrencyLimitForUser(user),
16937
16864
  has_concurrency_sub: !!user.concurrency_stripe_sub_id,
16865
+ subscription_tier: user.subscription_tier,
16866
+ subscription_concurrency: user.subscription_concurrency,
16938
16867
  ...stats
16939
16868
  });
16940
16869
  });
@@ -17399,13 +17328,12 @@ app.get("/extract-site/status/:id", auth2, async (c) => {
17399
17328
  });
17400
17329
  });
17401
17330
  app.post("/billing/checkout", requireAllowedOrigin, sessionAuth, async (c) => {
17331
+ return c.json({ error: "One-time credit packs are no longer available. Subscribe to a plan instead \u2014 use /billing/subscribe.", error_code: "packs_removed" }, 410);
17332
+ });
17333
+ app.post("/billing/concurrency/checkout", requireAllowedOrigin, sessionAuth, async (c) => {
17402
17334
  try {
17403
17335
  const user = c.get("sessionUser");
17404
- const raw = await c.req.json();
17405
- const parsed = BillingCheckoutBodySchema.safeParse(raw);
17406
- if (!parsed.success) return c.json({ error: "Invalid request" }, 400);
17407
- const { priceId } = parsed.data;
17408
- if (!(priceId in BALANCE_PRICE_IDS)) return c.json({ error: "Invalid price" }, 400);
17336
+ if (user.concurrency_stripe_sub_id) return c.json({ error: "Already subscribed \u2014 cancel existing slot first to change." }, 409);
17409
17337
  const secret2 = process.env.STRIPE_SECRET_KEY?.trim();
17410
17338
  if (!secret2) return c.json({ error: "Stripe is not configured." }, 503);
17411
17339
  const stripeClient = new Stripe2(secret2, { apiVersion: STRIPE_API_VERSION });
@@ -17417,26 +17345,28 @@ app.post("/billing/checkout", requireAllowedOrigin, sessionAuth, async (c) => {
17417
17345
  }
17418
17346
  const session = await stripeClient.checkout.sessions.create({
17419
17347
  customer: customerId,
17420
- mode: "payment",
17421
- line_items: [{ price: priceId, quantity: 1 }],
17348
+ mode: "subscription",
17349
+ line_items: [{ price: CONCURRENCY_PRICE_ID, quantity: 1 }],
17422
17350
  ui_mode: "embedded",
17423
17351
  automatic_tax: { enabled: true },
17424
17352
  billing_address_collection: "required",
17425
17353
  customer_update: { address: "auto", name: "auto" },
17426
17354
  tax_id_collection: { enabled: true },
17427
- return_url: `${appOrigin()}/billing?session_id={CHECKOUT_SESSION_ID}`
17355
+ return_url: `${appOrigin()}/billing?slot_added=1`
17428
17356
  });
17429
17357
  return c.json({ clientSecret: session.client_secret });
17430
17358
  } catch (err) {
17431
17359
  const message = err instanceof Error ? err.message : "Unable to start checkout.";
17432
- console.error("[billing/checkout]", message);
17360
+ console.error("[billing/concurrency/checkout]", message);
17433
17361
  return c.json({ error: message }, 500);
17434
17362
  }
17435
17363
  });
17436
- app.post("/billing/concurrency/checkout", requireAllowedOrigin, sessionAuth, async (c) => {
17364
+ app.post("/billing/subscribe", requireAllowedOrigin, sessionAuth, async (c) => {
17437
17365
  try {
17438
17366
  const user = c.get("sessionUser");
17439
- if (user.concurrency_stripe_sub_id) return c.json({ error: "Already subscribed \u2014 cancel existing slot first to change." }, 409);
17367
+ const raw = await c.req.json().catch(() => ({}));
17368
+ const tier = SUBSCRIPTION_TIER_BY_KEY[String(raw.tier ?? "")];
17369
+ if (!tier) return c.json({ error: "Invalid tier. Choose starter, growth, or scale." }, 400);
17440
17370
  const secret2 = process.env.STRIPE_SECRET_KEY?.trim();
17441
17371
  if (!secret2) return c.json({ error: "Stripe is not configured." }, 503);
17442
17372
  const stripeClient = new Stripe2(secret2, { apiVersion: STRIPE_API_VERSION });
@@ -17446,21 +17376,33 @@ app.post("/billing/concurrency/checkout", requireAllowedOrigin, sessionAuth, asy
17446
17376
  customerId = customer.id;
17447
17377
  await setStripeCustomerId(user.id, customerId);
17448
17378
  }
17379
+ if (user.subscription_id) {
17380
+ const sub = await stripeClient.subscriptions.retrieve(user.subscription_id);
17381
+ const itemId = sub.items.data[0]?.id;
17382
+ if (itemId) {
17383
+ await stripeClient.subscriptions.update(user.subscription_id, {
17384
+ items: [{ id: itemId, price: tier.price_id }],
17385
+ proration_behavior: "create_prorations"
17386
+ });
17387
+ return c.json({ updated: true, tier: tier.tier });
17388
+ }
17389
+ }
17449
17390
  const session = await stripeClient.checkout.sessions.create({
17450
17391
  customer: customerId,
17451
17392
  mode: "subscription",
17452
- line_items: [{ price: CONCURRENCY_PRICE_ID, quantity: 1 }],
17393
+ line_items: [{ price: tier.price_id, quantity: 1 }],
17394
+ ...tier.intro_coupon ? { discounts: [{ coupon: tier.intro_coupon }] } : {},
17453
17395
  ui_mode: "embedded",
17454
17396
  automatic_tax: { enabled: true },
17455
17397
  billing_address_collection: "required",
17456
17398
  customer_update: { address: "auto", name: "auto" },
17457
17399
  tax_id_collection: { enabled: true },
17458
- return_url: `${appOrigin()}/billing?slot_added=1`
17400
+ return_url: `${appOrigin()}/billing?subscribed=${tier.tier}`
17459
17401
  });
17460
17402
  return c.json({ clientSecret: session.client_secret });
17461
17403
  } catch (err) {
17462
- const message = err instanceof Error ? err.message : "Unable to start checkout.";
17463
- console.error("[billing/concurrency/checkout]", message);
17404
+ const message = err instanceof Error ? err.message : "Unable to start subscription.";
17405
+ console.error("[billing/subscribe]", message);
17464
17406
  return c.json({ error: message }, 500);
17465
17407
  }
17466
17408
  });
@@ -17508,7 +17450,7 @@ app.post("/billing/concurrency/terminal-checkout", auth2, async (c) => {
17508
17450
  current_extra_slots: user.extra_concurrency_slots,
17509
17451
  current_limit: concurrencyLimitForUser(user),
17510
17452
  after_checkout_extra_slots: user.extra_concurrency_slots + 1,
17511
- after_checkout_limit: concurrencyLimitForUser({ extra_concurrency_slots: user.extra_concurrency_slots + 1 })
17453
+ after_checkout_limit: concurrencyLimitForUser({ extra_concurrency_slots: user.extra_concurrency_slots + 1, subscription_concurrency: user.subscription_concurrency })
17512
17454
  },
17513
17455
  next_step: "Open checkout_url in a browser, complete checkout, then restart or retry the MCP request."
17514
17456
  });
@@ -17577,7 +17519,7 @@ app.get("/cron/tick", async (c) => {
17577
17519
  if (!process.env.CRON_SECRET || secret2 !== `Bearer ${process.env.CRON_SECRET}`) {
17578
17520
  return c.json({ error: "Unauthorized" }, 401);
17579
17521
  }
17580
- const { drainQueue } = await import("./worker-PR7GODIV.js");
17522
+ const { drainQueue } = await import("./worker-AITQTXHM.js");
17581
17523
  const budget = { maxJobs: 10, deadlineMs: Date.now() + 28e4 };
17582
17524
  const workflowDispatchResult = await dispatchDueWorkflowSchedules(`${new URL(c.req.url).protocol}//${new URL(c.req.url).host}`);
17583
17525
  const [results, sweepResult, reapResult, expiredResult] = await Promise.all([
@@ -17722,4 +17664,4 @@ app.get("/blog/:slug/", (c) => {
17722
17664
  export {
17723
17665
  app
17724
17666
  };
17725
- //# sourceMappingURL=server-NKZW2SEV.js.map
17667
+ //# sourceMappingURL=server-K4UIE2R3.js.map