@beignet/cli 0.0.21 → 0.0.23

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 (50) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +25 -3
  3. package/dist/choices.d.ts +8 -0
  4. package/dist/choices.d.ts.map +1 -1
  5. package/dist/choices.js +4 -0
  6. package/dist/choices.js.map +1 -1
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +8 -1
  9. package/dist/index.js.map +1 -1
  10. package/dist/inspect.js +152 -0
  11. package/dist/inspect.js.map +1 -1
  12. package/dist/lib.d.ts +2 -2
  13. package/dist/lib.d.ts.map +1 -1
  14. package/dist/lib.js +1 -1
  15. package/dist/lib.js.map +1 -1
  16. package/dist/make.d.ts +4 -3
  17. package/dist/make.d.ts.map +1 -1
  18. package/dist/make.js +333 -30
  19. package/dist/make.js.map +1 -1
  20. package/dist/mcp.d.ts.map +1 -1
  21. package/dist/mcp.js +6 -2
  22. package/dist/mcp.js.map +1 -1
  23. package/dist/templates/agents.d.ts.map +1 -1
  24. package/dist/templates/agents.js +9 -5
  25. package/dist/templates/agents.js.map +1 -1
  26. package/dist/templates/base.d.ts.map +1 -1
  27. package/dist/templates/base.js +1 -0
  28. package/dist/templates/base.js.map +1 -1
  29. package/dist/templates/index.d.ts.map +1 -1
  30. package/dist/templates/index.js +1 -0
  31. package/dist/templates/index.js.map +1 -1
  32. package/dist/templates/server.d.ts +1 -0
  33. package/dist/templates/server.d.ts.map +1 -1
  34. package/dist/templates/server.js +30 -0
  35. package/dist/templates/server.js.map +1 -1
  36. package/dist/templates/shell.d.ts.map +1 -1
  37. package/dist/templates/shell.js +63 -29
  38. package/dist/templates/shell.js.map +1 -1
  39. package/package.json +2 -2
  40. package/src/choices.ts +10 -0
  41. package/src/index.ts +11 -0
  42. package/src/inspect.ts +266 -0
  43. package/src/lib.ts +2 -1
  44. package/src/make.ts +433 -38
  45. package/src/mcp.ts +7 -1
  46. package/src/templates/agents.ts +9 -5
  47. package/src/templates/base.ts +1 -0
  48. package/src/templates/index.ts +1 -0
  49. package/src/templates/server.ts +30 -0
  50. package/src/templates/shell.ts +64 -29
@@ -52,8 +52,9 @@ is a silent failure — the file exists but never runs:
52
52
 
53
53
  The starter ships no workflow registries — generators create them on first
