Some checks failed
CI / Lint, Unit & Integration Tests (push) Has been cancelled
Add real Shopify Billing API integration: Free/Starter/Growth/Pro plans (app/lib/billing-plans.ts, priced per PRODUCT_STRATEGY.md §6) wired into shopify.server.ts's billing config, a merchant-facing plan page (app/routes/app.billing.tsx) using billing.request/billing.cancel, and webhooks.app_subscriptions.update.tsx as the durable sync path for Shop.tier (fires even when a merchant cancels from Shopify's own billing page, not just from this app). Gate the features actually built so far in both loader and action (never just hidden in the UI, so a direct POST can't bypass a tier limit): delivery zones/rates require Growth+, the dispatch dashboard requires Starter+, and location count is capped per tier (Free=1, Starter=3, Growth/Pro=unlimited). Split pure tier logic (app/lib/billing-plans.ts) from DB-backed reads/writes (app/services/billing.server.ts) so the client-rendered UpsellState component can import the Tier type without pulling server code into the client bundle — same split as currency.ts. Covered by tests/unit/billing-plans.test.ts (pure tier ranking/mapping) and tests/integration/billing.test.ts (tier persistence and location-limit enforcement against live Postgres). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
115 lines
4.8 KiB
TOML
115 lines
4.8 KiB
TOML
# Learn more about configuring your app at https://shopify.dev/docs/apps/tools/cli/configuration
|
|
|
|
client_id = "890f611da9f31c1a8e3183b5300b2f53"
|
|
name = "Metatron-delivery"
|
|
application_url = "https://shopify.dev/apps/default-app-home"
|
|
embedded = true
|
|
|
|
[access_scopes]
|
|
# Learn more at https://shopify.dev/docs/apps/tools/cli/configuration#access_scopes
|
|
# read_customers deliberately omitted: no feature currently calls the
|
|
# Customers API (Booking.customerEmail/customerPhone come straight off the
|
|
# orders/create webhook payload, covered by read_orders) — requesting it
|
|
# unused would also gate this app behind Shopify's Protected Customer Data
|
|
# Access approval for no reason. Add it back only when a feature (e.g. the
|
|
# "recognize returning customers" parity item) actually needs it, and
|
|
# expect to need that approval granted at that point.
|
|
scopes = "read_locales,read_locations,read_markets,read_metaobjects,read_orders,read_products,write_cart_transforms,write_delivery_customizations,write_metaobjects,write_orders,write_payment_customizations"
|
|
|
|
[auth]
|
|
redirect_urls = [ "https://shopify.dev/apps/default-app-home/api/auth" ]
|
|
|
|
[webhooks]
|
|
api_version = "2025-01"
|
|
|
|
# Handled by: app/routes/webhooks.app.uninstalled.tsx
|
|
[[webhooks.subscriptions]]
|
|
uri = "/webhooks/app/uninstalled"
|
|
topics = ["app/uninstalled"]
|
|
|
|
# Handled by: app/routes/webhooks.app.scopes_update.tsx
|
|
[[webhooks.subscriptions]]
|
|
uri = "/webhooks/app/scopes_update"
|
|
topics = ["app/scopes_update"]
|
|
|
|
# Handled by: app/routes/webhooks.orders.create.tsx
|
|
[[webhooks.subscriptions]]
|
|
uri = "/webhooks/orders/create"
|
|
topics = ["orders/create"]
|
|
|
|
# Handled by: app/routes/webhooks.orders.updated.tsx
|
|
[[webhooks.subscriptions]]
|
|
uri = "/webhooks/orders/updated"
|
|
topics = ["orders/updated"]
|
|
|
|
# Handled by: app/routes/webhooks.orders.cancelled.tsx
|
|
[[webhooks.subscriptions]]
|
|
uri = "/webhooks/orders/cancelled"
|
|
topics = ["orders/cancelled"]
|
|
|
|
# Handled by: app/routes/webhooks.app_subscriptions.update.tsx — keeps
|
|
# Shop.tier in sync with the merchant's actual billing state, including
|
|
# cancellations made from Shopify's own billing page (not just via
|
|
# /app/billing in this app).
|
|
[[webhooks.subscriptions]]
|
|
uri = "/webhooks/app_subscriptions/update"
|
|
topics = ["app_subscriptions/update"]
|
|
|
|
# Mandatory GDPR compliance topics — required for Built-for-Shopify /
|
|
# public app review. TEMPORARILY DISABLED: `shopify app dev`/`deploy`
|
|
# refuses to push these until the org has requested and been granted
|
|
# "Protected customer data access" in the Partner Dashboard (Apps ->
|
|
# this app -> API access -> Protected customer data) — that's a manual
|
|
# questionnaire/approval step, not something the CLI or config can
|
|
# bypass. RE-ENABLE these three blocks (handlers already exist and are
|
|
# wired: app/routes/webhooks.customers.data_request.tsx,
|
|
# webhooks.customers.redact.tsx, webhooks.shop.redact.tsx) once that
|
|
# access is granted, and before any public launch/BfS submission.
|
|
|
|
# [[webhooks.subscriptions]]
|
|
# uri = "/webhooks/customers/data_request"
|
|
# compliance_topics = ["customers/data_request"]
|
|
|
|
# [[webhooks.subscriptions]]
|
|
# uri = "/webhooks/customers/redact"
|
|
# compliance_topics = ["customers/redact"]
|
|
|
|
# [[webhooks.subscriptions]]
|
|
# uri = "/webhooks/shop/redact"
|
|
# compliance_topics = ["shop/redact"]
|
|
|
|
# This org appears enrolled in Shopify's "Next Generation Events" developer
|
|
# preview (https://shopify.dev/changelog/next-generation-events-now-available-in-developer-preview),
|
|
# a separate, optional delivery mechanism from classic [webhooks] above
|
|
# (GraphQL-style resource topics + create/update/delete actions, api_version
|
|
# pinned to "unstable" while in preview). The CLI now treats [events] as a
|
|
# REQUIRED section for this app/org even though our app doesn't use it —
|
|
# everything real is handled via [webhooks]. This subscription is a
|
|
# functionally-inert placeholder that exists solely to satisfy that schema
|
|
# gate (app/routes/webhooks.events.placeholder.tsx just logs and returns
|
|
# 200) — it is not part of this app's actual feature set.
|
|
[events]
|
|
api_version = "unstable"
|
|
|
|
[[events.subscription]]
|
|
handle = "unused-events-preview-placeholder"
|
|
topic = "Product"
|
|
actions = ["create"]
|
|
uri = "/webhooks/events/placeholder"
|
|
|
|
# App proxy so the storefront Theme App Extension can call our backend
|
|
# without CORS issues (see IMPLEMENTATION_PLAN.md §5.3). `shopify app dev`
|
|
# points this at your dev tunnel automatically when
|
|
# automatically_update_urls_on_dev is true (see [build] below); if it
|
|
# doesn't, set it manually to `<your-tunnel-url>/apps/scheduling` — the
|
|
# Remix routes it forwards to (apps.scheduling.*.tsx) assume that exact
|
|
# prefix.
|
|
[app_proxy]
|
|
url = "https://replace-with-your-tunnel-url.example.com/apps/scheduling"
|
|
subpath = "scheduling"
|
|
prefix = "apps"
|
|
|
|
[build]
|
|
include_config_on_deploy = true
|
|
automatically_update_urls_on_dev = true
|