From 8a40bcbee61bc36e69d2a5415d21e124d9675f4d Mon Sep 17 00:00:00 2001 From: Gerhard Scheikl Date: Fri, 15 May 2026 15:12:59 +0200 Subject: [PATCH] fix(invoice): use shippingLine.deliveryCategory as primary pickup signal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Order 1032 on dev still rendered as 'Versandart: Lager Graz' because the shipping line's title/code/source contained no 'pickup' keyword — only `shippingLine.deliveryCategory == "pickup"` flagged it as a pickup. `shippingLine.deliveryCategory` only requires `read_orders` (already granted), so query and use it as the primary signal. Keep the regex on title/code/source/carrier as a fallback for custom rates without a proper pickup category. --- .react-router/types/+future.ts | 9 + .react-router/types/+routes.ts | 170 ++++++++++++++++++ .react-router/types/+server-build.d.ts | 18 ++ .react-router/types/app/+types/root.ts | 68 +++++++ .../+types/api.flow.generate-invoice.ts | 71 ++++++++ .../+types/api.flow.send-invoice-email.ts | 71 ++++++++ .../+types/api.orders.$orderId.invoice.ts | 71 ++++++++ .../+types/api.public.girocode[.png].ts | 71 ++++++++ .../routes/+types/api.public.payment-info.ts | 71 ++++++++ .../types/app/routes/+types/app._index.ts | 74 ++++++++ .../types/app/routes/+types/app.invoices.ts | 74 ++++++++ .../types/app/routes/+types/app.settings.ts | 74 ++++++++ .react-router/types/app/routes/+types/app.ts | 71 ++++++++ .../types/app/routes/+types/auth.$.ts | 71 ++++++++ .../types/app/routes/+types/healthz.ts | 71 ++++++++ .../+types/webhooks.app.scopes_update.ts | 71 ++++++++ .../routes/+types/webhooks.app.uninstalled.ts | 71 ++++++++ .../routes/+types/webhooks.orders.create.ts | 71 ++++++++ .../+types/webhooks.orders.fulfilled.ts | 71 ++++++++ .../routes/+types/webhooks.orders.updated.ts | 71 ++++++++ .../types/app/routes/_index/+types/route.ts | 71 ++++++++ .../app/routes/auth.login/+types/route.ts | 71 ++++++++ app/services/invoice/composeInvoice.ts | 45 +++-- .../invoice/loadOrderForInvoice.server.ts | 5 + scripts/render-sample.ts | 33 ++++ 25 files changed, 1619 insertions(+), 16 deletions(-) create mode 100644 .react-router/types/+future.ts create mode 100644 .react-router/types/+routes.ts create mode 100644 .react-router/types/+server-build.d.ts create mode 100644 .react-router/types/app/+types/root.ts create mode 100644 .react-router/types/app/routes/+types/api.flow.generate-invoice.ts create mode 100644 .react-router/types/app/routes/+types/api.flow.send-invoice-email.ts create mode 100644 .react-router/types/app/routes/+types/api.orders.$orderId.invoice.ts create mode 100644 .react-router/types/app/routes/+types/api.public.girocode[.png].ts create mode 100644 .react-router/types/app/routes/+types/api.public.payment-info.ts create mode 100644 .react-router/types/app/routes/+types/app._index.ts create mode 100644 .react-router/types/app/routes/+types/app.invoices.ts create mode 100644 .react-router/types/app/routes/+types/app.settings.ts create mode 100644 .react-router/types/app/routes/+types/app.ts create mode 100644 .react-router/types/app/routes/+types/auth.$.ts create mode 100644 .react-router/types/app/routes/+types/healthz.ts create mode 100644 .react-router/types/app/routes/+types/webhooks.app.scopes_update.ts create mode 100644 .react-router/types/app/routes/+types/webhooks.app.uninstalled.ts create mode 100644 .react-router/types/app/routes/+types/webhooks.orders.create.ts create mode 100644 .react-router/types/app/routes/+types/webhooks.orders.fulfilled.ts create mode 100644 .react-router/types/app/routes/+types/webhooks.orders.updated.ts create mode 100644 .react-router/types/app/routes/_index/+types/route.ts create mode 100644 .react-router/types/app/routes/auth.login/+types/route.ts diff --git a/.react-router/types/+future.ts b/.react-router/types/+future.ts new file mode 100644 index 0000000..7f4533c --- /dev/null +++ b/.react-router/types/+future.ts @@ -0,0 +1,9 @@ +// Generated by React Router + +import "react-router"; + +declare module "react-router" { + interface Future { + v8_middleware: false + } +} \ No newline at end of file diff --git a/.react-router/types/+routes.ts b/.react-router/types/+routes.ts new file mode 100644 index 0000000..2d9c17c --- /dev/null +++ b/.react-router/types/+routes.ts @@ -0,0 +1,170 @@ +// Generated by React Router + +import "react-router" + +declare module "react-router" { + interface Register { + pages: Pages + routeFiles: RouteFiles + routeModules: RouteModules + } +} + +type Pages = { + "/": { + params: {}; + }; + "/api/flow/send-invoice-email": { + params: {}; + }; + "/api/orders/:orderId/invoice": { + params: { + "orderId": string; + }; + }; + "/webhooks/app/scopes_update": { + params: {}; + }; + "/api/flow/generate-invoice": { + params: {}; + }; + "/api/public/girocode.png": { + params: {}; + }; + "/webhooks/orders/fulfilled": { + params: {}; + }; + "/webhooks/app/uninstalled": { + params: {}; + }; + "/api/public/payment-info": { + params: {}; + }; + "/webhooks/orders/updated": { + params: {}; + }; + "/webhooks/orders/create": { + params: {}; + }; + "/auth/login": { + params: {}; + }; + "/healthz": { + params: {}; + }; + "/auth/*": { + params: { + "*": string; + }; + }; + "/app": { + params: {}; + }; + "/app/invoices": { + params: {}; + }; + "/app/settings": { + params: {}; + }; +}; + +type RouteFiles = { + "root.tsx": { + id: "root"; + page: "/" | "/api/flow/send-invoice-email" | "/api/orders/:orderId/invoice" | "/webhooks/app/scopes_update" | "/api/flow/generate-invoice" | "/api/public/girocode.png" | "/webhooks/orders/fulfilled" | "/webhooks/app/uninstalled" | "/api/public/payment-info" | "/webhooks/orders/updated" | "/webhooks/orders/create" | "/auth/login" | "/healthz" | "/auth/*" | "/app" | "/app/invoices" | "/app/settings"; + }; + "routes/api.flow.send-invoice-email.tsx": { + id: "routes/api.flow.send-invoice-email"; + page: "/api/flow/send-invoice-email"; + }; + "routes/api.orders.$orderId.invoice.tsx": { + id: "routes/api.orders.$orderId.invoice"; + page: "/api/orders/:orderId/invoice"; + }; + "routes/webhooks.app.scopes_update.tsx": { + id: "routes/webhooks.app.scopes_update"; + page: "/webhooks/app/scopes_update"; + }; + "routes/api.flow.generate-invoice.tsx": { + id: "routes/api.flow.generate-invoice"; + page: "/api/flow/generate-invoice"; + }; + "routes/api.public.girocode[.png].tsx": { + id: "routes/api.public.girocode[.png]"; + page: "/api/public/girocode.png"; + }; + "routes/webhooks.orders.fulfilled.tsx": { + id: "routes/webhooks.orders.fulfilled"; + page: "/webhooks/orders/fulfilled"; + }; + "routes/webhooks.app.uninstalled.tsx": { + id: "routes/webhooks.app.uninstalled"; + page: "/webhooks/app/uninstalled"; + }; + "routes/api.public.payment-info.tsx": { + id: "routes/api.public.payment-info"; + page: "/api/public/payment-info"; + }; + "routes/webhooks.orders.updated.tsx": { + id: "routes/webhooks.orders.updated"; + page: "/webhooks/orders/updated"; + }; + "routes/webhooks.orders.create.tsx": { + id: "routes/webhooks.orders.create"; + page: "/webhooks/orders/create"; + }; + "routes/auth.login/route.tsx": { + id: "routes/auth.login"; + page: "/auth/login"; + }; + "routes/healthz.tsx": { + id: "routes/healthz"; + page: "/healthz"; + }; + "routes/_index/route.tsx": { + id: "routes/_index"; + page: "/"; + }; + "routes/auth.$.tsx": { + id: "routes/auth.$"; + page: "/auth/*"; + }; + "routes/app.tsx": { + id: "routes/app"; + page: "/app" | "/app/invoices" | "/app/settings"; + }; + "routes/app.invoices.tsx": { + id: "routes/app.invoices"; + page: "/app/invoices"; + }; + "routes/app.settings.tsx": { + id: "routes/app.settings"; + page: "/app/settings"; + }; + "routes/app._index.tsx": { + id: "routes/app._index"; + page: "/app"; + }; +}; + +type RouteModules = { + "root": typeof import("./app/root.tsx"); + "routes/api.flow.send-invoice-email": typeof import("./app/routes/api.flow.send-invoice-email.tsx"); + "routes/api.orders.$orderId.invoice": typeof import("./app/routes/api.orders.$orderId.invoice.tsx"); + "routes/webhooks.app.scopes_update": typeof import("./app/routes/webhooks.app.scopes_update.tsx"); + "routes/api.flow.generate-invoice": typeof import("./app/routes/api.flow.generate-invoice.tsx"); + "routes/api.public.girocode[.png]": typeof import("./app/routes/api.public.girocode[.png].tsx"); + "routes/webhooks.orders.fulfilled": typeof import("./app/routes/webhooks.orders.fulfilled.tsx"); + "routes/webhooks.app.uninstalled": typeof import("./app/routes/webhooks.app.uninstalled.tsx"); + "routes/api.public.payment-info": typeof import("./app/routes/api.public.payment-info.tsx"); + "routes/webhooks.orders.updated": typeof import("./app/routes/webhooks.orders.updated.tsx"); + "routes/webhooks.orders.create": typeof import("./app/routes/webhooks.orders.create.tsx"); + "routes/auth.login": typeof import("./app/routes/auth.login/route.tsx"); + "routes/healthz": typeof import("./app/routes/healthz.tsx"); + "routes/_index": typeof import("./app/routes/_index/route.tsx"); + "routes/auth.$": typeof import("./app/routes/auth.$.tsx"); + "routes/app": typeof import("./app/routes/app.tsx"); + "routes/app.invoices": typeof import("./app/routes/app.invoices.tsx"); + "routes/app.settings": typeof import("./app/routes/app.settings.tsx"); + "routes/app._index": typeof import("./app/routes/app._index.tsx"); +}; \ No newline at end of file diff --git a/.react-router/types/+server-build.d.ts b/.react-router/types/+server-build.d.ts new file mode 100644 index 0000000..13792c1 --- /dev/null +++ b/.react-router/types/+server-build.d.ts @@ -0,0 +1,18 @@ +// Generated by React Router + +declare module "virtual:react-router/server-build" { + import { ServerBuild } from "react-router"; + export const assets: ServerBuild["assets"]; + export const assetsBuildDirectory: ServerBuild["assetsBuildDirectory"]; + export const basename: ServerBuild["basename"]; + export const entry: ServerBuild["entry"]; + export const future: ServerBuild["future"]; + export const isSpaMode: ServerBuild["isSpaMode"]; + export const prerender: ServerBuild["prerender"]; + export const publicPath: ServerBuild["publicPath"]; + export const routeDiscovery: ServerBuild["routeDiscovery"]; + export const routes: ServerBuild["routes"]; + export const ssr: ServerBuild["ssr"]; + export const allowedActionOrigins: ServerBuild["allowedActionOrigins"]; + export const unstable_getCriticalCss: ServerBuild["unstable_getCriticalCss"]; +} \ No newline at end of file diff --git a/.react-router/types/app/+types/root.ts b/.react-router/types/app/+types/root.ts new file mode 100644 index 0000000..58af758 --- /dev/null +++ b/.react-router/types/app/+types/root.ts @@ -0,0 +1,68 @@ +// Generated by React Router + +import type { GetInfo, GetAnnotations } from "react-router/internal"; + +type Module = typeof import("../root.js") + +type Info = GetInfo<{ + file: "root.tsx", + module: Module +}> + +type Matches = [{ + id: "root"; + module: typeof import("../root.js"); +}]; + +type Annotations = GetAnnotations; + +export namespace Route { + // links + export type LinkDescriptors = Annotations["LinkDescriptors"]; + export type LinksFunction = Annotations["LinksFunction"]; + + // meta + export type MetaArgs = Annotations["MetaArgs"]; + export type MetaDescriptors = Annotations["MetaDescriptors"]; + export type MetaFunction = Annotations["MetaFunction"]; + + // headers + export type HeadersArgs = Annotations["HeadersArgs"]; + export type HeadersFunction = Annotations["HeadersFunction"]; + + // middleware + export type MiddlewareFunction = Annotations["MiddlewareFunction"]; + + // clientMiddleware + export type ClientMiddlewareFunction = Annotations["ClientMiddlewareFunction"]; + + // loader + export type LoaderArgs = Annotations["LoaderArgs"]; + + // clientLoader + export type ClientLoaderArgs = Annotations["ClientLoaderArgs"]; + + // action + export type ActionArgs = Annotations["ActionArgs"]; + + // clientAction + export type ClientActionArgs = Annotations["ClientActionArgs"]; + + // HydrateFallback + export type HydrateFallbackProps = Annotations["HydrateFallbackProps"]; + + // ServerHydrateFallback + export type ServerHydrateFallbackProps = Annotations["ServerHydrateFallbackProps"]; + + // Component + export type ComponentProps = Annotations["ComponentProps"]; + + // ServerComponent + export type ServerComponentProps = Annotations["ServerComponentProps"]; + + // ErrorBoundary + export type ErrorBoundaryProps = Annotations["ErrorBoundaryProps"]; + + // ServerErrorBoundary + export type ServerErrorBoundaryProps = Annotations["ServerErrorBoundaryProps"]; +} \ No newline at end of file diff --git a/.react-router/types/app/routes/+types/api.flow.generate-invoice.ts b/.react-router/types/app/routes/+types/api.flow.generate-invoice.ts new file mode 100644 index 0000000..cf44d24 --- /dev/null +++ b/.react-router/types/app/routes/+types/api.flow.generate-invoice.ts @@ -0,0 +1,71 @@ +// Generated by React Router + +import type { GetInfo, GetAnnotations } from "react-router/internal"; + +type Module = typeof import("../api.flow.generate-invoice.js") + +type Info = GetInfo<{ + file: "routes/api.flow.generate-invoice.tsx", + module: Module +}> + +type Matches = [{ + id: "root"; + module: typeof import("../../root.js"); +}, { + id: "routes/api.flow.generate-invoice"; + module: typeof import("../api.flow.generate-invoice.js"); +}]; + +type Annotations = GetAnnotations; + +export namespace Route { + // links + export type LinkDescriptors = Annotations["LinkDescriptors"]; + export type LinksFunction = Annotations["LinksFunction"]; + + // meta + export type MetaArgs = Annotations["MetaArgs"]; + export type MetaDescriptors = Annotations["MetaDescriptors"]; + export type MetaFunction = Annotations["MetaFunction"]; + + // headers + export type HeadersArgs = Annotations["HeadersArgs"]; + export type HeadersFunction = Annotations["HeadersFunction"]; + + // middleware + export type MiddlewareFunction = Annotations["MiddlewareFunction"]; + + // clientMiddleware + export type ClientMiddlewareFunction = Annotations["ClientMiddlewareFunction"]; + + // loader + export type LoaderArgs = Annotations["LoaderArgs"]; + + // clientLoader + export type ClientLoaderArgs = Annotations["ClientLoaderArgs"]; + + // action + export type ActionArgs = Annotations["ActionArgs"]; + + // clientAction + export type ClientActionArgs = Annotations["ClientActionArgs"]; + + // HydrateFallback + export type HydrateFallbackProps = Annotations["HydrateFallbackProps"]; + + // ServerHydrateFallback + export type ServerHydrateFallbackProps = Annotations["ServerHydrateFallbackProps"]; + + // Component + export type ComponentProps = Annotations["ComponentProps"]; + + // ServerComponent + export type ServerComponentProps = Annotations["ServerComponentProps"]; + + // ErrorBoundary + export type ErrorBoundaryProps = Annotations["ErrorBoundaryProps"]; + + // ServerErrorBoundary + export type ServerErrorBoundaryProps = Annotations["ServerErrorBoundaryProps"]; +} \ No newline at end of file diff --git a/.react-router/types/app/routes/+types/api.flow.send-invoice-email.ts b/.react-router/types/app/routes/+types/api.flow.send-invoice-email.ts new file mode 100644 index 0000000..dde5cbd --- /dev/null +++ b/.react-router/types/app/routes/+types/api.flow.send-invoice-email.ts @@ -0,0 +1,71 @@ +// Generated by React Router + +import type { GetInfo, GetAnnotations } from "react-router/internal"; + +type Module = typeof import("../api.flow.send-invoice-email.js") + +type Info = GetInfo<{ + file: "routes/api.flow.send-invoice-email.tsx", + module: Module +}> + +type Matches = [{ + id: "root"; + module: typeof import("../../root.js"); +}, { + id: "routes/api.flow.send-invoice-email"; + module: typeof import("../api.flow.send-invoice-email.js"); +}]; + +type Annotations = GetAnnotations; + +export namespace Route { + // links + export type LinkDescriptors = Annotations["LinkDescriptors"]; + export type LinksFunction = Annotations["LinksFunction"]; + + // meta + export type MetaArgs = Annotations["MetaArgs"]; + export type MetaDescriptors = Annotations["MetaDescriptors"]; + export type MetaFunction = Annotations["MetaFunction"]; + + // headers + export type HeadersArgs = Annotations["HeadersArgs"]; + export type HeadersFunction = Annotations["HeadersFunction"]; + + // middleware + export type MiddlewareFunction = Annotations["MiddlewareFunction"]; + + // clientMiddleware + export type ClientMiddlewareFunction = Annotations["ClientMiddlewareFunction"]; + + // loader + export type LoaderArgs = Annotations["LoaderArgs"]; + + // clientLoader + export type ClientLoaderArgs = Annotations["ClientLoaderArgs"]; + + // action + export type ActionArgs = Annotations["ActionArgs"]; + + // clientAction + export type ClientActionArgs = Annotations["ClientActionArgs"]; + + // HydrateFallback + export type HydrateFallbackProps = Annotations["HydrateFallbackProps"]; + + // ServerHydrateFallback + export type ServerHydrateFallbackProps = Annotations["ServerHydrateFallbackProps"]; + + // Component + export type ComponentProps = Annotations["ComponentProps"]; + + // ServerComponent + export type ServerComponentProps = Annotations["ServerComponentProps"]; + + // ErrorBoundary + export type ErrorBoundaryProps = Annotations["ErrorBoundaryProps"]; + + // ServerErrorBoundary + export type ServerErrorBoundaryProps = Annotations["ServerErrorBoundaryProps"]; +} \ No newline at end of file diff --git a/.react-router/types/app/routes/+types/api.orders.$orderId.invoice.ts b/.react-router/types/app/routes/+types/api.orders.$orderId.invoice.ts new file mode 100644 index 0000000..fef5aa8 --- /dev/null +++ b/.react-router/types/app/routes/+types/api.orders.$orderId.invoice.ts @@ -0,0 +1,71 @@ +// Generated by React Router + +import type { GetInfo, GetAnnotations } from "react-router/internal"; + +type Module = typeof import("../api.orders.$orderId.invoice.js") + +type Info = GetInfo<{ + file: "routes/api.orders.$orderId.invoice.tsx", + module: Module +}> + +type Matches = [{ + id: "root"; + module: typeof import("../../root.js"); +}, { + id: "routes/api.orders.$orderId.invoice"; + module: typeof import("../api.orders.$orderId.invoice.js"); +}]; + +type Annotations = GetAnnotations; + +export namespace Route { + // links + export type LinkDescriptors = Annotations["LinkDescriptors"]; + export type LinksFunction = Annotations["LinksFunction"]; + + // meta + export type MetaArgs = Annotations["MetaArgs"]; + export type MetaDescriptors = Annotations["MetaDescriptors"]; + export type MetaFunction = Annotations["MetaFunction"]; + + // headers + export type HeadersArgs = Annotations["HeadersArgs"]; + export type HeadersFunction = Annotations["HeadersFunction"]; + + // middleware + export type MiddlewareFunction = Annotations["MiddlewareFunction"]; + + // clientMiddleware + export type ClientMiddlewareFunction = Annotations["ClientMiddlewareFunction"]; + + // loader + export type LoaderArgs = Annotations["LoaderArgs"]; + + // clientLoader + export type ClientLoaderArgs = Annotations["ClientLoaderArgs"]; + + // action + export type ActionArgs = Annotations["ActionArgs"]; + + // clientAction + export type ClientActionArgs = Annotations["ClientActionArgs"]; + + // HydrateFallback + export type HydrateFallbackProps = Annotations["HydrateFallbackProps"]; + + // ServerHydrateFallback + export type ServerHydrateFallbackProps = Annotations["ServerHydrateFallbackProps"]; + + // Component + export type ComponentProps = Annotations["ComponentProps"]; + + // ServerComponent + export type ServerComponentProps = Annotations["ServerComponentProps"]; + + // ErrorBoundary + export type ErrorBoundaryProps = Annotations["ErrorBoundaryProps"]; + + // ServerErrorBoundary + export type ServerErrorBoundaryProps = Annotations["ServerErrorBoundaryProps"]; +} \ No newline at end of file diff --git a/.react-router/types/app/routes/+types/api.public.girocode[.png].ts b/.react-router/types/app/routes/+types/api.public.girocode[.png].ts new file mode 100644 index 0000000..a0d8e44 --- /dev/null +++ b/.react-router/types/app/routes/+types/api.public.girocode[.png].ts @@ -0,0 +1,71 @@ +// Generated by React Router + +import type { GetInfo, GetAnnotations } from "react-router/internal"; + +type Module = typeof import("../api.public.girocode[.png].js") + +type Info = GetInfo<{ + file: "routes/api.public.girocode[.png].tsx", + module: Module +}> + +type Matches = [{ + id: "root"; + module: typeof import("../../root.js"); +}, { + id: "routes/api.public.girocode[.png]"; + module: typeof import("../api.public.girocode[.png].js"); +}]; + +type Annotations = GetAnnotations; + +export namespace Route { + // links + export type LinkDescriptors = Annotations["LinkDescriptors"]; + export type LinksFunction = Annotations["LinksFunction"]; + + // meta + export type MetaArgs = Annotations["MetaArgs"]; + export type MetaDescriptors = Annotations["MetaDescriptors"]; + export type MetaFunction = Annotations["MetaFunction"]; + + // headers + export type HeadersArgs = Annotations["HeadersArgs"]; + export type HeadersFunction = Annotations["HeadersFunction"]; + + // middleware + export type MiddlewareFunction = Annotations["MiddlewareFunction"]; + + // clientMiddleware + export type ClientMiddlewareFunction = Annotations["ClientMiddlewareFunction"]; + + // loader + export type LoaderArgs = Annotations["LoaderArgs"]; + + // clientLoader + export type ClientLoaderArgs = Annotations["ClientLoaderArgs"]; + + // action + export type ActionArgs = Annotations["ActionArgs"]; + + // clientAction + export type ClientActionArgs = Annotations["ClientActionArgs"]; + + // HydrateFallback + export type HydrateFallbackProps = Annotations["HydrateFallbackProps"]; + + // ServerHydrateFallback + export type ServerHydrateFallbackProps = Annotations["ServerHydrateFallbackProps"]; + + // Component + export type ComponentProps = Annotations["ComponentProps"]; + + // ServerComponent + export type ServerComponentProps = Annotations["ServerComponentProps"]; + + // ErrorBoundary + export type ErrorBoundaryProps = Annotations["ErrorBoundaryProps"]; + + // ServerErrorBoundary + export type ServerErrorBoundaryProps = Annotations["ServerErrorBoundaryProps"]; +} \ No newline at end of file diff --git a/.react-router/types/app/routes/+types/api.public.payment-info.ts b/.react-router/types/app/routes/+types/api.public.payment-info.ts new file mode 100644 index 0000000..f0d272a --- /dev/null +++ b/.react-router/types/app/routes/+types/api.public.payment-info.ts @@ -0,0 +1,71 @@ +// Generated by React Router + +import type { GetInfo, GetAnnotations } from "react-router/internal"; + +type Module = typeof import("../api.public.payment-info.js") + +type Info = GetInfo<{ + file: "routes/api.public.payment-info.tsx", + module: Module +}> + +type Matches = [{ + id: "root"; + module: typeof import("../../root.js"); +}, { + id: "routes/api.public.payment-info"; + module: typeof import("../api.public.payment-info.js"); +}]; + +type Annotations = GetAnnotations; + +export namespace Route { + // links + export type LinkDescriptors = Annotations["LinkDescriptors"]; + export type LinksFunction = Annotations["LinksFunction"]; + + // meta + export type MetaArgs = Annotations["MetaArgs"]; + export type MetaDescriptors = Annotations["MetaDescriptors"]; + export type MetaFunction = Annotations["MetaFunction"]; + + // headers + export type HeadersArgs = Annotations["HeadersArgs"]; + export type HeadersFunction = Annotations["HeadersFunction"]; + + // middleware + export type MiddlewareFunction = Annotations["MiddlewareFunction"]; + + // clientMiddleware + export type ClientMiddlewareFunction = Annotations["ClientMiddlewareFunction"]; + + // loader + export type LoaderArgs = Annotations["LoaderArgs"]; + + // clientLoader + export type ClientLoaderArgs = Annotations["ClientLoaderArgs"]; + + // action + export type ActionArgs = Annotations["ActionArgs"]; + + // clientAction + export type ClientActionArgs = Annotations["ClientActionArgs"]; + + // HydrateFallback + export type HydrateFallbackProps = Annotations["HydrateFallbackProps"]; + + // ServerHydrateFallback + export type ServerHydrateFallbackProps = Annotations["ServerHydrateFallbackProps"]; + + // Component + export type ComponentProps = Annotations["ComponentProps"]; + + // ServerComponent + export type ServerComponentProps = Annotations["ServerComponentProps"]; + + // ErrorBoundary + export type ErrorBoundaryProps = Annotations["ErrorBoundaryProps"]; + + // ServerErrorBoundary + export type ServerErrorBoundaryProps = Annotations["ServerErrorBoundaryProps"]; +} \ No newline at end of file diff --git a/.react-router/types/app/routes/+types/app._index.ts b/.react-router/types/app/routes/+types/app._index.ts new file mode 100644 index 0000000..5f4aed0 --- /dev/null +++ b/.react-router/types/app/routes/+types/app._index.ts @@ -0,0 +1,74 @@ +// Generated by React Router + +import type { GetInfo, GetAnnotations } from "react-router/internal"; + +type Module = typeof import("../app._index.js") + +type Info = GetInfo<{ + file: "routes/app._index.tsx", + module: Module +}> + +type Matches = [{ + id: "root"; + module: typeof import("../../root.js"); +}, { + id: "routes/app"; + module: typeof import("../app.js"); +}, { + id: "routes/app._index"; + module: typeof import("../app._index.js"); +}]; + +type Annotations = GetAnnotations; + +export namespace Route { + // links + export type LinkDescriptors = Annotations["LinkDescriptors"]; + export type LinksFunction = Annotations["LinksFunction"]; + + // meta + export type MetaArgs = Annotations["MetaArgs"]; + export type MetaDescriptors = Annotations["MetaDescriptors"]; + export type MetaFunction = Annotations["MetaFunction"]; + + // headers + export type HeadersArgs = Annotations["HeadersArgs"]; + export type HeadersFunction = Annotations["HeadersFunction"]; + + // middleware + export type MiddlewareFunction = Annotations["MiddlewareFunction"]; + + // clientMiddleware + export type ClientMiddlewareFunction = Annotations["ClientMiddlewareFunction"]; + + // loader + export type LoaderArgs = Annotations["LoaderArgs"]; + + // clientLoader + export type ClientLoaderArgs = Annotations["ClientLoaderArgs"]; + + // action + export type ActionArgs = Annotations["ActionArgs"]; + + // clientAction + export type ClientActionArgs = Annotations["ClientActionArgs"]; + + // HydrateFallback + export type HydrateFallbackProps = Annotations["HydrateFallbackProps"]; + + // ServerHydrateFallback + export type ServerHydrateFallbackProps = Annotations["ServerHydrateFallbackProps"]; + + // Component + export type ComponentProps = Annotations["ComponentProps"]; + + // ServerComponent + export type ServerComponentProps = Annotations["ServerComponentProps"]; + + // ErrorBoundary + export type ErrorBoundaryProps = Annotations["ErrorBoundaryProps"]; + + // ServerErrorBoundary + export type ServerErrorBoundaryProps = Annotations["ServerErrorBoundaryProps"]; +} \ No newline at end of file diff --git a/.react-router/types/app/routes/+types/app.invoices.ts b/.react-router/types/app/routes/+types/app.invoices.ts new file mode 100644 index 0000000..301929d --- /dev/null +++ b/.react-router/types/app/routes/+types/app.invoices.ts @@ -0,0 +1,74 @@ +// Generated by React Router + +import type { GetInfo, GetAnnotations } from "react-router/internal"; + +type Module = typeof import("../app.invoices.js") + +type Info = GetInfo<{ + file: "routes/app.invoices.tsx", + module: Module +}> + +type Matches = [{ + id: "root"; + module: typeof import("../../root.js"); +}, { + id: "routes/app"; + module: typeof import("../app.js"); +}, { + id: "routes/app.invoices"; + module: typeof import("../app.invoices.js"); +}]; + +type Annotations = GetAnnotations; + +export namespace Route { + // links + export type LinkDescriptors = Annotations["LinkDescriptors"]; + export type LinksFunction = Annotations["LinksFunction"]; + + // meta + export type MetaArgs = Annotations["MetaArgs"]; + export type MetaDescriptors = Annotations["MetaDescriptors"]; + export type MetaFunction = Annotations["MetaFunction"]; + + // headers + export type HeadersArgs = Annotations["HeadersArgs"]; + export type HeadersFunction = Annotations["HeadersFunction"]; + + // middleware + export type MiddlewareFunction = Annotations["MiddlewareFunction"]; + + // clientMiddleware + export type ClientMiddlewareFunction = Annotations["ClientMiddlewareFunction"]; + + // loader + export type LoaderArgs = Annotations["LoaderArgs"]; + + // clientLoader + export type ClientLoaderArgs = Annotations["ClientLoaderArgs"]; + + // action + export type ActionArgs = Annotations["ActionArgs"]; + + // clientAction + export type ClientActionArgs = Annotations["ClientActionArgs"]; + + // HydrateFallback + export type HydrateFallbackProps = Annotations["HydrateFallbackProps"]; + + // ServerHydrateFallback + export type ServerHydrateFallbackProps = Annotations["ServerHydrateFallbackProps"]; + + // Component + export type ComponentProps = Annotations["ComponentProps"]; + + // ServerComponent + export type ServerComponentProps = Annotations["ServerComponentProps"]; + + // ErrorBoundary + export type ErrorBoundaryProps = Annotations["ErrorBoundaryProps"]; + + // ServerErrorBoundary + export type ServerErrorBoundaryProps = Annotations["ServerErrorBoundaryProps"]; +} \ No newline at end of file diff --git a/.react-router/types/app/routes/+types/app.settings.ts b/.react-router/types/app/routes/+types/app.settings.ts new file mode 100644 index 0000000..09860c3 --- /dev/null +++ b/.react-router/types/app/routes/+types/app.settings.ts @@ -0,0 +1,74 @@ +// Generated by React Router + +import type { GetInfo, GetAnnotations } from "react-router/internal"; + +type Module = typeof import("../app.settings.js") + +type Info = GetInfo<{ + file: "routes/app.settings.tsx", + module: Module +}> + +type Matches = [{ + id: "root"; + module: typeof import("../../root.js"); +}, { + id: "routes/app"; + module: typeof import("../app.js"); +}, { + id: "routes/app.settings"; + module: typeof import("../app.settings.js"); +}]; + +type Annotations = GetAnnotations; + +export namespace Route { + // links + export type LinkDescriptors = Annotations["LinkDescriptors"]; + export type LinksFunction = Annotations["LinksFunction"]; + + // meta + export type MetaArgs = Annotations["MetaArgs"]; + export type MetaDescriptors = Annotations["MetaDescriptors"]; + export type MetaFunction = Annotations["MetaFunction"]; + + // headers + export type HeadersArgs = Annotations["HeadersArgs"]; + export type HeadersFunction = Annotations["HeadersFunction"]; + + // middleware + export type MiddlewareFunction = Annotations["MiddlewareFunction"]; + + // clientMiddleware + export type ClientMiddlewareFunction = Annotations["ClientMiddlewareFunction"]; + + // loader + export type LoaderArgs = Annotations["LoaderArgs"]; + + // clientLoader + export type ClientLoaderArgs = Annotations["ClientLoaderArgs"]; + + // action + export type ActionArgs = Annotations["ActionArgs"]; + + // clientAction + export type ClientActionArgs = Annotations["ClientActionArgs"]; + + // HydrateFallback + export type HydrateFallbackProps = Annotations["HydrateFallbackProps"]; + + // ServerHydrateFallback + export type ServerHydrateFallbackProps = Annotations["ServerHydrateFallbackProps"]; + + // Component + export type ComponentProps = Annotations["ComponentProps"]; + + // ServerComponent + export type ServerComponentProps = Annotations["ServerComponentProps"]; + + // ErrorBoundary + export type ErrorBoundaryProps = Annotations["ErrorBoundaryProps"]; + + // ServerErrorBoundary + export type ServerErrorBoundaryProps = Annotations["ServerErrorBoundaryProps"]; +} \ No newline at end of file diff --git a/.react-router/types/app/routes/+types/app.ts b/.react-router/types/app/routes/+types/app.ts new file mode 100644 index 0000000..620fa68 --- /dev/null +++ b/.react-router/types/app/routes/+types/app.ts @@ -0,0 +1,71 @@ +// Generated by React Router + +import type { GetInfo, GetAnnotations } from "react-router/internal"; + +type Module = typeof import("../app.js") + +type Info = GetInfo<{ + file: "routes/app.tsx", + module: Module +}> + +type Matches = [{ + id: "root"; + module: typeof import("../../root.js"); +}, { + id: "routes/app"; + module: typeof import("../app.js"); +}]; + +type Annotations = GetAnnotations; + +export namespace Route { + // links + export type LinkDescriptors = Annotations["LinkDescriptors"]; + export type LinksFunction = Annotations["LinksFunction"]; + + // meta + export type MetaArgs = Annotations["MetaArgs"]; + export type MetaDescriptors = Annotations["MetaDescriptors"]; + export type MetaFunction = Annotations["MetaFunction"]; + + // headers + export type HeadersArgs = Annotations["HeadersArgs"]; + export type HeadersFunction = Annotations["HeadersFunction"]; + + // middleware + export type MiddlewareFunction = Annotations["MiddlewareFunction"]; + + // clientMiddleware + export type ClientMiddlewareFunction = Annotations["ClientMiddlewareFunction"]; + + // loader + export type LoaderArgs = Annotations["LoaderArgs"]; + + // clientLoader + export type ClientLoaderArgs = Annotations["ClientLoaderArgs"]; + + // action + export type ActionArgs = Annotations["ActionArgs"]; + + // clientAction + export type ClientActionArgs = Annotations["ClientActionArgs"]; + + // HydrateFallback + export type HydrateFallbackProps = Annotations["HydrateFallbackProps"]; + + // ServerHydrateFallback + export type ServerHydrateFallbackProps = Annotations["ServerHydrateFallbackProps"]; + + // Component + export type ComponentProps = Annotations["ComponentProps"]; + + // ServerComponent + export type ServerComponentProps = Annotations["ServerComponentProps"]; + + // ErrorBoundary + export type ErrorBoundaryProps = Annotations["ErrorBoundaryProps"]; + + // ServerErrorBoundary + export type ServerErrorBoundaryProps = Annotations["ServerErrorBoundaryProps"]; +} \ No newline at end of file diff --git a/.react-router/types/app/routes/+types/auth.$.ts b/.react-router/types/app/routes/+types/auth.$.ts new file mode 100644 index 0000000..21595e8 --- /dev/null +++ b/.react-router/types/app/routes/+types/auth.$.ts @@ -0,0 +1,71 @@ +// Generated by React Router + +import type { GetInfo, GetAnnotations } from "react-router/internal"; + +type Module = typeof import("../auth.$.js") + +type Info = GetInfo<{ + file: "routes/auth.$.tsx", + module: Module +}> + +type Matches = [{ + id: "root"; + module: typeof import("../../root.js"); +}, { + id: "routes/auth.$"; + module: typeof import("../auth.$.js"); +}]; + +type Annotations = GetAnnotations; + +export namespace Route { + // links + export type LinkDescriptors = Annotations["LinkDescriptors"]; + export type LinksFunction = Annotations["LinksFunction"]; + + // meta + export type MetaArgs = Annotations["MetaArgs"]; + export type MetaDescriptors = Annotations["MetaDescriptors"]; + export type MetaFunction = Annotations["MetaFunction"]; + + // headers + export type HeadersArgs = Annotations["HeadersArgs"]; + export type HeadersFunction = Annotations["HeadersFunction"]; + + // middleware + export type MiddlewareFunction = Annotations["MiddlewareFunction"]; + + // clientMiddleware + export type ClientMiddlewareFunction = Annotations["ClientMiddlewareFunction"]; + + // loader + export type LoaderArgs = Annotations["LoaderArgs"]; + + // clientLoader + export type ClientLoaderArgs = Annotations["ClientLoaderArgs"]; + + // action + export type ActionArgs = Annotations["ActionArgs"]; + + // clientAction + export type ClientActionArgs = Annotations["ClientActionArgs"]; + + // HydrateFallback + export type HydrateFallbackProps = Annotations["HydrateFallbackProps"]; + + // ServerHydrateFallback + export type ServerHydrateFallbackProps = Annotations["ServerHydrateFallbackProps"]; + + // Component + export type ComponentProps = Annotations["ComponentProps"]; + + // ServerComponent + export type ServerComponentProps = Annotations["ServerComponentProps"]; + + // ErrorBoundary + export type ErrorBoundaryProps = Annotations["ErrorBoundaryProps"]; + + // ServerErrorBoundary + export type ServerErrorBoundaryProps = Annotations["ServerErrorBoundaryProps"]; +} \ No newline at end of file diff --git a/.react-router/types/app/routes/+types/healthz.ts b/.react-router/types/app/routes/+types/healthz.ts new file mode 100644 index 0000000..cf3031a --- /dev/null +++ b/.react-router/types/app/routes/+types/healthz.ts @@ -0,0 +1,71 @@ +// Generated by React Router + +import type { GetInfo, GetAnnotations } from "react-router/internal"; + +type Module = typeof import("../healthz.js") + +type Info = GetInfo<{ + file: "routes/healthz.tsx", + module: Module +}> + +type Matches = [{ + id: "root"; + module: typeof import("../../root.js"); +}, { + id: "routes/healthz"; + module: typeof import("../healthz.js"); +}]; + +type Annotations = GetAnnotations; + +export namespace Route { + // links + export type LinkDescriptors = Annotations["LinkDescriptors"]; + export type LinksFunction = Annotations["LinksFunction"]; + + // meta + export type MetaArgs = Annotations["MetaArgs"]; + export type MetaDescriptors = Annotations["MetaDescriptors"]; + export type MetaFunction = Annotations["MetaFunction"]; + + // headers + export type HeadersArgs = Annotations["HeadersArgs"]; + export type HeadersFunction = Annotations["HeadersFunction"]; + + // middleware + export type MiddlewareFunction = Annotations["MiddlewareFunction"]; + + // clientMiddleware + export type ClientMiddlewareFunction = Annotations["ClientMiddlewareFunction"]; + + // loader + export type LoaderArgs = Annotations["LoaderArgs"]; + + // clientLoader + export type ClientLoaderArgs = Annotations["ClientLoaderArgs"]; + + // action + export type ActionArgs = Annotations["ActionArgs"]; + + // clientAction + export type ClientActionArgs = Annotations["ClientActionArgs"]; + + // HydrateFallback + export type HydrateFallbackProps = Annotations["HydrateFallbackProps"]; + + // ServerHydrateFallback + export type ServerHydrateFallbackProps = Annotations["ServerHydrateFallbackProps"]; + + // Component + export type ComponentProps = Annotations["ComponentProps"]; + + // ServerComponent + export type ServerComponentProps = Annotations["ServerComponentProps"]; + + // ErrorBoundary + export type ErrorBoundaryProps = Annotations["ErrorBoundaryProps"]; + + // ServerErrorBoundary + export type ServerErrorBoundaryProps = Annotations["ServerErrorBoundaryProps"]; +} \ No newline at end of file diff --git a/.react-router/types/app/routes/+types/webhooks.app.scopes_update.ts b/.react-router/types/app/routes/+types/webhooks.app.scopes_update.ts new file mode 100644 index 0000000..751b6ee --- /dev/null +++ b/.react-router/types/app/routes/+types/webhooks.app.scopes_update.ts @@ -0,0 +1,71 @@ +// Generated by React Router + +import type { GetInfo, GetAnnotations } from "react-router/internal"; + +type Module = typeof import("../webhooks.app.scopes_update.js") + +type Info = GetInfo<{ + file: "routes/webhooks.app.scopes_update.tsx", + module: Module +}> + +type Matches = [{ + id: "root"; + module: typeof import("../../root.js"); +}, { + id: "routes/webhooks.app.scopes_update"; + module: typeof import("../webhooks.app.scopes_update.js"); +}]; + +type Annotations = GetAnnotations; + +export namespace Route { + // links + export type LinkDescriptors = Annotations["LinkDescriptors"]; + export type LinksFunction = Annotations["LinksFunction"]; + + // meta + export type MetaArgs = Annotations["MetaArgs"]; + export type MetaDescriptors = Annotations["MetaDescriptors"]; + export type MetaFunction = Annotations["MetaFunction"]; + + // headers + export type HeadersArgs = Annotations["HeadersArgs"]; + export type HeadersFunction = Annotations["HeadersFunction"]; + + // middleware + export type MiddlewareFunction = Annotations["MiddlewareFunction"]; + + // clientMiddleware + export type ClientMiddlewareFunction = Annotations["ClientMiddlewareFunction"]; + + // loader + export type LoaderArgs = Annotations["LoaderArgs"]; + + // clientLoader + export type ClientLoaderArgs = Annotations["ClientLoaderArgs"]; + + // action + export type ActionArgs = Annotations["ActionArgs"]; + + // clientAction + export type ClientActionArgs = Annotations["ClientActionArgs"]; + + // HydrateFallback + export type HydrateFallbackProps = Annotations["HydrateFallbackProps"]; + + // ServerHydrateFallback + export type ServerHydrateFallbackProps = Annotations["ServerHydrateFallbackProps"]; + + // Component + export type ComponentProps = Annotations["ComponentProps"]; + + // ServerComponent + export type ServerComponentProps = Annotations["ServerComponentProps"]; + + // ErrorBoundary + export type ErrorBoundaryProps = Annotations["ErrorBoundaryProps"]; + + // ServerErrorBoundary + export type ServerErrorBoundaryProps = Annotations["ServerErrorBoundaryProps"]; +} \ No newline at end of file diff --git a/.react-router/types/app/routes/+types/webhooks.app.uninstalled.ts b/.react-router/types/app/routes/+types/webhooks.app.uninstalled.ts new file mode 100644 index 0000000..f802b78 --- /dev/null +++ b/.react-router/types/app/routes/+types/webhooks.app.uninstalled.ts @@ -0,0 +1,71 @@ +// Generated by React Router + +import type { GetInfo, GetAnnotations } from "react-router/internal"; + +type Module = typeof import("../webhooks.app.uninstalled.js") + +type Info = GetInfo<{ + file: "routes/webhooks.app.uninstalled.tsx", + module: Module +}> + +type Matches = [{ + id: "root"; + module: typeof import("../../root.js"); +}, { + id: "routes/webhooks.app.uninstalled"; + module: typeof import("../webhooks.app.uninstalled.js"); +}]; + +type Annotations = GetAnnotations; + +export namespace Route { + // links + export type LinkDescriptors = Annotations["LinkDescriptors"]; + export type LinksFunction = Annotations["LinksFunction"]; + + // meta + export type MetaArgs = Annotations["MetaArgs"]; + export type MetaDescriptors = Annotations["MetaDescriptors"]; + export type MetaFunction = Annotations["MetaFunction"]; + + // headers + export type HeadersArgs = Annotations["HeadersArgs"]; + export type HeadersFunction = Annotations["HeadersFunction"]; + + // middleware + export type MiddlewareFunction = Annotations["MiddlewareFunction"]; + + // clientMiddleware + export type ClientMiddlewareFunction = Annotations["ClientMiddlewareFunction"]; + + // loader + export type LoaderArgs = Annotations["LoaderArgs"]; + + // clientLoader + export type ClientLoaderArgs = Annotations["ClientLoaderArgs"]; + + // action + export type ActionArgs = Annotations["ActionArgs"]; + + // clientAction + export type ClientActionArgs = Annotations["ClientActionArgs"]; + + // HydrateFallback + export type HydrateFallbackProps = Annotations["HydrateFallbackProps"]; + + // ServerHydrateFallback + export type ServerHydrateFallbackProps = Annotations["ServerHydrateFallbackProps"]; + + // Component + export type ComponentProps = Annotations["ComponentProps"]; + + // ServerComponent + export type ServerComponentProps = Annotations["ServerComponentProps"]; + + // ErrorBoundary + export type ErrorBoundaryProps = Annotations["ErrorBoundaryProps"]; + + // ServerErrorBoundary + export type ServerErrorBoundaryProps = Annotations["ServerErrorBoundaryProps"]; +} \ No newline at end of file diff --git a/.react-router/types/app/routes/+types/webhooks.orders.create.ts b/.react-router/types/app/routes/+types/webhooks.orders.create.ts new file mode 100644 index 0000000..63e4e7c --- /dev/null +++ b/.react-router/types/app/routes/+types/webhooks.orders.create.ts @@ -0,0 +1,71 @@ +// Generated by React Router + +import type { GetInfo, GetAnnotations } from "react-router/internal"; + +type Module = typeof import("../webhooks.orders.create.js") + +type Info = GetInfo<{ + file: "routes/webhooks.orders.create.tsx", + module: Module +}> + +type Matches = [{ + id: "root"; + module: typeof import("../../root.js"); +}, { + id: "routes/webhooks.orders.create"; + module: typeof import("../webhooks.orders.create.js"); +}]; + +type Annotations = GetAnnotations; + +export namespace Route { + // links + export type LinkDescriptors = Annotations["LinkDescriptors"]; + export type LinksFunction = Annotations["LinksFunction"]; + + // meta + export type MetaArgs = Annotations["MetaArgs"]; + export type MetaDescriptors = Annotations["MetaDescriptors"]; + export type MetaFunction = Annotations["MetaFunction"]; + + // headers + export type HeadersArgs = Annotations["HeadersArgs"]; + export type HeadersFunction = Annotations["HeadersFunction"]; + + // middleware + export type MiddlewareFunction = Annotations["MiddlewareFunction"]; + + // clientMiddleware + export type ClientMiddlewareFunction = Annotations["ClientMiddlewareFunction"]; + + // loader + export type LoaderArgs = Annotations["LoaderArgs"]; + + // clientLoader + export type ClientLoaderArgs = Annotations["ClientLoaderArgs"]; + + // action + export type ActionArgs = Annotations["ActionArgs"]; + + // clientAction + export type ClientActionArgs = Annotations["ClientActionArgs"]; + + // HydrateFallback + export type HydrateFallbackProps = Annotations["HydrateFallbackProps"]; + + // ServerHydrateFallback + export type ServerHydrateFallbackProps = Annotations["ServerHydrateFallbackProps"]; + + // Component + export type ComponentProps = Annotations["ComponentProps"]; + + // ServerComponent + export type ServerComponentProps = Annotations["ServerComponentProps"]; + + // ErrorBoundary + export type ErrorBoundaryProps = Annotations["ErrorBoundaryProps"]; + + // ServerErrorBoundary + export type ServerErrorBoundaryProps = Annotations["ServerErrorBoundaryProps"]; +} \ No newline at end of file diff --git a/.react-router/types/app/routes/+types/webhooks.orders.fulfilled.ts b/.react-router/types/app/routes/+types/webhooks.orders.fulfilled.ts new file mode 100644 index 0000000..b1e8df2 --- /dev/null +++ b/.react-router/types/app/routes/+types/webhooks.orders.fulfilled.ts @@ -0,0 +1,71 @@ +// Generated by React Router + +import type { GetInfo, GetAnnotations } from "react-router/internal"; + +type Module = typeof import("../webhooks.orders.fulfilled.js") + +type Info = GetInfo<{ + file: "routes/webhooks.orders.fulfilled.tsx", + module: Module +}> + +type Matches = [{ + id: "root"; + module: typeof import("../../root.js"); +}, { + id: "routes/webhooks.orders.fulfilled"; + module: typeof import("../webhooks.orders.fulfilled.js"); +}]; + +type Annotations = GetAnnotations; + +export namespace Route { + // links + export type LinkDescriptors = Annotations["LinkDescriptors"]; + export type LinksFunction = Annotations["LinksFunction"]; + + // meta + export type MetaArgs = Annotations["MetaArgs"]; + export type MetaDescriptors = Annotations["MetaDescriptors"]; + export type MetaFunction = Annotations["MetaFunction"]; + + // headers + export type HeadersArgs = Annotations["HeadersArgs"]; + export type HeadersFunction = Annotations["HeadersFunction"]; + + // middleware + export type MiddlewareFunction = Annotations["MiddlewareFunction"]; + + // clientMiddleware + export type ClientMiddlewareFunction = Annotations["ClientMiddlewareFunction"]; + + // loader + export type LoaderArgs = Annotations["LoaderArgs"]; + + // clientLoader + export type ClientLoaderArgs = Annotations["ClientLoaderArgs"]; + + // action + export type ActionArgs = Annotations["ActionArgs"]; + + // clientAction + export type ClientActionArgs = Annotations["ClientActionArgs"]; + + // HydrateFallback + export type HydrateFallbackProps = Annotations["HydrateFallbackProps"]; + + // ServerHydrateFallback + export type ServerHydrateFallbackProps = Annotations["ServerHydrateFallbackProps"]; + + // Component + export type ComponentProps = Annotations["ComponentProps"]; + + // ServerComponent + export type ServerComponentProps = Annotations["ServerComponentProps"]; + + // ErrorBoundary + export type ErrorBoundaryProps = Annotations["ErrorBoundaryProps"]; + + // ServerErrorBoundary + export type ServerErrorBoundaryProps = Annotations["ServerErrorBoundaryProps"]; +} \ No newline at end of file diff --git a/.react-router/types/app/routes/+types/webhooks.orders.updated.ts b/.react-router/types/app/routes/+types/webhooks.orders.updated.ts new file mode 100644 index 0000000..11a544b --- /dev/null +++ b/.react-router/types/app/routes/+types/webhooks.orders.updated.ts @@ -0,0 +1,71 @@ +// Generated by React Router + +import type { GetInfo, GetAnnotations } from "react-router/internal"; + +type Module = typeof import("../webhooks.orders.updated.js") + +type Info = GetInfo<{ + file: "routes/webhooks.orders.updated.tsx", + module: Module +}> + +type Matches = [{ + id: "root"; + module: typeof import("../../root.js"); +}, { + id: "routes/webhooks.orders.updated"; + module: typeof import("../webhooks.orders.updated.js"); +}]; + +type Annotations = GetAnnotations; + +export namespace Route { + // links + export type LinkDescriptors = Annotations["LinkDescriptors"]; + export type LinksFunction = Annotations["LinksFunction"]; + + // meta + export type MetaArgs = Annotations["MetaArgs"]; + export type MetaDescriptors = Annotations["MetaDescriptors"]; + export type MetaFunction = Annotations["MetaFunction"]; + + // headers + export type HeadersArgs = Annotations["HeadersArgs"]; + export type HeadersFunction = Annotations["HeadersFunction"]; + + // middleware + export type MiddlewareFunction = Annotations["MiddlewareFunction"]; + + // clientMiddleware + export type ClientMiddlewareFunction = Annotations["ClientMiddlewareFunction"]; + + // loader + export type LoaderArgs = Annotations["LoaderArgs"]; + + // clientLoader + export type ClientLoaderArgs = Annotations["ClientLoaderArgs"]; + + // action + export type ActionArgs = Annotations["ActionArgs"]; + + // clientAction + export type ClientActionArgs = Annotations["ClientActionArgs"]; + + // HydrateFallback + export type HydrateFallbackProps = Annotations["HydrateFallbackProps"]; + + // ServerHydrateFallback + export type ServerHydrateFallbackProps = Annotations["ServerHydrateFallbackProps"]; + + // Component + export type ComponentProps = Annotations["ComponentProps"]; + + // ServerComponent + export type ServerComponentProps = Annotations["ServerComponentProps"]; + + // ErrorBoundary + export type ErrorBoundaryProps = Annotations["ErrorBoundaryProps"]; + + // ServerErrorBoundary + export type ServerErrorBoundaryProps = Annotations["ServerErrorBoundaryProps"]; +} \ No newline at end of file diff --git a/.react-router/types/app/routes/_index/+types/route.ts b/.react-router/types/app/routes/_index/+types/route.ts new file mode 100644 index 0000000..d8dbf4a --- /dev/null +++ b/.react-router/types/app/routes/_index/+types/route.ts @@ -0,0 +1,71 @@ +// Generated by React Router + +import type { GetInfo, GetAnnotations } from "react-router/internal"; + +type Module = typeof import("../route.js") + +type Info = GetInfo<{ + file: "routes/_index/route.tsx", + module: Module +}> + +type Matches = [{ + id: "root"; + module: typeof import("../../../root.js"); +}, { + id: "routes/_index"; + module: typeof import("../route.js"); +}]; + +type Annotations = GetAnnotations; + +export namespace Route { + // links + export type LinkDescriptors = Annotations["LinkDescriptors"]; + export type LinksFunction = Annotations["LinksFunction"]; + + // meta + export type MetaArgs = Annotations["MetaArgs"]; + export type MetaDescriptors = Annotations["MetaDescriptors"]; + export type MetaFunction = Annotations["MetaFunction"]; + + // headers + export type HeadersArgs = Annotations["HeadersArgs"]; + export type HeadersFunction = Annotations["HeadersFunction"]; + + // middleware + export type MiddlewareFunction = Annotations["MiddlewareFunction"]; + + // clientMiddleware + export type ClientMiddlewareFunction = Annotations["ClientMiddlewareFunction"]; + + // loader + export type LoaderArgs = Annotations["LoaderArgs"]; + + // clientLoader + export type ClientLoaderArgs = Annotations["ClientLoaderArgs"]; + + // action + export type ActionArgs = Annotations["ActionArgs"]; + + // clientAction + export type ClientActionArgs = Annotations["ClientActionArgs"]; + + // HydrateFallback + export type HydrateFallbackProps = Annotations["HydrateFallbackProps"]; + + // ServerHydrateFallback + export type ServerHydrateFallbackProps = Annotations["ServerHydrateFallbackProps"]; + + // Component + export type ComponentProps = Annotations["ComponentProps"]; + + // ServerComponent + export type ServerComponentProps = Annotations["ServerComponentProps"]; + + // ErrorBoundary + export type ErrorBoundaryProps = Annotations["ErrorBoundaryProps"]; + + // ServerErrorBoundary + export type ServerErrorBoundaryProps = Annotations["ServerErrorBoundaryProps"]; +} \ No newline at end of file diff --git a/.react-router/types/app/routes/auth.login/+types/route.ts b/.react-router/types/app/routes/auth.login/+types/route.ts new file mode 100644 index 0000000..ed42796 --- /dev/null +++ b/.react-router/types/app/routes/auth.login/+types/route.ts @@ -0,0 +1,71 @@ +// Generated by React Router + +import type { GetInfo, GetAnnotations } from "react-router/internal"; + +type Module = typeof import("../route.js") + +type Info = GetInfo<{ + file: "routes/auth.login/route.tsx", + module: Module +}> + +type Matches = [{ + id: "root"; + module: typeof import("../../../root.js"); +}, { + id: "routes/auth.login"; + module: typeof import("../route.js"); +}]; + +type Annotations = GetAnnotations; + +export namespace Route { + // links + export type LinkDescriptors = Annotations["LinkDescriptors"]; + export type LinksFunction = Annotations["LinksFunction"]; + + // meta + export type MetaArgs = Annotations["MetaArgs"]; + export type MetaDescriptors = Annotations["MetaDescriptors"]; + export type MetaFunction = Annotations["MetaFunction"]; + + // headers + export type HeadersArgs = Annotations["HeadersArgs"]; + export type HeadersFunction = Annotations["HeadersFunction"]; + + // middleware + export type MiddlewareFunction = Annotations["MiddlewareFunction"]; + + // clientMiddleware + export type ClientMiddlewareFunction = Annotations["ClientMiddlewareFunction"]; + + // loader + export type LoaderArgs = Annotations["LoaderArgs"]; + + // clientLoader + export type ClientLoaderArgs = Annotations["ClientLoaderArgs"]; + + // action + export type ActionArgs = Annotations["ActionArgs"]; + + // clientAction + export type ClientActionArgs = Annotations["ClientActionArgs"]; + + // HydrateFallback + export type HydrateFallbackProps = Annotations["HydrateFallbackProps"]; + + // ServerHydrateFallback + export type ServerHydrateFallbackProps = Annotations["ServerHydrateFallbackProps"]; + + // Component + export type ComponentProps = Annotations["ComponentProps"]; + + // ServerComponent + export type ServerComponentProps = Annotations["ServerComponentProps"]; + + // ErrorBoundary + export type ErrorBoundaryProps = Annotations["ErrorBoundaryProps"]; + + // ServerErrorBoundary + export type ServerErrorBoundaryProps = Annotations["ServerErrorBoundaryProps"]; +} \ No newline at end of file diff --git a/app/services/invoice/composeInvoice.ts b/app/services/invoice/composeInvoice.ts index 255dcb2..9983f71 100644 --- a/app/services/invoice/composeInvoice.ts +++ b/app/services/invoice/composeInvoice.ts @@ -487,36 +487,49 @@ function mapTracking(order: RawOrderForInvoice): TrackingInfo[] { } /** - * Detects whether the order is a "local pickup" order. Pickup is detected - * heuristically from `shippingLine.{source,code,title,carrierIdentifier}`: + * Detects whether the order is a "local pickup" order using two signals: * - * - The Shopify Local Pickup app sets `shippingLine.code = "Pickup"` and - * uses the chosen pickup-location name as the shipping-line title — so - * the title doubles as the location name. - * - Merchants who model pickup as a custom shipping rate typically include - * "Abholung"/"Pickup" in the title or code. + * 1. Primary: `shippingLine.deliveryCategory` (e.g. `"pickup"`, + * `"local_pickup"`). This is what Shopify's Local Pickup app and any + * properly-categorised custom pickup rate set, and only requires the + * `read_orders` scope. + * 2. Fallback: regex on `shippingLine.{source,code,title,carrierIdentifier}` + * for merchants who model pickup as a custom shipping rate without a + * pickup category (e.g. titled "Abholung im Lager"). * - * (We deliberately do NOT query `Order.fulfillmentOrders.deliveryMethod` - * here: that field requires the `read_merchant_managed_fulfillment_orders` - * scope, which would force every install to re-grant permissions.) + * (We deliberately do NOT query `Order.fulfillmentOrders.deliveryMethod`: + * that field requires the `read_merchant_managed_fulfillment_orders` scope, + * which would force every install to re-grant permissions.) * - * Returns the pickup descriptor (with location name when known) or `null` - * when the order is a normal shipping order. Callers should not render the - * pickup-location address as a separate "delivery address". + * When pickup is detected, the location name is taken from + * `shippingLine.title` — for Shopify Local Pickup the title IS the chosen + * location name (e.g. "Lager Graz"). + * + * Returns the pickup descriptor or `null` when the order is a normal + * shipping order. Callers should not render the pickup-location address as + * a separate "delivery address". */ function detectPickup( order: RawOrderForInvoice, ): { locationName: string | null } | null { const sl = order.shippingLine; if (!sl) return null; + // Primary signal: shippingLine.deliveryCategory is "pickup" / "local_pickup" + // for any pickup-like fulfillment (set by Shopify's Local Pickup app and by + // custom apps that use the proper category). Doesn't require any extra scope. + const dc = (sl.deliveryCategory ?? "").toLowerCase(); + const isPickupCategory = dc.includes("pickup") || dc.includes("pick_up") || dc.includes("pick-up"); + // Fallback: string heuristic on title/code/source/carrier — covers + // merchants who model pickup as a custom shipping rate without category. const haystack = [sl.source, sl.code, sl.title, sl.carrierIdentifier] .filter(Boolean) .join(" ") .toLowerCase(); - if (!/pick[\s-]?up|abholung|abhol\b/.test(haystack)) return null; + const isPickupString = /pick[\s-]?up|abholung|abhol\b/.test(haystack); + if (!isPickupCategory && !isPickupString) return null; // For Shopify Local Pickup, `title` is the location name itself - // (e.g. "Lager Graz"). For custom-rate pickup ("Abholung im Lager"), - // it's a generic description — still better than nothing as a hint. + // (e.g. "Lager Graz"). For custom-rate pickup, it's a generic description + // — still better than nothing as a hint. return { locationName: sl.title?.trim() || null }; } diff --git a/app/services/invoice/loadOrderForInvoice.server.ts b/app/services/invoice/loadOrderForInvoice.server.ts index c3bc7a5..6dbb4c6 100644 --- a/app/services/invoice/loadOrderForInvoice.server.ts +++ b/app/services/invoice/loadOrderForInvoice.server.ts @@ -83,6 +83,10 @@ export interface RawShippingLine { code: string | null; source: string | null; carrierIdentifier: string | null; + /** Lowercase string like "shipping", "pickup", "local_pickup". Used as + * the primary pickup signal because it doesn't require the + * fulfillment-orders scope. */ + deliveryCategory: string | null; originalPriceSet: { shopMoney: RawMoney } | null; discountedPriceSet: { shopMoney: RawMoney } | null; taxLines: RawTaxLine[]; @@ -156,6 +160,7 @@ const QUERY = `#graphql code source carrierIdentifier + deliveryCategory originalPriceSet { shopMoney { amount currencyCode } } discountedPriceSet { shopMoney { amount currencyCode } } taxLines { diff --git a/scripts/render-sample.ts b/scripts/render-sample.ts index 6963ef5..f59df52 100644 --- a/scripts/render-sample.ts +++ b/scripts/render-sample.ts @@ -168,6 +168,7 @@ function buildAtB2BOrder(): RawOrderForInvoice { code: "STD", source: "shopify", carrierIdentifier: null, + deliveryCategory: "shipping", originalPriceSet: { shopMoney: { amount: "5.00", currencyCode: "EUR" } }, discountedPriceSet: { shopMoney: { amount: "5.00", currencyCode: "EUR" } }, taxLines: [ @@ -302,6 +303,25 @@ function buildPickupOrder(): RawOrderForInvoice { code: "Pickup", source: "shopify", carrierIdentifier: null, + deliveryCategory: "pickup", + originalPriceSet: { shopMoney: { amount: "0.00", currencyCode: "EUR" } }, + discountedPriceSet: { shopMoney: { amount: "0.00", currencyCode: "EUR" } }, + taxLines: [], + }; + return o; +} + +/** Pickup variant where neither title/code nor source mention "pickup" — + * detection must rely purely on `deliveryCategory`. Mirrors what we + * observed on a real Shopify Local Pickup install. */ +function buildCategoryOnlyPickupOrder(): RawOrderForInvoice { + const o = buildAtB2BOrder(); + o.shippingLine = { + title: "Lager Graz", + code: "Standard", + source: "shopify", + carrierIdentifier: null, + deliveryCategory: "pickup", originalPriceSet: { shopMoney: { amount: "0.00", currencyCode: "EUR" } }, discountedPriceSet: { shopMoney: { amount: "0.00", currencyCode: "EUR" } }, taxLines: [], @@ -622,6 +642,19 @@ async function main() { const pickupEnText = await pdfToText(await renderInvoicePdf(pickupEnVm)); assert("EN pickup PDF shows 'Pick-up location' label", pickupEnText.includes("Pick-up location")); + // Real-world pickup variant: shippingLine has no "pickup" keyword in + // title/code/source — only `deliveryCategory` says it's pickup. + const categoryPickupVm = composeInvoice({ + order: buildCategoryOnlyPickupOrder(), + settings: settings as never, + invoiceNumber: "RE-1033", + }); + assert("isPickup detected from deliveryCategory alone", categoryPickupVm.isPickup); + assertEq("pickupLocationName from title when category-only", + categoryPickupVm.pickupLocationName, "Lager Graz"); + assert("shippingMethod cleared in category-only pickup", + categoryPickupVm.shippingMethod == null); + // Fallback: when footerNoteEn is empty, English uses the German note. console.log("• Footer note fallback (en → de when EN empty)"); const settingsNoEn = { ...(settings as object), footerNoteEn: "" } as never;