54
54
  use, so their absence is fine. \`${cli} make event\`, \`${cli} make job\`,
55
- \`${cli} make schedule\`, \`${cli} make task\`, \`${cli} make seed\`, and
56
- \`${cli} make upload\` create or update their required app entrypoints.
55
+ \`${cli} make listener\`, \`${cli} make schedule\`, \`${cli} make task\`,
56
+ \`${cli} make seed\`, and \`${cli} make upload\` create or update their
57
+ required app entrypoints.
57
58
  \`${cli} doctor\` detects registration drift. \`${cli} doctor --fix\` repairs
58
59
  route-group, schedule, task, and outbox registration; listener drift is
59
60
  report-only and must be fixed by hand.
@@ -62,8 +63,10 @@ report-only and must be fixed by hand.
62
63
 
63
64
  \`${cli} make <artifact> <name>\` creates correctly placed, pre-registered
64
65
  files — prefer it over hand-writing them. See \`${cli} make --help\` for the
65
- artifact list. After changing the Drizzle schema in \`infra/db/schema/\`, run
66
- \`${cli} db generate\` then \`${cli} db migrate\`.
66
+ artifact list. Use \`${cli} make feature <name> --recipe full-slice\` when you
67
+ need a richer reference slice with policy, client helpers, workflow artifacts,
68
+ events, listener registration, jobs, and outbox wiring. After changing the Drizzle schema in
69
+ \`infra/db/schema/\`, run \`${cli} db generate\` then \`${cli} db migrate\`.
67
70
 
68
71
  ## Validation loop
69
72
 
@@ -98,7 +101,8 @@ skill-loading block.
98
101
 
99
102
  - Feature artifacts live under \`features/<feature>/\`, with tests in
100
103
  \`features/<feature>/tests/\` (not \`__tests__/\`).
101
- - Feature-specific client data-fetching helpers and hooks may live in
104
+ - Feature-specific client data-fetching helpers, query options, mutation
105
+ options, invalidation helpers, and hooks live in
102
106
  \`features/<feature>/client/\`; shared client setup stays in root \`client/\`.
103
107
  - Domain and use-case code must not import infra, providers, or React.
104
108
  - Routes must not import concrete infra.
@@ -273,6 +273,7 @@ ${cli} doctor
273
273
  \`\`\`
274
274
 
275
275
  \`make feature\` creates a contract-to-test vertical slice with Drizzle schema and repository files, so regenerate and migrate the database before running the app against the new feature.
276
+ Use \`${cli} make feature projects --recipe full-slice\` when you want a richer reference slice with policy, feature client helpers, workflow artifacts, events, listener registration, jobs, and outbox wiring.
276
277
 
277
278
  ## App map
278
279
 
@@ -58,6 +58,7 @@ export function getTemplateFiles(ctx: TemplateContext): TemplateFile[] {
58
58
  content: serverFiles.apiCatchAllRoute,
59
59
  },
60
60
  { path: "app/api/health/route.ts", content: serverFiles.healthRoute },
61
+ { path: "app/api/ready/route.ts", content: serverFiles.readyRoute },
61
62
  {
62
63
  path: "app/api/devtools/[[...path]]/route.ts",
63
64
  content: serverFiles.devtoolsRoute,
@@ -515,6 +515,33 @@ export function GET() {
515
515
  },
516
516
  );
517
517
  }
518
+ `,
519
+ readyRoute: `import { createHealthHandler } from "@beignet/core/server";
520
+ import { env } from "@/lib/env";
521
+ import { server } from "@/server";
522
+
523
+ const readiness = createHealthHandler(
524
+ server.ports,
525
+ {
526
+ checks: {
527
+ database: (ports) => ports.db.checkHealth(),
528
+ },
529
+ timeoutMs: 2000,
530
+ },
531
+ env.NODE_ENV,
532
+ );
533
+
534
+ export async function GET(request: Request) {
535
+ const response = await readiness(request);
536
+
537
+ return Response.json(response.body, {
538
+ status: response.status,
539
+ headers: {
540
+ ...response.headers,
541
+ "cache-control": "no-store",
542
+ },
543
+ });
544
+ }
518
545
  `,
519
546
  devtoolsRoute: `import { createDevtoolsRoute } from "@beignet/devtools";
520
547
  import { env } from "@/lib/env";
@@ -578,6 +605,9 @@ export default function RootLayout({ children }: { children: ReactNode }) {
578
605
  <li>
579
606
  <a href="/api/health">/api/health</a> — health check
580
607
  </li>
608
+ <li>
609
+ <a href="/api/ready">/api/ready</a> — readiness check
610
+ </li>
581
611
  <li>
582
612
  <a href="/api/openapi">/api/openapi</a> — OpenAPI document
583
613
  </li>
@@ -110,6 +110,9 @@ export default function HomePage() {
110
110
  <a className="hover:text-foreground" href="/api/health">
111
111
  Health
112
112
  </a>
113
+ <a className="hover:text-foreground" href="/api/ready">
114
+ Ready
115
+ </a>
113
116
  <a className="hover:text-foreground" href="/api/openapi">
114
117
  OpenAPI
115
118
  </a>
@@ -1032,12 +1035,41 @@ export function SettingsNav() {
1032
1035
  }
1033
1036
  `;
1034
1037
 
