Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions harper-best-practices/rules/programmatic-table-requests.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand All @@ -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 |
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kriszyp which ones do we want to flag as dangerous from a performance perspective?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

contains and ends_with are the ones that defeat any indexing.

| `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.