meadow-endpoints 4.0.21 → 4.0.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/README.md +8 -15
  2. package/diagrams/how-it-works.excalidraw +1462 -0
  3. package/diagrams/how-it-works.mmd +9 -0
  4. package/diagrams/how-it-works.svg +2 -0
  5. package/dist/meadow-endpoints.js +591 -227
  6. package/dist/meadow-endpoints.js.map +1 -1
  7. package/dist/meadow-endpoints.min.js +22 -17
  8. package/dist/meadow-endpoints.min.js.map +1 -1
  9. package/docs/README.md +9 -25
  10. package/docs/_brand.json +18 -0
  11. package/docs/_cover.md +9 -0
  12. package/docs/_sidebar.md +1 -0
  13. package/docs/_version.json +3 -3
  14. package/docs/architecture.md +119 -0
  15. package/docs/crud/README.md +6 -6
  16. package/docs/diagrams/behavior-injection-hook-points.excalidraw +677 -0
  17. package/docs/diagrams/behavior-injection-hook-points.mmd +9 -0
  18. package/docs/diagrams/behavior-injection-hook-points.svg +2 -0
  19. package/docs/diagrams/how-it-works.excalidraw +2777 -0
  20. package/docs/diagrams/how-it-works.mmd +16 -0
  21. package/docs/diagrams/how-it-works.svg +2 -0
  22. package/docs/diagrams/how-routes-are-generated.excalidraw +1237 -0
  23. package/docs/diagrams/how-routes-are-generated.mmd +13 -0
  24. package/docs/diagrams/how-routes-are-generated.svg +2 -0
  25. package/docs/diagrams/request-lifecycle.excalidraw +1897 -0
  26. package/docs/diagrams/request-lifecycle.mmd +22 -0
  27. package/docs/diagrams/request-lifecycle.svg +2 -0
  28. package/docs/diagrams/where-it-sits-in-the-stack.excalidraw +2068 -0
  29. package/docs/diagrams/where-it-sits-in-the-stack.mmd +19 -0
  30. package/docs/diagrams/where-it-sits-in-the-stack.svg +2 -0
  31. package/docs/index.html +6 -7
  32. package/docs/quickstart.md +151 -0
  33. package/docs/retold-catalog.json +155 -186
  34. package/docs/retold-keyword-index.json +6593 -2920
  35. package/package.json +8 -8
  36. package/source/controller/Meadow-Endpoints-Controller-Base.js +40 -0
  37. package/source/endpoints/count/Meadow-Endpoint-Count.js +1 -0
  38. package/source/endpoints/count/Meadow-Endpoint-CountBy.js +1 -0
  39. package/source/endpoints/create/Meadow-Operation-Create.js +1 -0
  40. package/source/endpoints/delete/Meadow-Endpoint-Delete.js +1 -0
  41. package/source/endpoints/delete/Meadow-Endpoint-Undelete.js +1 -0
  42. package/source/endpoints/read/Meadow-Endpoint-Read.js +1 -0
  43. package/source/endpoints/read/Meadow-Endpoint-ReadDistinctList.js +1 -0
  44. package/source/endpoints/read/Meadow-Endpoint-ReadLiteList.js +1 -0
  45. package/source/endpoints/read/Meadow-Endpoint-ReadMax.js +1 -0
  46. package/source/endpoints/read/Meadow-Endpoint-ReadSelectList.js +1 -0
  47. package/source/endpoints/read/Meadow-Endpoint-Reads.js +1 -0
  48. package/source/endpoints/read/Meadow-Endpoint-ReadsBy.js +1 -0
  49. package/source/endpoints/update/Meadow-Operation-Update.js +2 -0
  50. package/source/endpoints/upsert/Meadow-Operation-Upsert.js +1 -0
  51. package/test/MeadowEndpoints_SessionOverride_tests.js +75 -0
  52. package/dist/indoctrinate_content_staging/Indoctrinate-Catalog-AppData.json +0 -4769
  53. package/docs/css/docuserve.css +0 -327
