@harperfast/template-react-ts-studio 1.11.3 → 1.11.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/.agents/skills/harper-best-practices/AGENTS.md +567 -490
- package/.agents/skills/harper-best-practices/rules/automatic-apis.md +46 -78
- package/.agents/skills/harper-best-practices/rules/defining-relationships.md +41 -63
- package/.agents/skills/harper-best-practices/rules/deploying-to-harper-fabric.md +59 -45
- package/.agents/skills/harper-best-practices/rules/load-env.md +24 -23
- package/.agents/skills/harper-best-practices/rules/programmatic-table-requests.md +62 -78
- package/.agents/skills/harper-best-practices/rules/querying-rest-apis.md +92 -65
- package/.agents/skills/harper-best-practices/rules/schema-design-tooling.md +53 -55
- package/.agents/skills/harper-best-practices/rules/v5-upgrade.md +98 -62
- package/.agents/skills/harper-best-practices/rules/vector-indexing.md +113 -42
- package/.agents/skills/harper-mcp/AGENTS.md +501 -0
- package/.agents/skills/harper-mcp/SKILL.md +91 -0
- package/.agents/skills/harper-mcp/rules/automatic-verb-tools.md +50 -0
- package/.agents/skills/harper-mcp/rules/connecting-clients.md +59 -0
- package/.agents/skills/harper-mcp/rules/custom-mcp-prompts.md +52 -0
- package/.agents/skills/harper-mcp/rules/custom-mcp-resources.md +64 -0
- package/.agents/skills/harper-mcp/rules/custom-mcp-tools.md +72 -0
- package/.agents/skills/harper-mcp/rules/durable-quotas.md +73 -0
- package/.agents/skills/harper-mcp/rules/enabling-mcp.md +63 -0
- package/.agents/skills/harper-mcp/rules/rate-limiting.md +62 -0
- package/.agents/skills/harper-mcp/rules/resources-surface.md +44 -0
- package/.agents/skills/harper-mcp/rules/security-posture.md +36 -0
- package/.agents/skills/harper-mcp/rules.manifest.yaml +203 -0
- package/agent/skills/harper-best-practices/AGENTS.md +567 -490
- package/agent/skills/harper-best-practices/rules/automatic-apis.md +46 -78
- package/agent/skills/harper-best-practices/rules/defining-relationships.md +41 -63
- package/agent/skills/harper-best-practices/rules/deploying-to-harper-fabric.md +59 -45
- package/agent/skills/harper-best-practices/rules/load-env.md +24 -23
- package/agent/skills/harper-best-practices/rules/programmatic-table-requests.md +62 -78
- package/agent/skills/harper-best-practices/rules/querying-rest-apis.md +92 -65
- package/agent/skills/harper-best-practices/rules/schema-design-tooling.md +53 -55
- package/agent/skills/harper-best-practices/rules/v5-upgrade.md +98 -62
- package/agent/skills/harper-best-practices/rules/vector-indexing.md +113 -42
- package/agent/skills/harper-mcp/AGENTS.md +501 -0
- package/agent/skills/harper-mcp/SKILL.md +83 -0
- package/agent/skills/harper-mcp/rules/automatic-verb-tools.md +50 -0
- package/agent/skills/harper-mcp/rules/connecting-clients.md +59 -0
- package/agent/skills/harper-mcp/rules/custom-mcp-prompts.md +52 -0
- package/agent/skills/harper-mcp/rules/custom-mcp-resources.md +64 -0
- package/agent/skills/harper-mcp/rules/custom-mcp-tools.md +72 -0
- package/agent/skills/harper-mcp/rules/durable-quotas.md +73 -0
- package/agent/skills/harper-mcp/rules/enabling-mcp.md +63 -0
- package/agent/skills/harper-mcp/rules/rate-limiting.md +62 -0
- package/agent/skills/harper-mcp/rules/resources-surface.md +44 -0
- package/agent/skills/harper-mcp/rules/security-posture.md +36 -0
- package/agent/skills/harper-mcp/rules.manifest.yaml +203 -0
- package/package.json +2 -2
- package/skills-lock.json +7 -1
|
@@ -6,8 +6,8 @@ metadata:
|
|
|
6
6
|
sources:
|
|
7
7
|
- reference/v5/rest/overview.md
|
|
8
8
|
- reference/v5/rest/websockets.md
|
|
9
|
-
sourceCommit:
|
|
10
|
-
inputHash:
|
|
9
|
+
sourceCommit: 3749d0c54be457a2a65d9a63c738a5dc88989ecd
|
|
10
|
+
inputHash: 6c7013b1307d9f7b
|
|
11
11
|
---
|
|
12
12
|
|
|
13
13
|
# Automatic APIs
|
|
@@ -20,13 +20,13 @@ Apply this rule when adding REST or WebSocket API access to Harper tables or cus
|
|
|
20
20
|
|
|
21
21
|
## How It Works
|
|
22
22
|
|
|
23
|
-
1. **Enable the REST plugin**: Add `rest: true` to your application's `config.yaml`. This activates the HTTP REST interface and enables WebSocket support
|
|
23
|
+
1. **Enable the REST plugin**: Add `rest: true` to your application's `config.yaml`. This activates the HTTP REST interface on the application server port (default `9926`) and enables WebSocket support automatically.
|
|
24
24
|
|
|
25
25
|
```yaml
|
|
26
26
|
rest: true
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
To configure
|
|
29
|
+
To configure options explicitly:
|
|
30
30
|
|
|
31
31
|
```yaml
|
|
32
32
|
rest:
|
|
@@ -34,69 +34,26 @@ Apply this rule when adding REST or WebSocket API access to Harper tables or cus
|
|
|
34
34
|
webSocket: false # disables automatic WebSocket support (enabled by default)
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
-
2. **Export your resource in the schema**: Tables are not exposed by default. Use the `@export` directive in your schema definition to
|
|
37
|
+
2. **Export your resource in the schema**: Tables are not exposed by default. Use the `@export` directive in your schema definition to expose a table as a REST endpoint. The exported name defines the base URL path.
|
|
38
38
|
|
|
39
|
-
3. **Use the correct URL structure**:
|
|
39
|
+
3. **Use the correct URL structure**: Target resources using these path conventions:
|
|
40
40
|
|
|
41
|
-
| Path | Description
|
|
42
|
-
| -------------------------------------------- |
|
|
43
|
-
| `/my-resource` | Returns
|
|
44
|
-
| `/my-resource/` |
|
|
45
|
-
| `/my-resource/record-id` |
|
|
46
|
-
| `/my-resource/record-id/` |
|
|
47
|
-
| `/my-resource/record-id/with/multiple/parts` | Record id with multiple path segments
|
|
41
|
+
| Path | Description |
|
|
42
|
+
| -------------------------------------------- | ----------------------------------------------------------- |
|
|
43
|
+
| `/my-resource` | Returns resource metadata |
|
|
44
|
+
| `/my-resource/` | Collection — all records; append query parameters to search |
|
|
45
|
+
| `/my-resource/record-id` | Specific record by primary key |
|
|
46
|
+
| `/my-resource/record-id/` | Collection of records with the given id prefix |
|
|
47
|
+
| `/my-resource/record-id/with/multiple/parts` | Record id with multiple path segments |
|
|
48
48
|
|
|
49
|
-
4. **Map HTTP methods
|
|
50
|
-
- **GET** — Retrieve a record or search. Calls `get()`.
|
|
49
|
+
4. **Map operations to HTTP methods**: Each HTTP method maps to a resource method:
|
|
50
|
+
- **GET** — Retrieve a record or search. Calls `get()`. Responses include an `ETag` header; send `If-None-Match` on subsequent requests to receive `304 Not Modified` when unchanged.
|
|
51
|
+
- **PUT** — Create or replace a record (upsert). Calls `put(record)`. The stored record exactly matches the submitted body; omitted properties are removed.
|
|
52
|
+
- **POST** — Create a record without specifying a primary key. Calls `post(data)`. The assigned key is returned in the `Location` response header.
|
|
53
|
+
- **PATCH** — Partially update a record, merging only provided top-level properties. Calls the resource's patch handler. Merge is **shallow** — nested objects are replaced entirely, not deep-merged.
|
|
54
|
+
- **DELETE** — Delete a record by id or all records matching a query.
|
|
51
55
|
|
|
52
|
-
|
|
53
|
-
GET /MyTable/123
|
|
54
|
-
GET /MyTable/?name=Harper
|
|
55
|
-
GET /MyTable/123.propertyName
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
Responses include an `ETag` header. Clients may send `If-None-Match` to receive `304 Not Modified` when the record is unchanged.
|
|
59
|
-
|
|
60
|
-
- **PUT** — Create or replace a record (upsert). Calls `put(record)`. Properties not in the body are removed.
|
|
61
|
-
|
|
62
|
-
```
|
|
63
|
-
PUT /MyTable/123
|
|
64
|
-
Content-Type: application/json
|
|
65
|
-
|
|
66
|
-
{ "name": "some data" }
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
- **POST** — Create a new record without specifying a primary key. Calls `post(data)`. The assigned key is returned in the `Location` response header.
|
|
70
|
-
|
|
71
|
-
```
|
|
72
|
-
POST /MyTable/
|
|
73
|
-
Content-Type: application/json
|
|
74
|
-
|
|
75
|
-
{ "name": "some data" }
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
- **PATCH** — Partially update a record, merging only provided properties. Unspecified properties are preserved.
|
|
79
|
-
|
|
80
|
-
```
|
|
81
|
-
PATCH /MyTable/123
|
|
82
|
-
Content-Type: application/json
|
|
83
|
-
|
|
84
|
-
{ "status": "active" }
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
- **DELETE** — Delete a record or all records matching a query.
|
|
88
|
-
```
|
|
89
|
-
DELETE /MyTable/123
|
|
90
|
-
DELETE /MyTable/?status=archived
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
5. **Access the auto-generated OpenAPI spec**: Harper generates an OpenAPI specification for all exported resources. Retrieve it at:
|
|
94
|
-
|
|
95
|
-
```
|
|
96
|
-
GET /openapi
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
6. **Connect via WebSocket**: When `rest` is enabled, WebSocket support is on by default. Connect to a resource URL to subscribe to change events for that resource.
|
|
56
|
+
5. **Connect via WebSocket**: A WebSocket connection to a resource URL subscribes to that resource and streams change events. See [real-time-apps.md](real-time-apps.md) for full real-time patterns.
|
|
100
57
|
|
|
101
58
|
```javascript
|
|
102
59
|
let ws = new WebSocket('wss://server/my-resource/341');
|
|
@@ -105,13 +62,17 @@ Apply this rule when adding REST or WebSocket API access to Harper tables or cus
|
|
|
105
62
|
};
|
|
106
63
|
```
|
|
107
64
|
|
|
108
|
-
|
|
65
|
+
6. **Implement a custom `connect()` handler** on a resource class to control WebSocket behavior. The method receives `incomingMessages` and must return an async iterable producing messages to send to the client.
|
|
66
|
+
|
|
67
|
+
7. **Retrieve the OpenAPI spec**: Harper auto-generates an OpenAPI specification for all exported resources, available at:
|
|
109
68
|
|
|
110
|
-
|
|
69
|
+
```
|
|
70
|
+
GET /openapi
|
|
71
|
+
```
|
|
111
72
|
|
|
112
73
|
## Examples
|
|
113
74
|
|
|
114
|
-
**Simple echo server
|
|
75
|
+
**Simple echo WebSocket server**:
|
|
115
76
|
|
|
116
77
|
```javascript
|
|
117
78
|
export class Echo extends Resource {
|
|
@@ -123,7 +84,7 @@ export class Echo extends Resource {
|
|
|
123
84
|
}
|
|
124
85
|
```
|
|
125
86
|
|
|
126
|
-
**
|
|
87
|
+
**Custom `connect()` using the default iterable with `send()` and `close` event**:
|
|
127
88
|
|
|
128
89
|
```javascript
|
|
129
90
|
export class Example extends Resource {
|
|
@@ -147,19 +108,26 @@ export class Example extends Resource {
|
|
|
147
108
|
}
|
|
148
109
|
```
|
|
149
110
|
|
|
150
|
-
**
|
|
111
|
+
**Common REST operations**:
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
GET /MyTable/123
|
|
115
|
+
GET /MyTable/?name=Harper
|
|
116
|
+
PUT /MyTable/123
|
|
117
|
+
PATCH /MyTable/123
|
|
118
|
+
DELETE /MyTable/?status=archived
|
|
119
|
+
```
|
|
151
120
|
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
webSocket: false
|
|
121
|
+
```json
|
|
122
|
+
{ "name": "some data" }
|
|
155
123
|
```
|
|
156
124
|
|
|
157
125
|
## Notes
|
|
158
126
|
|
|
159
|
-
-
|
|
160
|
-
-
|
|
161
|
-
-
|
|
162
|
-
-
|
|
163
|
-
-
|
|
164
|
-
-
|
|
165
|
-
-
|
|
127
|
+
- `rest: true` is the minimal config to enable both REST and WebSocket support. Set `webSocket: false` under the `rest` key to disable WebSocket only.
|
|
128
|
+
- The `@export` directive in the schema is required for any table to appear as a REST endpoint — tables are not exported by default.
|
|
129
|
+
- PATCH merges are shallow (top-level only). Nested objects in the request body replace the entire existing sub-object. Dot-path keys (e.g., `"settings.theme"`) are stored as literal keys, not interpreted as paths.
|
|
130
|
+
- For MQTT over WebSocket, set the sub-protocol header `Sec-WebSocket-Protocol: mqtt`.
|
|
131
|
+
- In distributed environments, non-retained messages are delivered in arrival order; retained messages (PUT/updated records) keep only the latest timestamp as the winning record.
|
|
132
|
+
- For full query syntax on GET and DELETE, see [querying-rest-apis.md](querying-rest-apis.md).
|
|
133
|
+
- For building real-time features with WebSocket subscriptions, see [real-time-apps.md](real-time-apps.md).
|
|
@@ -6,8 +6,8 @@ metadata:
|
|
|
6
6
|
sources:
|
|
7
7
|
- reference/v5/database/schema.md#Relationships
|
|
8
8
|
- reference/v5/rest/querying.md#Relationships and Joins
|
|
9
|
-
sourceCommit:
|
|
10
|
-
inputHash:
|
|
9
|
+
sourceCommit: 3749d0c54be457a2a65d9a63c738a5dc88989ecd
|
|
10
|
+
inputHash: fd399fd81a88f13e
|
|
11
11
|
---
|
|
12
12
|
|
|
13
13
|
# Defining Relationships Between Tables in Harper
|
|
@@ -16,17 +16,17 @@ Instructions for the agent to follow when defining and querying relationships be
|
|
|
16
16
|
|
|
17
17
|
## When to Use
|
|
18
18
|
|
|
19
|
-
Apply this rule
|
|
19
|
+
Apply this rule when adding foreign key relationships between schema tables, enabling join queries, or returning nested related records in query results. Use it any time a schema type needs to reference records in another table via a foreign key attribute.
|
|
20
20
|
|
|
21
21
|
## How It Works
|
|
22
22
|
|
|
23
|
-
1. **Use `@relationship(from: attribute)` for many-to-one or many-to-many**: Place this on
|
|
23
|
+
1. **Use `@relationship(from: attribute)` for many-to-one or many-to-many**: Place this on the field in the table that holds the foreign key. The `from` parameter names the attribute on this table that stores the foreign key referencing the target table's primary key.
|
|
24
24
|
|
|
25
25
|
```graphql
|
|
26
26
|
type RealityShow @table @export {
|
|
27
27
|
id: Long @primaryKey
|
|
28
28
|
networkId: Long @indexed
|
|
29
|
-
network: Network @relationship(from: networkId)
|
|
29
|
+
network: Network @relationship(from: networkId) # many-to-one
|
|
30
30
|
title: String @indexed
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -36,7 +36,7 @@ Apply this rule whenever a schema requires linking two tables via a foreign key
|
|
|
36
36
|
}
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
If the foreign key attribute is an array, the relationship becomes many-to-many:
|
|
40
40
|
|
|
41
41
|
```graphql
|
|
42
42
|
type RealityShow @table @export {
|
|
@@ -46,24 +46,24 @@ Apply this rule whenever a schema requires linking two tables via a foreign key
|
|
|
46
46
|
}
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
-
2. **Use `@relationship(to: attribute)` for one-to-many or many-to-many**: Place this on
|
|
49
|
+
2. **Use `@relationship(to: attribute)` for one-to-many or many-to-many**: Place this on the table whose primary key is referenced by the foreign key in the target table. The `to` parameter names the attribute on the target table that holds the foreign key. The result type **must** be an array.
|
|
50
50
|
|
|
51
51
|
```graphql
|
|
52
52
|
type Network @table @export {
|
|
53
53
|
id: Long @primaryKey
|
|
54
54
|
name: String @indexed
|
|
55
|
-
shows: [RealityShow] @relationship(to: networkId)
|
|
55
|
+
shows: [RealityShow] @relationship(to: networkId) # one-to-many
|
|
56
56
|
}
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
3. **Use `@relationship(from: attribute, to: attribute)` for foreign key to foreign key joins**: Specify both `from` and `to` when neither side uses the primary key.
|
|
59
|
+
3. **Use `@relationship(from: attribute, to: attribute)` for foreign key to foreign key joins**: Specify both `from` and `to` when neither side uses the primary key. Harper resolves the relationship by searching the target table's `to` attribute for matches using this record's `from` attribute value. The result type must be an array.
|
|
60
60
|
|
|
61
61
|
```graphql
|
|
62
62
|
type OrderItem @table @export {
|
|
63
63
|
id: Long @primaryKey
|
|
64
64
|
orderId: Long @indexed
|
|
65
65
|
productSku: Long @indexed
|
|
66
|
-
|
|
66
|
+
products: [Product] @relationship(from: productSku, to: sku)
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
type Product @table @export {
|
|
@@ -73,15 +73,14 @@ Apply this rule whenever a schema requires linking two tables via a foreign key
|
|
|
73
73
|
}
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
-
4. **Query across relationships using dot-syntax**: Filter by related table attributes using chained dot notation. This behaves as an INNER JOIN.
|
|
76
|
+
4. **Query across relationships using dot-syntax**: Filter records by related table attributes using chained dot notation. This behaves as an INNER JOIN — only records with a matching related record are returned.
|
|
77
77
|
|
|
78
78
|
```
|
|
79
|
-
GET /RealityShow?network.name=Bravo
|
|
80
79
|
GET /Product/?brand.name=Microsoft
|
|
81
80
|
GET /Brand/?products.name=Keyboard
|
|
82
81
|
```
|
|
83
82
|
|
|
84
|
-
5. **
|
|
83
|
+
5. **Include relationship fields in results using `select()`**: Relationship attributes are not returned by default. Use `select()` to include them, optionally specifying nested fields with `{}`.
|
|
85
84
|
|
|
86
85
|
```
|
|
87
86
|
GET /Product/?brand.name=Microsoft&select(name,brand)
|
|
@@ -89,77 +88,56 @@ Apply this rule whenever a schema requires linking two tables via a foreign key
|
|
|
89
88
|
GET /Product/?name=Keyboard&select(name,brand{name,id})
|
|
90
89
|
```
|
|
91
90
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
**Many-to-one relationship** — a show belongs to a network:
|
|
91
|
+
When selecting a relationship without filtering on it, Harper performs a LEFT JOIN — the relationship property is omitted if the foreign key is null or references a non-existent record.
|
|
95
92
|
|
|
96
|
-
|
|
97
|
-
type RealityShow @table @export {
|
|
98
|
-
id: Long @primaryKey
|
|
99
|
-
networkId: Long @indexed
|
|
100
|
-
network: Network @relationship(from: networkId)
|
|
101
|
-
title: String @indexed
|
|
102
|
-
}
|
|
93
|
+
6. **Model many-to-many without a junction table**: Store an array of foreign key values and use `@relationship(from: ...)` pointing to that array attribute. The array order of the foreign key values is preserved when resolving the relationship.
|
|
103
94
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
95
|
+
```graphql
|
|
96
|
+
type Product @table @export {
|
|
97
|
+
id: Long @primaryKey
|
|
98
|
+
name: String
|
|
99
|
+
resellerIds: [Long] @indexed
|
|
100
|
+
resellers: [Reseller] @relationship(from: "resellerIds")
|
|
101
|
+
}
|
|
102
|
+
```
|
|
109
103
|
|
|
110
|
-
|
|
104
|
+
7. **Define self-referential relationships** for parent-child hierarchies by pointing `@relationship` back at the same table type.
|
|
111
105
|
|
|
112
|
-
|
|
113
|
-
GET /RealityShow?network.name=Bravo
|
|
114
|
-
```
|
|
106
|
+
## Examples
|
|
115
107
|
|
|
116
|
-
**
|
|
108
|
+
**Full schema with bidirectional relationships:**
|
|
117
109
|
|
|
118
110
|
```graphql
|
|
119
|
-
type
|
|
111
|
+
type Product @table @export {
|
|
120
112
|
id: Long @primaryKey
|
|
121
|
-
name: String
|
|
122
|
-
|
|
113
|
+
name: String
|
|
114
|
+
brandId: Long @indexed
|
|
115
|
+
brand: Brand @relationship(from: "brandId")
|
|
123
116
|
}
|
|
124
|
-
```
|
|
125
117
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
```graphql
|
|
129
|
-
type Product @table @export {
|
|
118
|
+
type Brand @table @export {
|
|
130
119
|
id: Long @primaryKey
|
|
131
120
|
name: String
|
|
132
|
-
|
|
133
|
-
resellers: [Reseller] @relationship(from: resellerIds)
|
|
121
|
+
products: [Product] @relationship(to: "brandId")
|
|
134
122
|
}
|
|
135
123
|
```
|
|
136
124
|
|
|
137
|
-
|
|
125
|
+
**Querying with joins and nested select:**
|
|
138
126
|
|
|
139
127
|
```
|
|
140
|
-
GET /Product/?
|
|
128
|
+
GET /Product/?brand.name=Microsoft&select(name,brand{name,id})
|
|
129
|
+
GET /Brand/?products.name=Keyboard
|
|
141
130
|
```
|
|
142
131
|
|
|
143
|
-
**
|
|
132
|
+
**Many-to-many query with nested select:**
|
|
144
133
|
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
id: Long @primaryKey
|
|
148
|
-
orderId: Long @indexed
|
|
149
|
-
productSku: Long @indexed
|
|
150
|
-
product: Product @relationship(from: productSku, to: sku)
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
type Product @table @export {
|
|
154
|
-
id: Long @primaryKey
|
|
155
|
-
sku: Long @indexed
|
|
156
|
-
name: String
|
|
157
|
-
}
|
|
134
|
+
```
|
|
135
|
+
GET /Product/?resellers.name=Cool Shop&select(id,name,resellers{name,id})
|
|
158
136
|
```
|
|
159
137
|
|
|
160
138
|
## Notes
|
|
161
139
|
|
|
162
|
-
-
|
|
163
|
-
-
|
|
164
|
-
- The array
|
|
165
|
-
-
|
|
140
|
+
- Every attribute named in `from` or `to` must exist on the respective table and be annotated with `@indexed` to support join queries.
|
|
141
|
+
- The `to`-only and `from`+`to` forms both require the result field type to be an array (e.g., `[RealityShow]`).
|
|
142
|
+
- The `from`-only form on a non-array attribute produces a many-to-one relationship; on an array attribute it produces many-to-many.
|
|
143
|
+
- Self-referential relationships are supported for hierarchical data within a single table.
|
|
@@ -8,28 +8,32 @@ metadata:
|
|
|
8
8
|
- >-
|
|
9
9
|
fabric/cluster-creation-management.md#Connecting the Harper CLI to a
|
|
10
10
|
Cluster
|
|
11
|
-
sourceCommit:
|
|
12
|
-
inputHash:
|
|
11
|
+
sourceCommit: 3749d0c54be457a2a65d9a63c738a5dc88989ecd
|
|
12
|
+
inputHash: 39faf283b6964e93
|
|
13
13
|
---
|
|
14
14
|
|
|
15
15
|
# Deploying to Harper Fabric
|
|
16
16
|
|
|
17
|
-
Instructions for the agent to follow when deploying a Harper application to
|
|
17
|
+
Instructions for the agent to follow when deploying a Harper application to a remote Harper Fabric cloud instance.
|
|
18
18
|
|
|
19
19
|
## When to Use
|
|
20
20
|
|
|
21
|
-
Apply this rule when deploying a Harper application to a remote Harper
|
|
21
|
+
Apply this rule when deploying a Harper application to a remote Harper Fabric cluster or any remote Harper instance. Use it when setting up CI/CD pipelines that push application packages to a target environment, or when deploying from a local directory or external package source to a remote cluster.
|
|
22
22
|
|
|
23
23
|
## How It Works
|
|
24
24
|
|
|
25
|
-
1. **
|
|
25
|
+
1. **Obtain the target URL**: Get the cluster's **Application URL** from the cluster's **Config → Overview** page. This is the hostname passed to all CLI commands as `target`.
|
|
26
|
+
|
|
27
|
+
2. **Authenticate with `harper login`**: Run `harper login` once to store an authentication token locally. The CLI also writes `HARPER_CLI_TARGET` to a local `.env` for subsequent commands.
|
|
26
28
|
|
|
27
29
|
```bash
|
|
28
30
|
harper login <Application URL>
|
|
29
31
|
# Provide cluster username and password when prompted
|
|
30
32
|
```
|
|
31
33
|
|
|
32
|
-
|
|
34
|
+
See [creating-a-fabric-account-and-cluster.md](creating-a-fabric-account-and-cluster.md) for setting up a cluster before this step.
|
|
35
|
+
|
|
36
|
+
3. **Deploy with `harper deploy`**: After logging in, deploy without repeating credentials.
|
|
33
37
|
|
|
34
38
|
```bash
|
|
35
39
|
harper deploy \
|
|
@@ -40,83 +44,93 @@ Apply this rule when deploying a Harper application to a remote Harper instance
|
|
|
40
44
|
replicated=true
|
|
41
45
|
```
|
|
42
46
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
| Value | Effect |
|
|
46
|
-
| ---------------------------------------------------- | ------------------------------------------------ |
|
|
47
|
-
| _(omitted)_ | Packages and deploys the current local directory |
|
|
48
|
-
| `"@harperdb/status-check"` | npm package |
|
|
49
|
-
| `"HarperDB/status-check"` | GitHub repo (short form) |
|
|
50
|
-
| `"https://github.com/HarperDB/status-check"` | GitHub repo (full URL) |
|
|
51
|
-
| `"git+ssh://git@github.com:HarperDB/secret-app.git"` | Private repo via SSH |
|
|
52
|
-
| `"https://example.com/application.tar.gz"` | Remote tarball |
|
|
53
|
-
|
|
54
|
-
For git tags, use the `semver` directive for reliable versioning:
|
|
47
|
+
4. **Use environment variables for CI/CD**: Instead of `harper login`, export credentials as environment variables before running `harper deploy`.
|
|
55
48
|
|
|
56
|
-
```
|
|
57
|
-
|
|
49
|
+
```bash
|
|
50
|
+
export HARPER_CLI_USERNAME=<username>
|
|
51
|
+
export HARPER_CLI_PASSWORD=<password>
|
|
52
|
+
harper deploy \
|
|
53
|
+
project=<name> \
|
|
54
|
+
package=<package> \
|
|
55
|
+
target=<remote> \
|
|
56
|
+
restart=true \
|
|
57
|
+
replicated=true
|
|
58
58
|
```
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
5. **Use inline auth parameters for one-off commands**: Pass `auth_username` and `auth_password` directly. These take precedence over environment variables and saved login tokens. Not recommended for production.
|
|
61
61
|
|
|
62
62
|
```bash
|
|
63
|
-
export HARPER_CLI_USERNAME=<username>
|
|
64
|
-
export HARPER_CLI_PASSWORD=<password>
|
|
65
63
|
harper deploy \
|
|
66
64
|
project=<name> \
|
|
67
65
|
package=<package> \
|
|
66
|
+
auth_username=<username> \
|
|
67
|
+
auth_password=<password> \
|
|
68
68
|
target=<remote> \
|
|
69
69
|
restart=true \
|
|
70
70
|
replicated=true
|
|
71
71
|
```
|
|
72
72
|
|
|
73
|
-
|
|
73
|
+
6. **Choose a package source**: Set the `package` parameter to any valid npm dependency value, or omit it to package and deploy the current local directory.
|
|
74
|
+
|
|
75
|
+
| Value | Meaning |
|
|
76
|
+
| ---------------------------------------------------- | ---------------------------------------------- |
|
|
77
|
+
| _(omitted)_ | Package and deploy the current local directory |
|
|
78
|
+
| `"@harperdb/status-check"` | npm package |
|
|
79
|
+
| `"HarperDB/status-check"` | GitHub shorthand |
|
|
80
|
+
| `"https://github.com/HarperDB/status-check"` | GitHub full URL |
|
|
81
|
+
| `"git+ssh://git@github.com:HarperDB/secret-app.git"` | Private repo via SSH |
|
|
82
|
+
| `"https://example.com/application.tar.gz"` | Remote tarball |
|
|
83
|
+
|
|
84
|
+
For pinned git tags, use the `semver` directive:
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
HarperDB/application-template#semver:v1.0.0
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
For SSH-based private repos, register keys with the `Add SSH Key` operation before deploying.
|
|
74
91
|
|
|
75
92
|
## Examples
|
|
76
93
|
|
|
77
|
-
**Interactive login then deploy
|
|
94
|
+
**Interactive login then deploy:**
|
|
78
95
|
|
|
79
96
|
```bash
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
# Provide your username and password when prompted
|
|
97
|
+
harper login https://my-cluster.harperdbcloud.com
|
|
98
|
+
# Enter username and password when prompted
|
|
83
99
|
|
|
84
|
-
# Subsequently deploy without credentials
|
|
85
100
|
harper deploy \
|
|
86
|
-
project
|
|
87
|
-
package
|
|
88
|
-
target
|
|
101
|
+
project=my-app \
|
|
102
|
+
package="HarperDB/application-template#semver:v1.0.0" \
|
|
103
|
+
target=https://my-cluster.harperdbcloud.com \
|
|
89
104
|
restart=true \
|
|
90
105
|
replicated=true
|
|
91
106
|
```
|
|
92
107
|
|
|
93
|
-
**
|
|
108
|
+
**CI/CD pipeline deploy using environment variables:**
|
|
94
109
|
|
|
95
110
|
```bash
|
|
111
|
+
export HARPER_CLI_USERNAME=admin
|
|
112
|
+
export HARPER_CLI_PASSWORD=secret
|
|
96
113
|
harper deploy \
|
|
97
|
-
project
|
|
98
|
-
package
|
|
99
|
-
|
|
100
|
-
password=<password> \
|
|
101
|
-
target=<remote> \
|
|
114
|
+
project=my-app \
|
|
115
|
+
package="@harperdb/status-check" \
|
|
116
|
+
target=https://my-cluster.harperdbcloud.com \
|
|
102
117
|
restart=true \
|
|
103
118
|
replicated=true
|
|
104
119
|
```
|
|
105
120
|
|
|
106
|
-
**Deploy
|
|
121
|
+
**Deploy current local directory:**
|
|
107
122
|
|
|
108
123
|
```bash
|
|
109
124
|
harper deploy \
|
|
110
125
|
project=my-app \
|
|
111
|
-
|
|
112
|
-
target=<remote> \
|
|
126
|
+
target=https://my-cluster.harperdbcloud.com \
|
|
113
127
|
restart=true \
|
|
114
128
|
replicated=true
|
|
115
129
|
```
|
|
116
130
|
|
|
117
131
|
## Notes
|
|
118
132
|
|
|
119
|
-
-
|
|
120
|
-
-
|
|
121
|
-
- Harper generates a `package.json` from component configurations and resolves
|
|
122
|
-
- For SSH-based private repos, register
|
|
133
|
+
- Authentication precedence (highest to lowest): inline `auth_username`/`auth_password` parameters → environment variables (`HARPER_CLI_USERNAME`/`HARPER_CLI_PASSWORD`) → saved login token from `harper login`.
|
|
134
|
+
- `harper login` writes `HARPER_CLI_TARGET` to a local `.env`, so subsequent commands do not need `target` repeated if that file is present.
|
|
135
|
+
- Harper generates a `package.json` from component configurations and resolves packages via `npm install`. A local file path creates a symlink, so changes are picked up between restarts without redeploying.
|
|
136
|
+
- For SSH-based private repos, register the SSH key with the `Add SSH Key` operation before running `harper deploy`.
|