@carrierllc/mcp 0.13.41 → 0.13.47

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 (68) hide show
  1. package/dist/{chunk-6OAZJBLA.js → chunk-4XUAUQ3U.js} +67 -7
  2. package/dist/chunk-4XUAUQ3U.js.map +1 -0
  3. package/dist/cli.js +55 -9
  4. package/dist/cli.js.map +1 -1
  5. package/dist/index.js +66 -15
  6. package/dist/index.js.map +1 -1
  7. package/package.json +1 -1
  8. package/templates/storefront/CLERK.md +23 -0
  9. package/templates/storefront/src/app/activate/[orderId]/ActivateClient.tsx +29 -22
  10. package/templates/storefront/src/app/activate/[orderId]/page.tsx +2 -2
  11. package/templates/storefront/src/app/api/checkout/claim/route.ts +7 -6
  12. package/templates/storefront/src/app/api/checkout/guest/route.ts +72 -17
  13. package/templates/storefront/src/app/api/orders/[orderId]/route.ts +2 -2
  14. package/templates/storefront/src/app/checkout/[templateId]/CheckoutClient.tsx +51 -25
  15. package/templates/storefront/src/app/checkout/success/CheckoutSuccessClient.tsx +165 -131
  16. package/templates/storefront/src/app/checkout/success/FocusHeading.tsx +20 -0
  17. package/templates/storefront/src/app/checkout/success/page.tsx +136 -15
  18. package/templates/storefront/src/app/dashboard/EsimControls.tsx +20 -24
  19. package/templates/storefront/src/app/dashboard/page.tsx +43 -23
  20. package/templates/storefront/src/app/globals.css +44 -5
  21. package/templates/storefront/src/app/help/page.tsx +2 -2
  22. package/templates/storefront/src/app/layout.tsx +5 -3
  23. package/templates/storefront/src/app/page.tsx +27 -7
  24. package/templates/storefront/src/app/shop/ShopClient.tsx +106 -72
  25. package/templates/storefront/src/app/shop/page.tsx +7 -2
  26. package/templates/storefront/src/app/sign-in/[[...sign-in]]/StorefrontSignInClient.tsx +297 -0
  27. package/templates/storefront/src/app/sign-in/[[...sign-in]]/page.tsx +13 -14
  28. package/templates/storefront/src/app/sign-up/[[...sign-up]]/StorefrontSignUpClient.tsx +31 -28
  29. package/templates/storefront/src/app/sign-up/[[...sign-up]]/page.tsx +5 -2
  30. package/templates/storefront/src/brand.config.ts +16 -0
  31. package/templates/storefront/src/components/Providers.tsx +20 -1
  32. package/templates/storefront/src/components/faq/FaqSection.tsx +2 -2
  33. package/templates/storefront/src/components/footer/StorefrontFooter.tsx +7 -7
  34. package/templates/storefront/src/components/landing/FinalCTA.tsx +4 -9
  35. package/templates/storefront/src/components/landing/HeroSection.tsx +4 -7
  36. package/templates/storefront/src/components/landing/HowItWorks.tsx +1 -1
  37. package/templates/storefront/src/components/landing/PlanCard.tsx +23 -13
  38. package/templates/storefront/src/components/landing/TierPlanBoard.tsx +237 -0
  39. package/templates/storefront/src/components/nav/StorefrontNav.tsx +8 -11
  40. package/templates/storefront/src/components/shop/CountrySearch.tsx +94 -0
  41. package/templates/storefront/src/components/theme/BrandStyles.tsx +2 -2
  42. package/templates/storefront/src/components/theme/ThemeToggle.tsx +1 -1
  43. package/templates/storefront/src/components/theme/brand-accent-css.ts +21 -0
  44. package/templates/storefront/src/components/theme/brand-style.ts +88 -0
  45. package/templates/storefront/src/components/theme/clerk-appearance.ts +18 -2
  46. package/templates/storefront/src/lib/buyer-auth-copy.ts +83 -0
  47. package/templates/storefront/src/lib/buyer-error.ts +32 -0
  48. package/templates/storefront/src/lib/buyer-session.ts +41 -0
  49. package/templates/storefront/src/lib/catalog-countries.ts +179 -0
  50. package/templates/storefront/src/lib/checkout-client-error.ts +28 -0
  51. package/templates/storefront/src/lib/checkout-copy.ts +89 -0
  52. package/templates/storefront/src/lib/checkout-order-claim.ts +8 -7
  53. package/templates/storefront/src/lib/checkout-return.ts +18 -0
  54. package/templates/storefront/src/lib/clerk-instance.ts +89 -0
  55. package/templates/storefront/src/lib/order-reference.ts +15 -0
  56. package/templates/storefront/src/lib/request-origin.ts +28 -0
  57. package/templates/storefront/src/lib/sanitize-auth-redirect.ts +20 -4
  58. package/templates/storefront/src/lib/tap-target.ts +17 -0
  59. package/templates/storefront/src/lib/verify-checkout-session.ts +118 -19
  60. package/templates/storefront/src/middleware.ts +11 -0
  61. package/templates/storefront/src/vendor/carrier/catalog-guard.ts +9 -5
  62. package/templates/storefront/src/vendor/carrier/client.ts +22 -4
  63. package/templates/storefront/src/vendor/carrier/country-offers.ts +106 -0
  64. package/templates/storefront/src/vendor/carrier/stripe-price.ts +134 -0
  65. package/templates/storefront/src/vendor/carrier/tiers.ts +161 -0
  66. package/templates/storefront/src/vendor/carrier/types.ts +22 -0
  67. package/templates/storefront/src/vendor/geo/index.ts +15 -4
  68. package/dist/chunk-6OAZJBLA.js.map +0 -1
