docs(rest): map exported tables to their automatic REST endpoints - #650
docs(rest): map exported tables to their automatic REST endpoints#650Ethan-Arrowood wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
Code Review
This pull request updates the documentation to clarify the requirements for serving tables over REST, specifically noting that both the @export directive and the rest plugin must be enabled. It also introduces a comprehensive section detailing the automatic REST endpoints generated for exported tables. The feedback suggests replacing em dashes with hyphens in the newly added Markdown text to maintain consistency with the repository's style guidelines.
|
|
||
| The optional `name` parameter specifies the URL path segment (e.g., `/my-table/`). Without `name`, the type name is used. | ||
|
|
||
| `@export` alone does not serve HTTP traffic — the `rest` plugin must also be enabled in the application's `config.yaml`. See [REST Overview / Tables and Their Automatic Endpoints](../rest/overview.md#tables-and-their-automatic-endpoints) for the endpoints an exported table produces and the `rest: true` requirement. |
There was a problem hiding this comment.
Per the repository's general rules, please use a hyphen (-) instead of an em dash (—) for consistency. The rule states to use hyphens even if there are pre-existing inconsistencies in the file.
| `@export` alone does not serve HTTP traffic — the `rest` plugin must also be enabled in the application's `config.yaml`. See [REST Overview / Tables and Their Automatic Endpoints](../rest/overview.md#tables-and-their-automatic-endpoints) for the endpoints an exported table produces and the `rest: true` requirement. | |
| `@export` alone does not serve HTTP traffic - the `rest` plugin must also be enabled in the application's `config.yaml`. See [REST Overview / Tables and Their Automatic Endpoints](../rest/overview.md#tables-and-their-automatic-endpoints) for the endpoints an exported table produces and the `rest: true` requirement. |
References
- In Markdown documentation, use hyphens ('-') instead of em dashes ('—') as field separators to adhere to the style guide, even if the file has pre-existing inconsistencies using em dashes.
There was a problem hiding this comment.
Not taking this one. The em-dash rule is being over-generalized here.
AGENTS.md says em dashes "are fine for parenthetical asides and match existing prose; do not use them as field separators." The field-separator prohibition refers to the bullet immediately above it - Type: / Default: reference blocks, where each field goes on its own line. It is not a ban on - **term** — description in prose lists.
Two checks: the docs tree has 633 em-dash list-item lines across 63 reference files, and AGENTS.md itself uses this exact pattern - including in the rule being quoted (- **Hyphens vs. dashes** — em dashes...).
So these are the established convention, not "pre-existing inconsistencies." Applying the suggestion would leave the touched lines inconsistent with every sibling line in the same list.
sent with Claude Opus 5
| rest: true | ||
| ``` | ||
|
|
||
| Neither half is sufficient on its own. Without `@export` the table has no REST route and callers get `404`. Without `rest: true` the REST handler is never registered for the application, so exported tables do not respond to HTTP requests at all — `rest` is not enabled by default. |
There was a problem hiding this comment.
Per the repository's general rules, please use a hyphen (-) instead of an em dash (—). This change should be applied consistently throughout the new content in this file where em dashes are used (e.g., on lines 67, 72, 73, and 75).
| Neither half is sufficient on its own. Without `@export` the table has no REST route and callers get `404`. Without `rest: true` the REST handler is never registered for the application, so exported tables do not respond to HTTP requests at all — `rest` is not enabled by default. | |
| Neither half is sufficient on its own. Without `@export` the table has no REST route and callers get `404`. Without `rest: true` the REST handler is never registered for the application, so exported tables do not respond to HTTP requests at all - `rest` is not enabled by default. |
References
- In Markdown documentation, use hyphens ('-') instead of em dashes ('—') as field separators to adhere to the style guide, even if the file has pre-existing inconsistencies using em dashes.
There was a problem hiding this comment.
Not taking this one. The em-dash rule is being over-generalized here.
AGENTS.md says em dashes "are fine for parenthetical asides and match existing prose; do not use them as field separators." The field-separator prohibition refers to the bullet immediately above it - Type: / Default: reference blocks, where each field goes on its own line. It is not a ban on - **term** — description in prose lists.
Two checks: the docs tree has 633 em-dash list-item lines across 63 reference files, and AGENTS.md itself uses this exact pattern - including in the rule being quoted (- **Hyphens vs. dashes** — em dashes...).
So these are the established convention, not "pre-existing inconsistencies." Applying the suggestion would leave the touched lines inconsistent with every sibling line in the same list.
sent with Claude Opus 5
🚀 Preview DeploymentYour preview deployment is ready! 🔗 Preview URL: https://preview.harper-documentation.harperfabric.com/pr-650 This preview will update automatically when you push new commits. |
Adds a "Tables and Their Automatic Endpoints" section to the REST overview that joins the two facts a reader currently has to assemble from separate pages: a table needs `@table @export` in the schema AND `rest: true` in the application's config.yaml before it answers any HTTP request. `rest` is not in defaultConfig.yaml, so without it the REST handler is never registered and exported tables 404. The section is a compact endpoint table whose rows link down to the existing per-method sections rather than restating them, so PUT/PATCH semantics stay defined in exactly one place. Also adds a one-sentence pointer from the schema reference's `@export` directive to the new section. Closes #538 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…T status
Three corrections to the endpoints section, each re-verified against
harper origin/main c4dd96237:
- Remove the incorrect HEAD/OPTIONS/405 note. `allowedMethods()`
(resources/Resource.ts:1003) is called with the Resource *class* in
server/REST.ts's OPTIONS case, so it inspects statics, not instance
methods: it over-reports MOVE and COPY (statics exist and dispatch to
instance methods a table does not define, so both 405) and omits HEAD
(no static). "OPTIONS reports the supported methods" overstated it.
Replaced with what is actually true: HEAD is GET minus the body
(REST.ts:352), and QUERY works on the collection path, dispatching
through `Resource.query` to the table's `search` (Resource.ts:347).
- Add a carve-out for components with no configuration file.
static/defaultConfig.yaml has no `rest` key, but
components/DEFAULT_CONFIG.ts sets `rest: true`, and
componentLoader.ts:602-614 selects one or the other verbatim with no
merge. The two cases are disjoint, so the blanket "not enabled by
default" told a reader with no config.yaml their exported tables would
404 when they work.
- Correct the POST row: `POST /Table` without the trailing slash returns
404 from a purpose-built ClientError during argument normalization
(Resource.ts:747), not 405; only `POST /Table/{id}` reaches
missingMethod. Also note the response is 201 and that `Location`
carries the bare primary key rather than a URL (Resource.ts:246,
REST.ts:319-320).
Also folds in PUT's three always-applied exceptions to full replacement
(Table.ts:2461-2487) as a note rather than a table row, so the
"omitted properties are removed" warning keeps the lede.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
dd9bc32 to
d4687e6
Compare
🚀 Preview DeploymentYour preview deployment is ready! 🔗 Preview URL: https://preview.harper-documentation.harperfabric.com/pr-650 This preview will update automatically when you push new commits. |
What
Adds a canonical Tables and Their Automatic Endpoints section to
reference/rest/overview.md, plus a one-sentence pointer from the@exportdirective inreference/database/schema.md.Why this shape
The facts already existed but were never joined:
@exportis documented in the schema reference,rest: trueunder Configuration in the REST overview, and the per-method behavior in that same file's GET/PUT/POST/PATCH/DELETE sections. Nothing connected "I defined and exported a table" to "here is the HTTP surface I now have." That disconnect is the reported gap.The new section is a compact endpoint table whose rows link down to the existing per-method sections rather than restating them. Restating PUT/PATCH semantics in two places on the same page would guarantee drift, and PUT/PATCH are exactly the two whose nuance matters most. Each row carries a one-line description and an anchor to the fuller section below.
It lives in
rest/overview.mdrather thanschema.mdbecauserest: trueand all per-method nuance are already on that page.schema.mdgets a pointer, not a duplicate table.The
rest: truegateThe section states plainly that both halves are required:
@table @exportin the schema - without it there is no REST route and callers get404.rest: truein the application'sconfig.yaml- without it the REST handler is never registered for the application, so even an exported table does not respond to HTTP.With one carve-out, called out in an admonition: a component directory with no configuration file at all falls back to
components/DEFAULT_CONFIG.ts, which setsrest: trueand loads*.graphqlfrom the component root.componentLoader.ts:602-614selects a config file or the built-in default verbatim, with no merge, which makes the two cases fully disjoint - so aconfig.yamlthat omitsrestturns REST off even though the same directory would have had it with no file present. That is the gotcha the issue centers on, stated without over-claiming.Verified against harper
origin/main(c4dd96237)rest: truegate.restis a key inTRUSTED_RESOURCE_PLUGINS(components/componentLoader.ts:300) mapping toserver/REST.ts; absent config keys are skipped by the loader.static/defaultConfig.yamlhas norestkey;components/DEFAULT_CONFIG.ts:2does setrest: true, and applies only when no config file exists (see carve-out above).server/REST.tsdispatchesGET/HEAD/POST/PUT/DELETE/PATCH/OPTIONS/CONNECT/TRACE/QUERY/COPY/MOVE, delegating to the matched Resource class's same-named static and returning405viamissingMethod()when the underlying instance method is absent. A table's working surface is GET, HEAD, PUT, POST, PATCH, DELETE, and QUERY.Table.put->update(..., fullUpdate = true); thefullUpdatebranch in_writeUpdatereplaces the stored record. Properties absent from the body are removed.Table.ts:2461-2487):@createdTimeretains the original record's value,@updatedTimeis re-stamped with the write time, and the primary key is forced to the URL{id}even when the body carries a different one. Recorded as a note rather than a table row so the "omitted properties are removed" warning keeps the lede.Table.patch->update(..., fullUpdate = false), a top-level merge. Row links to the existing detailed warning.201(REST.ts:319). The new key is returned inLocation, and the value is the bare primary key, not a URL -Resource.ts:246setscontext.newLocation = id ?? results?.[primaryKey]andREST.ts:320emits it verbatim.POST /Tablewithout the trailing slash returns 404 from a purpose-builtClientErrorduring argument normalization (Resource.ts:747); onlyPOST /Table/{id}falls through tomissingMethod-> 405.Resource.ts:347dispatchesmethod: 'query'toresource.search, whichTable.ts:3244implements. Exercised end-to-end over real HTTP inintegrationTests/security/query-row-allowread-checkpermission.test.ts(QUERY /Vault/-> 200), withunitTests/server/serverHelpers/uwsServer.test.jsconfirming the server accepts the verb.RequestTargetsetsisCollection = trueonly for a trailing slash (or a bare query string); an exact resource-path match setsisCollection = false, id = null.Table.getthen returns a describe object (table name, database,attributes, and an href to./) forGET /Table.recordCount/estimatedRecordRangeareundefinedunless expensive estimates are requested, so the section does not promise a record count.Table.deletetreats any collection target as a search target and deletes every matching record. With no query parameters that is every record in the table. The row says so accurately without making it sound casual.No place where the source contradicted the existing text of
rest/overview.md; the page was accurate on every point checked.Corrections made after initial review
Three problems were found in the first push and are fixed here:
HEAD/OPTIONS/405note. It claimedOPTIONS"reports the resource's supported methods." It does not.allowedMethods()(resources/Resource.ts:1003) iteratesKNOWN_METHODS=get, head, put, post, delete, patch, query, move, copyand pushes anytypeof resource[method] === 'function'- andREST.ts's OPTIONS case calls it with the Resource class, so it inspects statics rather than instance methods.Resourcedefines statics for every entry excepthead, so a table'sAllowheader over-reportsMOVEandCOPY(the statics exist and dispatch to instance methods a table does not define, so both 405) and omitsHEAD(served, but no static). Rather than document that mismatch, the note now states only what is true:HEADisGETminus the body (REST.ts:352), andQUERYruns a body-supplied search on the collection path.restis not enabled by default" would have told a reader with noconfig.yamlthat their exported tables 404 when they actually work.POSTis404, not405, and the two cases have different codes for different reasons (see above).Note for a follow-up skills PR
The hand-authored rule
harper-best-practices/rules/adding-tables-with-schemasin@harperfast/skillscontains a PUT-semantics error: it saysPUT /{Table}/{id}"Updates an existing record." PUT is create-or-replace with upsert semantics, and properties omitted from the body are removed - the difference between an update and silent data loss. The same rule also omits that PATCH's merge is shallow, and omits theLocationheader onPOST. That rule is out of scope here (separate repo, gated work); a follow-up skills PR will correct it, and can then source from this section.Separately, the
Allowmismatch found while checking correction 1 (MOVE/COPY advertised but 405, HEAD served but unadvertised) looks like a harper bug rather than something to document. Not filed here.Verification
mainatca6143ef.npm run format:writeclean,npm run format:checkpasses.npm run buildsucceeds. Every anchor added was verified by grepping the generatedbuild/reference/v5/**.htmlfor the targetid(rather than trusting the exit code, sinceonBrokenAnchorsonly warns):#export,#createdtime,#updatedtime,#configuration,#get,#post,#put,#patch,#delete,#url-structure,#openapi,#tables-and-their-automatic-endpoints, plus the four cross-page targets. The only broken anchors reported are the two known pre-existing ones (backups/overviewandrelease-notes/v5-lincoln/5.1), owned elsewhere.Closes #538
🤖 Generated with Claude Code