@harperfast/template-react-ts-studio 1.12.8 → 1.12.10
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 +514 -445
- package/.agents/skills/harper-best-practices/rules/automatic-apis.md +96 -93
- package/.agents/skills/harper-best-practices/rules/deploying-to-harper-fabric.md +84 -58
- package/.agents/skills/harper-best-practices/rules/extending-tables.md +27 -35
- package/.agents/skills/harper-best-practices/rules/handling-binary-data.md +40 -39
- package/.agents/skills/harper-best-practices/rules/querying-rest-apis.md +93 -37
- package/.agents/skills/harper-best-practices/rules/schema-design-tooling.md +68 -66
- package/.agents/skills/harper-best-practices/rules/using-blob-datatype.md +24 -28
- package/.agents/skills/harper-best-practices/rules/v5-upgrade.md +98 -105
- package/.agents/skills/harper-best-practices/rules.manifest.yaml +28 -3
- package/.agents/skills/harper-mcp/AGENTS.md +138 -26
- package/.agents/skills/harper-mcp/rules/enabling-mcp.md +140 -28
- package/agent/skills/harper-best-practices/AGENTS.md +514 -445
- package/agent/skills/harper-best-practices/rules/automatic-apis.md +96 -93
- package/agent/skills/harper-best-practices/rules/deploying-to-harper-fabric.md +84 -58
- package/agent/skills/harper-best-practices/rules/extending-tables.md +27 -35
- package/agent/skills/harper-best-practices/rules/handling-binary-data.md +40 -39
- package/agent/skills/harper-best-practices/rules/querying-rest-apis.md +93 -37
- package/agent/skills/harper-best-practices/rules/schema-design-tooling.md +68 -66
- package/agent/skills/harper-best-practices/rules/using-blob-datatype.md +24 -28
- package/agent/skills/harper-best-practices/rules/v5-upgrade.md +98 -105
- package/agent/skills/harper-best-practices/rules.manifest.yaml +28 -3
- package/agent/skills/harper-mcp/AGENTS.md +138 -26
- package/agent/skills/harper-mcp/rules/enabling-mcp.md +140 -28
- package/package.json +1 -1
- package/skills-lock.json +2 -2
|
@@ -12,8 +12,8 @@ metadata:
|
|
|
12
12
|
- reference/v5/rest/overview.md#Content Types
|
|
13
13
|
- reference/v5/rest/overview.md#OpenAPI
|
|
14
14
|
- reference/v5/rest/websockets.md
|
|
15
|
-
sourceCommit:
|
|
16
|
-
inputHash:
|
|
15
|
+
sourceCommit: 2cfb81318f17e0aca2d600109e6ad813d2d0443e
|
|
16
|
+
inputHash: fc3e7ae596f475b2
|
|
17
17
|
---
|
|
18
18
|
|
|
19
19
|
# Automatic APIs
|
|
@@ -22,25 +22,26 @@ Instructions for the agent to follow when using Harper's automatically generated
|
|
|
22
22
|
|
|
23
23
|
## When to Use
|
|
24
24
|
|
|
25
|
-
Apply this rule when enabling HTTP REST endpoints or WebSocket subscriptions for Harper tables
|
|
25
|
+
Apply this rule when enabling HTTP REST endpoints or WebSocket subscriptions for Harper tables and custom resources. Use it whenever you need to configure the REST plugin, understand the auto-generated endpoint surface, or wire up real-time WebSocket connections. See [querying-rest-apis.md](querying-rest-apis.md) for query syntax and [real-time-apps.md](real-time-apps.md) for real-time patterns.
|
|
26
26
|
|
|
27
27
|
## How It Works
|
|
28
28
|
|
|
29
|
-
1. **Enable REST
|
|
29
|
+
1. **Enable the REST plugin** by adding `rest: true` to your application's `config.yaml`:
|
|
30
30
|
|
|
31
31
|
```yaml
|
|
32
32
|
rest: true
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
Extended options:
|
|
36
36
|
|
|
37
37
|
```yaml
|
|
38
38
|
rest:
|
|
39
39
|
lastModified: true # enables Last-Modified response header support
|
|
40
40
|
webSocket: false # disables automatic WebSocket support (enabled by default)
|
|
41
|
+
exactCount: true # opt in to Prefer: count=exact scans (off by default)
|
|
41
42
|
```
|
|
42
43
|
|
|
43
|
-
2. **Export the table in
|
|
44
|
+
2. **Export the table in your schema** using `@export`. Tables are not exposed by default — `@export` is required for Harper to register a REST route:
|
|
44
45
|
|
|
45
46
|
```graphql
|
|
46
47
|
type Product @table @export {
|
|
@@ -50,46 +51,41 @@ Apply this rule when enabling HTTP REST endpoints or WebSocket subscriptions for
|
|
|
50
51
|
}
|
|
51
52
|
```
|
|
52
53
|
|
|
53
|
-
|
|
54
|
+
Without `@export`, the table has no REST route and callers receive `404`. Without `rest: true` in `config.yaml`, even an exported table does not respond to HTTP requests.
|
|
54
55
|
|
|
55
|
-
|
|
56
|
-
graphqlSchema:
|
|
57
|
-
files: schema.graphql
|
|
58
|
-
rest: true
|
|
59
|
-
```
|
|
56
|
+
3. **Understand the auto-generated endpoints**. With both `@export` and `rest: true` in place, Harper registers the following on the application HTTP server port (default `9926`):
|
|
60
57
|
|
|
61
|
-
|
|
58
|
+
| Endpoint | Description |
|
|
59
|
+
| ---------------------------- | ------------------------------------------------------------------------------------ |
|
|
60
|
+
| `GET /Product` | Resource description — table name, database, declared attributes |
|
|
61
|
+
| `GET /Product/` | Record collection; append query parameters to filter, sort, page |
|
|
62
|
+
| `GET /Product/{id}` | Single record by primary key; `404` if not found |
|
|
63
|
+
| `GET /Product/{id}.property` | Single declared property of one record |
|
|
64
|
+
| `POST /Product/` | Creates a record; responds `201`; primary key returned in `Location` header |
|
|
65
|
+
| `PUT /Product/{id}` | Creates or replaces the record at `{id}` (upsert); omitted properties are removed |
|
|
66
|
+
| `PATCH /Product/{id}` | Shallow-merges body into existing record; unspecified top-level properties preserved |
|
|
67
|
+
| `DELETE /Product/{id}` | Deletes the record at `{id}` |
|
|
68
|
+
| `DELETE /Product/?query` | Deletes every record matching the query |
|
|
69
|
+
- `HEAD` is served exactly as `GET` with the response body omitted. `QUERY` is accepted on the collection path (`QUERY /Product/`) and runs a search taken from the request body rather than the URL.
|
|
62
70
|
|
|
63
|
-
|
|
64
|
-
| ---------------------------- | --------------------------------------------------------------------------- |
|
|
65
|
-
| `GET /Product` | Returns resource description (table name, database, attributes) |
|
|
66
|
-
| `GET /Product/` | Returns the record collection; append query parameters to filter |
|
|
67
|
-
| `GET /Product/{id}` | Returns a single record by primary key; `404` if not found |
|
|
68
|
-
| `GET /Product/{id}.property` | Returns a single declared property of one record |
|
|
69
|
-
| `POST /Product/` | Creates a record; responds `201`; primary key returned in `Location` header |
|
|
70
|
-
| `PUT /Product/{id}` | Creates or replaces the record at `{id}` (upsert) |
|
|
71
|
-
| `PATCH /Product/{id}` | Merges body into existing record (shallow, top-level only) |
|
|
72
|
-
| `DELETE /Product/{id}` | Deletes the record at `{id}` |
|
|
73
|
-
| `DELETE /Product/?query` | Deletes every record matching the query |
|
|
71
|
+
4. **Use the correct URL structure**. The trailing slash is significant:
|
|
74
72
|
|
|
75
|
-
|
|
73
|
+
| Path | Addresses |
|
|
74
|
+
| ------------------------- | ---------------------------------------------- |
|
|
75
|
+
| `/my-resource` | The resource itself (metadata) |
|
|
76
|
+
| `/my-resource/` | The record collection |
|
|
77
|
+
| `/my-resource/record-id` | A specific record by primary key |
|
|
78
|
+
| `/my-resource/record-id/` | Collection of records with the given id prefix |
|
|
76
79
|
|
|
77
|
-
5. **
|
|
80
|
+
5. **Handle `POST` primary keys via `Location`**. On a successful `POST`, the new record's primary key is returned in the `Location` response header — the value supplied by the body, or a Harper-assigned key if the body omitted the primary-key property.
|
|
78
81
|
|
|
79
|
-
6. **Use conditional requests for caching
|
|
82
|
+
6. **Use conditional GET requests for caching**. GET responses include an `ETag` header. Send `If-None-Match` on subsequent requests; if the record is unchanged, Harper returns `304 Not Modified` with no body.
|
|
80
83
|
|
|
81
|
-
7. **
|
|
84
|
+
7. **Apply `@updatedTime` for write timestamps**. On `PUT`, Harper re-stamps any `@updatedTime` attribute with the time of the write, preserves any `@createdTime` value from the original record, and forces the primary key to match the `{id}` in the URL.
|
|
82
85
|
|
|
83
|
-
8. **
|
|
84
|
-
|
|
85
|
-
```javascript
|
|
86
|
-
let ws = new WebSocket('wss://server/my-resource/341');
|
|
87
|
-
ws.onmessage = (event) => {
|
|
88
|
-
let data = JSON.parse(event.data);
|
|
89
|
-
};
|
|
90
|
-
```
|
|
86
|
+
8. **Control OpenAPI visibility**. Every non-hidden exported resource appears in the generated OpenAPI document at `GET /openapi`. To exclude a type, mark it `@hidden` in the schema, or set `static hidden = true` on a programmatic resource class.
|
|
91
87
|
|
|
92
|
-
9. **Implement a custom `connect()` handler** when default subscription behavior is insufficient. The method must return an async iterable that produces messages to send to the client
|
|
88
|
+
9. **Implement a custom `connect()` handler** when default subscription behavior is insufficient. The method must return an async iterable that produces messages to send to the client:
|
|
93
89
|
|
|
94
90
|
```javascript
|
|
95
91
|
export class Echo extends Resource {
|
|
@@ -101,9 +97,28 @@ Apply this rule when enabling HTTP REST endpoints or WebSocket subscriptions for
|
|
|
101
97
|
}
|
|
102
98
|
```
|
|
103
99
|
|
|
100
|
+
10. **Connect via WebSocket**. WebSocket support is enabled automatically with `rest: true`. Connect to a resource URL to subscribe to change events:
|
|
101
|
+
|
|
102
|
+
```javascript
|
|
103
|
+
let ws = new WebSocket('wss://server/my-resource/341');
|
|
104
|
+
ws.onmessage = (event) => {
|
|
105
|
+
let data = JSON.parse(event.data);
|
|
106
|
+
};
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Disable WebSocket support independently with `webSocket: false` under `rest`.
|
|
110
|
+
|
|
111
|
+
11. **Use MQTT over WebSockets** by setting the sub-protocol header:
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
Sec-WebSocket-Protocol: mqtt
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
12. **Specify response format** using the `Accept` header. The suffixes `.json`, `.cbor`, `.msgpack`, and `.csv` are reserved as content-type selectors on property paths and take precedence over property names.
|
|
118
|
+
|
|
104
119
|
## Examples
|
|
105
120
|
|
|
106
|
-
|
|
121
|
+
**Schema and config for a REST-enabled table:**
|
|
107
122
|
|
|
108
123
|
```graphql
|
|
109
124
|
# schema.graphql
|
|
@@ -121,89 +136,77 @@ graphqlSchema:
|
|
|
121
136
|
rest: true
|
|
122
137
|
```
|
|
123
138
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
```
|
|
127
|
-
GET /Product/123
|
|
128
|
-
# Response includes:
|
|
129
|
-
# ETag: "abc123"
|
|
139
|
+
**Conditional GET with ETag caching:**
|
|
130
140
|
|
|
141
|
+
```http
|
|
131
142
|
GET /Product/123
|
|
132
143
|
If-None-Match: "abc123"
|
|
133
|
-
# Response: 304 Not Modified (no body transferred)
|
|
134
144
|
```
|
|
135
145
|
|
|
136
|
-
|
|
146
|
+
Response when unchanged:
|
|
137
147
|
|
|
138
148
|
```
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
{ "name": "Widget", "price": 9.99 }
|
|
143
|
-
|
|
144
|
-
# Response:
|
|
145
|
-
# 201 Created
|
|
146
|
-
# Location: 7f3a9c
|
|
149
|
+
HTTP/1.1 304 Not Modified
|
|
150
|
+
ETag: "abc123"
|
|
147
151
|
```
|
|
148
152
|
|
|
149
|
-
|
|
153
|
+
**POST and read the Location header:**
|
|
150
154
|
|
|
151
|
-
```
|
|
152
|
-
|
|
155
|
+
```http
|
|
156
|
+
POST /Product/
|
|
153
157
|
Content-Type: application/json
|
|
154
158
|
|
|
155
|
-
{ "
|
|
159
|
+
{ "name": "Widget" }
|
|
156
160
|
```
|
|
157
161
|
|
|
158
|
-
Only `price` is updated; other top-level properties are preserved. Nested objects in the body replace the stored sub-object wholesale — deep merge does not occur.
|
|
159
|
-
|
|
160
|
-
### Request MessagePack response
|
|
161
|
-
|
|
162
162
|
```
|
|
163
|
-
|
|
164
|
-
|
|
163
|
+
HTTP/1.1 201 Created
|
|
164
|
+
Location: 7f3a9c
|
|
165
165
|
```
|
|
166
166
|
|
|
167
|
-
|
|
167
|
+
**PATCH (shallow merge only):**
|
|
168
168
|
|
|
169
|
-
|
|
169
|
+
```http
|
|
170
|
+
PATCH /Product/123
|
|
171
|
+
Content-Type: application/json
|
|
170
172
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
connect(incomingMessages) {
|
|
174
|
-
let outgoingMessages = super.connect();
|
|
173
|
+
{ "status": "active" }
|
|
174
|
+
```
|
|
175
175
|
|
|
176
|
-
|
|
177
|
-
outgoingMessages.send({ greeting: 'hi again!' });
|
|
178
|
-
}, 1000);
|
|
176
|
+
**Custom WebSocket connect handler:**
|
|
179
177
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
178
|
+
```javascript
|
|
179
|
+
export class Echo extends Resource {
|
|
180
|
+
async *connect(incomingMessages) {
|
|
181
|
+
for await (let message of incomingMessages) {
|
|
182
|
+
yield message; // echo each message back
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
```
|
|
183
187
|
|
|
184
|
-
|
|
185
|
-
clearInterval(timer);
|
|
186
|
-
});
|
|
188
|
+
**Hide a resource from OpenAPI — schema directive:**
|
|
187
189
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
+
```graphql
|
|
191
|
+
type InternalLog @table @export @hidden {
|
|
192
|
+
id: Long @primaryKey
|
|
190
193
|
}
|
|
191
194
|
```
|
|
192
195
|
|
|
193
|
-
|
|
196
|
+
**Hide a resource from OpenAPI — programmatic class:**
|
|
194
197
|
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
|
|
198
|
+
```javascript
|
|
199
|
+
export class InternalLog extends Resource {
|
|
200
|
+
static hidden = true;
|
|
201
|
+
}
|
|
198
202
|
```
|
|
199
203
|
|
|
200
204
|
## Notes
|
|
201
205
|
|
|
202
|
-
-
|
|
203
|
-
- `
|
|
204
|
-
- A `POST` to
|
|
205
|
-
-
|
|
206
|
-
-
|
|
207
|
-
- Server-Sent Events subscriptions are served on the same paths, negotiated via `Accept: text/event-stream
|
|
208
|
-
-
|
|
209
|
-
- MQTT over WebSockets requires the sub-protocol header `Sec-WebSocket-Protocol: mqtt`.
|
|
206
|
+
- A component directory with **no** `config.yaml` inherits Harper's built-in default, which enables `rest` automatically. As soon as a `config.yaml` exists, it is used verbatim — omitting `rest` from it disables REST even if the directory previously had it without a config file. Always add `rest: true` when adding a config file.
|
|
207
|
+
- `POST /Product` (no trailing slash) returns `404`. The trailing slash is required for collection operations.
|
|
208
|
+
- A `POST` to a primary key that already exists fails with `409` rather than overwriting.
|
|
209
|
+
- PATCH merge is **shallow** — a nested object in the body replaces the stored nested object wholesale; nested properties not included in the body are dropped.
|
|
210
|
+
- The `.msgpack` suffix (along with `.json`, `.cbor`, `.csv`) is reserved as a content-type selector and cannot be used as a property name in dot-path access.
|
|
211
|
+
- Server-Sent Events subscriptions are served on the same paths, negotiated via `Accept: text/event-stream`; they are not affected by the `webSocket` option.
|
|
212
|
+
- See [querying-rest-apis.md](querying-rest-apis.md) for full query syntax on collection endpoints and [real-time-apps.md](real-time-apps.md) for real-time subscription patterns.
|
|
@@ -8,8 +8,8 @@ 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: 2cfb81318f17e0aca2d600109e6ad813d2d0443e
|
|
12
|
+
inputHash: c821d15a19e2370f
|
|
13
13
|
---
|
|
14
14
|
|
|
15
15
|
# Deploying to Harper Fabric
|
|
@@ -18,7 +18,7 @@ Instructions for the agent to follow when deploying a Harper application to a re
|
|
|
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 instance or Fabric cluster, including first-time deploys, redeployments, rollbacks, and CI/CD pipeline deployments. Also apply it when provisioning credentials for private repository deploys. See [creating-a-fabric-account-and-cluster.md](creating-a-fabric-account-and-cluster.md) for setting up the cluster before deploying.
|
|
22
22
|
|
|
23
23
|
## How It Works
|
|
24
24
|
|
|
@@ -29,7 +29,7 @@ Apply this rule when deploying a Harper application to a remote Harper Fabric cl
|
|
|
29
29
|
# Provide cluster username and password when prompted
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
2. **Deploy the application**: After login, run `harper deploy` without repeating credentials.
|
|
32
|
+
2. **Deploy the application**: After login, run `harper deploy` without repeating credentials. Use `restart=true` and `replicated=true` for production deploys.
|
|
33
33
|
|
|
34
34
|
```bash
|
|
35
35
|
harper deploy \
|
|
@@ -40,42 +40,32 @@ Apply this rule when deploying a Harper application to a remote Harper Fabric cl
|
|
|
40
40
|
replicated=true
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
-
3. **
|
|
43
|
+
3. **Choose a package source**: Set the `package` parameter to any valid npm dependency value. Options:
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
replicated=true
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
4. **Choose a package source**: The `package` field accepts any valid npm dependency value. Select the form that matches your source:
|
|
57
|
-
|
|
58
|
-
| Source | `package` value |
|
|
59
|
-
| ----------------------- | ---------------------------------------------------- |
|
|
60
|
-
| Current local directory | Omit `package` |
|
|
61
|
-
| npm package | `"@harperdb/status-check"` |
|
|
62
|
-
| GitHub (public) | `"HarperFast/status-check"` or full URL |
|
|
63
|
-
| Private repo (SSH) | `"git+ssh://git@github.com:HarperDB/secret-app.git"` |
|
|
64
|
-
| Tarball | `"https://example.com/application.tar.gz"` |
|
|
45
|
+
| Source | Example value |
|
|
46
|
+
| ----------------------- | ------------------------------------------------------------ |
|
|
47
|
+
| Current local directory | Omit `package` |
|
|
48
|
+
| npm package | `package="@harperdb/status-check"` |
|
|
49
|
+
| GitHub (shorthand) | `package="HarperFast/status-check"` |
|
|
50
|
+
| GitHub (URL) | `package="https://github.com/HarperFast/status-check"` |
|
|
51
|
+
| Private repo (SSH) | `package="git+ssh://git@github.com:HarperDB/secret-app.git"` |
|
|
52
|
+
| Tarball | `package="https://example.com/application.tar.gz"` |
|
|
65
53
|
|
|
66
|
-
|
|
54
|
+
When using git tags, use the `semver` directive:
|
|
67
55
|
|
|
68
56
|
```
|
|
69
57
|
HarperFast/application-template#semver:v1.0.0
|
|
70
58
|
```
|
|
71
59
|
|
|
72
|
-
|
|
60
|
+
4. **Deploy by reference (pinned commit)**: Use `by_ref=true` to send a pinned git reference instead of uploading a snapshot. The cluster fetches and builds from that exact commit SHA.
|
|
73
61
|
|
|
74
62
|
```bash
|
|
75
63
|
harper deploy by_ref=true restart=true replicated=true
|
|
76
64
|
```
|
|
77
65
|
|
|
78
|
-
|
|
66
|
+
- `by_ref` — Build the package reference from the local repository.
|
|
67
|
+
- `ref` _(optional)_ — Deploy a specific commit, tag, or branch instead of `HEAD`. Implies `by_ref`. Tags and branches in `refs/tags` and `refs/heads` namespaces are resolved to a full commit SHA before the deploy is sent.
|
|
68
|
+
- `credential` _(optional)_ — Set to `true` to authenticate the clone with the stored credential for the repository's host. Omit for public repositories.
|
|
79
69
|
|
|
80
70
|
```bash
|
|
81
71
|
# Deploy a specific tag
|
|
@@ -85,32 +75,61 @@ Apply this rule when deploying a Harper application to a remote Harper Fabric cl
|
|
|
85
75
|
harper deploy ref=9f8c2a1 restart=true replicated=true
|
|
86
76
|
```
|
|
87
77
|
|
|
88
|
-
**
|
|
89
|
-
-
|
|
90
|
-
-
|
|
91
|
-
-
|
|
92
|
-
- Commit and push before deploying
|
|
78
|
+
**Important constraints on refs:**
|
|
79
|
+
- A full commit SHA is accepted directly with no resolution.
|
|
80
|
+
- Every other `ref` must resolve to something a clone can fetch: `refs/tags/*` or `refs/heads/*`, or a bare branch or tag name.
|
|
81
|
+
- Qualified refs outside those two namespaces (e.g., `refs/pull/123/head`) are rejected.
|
|
82
|
+
- Commit and push before deploying — the cluster clones from the remote and only sees pushed commits.
|
|
83
|
+
- Run `git fetch` if a ref can't be resolved, or pass a full commit SHA.
|
|
93
84
|
|
|
94
|
-
|
|
85
|
+
5. **Handle private repositories**: Pass `credential=true` so the CLI attaches a credentials reference that the cluster resolves in memory at clone time. No token travels in the operation body or lands on disk.
|
|
95
86
|
|
|
96
87
|
```bash
|
|
97
88
|
harper deploy by_ref=true credential=true restart=true replicated=true
|
|
98
89
|
```
|
|
99
90
|
|
|
100
|
-
|
|
91
|
+
Provision the credential once with `setup=true` before using `credential=true`.
|
|
92
|
+
|
|
93
|
+
6. **Provision a deploy credential**: Run `harper deploy setup=true` once per component and source to provision credentials for private deploys. This operation requires **super_user** — run it with an administrative credential, not the CI identity.
|
|
101
94
|
|
|
102
95
|
```bash
|
|
103
96
|
harper deploy setup=true
|
|
104
97
|
```
|
|
105
98
|
|
|
106
|
-
This command:
|
|
99
|
+
This interactive command:
|
|
107
100
|
1. Fetches the cluster's public key with `get_secrets_public_key`.
|
|
108
101
|
2. Encrypts the token locally into an `enc:v1:` envelope.
|
|
109
102
|
3. Stores only the ciphertext with `set_secret`, in the component-scoped tier.
|
|
110
103
|
4. Grants the component permission to resolve it with `grant_secret`.
|
|
111
104
|
5. Prints the `credentials` reference for the deploy to use.
|
|
112
105
|
|
|
113
|
-
Use a
|
|
106
|
+
**Use a fine-grained PAT** for GitHub repositories. The prompt defaults to a fine-grained personal access token with **Contents: Read-only** on that one repository. If you use the `gh` CLI session token instead, it typically carries `read:org`, `repo`, `gist`, and `workflow` scopes across your whole account — the CLI prints a warning if you choose it. Use the narrowest credential that does the job, because the stored token is replayed on every cold deploy and rollback.
|
|
107
|
+
|
|
108
|
+
7. **Use environment variables for CI/CD**: Instead of `harper login`, export credentials as environment variables.
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
export HARPER_CLI_USERNAME=<username>
|
|
112
|
+
export HARPER_CLI_PASSWORD=<password>
|
|
113
|
+
harper deploy \
|
|
114
|
+
project=<name> \
|
|
115
|
+
package=<package> \
|
|
116
|
+
target=<remote> \
|
|
117
|
+
restart=true \
|
|
118
|
+
replicated=true
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
8. **Use dedicated auth parameters for one-off commands** (not recommended for production): Pass `auth_username` and `auth_password` directly. These take precedence over environment variables and saved login tokens.
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
harper deploy \
|
|
125
|
+
project=<name> \
|
|
126
|
+
package=<package> \
|
|
127
|
+
auth_username=<username> \
|
|
128
|
+
auth_password=<password> \
|
|
129
|
+
target=<remote> \
|
|
130
|
+
restart=true \
|
|
131
|
+
replicated=true
|
|
132
|
+
```
|
|
114
133
|
|
|
115
134
|
## Examples
|
|
116
135
|
|
|
@@ -126,41 +145,48 @@ harper deploy \
|
|
|
126
145
|
replicated=true
|
|
127
146
|
```
|
|
128
147
|
|
|
129
|
-
**
|
|
148
|
+
**Deploy by reference with a tag:**
|
|
130
149
|
|
|
131
150
|
```bash
|
|
132
|
-
|
|
133
|
-
export HARPER_CLI_PASSWORD=secret
|
|
134
|
-
harper deploy \
|
|
135
|
-
project=my-app \
|
|
136
|
-
package="HarperFast/my-app" \
|
|
137
|
-
target=https://my-cluster.harperdbcloud.com \
|
|
138
|
-
restart=true \
|
|
139
|
-
replicated=true
|
|
151
|
+
harper deploy ref=v1.2.0 restart=true replicated=true
|
|
140
152
|
```
|
|
141
153
|
|
|
142
|
-
**Deploy
|
|
154
|
+
**Deploy a private GitHub repo by reference:**
|
|
143
155
|
|
|
144
156
|
```bash
|
|
145
|
-
|
|
157
|
+
# Provision credential once (requires super_user)
|
|
158
|
+
harper deploy setup=true
|
|
159
|
+
|
|
160
|
+
# Deploy using stored credential
|
|
161
|
+
harper deploy by_ref=true credential=true restart=true replicated=true
|
|
146
162
|
```
|
|
147
163
|
|
|
148
|
-
**
|
|
164
|
+
**GitHub Actions — pull request deploy:**
|
|
149
165
|
|
|
150
166
|
```bash
|
|
151
|
-
|
|
152
|
-
|
|
167
|
+
harper deploy ref=${{ github.event.pull_request.head.sha }} restart=true replicated=true
|
|
168
|
+
```
|
|
153
169
|
|
|
154
|
-
|
|
155
|
-
|
|
170
|
+
**CI/CD deploy using environment variables:**
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
export HARPER_CLI_USERNAME=<username>
|
|
174
|
+
export HARPER_CLI_PASSWORD=<password>
|
|
175
|
+
harper deploy \
|
|
176
|
+
project=my-app \
|
|
177
|
+
package="@myorg/my-app" \
|
|
178
|
+
target=https://my-cluster.harperdbcloud.com \
|
|
179
|
+
restart=true \
|
|
180
|
+
replicated=true
|
|
156
181
|
```
|
|
157
182
|
|
|
158
183
|
## Notes
|
|
159
184
|
|
|
160
|
-
-
|
|
185
|
+
- The cluster's Application URL is found on the **Config → Overview** page of the Fabric dashboard.
|
|
186
|
+
- `harper deploy setup=true` calls `get_secrets_public_key`, `set_secret`, and `grant_secret`, all of which require **super_user**. Do not run it with the CI identity.
|
|
161
187
|
- The `enc:v1:` envelope means the plaintext token never leaves your machine — only ciphertext is stored and replicated.
|
|
162
|
-
-
|
|
163
|
-
- Because stored credentials are durable, later deploys and rollbacks reuse them without re-entering anything.
|
|
164
|
-
- The unpushed-commit check is skipped under GitHub Actions; the dirty-tree warning still applies.
|
|
165
|
-
- Deploying by reference means the cluster installs and builds from source. If your application requires a build step that cannot run on the node, deploy the built output as a payload deploy instead.
|
|
188
|
+
- Secrets are stored scoped to the component, not in the global `processEnv` tier. If a global secret already exists at the derived name, it is converted to the scoped tier.
|
|
166
189
|
- For SSH-based private repos, use the `add_ssh_key` operation to register keys before deploying.
|
|
190
|
+
- If your application requires a build step that cannot run on the cluster node, deploy a built payload (omit `by_ref`) instead of deploying by reference.
|
|
191
|
+
- The unpushed-commit check is skipped under GitHub Actions; the dirty-tree warning still applies.
|
|
192
|
+
- Annotated tags in `refs/tags` resolve to the commit they point at, not the tag object.
|