@@ -71,25 +71,25 @@ The `Allow` header is also set for HTTP compliance.
7171The frontend can fetch the schema at runtime and generate form fields
7272automatically. The schema provides:
7373
74- | JSON Schema keyword | Form behavior |
75- | ------------------------- | ---------------------------------------------- |
76- | ` type: "string" ` | ` <input type="text"> ` |
77- | ` format: "email" ` | ` <input type="email"> ` |
78- | ` format: "date-time" ` | ` <input type="datetime-local"> ` |
79- | ` enum: [...] ` | ` <select> ` with options |
80- | ` minLength ` / ` maxLength ` | Validation constraints |
81- | ` readOnly: true ` | Field displayed but not editable |
82- | ` required: [...] ` | Native ` required ` attribute + visual indicator |
74+ | JSON Schema keyword | Form behavior |
75+ | ---| ---|
76+ | ` type: "string" ` | ` <input type="text"> ` |
77+ | ` format: "email" ` | ` <input type="email"> ` |
78+ | ` format: "date-time" ` | ` <input type="datetime-local"> ` |
79+ | ` enum: [...] ` | ` <select> ` with options |
80+ | ` minLength ` / ` maxLength ` | Validation constraints |
81+ | ` readOnly: true ` | Field displayed but not editable |
82+ | ` required: [...] ` | Native ` required ` attribute + visual indicator |
8383
8484JSON Schema constraints map directly to HTML validation attributes:
8585
8686| JSON Schema | HTML attribute |
87- | ----------- | -------------- |
88- | ` minLength ` | ` minlength ` |
89- | ` maxLength ` | ` maxlength ` |
90- | ` minimum ` | ` min ` |
91- | ` maximum ` | ` max ` |
92- | ` pattern ` | ` pattern ` |
87+ | ---| ---|
88+ | ` minLength ` | ` minlength ` |
89+ | ` maxLength ` | ` maxlength ` |
90+ | ` minimum ` | ` min ` |
91+ | ` maximum ` | ` max ` |
92+ | ` pattern ` | ` pattern ` |
9393
9494The browser's native constraint validation API enforces these — no custom
9595JS validation needed for client-side checks.
@@ -116,13 +116,13 @@ The `schema-form` component maps `fields` entries to the corresponding
116116
117117### Error Response Contract
118118
119- | Status | Body | Meaning |
120- | ------ | ------------------- | --------------------------------------------------- |
121- | ` 422 ` | ` { error, fields } ` | Validation failed — ` fields ` maps names to messages |
122- | ` 404 ` | ` { error } ` | Entity or collection not found |
123- | ` 201 ` | Entity JSON | Created successfully |
124- | ` 200 ` | Entity JSON | Updated successfully |
125- | ` 204 ` | Empty | Deleted successfully |
119+ | Status | Body | Meaning |
120+ | ---| ---| ---|
121+ | ` 422 ` | ` { error, fields } ` | Validation failed — ` fields ` maps names to messages |
122+ | ` 404 ` | ` { error } ` | Entity or collection not found |
123+ | ` 201 ` | Entity JSON | Created successfully |
124+ | ` 200 ` | Entity JSON | Updated successfully |
125+ | ` 204 ` | Empty | Deleted successfully |
126126
127127This allows a single generic ` schema-form ` component to render any entity's
128128create/edit form without entity-specific template code.
@@ -135,12 +135,12 @@ create/edit form without entity-specific template code.
135135
136136Query params for filtering, sorting, pagination:
137137
138- | Param | Example | Purpose |
139- | -------- | ------------------ | ------------------------------- |
140- | ` limit ` | ` ?limit=20 ` | Page size (default: 20) |
141- | ` offset ` | ` ?offset=40 ` | Skip N records |
142- | ` sort ` | ` ?sort=-createdAt ` | Sort field, ` - ` prefix for desc |
143- | ` filter ` | ` ?role=admin ` | Field equality filter |
138+ | Param | Example | Purpose |
139+ | ---| ---| ---|
140+ | ` limit ` | ` ?limit=20 ` | Page size (default: 20) |
141+ | ` offset ` | ` ?offset=40 ` | Skip N records |
142+ | ` sort ` | ` ?sort=-createdAt ` | Sort field, ` - ` prefix for desc |
143+ | ` filter ` | ` ?role=admin ` | Field equality filter |
144144
145145Response:
146146
@@ -201,11 +201,11 @@ event: update
201201data: {"type":"user","id":"2","action":"deleted"}
202202```
203203
204- | Field | Value |
205- | -------- | ------------------------------------------------- |
206- | ` type ` | Entity name (lowercase, singular): ` user ` , ` post ` |
207- | ` id ` | Entity ID that changed |
208- | ` action ` | ` created ` , ` updated ` , or ` deleted ` |
204+ | Field | Value |
205+ | ---| ---|
206+ | ` type ` | Entity name (lowercase, singular): ` user ` , ` post ` |
207+ | ` id ` | Entity ID that changed |
208+ | ` action ` | ` created ` , ` updated ` , or ` deleted ` |
209209
210210### Frontend Integration
211211
@@ -227,44 +227,11 @@ required.
227227const db = new Map ();
228228
229229// Seed with dummy users
230- db .set (
231- ' users' ,
232- new Map ([
233- [
234- ' 1' ,
235- {
236- id: ' 1' ,
237- firstName: ' Jane' ,
238- lastName: ' Doe' ,
239- email: ' jane@example.com' ,
240- role: ' admin' ,
241- createdAt: ' 2024-01-15T09:00:00Z' ,
242- },
243- ],
244- [
245- ' 2' ,
246- {
247- id: ' 2' ,
248- firstName: ' John' ,
249- lastName: ' Smith' ,
250- email: ' john@example.com' ,
251- role: ' editor' ,
252- createdAt: ' 2024-02-20T14:30:00Z' ,
253- },
254- ],
255- [
256- ' 3' ,
257- {
258- id: ' 3' ,
259- firstName: ' Alex' ,
260- lastName: ' Chen' ,
261- email: ' alex@example.com' ,
262- role: ' viewer' ,
263- createdAt: ' 2024-03-10T11:15:00Z' ,
264- },
265- ],
266- ]),
267- );
230+ db .set (' users' , new Map ([
231+ [' 1' , { id: ' 1' , firstName: ' Jane' , lastName: ' Doe' , email: ' jane@example.com' , role: ' admin' , createdAt: ' 2024-01-15T09:00:00Z' }],
232+ [' 2' , { id: ' 2' , firstName: ' John' , lastName: ' Smith' , email: ' john@example.com' , role: ' editor' , createdAt: ' 2024-02-20T14:30:00Z' }],
233+ [' 3' , { id: ' 3' , firstName: ' Alex' , lastName: ' Chen' , email: ' alex@example.com' , role: ' viewer' , createdAt: ' 2024-03-10T11:15:00Z' }],
234+ ]));
268235```
269236
270237### Schema Registry (server-side)
@@ -278,9 +245,7 @@ schemas.set('users', {
278245 title: ' User' ,
279246 type: ' object' ,
280247 required: [' firstName' , ' lastName' , ' email' ],
281- properties: {
282- /* ... as above ... */
283- },
248+ properties: { /* ... as above ... */ },
284249});
285250```
286251
@@ -298,15 +263,15 @@ router that works for any entity registered in the schema map.
298263
299264## Frontend ↔ Backend Contract
300265
301- | Frontend (Hybrids Store) | Backend (Express) |
302- | --------------------------------- | -------------------------- |
303- | ` [store.connect].get(id) ` | ` GET /api/:entity/:id ` |
304- | ` [store.connect].set(id, values) ` | ` PUT /api/:entity/:id ` |
305- | ` [store.connect].list(params) ` | ` GET /api/:entity?... ` |
306- | ` store.set(model, null) ` (delete) | ` DELETE /api/:entity/:id ` |
307- | Schema fetch for forms | ` OPTIONS /api/:entity ` |
308- | Schema fetch for item | ` OPTIONS /api/:entity/:id ` |
309- | Realtime invalidation | ` GET /api/events ` (SSE) |
266+ | Frontend (Hybrids Store) | Backend (Express) |
267+ | ---| ---|
268+ | ` [store.connect].get(id) ` | ` GET /api/:entity/:id ` |
269+ | ` [store.connect].set(id, values) ` | ` PUT /api/:entity/:id ` |
270+ | ` [store.connect].list(params) ` | ` GET /api/:entity?... ` |
271+ | ` store.set(model, null) ` (delete) | ` DELETE /api/:entity/:id ` |
272+ | Schema fetch for forms | ` OPTIONS /api/:entity ` |
273+ | Schema fetch for item | ` OPTIONS /api/:entity/:id ` |
274+ | Realtime invalidation | ` GET /api/events ` (SSE) |
310275
311276This contract means adding a new entity type requires:
312277
0 commit comments