@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,138 @@
1
+ /**
2
+ * A reactive mirror of one boxd machine this component created or forked.
3
+ *
4
+ * boxd stays the source of truth: every lifecycle action writes back the
5
+ * status it observed, and `machines.refresh` re-reads it on demand. The row
6
+ * outlives the machine (status `"destroyed"`) so its execution history stays
7
+ * readable.
8
+ */
9
+ export declare const machineFields: {
10
+ /** boxd machine id. External, not a Convex document id. */
11
+ machineId: import("convex/values").VString<string, "required">;
12
+ name: import("convex/values").VString<string, "required">;
13
+ /**
14
+ * Opaque tenant key from the host app. Components can't read `ctx.auth`, so
15
+ * the app derives this from its own auth and every call must present the
16
+ * same value to touch the machine.
17
+ */
18
+ ownerId: import("convex/values").VString<string | undefined, "optional">;
19
+ /** Last observed boxd status: `running`, `suspended`, `hibernated`, ... */
20
+ status: import("convex/values").VString<string, "required">;
21
+ image: import("convex/values").VString<string | undefined, "optional">;
22
+ /** `https://<name>.<zone>`, the machine's default HTTPS route. */
23
+ url: import("convex/values").VString<string | undefined, "optional">;
24
+ vcpu: import("convex/values").VFloat64<number | undefined, "optional">;
25
+ memoryBytes: import("convex/values").VFloat64<number | undefined, "optional">;
26
+ /** Set when this machine is a fork of another machine. */
27
+ forkedFrom: import("convex/values").VString<string | undefined, "optional">;
28
+ /** The last failed operation's message. Cleared by the next success. */
29
+ lastError: import("convex/values").VString<string | undefined, "optional">;
30
+ updatedAt: import("convex/values").VFloat64<number, "required">;
31
+ };
32
+ export declare const executionStatus: import("convex/values").VUnion<"running" | "completed" | "failed", [import("convex/values").VLiteral<"running", "required">, import("convex/values").VLiteral<"completed", "required">, import("convex/values").VLiteral<"failed", "required">], "required", never>;
33
+ /** One row per `exec`, so the app can render live status and history. */
34
+ export declare const executionFields: {
35
+ machineId: import("convex/values").VString<string, "required">;
36
+ ownerId: import("convex/values").VString<string | undefined, "optional">;
37
+ /** The command line that ran, truncated for storage. */
38
+ command: import("convex/values").VString<string, "required">;
39
+ cwd: import("convex/values").VString<string | undefined, "optional">;
40
+ status: import("convex/values").VUnion<"running" | "completed" | "failed", [import("convex/values").VLiteral<"running", "required">, import("convex/values").VLiteral<"completed", "required">, import("convex/values").VLiteral<"failed", "required">], "required", never>;
41
+ exitCode: import("convex/values").VFloat64<number | undefined, "optional">;
42
+ /** Truncated for storage; the action's return value carries more. */
43
+ stdout: import("convex/values").VString<string | undefined, "optional">;
44
+ stderr: import("convex/values").VString<string | undefined, "optional">;
45
+ error: import("convex/values").VString<string | undefined, "optional">;
46
+ startedAt: import("convex/values").VFloat64<number, "required">;
47
+ finishedAt: import("convex/values").VFloat64<number | undefined, "optional">;
48
+ };
49
+ declare const _default: import("convex/server").SchemaDefinition<{
50
+ machines: import("convex/server").TableDefinition<import("convex/values").VObject<{
51
+ ownerId?: string | undefined;
52
+ image?: string | undefined;
53
+ vcpu?: number | undefined;
54
+ url?: string | undefined;
55
+ memoryBytes?: number | undefined;
56
+ forkedFrom?: string | undefined;
57
+ lastError?: string | undefined;
58
+ machineId: string;
59
+ name: string;
60
+ status: string;
61
+ updatedAt: number;
62
+ }, {
63
+ /** boxd machine id. External, not a Convex document id. */
64
+ machineId: import("convex/values").VString<string, "required">;
65
+ name: import("convex/values").VString<string, "required">;
66
+ /**
67
+ * Opaque tenant key from the host app. Components can't read `ctx.auth`, so
68
+ * the app derives this from its own auth and every call must present the
69
+ * same value to touch the machine.
70
+ */
71
+ ownerId: import("convex/values").VString<string | undefined, "optional">;
72
+ /** Last observed boxd status: `running`, `suspended`, `hibernated`, ... */
73
+ status: import("convex/values").VString<string, "required">;
74
+ image: import("convex/values").VString<string | undefined, "optional">;
75
+ /** `https://<name>.<zone>`, the machine's default HTTPS route. */
76
+ url: import("convex/values").VString<string | undefined, "optional">;
77
+ vcpu: import("convex/values").VFloat64<number | undefined, "optional">;
78
+ memoryBytes: import("convex/values").VFloat64<number | undefined, "optional">;
79
+ /** Set when this machine is a fork of another machine. */
80
+ forkedFrom: import("convex/values").VString<string | undefined, "optional">;
81
+ /** The last failed operation's message. Cleared by the next success. */
82
+ lastError: import("convex/values").VString<string | undefined, "optional">;
83
+ updatedAt: import("convex/values").VFloat64<number, "required">;
84
+ }, "required", "machineId" | "ownerId" | "image" | "name" | "vcpu" | "status" | "url" | "memoryBytes" | "forkedFrom" | "lastError" | "updatedAt">, {
85
+ by_machine_id: ["machineId", "_creationTime"];
86
+ by_owner: ["ownerId", "_creationTime"];
87
+ }, {}, {}>;
88
+ executions: import("convex/server").TableDefinition<import("convex/values").VObject<{
89
+ cwd?: string | undefined;
90
+ ownerId?: string | undefined;
91
+ exitCode?: number | undefined;
92
+ stdout?: string | undefined;
93
+ stderr?: string | undefined;
94
+ error?: string | undefined;
95
+ finishedAt?: number | undefined;
96
+ command: string;
97
+ machineId: string;
98
+ status: "running" | "completed" | "failed";
99
+ startedAt: number;
100
+ }, {
101
+ machineId: import("convex/values").VString<string, "required">;
102
+ ownerId: import("convex/values").VString<string | undefined, "optional">;
103
+ /** The command line that ran, truncated for storage. */
104
+ command: import("convex/values").VString<string, "required">;
105
+ cwd: import("convex/values").VString<string | undefined, "optional">;
106
+ status: import("convex/values").VUnion<"running" | "completed" | "failed", [import("convex/values").VLiteral<"running", "required">, import("convex/values").VLiteral<"completed", "required">, import("convex/values").VLiteral<"failed", "required">], "required", never>;
107
+ exitCode: import("convex/values").VFloat64<number | undefined, "optional">;
108
+ /** Truncated for storage; the action's return value carries more. */
109
+ stdout: import("convex/values").VString<string | undefined, "optional">;
110
+ stderr: import("convex/values").VString<string | undefined, "optional">;
111
+ error: import("convex/values").VString<string | undefined, "optional">;
112
+ startedAt: import("convex/values").VFloat64<number, "required">;
113
+ finishedAt: import("convex/values").VFloat64<number | undefined, "optional">;
114
+ }, "required", "command" | "cwd" | "machineId" | "ownerId" | "status" | "exitCode" | "stdout" | "stderr" | "error" | "startedAt" | "finishedAt">, {
115
+ by_machine: ["machineId", "_creationTime"];
116
+ }, {}, {}>;
117
+ /**
118
+ * Cached session tokens, keyed by a SHA-256 of the API key and endpoint.
119
+ * boxd rate-limits the key-for-token exchange per source IP, and every
120
+ * Convex deployment in a region shares a few egress IPs, so each action
121
+ * must reuse the token rather than exchange the key again. Internal only:
122
+ * nothing in the component's public API returns these rows.
123
+ */
124
+ sessions: import("convex/server").TableDefinition<import("convex/values").VObject<{
125
+ keyHash: string;
126
+ token: string;
127
+ expiresAt: number;
128
+ }, {
129
+ keyHash: import("convex/values").VString<string, "required">;
130
+ token: import("convex/values").VString<string, "required">;
131
+ /** Epoch milliseconds. */
132
+ expiresAt: import("convex/values").VFloat64<number, "required">;
133
+ }, "required", "keyHash" | "token" | "expiresAt">, {
134
+ by_key_hash: ["keyHash", "_creationTime"];
135
+ }, {}, {}>;
136
+ }, true>;
137
+ export default _default;
138
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/component/schema.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa;IACxB,2DAA2D;;;IAG3D;;;;OAIG;;IAEH,2EAA2E;;;IAG3E,kEAAkE;;;;IAIlE,0DAA0D;;IAE1D,wEAAwE;;;CAGzE,CAAC;AAEF,eAAO,MAAM,eAAe,qQAI3B,CAAC;AAEF,yEAAyE;AACzE,eAAO,MAAM,eAAe;;;IAG1B,wDAAwD;;;;;IAKxD,qEAAqE;;;;;;CAMtE,CAAC;;;;;;;;;;;;;;;QA5CA,2DAA2D;;;QAG3D;;;;WAIG;;QAEH,2EAA2E;;;QAG3E,kEAAkE;;;;QAIlE,0DAA0D;;QAE1D,wEAAwE;;;;;;;;;;;;;;;;;;;;;;QAexE,wDAAwD;;;;;QAKxD,qEAAqE;;;;;;;;;IAarE;;;;;;OAMG;;;;;;;;QAID,0BAA0B;;;;;;AAf9B,wBAkBG"}
@@ -0,0 +1,70 @@
1
+ import { defineSchema, defineTable } from "convex/server";
2
+ import { v } from "convex/values";
3
+ /**
4
+ * A reactive mirror of one boxd machine this component created or forked.
5
+ *
6
+ * boxd stays the source of truth: every lifecycle action writes back the
7
+ * status it observed, and `machines.refresh` re-reads it on demand. The row
8
+ * outlives the machine (status `"destroyed"`) so its execution history stays
9
+ * readable.
10
+ */
11
+ export const machineFields = {
12
+ /** boxd machine id. External, not a Convex document id. */
13
+ machineId: v.string(),
14
+ name: v.string(),
15
+ /**
16
+ * Opaque tenant key from the host app. Components can't read `ctx.auth`, so
17
+ * the app derives this from its own auth and every call must present the
18
+ * same value to touch the machine.
19
+ */
20
+ ownerId: v.optional(v.string()),
21
+ /** Last observed boxd status: `running`, `suspended`, `hibernated`, ... */
22
+ status: v.string(),
23
+ image: v.optional(v.string()),
24
+ /** `https://<name>.<zone>`, the machine's default HTTPS route. */
25
+ url: v.optional(v.string()),
26
+ vcpu: v.optional(v.number()),
27
+ memoryBytes: v.optional(v.number()),
28
+ /** Set when this machine is a fork of another machine. */
29
+ forkedFrom: v.optional(v.string()),
30
+ /** The last failed operation's message. Cleared by the next success. */
31
+ lastError: v.optional(v.string()),
32
+ updatedAt: v.number(),
33
+ };
34
+ export const executionStatus = v.union(v.literal("running"), v.literal("completed"), v.literal("failed"));
35
+ /** One row per `exec`, so the app can render live status and history. */
36
+ export const executionFields = {
37
+ machineId: v.string(),
38
+ ownerId: v.optional(v.string()),
39
+ /** The command line that ran, truncated for storage. */
40
+ command: v.string(),
41
+ cwd: v.optional(v.string()),
42
+ status: executionStatus,
43
+ exitCode: v.optional(v.number()),
44
+ /** Truncated for storage; the action's return value carries more. */
45
+ stdout: v.optional(v.string()),
46
+ stderr: v.optional(v.string()),
47
+ error: v.optional(v.string()),
48
+ startedAt: v.number(),
49
+ finishedAt: v.optional(v.number()),
50
+ };
51
+ export default defineSchema({
52
+ machines: defineTable(machineFields)
53
+ .index("by_machine_id", ["machineId"])
54
+ .index("by_owner", ["ownerId"]),
55
+ executions: defineTable(executionFields).index("by_machine", ["machineId"]),
56
+ /**
57
+ * Cached session tokens, keyed by a SHA-256 of the API key and endpoint.
58
+ * boxd rate-limits the key-for-token exchange per source IP, and every
59
+ * Convex deployment in a region shares a few egress IPs, so each action
60
+ * must reuse the token rather than exchange the key again. Internal only:
61
+ * nothing in the component's public API returns these rows.
62
+ */
63
+ sessions: defineTable({
64
+ keyHash: v.string(),
65
+ token: v.string(),
66
+ /** Epoch milliseconds. */
67
+ expiresAt: v.number(),
68
+ }).index("by_key_hash", ["keyHash"]),
69
+ });
70
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/component/schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * The session-token cache behind every boxd call. Internal functions only:
3
+ * the app can't read a token through the component's API.
4
+ */
5
+ export declare const get: import("convex/server").RegisteredQuery<"internal", {
6
+ keyHash: string;
7
+ }, Promise<{
8
+ token: string;
9
+ expiresAt: number;
10
+ } | null>>;
11
+ export declare const put: import("convex/server").RegisteredMutation<"internal", {
12
+ keyHash: string;
13
+ token: string;
14
+ expiresAt: number;
15
+ }, Promise<null>>;
16
+ /** Forget a token boxd rejected, so the next call exchanges the key again. */
17
+ export declare const drop: import("convex/server").RegisteredMutation<"internal", {
18
+ keyHash: string;
19
+ token: string;
20
+ }, Promise<null>>;
21
+ //# sourceMappingURL=sessions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../src/component/sessions.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,eAAO,MAAM,GAAG;;;;;UAUd,CAAC;AAEH,eAAO,MAAM,GAAG;;;;iBAsBd,CAAC;AAEH,8EAA8E;AAC9E,eAAO,MAAM,IAAI;;;iBAaf,CAAC"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * The session-token cache behind every boxd call. Internal functions only:
3
+ * the app can't read a token through the component's API.
4
+ */
5
+ import { v } from "convex/values";
6
+ import { internalMutation, internalQuery } from "./_generated/server.js";
7
+ const session = v.object({ token: v.string(), expiresAt: v.number() });
8
+ export const get = internalQuery({
9
+ args: { keyHash: v.string() },
10
+ returns: v.union(v.null(), session),
11
+ handler: async (ctx, { keyHash }) => {
12
+ const row = await ctx.db
13
+ .query("sessions")
14
+ .withIndex("by_key_hash", (q) => q.eq("keyHash", keyHash))
15
+ .unique();
16
+ return row ? { token: row.token, expiresAt: row.expiresAt } : null;
17
+ },
18
+ });
19
+ export const put = internalMutation({
20
+ args: { keyHash: v.string(), token: v.string(), expiresAt: v.number() },
21
+ returns: v.null(),
22
+ handler: async (ctx, args) => {
23
+ const row = await ctx.db
24
+ .query("sessions")
25
+ .withIndex("by_key_hash", (q) => q.eq("keyHash", args.keyHash))
26
+ .unique();
27
+ if (row) {
28
+ // Two actions can exchange at the same time. Keep the token that lives
29
+ // longer, so a slow writer never replaces a fresher one.
30
+ if (row.expiresAt < args.expiresAt) {
31
+ await ctx.db.patch("sessions", row._id, {
32
+ token: args.token,
33
+ expiresAt: args.expiresAt,
34
+ });
35
+ }
36
+ }
37
+ else {
38
+ await ctx.db.insert("sessions", args);
39
+ }
40
+ return null;
41
+ },
42
+ });
43
+ /** Forget a token boxd rejected, so the next call exchanges the key again. */
44
+ export const drop = internalMutation({
45
+ args: { keyHash: v.string(), token: v.string() },
46
+ returns: v.null(),
47
+ handler: async (ctx, { keyHash, token }) => {
48
+ const row = await ctx.db
49
+ .query("sessions")
50
+ .withIndex("by_key_hash", (q) => q.eq("keyHash", keyHash))
51
+ .unique();
52
+ // Only drop the token that failed: another action may already have
53
+ // stored a fresh one.
54
+ if (row && row.token === token)
55
+ await ctx.db.delete("sessions", row._id);
56
+ return null;
57
+ },
58
+ });
59
+ //# sourceMappingURL=sessions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../src/component/sessions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Argument checks that Convex validators can't express. Each one runs before
3
+ * any remote call or row write, and throws `INVALID_ARGUMENT`.
4
+ */
5
+ /**
6
+ * A caller-supplied timeout, validated and capped. A value that is not a
7
+ * positive number fails loudly instead of meaning "no limit".
8
+ */
9
+ export declare function boundedTimeout(requested: number | undefined, fallback: number, max: number, field: string): number;
10
+ export declare function requirePort(port: number): number;
11
+ /** A proxy name is one DNS label: `<name>.<machine>.<zone>`. */
12
+ export declare function requireSubdomainLabel(name: string): string;
13
+ export declare function requireAbsolutePath(path: string): string;
14
+ export declare function requireNonEmpty(value: string, field: string): string;
15
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/component/validate.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,GACZ,MAAM,CAQR;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKhD;AAID,gEAAgE;AAChE,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAO1D;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKxD;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAKpE"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Argument checks that Convex validators can't express. Each one runs before
3
+ * any remote call or row write, and throws `INVALID_ARGUMENT`.
4
+ */
5
+ import { invalidArgument } from "./errors.js";
6
+ /**
7
+ * A caller-supplied timeout, validated and capped. A value that is not a
8
+ * positive number fails loudly instead of meaning "no limit".
9
+ */
10
+ export function boundedTimeout(requested, fallback, max, field) {
11
+ if (requested === undefined)
12
+ return fallback;
13
+ if (!Number.isFinite(requested) || requested <= 0) {
14
+ throw invalidArgument(`${field} must be a positive number of milliseconds, got ${requested}`);
15
+ }
16
+ return Math.min(Math.floor(requested), max);
17
+ }
18
+ export function requirePort(port) {
19
+ if (!Number.isInteger(port) || port < 1 || port > 65_535) {
20
+ throw invalidArgument(`port must be an integer in 1-65535, got ${port}`);
21
+ }
22
+ return port;
23
+ }
24
+ const SUBDOMAIN_LABEL = /^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$/;
25
+ /** A proxy name is one DNS label: `<name>.<machine>.<zone>`. */
26
+ export function requireSubdomainLabel(name) {
27
+ if (!SUBDOMAIN_LABEL.test(name)) {
28
+ throw invalidArgument(`name must be one DNS label (lowercase letters, digits and inner hyphens), got ${JSON.stringify(name)}`);
29
+ }
30
+ return name;
31
+ }
32
+ export function requireAbsolutePath(path) {
33
+ if (!path.startsWith("/")) {
34
+ throw invalidArgument(`path must be absolute, got ${JSON.stringify(path)}`);
35
+ }
36
+ return path;
37
+ }
38
+ export function requireNonEmpty(value, field) {
39
+ if (value.trim().length === 0) {
40
+ throw invalidArgument(`${field} must not be empty`);
41
+ }
42
+ return value;
43
+ }
44
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/component/validate.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C;;;GAGG;AACH,MAAM,UAAU,cAAc,CAC5B,SAA6B,EAC7B,QAAgB,EAChB,GAAW,EACX,KAAa;IAEb,IAAI,SAAS,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IAC7C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;QAClD,MAAM,eAAe,CACnB,GAAG,KAAK,mDAAmD,SAAS,EAAE,CACvE,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,GAAG,CAAC,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,MAAM,EAAE,CAAC;QACzD,MAAM,eAAe,CAAC,2CAA2C,IAAI,EAAE,CAAC,CAAC;IAC3E,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,eAAe,GAAG,sCAAsC,CAAC;AAE/D,gEAAgE;AAChE,MAAM,UAAU,qBAAqB,CAAC,IAAY;IAChD,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAChC,MAAM,eAAe,CACnB,iFAAiF,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CACxG,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,eAAe,CAAC,8BAA8B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC9E,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAa,EAAE,KAAa;IAC1D,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,MAAM,eAAe,CAAC,GAAG,KAAK,oBAAoB,CAAC,CAAC;IACtD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
package/package.json ADDED
@@ -0,0 +1,99 @@
1
+ {
2
+ "name": "@boxd-sh/convex",
3
+ "description": "Convex component for boxd composable computers",
4
+ "repository": "github:azin-tech/boxd-convex",
5
+ "homepage": "https://github.com/azin-tech/boxd-convex#readme",
6
+ "bugs": {
7
+ "url": "https://github.com/azin-tech/boxd-convex/issues"
8
+ },
9
+ "version": "0.1.0",
10
+ "license": "MIT",
11
+ "author": "Azin",
12
+ "keywords": [
13
+ "convex",
14
+ "component",
15
+ "convex-component",
16
+ "boxd",
17
+ "sandbox",
18
+ "microvm",
19
+ "vm",
20
+ "code-execution",
21
+ "ai-agents"
22
+ ],
23
+ "type": "module",
24
+ "scripts": {
25
+ "build": "tsc --project ./tsconfig.build.json",
26
+ "build:codegen": "convex codegen --component-dir ./src/component && npm run build",
27
+ "build:clean": "rm -rf dist *.tsbuildinfo && npm run build:codegen",
28
+ "dev:demo": "vite --config demo/vite.config.ts",
29
+ "build:demo": "vite build --config demo/vite.config.ts",
30
+ "typecheck": "tsc --noEmit && tsc -p example/convex && tsc -p demo/convex && tsc -p demo",
31
+ "lint": "eslint .",
32
+ "format": "prettier --write .",
33
+ "format:check": "prettier --check .",
34
+ "test": "vitest run --typecheck",
35
+ "test:watch": "vitest --typecheck --clearScreen false",
36
+ "test:live": "node scripts/live.mjs",
37
+ "check": "npm run build && npm run typecheck && npm run lint && npm run format:check && npm run test",
38
+ "prepare": "npm run build"
39
+ },
40
+ "files": [
41
+ "dist",
42
+ "src",
43
+ "!src/**/*.test.ts"
44
+ ],
45
+ "exports": {
46
+ "./package.json": "./package.json",
47
+ ".": {
48
+ "types": "./dist/client/index.d.ts",
49
+ "default": "./dist/client/index.js"
50
+ },
51
+ "./test": "./src/test.ts",
52
+ "./_generated/component.js": {
53
+ "types": "./dist/component/_generated/component.d.ts"
54
+ },
55
+ "./_generated/component": {
56
+ "types": "./dist/component/_generated/component.d.ts"
57
+ },
58
+ "./convex.config.js": {
59
+ "types": "./dist/component/convex.config.d.ts",
60
+ "default": "./dist/component/convex.config.js"
61
+ },
62
+ "./convex.config": {
63
+ "types": "./dist/component/convex.config.d.ts",
64
+ "default": "./dist/component/convex.config.js"
65
+ }
66
+ },
67
+ "types": "./dist/client/index.d.ts",
68
+ "module": "./dist/client/index.js",
69
+ "dependencies": {
70
+ "@boxd-sh/sdk": "^0.2.13"
71
+ },
72
+ "peerDependencies": {
73
+ "convex": "^1.46.0"
74
+ },
75
+ "devDependencies": {
76
+ "@auth/core": "^0.41.3",
77
+ "@convex-dev/auth": "^0.0.96",
78
+ "@convex-dev/eslint-plugin": "^5.0.0",
79
+ "@convex-dev/rate-limiter": "^0.4.0",
80
+ "@edge-runtime/vm": "^5.0.0",
81
+ "@eslint/js": "9.39.5",
82
+ "@types/node": "^24.13.3",
83
+ "@types/react": "^19.3.0",
84
+ "@types/react-dom": "^19.3.0",
85
+ "@vitejs/plugin-react": "^6.1.1",
86
+ "convex": "^1.46.0",
87
+ "convex-test": "^0.0.60",
88
+ "eslint": "9.39.5",
89
+ "globals": "^17.9.0",
90
+ "jose": "^6.2.12",
91
+ "prettier": "3.9.6",
92
+ "react": "^19.3.0",
93
+ "react-dom": "^19.3.0",
94
+ "typescript": "^5.9.3",
95
+ "typescript-eslint": "8.66.0",
96
+ "vite": "^8.3.1",
97
+ "vitest": "4.1.11"
98
+ }
99
+ }
@@ -0,0 +1 @@
1
+ // This is only here so convex-test can detect a _generated folder