@harperfast/template-react-studio 1.2.1 → 1.3.0
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 +258 -0
- package/.agents/skills/harper-best-practices/SKILL.md +88 -0
- package/.agents/skills/harper-best-practices/rules/adding-tables-with-schemas.md +40 -0
- package/.agents/skills/harper-best-practices/rules/automatic-apis.md +34 -0
- package/.agents/skills/harper-best-practices/rules/caching.md +46 -0
- package/.agents/skills/harper-best-practices/rules/checking-authentication.md +165 -0
- package/.agents/skills/harper-best-practices/rules/custom-resources.md +35 -0
- package/.agents/skills/harper-best-practices/rules/defining-relationships.md +33 -0
- package/.agents/skills/harper-best-practices/rules/deploying-to-harper-fabric.md +24 -0
- package/.agents/skills/harper-best-practices/rules/extending-tables.md +37 -0
- package/.agents/skills/harper-best-practices/rules/handling-binary-data.md +43 -0
- package/.agents/skills/harper-best-practices/rules/programmatic-table-requests.md +39 -0
- package/.agents/skills/harper-best-practices/rules/querying-rest-apis.md +22 -0
- package/.agents/skills/harper-best-practices/rules/real-time-apps.md +37 -0
- package/.agents/skills/harper-best-practices/rules/serving-web-content.md +34 -0
- package/.agents/skills/harper-best-practices/rules/typescript-type-stripping.md +32 -0
- package/.agents/skills/harper-best-practices/rules/using-blob-datatype.md +36 -0
- package/.agents/skills/harper-best-practices/rules/vector-indexing.md +152 -0
- package/README.md +1 -1
- package/package.json +1 -1
- package/resources/README.md +3 -3
- package/schemas/README.md +2 -2
- package/skills-lock.json +10 -0
- package/AGENTS.md +0 -22
- package/skills/adding-tables-with-schemas.md +0 -34
- package/skills/automatic-apis.md +0 -53
- package/skills/automatic-rest-apis.md +0 -41
- package/skills/caching.md +0 -113
- package/skills/checking-authentication.md +0 -281
- package/skills/custom-resources.md +0 -86
- package/skills/defining-relationships.md +0 -71
- package/skills/deploying-to-harper-fabric.md +0 -20
- package/skills/extending-tables.md +0 -70
- package/skills/handling-binary-data.md +0 -67
- package/skills/programmatic-table-requests.md +0 -185
- package/skills/querying-rest-apis.md +0 -69
- package/skills/real-time-apps.md +0 -75
- package/skills/serving-web-content.md +0 -82
- package/skills/typescript-type-stripping.md +0 -47
- package/skills/using-blob-datatype.md +0 -131
- package/skills/vector-indexing.md +0 -215
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
# Harper Best Practices
|
|
2
|
+
|
|
3
|
+
Guidelines for building scalable, secure, and performant applications on Harper. These practices cover everything from initial schema design to advanced deployment strategies.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Table of Contents
|
|
8
|
+
|
|
9
|
+
1. [Schema & Data Design](#1-schema--data-design) — **HIGH**
|
|
10
|
+
- 1.1 [Adding Tables with Schemas](#11-adding-tables-with-schemas)
|
|
11
|
+
- 1.2 [Defining Relationships](#12-defining-relationships)
|
|
12
|
+
- 1.3 [Vector Indexing](#13-vector-indexing)
|
|
13
|
+
- 1.4 [Using Blobs](#14-using-blobs)
|
|
14
|
+
- 1.5 [Handling Binary Data](#15-handling-binary-data)
|
|
15
|
+
2. [API & Communication](#2-api--communication) — **HIGH**
|
|
16
|
+
- 2.1 [Automatic REST APIs](#21-automatic-rest-apis)
|
|
17
|
+
- 2.2 [Querying REST APIs](#22-querying-rest-apis)
|
|
18
|
+
- 2.3 [Real-time Applications](#23-real-time-applications)
|
|
19
|
+
- 2.4 [Checking Authentication](#24-checking-authentication)
|
|
20
|
+
3. [Logic & Extension](#3-logic--extension) — **MEDIUM**
|
|
21
|
+
- 3.1 [Custom Resources](#31-custom-resources)
|
|
22
|
+
- 3.2 [Extending Table Resources](#32-extending-table-resources)
|
|
23
|
+
- 3.3 [Programmatic Table Requests](#33-programmatic-table-requests)
|
|
24
|
+
- 3.4 [TypeScript Type Stripping](#34-typescript-type-stripping)
|
|
25
|
+
- 3.5 [Caching](#35-caching)
|
|
26
|
+
4. [Infrastructure & Ops](#4-infrastructure--ops) — **MEDIUM**
|
|
27
|
+
- 4.1 [Deploying to Harper Fabric](#41-deploying-to-harper-fabric)
|
|
28
|
+
- 4.2 [Serving Web Content](#42-serving-web-content)
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 1. Schema & Data Design
|
|
33
|
+
|
|
34
|
+
**Impact: HIGH**
|
|
35
|
+
|
|
36
|
+
### 1.1 Adding Tables with Schemas
|
|
37
|
+
|
|
38
|
+
Instructions for the agent to follow when adding tables to a Harper database.
|
|
39
|
+
|
|
40
|
+
#### When to Use
|
|
41
|
+
Use this skill when you need to define new data structures or modify existing ones in a Harper database.
|
|
42
|
+
|
|
43
|
+
#### Steps
|
|
44
|
+
1. **Create Dedicated Schema Files**: Prefer having a dedicated schema `.graphql` file for each table. Check the `config.yaml` file under `graphqlSchema.files` to see how it's configured. It typically accepts wildcards (e.g., `schemas/*.graphql`), but may be configured to point at a single file.
|
|
45
|
+
2. **Use Directives**: All available directives for defining your schema are defined in `node_modules/harperdb/schema.graphql`. Common directives include `@table`, `@export`, `@primaryKey`, `@indexed`, and `@relationship`.
|
|
46
|
+
3. **Define Relationships**: Link tables together using the `@relationship` directive.
|
|
47
|
+
4. **Enable Automatic APIs**: If you add `@table @export` to a schema type, Harper automatically sets up REST and WebSocket APIs for basic CRUD operations against that table.
|
|
48
|
+
5. **Consider Table Extensions**: If you are going to extend the table in your resources, then do not `@export` the table from the schema.
|
|
49
|
+
|
|
50
|
+
#### Example
|
|
51
|
+
```graphql
|
|
52
|
+
type ExamplePerson @table @export {
|
|
53
|
+
id: ID @primaryKey
|
|
54
|
+
name: String
|
|
55
|
+
tag: String @indexed
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### 1.2 Defining Relationships
|
|
60
|
+
|
|
61
|
+
Using the `@relationship` directive to link tables.
|
|
62
|
+
|
|
63
|
+
#### When to Use
|
|
64
|
+
Use this when you have two or more tables that need to be logically linked (e.g., a "Product" table and a "Category" table).
|
|
65
|
+
|
|
66
|
+
#### Steps
|
|
67
|
+
1. **Identify the Relationship**: Determine which table should "own" the relationship. This is typically the table that will hold the foreign key.
|
|
68
|
+
2. **Apply the `@relationship` Directive**: In your GraphQL schema, use the `@relationship` directive on the field that links to another table.
|
|
69
|
+
3. **Specify the `name` and `path` Arguments**:
|
|
70
|
+
- `name`: A unique name for the relationship.
|
|
71
|
+
- `path`: The field name in the current table that holds the value to match in the related table.
|
|
72
|
+
4. **Define the Inverse Relationship (Optional but Recommended)**: For better queryability, define the relationship in the related table as well.
|
|
73
|
+
|
|
74
|
+
#### Example
|
|
75
|
+
```graphql
|
|
76
|
+
type Product @table @export {
|
|
77
|
+
id: ID @primaryKey
|
|
78
|
+
name: String
|
|
79
|
+
category: Category @relationship(name: "product_category", path: "category_id")
|
|
80
|
+
category_id: ID
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
type Category @table @export {
|
|
84
|
+
id: ID @primaryKey
|
|
85
|
+
name: String
|
|
86
|
+
products: [Product] @relationship(name: "product_category", path: "id")
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### 1.3 Vector Indexing
|
|
91
|
+
|
|
92
|
+
How to define and use vector indexes for efficient similarity search.
|
|
93
|
+
|
|
94
|
+
#### When to Use
|
|
95
|
+
Use this when you need to perform similarity searches on high-dimensional data, such as image embeddings, text embeddings, or any other numeric vectors.
|
|
96
|
+
|
|
97
|
+
#### Steps
|
|
98
|
+
1. **Define the Vector Field**: In your GraphQL schema, define a field with a list of floats (e.g., `[Float]`).
|
|
99
|
+
2. **Apply the `@indexed` Directive**: Use the `@indexed` directive on the vector field and specify the index type as `vector`.
|
|
100
|
+
3. **Configure the Index (Optional)**: You can provide additional configuration for the vector index, such as the distance metric (e.g., `cosine`, `euclidean`).
|
|
101
|
+
4. **Querying**: Use the `vector` operator in your REST or programmatic requests to perform similarity searches.
|
|
102
|
+
|
|
103
|
+
#### Example
|
|
104
|
+
```graphql
|
|
105
|
+
type Document @table @export {
|
|
106
|
+
id: ID @primaryKey
|
|
107
|
+
content: String
|
|
108
|
+
embedding: [Float] @indexed(type: "vector", options: { dims: 1536, metric: "cosine" })
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### 1.4 Using Blobs
|
|
113
|
+
|
|
114
|
+
How to store and retrieve large data in HarperDB.
|
|
115
|
+
|
|
116
|
+
#### When to Use
|
|
117
|
+
Use this when you need to store large, unstructured data such as files, images, or large text documents that exceed the typical size of a standard database field.
|
|
118
|
+
|
|
119
|
+
#### Steps
|
|
120
|
+
1. **Define the Blob Field**: Use the `Blob` scalar type in your GraphQL schema.
|
|
121
|
+
2. **Storing Data**: Send the data as a buffer or a stream when creating or updating a record.
|
|
122
|
+
3. **Retrieving Data**: Access the blob field, which will return the data as a stream or buffer.
|
|
123
|
+
|
|
124
|
+
### 1.5 Handling Binary Data
|
|
125
|
+
|
|
126
|
+
How to store and serve binary data like images or MP3s.
|
|
127
|
+
|
|
128
|
+
#### When to Use
|
|
129
|
+
Use this when your application needs to handle binary files, particularly for storage and retrieval.
|
|
130
|
+
|
|
131
|
+
#### Steps
|
|
132
|
+
1. **Use the `Blob` type**: As with general large data, the `Blob` type is best for binary files.
|
|
133
|
+
2. **Streaming**: For large files, use streaming to minimize memory usage during upload and download.
|
|
134
|
+
3. **MIME Types**: Store the MIME type alongside the binary data to ensure it is served correctly by your application logic.
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## 2. API & Communication
|
|
139
|
+
|
|
140
|
+
**Impact: HIGH**
|
|
141
|
+
|
|
142
|
+
### 2.1 Automatic REST APIs
|
|
143
|
+
|
|
144
|
+
Details on the CRUD endpoints automatically generated for exported tables.
|
|
145
|
+
|
|
146
|
+
#### Endpoints
|
|
147
|
+
- `GET /{TableName}`: Describes the schema.
|
|
148
|
+
- `GET /{TableName}/`: Lists records (supports filtering/sorting).
|
|
149
|
+
- `GET /{TableName}/{id}`: Gets a record by ID.
|
|
150
|
+
- `POST /{TableName}/`: Creates a record.
|
|
151
|
+
- `PUT /{TableName}/{id}`: Updates a record.
|
|
152
|
+
- `PATCH /{TableName}/{id}`: Partial update.
|
|
153
|
+
- `DELETE /{TableName}/`: Deletes records.
|
|
154
|
+
- `DELETE /{TableName}/{id}`: Deletes by ID.
|
|
155
|
+
|
|
156
|
+
### 2.2 Querying REST APIs
|
|
157
|
+
|
|
158
|
+
How to use filters, operators, sorting, and pagination in REST requests.
|
|
159
|
+
|
|
160
|
+
#### Query Parameters
|
|
161
|
+
- `limit`: Number of records to return.
|
|
162
|
+
- `offset`: Number of records to skip.
|
|
163
|
+
- `sort`: Field to sort by.
|
|
164
|
+
- `order`: `asc` or `desc`.
|
|
165
|
+
- `filter`: JSON object for filtering.
|
|
166
|
+
|
|
167
|
+
### 2.3 Real-time Applications
|
|
168
|
+
|
|
169
|
+
Implementing WebSockets and Pub/Sub for live data updates.
|
|
170
|
+
|
|
171
|
+
#### When to Use
|
|
172
|
+
Use this for applications that require live updates, such as chat apps, live dashboards, or collaborative tools.
|
|
173
|
+
|
|
174
|
+
#### Steps
|
|
175
|
+
1. **WebSocket Connection**: Connect to the Harper WebSocket endpoint.
|
|
176
|
+
2. **Subscribing**: Subscribe to table updates or specific records.
|
|
177
|
+
3. **Pub/Sub**: Use the internal bus to publish and subscribe to custom events.
|
|
178
|
+
|
|
179
|
+
### 2.4 Checking Authentication
|
|
180
|
+
|
|
181
|
+
How to use sessions to verify user identity and roles.
|
|
182
|
+
|
|
183
|
+
#### When to Use
|
|
184
|
+
Use this to secure your application by ensuring that only authorized users can access certain resources or perform specific actions.
|
|
185
|
+
|
|
186
|
+
#### Steps
|
|
187
|
+
1. **Session Handling**: Access the session object from the request context.
|
|
188
|
+
2. **Identity Verification**: Check for the presence of a user ID or token.
|
|
189
|
+
3. **Role Checks**: Verify if the user has the required roles for the action.
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## 3. Logic & Extension
|
|
194
|
+
|
|
195
|
+
**Impact: MEDIUM**
|
|
196
|
+
|
|
197
|
+
### 3.1 Custom Resources
|
|
198
|
+
|
|
199
|
+
How to define custom REST endpoints using JavaScript or TypeScript.
|
|
200
|
+
|
|
201
|
+
#### Steps
|
|
202
|
+
1. **Create Resource File**: Define your logic in a JS or TS file.
|
|
203
|
+
2. **Export Handlers**: Export functions like `GET`, `POST`, etc.
|
|
204
|
+
3. **Registration**: Ensure the resource is correctly registered in your application configuration.
|
|
205
|
+
|
|
206
|
+
### 3.2 Extending Table Resources
|
|
207
|
+
|
|
208
|
+
Adding custom logic to automatically generated table resources.
|
|
209
|
+
|
|
210
|
+
#### Steps
|
|
211
|
+
1. **Define Extension**: Create a resource file that targets an existing table.
|
|
212
|
+
2. **Intercept Requests**: Use handlers to add custom validation or data transformation.
|
|
213
|
+
3. **No `@export`**: If extending, remember not to `@export` the table in the schema.
|
|
214
|
+
|
|
215
|
+
### 3.3 Programmatic Table Requests
|
|
216
|
+
|
|
217
|
+
How to use filters, operators, sorting, and pagination in programmatic table requests.
|
|
218
|
+
|
|
219
|
+
#### Usage
|
|
220
|
+
When writing custom resources, use the internal API to query tables with full support for advanced filtering and sorting.
|
|
221
|
+
|
|
222
|
+
### 3.4 TypeScript Type Stripping
|
|
223
|
+
|
|
224
|
+
Using TypeScript directly without build tools via Node.js Type Stripping.
|
|
225
|
+
|
|
226
|
+
#### Configuration
|
|
227
|
+
Harper supports native TypeScript type stripping, allowing you to run `.ts` files directly. Ensure your environment is configured to take advantage of this for faster development cycles.
|
|
228
|
+
|
|
229
|
+
### 3.5 Caching
|
|
230
|
+
|
|
231
|
+
How caching is defined and implemented in Harper applications.
|
|
232
|
+
|
|
233
|
+
#### Strategies
|
|
234
|
+
- **In-memory**: For fast access to frequently used data.
|
|
235
|
+
- **Distributed**: For scaling across multiple nodes in Harper Fabric.
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## 4. Infrastructure & Ops
|
|
240
|
+
|
|
241
|
+
**Impact: MEDIUM**
|
|
242
|
+
|
|
243
|
+
### 4.1 Deploying to Harper Fabric
|
|
244
|
+
|
|
245
|
+
Globally scaling your Harper application.
|
|
246
|
+
|
|
247
|
+
#### Benefits
|
|
248
|
+
- **Global Distribution**: Low latency for users everywhere.
|
|
249
|
+
- **Automatic Sync**: Data is synced across the fabric automatically.
|
|
250
|
+
- **Free Tier**: Start for free and scale as you grow.
|
|
251
|
+
|
|
252
|
+
### 4.2 Serving Web Content
|
|
253
|
+
|
|
254
|
+
Two ways to serve web content from a Harper application.
|
|
255
|
+
|
|
256
|
+
#### Methods
|
|
257
|
+
1. **Static Serving**: Serve HTML, CSS, and JS files directly.
|
|
258
|
+
2. **Dynamic Rendering**: Use custom resources to render content on the fly.
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: harper-best-practices
|
|
3
|
+
description:
|
|
4
|
+
Best practices for building Harper applications, covering schema definition,
|
|
5
|
+
automatic APIs, authentication, custom resources, and data handling.
|
|
6
|
+
Triggers on tasks involving Harper database design, API implementation,
|
|
7
|
+
and deployment.
|
|
8
|
+
license: MIT
|
|
9
|
+
metadata:
|
|
10
|
+
author: harper
|
|
11
|
+
version: '1.0.0'
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Harper Best Practices
|
|
15
|
+
|
|
16
|
+
Guidelines for building scalable, secure, and performant applications on Harper. These practices cover everything from initial schema design to advanced deployment strategies.
|
|
17
|
+
|
|
18
|
+
## When to Use
|
|
19
|
+
|
|
20
|
+
Reference these guidelines when:
|
|
21
|
+
|
|
22
|
+
- Defining or modifying database schemas
|
|
23
|
+
- Implementing or extending REST/WebSocket APIs
|
|
24
|
+
- Handling authentication and session management
|
|
25
|
+
- Working with custom resources and extensions
|
|
26
|
+
- Optimizing data storage and retrieval (Blobs, Vector Indexing)
|
|
27
|
+
- Deploying applications to Harper Fabric
|
|
28
|
+
|
|
29
|
+
## Steps
|
|
30
|
+
|
|
31
|
+
1. Review the requirements for the task (schema design, API needs, or infrastructure setup).
|
|
32
|
+
2. Consult the relevant category under "Rule Categories by Priority" to understand the impact of your decisions.
|
|
33
|
+
3. Apply specific rules from the "Quick Reference" section below by reading their detailed rule files.
|
|
34
|
+
4. If you're building a new table, prioritize the `schema-` rules.
|
|
35
|
+
5. If you're extending functionality, consult the `logic-` and `api-` rules.
|
|
36
|
+
6. Validate your implementation against the `ops-` rules before deployment.
|
|
37
|
+
|
|
38
|
+
## Rule Categories by Priority
|
|
39
|
+
|
|
40
|
+
| Priority | Category | Impact | Prefix |
|
|
41
|
+
| -------- | ----------------------- | ------ | --------------- |
|
|
42
|
+
| 1 | Schema & Data Design | HIGH | `schema-` |
|
|
43
|
+
| 2 | API & Communication | HIGH | `api-` |
|
|
44
|
+
| 3 | Logic & Extension | MEDIUM | `logic-` |
|
|
45
|
+
| 4 | Infrastructure & Ops | MEDIUM | `ops-` |
|
|
46
|
+
|
|
47
|
+
## Quick Reference
|
|
48
|
+
|
|
49
|
+
### 1. Schema & Data Design (HIGH)
|
|
50
|
+
|
|
51
|
+
- `adding-tables-with-schemas` - Define tables using GraphQL schemas and directives
|
|
52
|
+
- `defining-relationships` - Link tables using the `@relationship` directive
|
|
53
|
+
- `vector-indexing` - Efficient similarity search with vector indexes
|
|
54
|
+
- `using-blob-datatype` - Store and retrieve large data (Blobs)
|
|
55
|
+
- `handling-binary-data` - Manage binary data like images or MP3s
|
|
56
|
+
|
|
57
|
+
### 2. API & Communication (HIGH)
|
|
58
|
+
|
|
59
|
+
- `automatic-apis` - Leverage automatically generated CRUD endpoints
|
|
60
|
+
- `querying-rest-apis` - Filters, sorting, and pagination in REST requests
|
|
61
|
+
- `real-time-apps` - WebSockets and Pub/Sub for live data updates
|
|
62
|
+
- `checking-authentication` - Secure apps with session-based identity verification
|
|
63
|
+
|
|
64
|
+
### 3. Logic & Extension (MEDIUM)
|
|
65
|
+
|
|
66
|
+
- `custom-resources` - Define custom REST endpoints using JS/TS
|
|
67
|
+
- `extending-tables` - Add custom logic to generated table resources
|
|
68
|
+
- `programmatic-table-requests` - Advanced filtering and sorting in code
|
|
69
|
+
- `typescript-type-stripping` - Use TypeScript without build tools
|
|
70
|
+
- `caching` - Implement and define caching for performance
|
|
71
|
+
|
|
72
|
+
### 4. Infrastructure & Ops (MEDIUM)
|
|
73
|
+
|
|
74
|
+
- `deploying-to-harper-fabric` - Scale globally with Harper Fabric
|
|
75
|
+
- `serving-web-content` - Ways to serve web content from Harper
|
|
76
|
+
|
|
77
|
+
## How to Use
|
|
78
|
+
|
|
79
|
+
Read individual rule files for detailed explanations and code examples:
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
rules/adding-tables-with-schemas.md
|
|
83
|
+
rules/automatic-apis.md
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Full Compiled Document
|
|
87
|
+
|
|
88
|
+
For the complete guide with all rules expanded: `AGENTS.md`
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: adding-tables-with-schemas
|
|
3
|
+
description: Guidelines for adding tables to a Harper database using GraphQL schemas.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Adding Tables with Schemas
|
|
7
|
+
|
|
8
|
+
Instructions for the agent to follow when adding tables to a Harper database.
|
|
9
|
+
|
|
10
|
+
## When to Use
|
|
11
|
+
|
|
12
|
+
Use this skill when you need to define new data structures or modify existing ones in a Harper database.
|
|
13
|
+
|
|
14
|
+
## Steps
|
|
15
|
+
|
|
16
|
+
1. **Create Dedicated Schema Files**: Prefer having a dedicated schema `.graphql` file for each table. Check the `config.yaml` file under `graphqlSchema.files` to see how it's configured. It typically accepts wildcards (e.g., `schemas/*.graphql`), but may be configured to point at a single file.
|
|
17
|
+
2. **Use Directives**: All available directives for defining your schema are defined in `node_modules/harperdb/schema.graphql`. Common directives include `@table`, `@export`, `@primaryKey`, `@indexed`, and `@relationship`.
|
|
18
|
+
3. **Define Relationships**: Link tables together using the `@relationship` directive. For more details, see the [Defining Relationships](defining-relationships.md) skill.
|
|
19
|
+
4. **Enable Automatic APIs**: If you add `@table @export` to a schema type, Harper automatically sets up REST and WebSocket APIs for basic CRUD operations against that table. For a detailed list of available endpoints and how to use them, see the [Automatic REST APIs](automatic-apis.md) skill.
|
|
20
|
+
- `GET /{TableName}`: Describes the schema itself.
|
|
21
|
+
- `GET /{TableName}/`: Lists all records (supports filtering, sorting, and pagination via query parameters). See the [Querying REST APIs](querying-rest-apis.md) skill for details.
|
|
22
|
+
- `GET /{TableName}/{id}`: Retrieves a single record by its ID.
|
|
23
|
+
- `POST /{TableName}/`: Creates a new record.
|
|
24
|
+
- `PUT /{TableName}/{id}`: Updates an existing record.
|
|
25
|
+
- `PATCH /{TableName}/{id}`: Performs a partial update on a record.
|
|
26
|
+
- `DELETE /{TableName}/`: Deletes all records or filtered records.
|
|
27
|
+
- `DELETE /{TableName}/{id}`: Deletes a single record by its ID.
|
|
28
|
+
5. **Consider Table Extensions**: If you are going to [extend the table](./extending-tables.md) in your resources, then do not `@export` the table from the schema.
|
|
29
|
+
|
|
30
|
+
### Example
|
|
31
|
+
|
|
32
|
+
In a hypothetical `schemas/ExamplePerson.graphql`:
|
|
33
|
+
|
|
34
|
+
```graphql
|
|
35
|
+
type ExamplePerson @table @export {
|
|
36
|
+
id: ID @primaryKey
|
|
37
|
+
name: String
|
|
38
|
+
tag: String @indexed
|
|
39
|
+
}
|
|
40
|
+
```
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: automatic-apis
|
|
3
|
+
description: How to use Harper's automatically generated REST and WebSocket APIs.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Automatic APIs
|
|
7
|
+
|
|
8
|
+
Instructions for the agent to follow when utilizing Harper's automatic APIs.
|
|
9
|
+
|
|
10
|
+
## When to Use
|
|
11
|
+
|
|
12
|
+
Use this skill when you want to interact with Harper tables via REST or WebSockets without writing custom resource logic. This is ideal for basic CRUD operations and real-time updates.
|
|
13
|
+
|
|
14
|
+
## Steps
|
|
15
|
+
|
|
16
|
+
1. **Enable Automatic APIs**: Ensure your GraphQL schema includes the `@export` directive for the table:
|
|
17
|
+
```graphql
|
|
18
|
+
type MyTable @table @export {
|
|
19
|
+
id: ID @primaryKey
|
|
20
|
+
# ... other fields
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
2. **Access REST Endpoints**: Use the following endpoints for a table named `TableName` (Note: Paths are **case-sensitive**):
|
|
24
|
+
- **Describe Schema**: `GET /{TableName}`
|
|
25
|
+
- **List Records**: `GET /{TableName}/` (Supports filtering, sorting, and pagination. See [Querying REST APIs](querying-rest-apis.md)).
|
|
26
|
+
- **Get Single Record**: `GET /{TableName}/{id}`
|
|
27
|
+
- **Create Record**: `POST /{TableName}/` (Request body should be JSON).
|
|
28
|
+
- **Update Record (Full)**: `PUT /{TableName}/{id}`
|
|
29
|
+
- **Update Record (Partial)**: `PATCH /{TableName}/{id}`
|
|
30
|
+
- **Delete All/Filtered Records**: `DELETE /{TableName}/`
|
|
31
|
+
- **Delete Single Record**: `DELETE /{TableName}/{id}`
|
|
32
|
+
3. **Use Automatic WebSockets**: Connect to `ws://your-harper-instance/{TableName}` to receive events whenever updates are made to that table. This is the easiest way to add real-time capabilities. For more complex needs, see [Real-time Applications](real-time-apps.md).
|
|
33
|
+
4. **Apply Filtering and Querying**: Use query parameters with `GET /{TableName}/` and `DELETE /{TableName}/`. See the [Querying REST APIs](querying-rest-apis.md) skill for advanced details.
|
|
34
|
+
5. **Customize if Needed**: If the automatic APIs don't meet your requirements, [customize the resources](./custom-resources.md).
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: caching
|
|
3
|
+
description: How to implement integrated data caching in Harper from external sources.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Caching
|
|
7
|
+
|
|
8
|
+
Instructions for the agent to follow when implementing caching in Harper.
|
|
9
|
+
|
|
10
|
+
## When to Use
|
|
11
|
+
|
|
12
|
+
Use this skill when you need high-performance, low-latency storage for data from external sources. It's ideal for reducing API calls to third-party services, preventing cache stampedes, and making external data queryable as if it were native Harper tables.
|
|
13
|
+
|
|
14
|
+
## Steps
|
|
15
|
+
|
|
16
|
+
1. **Configure a Cache Table**: Define a table in your `schema.graphql` with an `expiration` (in seconds):
|
|
17
|
+
```graphql
|
|
18
|
+
type MyCache @table(expiration: 3600) @export {
|
|
19
|
+
id: ID @primaryKey
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
2. **Define an External Source**: Create a Resource class that fetches the data:
|
|
23
|
+
```js
|
|
24
|
+
import { Resource } from 'harperdb';
|
|
25
|
+
|
|
26
|
+
export class ThirdPartyAPI extends Resource {
|
|
27
|
+
async get() {
|
|
28
|
+
const id = this.getId();
|
|
29
|
+
const response = await fetch(`https://api.example.com/items/${id}`);
|
|
30
|
+
if (!response.ok) {
|
|
31
|
+
throw new Error('Source fetch failed');
|
|
32
|
+
}
|
|
33
|
+
return await response.json();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
3. **Attach Source to Table**: Use `sourcedFrom` to link your resource to the table:
|
|
38
|
+
```js
|
|
39
|
+
import { tables } from 'harperdb';
|
|
40
|
+
import { ThirdPartyAPI } from './ThirdPartyAPI.js';
|
|
41
|
+
|
|
42
|
+
const { MyCache } = tables;
|
|
43
|
+
MyCache.sourcedFrom(ThirdPartyAPI);
|
|
44
|
+
```
|
|
45
|
+
4. **Implement Active Caching (Optional)**: Use `subscribe()` for proactive updates. See [Real Time Apps](real-time-apps.md).
|
|
46
|
+
5. **Implement Write-Through Caching (Optional)**: Define `put` or `post` in your resource to propagate updates upstream.
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: checking-authentication
|
|
3
|
+
description: How to handle user authentication and sessions in Harper Resources.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Checking Authentication
|
|
7
|
+
|
|
8
|
+
Instructions for the agent to follow when handling authentication and sessions.
|
|
9
|
+
|
|
10
|
+
## When to Use
|
|
11
|
+
|
|
12
|
+
Use this skill when you need to implement sign-in/sign-out functionality, protect specific resource endpoints, or identify the currently logged-in user in a Harper application.
|
|
13
|
+
|
|
14
|
+
## Steps
|
|
15
|
+
|
|
16
|
+
1. **Configure Harper for Sessions**: Ensure `harperdb-config.yaml` has sessions enabled and local auto-authorization disabled for testing:
|
|
17
|
+
```yaml
|
|
18
|
+
authentication:
|
|
19
|
+
authorizeLocal: false
|
|
20
|
+
enableSessions: true
|
|
21
|
+
```
|
|
22
|
+
2. **Implement Sign In**: Use `this.getContext().login(username, password)` to create a session:
|
|
23
|
+
```ts
|
|
24
|
+
async post(_target, data) {
|
|
25
|
+
const context = this.getContext();
|
|
26
|
+
try {
|
|
27
|
+
await context.login(data.username, data.password);
|
|
28
|
+
} catch {
|
|
29
|
+
return new Response('Invalid credentials', { status: 403 });
|
|
30
|
+
}
|
|
31
|
+
return new Response('Logged in', { status: 200 });
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
3. **Identify Current User**: Use `this.getCurrentUser()` to access session data:
|
|
35
|
+
```ts
|
|
36
|
+
async get() {
|
|
37
|
+
const user = this.getCurrentUser?.();
|
|
38
|
+
if (!user) return new Response(null, { status: 401 });
|
|
39
|
+
return { username: user.username, role: user.role };
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
4. **Implement Sign Out**: Use `this.getContext().logout()` or delete the session from context:
|
|
43
|
+
```ts
|
|
44
|
+
async post() {
|
|
45
|
+
const context = this.getContext();
|
|
46
|
+
await context.session?.delete?.(context.session.id);
|
|
47
|
+
return new Response('Logged out', { status: 200 });
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
5. **Protect Routes**: In your Resource, use `allowRead()`, `allowUpdate()`, etc., to enforce authorization logic based on `this.getCurrentUser()`. For privileged actions, verify `user.role.permission.super_user`.
|
|
51
|
+
|
|
52
|
+
## Status code conventions used here
|
|
53
|
+
|
|
54
|
+
- 200: Successful operation. For `GET /me`, a `200` with empty body means “not signed in”.
|
|
55
|
+
- 400: Missing required fields (e.g., username/password on sign-in).
|
|
56
|
+
- 401: No current session for an action that requires one (e.g., sign out when not signed in).
|
|
57
|
+
- 403: Authenticated but not authorized (bad credentials on login attempt, or insufficient privileges).
|
|
58
|
+
|
|
59
|
+
## Client considerations
|
|
60
|
+
|
|
61
|
+
- Sessions are cookie-based; the server handles setting and reading the cookie via Harper. If you make cross-origin requests, ensure the appropriate `credentials` mode and CORS settings.
|
|
62
|
+
- If developing locally, double-check the server config still has `authentication.authorizeLocal: false` to avoid accidental superuser bypass.
|
|
63
|
+
|
|
64
|
+
## Token-based auth (JWT + refresh token) for non-browser clients
|
|
65
|
+
|
|
66
|
+
Cookie-backed sessions are great for browser flows. For CLI tools, mobile apps, or other non-browser clients, it’s often easier to use **explicit tokens**:
|
|
67
|
+
|
|
68
|
+
- **JWT (`operation_token`)**: short-lived bearer token used to authorize API requests.
|
|
69
|
+
- **Refresh token (`refresh_token`)**: longer-lived token used to mint a new JWT when it expires.
|
|
70
|
+
|
|
71
|
+
This project includes two Resource patterns for that flow:
|
|
72
|
+
|
|
73
|
+
### Issuing tokens: `IssueTokens`
|
|
74
|
+
|
|
75
|
+
**Description / use case:** Generate `{ refreshToken, jwt }` either:
|
|
76
|
+
|
|
77
|
+
- with an existing Authorization token (either Basic Auth or a JWT) and you want to issue new tokens, or
|
|
78
|
+
- from an explicit `{ username, password }` payload (useful for direct “login” from a CLI/mobile client).
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
js
|
|
82
|
+
export class IssueTokens extends Resource {
|
|
83
|
+
static loadAsInstance = false;
|
|
84
|
+
|
|
85
|
+
async get(target) {
|
|
86
|
+
const { refresh_token: refreshToken, operation_token: jwt } =
|
|
87
|
+
await databases.system.hdb_user.operation(
|
|
88
|
+
{ operation: 'create_authentication_tokens' },
|
|
89
|
+
this.getContext(),
|
|
90
|
+
);
|
|
91
|
+
return { refreshToken, jwt };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async post(target, data) {
|
|
95
|
+
if (!data.username || !data.password) {
|
|
96
|
+
throw new Error('username and password are required');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const { refresh_token: refreshToken, operation_token: jwt } =
|
|
100
|
+
await databases.system.hdb_user.operation({
|
|
101
|
+
operation: 'create_authentication_tokens',
|
|
102
|
+
username: data.username,
|
|
103
|
+
password: data.password,
|
|
104
|
+
});
|
|
105
|
+
return { refreshToken, jwt };
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**Recommended documentation notes to include:**
|
|
111
|
+
|
|
112
|
+
- `GET` variant: intended for “I already have an Authorization token, give me new tokens”.
|
|
113
|
+
- `POST` variant: intended for “I have credentials, give me tokens”.
|
|
114
|
+
- Response shape:
|
|
115
|
+
- `refreshToken`: store securely (long-lived).
|
|
116
|
+
- `jwt`: attach to requests (short-lived).
|
|
117
|
+
|
|
118
|
+
### Refreshing a JWT: `RefreshJWT`
|
|
119
|
+
|
|
120
|
+
**Description / use case:** When the JWT expires, the client uses the refresh token to get a new JWT without re-supplying username/password.
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
js
|
|
124
|
+
export class RefreshJWT extends Resource {
|
|
125
|
+
static loadAsInstance = false;
|
|
126
|
+
|
|
127
|
+
async post(target, data) {
|
|
128
|
+
if (!data.refreshToken) {
|
|
129
|
+
throw new Error('refreshToken is required');
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const { operation_token: jwt } = await databases.system.hdb_user.operation({
|
|
133
|
+
operation: 'refresh_operation_token',
|
|
134
|
+
refresh_token: data.refreshToken,
|
|
135
|
+
});
|
|
136
|
+
return { jwt };
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Recommended documentation notes to include:**
|
|
142
|
+
|
|
143
|
+
- Requires `refreshToken` in the request body.
|
|
144
|
+
- Returns a new `{ jwt }`.
|
|
145
|
+
- If refresh fails (expired/revoked), client must re-authenticate (e.g., call `IssueTokens.post` again).
|
|
146
|
+
|
|
147
|
+
### Suggested client flow (high-level)
|
|
148
|
+
|
|
149
|
+
1. **Sign in (token flow)**
|
|
150
|
+
- POST /IssueTokens/ with a body of `{ "username": "your username", "password": "your password" }` or GET /IssueTokens/ with an existing Authorization token.
|
|
151
|
+
- Receive `{ jwt, refreshToken }` in the response
|
|
152
|
+
2. **Call protected APIs**
|
|
153
|
+
- Send the JWT with each request in the Authorization header (as your auth mechanism expects)
|
|
154
|
+
3. **JWT expires**
|
|
155
|
+
- POST /RefreshJWT/ with a body of `{ "refreshToken": "your refresh token" }`.
|
|
156
|
+
- Receive `{ jwt }` in the response and continue
|
|
157
|
+
|
|
158
|
+
## Quick checklist
|
|
159
|
+
|
|
160
|
+
- [ ] Public endpoints explicitly `allowRead`/`allowCreate` as needed.
|
|
161
|
+
- [ ] Sign-in uses `context.login` and handles 400/403 correctly.
|
|
162
|
+
- [ ] Protected routes call `ensureSuperUser(this.getCurrentUser())` (or another role check) before doing work.
|
|
163
|
+
- [ ] Sign-out verifies a session and deletes it.
|
|
164
|
+
- [ ] `authentication.authorizeLocal` is `false` and `enableSessions` is `true` in Harper config.
|
|
165
|
+
- [ ] If using tokens: `IssueTokens` issues `{ jwt, refreshToken }`, `RefreshJWT` refreshes `{ jwt }` with a `refreshToken`.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: custom-resources
|
|
3
|
+
description: How to define custom REST endpoints with JavaScript or TypeScript in Harper.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Custom Resources
|
|
7
|
+
|
|
8
|
+
Instructions for the agent to follow when creating custom resources in Harper.
|
|
9
|
+
|
|
10
|
+
## When to Use
|
|
11
|
+
|
|
12
|
+
Use this skill when the automatic CRUD operations provided by `@table @export` are insufficient, and you need custom logic, third-party API integration, or specialized data handling for your REST endpoints.
|
|
13
|
+
|
|
14
|
+
## Steps
|
|
15
|
+
|
|
16
|
+
1. **Check if a Custom Resource is Necessary**: Verify if [Automatic APIs](./automatic-apis.md) or [Extending Tables](./extending-tables.md) can satisfy the requirement first.
|
|
17
|
+
2. **Create the Resource File**: Create a `.ts` or `.js` file in the directory specified by `jsResource` in `config.yaml` (typically `resources/`).
|
|
18
|
+
3. **Define the Resource Class**: Export a class extending `Resource` from `harperdb`:
|
|
19
|
+
```typescript
|
|
20
|
+
import { type RequestTargetOrId, Resource } from 'harperdb';
|
|
21
|
+
|
|
22
|
+
export class MyResource extends Resource {
|
|
23
|
+
async get(target?: RequestTargetOrId) {
|
|
24
|
+
return { message: 'Hello from custom GET!' };
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
4. **Implement HTTP Methods**: Add methods like `get`, `post`, `put`, `patch`, or `delete` to handle corresponding requests. Note that paths are **case-sensitive** and match the class name.
|
|
29
|
+
5. **Access Tables (Optional)**: Import and use the `tables` object to interact with your data:
|
|
30
|
+
```typescript
|
|
31
|
+
import { tables } from 'harperdb';
|
|
32
|
+
// ... inside a method
|
|
33
|
+
const results = await tables.MyTable.list();
|
|
34
|
+
```
|
|
35
|
+
6. **Configure Loading**: Ensure `config.yaml` points to your resource files (e.g., `jsResource: { files: 'resources/*.ts' }`).
|