diff --git a/examples/stackblitz/README.md b/examples/stackblitz/README.md new file mode 100644 index 00000000..94394003 --- /dev/null +++ b/examples/stackblitz/README.md @@ -0,0 +1,15 @@ +# StitchAPI — StackBlitz templates + +Minimal, self-contained apps you can open and run in the browser — no local setup. Each +installs the published `@stitchapi/*` packages from npm and points at the public demo API +(`https://demo.stitchapi.dev`); edit `src/api.ts` to hit your own. + +| Template | What it shows | Open | +| ------------------------------------------------ | -------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | +| [`react-quickstart`](./react-quickstart) | `stitch()` + `useStitch` — declare an endpoint once, call it as a hook | [StackBlitz](https://stackblitz.com/github/rejifald/StitchAPI/tree/main/examples/stackblitz/react-quickstart) | +| [`react-tanstack-query`](./react-tanstack-query) | `stitchQueryOptions` — a stitch as a TanStack Query `queryFn` (complement, not a competitor) | [StackBlitz](https://stackblitz.com/github/rejifald/StitchAPI/tree/main/examples/stackblitz/react-tanstack-query) | + +> The StackBlitz links resolve against `main`, so they go live once this lands. Until then, +> run any template locally with `npm install && npm run dev`. + +Docs & live playground: . diff --git a/examples/stackblitz/react-quickstart/.stackblitzrc b/examples/stackblitz/react-quickstart/.stackblitzrc new file mode 100644 index 00000000..d98146f4 --- /dev/null +++ b/examples/stackblitz/react-quickstart/.stackblitzrc @@ -0,0 +1,4 @@ +{ + "installDependencies": true, + "startCommand": "npm run dev" +} diff --git a/examples/stackblitz/react-quickstart/README.md b/examples/stackblitz/react-quickstart/README.md new file mode 100644 index 00000000..aade19ef --- /dev/null +++ b/examples/stackblitz/react-quickstart/README.md @@ -0,0 +1,23 @@ +# StitchAPI — React quick start + +The smallest useful `@stitchapi/react` app: declare an endpoint once with `stitch()`, call it +through `useStitch`, render the typed result. + +[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/rejifald/StitchAPI/tree/main/examples/stackblitz/react-quickstart) + +## Run locally + +```bash +npm install +npm run dev +``` + +## What to look at + +- **`src/api.ts`** — the whole API layer: `stitch('https://demo.stitchapi.dev/users')`. + Point it at your own URL. Add `output:` (a Zod/Standard Schema) to also validate the response. +- **`src/App.tsx`** — `useStitch(getUsers, {})` returns `{ data, isPending, isError, refetch }` + and re-renders on each transition. + +Streaming? Swap `useStitch` for `useStitchStream` and read `chunks` / `isStreaming` — the UI +re-renders as response deltas arrive. See . diff --git a/examples/stackblitz/react-quickstart/index.html b/examples/stackblitz/react-quickstart/index.html new file mode 100644 index 00000000..ee1b3cae --- /dev/null +++ b/examples/stackblitz/react-quickstart/index.html @@ -0,0 +1,12 @@ + + + + + + StitchAPI · React quick start + + +
+ + + diff --git a/examples/stackblitz/react-quickstart/package.json b/examples/stackblitz/react-quickstart/package.json new file mode 100644 index 00000000..0da24080 --- /dev/null +++ b/examples/stackblitz/react-quickstart/package.json @@ -0,0 +1,25 @@ +{ + "name": "stitchapi-react-quickstart", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "stitchapi": "1.0.0-rc.4", + "@stitchapi/query-core": "1.0.0-rc.4", + "@stitchapi/react": "1.0.0-rc.4", + "react": "^18.3.1", + "react-dom": "^18.3.1" + }, + "devDependencies": { + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", + "@vitejs/plugin-react": "^4.3.1", + "typescript": "^5.5.4", + "vite": "^5.4.0" + } +} diff --git a/examples/stackblitz/react-quickstart/src/App.tsx b/examples/stackblitz/react-quickstart/src/App.tsx new file mode 100644 index 00000000..17ccdec9 --- /dev/null +++ b/examples/stackblitz/react-quickstart/src/App.tsx @@ -0,0 +1,50 @@ +import { getUsers } from './api'; + +import { useStitch } from '@stitchapi/react'; + +export default function App() { + // useStitch runs the stitch on mount and re-renders on every transition + // (pending → success/error). `refetch` re-runs it from scratch. + const { data, isPending, isError, refetch } = useStitch(getUsers, {}); + + return ( +
+

+ @stitchapi/react — quick start +

+

+ One stitch() declaration, called through{' '} + useStitch. Edit src/api.ts to point at + your own API. +

+ + {isPending &&

Loading…

} + + {isError && ( +

+ Request failed.{' '} + +

+ )} + +
    + {data?.map((u) => ( +
  • + {u.name} —{' '} + {u.email} +
  • + ))} +
+
+ ); +} diff --git a/examples/stackblitz/react-quickstart/src/api.ts b/examples/stackblitz/react-quickstart/src/api.ts new file mode 100644 index 00000000..4ac3a947 --- /dev/null +++ b/examples/stackblitz/react-quickstart/src/api.ts @@ -0,0 +1,12 @@ +import { stitch } from 'stitchapi'; + +export interface User { + id: number; + name: string; + email: string; +} + +// A stitch is an endpoint declared once and called like a local function — +// no client instance, no codegen, no config files. The explicit generic types +// the parsed JSON result; swap it for an `output:` schema to also validate it. +export const getUsers = stitch('https://demo.stitchapi.dev/users'); diff --git a/examples/stackblitz/react-quickstart/src/main.tsx b/examples/stackblitz/react-quickstart/src/main.tsx new file mode 100644 index 00000000..e2367e8e --- /dev/null +++ b/examples/stackblitz/react-quickstart/src/main.tsx @@ -0,0 +1,10 @@ +import App from './App'; + +import React from 'react'; +import { createRoot } from 'react-dom/client'; + +createRoot(document.getElementById('root')!).render( + + + , +); diff --git a/examples/stackblitz/react-quickstart/tsconfig.json b/examples/stackblitz/react-quickstart/tsconfig.json new file mode 100644 index 00000000..4c311e07 --- /dev/null +++ b/examples/stackblitz/react-quickstart/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + "strict": true + }, + "include": ["src", "vite.config.ts"] +} diff --git a/examples/stackblitz/react-quickstart/vite.config.ts b/examples/stackblitz/react-quickstart/vite.config.ts new file mode 100644 index 00000000..67eb09f7 --- /dev/null +++ b/examples/stackblitz/react-quickstart/vite.config.ts @@ -0,0 +1,6 @@ +import react from '@vitejs/plugin-react'; +import { defineConfig } from 'vite'; + +export default defineConfig({ + plugins: [react()], +}); diff --git a/examples/stackblitz/react-tanstack-query/.stackblitzrc b/examples/stackblitz/react-tanstack-query/.stackblitzrc new file mode 100644 index 00000000..d98146f4 --- /dev/null +++ b/examples/stackblitz/react-tanstack-query/.stackblitzrc @@ -0,0 +1,4 @@ +{ + "installDependencies": true, + "startCommand": "npm run dev" +} diff --git a/examples/stackblitz/react-tanstack-query/README.md b/examples/stackblitz/react-tanstack-query/README.md new file mode 100644 index 00000000..d853c326 --- /dev/null +++ b/examples/stackblitz/react-tanstack-query/README.md @@ -0,0 +1,24 @@ +# StitchAPI as a TanStack Query `queryFn` + +StitchAPI does not compete with TanStack Query — it fills the `queryFn`. `stitchQueryOptions` +turns a `stitch()` into a plain TanStack Query options object (`queryKey` + `queryFn`), so +TanStack Query keeps owning caching and revalidation while the stitch supplies a typed, +validated, streaming-first fetcher. + +[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/rejifald/StitchAPI/tree/main/examples/stackblitz/react-tanstack-query) + +## Run locally + +```bash +npm install +npm run dev +``` + +## What to look at + +- **`src/api.ts`** — one `stitch()` declaration, identical to the plain quick start. +- **`src/App.tsx`** — `useQuery(stitchQueryOptions(getUsers, {}))`. No `@tanstack/react-query` + import is needed inside StitchAPI: `stitchQueryOptions` returns a POJO, so it stays an + optional peer. + +More: . diff --git a/examples/stackblitz/react-tanstack-query/index.html b/examples/stackblitz/react-tanstack-query/index.html new file mode 100644 index 00000000..5d10c443 --- /dev/null +++ b/examples/stackblitz/react-tanstack-query/index.html @@ -0,0 +1,12 @@ + + + + + + StitchAPI · TanStack Query queryFn + + +
+ + + diff --git a/examples/stackblitz/react-tanstack-query/package.json b/examples/stackblitz/react-tanstack-query/package.json new file mode 100644 index 00000000..59c627f6 --- /dev/null +++ b/examples/stackblitz/react-tanstack-query/package.json @@ -0,0 +1,26 @@ +{ + "name": "stitchapi-react-tanstack-query", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "stitchapi": "1.0.0-rc.4", + "@stitchapi/query-core": "1.0.0-rc.4", + "@stitchapi/react": "1.0.0-rc.4", + "@tanstack/react-query": "^5.51.0", + "react": "^18.3.1", + "react-dom": "^18.3.1" + }, + "devDependencies": { + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", + "@vitejs/plugin-react": "^4.3.1", + "typescript": "^5.5.4", + "vite": "^5.4.0" + } +} diff --git a/examples/stackblitz/react-tanstack-query/src/App.tsx b/examples/stackblitz/react-tanstack-query/src/App.tsx new file mode 100644 index 00000000..6ffe4c12 --- /dev/null +++ b/examples/stackblitz/react-tanstack-query/src/App.tsx @@ -0,0 +1,71 @@ +import { getUsers } from './api'; + +import { stitchQueryOptions } from '@stitchapi/react'; +import { + QueryClient, + QueryClientProvider, + useQuery, +} from '@tanstack/react-query'; + +const queryClient = new QueryClient(); + +function Users() { + // stitchQueryOptions(stitch, input) returns a plain TanStack Query options object + // (queryKey + queryFn). TanStack Query keeps owning caching and revalidation; + // the stitch supplies a typed, validated, streaming-first fetcher. + const { data, isPending, isError, refetch } = useQuery( + stitchQueryOptions(getUsers, {}), + ); + + return ( +
+

+ StitchAPI as a TanStack Query queryFn +

+

+ stitchQueryOptions(getUsers, {'{}'}) plugs the + stitch into useQuery. No competing cache — TanStack + owns it. +

+ + {isPending &&

Loading…

} + + {isError && ( +

+ Request failed.{' '} + +

+ )} + +
    + {data?.map((u) => ( +
  • + {u.name} —{' '} + {u.email} +
  • + ))} +
+
+ ); +} + +export default function App() { + return ( + + + + ); +} diff --git a/examples/stackblitz/react-tanstack-query/src/api.ts b/examples/stackblitz/react-tanstack-query/src/api.ts new file mode 100644 index 00000000..25c9fbf9 --- /dev/null +++ b/examples/stackblitz/react-tanstack-query/src/api.ts @@ -0,0 +1,11 @@ +import { stitch } from 'stitchapi'; + +export interface User { + id: number; + name: string; + email: string; +} + +// The same endpoint declaration as the plain quick start. Here it feeds TanStack +// Query as the queryFn — StitchAPI does not replace TanStack Query, it fills it. +export const getUsers = stitch('https://demo.stitchapi.dev/users'); diff --git a/examples/stackblitz/react-tanstack-query/src/main.tsx b/examples/stackblitz/react-tanstack-query/src/main.tsx new file mode 100644 index 00000000..e2367e8e --- /dev/null +++ b/examples/stackblitz/react-tanstack-query/src/main.tsx @@ -0,0 +1,10 @@ +import App from './App'; + +import React from 'react'; +import { createRoot } from 'react-dom/client'; + +createRoot(document.getElementById('root')!).render( + + + , +); diff --git a/examples/stackblitz/react-tanstack-query/tsconfig.json b/examples/stackblitz/react-tanstack-query/tsconfig.json new file mode 100644 index 00000000..4c311e07 --- /dev/null +++ b/examples/stackblitz/react-tanstack-query/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + "strict": true + }, + "include": ["src", "vite.config.ts"] +} diff --git a/examples/stackblitz/react-tanstack-query/vite.config.ts b/examples/stackblitz/react-tanstack-query/vite.config.ts new file mode 100644 index 00000000..67eb09f7 --- /dev/null +++ b/examples/stackblitz/react-tanstack-query/vite.config.ts @@ -0,0 +1,6 @@ +import react from '@vitejs/plugin-react'; +import { defineConfig } from 'vite'; + +export default defineConfig({ + plugins: [react()], +});