@fatagnus/remote-cmd-relay-convex 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +41 -0
- package/src/README.md +413 -0
- package/src/_generated/api.ts +62 -0
- package/src/_generated/component.ts +565 -0
- package/src/_generated/dataModel.ts +60 -0
- package/src/_generated/server.ts +161 -0
- package/src/assignments.test.ts +233 -0
- package/src/assignments.ts +222 -0
- package/src/commands.test.ts +331 -0
- package/src/commands.ts +286 -0
- package/src/component.ts +11 -0
- package/src/configPush.ts +96 -0
- package/src/convex.config.ts +5 -0
- package/src/credentials.ts +112 -0
- package/src/public.test.ts +576 -0
- package/src/public.ts +436 -0
- package/src/schema.ts +180 -0
- package/src/status.test.ts +308 -0
- package/src/status.ts +172 -0
- package/src/test.helpers.ts +399 -0
- package/src/test.setup.ts +256 -0
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@fatagnus/remote-cmd-relay-convex",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Convex component for managing remote command relays - assignment management, command queuing, status tracking, and credential inventory",
|
|
5
|
+
"author": "Ozan Turksever <ozan.turksever@gmail.com>",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/fatagnus/remote-cmd-relay.git",
|
|
10
|
+
"directory": "packages/convex"
|
|
11
|
+
},
|
|
12
|
+
"type": "module",
|
|
13
|
+
"main": "./src/component.ts",
|
|
14
|
+
"files": [
|
|
15
|
+
"src"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"typecheck": "tsc --noEmit",
|
|
19
|
+
"test": "vitest run"
|
|
20
|
+
},
|
|
21
|
+
"peerDependencies": {
|
|
22
|
+
"convex": "^1.17.0"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"convex": "^1.29.3",
|
|
26
|
+
"convex-test": "^0.0.41",
|
|
27
|
+
"typescript": "^5.7.2",
|
|
28
|
+
"vitest": "^3.0.5"
|
|
29
|
+
},
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=18"
|
|
32
|
+
},
|
|
33
|
+
"keywords": [
|
|
34
|
+
"convex",
|
|
35
|
+
"component",
|
|
36
|
+
"remote",
|
|
37
|
+
"command",
|
|
38
|
+
"relay",
|
|
39
|
+
"ssh"
|
|
40
|
+
]
|
|
41
|
+
}
|
package/src/README.md
ADDED
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
# Remote Command Relay - Convex Component
|
|
2
|
+
|
|
3
|
+
A Convex component that provides the backend infrastructure for managing remote command relays, including assignment management, command queuing, status tracking, credential inventory, and configuration push.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This component enables remote command execution on machines in restricted network segments by:
|
|
8
|
+
|
|
9
|
+
1. **Managing relay assignments** - Link API keys to machines
|
|
10
|
+
2. **Queuing commands** - Store pending commands for relay execution
|
|
11
|
+
3. **Tracking status** - Monitor relay health, capabilities, and metrics
|
|
12
|
+
4. **Credential inventory** - Track what credentials each relay has (metadata only)
|
|
13
|
+
5. **Configuration push** - Push config updates to relays
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
The component is registered in your app's `convex/convex.config.ts`:
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import { defineApp } from "convex/server";
|
|
21
|
+
import remoteCmdRelay from "./remoteCmdRelay/convex.config";
|
|
22
|
+
|
|
23
|
+
const app = defineApp();
|
|
24
|
+
app.use(remoteCmdRelay);
|
|
25
|
+
|
|
26
|
+
export default app;
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Schema
|
|
30
|
+
|
|
31
|
+
### Tables
|
|
32
|
+
|
|
33
|
+
#### `relayAssignments`
|
|
34
|
+
|
|
35
|
+
Links Better Auth API keys to machines.
|
|
36
|
+
|
|
37
|
+
| Field | Type | Description |
|
|
38
|
+
|-------|------|-------------|
|
|
39
|
+
| `apiKeyId` | string | Better Auth API key ID |
|
|
40
|
+
| `machineId` | string | Reference to machine in main app |
|
|
41
|
+
| `name` | string | Friendly name for the relay |
|
|
42
|
+
| `enabled` | boolean | Whether the relay is enabled |
|
|
43
|
+
| `lastSeenAt` | number? | Last heartbeat timestamp |
|
|
44
|
+
| `createdBy` | string | User who created the assignment |
|
|
45
|
+
| `createdAt` | number | Creation timestamp |
|
|
46
|
+
| `updatedAt` | number | Last update timestamp |
|
|
47
|
+
|
|
48
|
+
#### `relayStatus`
|
|
49
|
+
|
|
50
|
+
Tracks relay health, capabilities, and metrics.
|
|
51
|
+
|
|
52
|
+
| Field | Type | Description |
|
|
53
|
+
|-------|------|-------------|
|
|
54
|
+
| `relayId` | string | Reference to relayAssignments._id |
|
|
55
|
+
| `capabilities` | array | List of capabilities (ssh, local_cmd, perf_metrics) |
|
|
56
|
+
| `metrics` | object? | Performance metrics (CPU, memory, disk) |
|
|
57
|
+
| `version` | string? | Relay binary version |
|
|
58
|
+
| `hostname` | string? | Relay host machine name |
|
|
59
|
+
| `platform` | string? | OS platform |
|
|
60
|
+
| `lastHeartbeatAt` | number | Last heartbeat timestamp |
|
|
61
|
+
|
|
62
|
+
#### `relayCredentialInventory`
|
|
63
|
+
|
|
64
|
+
Tracks what credentials each relay reports it has (metadata only, not values).
|
|
65
|
+
|
|
66
|
+
| Field | Type | Description |
|
|
67
|
+
|-------|------|-------------|
|
|
68
|
+
| `relayId` | string | Reference to relayAssignments._id |
|
|
69
|
+
| `credentialName` | string | Name/identifier of the credential |
|
|
70
|
+
| `credentialType` | string | Type: ssh_key, password, api_key |
|
|
71
|
+
| `targetHost` | string? | What host this credential is for |
|
|
72
|
+
| `storageMode` | string | relay_only or shared |
|
|
73
|
+
| `lastUpdatedAt` | number | When credential was last updated on relay |
|
|
74
|
+
| `reportedAt` | number | When relay reported this credential |
|
|
75
|
+
|
|
76
|
+
#### `sharedCredentials`
|
|
77
|
+
|
|
78
|
+
Backup storage for shared mode credentials (encrypted).
|
|
79
|
+
|
|
80
|
+
| Field | Type | Description |
|
|
81
|
+
|-------|------|-------------|
|
|
82
|
+
| `name` | string | Credential name |
|
|
83
|
+
| `credentialType` | string | Type: ssh_key, password, api_key |
|
|
84
|
+
| `targetHost` | string? | What host this credential is for |
|
|
85
|
+
| `encryptedValue` | string | Encrypted credential value |
|
|
86
|
+
| `assignedRelays` | array | List of relay IDs this is assigned to |
|
|
87
|
+
| `createdBy` | string | User who created the credential |
|
|
88
|
+
|
|
89
|
+
#### `configPushQueue`
|
|
90
|
+
|
|
91
|
+
Queue for pushing configuration updates to relays.
|
|
92
|
+
|
|
93
|
+
| Field | Type | Description |
|
|
94
|
+
|-------|------|-------------|
|
|
95
|
+
| `relayId` | string | Target relay |
|
|
96
|
+
| `pushType` | string | Type: credential, ssh_targets, allowed_commands, metrics_interval |
|
|
97
|
+
| `payload` | string | JSON-encoded payload |
|
|
98
|
+
| `status` | string | Status: pending, sent, acked, failed |
|
|
99
|
+
| `createdBy` | string | User who created the push |
|
|
100
|
+
| `errorMessage` | string? | Error message if failed |
|
|
101
|
+
|
|
102
|
+
#### `commandQueue`
|
|
103
|
+
|
|
104
|
+
Commands waiting to be executed by relays.
|
|
105
|
+
|
|
106
|
+
| Field | Type | Description |
|
|
107
|
+
|-------|------|-------------|
|
|
108
|
+
| `machineId` | string | Target machine (relay assignment) |
|
|
109
|
+
| `targetType` | string | local or ssh |
|
|
110
|
+
| `targetHost` | string? | SSH target host |
|
|
111
|
+
| `targetPort` | number? | SSH target port |
|
|
112
|
+
| `targetUsername` | string? | SSH username |
|
|
113
|
+
| `command` | string | Command to execute |
|
|
114
|
+
| `timeoutMs` | number | Command timeout |
|
|
115
|
+
| `status` | string | pending, claimed, executing, completed, failed, timeout |
|
|
116
|
+
| `output` | string? | Command stdout |
|
|
117
|
+
| `stderr` | string? | Command stderr |
|
|
118
|
+
| `exitCode` | number? | Exit code |
|
|
119
|
+
| `error` | string? | Error message |
|
|
120
|
+
| `durationMs` | number? | Execution duration |
|
|
121
|
+
|
|
122
|
+
## Functions
|
|
123
|
+
|
|
124
|
+
### Assignments (`assignments.ts`)
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
// Create a new relay assignment
|
|
128
|
+
await ctx.runMutation(components.remoteCmdRelay.assignments.create, {
|
|
129
|
+
apiKeyId: "api_key_id",
|
|
130
|
+
machineId: "machine_id",
|
|
131
|
+
name: "Production Relay",
|
|
132
|
+
createdBy: "user_id",
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
// List all assignments
|
|
136
|
+
const assignments = await ctx.runQuery(
|
|
137
|
+
components.remoteCmdRelay.assignments.listAll,
|
|
138
|
+
{}
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
// Update assignment
|
|
142
|
+
await ctx.runMutation(components.remoteCmdRelay.assignments.update, {
|
|
143
|
+
id: assignmentId,
|
|
144
|
+
enabled: false,
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// Delete assignment
|
|
148
|
+
await ctx.runMutation(components.remoteCmdRelay.assignments.remove, {
|
|
149
|
+
id: assignmentId,
|
|
150
|
+
});
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Commands (`commands.ts`)
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
// Queue a command
|
|
157
|
+
await ctx.runMutation(components.remoteCmdRelay.commands.queue, {
|
|
158
|
+
machineId: "machine_id",
|
|
159
|
+
command: "df -h",
|
|
160
|
+
targetType: "local",
|
|
161
|
+
timeoutMs: 30000,
|
|
162
|
+
createdBy: "user_id",
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
// Queue SSH command
|
|
166
|
+
await ctx.runMutation(components.remoteCmdRelay.commands.queue, {
|
|
167
|
+
machineId: "machine_id",
|
|
168
|
+
command: "systemctl status nginx",
|
|
169
|
+
targetType: "ssh",
|
|
170
|
+
targetHost: "192.168.1.100",
|
|
171
|
+
targetPort: 22,
|
|
172
|
+
targetUsername: "admin",
|
|
173
|
+
timeoutMs: 30000,
|
|
174
|
+
createdBy: "user_id",
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
// Get pending commands for a machine
|
|
178
|
+
const commands = await ctx.runQuery(
|
|
179
|
+
components.remoteCmdRelay.commands.getPending,
|
|
180
|
+
{ machineId: "machine_id" }
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
// Claim a command (relay calls this)
|
|
184
|
+
await ctx.runMutation(components.remoteCmdRelay.commands.claim, {
|
|
185
|
+
commandId: "command_id",
|
|
186
|
+
claimedBy: "relay_id",
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
// Complete a command with results
|
|
190
|
+
await ctx.runMutation(components.remoteCmdRelay.commands.complete, {
|
|
191
|
+
commandId: "command_id",
|
|
192
|
+
success: true,
|
|
193
|
+
output: "Filesystem Size Used Avail Use% Mounted on\n...",
|
|
194
|
+
exitCode: 0,
|
|
195
|
+
durationMs: 150,
|
|
196
|
+
});
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### Status (`status.ts`)
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
// Report relay status (relay calls this)
|
|
203
|
+
await ctx.runMutation(components.remoteCmdRelay.status.reportStatus, {
|
|
204
|
+
relayId: "relay_id",
|
|
205
|
+
capabilities: ["ssh", "local_cmd", "perf_metrics"],
|
|
206
|
+
metrics: {
|
|
207
|
+
cpuPercent: 25.5,
|
|
208
|
+
memoryPercent: 60.2,
|
|
209
|
+
diskPercent: 45.0,
|
|
210
|
+
},
|
|
211
|
+
version: "1.0.0",
|
|
212
|
+
hostname: "prod-server-01",
|
|
213
|
+
platform: "linux",
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
// Get status for a relay
|
|
217
|
+
const status = await ctx.runQuery(
|
|
218
|
+
components.remoteCmdRelay.status.getByRelayId,
|
|
219
|
+
{ relayId: "relay_id" }
|
|
220
|
+
);
|
|
221
|
+
|
|
222
|
+
// List all relay statuses
|
|
223
|
+
const statuses = await ctx.runQuery(
|
|
224
|
+
components.remoteCmdRelay.status.listAll,
|
|
225
|
+
{}
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
// Find relays with specific capability
|
|
229
|
+
const sshRelays = await ctx.runQuery(
|
|
230
|
+
components.remoteCmdRelay.status.findByCapability,
|
|
231
|
+
{ capability: "ssh" }
|
|
232
|
+
);
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Credentials (`credentials.ts`)
|
|
236
|
+
|
|
237
|
+
```typescript
|
|
238
|
+
// Report credential inventory (relay calls this)
|
|
239
|
+
await ctx.runMutation(components.remoteCmdRelay.credentials.reportInventory, {
|
|
240
|
+
relayId: "relay_id",
|
|
241
|
+
credentials: [
|
|
242
|
+
{
|
|
243
|
+
credentialName: "prod-server-ssh",
|
|
244
|
+
credentialType: "ssh_key",
|
|
245
|
+
targetHost: "192.168.1.100",
|
|
246
|
+
storageMode: "relay_only",
|
|
247
|
+
lastUpdatedAt: Date.now(),
|
|
248
|
+
},
|
|
249
|
+
],
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
// Get credential inventory for a relay
|
|
253
|
+
const inventory = await ctx.runQuery(
|
|
254
|
+
components.remoteCmdRelay.credentials.getInventoryByRelayId,
|
|
255
|
+
{ relayId: "relay_id" }
|
|
256
|
+
);
|
|
257
|
+
|
|
258
|
+
// Find relays that have credentials for a target
|
|
259
|
+
const relays = await ctx.runQuery(
|
|
260
|
+
components.remoteCmdRelay.credentials.findRelaysForTarget,
|
|
261
|
+
{ targetHost: "192.168.1.100" }
|
|
262
|
+
);
|
|
263
|
+
|
|
264
|
+
// Create shared credential (stored on center)
|
|
265
|
+
await ctx.runMutation(components.remoteCmdRelay.credentials.createSharedCredential, {
|
|
266
|
+
name: "shared-api-key",
|
|
267
|
+
credentialType: "api_key",
|
|
268
|
+
encryptedValue: "encrypted...",
|
|
269
|
+
assignedRelays: ["relay_id_1", "relay_id_2"],
|
|
270
|
+
createdBy: "user_id",
|
|
271
|
+
});
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Config Push (`configPush.ts`)
|
|
275
|
+
|
|
276
|
+
```typescript
|
|
277
|
+
// Queue a config push
|
|
278
|
+
await ctx.runMutation(components.remoteCmdRelay.configPush.queuePush, {
|
|
279
|
+
relayId: "relay_id",
|
|
280
|
+
pushType: "credential",
|
|
281
|
+
payload: JSON.stringify({ name: "new-credential", ... }),
|
|
282
|
+
createdBy: "user_id",
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
// Get pending pushes for a relay
|
|
286
|
+
const pending = await ctx.runQuery(
|
|
287
|
+
components.remoteCmdRelay.configPush.getPendingForRelay,
|
|
288
|
+
{ relayId: "relay_id" }
|
|
289
|
+
);
|
|
290
|
+
|
|
291
|
+
// Acknowledge a push
|
|
292
|
+
await ctx.runMutation(components.remoteCmdRelay.configPush.acknowledge, {
|
|
293
|
+
pushId: "push_id",
|
|
294
|
+
success: true,
|
|
295
|
+
});
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### Public API (`public.ts`)
|
|
299
|
+
|
|
300
|
+
HTTP-accessible functions for relay communication:
|
|
301
|
+
|
|
302
|
+
```typescript
|
|
303
|
+
// Verify relay API key
|
|
304
|
+
const result = await ctx.runQuery(
|
|
305
|
+
components.remoteCmdRelay.public.verifyRelay,
|
|
306
|
+
{ apiKeyId: "api_key_id" }
|
|
307
|
+
);
|
|
308
|
+
|
|
309
|
+
// Get pending commands
|
|
310
|
+
const commands = await ctx.runQuery(
|
|
311
|
+
components.remoteCmdRelay.public.getPendingCommands,
|
|
312
|
+
{ machineId: "machine_id" }
|
|
313
|
+
);
|
|
314
|
+
|
|
315
|
+
// Claim a command
|
|
316
|
+
await ctx.runMutation(components.remoteCmdRelay.public.claimCommand, {
|
|
317
|
+
commandId: "command_id",
|
|
318
|
+
assignmentId: "assignment_id",
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
// Submit command result
|
|
322
|
+
await ctx.runMutation(components.remoteCmdRelay.public.submitResult, {
|
|
323
|
+
commandId: "command_id",
|
|
324
|
+
success: true,
|
|
325
|
+
output: "...",
|
|
326
|
+
exitCode: 0,
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
// Send heartbeat
|
|
330
|
+
await ctx.runMutation(components.remoteCmdRelay.public.sendHeartbeat, {
|
|
331
|
+
apiKeyId: "api_key_id",
|
|
332
|
+
});
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
## HTTP Routes
|
|
336
|
+
|
|
337
|
+
The component exposes HTTP endpoints in `convex/http.ts`:
|
|
338
|
+
|
|
339
|
+
| Method | Path | Description |
|
|
340
|
+
|--------|------|-------------|
|
|
341
|
+
| POST | `/relay/verify` | Verify API key and get assignment |
|
|
342
|
+
| GET | `/relay/commands` | Get pending commands |
|
|
343
|
+
| POST | `/relay/commands/claim` | Claim a command |
|
|
344
|
+
| POST | `/relay/commands/result` | Submit command result |
|
|
345
|
+
| POST | `/relay/heartbeat` | Send heartbeat |
|
|
346
|
+
| POST | `/relay/status` | Report full status |
|
|
347
|
+
|
|
348
|
+
All endpoints require the `X-API-Key` header (except `/relay/verify` which takes it in the body).
|
|
349
|
+
|
|
350
|
+
## Types
|
|
351
|
+
|
|
352
|
+
### Capabilities
|
|
353
|
+
|
|
354
|
+
```typescript
|
|
355
|
+
type Capability = "ssh" | "local_cmd" | "perf_metrics";
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### Credential Types
|
|
359
|
+
|
|
360
|
+
```typescript
|
|
361
|
+
type CredentialType = "ssh_key" | "password" | "api_key";
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
### Storage Modes
|
|
365
|
+
|
|
366
|
+
```typescript
|
|
367
|
+
type StorageMode = "relay_only" | "shared";
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### Command Status
|
|
371
|
+
|
|
372
|
+
```typescript
|
|
373
|
+
type CommandStatus =
|
|
374
|
+
| "pending"
|
|
375
|
+
| "claimed"
|
|
376
|
+
| "executing"
|
|
377
|
+
| "completed"
|
|
378
|
+
| "failed"
|
|
379
|
+
| "timeout";
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### Config Push Types
|
|
383
|
+
|
|
384
|
+
```typescript
|
|
385
|
+
type ConfigPushType =
|
|
386
|
+
| "credential"
|
|
387
|
+
| "ssh_targets"
|
|
388
|
+
| "allowed_commands"
|
|
389
|
+
| "metrics_interval";
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
## Security Considerations
|
|
393
|
+
|
|
394
|
+
1. **API Key Validation**: All relay communication is authenticated via Better Auth API keys
|
|
395
|
+
2. **Credential Security**:
|
|
396
|
+
- `relay_only` credentials never leave the relay
|
|
397
|
+
- `shared` credentials are stored encrypted on center
|
|
398
|
+
- Credential inventory only reports metadata (names), not values
|
|
399
|
+
3. **Admin Access**: All management functions require admin role
|
|
400
|
+
4. **Command Routing**: Commands are only sent to relays assigned to the target machine
|
|
401
|
+
|
|
402
|
+
## Files
|
|
403
|
+
|
|
404
|
+
| File | Description |
|
|
405
|
+
|------|-------------|
|
|
406
|
+
| `convex.config.ts` | Component definition |
|
|
407
|
+
| `schema.ts` | Database schema and validators |
|
|
408
|
+
| `assignments.ts` | Relay assignment CRUD |
|
|
409
|
+
| `commands.ts` | Command queue management |
|
|
410
|
+
| `status.ts` | Relay status and capability tracking |
|
|
411
|
+
| `credentials.ts` | Credential inventory and shared credentials |
|
|
412
|
+
| `configPush.ts` | Configuration push queue |
|
|
413
|
+
| `public.ts` | HTTP-accessible functions for relays |
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
/**
|
|
3
|
+
* Generated `api` utility.
|
|
4
|
+
*
|
|
5
|
+
* THIS CODE IS AUTOMATICALLY GENERATED.
|
|
6
|
+
*
|
|
7
|
+
* To regenerate, run `npx convex dev`.
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type * as assignments from "../assignments.js";
|
|
12
|
+
import type * as commands from "../commands.js";
|
|
13
|
+
import type * as component from "../component.js";
|
|
14
|
+
import type * as configPush from "../configPush.js";
|
|
15
|
+
import type * as credentials from "../credentials.js";
|
|
16
|
+
import type * as public_ from "../public.js";
|
|
17
|
+
import type * as status from "../status.js";
|
|
18
|
+
|
|
19
|
+
import type {
|
|
20
|
+
ApiFromModules,
|
|
21
|
+
FilterApi,
|
|
22
|
+
FunctionReference,
|
|
23
|
+
} from "convex/server";
|
|
24
|
+
import { anyApi, componentsGeneric } from "convex/server";
|
|
25
|
+
|
|
26
|
+
const fullApi: ApiFromModules<{
|
|
27
|
+
assignments: typeof assignments;
|
|
28
|
+
commands: typeof commands;
|
|
29
|
+
component: typeof component;
|
|
30
|
+
configPush: typeof configPush;
|
|
31
|
+
credentials: typeof credentials;
|
|
32
|
+
public: typeof public_;
|
|
33
|
+
status: typeof status;
|
|
34
|
+
}> = anyApi as any;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* A utility for referencing Convex functions in your app's public API.
|
|
38
|
+
*
|
|
39
|
+
* Usage:
|
|
40
|
+
* ```js
|
|
41
|
+
* const myFunctionReference = api.myModule.myFunction;
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export const api: FilterApi<
|
|
45
|
+
typeof fullApi,
|
|
46
|
+
FunctionReference<any, "public">
|
|
47
|
+
> = anyApi as any;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* A utility for referencing Convex functions in your app's internal API.
|
|
51
|
+
*
|
|
52
|
+
* Usage:
|
|
53
|
+
* ```js
|
|
54
|
+
* const myFunctionReference = internal.myModule.myFunction;
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export const internal: FilterApi<
|
|
58
|
+
typeof fullApi,
|
|
59
|
+
FunctionReference<any, "internal">
|
|
60
|
+
> = anyApi as any;
|
|
61
|
+
|
|
62
|
+
export const components = componentsGeneric() as unknown as {};
|