1038
+ const todoClientQueries = `import type { QueryClient } from "@tanstack/react-query";
1039
+ import { rq } from "@/client";
1040
+ import {
1041
+ createTodo,
1042
+ deleteTodo,
1043
+ listTodos,
1044
+ updateTodo,
1045
+ } from "@/features/todos/contracts";
1046
+
1047
+ export function listTodosQueryOptions() {
1048
+ return rq(listTodos).queryOptions();
1049
+ }
1050
+
1051
+ export function createTodoMutationOptions() {
1052
+ return rq(createTodo).mutationOptions();
1053
+ }
1054
+
1055
+ export function updateTodoMutationOptions() {
1056
+ return rq(updateTodo).mutationOptions();
1057
+ }
1058
+
1059
+ export function deleteTodoMutationOptions() {
1060
+ return rq(deleteTodo).mutationOptions();
1061
+ }
1062
+
1063
+ export function invalidateTodos(queryClient: QueryClient) {
1064
+ return rq(listTodos).invalidate(queryClient);
1065
+ }
1066
+ `;
1067
+
1035
1068
  const todoApp = `"use client";
1036
1069
 
1037
1070
  import { rootFormError } from "@beignet/react-hook-form";
1038
1071
  import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
1039
1072
  import { Trash2Icon } from "lucide-react";
1040
- import { rq } from "@/client";
1041
1073
  import { rhf } from "@/client/forms";
1042
1074
  import { Button } from "@/components/ui/button";
1043
1075
  import { Card, CardContent } from "@/components/ui/card";
@@ -1045,45 +1077,44 @@ import { Checkbox } from "@/components/ui/checkbox";
1045
1077
  import { Input } from "@/components/ui/input";
1046
1078
  import { Label } from "@/components/ui/label";
1047
1079
  import {
1048
- createTodo,
1049
- deleteTodo,
1050
- listTodos,
1051
- updateTodo,
1052
- } from "@/features/todos/contracts";
1080
+ createTodoMutationOptions,
1081
+ deleteTodoMutationOptions,
1082
+ invalidateTodos,
1083
+ listTodosQueryOptions,
1084
+ updateTodoMutationOptions,
1085
+ } from "@/features/todos/client/queries";
1086
+ import { createTodo } from "@/features/todos/contracts";
1053
1087
  import { cn } from "@/lib/utils";
1054
1088
 
1055
1089
  const createTodoForm = rhf(createTodo);
1056
1090
 
1057
1091
  export function TodoApp() {
1058
1092
  const queryClient = useQueryClient();
1059
- const todosQuery = useQuery(rq(listTodos).queryOptions());
1093
+ const todosQuery = useQuery(listTodosQueryOptions());
1060
1094
  const form = createTodoForm.useForm({
1061
1095
  defaultValues: { title: "" },
1062
1096
  });
1063
1097
 
1064
- const invalidateTodos = () => rq(listTodos).invalidate(queryClient);
1098
+ const invalidateTodoQueries = () => invalidateTodos(queryClient);
1065
1099
 
1066
- const createTodoMutation = useMutation(
1067
- rq(createTodo).mutationOptions({
1068
- onSuccess: async () => {
1069
- form.reset();
1070
- await invalidateTodos();
1071
- },
1072
- onError: (error) => {
1073
- form.setError("root", rootFormError(error, "Could not create the todo."));
1074
- },
1075
- }),
1076
- );
1077
- const updateTodoMutation = useMutation(
1078
- rq(updateTodo).mutationOptions({
1079
- onSuccess: invalidateTodos,
1080
- }),
1081
- );
1082
- const deleteTodoMutation = useMutation(
1083
- rq(deleteTodo).mutationOptions({
1084
- onSuccess: invalidateTodos,
1085
- }),
1086
- );
1100
+ const createTodoMutation = useMutation({
1101
+ ...createTodoMutationOptions(),
1102
+ onSuccess: async () => {
1103
+ form.reset();
1104
+ await invalidateTodoQueries();
1105
+ },
1106
+ onError: (error) => {
1107
+ form.setError("root", rootFormError(error, "Could not create the todo."));
1108
+ },
1109
+ });
1110
+ const updateTodoMutation = useMutation({
1111
+ ...updateTodoMutationOptions(),
1112
+ onSuccess: invalidateTodoQueries,
1113
+ });
1114
+ const deleteTodoMutation = useMutation({
1115
+ ...deleteTodoMutationOptions(),
1116
+ onSuccess: invalidateTodoQueries,
1117
+ });
1087
1118
 
1088
1119
  const onSubmit = form.handleSubmit((body) => {
1089
1120
  form.clearErrors("root");
@@ -1212,6 +1243,10 @@ export function shellTemplateFiles(ctx: TemplateContext): TemplateFile[] {
1212
1243
  { path: "components/theme-toggle.tsx", content: themeToggle },
1213
1244
  { path: "components/app-sidebar.tsx", content: appSidebar },
1214
1245
  { path: "components/settings-nav.tsx", content: settingsNav },
1246
+ {
1247
+ path: "features/todos/client/queries.ts",
1248
+ content: todoClientQueries,
1249
+ },
1215
1250
  {
1216
1251
  path: "features/todos/components/todo-app.tsx",
1217
1252
  content: todoApp,