@boxd-sh/convex 0.1.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.
Files changed (94) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +264 -0
  3. package/dist/client/_generated/_ignore.d.ts +1 -0
  4. package/dist/client/_generated/_ignore.d.ts.map +1 -0
  5. package/dist/client/_generated/_ignore.js +3 -0
  6. package/dist/client/_generated/_ignore.js.map +1 -0
  7. package/dist/client/index.d.ts +327 -0
  8. package/dist/client/index.d.ts.map +1 -0
  9. package/dist/client/index.js +126 -0
  10. package/dist/client/index.js.map +1 -0
  11. package/dist/component/_generated/api.d.ts +52 -0
  12. package/dist/component/_generated/api.d.ts.map +1 -0
  13. package/dist/component/_generated/api.js +31 -0
  14. package/dist/component/_generated/api.js.map +1 -0
  15. package/dist/component/_generated/component.d.ts +357 -0
  16. package/dist/component/_generated/component.d.ts.map +1 -0
  17. package/dist/component/_generated/component.js +11 -0
  18. package/dist/component/_generated/component.js.map +1 -0
  19. package/dist/component/_generated/dataModel.d.ts +46 -0
  20. package/dist/component/_generated/dataModel.d.ts.map +1 -0
  21. package/dist/component/_generated/dataModel.js +11 -0
  22. package/dist/component/_generated/dataModel.js.map +1 -0
  23. package/dist/component/_generated/server.d.ts +135 -0
  24. package/dist/component/_generated/server.d.ts.map +1 -0
  25. package/dist/component/_generated/server.js +80 -0
  26. package/dist/component/_generated/server.js.map +1 -0
  27. package/dist/component/boxd.d.ts +35 -0
  28. package/dist/component/boxd.d.ts.map +1 -0
  29. package/dist/component/boxd.js +144 -0
  30. package/dist/component/boxd.js.map +1 -0
  31. package/dist/component/convex.config.d.ts +6 -0
  32. package/dist/component/convex.config.d.ts.map +1 -0
  33. package/dist/component/convex.config.js +9 -0
  34. package/dist/component/convex.config.js.map +1 -0
  35. package/dist/component/errors.d.ts +25 -0
  36. package/dist/component/errors.d.ts.map +1 -0
  37. package/dist/component/errors.js +75 -0
  38. package/dist/component/errors.js.map +1 -0
  39. package/dist/component/exec.d.ts +25 -0
  40. package/dist/component/exec.d.ts.map +1 -0
  41. package/dist/component/exec.js +100 -0
  42. package/dist/component/exec.js.map +1 -0
  43. package/dist/component/executions.d.ts +70 -0
  44. package/dist/component/executions.d.ts.map +1 -0
  45. package/dist/component/executions.js +106 -0
  46. package/dist/component/executions.js.map +1 -0
  47. package/dist/component/files.d.ts +44 -0
  48. package/dist/component/files.d.ts.map +1 -0
  49. package/dist/component/files.js +105 -0
  50. package/dist/component/files.js.map +1 -0
  51. package/dist/component/limits.d.ts +33 -0
  52. package/dist/component/limits.d.ts.map +1 -0
  53. package/dist/component/limits.js +44 -0
  54. package/dist/component/limits.js.map +1 -0
  55. package/dist/component/machines.d.ts +337 -0
  56. package/dist/component/machines.d.ts.map +1 -0
  57. package/dist/component/machines.js +411 -0
  58. package/dist/component/machines.js.map +1 -0
  59. package/dist/component/records.d.ts +87 -0
  60. package/dist/component/records.d.ts.map +1 -0
  61. package/dist/component/records.js +51 -0
  62. package/dist/component/records.js.map +1 -0
  63. package/dist/component/schema.d.ts +138 -0
  64. package/dist/component/schema.d.ts.map +1 -0
  65. package/dist/component/schema.js +70 -0
  66. package/dist/component/schema.js.map +1 -0
  67. package/dist/component/sessions.d.ts +21 -0
  68. package/dist/component/sessions.d.ts.map +1 -0
  69. package/dist/component/sessions.js +59 -0
  70. package/dist/component/sessions.js.map +1 -0
  71. package/dist/component/validate.d.ts +15 -0
  72. package/dist/component/validate.d.ts.map +1 -0
  73. package/dist/component/validate.js +44 -0
  74. package/dist/component/validate.js.map +1 -0
  75. package/package.json +99 -0
  76. package/src/client/_generated/_ignore.ts +1 -0
  77. package/src/client/index.ts +199 -0
  78. package/src/component/_generated/api.ts +68 -0
  79. package/src/component/_generated/component.ts +430 -0
  80. package/src/component/_generated/dataModel.ts +60 -0
  81. package/src/component/_generated/server.ts +171 -0
  82. package/src/component/boxd.ts +188 -0
  83. package/src/component/convex.config.ts +9 -0
  84. package/src/component/errors.ts +105 -0
  85. package/src/component/exec.ts +134 -0
  86. package/src/component/executions.ts +115 -0
  87. package/src/component/files.ts +128 -0
  88. package/src/component/limits.ts +48 -0
  89. package/src/component/machines.ts +500 -0
  90. package/src/component/records.ts +71 -0
  91. package/src/component/schema.ts +77 -0
  92. package/src/component/sessions.ts +61 -0
  93. package/src/component/validate.ts +58 -0
  94. package/src/test.ts +28 -0
