robodev 0.31.0 → 0.32.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 +3 -3
- package/src/dev-clients.ts +5 -4
- package/src/dev-server.ts +6 -2
- package/src/dev.ts +36 -8
- package/templates/auth-chat/package.json +2 -2
- package/templates/backend/package.json +2 -2
- package/templates/empty/package.json +2 -2
- package/templates/marketplace/package.json +2 -2
- package/templates/space/package.json +2 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "robodev",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.32.0",
|
|
4
4
|
"description": "CLI for Robodev Starbase — create, auth, link, deploy, and run a project locally with robodev dev",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"embedded-postgres": "17.10.0-beta.17",
|
|
26
26
|
"fastify": "^5.12.1",
|
|
27
27
|
"tsx": "^4.20.5",
|
|
28
|
-
"@robodev-ai/runtime": "0.
|
|
29
|
-
"@robodev-ai/sdk": "0.
|
|
28
|
+
"@robodev-ai/runtime": "0.2.0",
|
|
29
|
+
"@robodev-ai/sdk": "0.11.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@types/node": "^24.3.0",
|
package/src/dev-clients.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { RouteClients } from "@robodev-ai/runtime";
|
|
2
|
-
import type { EmailClient, LlmClient } from "@robodev-ai/sdk";
|
|
2
|
+
import type { EmailClient, JobEnqueueInput, LlmClient } from "@robodev-ai/sdk";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* The `ctx.*` clients `robodev dev` can offer offline. `email` prints to the terminal;
|
|
6
|
-
*
|
|
7
|
-
* than silently doing nothing.
|
|
6
|
+
* `jobs` enqueues onto the local engine; everything else that needs Starbase
|
|
7
|
+
* infrastructure fails with a message that says so rather than silently doing nothing.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
function unavailable(feature: string): never {
|
|
@@ -36,6 +36,7 @@ function offlineLlmClient(): LlmClient {
|
|
|
36
36
|
export function devRouteClients(input: {
|
|
37
37
|
env: Record<string, string>;
|
|
38
38
|
log: (line: string) => void;
|
|
39
|
+
enqueue: (job: JobEnqueueInput) => Promise<{ id: string }>;
|
|
39
40
|
}): RouteClients {
|
|
40
41
|
return {
|
|
41
42
|
email: consoleEmailClient(input.log),
|
|
@@ -55,7 +56,7 @@ export function devRouteClients(input: {
|
|
|
55
56
|
list: () => unavailable("storage"),
|
|
56
57
|
},
|
|
57
58
|
push: { send: () => unavailable("push") },
|
|
58
|
-
jobs: { enqueue:
|
|
59
|
+
jobs: { enqueue: input.enqueue },
|
|
59
60
|
sockets: {
|
|
60
61
|
send: () => unavailable("sockets"),
|
|
61
62
|
broadcast: () => unavailable("sockets"),
|
package/src/dev-server.ts
CHANGED
|
@@ -13,7 +13,8 @@ import {
|
|
|
13
13
|
type AuthQueryable,
|
|
14
14
|
type RuntimeRoute,
|
|
15
15
|
} from "@robodev-ai/runtime";
|
|
16
|
-
import type { RobodevDb } from "@robodev-ai/sdk";
|
|
16
|
+
import type { JobEnqueueInput, RobodevDb } from "@robodev-ai/sdk";
|
|
17
|
+
import type { RuntimeJob } from "@robodev-ai/runtime";
|
|
17
18
|
import { devRouteClients } from "./dev-clients.js";
|
|
18
19
|
|
|
19
20
|
/** One compiled generation of the project. Swapped wholesale on reload. */
|
|
@@ -21,6 +22,7 @@ export type DevRuntime = {
|
|
|
21
22
|
db: RobodevDb;
|
|
22
23
|
pool: AuthQueryable & { end: () => Promise<void> };
|
|
23
24
|
routes: RuntimeRoute[];
|
|
25
|
+
jobs: RuntimeJob[];
|
|
24
26
|
openapi: Record<string, unknown>;
|
|
25
27
|
};
|
|
26
28
|
|
|
@@ -30,6 +32,7 @@ export type DevServerOptions = {
|
|
|
30
32
|
jwtSecret: string;
|
|
31
33
|
env: Record<string, string>;
|
|
32
34
|
log: (line: string) => void;
|
|
35
|
+
enqueue: (job: JobEnqueueInput) => Promise<{ id: string }>;
|
|
33
36
|
};
|
|
34
37
|
|
|
35
38
|
const SWAGGER_PATHS = new Set(["/_robodev/docs", "/_robodev/swagger", "/docs", "/swagger"]);
|
|
@@ -181,7 +184,8 @@ export async function startDevServer(
|
|
|
181
184
|
{ projectId: options.projectId, jwtSecret: options.jwtSecret },
|
|
182
185
|
authorization,
|
|
183
186
|
),
|
|
184
|
-
clients: () =>
|
|
187
|
+
clients: () =>
|
|
188
|
+
devRouteClients({ env: options.env, log: options.log, enqueue: options.enqueue }),
|
|
185
189
|
});
|
|
186
190
|
|
|
187
191
|
if (outcome.kind === "error") {
|
package/src/dev.ts
CHANGED
|
@@ -6,9 +6,12 @@ import { spawn, type ChildProcess } from "node:child_process";
|
|
|
6
6
|
import {
|
|
7
7
|
apiBundleExternals,
|
|
8
8
|
applyPlan,
|
|
9
|
+
assertJobCrons,
|
|
9
10
|
buildPlan,
|
|
10
11
|
compileApiTree,
|
|
12
|
+
createLocalJobsEngine,
|
|
11
13
|
ensureAuthSchema,
|
|
14
|
+
ensureJobsSchema,
|
|
12
15
|
isEsbuildFailure,
|
|
13
16
|
loadModules,
|
|
14
17
|
mapEsbuildErrors,
|
|
@@ -26,6 +29,7 @@ import {
|
|
|
26
29
|
type DevProject,
|
|
27
30
|
} from "./dev-project.js";
|
|
28
31
|
import { externalDevPostgres, startDevPostgres, type DevPostgres } from "./dev-postgres.js";
|
|
32
|
+
import { devRouteClients } from "./dev-clients.js";
|
|
29
33
|
import { buildDevOpenApi, startDevServer, type DevRuntime } from "./dev-server.js";
|
|
30
34
|
|
|
31
35
|
export type DevArgs = {
|
|
@@ -154,6 +158,15 @@ export async function main(args: string[]): Promise<void> {
|
|
|
154
158
|
let closing = false;
|
|
155
159
|
|
|
156
160
|
const log = (line: string) => console.log(line);
|
|
161
|
+
const engine = createLocalJobsEngine({
|
|
162
|
+
query: (sql, values) => {
|
|
163
|
+
if (!current) throw new Error("jobs engine not ready");
|
|
164
|
+
return current.pool.query(sql, values);
|
|
165
|
+
},
|
|
166
|
+
getGeneration: () => current,
|
|
167
|
+
log,
|
|
168
|
+
clients: () => devRouteClients({ env, log, enqueue: (input) => engine.enqueue(input) }),
|
|
169
|
+
});
|
|
157
170
|
|
|
158
171
|
async function compileAndActivate(input: { syncSchema: boolean }): Promise<void> {
|
|
159
172
|
const files = await collectBackendFiles(project.backendDir);
|
|
@@ -179,6 +192,7 @@ export async function main(args: string[]): Promise<void> {
|
|
|
179
192
|
}
|
|
180
193
|
|
|
181
194
|
const loaded = await loadModules(distDir, files);
|
|
195
|
+
assertJobCrons(loaded.jobs);
|
|
182
196
|
// Any edit to database.ts can change columns, not just tables, so compare its source.
|
|
183
197
|
const schemaSource = files.find((file) => file.path === "database.ts")?.content ?? "";
|
|
184
198
|
|
|
@@ -200,31 +214,36 @@ export async function main(args: string[]): Promise<void> {
|
|
|
200
214
|
const { db, pool } = createDb(postgres.connectionString, loaded.database.tables);
|
|
201
215
|
await pool.query("SELECT 1");
|
|
202
216
|
await ensureAuthSchema(pool);
|
|
217
|
+
await ensureJobsSchema(pool);
|
|
203
218
|
|
|
204
219
|
const previous = current;
|
|
205
220
|
current = {
|
|
206
221
|
db,
|
|
207
222
|
pool,
|
|
208
223
|
routes: loaded.routes,
|
|
224
|
+
jobs: loaded.jobs,
|
|
209
225
|
openapi: buildDevOpenApi(loaded.database.name, loaded.routes),
|
|
210
226
|
};
|
|
211
|
-
|
|
212
|
-
await previous.pool.end().catch(() => undefined);
|
|
213
|
-
}
|
|
227
|
+
await engine.reconcile(loaded.jobs);
|
|
214
228
|
|
|
215
229
|
for (const route of loaded.routes) {
|
|
216
230
|
console.log(` ${route.method.toUpperCase()} ${route.path}`);
|
|
217
231
|
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
` ${
|
|
221
|
-
|
|
232
|
+
for (const job of loaded.jobs) {
|
|
233
|
+
if (job.def.cron) {
|
|
234
|
+
console.log(` job ${job.name} (cron ${job.def.cron})`);
|
|
235
|
+
} else {
|
|
236
|
+
console.log(` job ${job.name}`);
|
|
237
|
+
}
|
|
222
238
|
}
|
|
223
239
|
if (loaded.sockets.length > 0) {
|
|
224
240
|
console.log(
|
|
225
241
|
` ${loaded.sockets.length} socket(s) compiled but not served — sockets need hosted Starbase.`,
|
|
226
242
|
);
|
|
227
243
|
}
|
|
244
|
+
if (previous) {
|
|
245
|
+
await previous.pool.end().catch(() => undefined);
|
|
246
|
+
}
|
|
228
247
|
}
|
|
229
248
|
|
|
230
249
|
async function releaseDatabase(): Promise<void> {
|
|
@@ -235,8 +254,16 @@ export async function main(args: string[]): Promise<void> {
|
|
|
235
254
|
let server: Awaited<ReturnType<typeof startDevServer>>;
|
|
236
255
|
try {
|
|
237
256
|
await compileAndActivate({ syncSchema: true });
|
|
257
|
+
await engine.start();
|
|
238
258
|
server = await startDevServer(
|
|
239
|
-
{
|
|
259
|
+
{
|
|
260
|
+
port: parsed.port,
|
|
261
|
+
projectId: DEV_PROJECT_ID,
|
|
262
|
+
jwtSecret: DEV_JWT_SECRET,
|
|
263
|
+
env,
|
|
264
|
+
log,
|
|
265
|
+
enqueue: (input) => engine.enqueue(input),
|
|
266
|
+
},
|
|
240
267
|
() => current,
|
|
241
268
|
);
|
|
242
269
|
} catch (error) {
|
|
@@ -312,6 +339,7 @@ export async function main(args: string[]): Promise<void> {
|
|
|
312
339
|
async function shutdown(code: number): Promise<void> {
|
|
313
340
|
if (closing) return;
|
|
314
341
|
closing = true;
|
|
342
|
+
await engine.stop();
|
|
315
343
|
for (const watcher of watchers) watcher.close();
|
|
316
344
|
fe?.kill("SIGTERM");
|
|
317
345
|
await server.close().catch(() => undefined);
|
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
"rules:gen": "rulesync generate"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@robodev-ai/sdk": "^0.
|
|
12
|
+
"@robodev-ai/sdk": "^0.11.0"
|
|
13
13
|
},
|
|
14
14
|
"devDependencies": {
|
|
15
|
-
"robodev": "^0.
|
|
15
|
+
"robodev": "^0.32.0",
|
|
16
16
|
"rulesync": "^8.18.0",
|
|
17
17
|
"typescript": "^5.9.2"
|
|
18
18
|
}
|
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
"rules:gen": "rulesync generate"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@robodev-ai/sdk": "^0.
|
|
12
|
+
"@robodev-ai/sdk": "^0.11.0"
|
|
13
13
|
},
|
|
14
14
|
"devDependencies": {
|
|
15
|
-
"robodev": "^0.
|
|
15
|
+
"robodev": "^0.32.0",
|
|
16
16
|
"rulesync": "^8.18.0",
|
|
17
17
|
"typescript": "^5.9.2"
|
|
18
18
|
}
|
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
"rules:gen": "rulesync generate"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@robodev-ai/sdk": "^0.
|
|
12
|
+
"@robodev-ai/sdk": "^0.11.0"
|
|
13
13
|
},
|
|
14
14
|
"devDependencies": {
|
|
15
|
-
"robodev": "^0.
|
|
15
|
+
"robodev": "^0.32.0",
|
|
16
16
|
"rulesync": "^8.18.0",
|
|
17
17
|
"typescript": "^5.9.2"
|
|
18
18
|
}
|