-
Notifications
You must be signed in to change notification settings - Fork 2
feat(mongo): add retail store example app validating MongoDB target #327
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
wmadden
merged 60 commits into
main
from
tml-2185-port-retail-store-v2-e-commerce-app-to-prisma-next-mongodb
Apr 13, 2026
Merged
Changes from all commits
Commits
Show all changes
60 commits
Select commit
Hold shift + click to select a range
9afb914
restore project spec and plans onto tml-2220 base
wmadden eff9cad
scaffold retail-store example package
wmadden 4d1d9d6
add retail-store PSL contract with embedded value objects
wmadden e747561
add db factory, seed data, and seed script
wmadden 014011f
add data access layer and integration tests (M2)
wmadden 0bc9507
add array update operators via mongoRaw (M3)
wmadden 3d65a30
add aggregation pipelines for events and products (M4)
wmadden e6719bd
add Next.js API routes for products, cart, orders, locations (M5)
wmadden 89eabd9
add Next.js UI pages for e-commerce storefront (M5)
wmadden cb9d943
add vector search stub, README, and typecheck fixes (M6)
wmadden a27dc9f
expand README with remote MongoDB setup instructions
wmadden 400cb71
auto-write DEMO_USER_ID to .env during seed
wmadden f51d3bc
rename MONGODB_URL env var to DB_URL
wmadden 393c726
address code review findings F01-F10
wmadden b558c6b
add Tailwind CSS v4, shadcn-style UI components, and PostCSS config
wmadden 5f8ff32
add cookie-based auth: middleware, login page, signup/logout API routes
wmadden 8f40e25
expand seed to 24 products across 5 brands, remove DEMO_USER_ID auto-…
wmadden 2059e3a
rebuild catalog pages with Tailwind, add pagination + search
wmadden a2663c3
replace DEMO_USER_ID with cookie-based auth across all routes
wmadden 3786f90
add interactive cart: Add to Cart button, CartProvider context, navba…
wmadden 02ed01e
add checkout page with home delivery and BOPIS options
wmadden 13bfa4f
update README for interactive auth flow, add middleware.ts to tsconfig
wmadden 30fab35
fix CartProvider: move fetch out of useState initializer into useEffect
wmadden 6a02fcf
fix add-to-cart: create cart document when none exists for user
wmadden d52cbf2
fix: encode MongoParamRef values via codec registry in adapter
wmadden ea084d6
fix: ORM mutations attach codecId from contract to MongoParamRef
wmadden e07616c
test: add cart and order lifecycle integration tests
wmadden 28eacbc
refactor: eliminate silent no-op writes in cart and order data layer
wmadden a2e3beb
fix: add auth guards to order routes, clear cart server-side on checkout
wmadden c98484e
fix: remove dead code in checkout, use product image.url in cart payload
wmadden 4bb2672
refactor: add rawObjectIdFilter helper for consistent ObjectId handling
wmadden 38de260
test: add API flow integration tests for auth, checkout, and order st…
wmadden 76554b2
docs: clarify F13/F16 migration gap — planner only handles indexes, P…
wmadden f199758
refactor(retail-store): replace Event metadata bag with polymorphic v…
wmadden 881c9b2
feat(retail-store): add indexes to schema and commit first migration
wmadden 9956f7e
fix(retail-store): align runtime DB name with CLI config
wmadden 1ff5ffe
fix(retail-store): resolve type errors after rebase onto main index f…
wmadden 90c3e11
fix(retail-store): align seed script and README DB name to retail-store
wmadden de5b19c
docs: add F20 (embedded models) and F21 (polymorphism) to framework g…
wmadden a3a7ae3
fix(adapter-mongo): guard optional codec.encode before invocation
wmadden 14d805d
feat(retail-store): expand indexes with text search, TTL, hashed, col…
wmadden cddbf27
feat(retail-store): add db:reset script to drop all collections
wmadden bdf5d70
fix(mongo-contract-psl): handle nullable value objects in validator d…
wmadden 4315cb3
chore(retail-store): re-emit contract and re-plan migration with fixe…
wmadden fe20476
Add .gitignore
wmadden 97a0472
Add Mongo workstream next-steps plan with sequenced work areas
wmadden 7e0dc98
Remove code review artifacts from branch, keep locally
wmadden e15a03e
Format json with biome
wmadden eafa46c
add flat-illustration product images as static assets
wmadden 557f12f
update README domain model and framework gaps
wmadden 1e04e58
reduce String() noise in seed with lineItemFrom helper
wmadden 4d46dc3
replace module-scope Response singletons with factory functions
wmadden 8efe74c
enforce auth + ownership on order detail page, return 401 for API routes
wmadden 0b45594
check res.ok on all client-side fetch calls
wmadden 2b7b61c
add input validation to API routes and checkout form
wmadden 2b2db7c
enforce unique cart per user, add stable pagination sort, retry faile…
wmadden ffd0a9a
validate PATCH payload on order status route, fix README wording
wmadden 8459476
fix type casts and stale timer in order detail and add-to-cart
wmadden 45bb59d
fix migration test to expect unique index on Cart.userId
wmadden baf4c27
fix cart validation, string casts, unmount guard, and test accuracy
wmadden File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,225 @@ | ||
| # MongoDB Workstream — Next Steps | ||
|
|
||
| **Context**: The retail store example app (PR #327) stress-tested the Mongo target end-to-end and surfaced framework gaps documented in [projects/mongo-example-apps/framework-limitations.md](../../../projects/mongo-example-apps/framework-limitations.md). This plan consolidates those gaps with incomplete items from the [ORM consolidation](../../../projects/orm-consolidation/plan.md) and [schema migrations](../../../projects/mongo-schema-migrations/plan.md) project plans into a sequenced set of work areas. | ||
|
|
||
| **Linear project**: [WS4: MongoDB & Cross-Family Architecture](https://linear.app/prisma-company/project/ws4-mongodb-and-cross-family-architecture-89d4dcdbcd9a) | ||
|
|
||
| --- | ||
|
|
||
| ## Status snapshot (as of 2026-04-13) | ||
|
|
||
| ### ORM Consolidation | ||
|
|
||
| | Phase | Status | Linear | Notes | | ||
| |---|---|---|---| | ||
| | Phase 1 (Mongo Collection spike) | Done | TML-2189 | | | ||
| | Phase 1.5 M1-M3 (write ops, demo, tests) | Done | TML-2194 | | | ||
| | Phase 1.5 M4 (dot-path mutations `$push`/`$pull`/`$inc`) | **Deferred** | — | No ticket. Maps to FL-04. | | ||
| | Phase 1.5 M5 (unified query plan) | Done | | | | ||
| | Phase 1.6 (codec-owned value serialization) | Done | TML-2202 | | | ||
| | Phase 1.75a (typed JSON simplification) | Done | TML-2204 | Sub-task TML-2229 (no-emit path) still open, Urgent. | | ||
| | Phase 1.75b (polymorphism) | Done | TML-2205, TML-2227 | | | ||
| | Phase 1.75c (value objects & embedded docs) | Done | TML-2206 | `@@owner` in PSL not implemented (FL-12). | | ||
| | Phase 2 (shared interface extraction) | Not started | TML-2213 | Assigned to Alexey. | | ||
| | Phase 2.5 (pipeline builder) | Done | M9 milestone | | | ||
| | Layering reorganization | Done | TML-2201 | | | ||
|
|
||
| ### Schema Migrations | ||
|
|
||
| | Milestone | Status | Linear | Notes | | ||
| |---|---|---|---| | ||
| | M1 tasks 1.1–1.8 (SPI, types, IR, DDL, planner) | Done | TML-2220 | | | ||
| | M1 tasks 1.9–1.13 (runner, marker, wiring, E2E, demo) | **Not done** | — | Runner and target wiring never implemented. | | ||
| | M2 (full vocabulary + validators + PSL) | Done per Linear | TML-2231 | Has bugs: FL-09, FL-10, FL-11. | | ||
| | M3 (polymorphic indexes) | Not started | TML-2232 | | | ||
| | M4 (online CLI + live introspection) | In Progress | TML-2233 | | | ||
| | Data migrations | Not started | TML-2219 | Depends on WS1 (Saevar). | | ||
| | Manual migrations | Not started | TML-2244 | Depends on WS1 (Saevar). | | ||
|
|
||
| ### Example Apps (M10) | ||
|
|
||
| | App | Status | Linear | Notes | | ||
| |---|---|---|---| | ||
| | Retail store | Merging | TML-2185 | PR #327 ready to merge. | | ||
| | Predictive maintenance | Not started | TML-2186 | Blocked on framework gaps. | | ||
|
|
||
| ### Closeout Backlog | ||
|
|
||
| | Item | Status | Linear | Priority | | ||
| |---|---|---|---| | ||
| | No-emit path parameterized types | To-do | TML-2229 | Urgent | | ||
| | DML visitor pattern | To-do | TML-2234 | Low | | ||
| | Close out pipeline builder project | Backlog | TML-2236 | | | ||
| | Close out ORM consolidation project | Backlog | TML-2237 | | | ||
|
|
||
| --- | ||
|
|
||
| ## Framework limitations discovered by retail store | ||
|
|
||
| Full details in [projects/mongo-example-apps/framework-limitations.md](../../../projects/mongo-example-apps/framework-limitations.md). | ||
|
|
||
| | ID | Issue | Area | | ||
| |---|---|---| | ||
| | FL-01 | Scalar codec output types not assignable to `string`/`number` | Type ergonomics | | ||
| | FL-02 | `_id` codec output type not assignable to `string` | Type ergonomics | | ||
| | FL-03 | Timestamp codec type incompatible with `Date`/`string` | Type ergonomics | | ||
| | FL-04 | No typed `$push`/`$pull`/`$inc` | ORM mutations | | ||
| | FL-05 | Pipeline/raw results untyped | Query results | | ||
| | FL-06 | ObjectId filter requires manual `MongoParamRef` wrapping | ORM queries | | ||
| | FL-07 | No `$vectorSearch` in pipeline builder | Extension (deferred) | | ||
| | FL-08 | 1:N back-relation loading not available/tested | ORM queries | | ||
| | FL-09 | Migration planner creates separate collections for variants | Migration bugs | | ||
| | FL-10 | Variant collection validators incomplete | Migration bugs | | ||
| | FL-11 | `$jsonSchema` drops Float fields | Migration bugs | | ||
| | FL-12 | Embedded models via `@@owner` not in PSL | Schema authoring | | ||
| | FL-13 | TS DSL for Mongo not available | Schema authoring (WS2) | | ||
| | FL-14 | Change streams | Future (WS3 VP5) | | ||
| | FL-15 | Atlas Search requires extension pack | Future | | ||
|
|
||
| --- | ||
|
|
||
| ## Work areas (sequenced) | ||
|
|
||
| ### Area 1: Mongo type ergonomics (FL-01, FL-02, FL-03, TML-2229) | ||
|
|
||
| **Linear**: [TML-2245](https://linear.app/prisma-company/issue/TML-2245) | ||
|
|
||
| **Priority: Highest.** ~60 type casts in the retail store. Every ORM-to-application boundary is broken. | ||
|
|
||
| **Root cause**: The codec type map resolves `mongo/string@1`, `mongo/objectId@1`, and `mongo/dateTime@1` to opaque branded types instead of their underlying TypeScript primitives. The runtime values *are* the expected primitives — the types don't reflect that. | ||
|
|
||
| **Scope**: | ||
|
|
||
| - Fix Mongo scalar codec output types (`mongo/string@1` → `string`, `mongo/int32@1` → `number`, etc.) | ||
| - Fix `mongo/objectId@1` output type to be assignable to `string` | ||
| - Fix `mongo/dateTime@1` output type to be assignable to `Date` (or `string`, depending on what the codec actually returns at runtime) | ||
| - Complete TML-2229: restore parameterized output types in the no-emit path | ||
|
|
||
| **Proof**: The retail store compiles with zero `as string` / `as unknown as string` / `String()` casts on ORM results. | ||
|
|
||
| **Depends on**: Nothing. | ||
|
|
||
| **Blocks**: Area 2 benefits from this (fewer workarounds in where clauses). | ||
|
|
||
| ### Area 2: ORM query and mutation ergonomics (FL-04, FL-06, FL-08) | ||
|
|
||
| **Linear**: [TML-2246](https://linear.app/prisma-company/issue/TML-2246) | ||
|
|
||
| **Priority: High.** Users drop to `mongoRaw` for the most common mutation patterns. | ||
|
|
||
| **Scope**: | ||
|
|
||
| - **FL-04**: Implement dot-path field accessor mutations — `$push`, `$pull`, `$inc`, `$set` on nested paths via `u("field.path")` (deferred Phase 1.5 M4). Maps to [ADR 180](../../architecture%20docs/adrs/ADR%20180%20-%20Dot-path%20field%20accessor.md). | ||
| - **FL-06**: ORM `where()` should auto-encode ObjectId-typed fields. When a contract field has `codecId: 'mongo/objectId@1'`, the ORM should wrap the value in `MongoParamRef` automatically instead of requiring the user to construct it manually. | ||
| - **FL-08**: Validate and test 1:N back-relation loading via `include()`. If it works, add test coverage. If it doesn't, implement it. | ||
|
|
||
| **Proof**: The retail store's `mongoRaw` calls for cart add/remove and order status update are replaced with ORM `update()` calls. ObjectId filter helpers (`objectIdEq()`) are removed. | ||
|
|
||
| **Depends on**: Area 1 (type fixes reduce noise, but not a hard blocker). | ||
|
|
||
| ### Area 3: Migration planner bugs (FL-09, FL-10, FL-11) | ||
|
|
||
| **Linear**: [TML-2247](https://linear.app/prisma-company/issue/TML-2247) | ||
|
|
||
| **Priority: High.** Bugs in completed M2 work that produce incorrect migration operations. | ||
|
|
||
| **Scope**: | ||
|
|
||
| - **FL-09 + FL-10**: Fix polymorphic variant collection handling. Variant models that share their base model's collection (via `@@map` or implicit STI) must not produce separate `createCollection` operations. Validators for the shared collection must include all base + variant fields, not just variant-specific fields. | ||
| - **FL-11**: Fix `$jsonSchema` derivation to recognize `Float` scalar type. Fields typed as `Float` should produce `{ bsonType: "double" }` in the validator. | ||
|
|
||
| **Proof**: Running `migration plan` on the retail store contract produces correct operations — no spurious variant collections, validators include all fields, Float fields are present. | ||
|
|
||
| **Depends on**: Nothing. | ||
|
|
||
| **Blocks**: Area 4 (M3 polymorphic indexes depend on correct variant handling). | ||
|
|
||
| ### Area 4: Migration system completion (M1 runner + wiring, M3, M4) | ||
|
|
||
| **Linear**: [TML-2248](https://linear.app/prisma-company/issue/TML-2248) | ||
|
|
||
| **Priority: Medium.** The planner generates operations but they can't be applied. | ||
|
|
||
| **Scope**: | ||
|
|
||
| - **M1 tasks 1.9–1.11**: Implement `MongoMigrationRunner` (three-phase loop: precheck → execute → postcheck), marker/ledger in `_prisma_migrations` collection, wire Mongo target descriptor. | ||
| - **M1 tasks 1.12–1.13**: End-to-end proof (plan + apply single index against `mongodb-memory-server`), add migrations to example app. | ||
| - **M3** (TML-2232): Polymorphic partial index derivation — auto-generate `partialFilterExpression` scoped to discriminator values for variant-specific indexes. | ||
| - **M4** (TML-2233, already in progress): Online CLI commands + live introspection — `db init`, `db update`, `db verify`, `db sign`, `db schema`, `migration status --db`, `migration show`. | ||
|
|
||
| **Note**: Data migrations (TML-2219) and manual migrations (TML-2244) depend on WS1 (Saevar's migration system work on VP1/VP2). They are not sequenced here. | ||
|
|
||
| **Proof**: `migration plan` + `migration apply` works end-to-end against a real MongoDB instance for the retail store contract. Polymorphic collections get partial indexes. | ||
|
|
||
| **Depends on**: Area 3 (bug fixes must land first). | ||
|
|
||
| ### Area 5: Pipeline and raw query result typing (FL-05) | ||
|
|
||
| **Linear**: [TML-2249](https://linear.app/prisma-company/issue/TML-2249) | ||
|
|
||
| **Priority: Medium.** All pipeline/raw results are `unknown`, requiring manual type assertions. | ||
|
|
||
| **Scope**: | ||
|
|
||
| - Pipeline builder `build()` should produce a `MongoQueryPlan` that carries the inferred result type from the document shape tracking. | ||
| - `runtime.execute()` should propagate the result type from the query plan. | ||
| - `rawPipeline()` remains untyped (user asserts the return type) but should accept a type parameter for the result. | ||
|
|
||
| **Proof**: A pipeline builder chain like `.match(...).group(...).build()` produces a plan whose execution returns typed results without `as` casts. | ||
|
|
||
| **Depends on**: Nothing (can run in parallel with Areas 1-4). | ||
|
|
||
| ### Area 6: Schema authoring gaps (FL-12, FL-13) | ||
|
|
||
| **Linear**: [TML-2250](https://linear.app/prisma-company/issue/TML-2250) | ||
|
|
||
| **Priority: Lower.** Missing PSL features that limit what the example app can demonstrate. | ||
|
|
||
| **Scope**: | ||
|
|
||
| - **FL-12**: Add `@@owner` attribute to the Mongo PSL interpreter, enabling embedded entity declarations (as distinct from value objects). The contract schema and emitter already support `owner` — the gap is only in PSL authoring and ORM embedded entity CRUD. | ||
| - **FL-13**: TypeScript DSL for Mongo contract authoring. This depends on WS2 (Alberto's contract authoring workstream) delivering the new TS authoring surface. Not actionable until that surface exists. | ||
|
|
||
| **Proof (FL-12)**: A PSL schema can declare `model Comment { ... @@owner(Post) }` and the emitter produces a contract with the correct owner/embed relation. | ||
|
|
||
| **Depends on**: FL-13 depends on WS2. | ||
|
|
||
| --- | ||
|
|
||
| ## Sequencing | ||
|
|
||
| ``` | ||
| ┌─ Area 5 (pipeline typing) ── parallel | ||
| │ | ||
| Area 1 (type ergonomics) ───┐ ├─ Area 6 (schema authoring) ── parallel | ||
| ├───┤ | ||
| Area 3 (migration bugs) ────┘ └─ Area 4 (migration completion) | ||
| │ | ||
| Area 2 (ORM ergonomics) ────────────── │ ── can overlap with Area 1 | ||
| │ | ||
| ▼ | ||
| TML-2186 (predictive maintenance app) | ||
| │ | ||
| ▼ | ||
| Shared ORM interface (M8, with Alexey) | ||
| ``` | ||
|
|
||
| - **Areas 1 and 3** are independent and can start immediately in parallel. | ||
| - **Area 2** benefits from Area 1 landing but is not blocked by it. | ||
| - **Area 4** is blocked by Area 3 (migration bugs must be fixed first). | ||
| - **Areas 5 and 6** are independent and can run in parallel with everything. | ||
| - **TML-2186** (predictive maintenance app) validates fixes end-to-end; sequence after Areas 1-3. | ||
| - **M8** (shared ORM interface, Alexey) remains the final phase. | ||
|
|
||
| --- | ||
|
|
||
| ## Deferred (not in this sequence) | ||
|
|
||
| | Item | Reason | | ||
| |---|---| | ||
| | FL-07 ($vectorSearch) | Requires Atlas extension pack — separate project. | | ||
| | FL-14 (change streams) | Requires streaming subscription support (WS3 VP5). | | ||
| | FL-15 (Atlas Search) | Requires extension pack — separate project. | | ||
| | TML-2234 (DML visitor pattern) | Low-priority cleanup. | | ||
| | TML-2219 (data migrations) | Depends on WS1 VP1 (Saevar). | | ||
| | TML-2244 (manual migrations) | Depends on WS1 VP2 (Saevar). | | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| next-env.d.ts | ||
| .next |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,117 @@ | ||
| # Retail Store — Prisma Next MongoDB Example | ||
|
|
||
| An interactive e-commerce example application demonstrating Prisma Next's MongoDB capabilities with a Next.js frontend. | ||
|
|
||
| ## What This Demonstrates | ||
|
|
||
| | Feature | Implementation | | ||
| |---|---| | ||
| | **PSL contract with embedded value objects** | 8 `type` definitions (Price, Image, Address, CartItem, etc.) nested inside 7 models | | ||
| | **ORM CRUD** | `create`, `createAll`, `update`, `delete`, `upsert` via `@prisma-next/mongo-orm` | | ||
| | **Reference relations** | `include('user')` compiles to `$lookup` for cart→user, order→user, invoice→order | | ||
| | **Array update operators** | `$push`/`$pull` via `mongoRaw` for cart items and order status history | | ||
| | **Aggregation pipelines** | `$match`→`$group`→`$sort` for event analytics, `$sample` for random products | | ||
| | **Pipeline search** | `$regex` via `MongoOrExpr` + `MongoFieldFilter.of` for multi-field text search | | ||
| | **Pagination** | ORM `.skip(n).take(n)` for paginated product listing | | ||
| | **Vector search** | `findSimilarProducts` via `$vectorSearch` (requires Atlas cluster) | | ||
| | **Cookie-based auth** | Next.js middleware + signup/logout API routes with `userId` cookie | | ||
| | **Interactive cart** | Add to Cart, remove, clear — all backed by PN data layer + CartProvider context | | ||
| | **Checkout flow** | Home delivery vs BOPIS (Buy Online, Pick Up In Store) with location picker | | ||
| | **Order lifecycle** | Status progression (placed → shipped → delivered) via `$push` status entries | | ||
| | **Next.js integration** | Server-rendered pages, client components, REST API routes, Tailwind CSS v4 | | ||
|
|
||
| ## Quick Start (tests only — no external DB) | ||
|
|
||
| ```bash | ||
| # 1. Build framework packages (from repo root) | ||
| pnpm build | ||
|
|
||
| # 2. Emit contract | ||
| pnpm emit | ||
|
|
||
| # 3. Run tests (uses mongodb-memory-server) | ||
| pnpm test | ||
| ``` | ||
|
|
||
| ## Running with a Remote MongoDB Instance | ||
|
|
||
| To run the full app (UI + API) against a real MongoDB cluster: | ||
|
|
||
| **1. Create `.env` in `examples/retail-store/`:** | ||
|
|
||
| ```env | ||
| DB_URL=mongodb+srv://user:pass@your-cluster.mongodb.net | ||
| MONGODB_DB=retail-store | ||
| ``` | ||
|
|
||
| **2. Seed the database:** | ||
|
|
||
| ```bash | ||
| pnpm db:seed | ||
| ``` | ||
|
|
||
| This populates all 7 collections with 24 products across 5 brands, 4 store locations, and sample users/orders/events. | ||
|
|
||
| **3. Start the dev server:** | ||
|
|
||
| ```bash | ||
| pnpm dev | ||
| ``` | ||
|
|
||
| Open [http://localhost:3000](http://localhost:3000). You'll be redirected to the login page — click "Sign Up" to create a user and start browsing. | ||
|
|
||
| ### User Flow | ||
|
|
||
| 1. **Sign Up** → creates a user doc via ORM, sets `userId` cookie | ||
| 2. **Browse** → paginated product catalog (8 per page), search bar | ||
| 3. **Add to Cart** → click on a product, "Add to Cart" button | ||
| 4. **Cart** → view items, remove individual items, clear cart | ||
| 5. **Checkout** → choose home delivery or store pickup, place order | ||
| 6. **Orders** → view order history, advance status (placed → shipped → delivered) | ||
| 7. **Log Out** → clears cookie, redirects to sign-up | ||
|
|
||
| ### Vector Search (optional, Atlas only) | ||
|
|
||
| To test `findSimilarProducts`, create a vector search index named `product_embedding_index` on the `products` collection's `embedding` field in Atlas, and populate the `embedding` arrays with actual vectors (the seed data sets `embedding: null` by default). | ||
|
|
||
| ## Domain Model | ||
|
|
||
| ```text | ||
| Products ─── Price, Image (embedded value objects) | ||
| Users ─── Address? (optional embedded) | ||
| Carts ──→ User (reference relation), CartItem[] (embedded array) | ||
| Orders ──→ User (reference relation), OrderLineItem[], StatusEntry[] | ||
| Locations ─── flat fields | ||
| Invoices ──→ Order (reference relation), InvoiceLineItem[] | ||
| Events ─── polymorphic (@@discriminator on type) | ||
| ├── ViewProductEvent (productId, subCategory, brand) | ||
| ├── SearchEvent (query) | ||
| └── AddToCartEvent (productId, brand) | ||
| ``` | ||
|
|
||
| ## Project Structure | ||
|
|
||
| ```text | ||
| prisma/contract.prisma PSL schema with types and models | ||
| src/contract.json Generated contract (machine-readable) | ||
| src/contract.d.ts Generated types (compile-time safety) | ||
| src/db.ts Database factory (orm, runtime, pipeline, raw) | ||
| src/seed.ts Seed data for all 7 collections | ||
| src/data/ Data access layer (typed functions per collection) | ||
| src/lib/auth.ts Server-side auth helper (cookie-based) | ||
| src/lib/utils.ts cn() utility for Tailwind class merging | ||
| src/components/ Navbar, CartProvider, AddToCartButton, UI primitives | ||
| test/ Integration tests against mongodb-memory-server | ||
| app/ Next.js App Router (pages + API routes) | ||
| middleware.ts Auth middleware (redirects to /login) | ||
| ``` | ||
|
|
||
| ## Framework Gaps | ||
|
|
||
| - **Float scalar type**: Not in default Mongo PSL scalar descriptors; added via custom `scalarTypeDescriptors` in config | ||
| - **ObjectId in filters**: `MongoFieldFilter.eq` with ObjectId values requires wrapping in `MongoParamRef` (see `src/data/object-id-filter.ts`) | ||
| - **Schema migrations**: Migration artifacts are committed under `migrations/`; run `pnpm migration:apply` to apply. The planner handles indexes and collection validators but not all schema-level operations. | ||
| - **Typed `$push`/`$pull`**: ORM doesn't expose array update operators; use `mongoRaw` with untyped commands | ||
| - **Pipeline output types**: The pipeline builder doesn't propagate output types through aggregation stages; results are cast to expected shapes at the call site | ||
| - **Atlas Search**: Requires extension pack not yet available | ||
| - **Change Streams**: Not yet supported in the framework |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| import { cookies } from 'next/headers'; | ||
| import { NextResponse } from 'next/server'; | ||
|
|
||
| export async function POST() { | ||
| const cookieStore = await cookies(); | ||
| cookieStore.delete('userId'); | ||
| return NextResponse.json({ ok: true }); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| import { cookies } from 'next/headers'; | ||
| import { NextResponse } from 'next/server'; | ||
| import { createUser } from '../../../../src/data/users'; | ||
| import { getDb } from '../../../../src/db-singleton'; | ||
|
|
||
| export async function POST() { | ||
| const db = await getDb(); | ||
| const shortId = Math.random().toString(36).slice(2, 8); | ||
| const user = await createUser(db, { | ||
| name: `User-${shortId}`, | ||
| email: `user-${shortId}@demo.local`, | ||
| address: null, | ||
| }); | ||
|
|
||
| const cookieStore = await cookies(); | ||
| cookieStore.set('userId', String(user._id), { | ||
| path: '/', | ||
| httpOnly: true, | ||
| sameSite: 'lax', | ||
| maxAge: 60 * 60 * 24 * 30, | ||
| }); | ||
|
|
||
| return NextResponse.json({ id: String(user._id), name: user.name }); | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.