@beignet/cli 0.0.22 → 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.
@@ -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
 
@@ -1035,12 +1035,41 @@ export function SettingsNav() {
1035
1035
  }
1036
1036
  `;
1037
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
+
1038
1068
  const todoApp = `"use client";
1039
1069
 
1040
1070
  import { rootFormError } from "@beignet/react-hook-form";
1041
1071
  import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
1042
1072
  import { Trash2Icon } from "lucide-react";
1043
- import { rq } from "@/client";
1044
1073
  import { rhf } from "@/client/forms";
1045
1074
  import { Button } from "@/components/ui/button";
1046
1075
  import { Card, CardContent } from "@/components/ui/card";
@@ -1048,45 +1077,44 @@ import { Checkbox } from "@/components/ui/checkbox";
1048
1077
  import { Input } from "@/components/ui/input";
1049
1078
  import { Label } from "@/components/ui/label";
1050
1079
  import {
1051
- createTodo,
1052
- deleteTodo,
1053
- listTodos,
1054
- updateTodo,
1055
- } 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";
1056
1087
  import { cn } from "@/lib/utils";
1057
1088
 
1058
1089
  const createTodoForm = rhf(createTodo);
1059
1090
 
1060
1091
  export function TodoApp() {
1061
1092
  const queryClient = useQueryClient();
1062
- const todosQuery = useQuery(rq(listTodos).queryOptions());
1093
+ const todosQuery = useQuery(listTodosQueryOptions());
1063
1094
  const form = createTodoForm.useForm({
1064
1095
  defaultValues: { title: "" },
1065
1096
  });
1066
1097
 
1067
- const invalidateTodos = () => rq(listTodos).invalidate(queryClient);
1098
+ const invalidateTodoQueries = () => invalidateTodos(queryClient);
1068
1099
 
1069
- const createTodoMutation = useMutation(
1070
- rq(createTodo).mutationOptions({
1071
- onSuccess: async () => {
1072
- form.reset();
1073
- await invalidateTodos();
1074
- },
1075
- onError: (error) => {
1076
- form.setError("root", rootFormError(error, "Could not create the todo."));
1077
- },
1078
- }),
1079
- );
1080
- const updateTodoMutation = useMutation(
1081
- rq(updateTodo).mutationOptions({
1082
- onSuccess: invalidateTodos,
1083
- }),
1084
- );
1085
- const deleteTodoMutation = useMutation(
1086
- rq(deleteTodo).mutationOptions({
1087
- onSuccess: invalidateTodos,
1088
- }),
1089
- );
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
+ });
1090
1118
 
1091
1119
  const onSubmit = form.handleSubmit((body) => {
1092
1120
  form.clearErrors("root");
@@ -1215,6 +1243,10 @@ export function shellTemplateFiles(ctx: TemplateContext): TemplateFile[] {
1215
1243
  { path: "components/theme-toggle.tsx", content: themeToggle },
1216
1244
  { path: "components/app-sidebar.tsx", content: appSidebar },
1217
1245
  { path: "components/settings-nav.tsx", content: settingsNav },
1246
+ {
1247
+ path: "features/todos/client/queries.ts",
1248
+ content: todoClientQueries,
1249
+ },
1218
1250
  {
1219
1251
  path: "features/todos/components/todo-app.tsx",
1220
1252
  content: todoApp,