@harperfast/skills 1.4.4 → 1.4.5
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/dist/index.js
CHANGED
|
@@ -28,8 +28,8 @@ export const ruleNames = [
|
|
|
28
28
|
* A map from rule names to their markdown content.
|
|
29
29
|
*/
|
|
30
30
|
export const rules = {
|
|
31
|
-
"adding-tables-with-schemas": "---\nname: adding-tables-with-schemas\ndescription: Guidelines for adding tables to a Harper database using GraphQL schemas.\n---\n\n# Adding Tables with Schemas\n\nInstructions for the agent to follow when adding tables to a Harper database.\n\n## When to Use\n\nUse this skill when you need to define new data structures or modify existing ones in a Harper database.\n\n## How It Works\n\n1. **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.\n2. **Use Directives**: All available directives for defining your schema are defined in `node_modules/harper/schema.graphql`. Common directives include `@table`, `@export`, `@primaryKey`, `@indexed`, and `@relationship`.\n3. **Define Relationships**: Link tables together using the `@relationship` directive. For more details, see the [Defining Relationships](defining-relationships.md) skill.\n4. **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.\n - `GET /{TableName}`: Describes the schema itself.\n - `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.\n - `GET /{TableName}/{id}`: Retrieves a single record by its ID.\n - `POST /{TableName}/`: Creates a new record.\n - `PUT /{TableName}/{id}`: Updates an existing record.\n - `PATCH /{TableName}/{id}`: Performs a partial update on a record.\n - `DELETE /{TableName}/`: Deletes all records or filtered records.\n - `DELETE /{TableName}/{id}`: Deletes a single record by its ID.\n5. **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.\n\n## Examples\n\nIn a hypothetical `schemas/ExamplePerson.graphql`:\n\n```graphql\ntype ExamplePerson @table @export {\n\tid: ID @primaryKey\n\tname: String\n\ttag: String @indexed\n}\n```\n",
|
|
32
|
-
"automatic-apis": "---\nname: automatic-apis\ndescription: How to use Harper's automatically generated REST and WebSocket APIs.\n---\n\n# Automatic APIs\n\nInstructions for the agent to follow when utilizing Harper's automatic APIs.\n\n## When to Use\n\nUse 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.\n\n## How It Works\n\n1. **Enable Automatic APIs**: Ensure your GraphQL schema includes the `@export` directive for the table.\
|
|
31
|
+
"adding-tables-with-schemas": "---\nname: adding-tables-with-schemas\ndescription: Guidelines for adding tables to a Harper database using GraphQL schemas.\n---\n\n# Adding Tables with Schemas\n\nInstructions for the agent to follow when adding tables to a Harper database.\n\n## When to Use\n\nUse this skill when you need to define new data structures or modify existing ones in a Harper database.\n\n## How It Works\n\n1. **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.\n2. **Use Directives**: All available directives for defining your schema are defined in `node_modules/harper/schema.graphql`. Common directives include `@table`, `@export`, `@primaryKey`, `@indexed`, and `@relationship`.\n3. **Define Relationships**: Link tables together using the `@relationship` directive. For more details, see the [Defining Relationships](defining-relationships.md) skill.\n4. **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. **Important**: REST endpoints also require `rest: true` in `config.yaml` — without it, `@export`ed tables will not respond to HTTP requests. For a detailed list of available endpoints and how to use them, see the [Automatic REST APIs](automatic-apis.md) skill.\n - `GET /{TableName}`: Describes the schema itself.\n - `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.\n - `GET /{TableName}/{id}`: Retrieves a single record by its ID.\n - `POST /{TableName}/`: Creates a new record.\n - `PUT /{TableName}/{id}`: Updates an existing record.\n - `PATCH /{TableName}/{id}`: Performs a partial update on a record.\n - `DELETE /{TableName}/`: Deletes all records or filtered records.\n - `DELETE /{TableName}/{id}`: Deletes a single record by its ID.\n5. **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.\n\n## Examples\n\nIn a hypothetical `schemas/ExamplePerson.graphql`:\n\n```graphql\ntype ExamplePerson @table @export {\n\tid: ID @primaryKey\n\tname: String\n\ttag: String @indexed\n}\n```\n",
|
|
32
|
+
"automatic-apis": "---\nname: automatic-apis\ndescription: How to use Harper's automatically generated REST and WebSocket APIs.\n---\n\n# Automatic APIs\n\nInstructions for the agent to follow when utilizing Harper's automatic APIs.\n\n## When to Use\n\nUse 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.\n\n## How It Works\n\n1. **Enable REST in `config.yaml`**: REST endpoints are **not active by default**. You must explicitly enable them:\n ```yaml\n rest: true\n ```\n Without this, `@export`ed tables will not respond to HTTP requests.\n2. **Enable Automatic APIs**: Ensure your GraphQL schema includes the `@export` directive for the table.\n3. **Access REST Endpoints**: Use the standard endpoints for your table (Note: Paths are case-sensitive).\n4. **Use Automatic WebSockets**: Connect to `wss://your-harper-instance/{TableName}` to receive events whenever updates are made to that table. This is the easiest way to add real-time capabilities. (Use `ws://` for local development without SSL). For more complex needs, see [Real-time Apps](real-time-apps.md).\n5. **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.\n6. **Customize if Needed**: If the automatic APIs don't meet your requirements, [customize the resources](./custom-resources.md).\n\n## Examples\n\n### Schema Configuration\n\n```graphql\ntype MyTable @table @export {\n\tid: ID @primaryKey\n\tname: String\n}\n```\n\n### Common REST Operations\n\n- **List Records**: `GET /MyTable/`\n- **Create Record**: `POST /MyTable/`\n- **Update Record**: `PATCH /MyTable/{id}`\n",
|
|
33
33
|
"caching": "---\nname: caching\ndescription: How to implement integrated data caching in Harper from external sources.\n---\n\n# Caching\n\nInstructions for the agent to follow when implementing caching in Harper.\n\n## When to Use\n\nUse 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.\n\n## How It Works\n\n1. **Configure a Cache Table**: Define a table in your `schema.graphql` with an `expiration` (in seconds).\n2. **Define an External Source**: Create a Resource class that fetches the data from your source.\n3. **Attach Source to Table**: Use `sourcedFrom` to link your resource to the table.\n4. **Implement Active Caching (Optional)**: Use `subscribe()` for proactive updates. See [Real-Time Apps](real-time-apps.md).\n5. **Implement Write-Through Caching (Optional)**: Define `put` or `post` in your resource to propagate updates upstream.\n\n## Examples\n\n### Schema Configuration\n\n```graphql\ntype MyCache @table(expiration: 3600) @export {\n\tid: ID @primaryKey\n}\n```\n\n### Resource Implementation\n\n```js\nimport { Resource, tables } from 'harper';\n\nexport class ThirdPartyAPI extends Resource {\n\tasync get() {\n\t\tconst id = this.getId();\n\t\tconst response = await fetch(`https://api.example.com/items/${id}`);\n\t\tif (!response.ok) {\n\t\t\tthrow new Error('Source fetch failed');\n\t\t}\n\t\treturn await response.json();\n\t}\n}\n\n// Attach source to table\ntables.MyCache.sourcedFrom(ThirdPartyAPI);\n```\n",
|
|
34
34
|
"checking-authentication": "---\nname: checking-authentication\ndescription: How to handle user authentication and sessions in Harper Resources.\n---\n\n# Checking Authentication\n\nInstructions for the agent to follow when handling authentication and sessions.\n\n## When to Use\n\nUse 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.\n\n## How It Works\n\n1. **Configure Harper for Sessions**: Ensure `harper-config.yaml` has sessions enabled and local auto-authorization disabled for testing:\n ```yaml\n authentication:\n authorizeLocal: false\n enableSessions: true\n ```\n2. **Implement Sign In**: Use `this.getContext().login(username, password)` to create a session:\n ```typescript\n async post(_target, data) {\n const context = this.getContext();\n try {\n await context.login(data.username, data.password);\n } catch {\n return new Response('Invalid credentials', { status: 403 });\n }\n return new Response('Logged in', { status: 200 });\n }\n ```\n3. **Identify Current User**: Use `this.getCurrentUser()` to access session data:\n ```typescript\n async get() {\n const user = this.getCurrentUser?.();\n if (!user) return new Response(null, { status: 401 });\n return { username: user.username, role: user.role };\n }\n ```\n4. **Implement Sign Out**: Use `this.getContext().logout()` or delete the session from context:\n ```typescript\n async post() {\n const context = this.getContext();\n await context.session?.delete?.(context.session.id);\n return new Response('Logged out', { status: 200 });\n }\n ```\n5. **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`.\n\n## Examples\n\n### Sign In Implementation\n\n```typescript\nasync post(_target, data) {\n const context = this.getContext();\n try {\n await context.login(data.username, data.password);\n } catch {\n return new Response('Invalid credentials', { status: 403 });\n }\n return new Response('Logged in', { status: 200 });\n}\n```\n\n### Identify Current User\n\n```typescript\nasync get() {\n const user = this.getCurrentUser?.();\n if (!user) return new Response(null, { status: 401 });\n return { username: user.username, role: user.role };\n}\n```\n\n### Sign Out Implementation\n\n```typescript\nasync post() {\n const context = this.getContext();\n await context.session?.delete?.(context.session.id);\n return new Response('Logged out', { status: 200 });\n}\n```\n\n## Status code conventions used here\n\n- 200: Successful operation. For `GET /me`, a `200` with empty body means “not signed in”.\n- 400: Missing required fields (e.g., username/password on sign-in).\n- 401: No current session for an action that requires one (e.g., sign out when not signed in).\n- 403: Authenticated but not authorized (bad credentials on login attempt, or insufficient privileges).\n\n## Client considerations\n\n- 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.\n- If developing locally, double-check the server config still has `authentication.authorizeLocal: false` to avoid accidental superuser bypass.\n\n## Token-based auth (JWT + refresh token) for non-browser clients\n\nCookie-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**:\n\n- **JWT (`operation_token`)**: short-lived bearer token used to authorize API requests.\n- **Refresh token (`refresh_token`)**: longer-lived token used to mint a new JWT when it expires.\n\nThis project includes two Resource patterns for that flow:\n\n### Issuing tokens: `IssueTokens`\n\n**Description / use case:** Generate `{ refreshToken, jwt }` either:\n\n- with an existing Authorization token (either Basic Auth or a JWT) and you want to issue new tokens, or\n- from an explicit `{ username, password }` payload (useful for direct “login” from a CLI/mobile client).\n\n```javascript\nexport class IssueTokens extends Resource {\n\tstatic loadAsInstance = false;\n\n\tasync get(target) {\n\t\tconst { refresh_token: refreshToken, operation_token: jwt } =\n\t\t\tawait databases.system.hdb_user.operation(\n\t\t\t\t{ operation: 'create_authentication_tokens' },\n\t\t\t\tthis.getContext(),\n\t\t\t);\n\t\treturn { refreshToken, jwt };\n\t}\n\n\tasync post(target, data) {\n\t\tif (!data.username || !data.password) {\n\t\t\tthrow new Error('username and password are required');\n\t\t}\n\n\t\tconst { refresh_token: refreshToken, operation_token: jwt } =\n\t\t\tawait databases.system.hdb_user.operation({\n\t\t\t\toperation: 'create_authentication_tokens',\n\t\t\t\tusername: data.username,\n\t\t\t\tpassword: data.password,\n\t\t\t});\n\t\treturn { refreshToken, jwt };\n\t}\n}\n```\n\n**Recommended documentation notes to include:**\n\n- `GET` variant: intended for “I already have an Authorization token, give me new tokens”.\n- `POST` variant: intended for “I have credentials, give me tokens”.\n- Response shape:\n - `refreshToken`: store securely (long-lived).\n - `jwt`: attach to requests (short-lived).\n\n### Refreshing a JWT: `RefreshJWT`\n\n**Description / use case:** When the JWT expires, the client uses the refresh token to get a new JWT without re-supplying username/password.\n\n```javascript\nexport class RefreshJWT extends Resource {\n\tstatic loadAsInstance = false;\n\n\tasync post(target, data) {\n\t\tif (!data.refreshToken) {\n\t\t\tthrow new Error('refreshToken is required');\n\t\t}\n\n\t\tconst { operation_token: jwt } = await databases.system.hdb_user.operation({\n\t\t\toperation: 'refresh_operation_token',\n\t\t\trefresh_token: data.refreshToken,\n\t\t});\n\t\treturn { jwt };\n\t}\n}\n```\n\n**Recommended documentation notes to include:**\n\n- Requires `refreshToken` in the request body.\n- Returns a new `{ jwt }`.\n- If refresh fails (expired/revoked), client must re-authenticate (e.g., call `IssueTokens.post` again).\n\n### Suggested client flow (high-level)\n\n1. **Sign in (token flow)**\n - POST /IssueTokens/ with a body of `{ \"username\": \"your username\", \"password\": \"your password\" }` or GET /IssueTokens/ with an existing Authorization token.\n - Receive `{ jwt, refreshToken }` in the response\n2. **Call protected APIs**\n - Send the JWT with each request in the Authorization header (as your auth mechanism expects)\n3. **JWT expires**\n - POST /RefreshJWT/ with a body of `{ \"refreshToken\": \"your refresh token\" }`.\n - Receive `{ jwt }` in the response and continue\n\n## Quick checklist\n\n- [ ] Public endpoints explicitly `allowRead`/`allowCreate` as needed.\n- [ ] Sign-in uses `context.login` and handles 400/403 correctly.\n- [ ] Protected routes call `ensureSuperUser(this.getCurrentUser())` (or another role check) before doing work.\n- [ ] Sign-out verifies a session and deletes it.\n- [ ] `authentication.authorizeLocal` is `false` and `enableSessions` is `true` in Harper config.\n- [ ] If using tokens: `IssueTokens` issues `{ jwt, refreshToken }`, `RefreshJWT` refreshes `{ jwt }` with a `refreshToken`.\n",
|
|
35
35
|
"creating-a-fabric-account-and-cluster": "---\nname: creating-a-fabric-account-and-cluster\ndescription: How to create a Harper Fabric account, organization, and cluster.\n---\n\n# Creating a Harper Fabric Account and Cluster\n\nFollow these steps to set up your Harper Fabric environment for deployment.\n\n## How It Works\n\n1. **Sign Up/In**: Go to [https://fabric.harper.fast/](https://fabric.harper.fast/) and sign up or sign in.\n2. **Create an Organization**: Create an organization (org) to manage your projects.\n3. **Create a Cluster**: Create a new cluster. This can be on the free tier, no credit card required.\n4. **Set Credentials**: During setup, set the cluster username and password to finish configuring it.\n5. **Get Application URL**: Navigate to the **Config** tab and copy the **Application URL**.\n6. **Configure Environment**: Update your `.env` file or GitHub Actions secrets with cluster-specific credentials.\n7. **Next Steps**: See the [deploying-to-harper-fabric](deploying-to-harper-fabric.md) rule for detailed instructions on deploying your application successfully.\n\n## Examples\n\n### Environment Configuration\n\n```bash\nCLI_TARGET_USERNAME='YOUR_CLUSTER_USERNAME'\nCLI_TARGET_PASSWORD='YOUR_CLUSTER_PASSWORD'\nCLI_TARGET='YOUR_CLUSTER_URL'\n```\n",
|
|
@@ -50,7 +50,7 @@ Use this skill when you need to define new data structures or modify existing on
|
|
|
50
50
|
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.
|
|
51
51
|
2. **Use Directives**: All available directives for defining your schema are defined in `node_modules/harper/schema.graphql`. Common directives include `@table`, `@export`, `@primaryKey`, `@indexed`, and `@relationship`.
|
|
52
52
|
3. **Define Relationships**: Link tables together using the `@relationship` directive.
|
|
53
|
-
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.
|
|
53
|
+
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. **Important**: REST endpoints also require `rest: true` in `config.yaml` — without it, `@export`ed tables will not respond to HTTP requests.
|
|
54
54
|
5. **Consider Table Extensions**: If you are going to extend the table in your resources, then do not `@export` the table from the schema.
|
|
55
55
|
|
|
56
56
|
#### Example
|
|
@@ -16,7 +16,7 @@ Use this skill when you need to define new data structures or modify existing on
|
|
|
16
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
17
|
2. **Use Directives**: All available directives for defining your schema are defined in `node_modules/harper/schema.graphql`. Common directives include `@table`, `@export`, `@primaryKey`, `@indexed`, and `@relationship`.
|
|
18
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.
|
|
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. **Important**: REST endpoints also require `rest: true` in `config.yaml` — without it, `@export`ed tables will not respond to HTTP requests. For a detailed list of available endpoints and how to use them, see the [Automatic REST APIs](automatic-apis.md) skill.
|
|
20
20
|
- `GET /{TableName}`: Describes the schema itself.
|
|
21
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
22
|
- `GET /{TableName}/{id}`: Retrieves a single record by its ID.
|
|
@@ -13,11 +13,16 @@ Use this skill when you want to interact with Harper tables via REST or WebSocke
|
|
|
13
13
|
|
|
14
14
|
## How It Works
|
|
15
15
|
|
|
16
|
-
1. **Enable
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
1. **Enable REST in `config.yaml`**: REST endpoints are **not active by default**. You must explicitly enable them:
|
|
17
|
+
```yaml
|
|
18
|
+
rest: true
|
|
19
|
+
```
|
|
20
|
+
Without this, `@export`ed tables will not respond to HTTP requests.
|
|
21
|
+
2. **Enable Automatic APIs**: Ensure your GraphQL schema includes the `@export` directive for the table.
|
|
22
|
+
3. **Access REST Endpoints**: Use the standard endpoints for your table (Note: Paths are case-sensitive).
|
|
23
|
+
4. **Use Automatic WebSockets**: Connect to `wss://your-harper-instance/{TableName}` to receive events whenever updates are made to that table. This is the easiest way to add real-time capabilities. (Use `ws://` for local development without SSL). For more complex needs, see [Real-time Apps](real-time-apps.md).
|
|
24
|
+
5. **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.
|
|
25
|
+
6. **Customize if Needed**: If the automatic APIs don't meet your requirements, [customize the resources](./custom-resources.md).
|
|
21
26
|
|
|
22
27
|
## Examples
|
|
23
28
|
|