@harperfast/template-react-ts-studio 1.11.2 → 1.11.4
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 +702 -490
- package/.agents/skills/harper-best-practices/SKILL.md +1 -0
- 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/delegating-to-the-built-in-agent.md +141 -0
- 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-best-practices/rules.manifest.yaml +9 -0
- 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 +702 -490
- package/agent/skills/harper-best-practices/SKILL.md +1 -0
- 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/delegating-to-the-built-in-agent.md +141 -0
- 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-best-practices/rules.manifest.yaml +9 -0
- 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 +1 -1
- package/skills-lock.json +7 -1
|
@@ -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`.
|
|
@@ -7,8 +7,8 @@ metadata:
|
|
|
7
7
|
mode: generate
|
|
8
8
|
sources:
|
|
9
9
|
- reference/v5/environment-variables/overview.md
|
|
10
|
-
sourceCommit:
|
|
11
|
-
inputHash:
|
|
10
|
+
sourceCommit: 3749d0c54be457a2a65d9a63c738a5dc88989ecd
|
|
11
|
+
inputHash: b4db5ede6b93d426
|
|
12
12
|
---
|
|
13
13
|
|
|
14
14
|
# Load Environment Variables with loadEnv
|
|
@@ -17,18 +17,18 @@ Instructions for the agent to follow when loading environment variables from `.e
|
|
|
17
17
|
|
|
18
18
|
## When to Use
|
|
19
19
|
|
|
20
|
-
Apply this rule when a Harper application needs to
|
|
20
|
+
Apply this rule when a Harper application needs to supply secrets, API endpoints, or other configuration values to component code via `process.env` without hardcoding them. Use `loadEnv` any time you need to load one or more `.env` files at application startup.
|
|
21
21
|
|
|
22
22
|
## How It Works
|
|
23
23
|
|
|
24
|
-
1. **Declare `loadEnv` in `config.yaml`**: Add `loadEnv` as
|
|
24
|
+
1. **Declare `loadEnv` in `config.yaml`**: Add `loadEnv` as the first entry in `config.yaml`. It is built into Harper and requires no installation.
|
|
25
25
|
|
|
26
26
|
```yaml
|
|
27
27
|
loadEnv:
|
|
28
28
|
files: '.env'
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
2. **Place `loadEnv` first**:
|
|
31
|
+
2. **Place `loadEnv` first**: Harper is a single-process application. List `loadEnv` before all other components so that environment variables are available on `process.env` before dependent components start.
|
|
32
32
|
|
|
33
33
|
```yaml
|
|
34
34
|
# config.yaml — loadEnv must come first
|
|
@@ -41,9 +41,9 @@ Apply this rule when a Harper application needs to load secrets or configuration
|
|
|
41
41
|
files: './src/*.js'
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
3. **
|
|
44
|
+
3. **Access loaded values in component code**: After `loadEnv` runs, all loaded values are available on `process.env` and shared across all components.
|
|
45
45
|
|
|
46
|
-
4. **
|
|
46
|
+
4. **Control override behavior**: By default, existing environment variables take precedence over values in `.env` files. Set `override: true` to make loaded values win instead.
|
|
47
47
|
|
|
48
48
|
```yaml
|
|
49
49
|
loadEnv:
|
|
@@ -51,14 +51,17 @@ Apply this rule when a Harper application needs to load secrets or configuration
|
|
|
51
51
|
override: true
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
-
5. **Load multiple files
|
|
54
|
+
5. **Load multiple files**: Pass an array of paths or a glob pattern to `files`. Files are loaded in the order specified.
|
|
55
|
+
|
|
55
56
|
```yaml
|
|
56
57
|
loadEnv:
|
|
57
58
|
files:
|
|
58
59
|
- '.env'
|
|
59
60
|
- '.env.local'
|
|
60
61
|
```
|
|
61
|
-
|
|
62
|
+
|
|
63
|
+
or with a glob:
|
|
64
|
+
|
|
62
65
|
```yaml
|
|
63
66
|
loadEnv:
|
|
64
67
|
files: 'env-vars/*'
|
|
@@ -73,17 +76,23 @@ Apply this rule when a Harper application needs to load secrets or configuration
|
|
|
73
76
|
|
|
74
77
|
## Examples
|
|
75
78
|
|
|
76
|
-
**
|
|
79
|
+
**Single file, default behavior:**
|
|
77
80
|
|
|
78
81
|
```yaml
|
|
82
|
+
# config.yaml
|
|
79
83
|
loadEnv:
|
|
80
84
|
files: '.env'
|
|
85
|
+
|
|
86
|
+
rest: true
|
|
87
|
+
|
|
88
|
+
myApp:
|
|
89
|
+
files: './src/*.js'
|
|
81
90
|
```
|
|
82
91
|
|
|
83
|
-
**
|
|
92
|
+
**Multiple files with override:**
|
|
84
93
|
|
|
85
94
|
```yaml
|
|
86
|
-
# config.yaml
|
|
95
|
+
# config.yaml
|
|
87
96
|
loadEnv:
|
|
88
97
|
files:
|
|
89
98
|
- '.env'
|
|
@@ -96,16 +105,8 @@ myApp:
|
|
|
96
105
|
files: './src/*.js'
|
|
97
106
|
```
|
|
98
107
|
|
|
99
|
-
**Glob pattern:**
|
|
100
|
-
|
|
101
|
-
```yaml
|
|
102
|
-
loadEnv:
|
|
103
|
-
files: 'env-vars/*'
|
|
104
|
-
```
|
|
105
|
-
|
|
106
108
|
## Notes
|
|
107
109
|
|
|
108
|
-
- `loadEnv`
|
|
109
|
-
-
|
|
110
|
-
-
|
|
111
|
-
- `files` is the only required option; omitting it will produce an invalid configuration.
|
|
110
|
+
- `loadEnv` loads values into `process.env` for **application** code only — it does not configure Harper itself.
|
|
111
|
+
- Harper's own instance-wide configuration is composed at startup **before** any component's `loadEnv` runs. Variables such as `HARPER_CONFIG`, `HARPER_SET_CONFIG`, and `HARPER_DEFAULT_CONFIG` delivered through a `.env` file are read too late and are ignored. Set Harper configuration directly in the configuration file or export variables in the real process/container environment before Harper starts.
|
|
112
|
+
- For production credentials, prefer the encrypted secrets store over a committed `.env` file. Secrets are also delivered to components via `process.env`.
|
|
@@ -14,8 +14,8 @@ metadata:
|
|
|
14
14
|
reference/v5/resources/resource-api.md#`addTo(property: string, value:
|
|
15
15
|
number)`
|
|
16
16
|
- reference/v5/components/javascript-environment.md#Module Loading
|
|
17
|
-
sourceCommit:
|
|
18
|
-
inputHash:
|
|
17
|
+
sourceCommit: 3749d0c54be457a2a65d9a63c738a5dc88989ecd
|
|
18
|
+
inputHash: ace5c3f4a0ad4519
|
|
19
19
|
---
|
|
20
20
|
|
|
21
21
|
# Programmatic Table Requests
|
|
@@ -24,11 +24,11 @@ Instructions for the agent to interact with Harper tables programmatically using
|
|
|
24
24
|
|
|
25
25
|
## When to Use
|
|
26
26
|
|
|
27
|
-
Apply this rule when writing server-side
|
|
27
|
+
Apply this rule when writing server-side code that reads from or writes to Harper tables directly — for example, in request handlers, background jobs, or SSR rendering — without going through the REST API. Use it whenever you need to construct queries with `conditions`, `select`, `sort`, or `search(`.
|
|
28
28
|
|
|
29
29
|
## How It Works
|
|
30
30
|
|
|
31
|
-
1. **Import `tables`**:
|
|
31
|
+
1. **Import `tables`**: Pull `tables` from the `harper` package. Each property on `tables` corresponds to a table defined in `schema.graphql`.
|
|
32
32
|
|
|
33
33
|
```javascript
|
|
34
34
|
import { tables } from 'harper';
|
|
@@ -36,10 +36,9 @@ Apply this rule when writing server-side Harper code that reads from or writes t
|
|
|
36
36
|
// same as: databases.data.Product
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
2. **Define your schema**: Declare tables in `schema.graphql
|
|
39
|
+
2. **Define your schema**: Declare tables with `@table` in `schema.graphql`. Each type becomes a property on `tables`.
|
|
40
40
|
|
|
41
41
|
```graphql
|
|
42
|
-
# schema.graphql
|
|
43
42
|
type Product @table {
|
|
44
43
|
id: Long @primaryKey
|
|
45
44
|
name: String
|
|
@@ -47,57 +46,75 @@ Apply this rule when writing server-side Harper code that reads from or writes t
|
|
|
47
46
|
}
|
|
48
47
|
```
|
|
49
48
|
|
|
50
|
-
3. **Create and
|
|
49
|
+
3. **Create and modify records**: Use `create`, `patch`, and `get` for basic CRUD.
|
|
51
50
|
|
|
52
51
|
```javascript
|
|
53
|
-
// Create a new record (id auto-generated)
|
|
54
52
|
const created = await Product.create({ name: 'Shirt', price: 9.5 });
|
|
55
|
-
|
|
56
|
-
// Modify the record
|
|
57
53
|
await Product.patch(created.id, { price: Math.round(created.price * 0.8 * 100) / 100 });
|
|
58
|
-
|
|
59
|
-
// Retrieve by primary key
|
|
60
54
|
const record = await Product.get(created.id);
|
|
61
55
|
```
|
|
62
56
|
|
|
63
|
-
4. **Query with `search(
|
|
57
|
+
4. **Query with `search(`**: Pass a query object to `Product.search(query)`. It returns an async iterable.
|
|
64
58
|
|
|
65
59
|
```javascript
|
|
66
60
|
const query = {
|
|
67
61
|
conditions: [{ attribute: 'price', comparator: 'less_than', value: 8.0 }],
|
|
68
62
|
};
|
|
69
63
|
for await (const record of Product.search(query)) {
|
|
70
|
-
//
|
|
64
|
+
// process record
|
|
71
65
|
}
|
|
72
66
|
```
|
|
73
67
|
|
|
74
|
-
5. **
|
|
68
|
+
5. **Build `conditions`**: Each condition object filters records. Nest conditions with `operator` for boolean logic.
|
|
69
|
+
|
|
70
|
+
| Property | Description |
|
|
71
|
+
| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
72
|
+
| `attribute` | Property name, or array for chained/joined properties (e.g. `['brand', 'name']`) |
|
|
73
|
+
| `value` | The value to match |
|
|
74
|
+
| `comparator` | `equals` (default), `greater_than`, `greater_than_equal`, `less_than`, `less_than_equal`, `starts_with`, `contains`, `ends_with`, `between`, `not_equal` |
|
|
75
|
+
| `conditions` | Nested conditions array |
|
|
76
|
+
| `operator` | `and` (default) or `or` for the nested `conditions` |
|
|
77
|
+
|
|
78
|
+
6. **Use `select`** to control which properties are returned. Accepts an array of property names, a string for a single property, or nested objects for relationships.
|
|
75
79
|
|
|
76
80
|
```javascript
|
|
77
|
-
|
|
78
|
-
|
|
81
|
+
// Array of names
|
|
82
|
+
Product.search({ select: ['name', 'price'] });
|
|
79
83
|
|
|
80
|
-
//
|
|
81
|
-
|
|
82
|
-
id: 42,
|
|
83
|
-
select: ['id', 'title', { name: 'author', select: ['name'] }],
|
|
84
|
-
});
|
|
84
|
+
// Nested relationship select
|
|
85
|
+
Book.get({ id: 42, select: ['id', 'title', { name: 'author', select: ['name'] }] });
|
|
85
86
|
```
|
|
86
87
|
|
|
87
|
-
|
|
88
|
+
Special `select` values:
|
|
89
|
+
- `$id` — returns the primary key regardless of its name
|
|
90
|
+
- `$updatedtime` — returns the last-updated timestamp
|
|
91
|
+
- `$distance` — returns the computed distance when querying a vector index
|
|
92
|
+
|
|
93
|
+
7. **Use `addTo`** for concurrent-safe numeric increments (CRDT incrementation, safe across threads and nodes).
|
|
88
94
|
|
|
89
95
|
```javascript
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
record.addTo('quantity', -1); // decrement safely across nodes
|
|
93
|
-
}
|
|
96
|
+
const record = await Product.update(target.id);
|
|
97
|
+
record.addTo('quantity', -1);
|
|
94
98
|
```
|
|
95
99
|
|
|
96
|
-
|
|
100
|
+
8. **Apply `sort`, `limit`, and `offset`** for ordering and pagination. A `sort` attribute must be `@indexed`, or at least one `conditions` entry must be present. Pass `allowFullScan: true` to permit an unconditional ordered scan.
|
|
101
|
+
|
|
102
|
+
```javascript
|
|
103
|
+
Product.search({
|
|
104
|
+
conditions: [{ attribute: 'id', comparator: 'greater_than', value: '' }],
|
|
105
|
+
sort: { attribute: 'id' },
|
|
106
|
+
});
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
| Sort property | Description |
|
|
110
|
+
| ------------- | ---------------------------------------------------------- |
|
|
111
|
+
| `attribute` | Property name (or array for chained relationship property) |
|
|
112
|
+
| `descending` | Sort descending if `true` (default: `false`) |
|
|
113
|
+
| `next` | Secondary sort to resolve ties (same structure) |
|
|
97
114
|
|
|
98
115
|
## Examples
|
|
99
116
|
|
|
100
|
-
|
|
117
|
+
**Nested conditions with `or`:**
|
|
101
118
|
|
|
102
119
|
```javascript
|
|
103
120
|
Product.search({
|
|
@@ -114,23 +131,25 @@ Product.search({
|
|
|
114
131
|
});
|
|
115
132
|
```
|
|
116
133
|
|
|
117
|
-
|
|
134
|
+
**Chained attribute reference (relationship join):**
|
|
118
135
|
|
|
119
136
|
```javascript
|
|
120
137
|
Product.search({ conditions: [{ attribute: ['brand', 'name'], value: 'Harper' }] });
|
|
121
138
|
```
|
|
122
139
|
|
|
123
|
-
|
|
140
|
+
**Deep nested `select` across multiple relationships:**
|
|
124
141
|
|
|
125
142
|
```javascript
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
]
|
|
143
|
+
Product.search({
|
|
144
|
+
select: [
|
|
145
|
+
'id',
|
|
146
|
+
'name',
|
|
147
|
+
{ name: 'segments', select: ['id', 'name', { name: 'client', select: ['id', 'name'] }] },
|
|
148
|
+
],
|
|
149
|
+
});
|
|
131
150
|
```
|
|
132
151
|
|
|
133
|
-
|
|
152
|
+
**SSR usage — read directly from `tables` in a render function:**
|
|
134
153
|
|
|
135
154
|
```typescript
|
|
136
155
|
import { tables } from 'harper';
|
|
@@ -143,44 +162,9 @@ export async function render(url: string): Promise<string> {
|
|
|
143
162
|
|
|
144
163
|
## Notes
|
|
145
164
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
| `greater_than_equal` | Greater than or equal |
|
|
153
|
-
| `less_than` | Strictly less |
|
|
154
|
-
| `less_than_equal` | Less than or equal |
|
|
155
|
-
| `starts_with` | String prefix match |
|
|
156
|
-
| `contains` | String contains |
|
|
157
|
-
| `ends_with` | String suffix match |
|
|
158
|
-
| `between` | Range match |
|
|
159
|
-
| `not_equal` | Inequality match |
|
|
160
|
-
|
|
161
|
-
### Query object options
|
|
162
|
-
|
|
163
|
-
| Property | Description |
|
|
164
|
-
| ----------------------- | ----------------------------------------------------------------------- |
|
|
165
|
-
| `conditions` | Array of condition objects to filter records |
|
|
166
|
-
| `operator` | Top-level `and` (default) or `or` for the `conditions` array |
|
|
167
|
-
| `limit` | Maximum number of records to return |
|
|
168
|
-
| `offset` | Number of records to skip (for pagination) |
|
|
169
|
-
| `select` | Properties to include in each returned record |
|
|
170
|
-
| `sort` | Sort order object with `attribute`, `descending`, and `next` properties |
|
|
171
|
-
| `explain` | If `true`, returns conditions reordered as Harper will execute them |
|
|
172
|
-
| `enforceExecutionOrder` | If `true`, forces conditions to execute in the order supplied |
|
|
173
|
-
|
|
174
|
-
### `select` special properties
|
|
175
|
-
|
|
176
|
-
- `$id` — Returns the primary key regardless of its name
|
|
177
|
-
- `$updatedtime` — Returns the last-updated timestamp
|
|
178
|
-
- `$distance` — Returns the computed distance from the target vector when the query uses a vector index
|
|
179
|
-
|
|
180
|
-
### Relationship join behavior
|
|
181
|
-
|
|
182
|
-
- Selecting a relationship **without** filtering on it behaves as a **LEFT JOIN** — records with no related row are still returned.
|
|
183
|
-
- Adding a `conditions` entry on a related attribute (e.g. `attribute: ['author', 'name']`) behaves as an **INNER JOIN** — only records with a matching related row are returned.
|
|
184
|
-
|
|
185
|
-
- Keep `harper` external when bundling for SSR (e.g. `ssr: { external: ['harper'] }` in `vite.config`) so it resolves to the runtime instead of being bundled.
|
|
186
|
-
- `tables`, `databases`, and other Harper APIs are the same live, process-wide objects regardless of whether accessed as globals or via `import { tables } from 'harper'`.
|
|
165
|
+
- Scope destructive operations (`update`, `patch`, `delete`) with specific `conditions` and validate the affected set before writing. These operate on live data and are not easily reversible.
|
|
166
|
+
- Sorting by a bare `@primaryKey` with no conditions raises `HdbError: <attribute> is not indexed and not combined with any other conditions`. Add an open-ended condition or pass `allowFullScan: true`.
|
|
167
|
+
- Selecting a relationship field without filtering on it behaves as a **LEFT JOIN**. Adding a condition on a related attribute (e.g. `attribute: ['author', 'name']`) behaves as an **INNER JOIN**.
|
|
168
|
+
- A to-many relationship resolves to an array; `await` the property before iterating when needed.
|
|
169
|
+
- `tables` and `databases.data` reference the same live objects — a record written through one component is immediately visible to all others.
|
|
170
|
+
- Keep `harper` external when bundling for SSR (e.g. `ssr: { external: ['harper'] }` in `vite.config`) so it resolves to the runtime.
|