@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.
Files changed (41) hide show
  1. package/.agents/skills/harper-best-practices/AGENTS.md +258 -0
  2. package/.agents/skills/harper-best-practices/SKILL.md +88 -0
  3. package/.agents/skills/harper-best-practices/rules/adding-tables-with-schemas.md +40 -0
  4. package/.agents/skills/harper-best-practices/rules/automatic-apis.md +34 -0
  5. package/.agents/skills/harper-best-practices/rules/caching.md +46 -0
  6. package/.agents/skills/harper-best-practices/rules/checking-authentication.md +165 -0
  7. package/.agents/skills/harper-best-practices/rules/custom-resources.md +35 -0
  8. package/.agents/skills/harper-best-practices/rules/defining-relationships.md +33 -0
  9. package/.agents/skills/harper-best-practices/rules/deploying-to-harper-fabric.md +24 -0
  10. package/.agents/skills/harper-best-practices/rules/extending-tables.md +37 -0
  11. package/.agents/skills/harper-best-practices/rules/handling-binary-data.md +43 -0
  12. package/.agents/skills/harper-best-practices/rules/programmatic-table-requests.md +39 -0
  13. package/.agents/skills/harper-best-practices/rules/querying-rest-apis.md +22 -0
  14. package/.agents/skills/harper-best-practices/rules/real-time-apps.md +37 -0
  15. package/.agents/skills/harper-best-practices/rules/serving-web-content.md +34 -0
  16. package/.agents/skills/harper-best-practices/rules/typescript-type-stripping.md +32 -0
  17. package/.agents/skills/harper-best-practices/rules/using-blob-datatype.md +36 -0
  18. package/.agents/skills/harper-best-practices/rules/vector-indexing.md +152 -0
  19. package/README.md +1 -1
  20. package/package.json +1 -1
  21. package/resources/README.md +3 -3
  22. package/schemas/README.md +2 -2
  23. package/skills-lock.json +10 -0
  24. package/AGENTS.md +0 -22
  25. package/skills/adding-tables-with-schemas.md +0 -34
  26. package/skills/automatic-apis.md +0 -53
  27. package/skills/automatic-rest-apis.md +0 -41
  28. package/skills/caching.md +0 -113
  29. package/skills/checking-authentication.md +0 -281
  30. package/skills/custom-resources.md +0 -86
  31. package/skills/defining-relationships.md +0 -71
  32. package/skills/deploying-to-harper-fabric.md +0 -20
  33. package/skills/extending-tables.md +0 -70
  34. package/skills/handling-binary-data.md +0 -67
  35. package/skills/programmatic-table-requests.md +0 -185
  36. package/skills/querying-rest-apis.md +0 -69
  37. package/skills/real-time-apps.md +0 -75
  38. package/skills/serving-web-content.md +0 -82
  39. package/skills/typescript-type-stripping.md +0 -47
  40. package/skills/using-blob-datatype.md +0 -131
  41. 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' }`).