robodev 0.50.0 → 0.51.1

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "robodev",
3
- "version": "0.50.0",
3
+ "version": "0.51.1",
4
4
  "description": "CLI for Robodev Starbase — create, auth, link, deploy, load, and run a project locally with robodev dev",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -26,8 +26,8 @@
26
26
  "embedded-postgres": "17.10.0-beta.17",
27
27
  "fastify": "^5.12.1",
28
28
  "tsx": "^4.20.5",
29
- "@robodev-ai/runtime": "0.10.0",
30
- "@robodev-ai/sdk": "0.15.0"
29
+ "@robodev-ai/sdk": "0.15.1",
30
+ "@robodev-ai/runtime": "0.11.1"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@types/node": "^24.3.0",
package/src/api.ts CHANGED
@@ -1,5 +1,19 @@
1
+ import { createRequire } from "node:module";
1
2
  import { readCredentials, starbaseUrl, writeCredentials, type Credentials } from "./config.js";
2
3
 
4
+ function cliVersion(): string {
5
+ try {
6
+ const pkg = createRequire(import.meta.url)("../package.json") as { version?: string };
7
+ return typeof pkg.version === "string" && pkg.version ? pkg.version : "unknown";
8
+ } catch {
9
+ return "unknown";
10
+ }
11
+ }
12
+
13
+ /** Starbase labels deploys carrying this header "CLI" (vs a bare API call with a token). */
14
+ export const ROBODEV_CLIENT_HEADER = "X-Robodev-Client";
15
+ export const ROBODEV_CLIENT = `robodev-cli/${cliVersion()}`;
16
+
3
17
  export class ApiError extends Error {
4
18
  constructor(
5
19
  message: string,
@@ -23,6 +37,7 @@ async function request<T>(
23
37
  if (credentials?.accessToken) {
24
38
  headers.set("Authorization", `Bearer ${credentials.accessToken}`);
25
39
  }
40
+ if (!headers.has(ROBODEV_CLIENT_HEADER)) headers.set(ROBODEV_CLIENT_HEADER, ROBODEV_CLIENT);
26
41
 
27
42
  const res = await fetch(`${starbaseUrl()}${path}`, { ...init, headers });
28
43
  const body = (await res.json().catch(() => ({}))) as Record<string, unknown>;
@@ -191,7 +191,7 @@ test("collectSourceFiles includes Tiny apps/fe when CLI database is absent", asy
191
191
  }
192
192
  });
193
193
 
194
- test("collectSourceFiles CLI database wins and drops leftover Tiny", async () => {
194
+ test("collectSourceFiles CLI database wins over the Tiny backend and keeps apps/fe", async () => {
195
195
  const root = await mkdtemp(join(tmpdir(), "rd-cli-src-win-"));
196
196
  try {
197
197
  await mkdir(join(root, "robodev"), { recursive: true });
@@ -206,7 +206,7 @@ test("collectSourceFiles CLI database wins and drops leftover Tiny", async () =>
206
206
  const paths = new Set(files.map((file) => file.path));
207
207
  assert.ok(paths.has("robodev/database.ts"));
208
208
  assert.ok(paths.has("src/App.tsx"));
209
- assert.ok(!paths.has("apps/fe/src/main.tsx"));
209
+ assert.ok(paths.has("apps/fe/src/main.tsx"));
210
210
  assert.ok(!paths.has("packages/be/database.ts"));
211
211
  } finally {
212
212
  await rm(root, { recursive: true, force: true });
package/src/dev.ts CHANGED
@@ -228,8 +228,12 @@ export async function main(args: string[]): Promise<void> {
228
228
  throw error;
229
229
  }
230
230
 
231
- const loaded = await loadModules(distDir, files);
232
- assertJobCrons(loaded.jobs);
231
+ // A reload is a fresh deploy of local code: strict checks, warnings printed.
232
+ const loaded = await loadModules(distDir, files, undefined, {
233
+ mode: "deploy",
234
+ onWarning: (message) => log(`Warning: ${message}`),
235
+ });
236
+ assertJobCrons(loaded.jobs, { mode: "deploy" });
233
237
  // Any edit to database.ts can change columns, not just tables, so compare its source.
234
238
  const schemaSource = files.find((file) => file.path === "database.ts")?.content ?? "";
235
239
 
package/src/index.ts CHANGED
@@ -337,6 +337,7 @@ async function runDeploy(
337
337
  docsUrl: string;
338
338
  routes: { method: string; path: string }[];
339
339
  plan: { operations: { type: string; table: string; column?: string; sql: string }[] };
340
+ warnings?: string[];
340
341
  }>(`/v1/projects/${link.projectId}/deploy`, {
341
342
  method: "POST",
342
343
  body: JSON.stringify({
@@ -364,6 +365,9 @@ async function runDeploy(
364
365
  for (const route of result.routes) {
365
366
  console.log(` ${route.method.toUpperCase()} ${route.path}`);
366
367
  }
368
+ for (const warning of result.warnings ?? []) {
369
+ console.log(`Warning: ${warning}`);
370
+ }
367
371
  return result.appUrl ?? result.apiUrl;
368
372
  } catch (error) {
369
373
  if (
@@ -26,6 +26,8 @@ Method exports: one export per method — `get` / `post` / `put` / `patch` / `de
26
26
 
27
27
  `ctx.user.id` is a string like `usr_abc123`, not a UUID. Type user id columns as `text`, never `uuid`.
28
28
 
29
+ Request input: declare `body: z.object({ ... })` (and `query:` for the query string) on `defineApi`, then read it as `ctx.body`, with `ctx.query` and `ctx.params` (the `[id]` segments) beside it. There is no `ctx.request` and no `request:` option; publish rejects `request:`.
30
+
29
31
  Throw an Error with an integer `statusCode` (400-599) to answer with that status: `throw Object.assign(new Error("Not found"), { statusCode: 404 })`. Any other throw is a generic 500.
30
32
 
31
33
  ## Hard rules
@@ -9,10 +9,10 @@
9
9
  "rules:gen": "rulesync generate"
10
10
  },
11
11
  "dependencies": {
12
- "@robodev-ai/sdk": "^0.15.0"
12
+ "@robodev-ai/sdk": "^0.15.1"
13
13
  },
14
14
  "devDependencies": {
15
- "robodev": "^0.50.0",
15
+ "robodev": "^0.51.1",
16
16
  "rulesync": "^8.18.0",
17
17
  "typescript": "^5.9.2"
18
18
  }
@@ -26,6 +26,8 @@ Method exports: one export per method — `get` / `post` / `put` / `patch` / `de
26
26
 
27
27
  `ctx.user.id` is a string like `usr_abc123`, not a UUID. Type user id columns as `text`, never `uuid`.
28
28
 
29
+ Request input: declare `body: z.object({ ... })` (and `query:` for the query string) on `defineApi`, then read it as `ctx.body`, with `ctx.query` and `ctx.params` (the `[id]` segments) beside it. There is no `ctx.request` and no `request:` option; publish rejects `request:`.
30
+
29
31
  Throw an Error with an integer `statusCode` (400-599) to answer with that status: `throw Object.assign(new Error("Not found"), { statusCode: 404 })`. Any other throw is a generic 500.
30
32
 
31
33
  ## Hard rules
@@ -8,10 +8,10 @@
8
8
  "deploy": "robodev deploy"
9
9
  },
10
10
  "dependencies": {
11
- "@robodev-ai/sdk": "^0.15.0"
11
+ "@robodev-ai/sdk": "^0.15.1"
12
12
  },
13
13
  "devDependencies": {
14
- "robodev": "^0.50.0",
14
+ "robodev": "^0.51.1",
15
15
  "typescript": "^5.9.2"
16
16
  }
17
17
  }
@@ -26,6 +26,8 @@ Method exports: one export per method — `get` / `post` / `put` / `patch` / `de
26
26
 
27
27
  `ctx.user.id` is a string like `usr_abc123`, not a UUID. Type user id columns as `text`, never `uuid`.
28
28
 
29
+ Request input: declare `body: z.object({ ... })` (and `query:` for the query string) on `defineApi`, then read it as `ctx.body`, with `ctx.query` and `ctx.params` (the `[id]` segments) beside it. There is no `ctx.request` and no `request:` option; publish rejects `request:`.
30
+
29
31
  Throw an Error with an integer `statusCode` (400-599) to answer with that status: `throw Object.assign(new Error("Not found"), { statusCode: 404 })`. Any other throw is a generic 500.
30
32
 
31
33
  ## Hard rules
@@ -10,13 +10,13 @@
10
10
  "build": "vite build"
11
11
  },
12
12
  "dependencies": {
13
- "@robodev-ai/sdk": "^0.15.0",
13
+ "@robodev-ai/sdk": "^0.15.1",
14
14
  "@robodev-ai/client": "^0.5.0",
15
15
  "react": "^18.3.1",
16
16
  "react-dom": "^18.3.1"
17
17
  },
18
18
  "devDependencies": {
19
- "robodev": "^0.50.0",
19
+ "robodev": "^0.51.1",
20
20
  "typescript": "^5.9.2",
21
21
  "vite": "^6.0.0"
22
22
  }
@@ -26,6 +26,8 @@ Method exports: one export per method — `get` / `post` / `put` / `patch` / `de
26
26
 
27
27
  `ctx.user.id` is a string like `usr_abc123`, not a UUID. Type user id columns as `text`, never `uuid`.
28
28
 
29
+ Request input: declare `body: z.object({ ... })` (and `query:` for the query string) on `defineApi`, then read it as `ctx.body`, with `ctx.query` and `ctx.params` (the `[id]` segments) beside it. There is no `ctx.request` and no `request:` option; publish rejects `request:`.
30
+
29
31
  Throw an Error with an integer `statusCode` (400-599) to answer with that status: `throw Object.assign(new Error("Not found"), { statusCode: 404 })`. Any other throw is a generic 500.
30
32
 
31
33
  ## Hard rules
@@ -9,10 +9,10 @@
9
9
  "rules:gen": "rulesync generate"
10
10
  },
11
11
  "dependencies": {
12
- "@robodev-ai/sdk": "^0.15.0"
12
+ "@robodev-ai/sdk": "^0.15.1"
13
13
  },
14
14
  "devDependencies": {
15
- "robodev": "^0.50.0",
15
+ "robodev": "^0.51.1",
16
16
  "rulesync": "^8.18.0",
17
17
  "typescript": "^5.9.2"
18
18
  }
@@ -26,6 +26,8 @@ Method exports: one export per method — `get` / `post` / `put` / `patch` / `de
26
26
 
27
27
  `ctx.user.id` is a string like `usr_abc123`, not a UUID. Type user id columns as `text`, never `uuid`.
28
28
 
29
+ Request input: declare `body: z.object({ ... })` (and `query:` for the query string) on `defineApi`, then read it as `ctx.body`, with `ctx.query` and `ctx.params` (the `[id]` segments) beside it. There is no `ctx.request` and no `request:` option; publish rejects `request:`.
30
+
29
31
  Throw an Error with an integer `statusCode` (400-599) to answer with that status: `throw Object.assign(new Error("Not found"), { statusCode: 404 })`. Any other throw is a generic 500.
30
32
 
31
33
  ## Hard rules
@@ -9,10 +9,10 @@
9
9
  "rules:gen": "rulesync generate"
10
10
  },
11
11
  "dependencies": {
12
- "@robodev-ai/sdk": "^0.15.0"
12
+ "@robodev-ai/sdk": "^0.15.1"
13
13
  },
14
14
  "devDependencies": {
15
- "robodev": "^0.50.0",
15
+ "robodev": "^0.51.1",
16
16
  "rulesync": "^8.18.0",
17
17
  "typescript": "^5.9.2"
18
18
  }
@@ -26,6 +26,8 @@ Method exports: one export per method — `get` / `post` / `put` / `patch` / `de
26
26
 
27
27
  `ctx.user.id` is a string like `usr_abc123`, not a UUID. Type user id columns as `text`, never `uuid`.
28
28
 
29
+ Request input: declare `body: z.object({ ... })` (and `query:` for the query string) on `defineApi`, then read it as `ctx.body`, with `ctx.query` and `ctx.params` (the `[id]` segments) beside it. There is no `ctx.request` and no `request:` option; publish rejects `request:`.
30
+
29
31
  Throw an Error with an integer `statusCode` (400-599) to answer with that status: `throw Object.assign(new Error("Not found"), { statusCode: 404 })`. Any other throw is a generic 500.
30
32
 
31
33
  ## Hard rules
@@ -11,7 +11,7 @@
11
11
  "generate:api": "orval"
12
12
  },
13
13
  "dependencies": {
14
- "@robodev-ai/sdk": "^0.15.0",
14
+ "@robodev-ai/sdk": "^0.15.1",
15
15
  "@robodev-ai/client": "^0.5.0",
16
16
  "react": "^18.3.1",
17
17
  "react-dom": "^18.3.1",
@@ -21,7 +21,7 @@
21
21
  "@types/react": "^18.3.12",
22
22
  "@types/react-dom": "^18.3.1",
23
23
  "orval": "^7.11.2",
24
- "robodev": "^0.50.0",
24
+ "robodev": "^0.51.1",
25
25
  "typescript": "^5.9.2",
26
26
  "vite": "^6.0.0"
27
27
  }
@@ -26,6 +26,8 @@ Method exports: one export per method — `get` / `post` / `put` / `patch` / `de
26
26
 
27
27
  `ctx.user.id` is a string like `usr_abc123`, not a UUID. Type user id columns as `text`, never `uuid`.
28
28
 
29
+ Request input: declare `body: z.object({ ... })` (and `query:` for the query string) on `defineApi`, then read it as `ctx.body`, with `ctx.query` and `ctx.params` (the `[id]` segments) beside it. There is no `ctx.request` and no `request:` option; publish rejects `request:`.
30
+
29
31
  Throw an Error with an integer `statusCode` (400-599) to answer with that status: `throw Object.assign(new Error("Not found"), { statusCode: 404 })`. Any other throw is a generic 500.
30
32
 
31
33
  ## Hard rules
@@ -9,10 +9,10 @@
9
9
  "rules:gen": "rulesync generate"
10
10
  },
11
11
  "dependencies": {
12
- "@robodev-ai/sdk": "^0.15.0"
12
+ "@robodev-ai/sdk": "^0.15.1"
13
13
  },
14
14
  "devDependencies": {
15
- "robodev": "^0.50.0",
15
+ "robodev": "^0.51.1",
16
16
  "rulesync": "^8.18.0",
17
17
  "typescript": "^5.9.2"
18
18
  }