@harperfast/template-react-ts-studio 1.12.2 → 1.12.3
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.
- package/.agents/skills/harper-best-practices/AGENTS.md +632 -474
- package/.agents/skills/harper-best-practices/rules/automatic-apis.md +131 -55
- package/.agents/skills/harper-best-practices/rules/checking-authentication.md +155 -61
- package/.agents/skills/harper-best-practices/rules/deploying-to-harper-fabric.md +63 -85
- package/.agents/skills/harper-best-practices/rules/programmatic-table-requests.md +111 -52
- package/.agents/skills/harper-best-practices/rules/querying-rest-apis.md +38 -70
- package/.agents/skills/harper-best-practices/rules/schema-design-tooling.md +81 -69
- package/.agents/skills/harper-best-practices/rules/v5-upgrade.md +82 -96
- package/.agents/skills/harper-best-practices/rules.manifest.yaml +212 -0
- package/agent/skills/harper-best-practices/AGENTS.md +632 -474
- package/agent/skills/harper-best-practices/rules/automatic-apis.md +131 -55
- package/agent/skills/harper-best-practices/rules/checking-authentication.md +155 -61
- package/agent/skills/harper-best-practices/rules/deploying-to-harper-fabric.md +63 -85
- package/agent/skills/harper-best-practices/rules/programmatic-table-requests.md +111 -52
- package/agent/skills/harper-best-practices/rules/querying-rest-apis.md +38 -70
- package/agent/skills/harper-best-practices/rules/schema-design-tooling.md +81 -69
- package/agent/skills/harper-best-practices/rules/v5-upgrade.md +82 -96
- package/agent/skills/harper-best-practices/rules.manifest.yaml +212 -0
- package/package.json +1 -1
- package/skills-lock.json +1 -1
|
@@ -5,17 +5,17 @@ metadata:
|
|
|
5
5
|
mode: generate
|
|
6
6
|
sources:
|
|
7
7
|
- reference/v5/rest/querying.md
|
|
8
|
-
sourceCommit:
|
|
9
|
-
inputHash:
|
|
8
|
+
sourceCommit: 677ad213d67822e109c83619e181ca23a59823db
|
|
9
|
+
inputHash: 0f8efee293628a52
|
|
10
10
|
---
|
|
11
11
|
|
|
12
|
-
# Querying
|
|
12
|
+
# Querying REST APIs
|
|
13
13
|
|
|
14
|
-
Instructions for the agent to filter, sort, select, and paginate
|
|
14
|
+
Instructions for the agent to filter, sort, select, and paginate Harper REST API collections using URL query parameters.
|
|
15
15
|
|
|
16
16
|
## When to Use
|
|
17
17
|
|
|
18
|
-
Apply this rule
|
|
18
|
+
Apply this rule whenever building or modifying code that queries Harper REST collection endpoints. Use it when you need to filter records by attribute values, apply comparison operators, sort or paginate results, or join across related tables. See [automatic-apis.md](automatic-apis.md) for how Harper exposes tables as REST endpoints.
|
|
19
19
|
|
|
20
20
|
## How It Works
|
|
21
21
|
|
|
@@ -26,13 +26,7 @@ Apply this rule when building or debugging REST API calls against Harper tables
|
|
|
26
26
|
GET /Product/?category=software&inStock=true
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
2. **
|
|
30
|
-
|
|
31
|
-
```
|
|
32
|
-
GET /Product/?discount=null
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
3. **Apply comparison operators (FIQL syntax)**: Use FIQL operators in query parameters for range and string matching.
|
|
29
|
+
2. **Apply comparison operators (FIQL syntax)**: Use FIQL operators in the query string for numeric, string, and date comparisons.
|
|
36
30
|
|
|
37
31
|
| Operator | Meaning |
|
|
38
32
|
| -------------------- | -------------------------------------- |
|
|
@@ -61,13 +55,13 @@ Apply this rule when building or debugging REST API calls against Harper tables
|
|
|
61
55
|
GET /Product/?listDate=gt=2017-03-08T09%3A30%3A00.000Z
|
|
62
56
|
```
|
|
63
57
|
|
|
64
|
-
|
|
58
|
+
3. **Chain conditions for range queries**: Omit the attribute name on the second condition to apply it to the same attribute. Only `gt`/`ge` combined with `lt`/`le` is supported.
|
|
65
59
|
|
|
66
60
|
```
|
|
67
61
|
GET /Product/?price=gt=100<=200
|
|
68
62
|
```
|
|
69
63
|
|
|
70
|
-
|
|
64
|
+
4. **Apply type conversion**: For FIQL comparators, Harper converts values automatically. Use explicit prefixes to force a type.
|
|
71
65
|
|
|
72
66
|
| Syntax | Behavior |
|
|
73
67
|
| ----------------------------------------- | ------------------------------------------- |
|
|
@@ -81,32 +75,26 @@ Apply this rule when building or debugging REST API calls against Harper tables
|
|
|
81
75
|
|
|
82
76
|
For strict operators (`=`, `===`, `!==`), no automatic type conversion is applied.
|
|
83
77
|
|
|
84
|
-
|
|
78
|
+
5. **Combine conditions with OR logic**: Use `|` instead of `&`.
|
|
85
79
|
|
|
86
80
|
```
|
|
87
81
|
GET /Product/?rating=5|featured=true
|
|
88
82
|
```
|
|
89
83
|
|
|
90
|
-
|
|
84
|
+
6. **Group conditions**: Use parentheses or square brackets to control order of operations. Prefer square brackets when constructing queries from user input, since standard URI encoding safely encodes `[` and `]`.
|
|
91
85
|
|
|
92
86
|
```
|
|
93
87
|
GET /Product/?rating=5|(price=gt=100&price=lt=200)
|
|
94
88
|
GET /Product/?rating=5&[tag=fast|tag=scalable|tag=efficient]
|
|
95
89
|
```
|
|
96
90
|
|
|
97
|
-
|
|
91
|
+
Construct from JavaScript:
|
|
98
92
|
|
|
99
93
|
```javascript
|
|
100
94
|
let url = `/Product/?rating=5&[${tags.map(encodeURIComponent).join('|')}]`;
|
|
101
95
|
```
|
|
102
96
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
```
|
|
106
|
-
GET /Product/?price=lt=100|[rating=5&[tag=fast|tag=scalable|tag=efficient]&inStock=true]
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
8. **Select specific properties with `select(`**: Append `select(...)` as a query function separated by `&` to control which fields are returned.
|
|
97
|
+
7. **Select specific properties with `select(`**: Append `select(...)` as a query function separated by `&`.
|
|
110
98
|
|
|
111
99
|
| Syntax | Returns |
|
|
112
100
|
| -------------------------------------- | ------------------------------------------- |
|
|
@@ -116,65 +104,47 @@ Apply this rule when building or debugging REST API calls against Harper tables
|
|
|
116
104
|
| `?select(property1,)` | Objects with a single specified property |
|
|
117
105
|
| `?select(property{subProp1,subProp2})` | Nested objects with specific sub-properties |
|
|
118
106
|
|
|
119
|
-
|
|
120
|
-
GET /Product/?category=software&select(name)
|
|
121
|
-
GET /Product/?brand.name=Microsoft&select(name,brand{name})
|
|
122
|
-
```
|
|
107
|
+
8. **Paginate with `limit(`**: Use `limit(end)` or `limit(start,end)` to control result count and offset.
|
|
123
108
|
|
|
124
|
-
9. **
|
|
109
|
+
9. **Sort with `sort(`**: Use `sort(property)` or `sort(+property,-property,...)`. Prefix `+` or no prefix = ascending; `-` = descending.
|
|
125
110
|
|
|
126
|
-
|
|
127
|
-
GET /Product/?rating=gt=3&inStock=true&select(rating,name)&limit(20)
|
|
128
|
-
GET /Product/?rating=gt=3&limit(10,30)
|
|
129
|
-
```
|
|
111
|
+
10. **Query across relationships**: Use dot-syntax to filter by related table attributes. Relationships must be defined in the schema using `@relationship`. Relationship attributes are not included by default — use `select()` to include them.
|
|
130
112
|
|
|
131
|
-
10. **Sort results with `sort(`**: Use `sort(property)` or `sort(+property,-property,...)` to order results. Prefix `+` or no prefix = ascending; `-` = descending.
|
|
132
|
-
|
|
133
|
-
```
|
|
134
|
-
GET /Product/?rating=gt=3&sort(+name)
|
|
135
|
-
GET /Product/?sort(+rating,-price)
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
11. **Query across relationships using dot-syntax**: Filter on related table attributes using dot-chained property names. Relationships must be defined in the schema with `@relationship`.
|
|
139
|
-
|
|
140
|
-
```
|
|
141
|
-
GET /Product/?brand.name=Microsoft
|
|
142
|
-
GET /Brand/?products.name=Keyboard
|
|
143
113
|
```
|
|
144
|
-
|
|
145
|
-
Use `select()` to include relationship attributes in the response (they are excluded by default):
|
|
146
|
-
|
|
147
|
-
```
|
|
148
|
-
GET /Product/?brand.name=Microsoft&select(name,brand)
|
|
149
114
|
GET /Product/?brand.name=Microsoft&select(name,brand{name})
|
|
150
115
|
```
|
|
151
116
|
|
|
152
|
-
|
|
117
|
+
11. **Query for null values**: Use `=null` as the value to match null or non-null records.
|
|
153
118
|
```
|
|
154
|
-
GET /
|
|
119
|
+
GET /Product/?discount=null
|
|
155
120
|
```
|
|
156
121
|
|
|
157
122
|
## Examples
|
|
158
123
|
|
|
159
|
-
**
|
|
124
|
+
**Filter with comparison operators and select:**
|
|
160
125
|
|
|
161
126
|
```
|
|
162
|
-
GET /Product/?category=software&price=gt=100&price=lt=200&select(name,price)
|
|
127
|
+
GET /Product/?category=software&price=gt=100&price=lt=200&select(name,price)
|
|
163
128
|
```
|
|
164
129
|
|
|
165
|
-
**
|
|
130
|
+
**Paginate and sort:**
|
|
166
131
|
|
|
167
132
|
```
|
|
168
|
-
GET /Product/?rating=gt=3&
|
|
133
|
+
GET /Product/?rating=gt=3&inStock=true&select(rating,name)&limit(20)
|
|
134
|
+
GET /Product/?rating=gt=3&limit(10,30)
|
|
135
|
+
GET /Product/?rating=gt=3&sort(+name)
|
|
136
|
+
GET /Product/?sort(+rating,-price)
|
|
169
137
|
```
|
|
170
138
|
|
|
171
|
-
**OR with grouping
|
|
139
|
+
**OR logic with grouping:**
|
|
172
140
|
|
|
173
141
|
```
|
|
174
142
|
GET /Product/?price=lt=100|[rating=5&[tag=fast|tag=scalable|tag=efficient]&inStock=true]
|
|
175
143
|
```
|
|
176
144
|
|
|
177
|
-
**
|
|
145
|
+
**Relationship join with nested select:**
|
|
146
|
+
|
|
147
|
+
Define the schema:
|
|
178
148
|
|
|
179
149
|
```graphql
|
|
180
150
|
type Product @table @export {
|
|
@@ -190,13 +160,14 @@ type Brand @table @export {
|
|
|
190
160
|
}
|
|
191
161
|
```
|
|
192
162
|
|
|
193
|
-
|
|
163
|
+
Query with join:
|
|
194
164
|
|
|
195
165
|
```
|
|
196
166
|
GET /Product/?brand.name=Microsoft&select(name,brand{name,id})
|
|
167
|
+
GET /Brand/?products.name=Keyboard
|
|
197
168
|
```
|
|
198
169
|
|
|
199
|
-
**Many-to-many relationship
|
|
170
|
+
**Many-to-many relationship:**
|
|
200
171
|
|
|
201
172
|
```graphql
|
|
202
173
|
type Product @table @export {
|
|
@@ -207,23 +178,20 @@ type Product @table @export {
|
|
|
207
178
|
}
|
|
208
179
|
```
|
|
209
180
|
|
|
210
|
-
Query:
|
|
211
|
-
|
|
212
181
|
```
|
|
213
182
|
GET /Product/?resellers.name=Cool Shop&select(id,name,resellers{name,id})
|
|
214
183
|
```
|
|
215
184
|
|
|
216
|
-
**
|
|
185
|
+
**Access a specific property by record ID:**
|
|
217
186
|
|
|
218
187
|
```
|
|
219
|
-
GET /
|
|
188
|
+
GET /MyTable/123.propertyName
|
|
220
189
|
```
|
|
221
190
|
|
|
222
191
|
## Notes
|
|
223
192
|
|
|
224
|
-
-
|
|
225
|
-
-
|
|
226
|
-
- When selecting a related attribute without filtering on it, the
|
|
227
|
-
- The
|
|
228
|
-
- Square brackets
|
|
229
|
-
- `directURLMapping: true` can be set on a resource to change URL path handling semantics; see your schema configuration for details.
|
|
193
|
+
- Only indexed attributes can be used as the primary filter attribute; when combining multiple attributes, only one needs to be indexed.
|
|
194
|
+
- Relationship attributes are excluded from responses by default. Always use `select(` to include them.
|
|
195
|
+
- When selecting a related attribute without filtering on it, the behavior is a LEFT JOIN — the property is omitted if the foreign key is null or references a non-existent record.
|
|
196
|
+
- The suffixes `.json`, `.cbor`, `.msgpack`, and `.csv` in URL paths are reserved as content-type selectors and take precedence over a property of the same name.
|
|
197
|
+
- Square brackets are preferred over parentheses when building grouped queries programmatically, because `[` and `]` are safely URL-encoded by standard encoding functions while `(` is not.
|
|
@@ -9,21 +9,32 @@ metadata:
|
|
|
9
9
|
- reference/v5/database/schema.md#Overview
|
|
10
10
|
- reference/v5/database/schema.md#Type Directives
|
|
11
11
|
- reference/v5/database/schema.md#Field Directives
|
|
12
|
-
sourceCommit:
|
|
13
|
-
inputHash:
|
|
12
|
+
sourceCommit: 677ad213d67822e109c83619e181ca23a59823db
|
|
13
|
+
inputHash: ecb06058191ba29f
|
|
14
14
|
---
|
|
15
15
|
|
|
16
16
|
# Schema Design and GraphQL Tooling
|
|
17
17
|
|
|
18
|
-
Instructions for the agent to follow when designing Harper schemas,
|
|
18
|
+
Instructions for the agent to follow when designing Harper database schemas using GraphQL type definitions, core directives, and tooling configuration.
|
|
19
19
|
|
|
20
20
|
## When to Use
|
|
21
21
|
|
|
22
|
-
Apply this rule when creating or modifying Harper schema files (`.graphql`), configuring
|
|
22
|
+
Apply this rule when creating or modifying Harper schema files (`.graphql`), configuring schema loading in `config.yaml`, or deciding which directives to apply to tables and fields. Use it whenever a task involves defining tables, primary keys, indexes, or export behavior.
|
|
23
23
|
|
|
24
24
|
## How It Works
|
|
25
25
|
|
|
26
|
-
1. **
|
|
26
|
+
1. **Create a GraphQL schema file** with Harper-specific directives. Schemas ensure required tables exist on deployment, enforce types and constraints, control indexing, and define relationships.
|
|
27
|
+
|
|
28
|
+
```graphql
|
|
29
|
+
type Dog @table {
|
|
30
|
+
id: Long @primaryKey
|
|
31
|
+
name: String
|
|
32
|
+
breed: String
|
|
33
|
+
age: Int
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
2. **Register the schema in `config.yaml`** using the `graphqlSchema` plugin:
|
|
27
38
|
|
|
28
39
|
```yaml
|
|
29
40
|
graphqlSchema:
|
|
@@ -32,76 +43,74 @@ Apply this rule when creating or modifying Harper schema files (`.graphql`), con
|
|
|
32
43
|
|
|
33
44
|
Both plugins and applications can specify schemas.
|
|
34
45
|
|
|
35
|
-
|
|
46
|
+
3. **Mark each type as a table** with `@table`. The type name becomes the table name by default.
|
|
36
47
|
|
|
37
48
|
```graphql
|
|
38
|
-
type
|
|
49
|
+
type MyTable @table {
|
|
39
50
|
id: Long @primaryKey
|
|
40
|
-
name: String
|
|
41
|
-
breed: String
|
|
42
|
-
age: Int
|
|
43
51
|
}
|
|
44
52
|
```
|
|
45
53
|
|
|
46
|
-
|
|
47
|
-
- `String` or `ID` → UUID string
|
|
48
|
-
- `Int`, `Long`, or `Any` → auto-incrementing integer
|
|
54
|
+
Key `@table` arguments:
|
|
49
55
|
|
|
50
|
-
|
|
56
|
+
| Argument | Type | Default | Description |
|
|
57
|
+
| -------------------- | --------- | ----------------------------- | --------------------------------------------------------------- |
|
|
58
|
+
| `table` | `String` | type name | Override the table name |
|
|
59
|
+
| `database` | `String` | `"data"` | Database to place the table in |
|
|
60
|
+
| `expiration` | `Int` | — | Seconds until a record goes stale |
|
|
61
|
+
| `eviction` | `Int` | `0` | Additional seconds after `expiration` before physical removal |
|
|
62
|
+
| `scanInterval` | `Int` | `(expiration + eviction) / 4` | Seconds between eviction scans |
|
|
63
|
+
| `replicate` | `Boolean` | `true` | Enable replication of this table |
|
|
64
|
+
| `cacheControl` | `String` | — | `Cache-Control` header for anonymous GET/HEAD 200/304 responses |
|
|
65
|
+
| `randomAccessFields` | `Boolean` | `storage.randomAccessFields` | Pin this table's record encoding |
|
|
66
|
+
|
|
67
|
+
4. **Designate a primary key** on every table using `@primaryKey`. Primary keys must be unique; duplicate inserts are rejected. If no primary key is provided on insert, Harper auto-generates one:
|
|
68
|
+
- **UUID string** — when type is `String` or `ID`
|
|
69
|
+
- **Auto-incrementing integer** — when type is `Int`, `Long`, or `Any`
|
|
51
70
|
|
|
52
|
-
|
|
71
|
+
Use `Long` or `Any` for auto-generated numeric keys; `Int` is 32-bit and may be insufficient for large tables.
|
|
53
72
|
|
|
54
73
|
```graphql
|
|
55
|
-
type
|
|
74
|
+
type Product @table {
|
|
56
75
|
id: Long @primaryKey
|
|
57
|
-
name: String
|
|
76
|
+
name: String
|
|
58
77
|
}
|
|
59
78
|
```
|
|
60
79
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
5. **Expose a table as an external endpoint** with `@export`. Available via REST, MQTT, and other interfaces. The optional `name` parameter sets the URL path segment:
|
|
80
|
+
5. **Add secondary indexes** with `@indexed` on any attribute that will be used for filtering in REST queries, SQL, or NoSQL operations. If the field value is an array, each element is individually indexed.
|
|
64
81
|
|
|
65
82
|
```graphql
|
|
66
|
-
type
|
|
83
|
+
type Product @table {
|
|
67
84
|
id: Long @primaryKey
|
|
85
|
+
category: String @indexed
|
|
86
|
+
price: Float @indexed
|
|
68
87
|
}
|
|
69
88
|
```
|
|
70
89
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
6. **Configure `@table` arguments** as needed. All arguments are optional:
|
|
74
|
-
|
|
75
|
-
| Argument | Type | Default | Description |
|
|
76
|
-
| -------------- | --------- | ----------------------------- | ------------------------------------------------------------- |
|
|
77
|
-
| `table` | `String` | type name | Override the table name |
|
|
78
|
-
| `database` | `String` | `"data"` | Database to place the table in |
|
|
79
|
-
| `expiration` | `Int` | — | Seconds until a record goes stale |
|
|
80
|
-
| `eviction` | `Int` | `0` | Additional seconds after `expiration` before physical removal |
|
|
81
|
-
| `scanInterval` | `Int` | `(expiration + eviction) / 4` | Seconds between eviction scans |
|
|
82
|
-
| `replicate` | `Boolean` | `true` | Enable replication of this table |
|
|
83
|
-
|
|
84
|
-
7. **Apply additional field directives** where needed:
|
|
85
|
-
- `@createdTime` — auto-assigns creation timestamp (Unix epoch ms)
|
|
86
|
-
- `@updatedTime` — auto-assigns update timestamp (Unix epoch ms)
|
|
87
|
-
- `@expiresAt` — marks a field as the record's absolute expiration time (Unix epoch ms)
|
|
88
|
-
- `@embed(source:, model:)` — computes an embedding vector when the source field is written; field type must be `[Float]`
|
|
89
|
-
- `@hidden` — suppresses the field from MCP tool descriptors and OpenAPI document (not an access-control mechanism)
|
|
90
|
-
|
|
91
|
-
8. **Use `@sealed`** on a type to prevent records from including properties beyond those declared in the schema:
|
|
90
|
+
6. **Expose tables via REST and other interfaces** using `@export`. Without `@export`, the table has no REST/MQTT route (callers get 404). The optional `name` parameter sets the URL path segment.
|
|
92
91
|
|
|
93
92
|
```graphql
|
|
94
|
-
type
|
|
93
|
+
type MyTable @table @export(name: "my-table") {
|
|
95
94
|
id: Long @primaryKey
|
|
96
|
-
name: String
|
|
97
95
|
}
|
|
98
96
|
```
|
|
99
97
|
|
|
100
|
-
|
|
98
|
+
`@export` is a routing directive, not access control. The table remains accessible through the Operations API and SQL regardless. REST must also be enabled for the application (via `rest: true` in `config.yaml` or Harper's built-in default).
|
|
99
|
+
|
|
100
|
+
7. **Apply additional type directives** as needed:
|
|
101
|
+
- `@sealed` — prevents records from including properties beyond those declared in the schema.
|
|
102
|
+
- `@hidden` — suppresses the type from MCP tool descriptors and the OpenAPI document. Does not restrict data access.
|
|
103
|
+
|
|
104
|
+
8. **Apply field directives** for computed and lifecycle behavior:
|
|
105
|
+
- `@createdTime` — assigns Unix epoch milliseconds on record creation.
|
|
106
|
+
- `@updatedTime` — assigns Unix epoch milliseconds on each update.
|
|
107
|
+
- `@expiresAt` — marks a field as the record's absolute expiration time (Unix epoch milliseconds); authoritative over the table-level `expiration` default.
|
|
108
|
+
- `@embed` — computes an embedding vector when the source field is written (requires `source` and `model` arguments; field type must be `[Float]`).
|
|
109
|
+
- `@hidden` (field) — suppresses the field from generated specs and MCP tool schemas; does not restrict data access.
|
|
101
110
|
|
|
102
111
|
## Examples
|
|
103
112
|
|
|
104
|
-
**Minimal
|
|
113
|
+
**Minimal two-table schema:**
|
|
105
114
|
|
|
106
115
|
```graphql
|
|
107
116
|
type Dog @table {
|
|
@@ -127,56 +136,59 @@ type WeatherCache @table(expiration: 300, eviction: 3300, scanInterval: 600) {
|
|
|
127
136
|
}
|
|
128
137
|
```
|
|
129
138
|
|
|
130
|
-
**
|
|
139
|
+
**Exported table with cache control:**
|
|
131
140
|
|
|
132
141
|
```graphql
|
|
133
|
-
type
|
|
142
|
+
type Product @table(cacheControl: "public, max-age=60") @export {
|
|
134
143
|
id: Long @primaryKey
|
|
135
|
-
name: String
|
|
144
|
+
name: String
|
|
145
|
+
price: Float
|
|
136
146
|
}
|
|
137
147
|
```
|
|
138
148
|
|
|
139
|
-
**
|
|
149
|
+
**Table with lifecycle fields and indexing:**
|
|
140
150
|
|
|
141
151
|
```graphql
|
|
142
|
-
type
|
|
152
|
+
type Event @table(database: "analytics", expiration: 86400) {
|
|
143
153
|
id: Long @primaryKey
|
|
144
|
-
|
|
145
|
-
|
|
154
|
+
name: String @indexed
|
|
155
|
+
createdAt: Long @createdTime
|
|
156
|
+
updatedAt: Long @updatedTime
|
|
146
157
|
}
|
|
147
158
|
```
|
|
148
159
|
|
|
149
|
-
**
|
|
160
|
+
**Session table with per-record expiration:**
|
|
150
161
|
|
|
151
162
|
```graphql
|
|
152
163
|
type Session @table {
|
|
153
164
|
id: ID @primaryKey
|
|
154
165
|
token: String
|
|
155
|
-
createdAt: Long @createdTime
|
|
156
|
-
updatedAt: Long @updatedTime
|
|
157
166
|
expiresAt: Long @expiresAt
|
|
158
167
|
}
|
|
159
168
|
```
|
|
160
169
|
|
|
161
|
-
**
|
|
170
|
+
**Sealed table preventing extra properties:**
|
|
162
171
|
|
|
163
172
|
```graphql
|
|
164
|
-
type
|
|
173
|
+
type StrictRecord @table @sealed {
|
|
165
174
|
id: Long @primaryKey
|
|
166
175
|
name: String
|
|
167
|
-
|
|
168
|
-
"""
|
|
169
|
-
Internal — do not surface to external consumers.
|
|
170
|
-
"""
|
|
171
|
-
creditScore: Int @hidden
|
|
172
176
|
}
|
|
173
177
|
```
|
|
174
178
|
|
|
179
|
+
**`config.yaml` schema registration:**
|
|
180
|
+
|
|
181
|
+
```yaml
|
|
182
|
+
graphqlSchema:
|
|
183
|
+
files: 'schema.graphql'
|
|
184
|
+
```
|
|
185
|
+
|
|
175
186
|
## Notes
|
|
176
187
|
|
|
177
|
-
-
|
|
178
|
-
- `
|
|
179
|
-
-
|
|
180
|
-
-
|
|
181
|
-
- `@
|
|
182
|
-
-
|
|
188
|
+
- Schemas are flexible by default — records may include additional properties beyond those declared. Use `@sealed` to prevent this.
|
|
189
|
+
- Use unique `database` names in plugins or applications to avoid table naming collisions, since all tables default to the `"data"` database.
|
|
190
|
+
- Replication is enabled by default. If you disable replication and re-enable it later, the table will not catch up on writes made while replication was disabled.
|
|
191
|
+
- `@hidden` (type or field) is a metadata-visibility directive only. Use table-level role permissions and `attribute_permissions` whitelists to restrict actual data access.
|
|
192
|
+
- `@export` absence causes 404 on REST/MQTT routes but does not protect data from the Operations API or SQL.
|
|
193
|
+
- The `cacheControl` argument emits headers only on anonymous (unauthenticated) GET/HEAD 200/304 responses. Authenticated responses receive `Cache-Control: private, no-cache`.
|
|
194
|
+
- `randomAccessFields` on `@table` pins the record encoding at table creation time. Editing the argument later does not repin an existing table.
|