From 9168458685fed023467a59dd0ce515382e46a400 Mon Sep 17 00:00:00 2001 From: Ethan Arrowood Date: Thu, 14 May 2026 13:47:02 -0600 Subject: [PATCH 1/2] docs: add programmatic conditions API to querying-rest-apis skill The skill only documented URL/FIQL query string syntax. Agents writing custom resources had no reference for the programmatic conditions API, including the exact comparator strings (equals, greater_than, etc.) which differ from the FIQL equivalents and are critical for queries to work at all. Adds a full reference for the conditions object shape, all comparator values, query object parameters, and annotated examples covering common patterns (simple filter, AND+OR, relationship traversal, sort+paginate). Co-Authored-By: Claude Sonnet 4.6 --- .../rules/querying-rest-apis.md | 92 ++++++++++++++++++- 1 file changed, 89 insertions(+), 3 deletions(-) diff --git a/harper-best-practices/rules/querying-rest-apis.md b/harper-best-practices/rules/querying-rest-apis.md index c1e39d3..a670b17 100644 --- a/harper-best-practices/rules/querying-rest-apis.md +++ b/harper-best-practices/rules/querying-rest-apis.md @@ -1,6 +1,6 @@ --- name: querying-rest-apis -description: How to use query parameters to filter, sort, and paginate Harper REST APIs. +description: How to filter, sort, and paginate Harper REST APIs via URL query strings and programmatic conditions. --- # Querying REST APIs @@ -9,9 +9,9 @@ Instructions for the agent to follow when querying Harper's REST APIs. ## When to Use -Use this skill when you need to perform advanced data retrieval (filtering, sorting, pagination, joins) using Harper's automatic REST endpoints. +Use this skill when you need to perform advanced data retrieval (filtering, sorting, pagination, joins) using Harper's automatic REST endpoints or programmatic table calls inside custom resources. -## How It Works +## URL Query String Syntax 1. **Basic Filtering**: Use attribute names as query parameters: `GET /Table/?key=value`. 2. **Use Comparison Operators**: Append operators like `gt`, `ge`, `lt`, `le`, `ne` using FIQL-style syntax: `GET /Table/?price=gt=100`. @@ -25,3 +25,89 @@ Use this skill when you need to perform advanced data retrieval (filtering, sort - Example (desc): `GET /Table/?sort(-price)` - Example (combined): `GET /Table/?sort(-price,+name)` 7. **Query Relationships**: Use dot syntax for tables linked with `@relationship`: `GET /Book/?author.name=Harper`. + +## Programmatic Conditions (Custom Resources) + +When querying tables inside custom resources (e.g., `tables.MyTable.search(query)`), use a query object with a `conditions` array instead of URL syntax. + +### Condition Object Shape + +Each entry in `conditions` has: + +| Property | Description | +|---|---| +| `attribute` | Field name (string), or array of field names to traverse a relationship (e.g., `['brand', 'name']`) | +| `value` | The value to compare against | +| `comparator` | One of the comparator strings below (default: `equals`) | +| `operator` | `and` (default) or `or` — applies to a nested `conditions` block | +| `conditions` | Nested array of condition objects for complex AND/OR logic | + +### Comparator Values + +Use these exact strings — incorrect comparator names will silently fail or error: + +| Comparator | Meaning | +|---|---| +| `equals` | Exact match (default) | +| `not_equal` | Not equal | +| `greater_than` | `>` | +| `greater_than_equal` | `>=` | +| `less_than` | `<` | +| `less_than_equal` | `<=` | +| `starts_with` | String starts with value | +| `contains` | String contains value | +| `ends_with` | String ends with value | +| `between` | Value is between two bounds (pass `value` as `[min, max]`) | + +### Query Object Parameters + +| Property | Description | +|---|---| +| `conditions` | Array of condition objects (see above) | +| `limit` | Maximum number of records to return | +| `offset` | Number of records to skip (for pagination) | +| `select` | Array of attribute names to return; supports `$id` and `$updatedtime` | +| `sort` | Object with `attribute`, `descending` (bool), and optional `next` for secondary sort | + +### Examples + +**Simple filter:** +```javascript +const results = await tables.Product.search({ + conditions: [{ attribute: 'price', comparator: 'less_than', value: 100 }], + limit: 20, +}); +``` + +**AND + nested OR:** +```javascript +const results = await tables.Product.search({ + conditions: [ + { attribute: 'price', comparator: 'less_than', value: 100 }, + { + operator: 'or', + conditions: [ + { attribute: 'rating', comparator: 'greater_than', value: 4 }, + { attribute: 'featured', value: true }, + ], + }, + ], +}); +``` + +**Relationship traversal:** +```javascript +const results = await tables.Book.search({ + conditions: [{ attribute: ['brand', 'name'], comparator: 'equals', value: 'Harper' }], +}); +``` + +**Sort and paginate:** +```javascript +const results = await tables.Product.search({ + conditions: [{ attribute: 'inStock', value: true }], + sort: { attribute: 'price', descending: false }, + limit: 10, + offset: 20, +}); +``` From d823c9913d6c4b09c7bcc0560dc42635e5efca51 Mon Sep 17 00:00:00 2001 From: Ethan Arrowood Date: Thu, 14 May 2026 13:50:38 -0600 Subject: [PATCH 2/2] docs: move query conditions reference to programmatic-table-requests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Conditions/comparators are only relevant when using the JS table API (search, get, subscribe) — not URL queries. Moved the full conditions reference (shape, comparator table, query params, examples) to programmatic-table-requests.md and restored querying-rest-apis.md to URL/FIQL-only content. Co-Authored-By: Claude Sonnet 4.6 --- .../rules/programmatic-table-requests.md | 85 +++++++++++++++++ .../rules/querying-rest-apis.md | 92 +------------------ 2 files changed, 88 insertions(+), 89 deletions(-) diff --git a/harper-best-practices/rules/programmatic-table-requests.md b/harper-best-practices/rules/programmatic-table-requests.md index 92883b3..245f83e 100644 --- a/harper-best-practices/rules/programmatic-table-requests.md +++ b/harper-best-practices/rules/programmatic-table-requests.md @@ -30,6 +30,7 @@ Use this skill when you need to perform database operations (CRUD, search, subsc // process record } ``` + See the [Query Conditions](#query-conditions) section below for the full query object reference. 5. **Real-time Subscriptions**: Use `subscribe(query)` to listen for changes: ```typescript for await (const event of tables.MyTable.subscribe(query)) { @@ -38,6 +39,90 @@ Use this skill when you need to perform database operations (CRUD, search, subsc ``` 6. **Publish Events**: Use `publish(id, message)` to trigger subscriptions without necessarily persisting data. +## Query Conditions + +When passing a query to `search()`, `get()`, or `subscribe()`, use a query object with a `conditions` array. + +### Condition Object Shape + +| Property | Description | +|---|---| +| `attribute` | Field name, or array of field names to traverse a relationship (e.g., `['brand', 'name']`) | +| `value` | The value to compare against | +| `comparator` | One of the comparator strings below (default: `equals`) | +| `operator` | `and` (default) or `or` — applies to a nested `conditions` block | +| `conditions` | Nested array of condition objects for complex AND/OR logic | + +### Comparator Values + +Use these exact strings — incorrect comparator names will silently fail or error: + +| Comparator | Meaning | +|---|---| +| `equals` | Exact match (default) | +| `not_equal` | Not equal | +| `greater_than` | `>` | +| `greater_than_equal` | `>=` | +| `less_than` | `<` | +| `less_than_equal` | `<=` | +| `starts_with` | String starts with value | +| `contains` | String contains value | +| `ends_with` | String ends with value | +| `between` | Value is between two bounds (pass `value` as `[min, max]`) | + +### Query Object Parameters + +| Property | Description | +|---|---| +| `conditions` | Array of condition objects | +| `limit` | Maximum number of records to return | +| `offset` | Number of records to skip (for pagination) | +| `select` | Array of attribute names to return; supports `$id` and `$updatedtime` | +| `sort` | Object with `attribute`, `descending` (bool), and optional `next` for secondary sort | + +### Examples + +**Simple filter:** +```javascript +for await (const record of tables.Product.search({ + conditions: [{ attribute: 'price', comparator: 'less_than', value: 100 }], + limit: 20, +})) { ... } +``` + +**AND + nested OR:** +```javascript +for await (const record of tables.Product.search({ + conditions: [ + { attribute: 'price', comparator: 'less_than', value: 100 }, + { + operator: 'or', + conditions: [ + { attribute: 'rating', comparator: 'greater_than', value: 4 }, + { attribute: 'featured', value: true }, + ], + }, + ], +})) { ... } +``` + +**Relationship traversal:** +```javascript +for await (const record of tables.Book.search({ + conditions: [{ attribute: ['brand', 'name'], comparator: 'equals', value: 'Harper' }], +})) { ... } +``` + +**Sort and paginate:** +```javascript +for await (const record of tables.Product.search({ + conditions: [{ attribute: 'inStock', value: true }], + sort: { attribute: 'price', descending: false }, + limit: 10, + offset: 20, +})) { ... } +``` + ## Cautions Be very careful when performing updates and deletions! You may be dealing with live production data. The wrong request to delete, without approval from a human, could be devastating to a business. Always use the proper approval process. diff --git a/harper-best-practices/rules/querying-rest-apis.md b/harper-best-practices/rules/querying-rest-apis.md index a670b17..c1e39d3 100644 --- a/harper-best-practices/rules/querying-rest-apis.md +++ b/harper-best-practices/rules/querying-rest-apis.md @@ -1,6 +1,6 @@ --- name: querying-rest-apis -description: How to filter, sort, and paginate Harper REST APIs via URL query strings and programmatic conditions. +description: How to use query parameters to filter, sort, and paginate Harper REST APIs. --- # Querying REST APIs @@ -9,9 +9,9 @@ Instructions for the agent to follow when querying Harper's REST APIs. ## When to Use -Use this skill when you need to perform advanced data retrieval (filtering, sorting, pagination, joins) using Harper's automatic REST endpoints or programmatic table calls inside custom resources. +Use this skill when you need to perform advanced data retrieval (filtering, sorting, pagination, joins) using Harper's automatic REST endpoints. -## URL Query String Syntax +## How It Works 1. **Basic Filtering**: Use attribute names as query parameters: `GET /Table/?key=value`. 2. **Use Comparison Operators**: Append operators like `gt`, `ge`, `lt`, `le`, `ne` using FIQL-style syntax: `GET /Table/?price=gt=100`. @@ -25,89 +25,3 @@ Use this skill when you need to perform advanced data retrieval (filtering, sort - Example (desc): `GET /Table/?sort(-price)` - Example (combined): `GET /Table/?sort(-price,+name)` 7. **Query Relationships**: Use dot syntax for tables linked with `@relationship`: `GET /Book/?author.name=Harper`. - -## Programmatic Conditions (Custom Resources) - -When querying tables inside custom resources (e.g., `tables.MyTable.search(query)`), use a query object with a `conditions` array instead of URL syntax. - -### Condition Object Shape - -Each entry in `conditions` has: - -| Property | Description | -|---|---| -| `attribute` | Field name (string), or array of field names to traverse a relationship (e.g., `['brand', 'name']`) | -| `value` | The value to compare against | -| `comparator` | One of the comparator strings below (default: `equals`) | -| `operator` | `and` (default) or `or` — applies to a nested `conditions` block | -| `conditions` | Nested array of condition objects for complex AND/OR logic | - -### Comparator Values - -Use these exact strings — incorrect comparator names will silently fail or error: - -| Comparator | Meaning | -|---|---| -| `equals` | Exact match (default) | -| `not_equal` | Not equal | -| `greater_than` | `>` | -| `greater_than_equal` | `>=` | -| `less_than` | `<` | -| `less_than_equal` | `<=` | -| `starts_with` | String starts with value | -| `contains` | String contains value | -| `ends_with` | String ends with value | -| `between` | Value is between two bounds (pass `value` as `[min, max]`) | - -### Query Object Parameters - -| Property | Description | -|---|---| -| `conditions` | Array of condition objects (see above) | -| `limit` | Maximum number of records to return | -| `offset` | Number of records to skip (for pagination) | -| `select` | Array of attribute names to return; supports `$id` and `$updatedtime` | -| `sort` | Object with `attribute`, `descending` (bool), and optional `next` for secondary sort | - -### Examples - -**Simple filter:** -```javascript -const results = await tables.Product.search({ - conditions: [{ attribute: 'price', comparator: 'less_than', value: 100 }], - limit: 20, -}); -``` - -**AND + nested OR:** -```javascript -const results = await tables.Product.search({ - conditions: [ - { attribute: 'price', comparator: 'less_than', value: 100 }, - { - operator: 'or', - conditions: [ - { attribute: 'rating', comparator: 'greater_than', value: 4 }, - { attribute: 'featured', value: true }, - ], - }, - ], -}); -``` - -**Relationship traversal:** -```javascript -const results = await tables.Book.search({ - conditions: [{ attribute: ['brand', 'name'], comparator: 'equals', value: 'Harper' }], -}); -``` - -**Sort and paginate:** -```javascript -const results = await tables.Product.search({ - conditions: [{ attribute: 'inStock', value: true }], - sort: { attribute: 'price', descending: false }, - limit: 10, - offset: 20, -}); -```