package/docs/README.md CHANGED
@@ -83,24 +83,8 @@ npm install meadow-endpoints
83
83
 
84
84
  Meadow Endpoints takes a configured Meadow DAL instance and registers HTTP routes with an Orator service server. Each route follows an async waterfall pattern with behavior injection points, allowing you to customize any step of the request lifecycle without replacing the endpoint implementation.
85
85
 
86
- ```
87
- Orator (API Server)
88
- └── Meadow Endpoints (Route Registration)
89
- ├── Controller (Request Lifecycle)
90
- │ ├── Session Marshaler (Authentication)
91
- │ ├── Behavior Injection (Authorization & Custom Logic)
92
- │ ├── Error Handler (Error Responses)
93
- │ └── Log Controller (Request Logging)
94
- ├── Endpoints (Route Handlers)
95
- │ ├── Create / BulkCreate
96
- │ ├── Read / Reads / ReadSelectList / ReadLiteList / ReadDistinctList
97
- │ ├── Update / BulkUpdate / Upsert / BulkUpsert
98
- │ ├── Delete / Undelete
99
- │ ├── Count / CountBy
100
- │ └── Schema / New / Validate
101
- └── Meadow DAL (Data Access)
102
- └── Database Provider
103
- ```
86
+ <!-- bespoke diagram: edit diagrams/how-it-works.mmd or .hints.json, then: npx pict-renderer-graph build modules/meadow/meadow-endpoints/docs -->
87
+ ![How It Works](diagrams/how-it-works.svg)
104
88
 
105
89
  ## Generated Routes
106
90
 
@@ -317,10 +301,10 @@ npx docsify-cli serve docs
317
301
 
318
302
  ## Related Packages
319
303
 
