Add MSW + React CRUD reference implementation#165
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
- Create objectstack.config.ts for declarative data model - Replace manual MSW handlers with auto-mocking MSWPlugin - Reduce browser.ts from 145 lines to 20 lines (86% reduction) - Add @objectstack/runtime dependency - Update QUICKSTART.md with simplified approach Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
- Create objectstack.config.ts for declarative data model - Add helper function to auto-generate MSW handlers from runtime - Remove plugin-msw dependency (browser incompatibility) - Update package.json and vite.config - Note: Vite workspace resolution issue with dynamic imports needs fix Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
|
This PR is very large. Consider breaking it into smaller PRs for easier review. |
- Create objectstack.config.ts for declarative data model - Add createMockHandlers.ts helper for auto-generating MSW handlers - Simplify browser.ts to 40 lines (from 145 lines = 72% reduction) - Remove complex runtime dependencies - Support client path compatibility (/api/v1/api/v1) - Tested and verified: Full CRUD operations working - Update QUICKSTART.md with simplified approach Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
…on-example-again
|
This PR is very large. Consider breaking it into smaller PRs for easier review. |
There was a problem hiding this comment.
Pull request overview
This PR adds a full React + MSW CRUD example wired to @objectstack/client, and wires the new example into the workspace configuration.
Changes:
- Adds the
examples/ui/msw-react-crudVite+React+TypeScript app, including task CRUD components, MSW browser setup, and anobjectstack.config.ts-driven mock API. - Updates
pnpm-workspace.yamlandpnpm-lock.yamlto register the new example and its dependencies (React 18, Vite, MSW). - Documents the example with README, QUICKSTART, and CHANGELOG files plus local tooling config (
tsconfig*,.gitignore).
Reviewed changes
Copilot reviewed 20 out of 21 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| pnpm-workspace.yaml | Registers examples/ui/* (including this example) as workspace packages and marks msw in onlyBuiltDependencies for consistent tooling. |
| pnpm-lock.yaml | Locks new dependencies for the example (React 18, Vite, MSW, plugin tooling) so the workspace installs reproducibly. |
| examples/ui/msw-react-crud/vite.config.ts | Defines Vite config for the example (React plugin, dev server on port 3000, and pre-bundling for msw modules). |
| examples/ui/msw-react-crud/tsconfig.node.json | TypeScript config for Node-side files (Vite config), aligned with ESNext/bundler resolution. |
| examples/ui/msw-react-crud/tsconfig.json | Strict TS config for the app source, enabling React JSX and common bundler-focused options. |
| examples/ui/msw-react-crud/src/types.ts | Declares Task, CreateTaskInput, and UpdateTaskInput interfaces to type CRUD operations in the UI. |
| examples/ui/msw-react-crud/src/mocks/createMockHandlers.ts | Implements an in-memory store and generates MSW handlers for discovery, metadata, and data CRUD endpoints from metadata. |
| examples/ui/msw-react-crud/src/mocks/browser.ts | Wires MSW browser worker startup, seeds initial task data, builds metadata from objectstack.config.ts, and starts the worker. |
| examples/ui/msw-react-crud/src/main.tsx | Bootstraps the app by starting the MSW worker and then rendering the React root component. |
| examples/ui/msw-react-crud/src/components/TaskList.tsx | React component that uses @objectstack/client to READ tasks, render a list, and perform delete/toggle-complete operations. |
| examples/ui/msw-react-crud/src/components/TaskItem.tsx | Presentational component for a single task row (priority badges, created date, edit/delete actions). |
| examples/ui/msw-react-crud/src/components/TaskForm.tsx | React form component demonstrating CREATE and UPDATE via @objectstack/client with basic validation and UX states. |
| examples/ui/msw-react-crud/src/App.tsx | High-level app shell that initializes the ObjectStack client, manages editing state, and composes TaskForm + TaskList. |
| examples/ui/msw-react-crud/src/App.css | Provides all layout and styling for the example (headers, task cards, buttons, states). |
| examples/ui/msw-react-crud/package.json | Defines the example package, its scripts, and runtime/dev dependencies (React 18, Vite 5, TypeScript, MSW, ObjectStack packages). |
| examples/ui/msw-react-crud/objectstack.config.ts | Declares the task object and basic app/navigation metadata used by the mock layer and to mirror ObjectStack conventions. |
| examples/ui/msw-react-crud/index.html | Basic HTML shell used by Vite to mount the React app at #root. |
| examples/ui/msw-react-crud/README.md | Main documentation for the example (features, structure, setup, API usage, and related resources); currently has minor mismatches with package.json and example paths. |
| examples/ui/msw-react-crud/QUICKSTART.md | Quick start guide that currently describes a plugin-based MSW integration; this does not match the manual handler approach used in this example. |
| examples/ui/msw-react-crud/CHANGELOG.md | Records the initial 1.0.0 release of the MSW + React CRUD example and its feature set. |
| examples/ui/msw-react-crud/.gitignore | Ignores node modules, build artifacts, editor/OS cruft, and the generated public/mockServiceWorker.js for this example. |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
|
|
||
| store.delete(id); | ||
|
|
||
| return HttpResponse.json({ success: true }, { status: 204 }); |
There was a problem hiding this comment.
The DELETE handler returns a 204 No Content status while still including a JSON body ({ success: true }), which is inconsistent with HTTP semantics and may confuse some clients or tooling. Consider either returning a 200 status with the JSON body, or keeping 204 and omitting the response body.
| return HttpResponse.json({ success: true }, { status: 204 }); | |
| return HttpResponse.json({ success: true }, { status: 200 }); |
| const top = parseInt(url.searchParams.get('top') || '100'); | ||
| const skip = parseInt(url.searchParams.get('$skip') || '0'); | ||
|
|
||
| const records = Array.from(store.values()); | ||
| const paginatedRecords = records.slice(skip, skip + top); | ||
|
|
||
| return HttpResponse.json({ | ||
| '@odata.context': `${baseUrl}/data/$metadata#${objectName}`, | ||
| value: paginatedRecords, | ||
| count: records.length |
There was a problem hiding this comment.
The list handler ignores sort-related query parameters, but TaskList calls client.data.find('task', { top: 100, sort: ['priority', '-createdAt'] }), so the example UI suggests sorted results that the mock API does not actually implement. Either implement sorting in this handler (e.g., honoring the sort parameter) or remove the sort option from the client call so behavior matches the example.
| - **@objectstack/plugin-msw** - MSW integration for ObjectStack | ||
| - **react** - UI library | ||
| - **msw** - Mock Service Worker for API mocking | ||
| - **vite** - Build tool and dev server | ||
| - **typescript** - Type safety | ||
|
|
There was a problem hiding this comment.
This dependencies list mentions @objectstack/plugin-msw, but this example's package.json does not declare or use that package, which can mislead users about required dependencies. Either add @objectstack/plugin-msw to this example's dependencies (and integrate it), or update the README to remove or clearly qualify this item.
| - **@objectstack/plugin-msw** - MSW integration for ObjectStack | |
| - **react** - UI library | |
| - **msw** - Mock Service Worker for API mocking | |
| - **vite** - Build tool and dev server | |
| - **typescript** - Type safety | |
| - **react** - UI library | |
| - **msw** - Mock Service Worker for API mocking | |
| - **vite** - Build tool and dev server | |
| - **typescript** - Type safety | |
| > Optional: **@objectstack/plugin-msw** provides a higher-level MSW integration for ObjectStack, but this example uses plain `msw` and does **not** require the plugin. For plugin usage, see the related `/examples/msw-demo`. |
| - [`/examples/msw-demo`](../../../msw-demo) - MSW plugin integration examples | ||
| - [`/examples/todo`](../../../todo) - Todo app with ObjectStack Client |
There was a problem hiding this comment.
The relative links to /examples/msw-demo and /examples/todo appear to be incorrect: from examples/ui/msw-react-crud/README.md, ../../../msw-demo and ../../../todo resolve to the repo root, while these examples live under examples/msw-demo and examples/todo. Updating these to ../../msw-demo and ../../todo (or using absolute paths from the repo root) would make the links work.
| - [`/examples/msw-demo`](../../../msw-demo) - MSW plugin integration examples | |
| - [`/examples/todo`](../../../todo) - Todo app with ObjectStack Client | |
| - [`/examples/msw-demo`](../../msw-demo) - MSW plugin integration examples | |
| - [`/examples/todo`](../../todo) - Todo app with ObjectStack Client |
| # Quick Start Guide - Simplified MSW Integration | ||
|
|
||
| This is the **simplified** version using `@objectstack/plugin-msw` that auto-mocks all API endpoints. No manual handler code required! | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| - Node.js 18 or later | ||
| - pnpm package manager | ||
|
|
||
| ## Step 1: Install Dependencies | ||
|
|
||
| From the repository root: | ||
|
|
||
| ```bash | ||
| pnpm install | ||
| ``` | ||
|
|
||
| ## Step 2: Build Required Packages | ||
|
|
||
| Build the core packages: | ||
|
|
||
| ```bash | ||
| # Build all required packages | ||
| pnpm --filter @objectstack/spec build | ||
| pnpm --filter @objectstack/runtime build | ||
| pnpm --filter @objectstack/plugin-msw build | ||
| pnpm --filter @objectstack/client build | ||
| ``` | ||
|
|
||
| ## Step 3: Initialize MSW | ||
|
|
||
| The MSW service worker file should already be initialized: | ||
|
|
||
| ```bash | ||
| cd examples/ui/msw-react-crud | ||
| npx msw init public/ --save | ||
| ``` | ||
|
|
||
| ## Step 4: Start the Development Server | ||
|
|
||
| ```bash | ||
| cd examples/ui/msw-react-crud | ||
| pnpm dev | ||
| ``` | ||
|
|
||
| The application will start on `http://localhost:3000` | ||
|
|
||
| ## ✨ What's Different? | ||
|
|
||
| ### Before (Manual Approach) ❌ | ||
|
|
||
| You had to manually write 145+ lines of MSW handlers: | ||
|
|
||
| ```typescript | ||
| // src/mocks/browser.ts - OLD WAY | ||
| const handlers = [ | ||
| http.get('/api/v1/data/task', ({ request }) => { | ||
| // Manual pagination, filtering, sorting... | ||
| }), | ||
| http.post('/api/v1/data/task', async ({ request }) => { | ||
| // Manual ID generation, validation... | ||
| }), | ||
| // ... more manual handlers | ||
| ]; | ||
| const worker = setupWorker(...handlers); | ||
| await worker.start(); | ||
| ``` | ||
|
|
||
| ### After (Plugin Approach) ✅ | ||
|
|
||
| Now just **3 lines** with auto-mocking: | ||
|
|
||
| ```typescript | ||
| // src/mocks/browser.ts - NEW WAY | ||
| const mswPlugin = new MSWPlugin({ baseUrl: '/api/v1' }); | ||
| const runtime = new ObjectStackKernel([appConfig, mswPlugin]); | ||
| await runtime.start(); // Auto-mocks ALL endpoints! | ||
| ``` |
There was a problem hiding this comment.
This QUICKSTART describes a "simplified" setup using @objectstack/plugin-msw (MSWPlugin, ObjectStackKernel, auto-mocked endpoints), but the actual example code in this folder uses manual MSW handlers via createMockHandlers and does not reference the plugin. Consider either updating the Quick Start to match the current implementation, or clearly scoping it as an alternative plugin-based approach and pointing to the appropriate example and required dependencies.
Demonstrates complete MSW browser integration with React components performing CRUD operations via
@objectstack/client.Implementation
New Example:
examples/ui/msw-react-crud/@objectstack/clientSDK methodsStack: React 18 + TypeScript + Vite + MSW 2.0
Documentation: README (API patterns, endpoint mapping), QUICKSTART (setup), CHANGELOG
Configuration
Updated
pnpm-workspace.yamlto includeexamples/ui/*packages for proper workspace resolution.Original prompt
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.