Some checks failed
CI / Lint, Unit & Integration Tests (push) Has been cancelled
Also fixes the [events] gate that was blocking ALL extension generation
(discovered while starting this phase).
- shopify.app.toml: this org appears enrolled in Shopify's "Next
Generation Events" developer preview, which the CLI now treats as a
REQUIRED top-level [events] section even though nothing in this app
actually uses it (real webhook handling is entirely classic [webhooks],
unaffected). Iteratively discovered the required shape from the CLI's
own field-by-field validation errors, then found the real docs (Events
is optional/developer-preview, api_version pinned to "unstable") to
confirm rather than keep guessing. Added a functionally-inert
[[events.subscription]] placeholder + a stub handler
(webhooks.events.placeholder.tsx) solely to satisfy the gate.
- app/services/availability-request.server.ts +
app/services/hold-request.server.ts: extracted the resolution logic that
used to live directly in apps.scheduling.availability.tsx/hold.tsx into
shared functions. This is what actually makes "same capacity pool feeds
every surface" (CLAUDE.md) true by construction rather than by
convention — the storefront, POS, and checkout routes now call the exact
same code, not three copies that could quietly drift apart.
- extensions/pos-datetime (generated via `shopify app generate extension
--template=pos_smart_grid` — pos_action's flavor requirement contradicted
the CLI's own global --flavor validator, so smart_grid was used instead):
a home-screen tile opening a modal where staff pick method -> date -> time
against the same availability/hold endpoints (pos.scheduling.*.tsx,
session-token authenticated), writing the same dd_* cart properties via
CartApi.addCartProperties — booking.server.ts needed zero changes to
handle POS-originated orders. Several API-shape guesses (toast isError
option, ChoiceList's `value`/`label` props, a nonexistent
action.dismissModal(), shopify.cart.cart.current) were wrong and caught
by typechecking directly against @shopify/ui-extensions' own bundled
.d.ts files (`npm run typecheck:pos`, now also in CI) — none of this was
verified against a live POS session, which isn't possible in this
environment.
- extensions/checkout-datetime (generated via `--template=checkout_ui`):
the Plus-only native picker in checkout itself
(purchase.checkout.block.render) plus a Thank You confirmation block
(purchase.thank-you.block.render). Went looking for an order-status
target too ("all plans show confirmed slot on thank-you/order-status" is
the Phase 7 accept criterion) and confirmed via the installed package's
own type definitions that purchase.order-status.block.render does not
exist in this API version — checkout UI extensions' thank-you/order-status
surfaces are Plus-only regardless. The actual "all plans" mechanism is
extensions/datetime-widget/blocks/order-confirmation.liquid — a new Theme
App Extension block reading order.note_attributes, which works on every
plan since it's plain Liquid, not checkout extensibility.
Both new UI extensions share one real unverified assumption, called out in
code comments: process.env.APP_URL is expected to be substituted at build
time by the Shopify CLI to the app's backend origin, since these run in a
different origin than the app and need an absolute URL, unlike the
storefront widget's relative /apps/scheduling/* path. Needs confirming
against a live dev session.
Verified: lint, typecheck (root + both new extensions'
`npm run typecheck:pos`/`typecheck:checkout`, all now in CI), 102 unit +
18 integration tests (unchanged — this phase didn't touch pure business
logic, only added thin auth wrappers around already-tested services), both
admin/widget builds.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
101 lines
3.4 KiB
JSON
101 lines
3.4 KiB
JSON
{
|
|
"name": "delivery-datetime-app",
|
|
"private": true,
|
|
"scripts": {
|
|
"build": "remix vite:build",
|
|
"predev": "npm run build:widget",
|
|
"dev": "shopify app dev",
|
|
"predeploy": "npm run build:widget",
|
|
"config:link": "shopify app config link",
|
|
"generate": "shopify app generate",
|
|
"deploy": "shopify app deploy",
|
|
"config:use": "shopify app config use",
|
|
"env": "shopify app env",
|
|
"start": "remix-serve ./build/server/index.js",
|
|
"docker-start": "npm run setup && npm run start",
|
|
"setup": "prisma generate && prisma migrate deploy",
|
|
"lint": "eslint --cache --cache-location ./node_modules/.cache/eslint .",
|
|
"typegen:functions": "npm --prefix extensions/validation-slot run typegen && npm --prefix extensions/delivery-customization run typegen",
|
|
"pretypecheck": "npm run typegen:functions",
|
|
"typecheck": "tsc --noEmit",
|
|
"typecheck:pos": "npm --prefix extensions/pos-datetime run typecheck",
|
|
"typecheck:checkout": "npm --prefix extensions/checkout-datetime run typecheck",
|
|
"test:functions": "npm --prefix extensions/validation-slot test && npm --prefix extensions/delivery-customization test",
|
|
"test": "vitest",
|
|
"test:integration": "vitest run --config vitest.integration.config.ts",
|
|
"test:e2e": "playwright test",
|
|
"build:widget": "esbuild widget-src/datetime-widget/datetime-widget.ts --bundle --minify --target=es2019 --outfile=extensions/datetime-widget/assets/datetime-widget.js",
|
|
"worker": "tsx jobs/worker.ts",
|
|
"shopify": "shopify",
|
|
"prisma": "prisma",
|
|
"graphql-codegen": "graphql-codegen",
|
|
"vite": "vite"
|
|
},
|
|
"type": "module",
|
|
"engines": {
|
|
"node": ">=20.19 <22 || >=22.12"
|
|
},
|
|
"dependencies": {
|
|
"@prisma/client": "^6.2.1",
|
|
"@remix-run/dev": "^2.16.1",
|
|
"@remix-run/fs-routes": "^2.16.1",
|
|
"@remix-run/node": "^2.16.1",
|
|
"@remix-run/react": "^2.16.1",
|
|
"@remix-run/serve": "^2.16.1",
|
|
"@shopify/app-bridge-react": "^4.1.6",
|
|
"@shopify/polaris": "^12.0.0",
|
|
"@shopify/shopify-app-remix": "^4.1.0",
|
|
"@shopify/shopify-app-session-storage-prisma": "^9.0.1",
|
|
"bullmq": "^5.34.0",
|
|
"ioredis": "^5.4.2",
|
|
"isbot": "^5.1.0",
|
|
"luxon": "^3.5.0",
|
|
"prisma": "^6.2.1",
|
|
"react": "^18.2.0",
|
|
"react-dom": "^18.2.0",
|
|
"vite-tsconfig-paths": "^5.0.1"
|
|
},
|
|
"devDependencies": {
|
|
"@playwright/test": "^1.49.1",
|
|
"@remix-run/eslint-config": "^2.16.1",
|
|
"@remix-run/route-config": "^2.16.1",
|
|
"@shopify/api-codegen-preset": "^1.1.1",
|
|
"@types/eslint": "^9.6.1",
|
|
"@types/luxon": "^3.4.2",
|
|
"@types/node": "^22.2.0",
|
|
"@types/react": "^18.2.31",
|
|
"@types/react-dom": "^18.2.14",
|
|
"dotenv": "^16.4.7",
|
|
"esbuild": "^0.24.2",
|
|
"eslint": "^8.42.0",
|
|
"eslint-config-prettier": "^10.0.1",
|
|
"prettier": "^3.2.4",
|
|
"tsx": "^4.19.2",
|
|
"typescript": "^5.2.2",
|
|
"vite": "^6.2.2",
|
|
"vitest": "^2.1.8"
|
|
},
|
|
"workspaces": {
|
|
"packages": [
|
|
"extensions/*"
|
|
]
|
|
},
|
|
"trustedDependencies": [
|
|
"@shopify/plugin-cloudflare"
|
|
],
|
|
"resolutions": {
|
|
"@graphql-tools/url-loader": "8.0.16",
|
|
"@graphql-codegen/client-preset": "4.7.0",
|
|
"@graphql-codegen/typescript-operations": "4.5.0",
|
|
"minimatch": "9.0.5",
|
|
"vite": "^6.2.2"
|
|
},
|
|
"overrides": {
|
|
"@graphql-tools/url-loader": "8.0.16",
|
|
"@graphql-codegen/client-preset": "4.7.0",
|
|
"@graphql-codegen/typescript-operations": "4.5.0",
|
|
"minimatch": "9.0.5",
|
|
"vite": "^6.2.2"
|
|
}
|
|
}
|