320
- - [meadow](https://github.com/stevenvelozo/meadow) - Data access layer (required)
321
- - [meadow-filter](https://github.com/stevenvelozo/meadow-filter) - URL filter expression parser
322
- - [orator](https://github.com/stevenvelozo/orator) - API server abstraction
323
- - [orator-serviceserver-restify](https://github.com/stevenvelozo/orator-serviceserver-restify) - Restify service server
324
- - [stricture](https://github.com/stevenvelozo/stricture) - Schema definition language
325
- - [foxhound](https://github.com/stevenvelozo/foxhound) - Query DSL for SQL generation
326
- - [fable](https://github.com/stevenvelozo/fable) - Service provider framework
304
+ - [meadow](https://fable-retold.github.io/meadow/) - Data access layer (required)
305
+ - [meadow-filter](https://github.com/fable-retold/meadow-filter) - URL filter expression parser
306
+ - [orator](https://fable-retold.github.io/orator/) - API server abstraction
307
+ - [orator-serviceserver-restify](https://fable-retold.github.io/orator-serviceserver-restify/) - Restify service server
308
+ - [stricture](https://fable-retold.github.io/stricture/) - Schema definition language
309
+ - [foxhound](https://fable-retold.github.io/foxhound/) - Query DSL for SQL generation
310
+ - [fable](https://fable-retold.github.io/fable/) - Service provider framework
@@ -0,0 +1,18 @@
1
+ {
2
+ "Hash": "meadow-endpoints",
3
+ "Name": "Meadow Endpoints",
4
+ "Tagline": "Automatic RESTful CRUD endpoint generation from Meadow entities with behavior injection hooks",
5
+ "Palette": "mix",
6
+ "Icon": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 96 96\" width=\"96\" height=\"96\">\n\t\t<defs>\n\t\t\t<clipPath id=\"frame-meadow-endpoints-filled-light\">\n\t\t\t\t<path d=\"M 2 48\n\t\t\tA 46 46 0 1 0 94 48\n\t\t\tA 46 46 0 1 0 2 48 Z\"/>\n\t\t\t</clipPath>\n\t\t</defs>\n\t\t<path d=\"M 2 48\n\t\t\tA 46 46 0 1 0 94 48\n\t\t\tA 46 46 0 1 0 2 48 Z\" fill=\"#2b55e2\"/>\n\t\t<g clip-path=\"url(#frame-meadow-endpoints-filled-light)\"><rect x=\"19.5\" y=\"28.5\" width=\"48\" height=\"48\" rx=\"8\" fill=\"#dd7d63\" opacity=\"0.9\"/>\n\t\t\t\t\t<rect x=\"28.5\" y=\"19.5\" width=\"48\" height=\"48\" rx=\"8\" fill=\"rgba(255,255,255,0.18)\"/></g>\n\t\t<text x=\"48\" y=\"50\" text-anchor=\"middle\" dominant-baseline=\"central\"\n\t\t\tfont-family=\"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif\"\n\t\t\tfont-size=\"38\" font-weight=\"600\"\n\t\t\tfill=\"#ffffff\" letter-spacing=\"-1\">ME</text>\n\t</svg>",
7
+ "IconType": "svg",
8
+ "Favicon": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 96 96\" width=\"96\" height=\"96\">\n\t\t<defs>\n\t\t\t<clipPath id=\"fav-meadow-endpoints-light\">\n\t\t\t\t<path d=\"M 2 48\n\t\t\tA 46 46 0 1 0 94 48\n\t\t\tA 46 46 0 1 0 2 48 Z\"/>\n\t\t\t</clipPath>\n\t\t</defs>\n\t\t<path d=\"M 2 48\n\t\t\tA 46 46 0 1 0 94 48\n\t\t\tA 46 46 0 1 0 2 48 Z\" fill=\"#2b55e2\"/>\n\t\t<g clip-path=\"url(#fav-meadow-endpoints-light)\"><rect x=\"26.5\" y=\"17.5\" width=\"52\" height=\"52\" rx=\"9\" fill=\"rgba(255,255,255,0.22)\"/></g>\n\t\t<text x=\"48\" y=\"50\" text-anchor=\"middle\" dominant-baseline=\"central\"\n\t\t\tfont-family=\"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif\"\n\t\t\tfont-size=\"60\" font-weight=\"800\"\n\t\t\tfill=\"#ffffff\" letter-spacing=\"-1\">M</text>\n\t</svg>",
9
+ "FaviconDark": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 96 96\" width=\"96\" height=\"96\">\n\t\t<defs>\n\t\t\t<clipPath id=\"fav-meadow-endpoints-dark\">\n\t\t\t\t<path d=\"M 2 48\n\t\t\tA 46 46 0 1 0 94 48\n\t\t\tA 46 46 0 1 0 2 48 Z\"/>\n\t\t\t</clipPath>\n\t\t</defs>\n\t\t<path d=\"M 2 48\n\t\t\tA 46 46 0 1 0 94 48\n\t\t\tA 46 46 0 1 0 2 48 Z\" fill=\"#8098e8\"/>\n\t\t<g clip-path=\"url(#fav-meadow-endpoints-dark)\"><rect x=\"26.5\" y=\"17.5\" width=\"52\" height=\"52\" rx=\"9\" fill=\"rgba(255,255,255,0.22)\"/></g>\n\t\t<text x=\"48\" y=\"50\" text-anchor=\"middle\" dominant-baseline=\"central\"\n\t\t\tfont-family=\"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif\"\n\t\t\tfont-size=\"60\" font-weight=\"800\"\n\t\t\tfill=\"#101418\" letter-spacing=\"-1\">M</text>\n\t</svg>",
10
+ "Colors": {
11
+ "Primary": "#2b55e2",
12
+ "Secondary": "#dd7d63",
13
+ "PrimaryLight": "#2b55e2",
14
+ "PrimaryDark": "#8098e8",
15
+ "SecondaryLight": "#dd7d63",
16
+ "SecondaryDark": "#eabbae"
17
+ }
18
+ }
package/docs/_cover.md ADDED
@@ -0,0 +1,9 @@
1
+ # Meadow-Endpoints
2
+
3
+ > Automatic API endpoints for Meadow data.
4
+
5
+ - Read the full documentation for usage, configuration, and reference
6
+
7
+ [GitHub](https://github.com/fable-retold/meadow-endpoints)
8
+ [Get Started](#meadow-endpoints)
9
+
package/docs/_sidebar.md CHANGED
@@ -1,6 +1,7 @@
1
1
  - Getting Started
2
2
 
3
3
  - [Introduction](/)
4
+ - [Quick Start](quickstart.md)
4
5
  - [Getting Started](getting-started.md)
5
6
  - [Architecture](architecture.md)
6
7
 
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "Name": "meadow-endpoints",
3
- "Version": "4.0.15",
3
+ "Version": "4.0.22",
4
4
  "Description": "Automatic API endpoints for Meadow data.",
5
- "GeneratedAt": "2026-04-10T17:21:31.782Z",
6
- "GitCommit": "b36813c"
5
+ "GeneratedAt": "2026-05-30T22:11:58.853Z",
6
+ "GitCommit": "dc9ec80"
7
7
  }
@@ -0,0 +1,119 @@
1
+ # Architecture
2
+
3
+ This document describes how Meadow Endpoints turns a single Meadow entity into a full suite of RESTful routes, the request lifecycle each route follows, the behavior-injection hook points that make that lifecycle customizable, and where the module sits in the Retold stack.
4
+
5
+ ## Where It Sits in the Stack
6
+
7
+ Meadow Endpoints is the Layer-3 keystone of the data tier. It binds a Meadow data access layer (the data broker below it) to an Orator service server (the API host above it), registering one HTTP route per generated endpoint.
8
+
9
+ <!-- bespoke diagram: edit diagrams/where-it-sits-in-the-stack.mmd or .hints.json, then: npx pict-renderer-graph build modules/meadow/meadow-endpoints/docs -->
10
+ ![Where It Sits in the Stack](diagrams/where-it-sits-in-the-stack.svg)
11
+
12
+ Orator hosts the routes and supplies the HTTP request and response objects. Meadow Endpoints owns the request lifecycle through its controller. Meadow executes the data operation against whichever database provider is configured. Fable underpins all of it, supplying configuration, logging, and the async utilities the controller uses.
13
+
14
+ ## How Routes Are Generated
15
+
16
+ A `MeadowEndpoints` instance is constructed from a configured Meadow DAL. The DAL scope (for example `Book`) and the configured version (default `1.0`) form the route prefix `/{version}/{entity}` -- so `Book` becomes `/1.0/Book`.
17
+
18
+ <!-- bespoke diagram: edit diagrams/how-routes-are-generated.mmd or .hints.json, then: npx pict-renderer-graph build modules/meadow/meadow-endpoints/docs -->
19
+ ![How Routes Are Generated](diagrams/how-routes-are-generated.svg)
20
+
21
+ Calling `connectRoutes(_Orator.serviceServer)` walks the enabled behavior sets and registers every route through the internal `connectRoute()` helper, which binds each endpoint handler to the controller instance. Endpoints are grouped into behavior sets -- `Create`, `Read`, `Reads`, `Update`, `Delete`, `Count`, `Schema`, `Validate`, and `New` -- and any set can be turned off before `connectRoutes()` is called so its routes are never registered.
22
+
23
+ Route ordering matters: the `Schema`, `Schema/New`, and `Schema/Validate` routes are registered before the `/:IDRecord` read route so the literal `Schema` path is not captured as a record identifier. For the same reason, the literal `Upsert` and `Upserts` PUT routes are registered before the by-id `PUT /:IDRecord` route. For the full generated route table, see [Generated Routes](generated-routes.md) and the [CRUD Deep Dive](crud/README.md).
24
+
25
+ ## Request Lifecycle
26
+
27
+ Every generated endpoint runs the same async waterfall. Each stage either advances to the next or short-circuits to the shared error handler. Behavior-injection hooks are interleaved between the built-in stages, so custom logic runs at well-defined points without replacing any built-in step.
28
+
29
+ <!-- bespoke diagram: edit diagrams/request-lifecycle.mmd or .hints.json, then: npx pict-renderer-graph build modules/meadow/meadow-endpoints/docs -->
30
+ ![Request Lifecycle](diagrams/request-lifecycle.svg)
31
+
32
+ Not every endpoint exposes all three hook phases. A single-record read, for example, runs `Read-PreOperation`, then `Read-QueryConfiguration`, then `Read-PostOperation`; a multi-record read runs `Reads-QueryConfiguration` and `Reads-PostOperation`. See [Behavior Injection](behavior-injection.md) for the complete hook matrix.
33
+
34
+ ### Request State
35
+
36
+ `initializeRequestState()` creates the `pRequestState` object that travels through the waterfall. It carries the operation verb and the marshalled `SessionData`, and each stage attaches what it produces -- `Query`, then `Record` or `Records`, then `Result` for counts, and so on. The hook functions receive this object as their second argument and read or mutate it in place.
37
+
38
+ ### Session Marshalling
39
+
40
+ Before any hook runs, the session marshaler populates `pRequestState.SessionData` from a configurable source, selected with `MeadowEndpointsSessionDataSource`:
41
+
42
+ | Source | Origin |
43
+ |--------|--------|
44
+ | `Request` (default) | `pRequest.UserSession`, set by Orator session middleware |
45
+ | `Header` | JSON parsed from the `x-trusted-session` HTTP header |
46
+ | `None` | The default session object only |
47
+
48
+ The marshaler always starts from the `MeadowEndpointsDefaultSessionObject` template and extends it with the resolved source, guaranteeing every operation sees a complete session shape (`UserID`, `CustomerID`, `SessionID`, `UserRole`, `UserRoleIndex`, `LoggedIn`). See [Session Management](session-management.md) for details.
49
+
50
+ ## Behavior-Injection Hook Points
51
+
52
+ Behavior injection is the primary extension mechanism: it lets you hook the lifecycle of any endpoint without subclassing or replacing the built-in handler. Hooks are registered by name on the controller's `BehaviorInjection` component, and each name follows the pattern `{Verb}-{Phase}`.
53
+
54
+ <!-- bespoke diagram: edit diagrams/behavior-injection-hook-points.mmd or .hints.json, then: npx pict-renderer-graph build modules/meadow/meadow-endpoints/docs -->
55
+ ![Behavior-Injection Hook Points](diagrams/behavior-injection-hook-points.svg)
56
+
57
+ A registered hook receives `(pRequest, pRequestState, fCallback)`. Call `fCallback()` with no argument to continue the waterfall, or call it with an error to halt and route to the error handler. Because the hook is invoked with the controller as its `this`, register hooks as standard functions rather than arrow functions when you need that scope.
58
+
59
+ ```javascript
60
+ const tmpEndpoints = new libMeadowEndpoints(tmpMeadow);
61
+
62
+ // Scope every multi-record read to the caller's customer
63
+ tmpEndpoints.controller.BehaviorInjection.setBehavior('Reads-QueryConfiguration',
64
+ function (pRequest, pRequestState, fCallback)
65
+ {
66
+ if (pRequestState.SessionData.UserRoleIndex < 5)
67
+ {
68
+ pRequestState.Query.addFilter('IDCustomer', pRequestState.SessionData.CustomerID);
69
+ }
70
+ return fCallback();
71
+ });
72
+ ```
73
+
74
+ The hook phases map onto the operations as follows:
75
+
76
+ | Phase | Runs |
77
+ |-------|------|
78
+ | `{Verb}-PreOperation` | Before the query is built -- ideal for authentication, authorization, and input validation |
79
+ | `{Verb}-QueryConfiguration` | After the query is built but before it executes -- ideal for adding tenant or role filters |
80
+ | `{Verb}-PostOperation` | After the data operation completes -- ideal for transforming results, auditing, or notifications |
81
+
82
+ The available verbs are `Create`, `Read`, `Reads`, `Update`, `Delete`, `Undelete`, `Count`, `CountBy`, `Schema`, `New`, and `Validate`. The exact set of phases each verb exposes is listed in the [Behavior Injection](behavior-injection.md) hook matrix and the [CRUD Deep Dive](crud/README.md).
83
+
84
+ ## Controller Architecture
85
+
86
+ The controller owns the request lifecycle and is composed of replaceable components. The default `BaseController` wires up sensible defaults for each:
87
+
88
+ | Component | Responsibility |
89
+ |-----------|----------------|
90
+ | Behavior Injection | Stores and runs the named `{Verb}-{Phase}` hooks |
91
+ | Session Marshaler | Resolves `SessionData` from the configured source |
92
+ | Error Handler | Formats errors and optionally sets HTTP status codes |
93
+ | Log Controller | Emits structured request logging through Fable |
94
+ | Filter Parser | Parses `FilteredTo` URL expressions into query filters |
95
+
96
+ For deep customization, supply your own controller through the constructor options -- either an instantiated `ControllerInstance` or a `ControllerClass` extending the exported `BaseController`. See [Custom Controllers](custom-controllers.md).
97
+
98
+ ```javascript
99
+ const libMeadowEndpoints = require('meadow-endpoints');
100
+ const BaseController = libMeadowEndpoints.BaseController;
101
+
102
+ class CustomController extends BaseController
103
+ {
104
+ constructor(pMeadowEndpoints, pControllerOptions)
105
+ {
106
+ super(pMeadowEndpoints, pControllerOptions);
107
+ }
108
+ }
109
+
110
+ const tmpEndpoints = new libMeadowEndpoints(tmpMeadow,
111
+ { ControllerClass: CustomController });
112
+ ```
113
+
114
+ ## Related Modules
115
+
116
+ - [meadow](https://fable-retold.github.io/meadow/) -- the data access layer Meadow Endpoints generates routes from
117
+ - [orator](https://fable-retold.github.io/orator/) -- the API server that hosts the generated routes
118
+ - [retold-data-service](https://fable-retold.github.io/retold-data-service/) -- assembles Meadow Endpoints into a complete, schema-driven REST service
119
+ - [pict-section-recordset](https://fable-retold.github.io/pict-section-recordset/) -- browser-side UI that consumes these CRUD endpoints
@@ -8,12 +8,12 @@ Meadow Endpoints generates a full suite of RESTful routes from a configured Mead
8
8
 
9
9
  | Group | Operations | Description |
10
10
  |-------|-----------|-------------|
11
- | [Create](crud/create.md) | Create, BulkCreate | Insert new records |
12
- | [Read](crud/read.md) | Read, Reads, ReadsBy, ReadMax, ReadSelectList, ReadLiteList, ReadDistinctList | Retrieve records with pagination, filtering, and projections |
13
- | [Update](crud/update.md) | Update, BulkUpdate, Upsert, BulkUpsert | Modify existing records |
14
- | [Delete](crud/delete.md) | Delete, Undelete | Soft-delete and restore records |
15
- | [Count](crud/count.md) | Count, CountBy | Aggregate record counts |
16
- | [Schema](crud/schema.md) | Schema, New, Validate | Serve schema metadata, default objects, and validation |
11
+ | [Create](create.md) | Create, BulkCreate | Insert new records |
12
+ | [Read](read.md) | Read, Reads, ReadsBy, ReadMax, ReadSelectList, ReadLiteList, ReadDistinctList | Retrieve records with pagination, filtering, and projections |
13
+ | [Update](update.md) | Update, BulkUpdate, Upsert, BulkUpsert | Modify existing records |
14
+ | [Delete](delete.md) | Delete, Undelete | Soft-delete and restore records |
15
+ | [Count](count.md) | Count, CountBy | Aggregate record counts |
16
+ | [Schema](schema.md) | Schema, New, Validate | Serve schema metadata, default objects, and validation |
17
17
 
18
18
  ## Complete Route Table
19
19