package/dist/cli.js CHANGED
@@ -44,7 +44,7 @@ import {
44
44
  verifyStorefront,
45
45
  walletScreen,
46
46
  which
47
- } from "./chunk-6OAZJBLA.js";
47
+ } from "./chunk-4XUAUQ3U.js";
48
48
  import {
49
49
  copyTree,
50
50
  exists,
@@ -194,7 +194,17 @@ function installAuthGuidance() {
194
194
  import { join as join3 } from "path";
195
195
  function preserveClerkFromEnv(existing, fresh) {
196
196
  let out = fresh;
197
- for (const key of ["NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY", "CLERK_SECRET_KEY"]) {
197
+ for (const key of [
198
+ "NEXT_PUBLIC_CLERK_INSTANCE",
199
+ "NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY",
200
+ "CLERK_SECRET_KEY",
201
+ "NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY_PRODUCTION",
202
+ "CLERK_SECRET_KEY_PRODUCTION",
203
+ "NEXT_PUBLIC_PASSWORD_RESET_ENABLED",
204
+ "NEXT_PUBLIC_CLERK_SIGN_IN_URL",
205
+ "NEXT_PUBLIC_CLERK_SIGN_UP_URL",
206
+ "NEXT_PUBLIC_COUNTRY_CATALOG"
207
+ ]) {
198
208
  const line = existing.split("\n").find((l) => l.startsWith(`${key}=`));
199
209
  if (!line) continue;
200
210
  const value = line.slice(key.length + 1);
@@ -2121,6 +2131,8 @@ function regionLabel(code) {
2121
2131
  }
2122
2132
 
2123
2133
  // ../../packages/sdk/src/storefront-write.ts
2134
+ var STRIPE_PRICE_ID_RE = /^price_[A-Za-z0-9_]+$/;
2135
+ var STRIPE_PRICE_ID_MAX_LENGTH = 255;
2124
2136
  var THEME_FIELDS = [
2125
2137
  ["accent", "accent"],
2126
2138
  ["accentDark", "accentDark"],
@@ -2157,7 +2169,9 @@ function completePlanInput(input, plans) {
2157
2169
  input.regions,
2158
2170
  input.description,
2159
2171
  input.active,
2160
- input.sortOrder
2172
+ input.sortOrder,
2173
+ input.stripePriceId,
2174
+ input.stripePriceMode
2161
2175
  ].some((value) => value !== void 0);
2162
2176
  if (!touched) return input;
2163
2177
  const slug2 = input.slug?.trim();
@@ -2184,6 +2198,8 @@ function storefrontPlanBody(input) {
2184
2198
  if (input.accountId !== void 0 && (!Number.isSafeInteger(input.accountId) || input.accountId <= 0)) {
2185
2199
  return { error: "OCS account id must be a positive integer." };
2186
2200
  }
2201
+ const stripe = stripePriceFields(input.stripePriceId, input.stripePriceMode);
2202
+ if (stripe && "error" in stripe) return stripe;
2187
2203
  const productId = input.productId?.trim() ?? "";
2188
2204
  if (productId !== "") {
2189
2205
  const body2 = { product_id: productId };
@@ -2191,7 +2207,7 @@ function storefrontPlanBody(input) {
2191
2207
  if (input.priceCents !== void 0) body2.price_cents = input.priceCents;
2192
2208
  if (input.active !== void 0) body2.active = input.active;
2193
2209
  if (input.sortOrder !== void 0) body2.sort_order = input.sortOrder;
2194
- return body2;
2210
+ return stripe ? { ...body2, ...stripe } : body2;
2195
2211
  }
2196
2212
  const touched = [
2197
2213
  input.slug,
@@ -2206,7 +2222,9 @@ function storefrontPlanBody(input) {
2206
2222
  input.regions,
2207
2223
  input.description,
2208
2224
  input.active,
2209
- input.sortOrder
2225
+ input.sortOrder,
2226
+ input.stripePriceId,
2227
+ input.stripePriceMode
2210
2228
  ].some((value) => value !== void 0);
2211
2229
  if (!touched) return null;
2212
2230
  if (!input.slug || !input.name || input.priceCents === void 0 || !input.currency || input.templateId === void 0) {
@@ -2230,7 +2248,27 @@ function storefrontPlanBody(input) {
2230
2248
  if (input.description !== void 0) body.description = input.description;
2231
2249
  if (input.active !== void 0) body.active = input.active;
2232
2250
  if (input.sortOrder !== void 0) body.sort_order = input.sortOrder;
2233
- return body;
2251
+ return stripe ? { ...body, ...stripe } : body;
2252
+ }
2253
+ function stripePriceFields(id, mode) {
2254
+ if (id === void 0 && mode === void 0) return void 0;
2255
+ if (typeof id === "string") {
2256
+ const trimmed = id.trim();
2257
+ if (trimmed.length < 1 || trimmed.length > STRIPE_PRICE_ID_MAX_LENGTH || !STRIPE_PRICE_ID_RE.test(trimmed)) {
2258
+ return { error: "stripe_price_id must look like price_\u2026 and be 1-255 characters." };
2259
+ }
2260
+ id = trimmed;
2261
+ }
2262
+ if (id === null || mode === null) {
2263
+ if (id !== void 0 && id !== null || mode !== void 0 && mode !== null) {
2264
+ return { error: "Sending null clears both stripe_price_id and stripe_price_mode." };
2265
+ }
2266
+ return { stripe_price_id: null, stripe_price_mode: null };
2267
+ }
2268
+ if (id === void 0 || mode === void 0) {
2269
+ return { error: "stripe_price_id and stripe_price_mode must be set together." };
2270
+ }
2271
+ return { stripe_price_id: id, stripe_price_mode: mode };
2234
2272
  }
2235
2273
  function isStorefrontPlanError(value) {
2236
2274
  return value !== null && "error" in value;
@@ -2327,6 +2365,10 @@ function hostedPublishInputFromFlags(flags) {
2327
2365
  if (!logo.ok) return { ok: false, text: logo.text };
2328
2366
  const sortOrder = parseWholeNumber(flags.planSortOrder, "Plan sort order");
2329
2367
  if (!sortOrder.ok) return { ok: false, text: sortOrder.message };
2368
+ const stripeMode = flags.stripePriceMode;
2369
+ if (stripeMode !== void 0 && stripeMode !== "test" && stripeMode !== "live") {
2370
+ return { ok: false, text: "stripe_price_mode must be test or live." };
2371
+ }
2330
2372
  return {
2331
2373
  ok: true,
2332
2374
  input: {
@@ -2355,7 +2397,9 @@ function hostedPublishInputFromFlags(flags) {
2355
2397
  regions: countries.value,
2356
2398
  description: flags.planText,
2357
2399
  planActive: flags.inactive ? false : void 0,
2358
- planSortOrder: sortOrder.value
2400
+ planSortOrder: sortOrder.value,
2401
+ stripePriceId: flags.stripePriceId,
2402
+ stripePriceMode: stripeMode
2359
2403
  }
2360
2404
  };
2361
2405
  }
@@ -2416,7 +2460,9 @@ function planInput(input) {
2416
2460
  regions: input.regions,
2417
2461
  description: input.description,
2418
2462
  active: input.planActive,
2419
- sortOrder: input.planSortOrder
2463
+ sortOrder: input.planSortOrder,
2464
+ stripePriceId: input.stripePriceId,
2465
+ stripePriceMode: input.stripePriceMode
2420
2466
  };
2421
2467
  }
2422
2468
  function findStore(body, slug2) {
@@ -7235,7 +7281,7 @@ site.command("deploy [dir]").description("Build + deploy a storefront to whichev
7235
7281
  p3.outro("");
7236
7282
  }
7237
7283
  );
7238
- site.command("publish").description("Publish a Carrier-hosted storefront. Does not deploy a self-hosted copy.").requiredOption("--slug <slug>", "Shop address, such as acme or Acme Mobile").requiredOption("--name <name>", "Brand name").option("--status <status>", "draft or published", "published").option("--accent <hex>", "Accent color, such as #112233").option("--accent-dark <hex>", "Darker accent").option("--bg <hex>", "Page background").option("--text <hex>", "Body text color").option("--logo <url-or-file>", "https logo address, or a PNG, JPEG, WebP, or GIF under 70 KB").option("--hero <text>", "Shop headline").option("--tagline <text>", "Line under the headline").option("--support-email <email>", "Support address").option("--legal-name <name>", "Legal name in the footer").option("--product <id>", "Connectivity plan id. Copies its template, price, and allowance.").option("--plan <slug>", "Plan slug, such as eu-1gb").option("--plan-name <name>", "Plan name on the shop").option("--price <amount>", "Retail price, such as 9.00").option("--price-cents <cents>", "Retail price in minor units").option("--currency <code>", "Three-letter currency code").option("--template-id <id>", "OCS package template id").option("--ocs-account-id <id>", "Owned OCS account override; omit for automatic resolution").option("--data-gb <gb>", "Data allowance, such as 1 or 1 GB, or the text Unlimited").option("--unlimited", "The only way to sell an unlimited plan. A 0 or missing --data-gb without this is refused.").option("--validity-days <days>", "Validity, such as 7 or 7 days").option("--countries <names>", "Country names or codes, such as France, DE").option("--plan-text <text>", "Buyer-facing sentence. Omit to leave the saved text unchanged.").option("--inactive", "Keep the plan off the shop").option("--plan-sort-order <n>", "Plan display order on the shop (ascending, default 0)").action(async (o) => {
7284
+ site.command("publish").description("Publish a Carrier-hosted storefront. Does not deploy a self-hosted copy.").requiredOption("--slug <slug>", "Shop address, such as acme or Acme Mobile").requiredOption("--name <name>", "Brand name").option("--status <status>", "draft or published", "published").option("--accent <hex>", "Accent color, such as #112233").option("--accent-dark <hex>", "Darker accent").option("--bg <hex>", "Page background").option("--text <hex>", "Body text color").option("--logo <url-or-file>", "https logo address, or a PNG, JPEG, WebP, or GIF under 70 KB").option("--hero <text>", "Shop headline").option("--tagline <text>", "Line under the headline").option("--support-email <email>", "Support address").option("--legal-name <name>", "Legal name in the footer").option("--product <id>", "Connectivity plan id. Copies its template, price, and allowance.").option("--plan <slug>", "Plan slug, such as eu-1gb").option("--plan-name <name>", "Plan name on the shop").option("--price <amount>", "Retail price, such as 9.00").option("--price-cents <cents>", "Retail price in minor units").option("--currency <code>", "Three-letter currency code").option("--template-id <id>", "OCS package template id").option("--ocs-account-id <id>", "Owned OCS account override; omit for automatic resolution").option("--data-gb <gb>", "Data allowance, such as 1 or 1 GB, or the text Unlimited").option("--unlimited", "The only way to sell an unlimited plan. A 0 or missing --data-gb without this is refused.").option("--validity-days <days>", "Validity, such as 7 or 7 days").option("--countries <names>", "Country names or codes, such as France, DE").option("--plan-text <text>", "Buyer-facing sentence. Omit to leave the saved text unchanged.").option("--inactive", "Keep the plan off the shop").option("--plan-sort-order <n>", "Plan display order on the shop (ascending, default 0)").option("--stripe-price-id <id>", "Existing Stripe Price id (price_\u2026, 1-255 characters), stored, not yet charged. Set with --stripe-price-mode.").option("--stripe-price-mode <mode>", "test or live. Set with --stripe-price-id.").action(async (o) => {
7239
7285
  header();
7240
7286
  const built = hostedPublishInputFromFlags(o);
7241
7287
  if (!built.ok) {