@@ -0,0 +1,11 @@
1
+ /* eslint-disable */
2
+ /**
3
+ * Generated data model types.
4
+ *
5
+ * THIS CODE IS AUTOMATICALLY GENERATED.
6
+ *
7
+ * To regenerate, run `npx convex dev`.
8
+ * @module
9
+ */
10
+ import schema from "../schema.js";
11
+ //# sourceMappingURL=dataModel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dataModel.js","sourceRoot":"","sources":["../../../src/component/_generated/dataModel.ts"],"names":[],"mappings":"AAAA,oBAAoB;AACpB;;;;;;;GAOG;AASH,OAAO,MAAM,MAAM,cAAc,CAAC"}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Generated utilities for implementing server-side Convex query and mutation functions.
3
+ *
4
+ * THIS CODE IS AUTOMATICALLY GENERATED.
5
+ *
6
+ * To regenerate, run `npx convex dev`.
7
+ * @module
8
+ */
9
+ import type { ActionBuilder, HttpActionBuilder, MutationBuilder, QueryBuilder, GenericActionCtx, GenericMutationCtx, GenericQueryCtx, GenericDatabaseReader, GenericDatabaseWriter } from "convex/server";
10
+ import type { DataModel } from "./dataModel.js";
11
+ /**
12
+ * Typesafe environment variables.
13
+ *
14
+ * This includes platform-provided env vars and any variables declared in
15
+ * `convex.config.ts`.
16
+ */
17
+ type Env = {
18
+ readonly CONVEX_CLOUD_URL: string;
19
+ readonly CONVEX_SITE_URL: string;
20
+ readonly BOXD_API_KEY: string;
21
+ readonly BOXD_BASE_URL: string | undefined;
22
+ };
23
+ /**
24
+ * Define a query in this Convex app's public API.
25
+ *
26
+ * This function will be allowed to read your Convex database and will be accessible from the client.
27
+ *
28
+ * @param func - The query function. It receives a {@link QueryCtx} as its first argument.
29
+ * @returns The wrapped query. Include this as an `export` to name it and make it accessible.
30
+ */
31
+ export declare const query: QueryBuilder<DataModel, "public">;
32
+ /**
33
+ * Define a query that is only accessible from other Convex functions (but not from the client).
34
+ *
35
+ * This function will be allowed to read from your Convex database. It will not be accessible from the client.
36
+ *
37
+ * @param func - The query function. It receives a {@link QueryCtx} as its first argument.
38
+ * @returns The wrapped query. Include this as an `export` to name it and make it accessible.
39
+ */
40
+ export declare const internalQuery: QueryBuilder<DataModel, "internal">;
41
+ /**
42
+ * Define a mutation in this Convex app's public API.
43
+ *
44
+ * This function will be allowed to modify your Convex database and will be accessible from the client.
45
+ *
46
+ * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument.
47
+ * @returns The wrapped mutation. Include this as an `export` to name it and make it accessible.
48
+ */
49
+ export declare const mutation: MutationBuilder<DataModel, "public">;
50
+ /**
51
+ * Define a mutation that is only accessible from other Convex functions (but not from the client).
52
+ *
53
+ * This function will be allowed to modify your Convex database. It will not be accessible from the client.
54
+ *
55
+ * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument.
56
+ * @returns The wrapped mutation. Include this as an `export` to name it and make it accessible.
57
+ */
58
+ export declare const internalMutation: MutationBuilder<DataModel, "internal">;
59
+ /**
60
+ * Define an action in this Convex app's public API.
61
+ *
62
+ * An action is a function which can execute any JavaScript code, including non-deterministic
63
+ * code and code with side-effects, like calling third-party services.
64
+ * They can be run in Convex's JavaScript environment or in Node.js using the "use node" directive.
65
+ * They can interact with the database indirectly by calling queries and mutations using the {@link ActionCtx}.
66
+ *
67
+ * @param func - The action. It receives an {@link ActionCtx} as its first argument.
68
+ * @returns The wrapped action. Include this as an `export` to name it and make it accessible.
69
+ */
70
+ export declare const action: ActionBuilder<DataModel, "public">;
71
+ /**
72
+ * Define an action that is only accessible from other Convex functions (but not from the client).
73
+ *
74
+ * @param func - The function. It receives an {@link ActionCtx} as its first argument.
75
+ * @returns The wrapped function. Include this as an `export` to name it and make it accessible.
76
+ */
77
+ export declare const internalAction: ActionBuilder<DataModel, "internal">;
78
+ /**
79
+ * Define an HTTP action.
80
+ *
81
+ * The wrapped function will be used to respond to HTTP requests received
82
+ * by a Convex deployment if the requests matches the path and method where
83
+ * this action is routed. Be sure to route your httpAction in `convex/http.js`.
84
+ *
85
+ * @param func - The function. It receives an {@link ActionCtx} as its first argument
86
+ * and a Fetch API `Request` object as its second.
87
+ * @returns The wrapped function. Import this function from `convex/http.js` and route it to hook it up.
88
+ */
89
+ export declare const httpAction: HttpActionBuilder;
90
+ export declare const env: Env;
91
+ /**
92
+ * A set of services for use within Convex query functions.
93
+ *
94
+ * The query context is passed as the first argument to any Convex query
95
+ * function run on the server.
96
+ *
97
+ * If you're using code generation, use the `QueryCtx` type in `convex/_generated/server.d.ts` instead.
98
+ */
99
+ export type QueryCtx = GenericQueryCtx<DataModel>;
100
+ /**
101
+ * A set of services for use within Convex mutation functions.
102
+ *
103
+ * The mutation context is passed as the first argument to any Convex mutation
104
+ * function run on the server.
105
+ *
106
+ * If you're using code generation, use the `MutationCtx` type in `convex/_generated/server.d.ts` instead.
107
+ */
108
+ export type MutationCtx = GenericMutationCtx<DataModel>;
109
+ /**
110
+ * A set of services for use within Convex action functions.
111
+ *
112
+ * The action context is passed as the first argument to any Convex action
113
+ * function run on the server.
114
+ */
115
+ export type ActionCtx = GenericActionCtx<DataModel>;
116
+ /**
117
+ * An interface to read from the database within Convex query functions.
118
+ *
119
+ * The two entry points are {@link DatabaseReader.get}, which fetches a single
120
+ * document by its {@link Id}, or {@link DatabaseReader.query}, which starts
121
+ * building a query.
122
+ */
123
+ export type DatabaseReader = GenericDatabaseReader<DataModel>;
124
+ /**
125
+ * An interface to read from and write to the database within Convex mutation
126
+ * functions.
127
+ *
128
+ * Convex guarantees that all writes within a single mutation are
129
+ * executed atomically, so you never have to worry about partial writes leaving
130
+ * your data in an inconsistent state. See [the Convex Guide](https://docs.convex.dev/understanding/convex-fundamentals/functions#atomicity-and-optimistic-concurrency-control)
131
+ * for the guarantees Convex provides your functions.
132
+ */
133
+ export type DatabaseWriter = GenericDatabaseWriter<DataModel>;
134
+ export {};
135
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/component/_generated/server.ts"],"names":[],"mappings":"AACA;;;;;;;GAOG;AAEH,OAAO,KAAK,EACV,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,qBAAqB,EACrB,qBAAqB,EACtB,MAAM,eAAe,CAAC;AAUvB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD;;;;;GAKG;AACH,KAAK,GAAG,GAAG;IACT,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5C,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,KAAK,EAAE,YAAY,CAAC,SAAS,EAAE,QAAQ,CAAgB,CAAC;AAErE;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,EAAE,YAAY,CAAC,SAAS,EAAE,UAAU,CACxC,CAAC;AAEvB;;;;;;;GAOG;AACH,eAAO,MAAM,QAAQ,EAAE,eAAe,CAAC,SAAS,EAAE,QAAQ,CAAmB,CAAC;AAE9E;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,EAAE,eAAe,CAAC,SAAS,EAAE,UAAU,CAC3C,CAAC;AAE1B;;;;;;;;;;GAUG;AACH,eAAO,MAAM,MAAM,EAAE,aAAa,CAAC,SAAS,EAAE,QAAQ,CAAiB,CAAC;AAExE;;;;;GAKG;AACH,eAAO,MAAM,cAAc,EAAE,aAAa,CAAC,SAAS,EAAE,UAAU,CACzC,CAAC;AAExB;;;;;;;;;;GAUG;AACH,eAAO,MAAM,UAAU,EAAE,iBAAqC,CAAC;AAC/D,eAAO,MAAM,GAAG,EAAE,GACJ,CAAC;AAEf;;;;;;;GAOG;AACH,MAAM,MAAM,QAAQ,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;AAElD;;;;;;;GAOG;AACH,MAAM,MAAM,WAAW,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;AAExD;;;;;GAKG;AACH,MAAM,MAAM,SAAS,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;AAEpD;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG,qBAAqB,CAAC,SAAS,CAAC,CAAC;AAE9D;;;;;;;;GAQG;AACH,MAAM,MAAM,cAAc,GAAG,qBAAqB,CAAC,SAAS,CAAC,CAAC"}
@@ -0,0 +1,80 @@
1
+ /* eslint-disable */
2
+ /**
3
+ * Generated utilities for implementing server-side Convex query and mutation functions.
4
+ *
5
+ * THIS CODE IS AUTOMATICALLY GENERATED.
6
+ *
7
+ * To regenerate, run `npx convex dev`.
8
+ * @module
9
+ */
10
+ import { actionGeneric, httpActionGeneric, queryGeneric, mutationGeneric, internalActionGeneric, internalMutationGeneric, internalQueryGeneric, } from "convex/server";
11
+ /**
12
+ * Define a query in this Convex app's public API.
13
+ *
14
+ * This function will be allowed to read your Convex database and will be accessible from the client.
15
+ *
16
+ * @param func - The query function. It receives a {@link QueryCtx} as its first argument.
17
+ * @returns The wrapped query. Include this as an `export` to name it and make it accessible.
18
+ */
19
+ export const query = queryGeneric;
20
+ /**
21
+ * Define a query that is only accessible from other Convex functions (but not from the client).
22
+ *
23
+ * This function will be allowed to read from your Convex database. It will not be accessible from the client.
24
+ *
25
+ * @param func - The query function. It receives a {@link QueryCtx} as its first argument.
26
+ * @returns The wrapped query. Include this as an `export` to name it and make it accessible.
27
+ */
28
+ export const internalQuery = internalQueryGeneric;
29
+ /**
30
+ * Define a mutation in this Convex app's public API.
31
+ *
32
+ * This function will be allowed to modify your Convex database and will be accessible from the client.
33
+ *
34
+ * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument.
35
+ * @returns The wrapped mutation. Include this as an `export` to name it and make it accessible.
36
+ */
37
+ export const mutation = mutationGeneric;
38
+ /**
39
+ * Define a mutation that is only accessible from other Convex functions (but not from the client).
40
+ *
41
+ * This function will be allowed to modify your Convex database. It will not be accessible from the client.
42
+ *
43
+ * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument.
44
+ * @returns The wrapped mutation. Include this as an `export` to name it and make it accessible.
45
+ */
46
+ export const internalMutation = internalMutationGeneric;
47
+ /**
48
+ * Define an action in this Convex app's public API.
49
+ *
50
+ * An action is a function which can execute any JavaScript code, including non-deterministic
51
+ * code and code with side-effects, like calling third-party services.
52
+ * They can be run in Convex's JavaScript environment or in Node.js using the "use node" directive.
53
+ * They can interact with the database indirectly by calling queries and mutations using the {@link ActionCtx}.
54
+ *
55
+ * @param func - The action. It receives an {@link ActionCtx} as its first argument.
56
+ * @returns The wrapped action. Include this as an `export` to name it and make it accessible.
57
+ */
58
+ export const action = actionGeneric;
59
+ /**
60
+ * Define an action that is only accessible from other Convex functions (but not from the client).
61
+ *
62
+ * @param func - The function. It receives an {@link ActionCtx} as its first argument.
63
+ * @returns The wrapped function. Include this as an `export` to name it and make it accessible.
64
+ */
65
+ export const internalAction = internalActionGeneric;
66
+ /**
67
+ * Define an HTTP action.
68
+ *
69
+ * The wrapped function will be used to respond to HTTP requests received
70
+ * by a Convex deployment if the requests matches the path and method where
71
+ * this action is routed. Be sure to route your httpAction in `convex/http.js`.
72
+ *
73
+ * @param func - The function. It receives an {@link ActionCtx} as its first argument
74
+ * and a Fetch API `Request` object as its second.
75
+ * @returns The wrapped function. Import this function from `convex/http.js` and route it to hook it up.
76
+ */
77
+ export const httpAction = httpActionGeneric;
78
+ export const env = globalThis
79
+ .process.env;
80
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/component/_generated/server.ts"],"names":[],"mappings":"AAAA,oBAAoB;AACpB;;;;;;;GAOG;AAaH,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,eAAe,EACf,qBAAqB,EACrB,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,eAAe,CAAC;AAgBvB;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,KAAK,GAAsC,YAAY,CAAC;AAErE;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,aAAa,GACxB,oBAAoB,CAAC;AAEvB;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAyC,eAAe,CAAC;AAE9E;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAC3B,uBAAuB,CAAC;AAE1B;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,MAAM,GAAuC,aAAa,CAAC;AAExE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GACzB,qBAAqB,CAAC;AAExB;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,UAAU,GAAsB,iBAAiB,CAAC;AAC/D,MAAM,CAAC,MAAM,GAAG,GAAS,UAAmD;KACzE,OAAO,CAAC,GAAG,CAAC"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Connects component actions to boxd.
3
+ *
4
+ * The component runs in Convex's default JavaScript runtime, so it uses the
5
+ * SDK's `@boxd-sh/sdk/web` entry: grpc-web over `fetch`, no Node built-ins.
6
+ *
7
+ * The API key comes from the component's own env (`BOXD_API_KEY`, bound by
8
+ * the app in `app.use`), so it never travels as a function argument. The SDK
9
+ * could exchange the key for a session token itself, but it would do so once
10
+ * per action: an SDK client lives only as long as the action. boxd
11
+ * rate-limits the exchange per source IP, and Convex deployments share their
12
+ * egress IPs. So the component exchanges the key once, caches the token in
13
+ * its `sessions` table, and hands the SDK the token.
14
+ */
15
+ import { Boxd } from "@boxd-sh/sdk/web";
16
+ import { type ActionCtx } from "./_generated/server.js";
17
+ /** boxd production. `BOXD_BASE_URL` points the component anywhere else. */
18
+ export declare const DEFAULT_BASE_URL = "https://boxd.sh:9443";
19
+ /**
20
+ * The console origin that serves the key exchange: `https://app.<zone>` for a
21
+ * cluster zone, or the endpoint's own origin for a local, IP or `app.` host.
22
+ * Mirrors `consoleBaseUrl` in `@boxd-sh/sdk`, which the SDK doesn't export.
23
+ */
24
+ export declare function exchangeUrl(baseURL: string): string;
25
+ /**
26
+ * Run `operation` with an authenticated SDK client, and turn whatever it
27
+ * throws into a coded `ConvexError`.
28
+ *
29
+ * A cached token can be revoked before it expires. If boxd rejects a cached
30
+ * token, the token is dropped, the key is exchanged again, and `operation`
31
+ * runs once more. That retry is safe for every operation, including create:
32
+ * boxd refuses an unauthenticated request before it does anything.
33
+ */
34
+ export declare function withBoxd<T>(ctx: ActionCtx, operation: (boxd: Boxd) => Promise<T>): Promise<T>;
35
+ //# sourceMappingURL=boxd.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boxd.d.ts","sourceRoot":"","sources":["../../src/component/boxd.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAExC,OAAO,EAAO,KAAK,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAG7D,2EAA2E;AAC3E,eAAO,MAAM,gBAAgB,yBAAyB,CAAC;AASvD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAgBnD;AAsGD;;;;;;;;GAQG;AACH,wBAAsB,QAAQ,CAAC,CAAC,EAC9B,GAAG,EAAE,SAAS,EACd,SAAS,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,GACpC,OAAO,CAAC,CAAC,CAAC,CAsBZ"}
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Connects component actions to boxd.
3
+ *
4
+ * The component runs in Convex's default JavaScript runtime, so it uses the
5
+ * SDK's `@boxd-sh/sdk/web` entry: grpc-web over `fetch`, no Node built-ins.
6
+ *
7
+ * The API key comes from the component's own env (`BOXD_API_KEY`, bound by
8
+ * the app in `app.use`), so it never travels as a function argument. The SDK
9
+ * could exchange the key for a session token itself, but it would do so once
10
+ * per action: an SDK client lives only as long as the action. boxd
11
+ * rate-limits the exchange per source IP, and Convex deployments share their
12
+ * egress IPs. So the component exchanges the key once, caches the token in
13
+ * its `sessions` table, and hands the SDK the token.
14
+ */
15
+ import { Boxd } from "@boxd-sh/sdk/web";
16
+ import { internal } from "./_generated/api.js";
17
+ import { env } from "./_generated/server.js";
18
+ import { boxdError, toConvexError } from "./errors.js";
19
+ /** boxd production. `BOXD_BASE_URL` points the component anywhere else. */
20
+ export const DEFAULT_BASE_URL = "https://boxd.sh:9443";
21
+ const EXCHANGE_PATH = "/api/v1/auth/token";
22
+ /** Exchange again this long before the cached token expires. */
23
+ const REFRESH_SKEW_MS = 5 * 60_000;
24
+ /**
25
+ * The console origin that serves the key exchange: `https://app.<zone>` for a
26
+ * cluster zone, or the endpoint's own origin for a local, IP or `app.` host.
27
+ * Mirrors `consoleBaseUrl` in `@boxd-sh/sdk`, which the SDK doesn't export.
28
+ */
29
+ export function exchangeUrl(baseURL) {
30
+ const trimmed = baseURL.trim().replace(/\/+$/, "");
31
+ const scheme = /^https?:\/\//.exec(trimmed)?.[0];
32
+ const local = /^(localhost|127\.)/.test(trimmed.slice(scheme?.length ?? 0));
33
+ // No scheme: pick the one the SDK would dial, plain HTTP for a local host.
34
+ const url = new URL(scheme ? trimmed : `${local ? "http" : "https"}://${trimmed}`);
35
+ const host = url.hostname;
36
+ const sameOrigin = host === "localhost" ||
37
+ host.startsWith("[") ||
38
+ /^\d{1,3}(\.\d{1,3}){3}$/.test(host) ||
39
+ host.startsWith("app.");
40
+ const origin = sameOrigin ? url.origin : `https://app.${host}`;
41
+ return `${origin}${EXCHANGE_PATH}`;
42
+ }
43
+ async function sha256Hex(text) {
44
+ const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(text));
45
+ return Array.from(new Uint8Array(digest), (b) => b.toString(16).padStart(2, "0")).join("");
46
+ }
47
+ async function exchange(apiKey, baseURL) {
48
+ const url = exchangeUrl(baseURL);
49
+ let response;
50
+ try {
51
+ response = await fetch(url, {
52
+ method: "POST",
53
+ headers: { "content-type": "application/json" },
54
+ body: JSON.stringify({ api_key: apiKey }),
55
+ });
56
+ }
57
+ catch (error) {
58
+ throw boxdError("UNAVAILABLE", `could not reach ${url} to exchange BOXD_API_KEY: ${String(error)}`);
59
+ }
60
+ if (response.status === 401) {
61
+ throw boxdError("UNAUTHENTICATED", "boxd rejected BOXD_API_KEY: it is invalid, expired or revoked. " +
62
+ "Create a new key with `boxd auth keys create <name>` and set it with " +
63
+ "`npx convex env set BOXD_API_KEY <key>`.");
64
+ }
65
+ if (response.status === 429) {
66
+ throw boxdError("RATE_LIMITED", "boxd rate-limited the API key exchange. Retry after a minute.");
67
+ }
68
+ if (!response.ok) {
69
+ const detail = await response.text().catch(() => "");
70
+ throw boxdError(response.status >= 500 ? "UNAVAILABLE" : "BOXD_ERROR", `boxd API key exchange failed with ${response.status}: ${detail.slice(0, 500)}`);
71
+ }
72
+ const body = (await response.json());
73
+ if (typeof body.token !== "string" || typeof body.expires_at !== "number") {
74
+ throw boxdError("BOXD_ERROR", "boxd API key exchange returned a malformed response");
75
+ }
76
+ return { token: body.token, expiresAt: body.expires_at * 1000 };
77
+ }
78
+ function config() {
79
+ // Read inside the handler: component env only exists at runtime.
80
+ const apiKey = env.BOXD_API_KEY?.trim();
81
+ if (!apiKey) {
82
+ throw boxdError("UNAUTHENTICATED", "BOXD_API_KEY is empty. Set it with `npx convex env set BOXD_API_KEY <key>` " +
83
+ "and bind it in convex.config.ts: " +
84
+ "`app.use(boxd, { env: { BOXD_API_KEY: app.env.BOXD_API_KEY } })`.");
85
+ }
86
+ const baseURL = env.BOXD_BASE_URL?.trim() || DEFAULT_BASE_URL;
87
+ return { apiKey, baseURL };
88
+ }
89
+ async function session(ctx, keyHash, apiKey, baseURL) {
90
+ const cached = await ctx.runQuery(internal.sessions.get, { keyHash });
91
+ if (cached && cached.expiresAt - REFRESH_SKEW_MS > Date.now()) {
92
+ return { session: cached, cached: true };
93
+ }
94
+ let fresh;
95
+ try {
96
+ fresh = await exchange(apiKey, baseURL);
97
+ }
98
+ catch (error) {
99
+ // Many actions can reach the refresh margin at once, and boxd
100
+ // rate-limits the exchange. A token that has not expired yet still
101
+ // works, so fall back to it rather than fail the call.
102
+ if (cached && cached.expiresAt > Date.now()) {
103
+ return { session: cached, cached: true };
104
+ }
105
+ throw error;
106
+ }
107
+ await ctx.runMutation(internal.sessions.put, { keyHash, ...fresh });
108
+ return { session: fresh, cached: false };
109
+ }
110
+ /**
111
+ * Run `operation` with an authenticated SDK client, and turn whatever it
112
+ * throws into a coded `ConvexError`.
113
+ *
114
+ * A cached token can be revoked before it expires. If boxd rejects a cached
115
+ * token, the token is dropped, the key is exchanged again, and `operation`
116
+ * runs once more. That retry is safe for every operation, including create:
117
+ * boxd refuses an unauthenticated request before it does anything.
118
+ */
119
+ export async function withBoxd(ctx, operation) {
120
+ const { apiKey, baseURL } = config();
121
+ const keyHash = await sha256Hex(`${baseURL}\n${apiKey}`);
122
+ const first = await session(ctx, keyHash, apiKey, baseURL);
123
+ try {
124
+ return await operation(new Boxd({ token: first.session.token, baseURL }));
125
+ }
126
+ catch (error) {
127
+ const converted = toConvexError(error);
128
+ if (!first.cached || converted.data.code !== "UNAUTHENTICATED") {
129
+ throw converted;
130
+ }
131
+ await ctx.runMutation(internal.sessions.drop, {
132
+ keyHash,
133
+ token: first.session.token,
134
+ });
135
+ }
136
+ const retry = await session(ctx, keyHash, apiKey, baseURL);
137
+ try {
138
+ return await operation(new Boxd({ token: retry.session.token, baseURL }));
139
+ }
140
+ catch (error) {
141
+ throw toConvexError(error);
142
+ }
143
+ }
144
+ //# sourceMappingURL=boxd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boxd.js","sourceRoot":"","sources":["../../src/component/boxd.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ declare const _default: import("convex/server").ComponentDefinition<any, {
2
+ readonly BOXD_API_KEY: import("convex/values").VString<string, "required">;
3
+ readonly BOXD_BASE_URL: import("convex/values").VString<string | undefined, "optional">;
4
+ }>;
5
+ export default _default;
6
+ //# sourceMappingURL=convex.config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"convex.config.d.ts","sourceRoot":"","sources":["../../src/component/convex.config.ts"],"names":[],"mappings":";;;;AAGA,wBAKG"}
@@ -0,0 +1,9 @@
1
+ import { defineComponent } from "convex/server";
2
+ import { v } from "convex/values";
3
+ export default defineComponent("boxd", {
4
+ env: {
5
+ BOXD_API_KEY: v.string(),
6
+ BOXD_BASE_URL: v.optional(v.string()),
7
+ },
8
+ });
9
+ //# sourceMappingURL=convex.config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"convex.config.js","sourceRoot":"","sources":["../../src/component/convex.config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,CAAC,EAAE,MAAM,eAAe,CAAC;AAElC,eAAe,eAAe,CAAC,MAAM,EAAE;IACrC,GAAG,EAAE;QACH,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;QACxB,aAAa,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;KACtC;CACF,CAAC,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { ConvexError, type Infer } from "convex/values";
2
+ export declare const errorCode: import("convex/values").VUnion<"INVALID_ARGUMENT" | "UNAUTHENTICATED" | "PERMISSION_DENIED" | "NOT_FOUND" | "CONFLICT" | "RATE_LIMITED" | "TIMEOUT" | "UNAVAILABLE" | "BOXD_ERROR", [import("convex/values").VLiteral<"INVALID_ARGUMENT", "required">, import("convex/values").VLiteral<"UNAUTHENTICATED", "required">, import("convex/values").VLiteral<"PERMISSION_DENIED", "required">, import("convex/values").VLiteral<"NOT_FOUND", "required">, import("convex/values").VLiteral<"CONFLICT", "required">, import("convex/values").VLiteral<"RATE_LIMITED", "required">, import("convex/values").VLiteral<"TIMEOUT", "required">, import("convex/values").VLiteral<"UNAVAILABLE", "required">, import("convex/values").VLiteral<"BOXD_ERROR", "required">], "required", never>;
3
+ /** The `data` of every `ConvexError` this component throws. */
4
+ export type BoxdErrorData = {
5
+ code: Infer<typeof errorCode>;
6
+ message: string;
7
+ /**
8
+ * Set when `create` or `fork` made a machine but it failed to become ready:
9
+ * the machine exists, and bills, until you destroy it.
10
+ */
11
+ machineId?: string;
12
+ };
13
+ export declare function boxdError(code: BoxdErrorData["code"], message: string): ConvexError<BoxdErrorData>;
14
+ export declare function invalidArgument(message: string): ConvexError<BoxdErrorData>;
15
+ /** A human-readable message for any thrown value, bounded for storage. */
16
+ export declare function errorMessage(error: unknown): string;
17
+ /**
18
+ * Map anything thrown while talking to boxd onto a `ConvexError` with a
19
+ * stable `code`, so the app can branch on `error.data.code` instead of
20
+ * parsing messages. A `ConvexError` passes through unchanged.
21
+ */
22
+ export declare function toConvexError(error: unknown): ConvexError<BoxdErrorData>;
23
+ /** True when `error` says the target no longer exists on boxd. */
24
+ export declare function isNotFound(error: unknown): boolean;
25
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/component/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAK,KAAK,KAAK,EAAE,MAAM,eAAe,CAAC;AAG3D,eAAO,MAAM,SAAS,qvBAUrB,CAAC;AAEF,+DAA+D;AAC/D,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,KAAK,CAAC,OAAO,SAAS,CAAC,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAgCF,wBAAgB,SAAS,CACvB,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,EAC3B,OAAO,EAAE,MAAM,GACd,WAAW,CAAC,aAAa,CAAC,CAE5B;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,CAAC,aAAa,CAAC,CAE3E;AAED,0EAA0E;AAC1E,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAYnD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,CAAC,aAAa,CAAC,CAYxE;AAED,kEAAkE;AAClE,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAElD"}
@@ -0,0 +1,75 @@
1
+ import { ConvexError, v } from "convex/values";
2
+ import { MAX_STORED_ERROR, truncate } from "./limits.js";
3
+ export const errorCode = v.union(v.literal("INVALID_ARGUMENT"), v.literal("UNAUTHENTICATED"), v.literal("PERMISSION_DENIED"), v.literal("NOT_FOUND"), v.literal("CONFLICT"), v.literal("RATE_LIMITED"), v.literal("TIMEOUT"), v.literal("UNAVAILABLE"), v.literal("BOXD_ERROR"));
4
+ // gRPC status codes, as carried on `BoxdError.grpcCode`.
5
+ const GRPC_CODES = {
6
+ 3: "INVALID_ARGUMENT",
7
+ 4: "TIMEOUT",
8
+ 5: "NOT_FOUND",
9
+ 6: "CONFLICT",
10
+ 7: "PERMISSION_DENIED",
11
+ 8: "RATE_LIMITED",
12
+ 9: "CONFLICT",
13
+ 14: "UNAVAILABLE",
14
+ 16: "UNAUTHENTICATED",
15
+ };
16
+ // The SDK's own error classes, for errors raised before anything reached the
17
+ // wire (a missing credential, a failed key exchange, a dropped connection).
18
+ // Matched by name and `grpcCode` rather than `instanceof`, so the modules
19
+ // that only store and read rows never load the SDK.
20
+ const SDK_CLASSES = {
21
+ AuthenticationError: "UNAUTHENTICATED",
22
+ PermissionDeniedError: "PERMISSION_DENIED",
23
+ NotFoundError: "NOT_FOUND",
24
+ ConflictError: "CONFLICT",
25
+ RateLimitError: "RATE_LIMITED",
26
+ APIConnectionError: "UNAVAILABLE",
27
+ };
28
+ // The SDK's client-side deadlines: "exec timed out after 5000ms", and
29
+ // "machine x did not reach 'running' within 90000ms".
30
+ const TIMEOUT_MESSAGE = /timed out|within \d+ms/i;
31
+ export function boxdError(code, message) {
32
+ return new ConvexError({ code, message });
33
+ }
34
+ export function invalidArgument(message) {
35
+ return boxdError("INVALID_ARGUMENT", message);
36
+ }
37
+ /** A human-readable message for any thrown value, bounded for storage. */
38
+ export function errorMessage(error) {
39
+ let message;
40
+ if (error instanceof ConvexError) {
41
+ const data = error.data;
42
+ message =
43
+ typeof data === "string" ? data : (data.message ?? String(error.data));
44
+ }
45
+ else if (error instanceof Error) {
46
+ message = error.message;
47
+ }
48
+ else {
49
+ message = String(error);
50
+ }
51
+ return truncate(message, MAX_STORED_ERROR);
52
+ }
53
+ /**
54
+ * Map anything thrown while talking to boxd onto a `ConvexError` with a
55
+ * stable `code`, so the app can branch on `error.data.code` instead of
56
+ * parsing messages. A `ConvexError` passes through unchanged.
57
+ */
58
+ export function toConvexError(error) {
59
+ if (error instanceof ConvexError)
60
+ return error;
61
+ const message = errorMessage(error);
62
+ if (error instanceof Error) {
63
+ const { grpcCode } = error;
64
+ const code = (typeof grpcCode === "number" ? GRPC_CODES[grpcCode] : undefined) ??
65
+ SDK_CLASSES[error.name] ??
66
+ (TIMEOUT_MESSAGE.test(message) ? "TIMEOUT" : "BOXD_ERROR");
67
+ return boxdError(code, message);
68
+ }
69
+ return boxdError("BOXD_ERROR", message);
70
+ }
71
+ /** True when `error` says the target no longer exists on boxd. */
72
+ export function isNotFound(error) {
73
+ return toConvexError(error).data.code === "NOT_FOUND";
74
+ }
75
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/component/errors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Run a command in a machine. Each run is recorded in `executions`
3
+ * (running → completed or failed), so the app can render live status and
4
+ * history from a reactive query.
5
+ *
6
+ * The call returns when the command exits. For work that can outlast the 10
7
+ * minute action ceiling, start it in the background inside the machine
8
+ * (`nohup ... &`) and poll it with later runs.
9
+ */
10
+ import type { Id } from "./_generated/dataModel.js";
11
+ export declare const run: import("convex/server").RegisteredAction<"public", {
12
+ cwd?: string | undefined;
13
+ env?: Record<string, string> | undefined;
14
+ ownerId?: string | undefined;
15
+ timeoutMs?: number | undefined;
16
+ command: string | string[];
17
+ machineId: string;
18
+ }, Promise<{
19
+ executionId: Id<"executions">;
20
+ exitCode: number;
21
+ success: boolean;
22
+ stdout: string;
23
+ stderr: string;
24
+ }>>;
25
+ //# sourceMappingURL=exec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exec.d.ts","sourceRoot":"","sources":["../../src/component/exec.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,2BAA2B,CAAC;AA+BpD,eAAO,MAAM,GAAG;;;;;;;;iBAwBC,EAAE,CAAC,YAAY,CAAC;cACnB,MAAM;aACP,OAAO;YACR,MAAM;YACN,MAAM;GA8DhB,CAAC"}