create-m5kdev 0.33.0 → 0.34.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 (147) hide show
  1. package/dist/src/catalog.cjs +21 -1
  2. package/dist/src/catalog.cjs.map +1 -1
  3. package/dist/src/catalog.d.cts +3 -1
  4. package/dist/src/create.cjs +6 -2
  5. package/dist/src/create.cjs.map +1 -1
  6. package/dist/src/doctor.cjs.map +1 -1
  7. package/dist/src/fs.cjs +10 -5
  8. package/dist/src/fs.cjs.map +1 -1
  9. package/dist/src/prompts.cjs +32 -0
  10. package/dist/src/prompts.cjs.map +1 -1
  11. package/dist/src/prompts.d.cts +7 -1
  12. package/dist/src/template.cjs +23 -4
  13. package/dist/src/template.cjs.map +1 -1
  14. package/dist/src/template.d.cts +17 -3
  15. package/dist/src/types.d.cts +11 -4
  16. package/package.json +4 -1
  17. package/templates/minimal-app/.cursor/rules/module-dto-guide.mdc +1 -1
  18. package/templates/minimal-app/.cursor/rules/module-grants-guide.mdc +3 -3
  19. package/templates/minimal-app/.cursor/rules/module-module-guide.mdc +3 -2
  20. package/templates/minimal-app/.cursor/rules/module-service-guide.mdc +1 -1
  21. package/templates/minimal-app/.dockerignore.tpl +31 -0
  22. package/templates/minimal-app/.gitignore.tpl +1 -0
  23. package/templates/minimal-app/AGENTS.md.tpl +13 -10
  24. package/templates/minimal-app/CLAUDE.md.tpl +132 -131
  25. package/templates/minimal-app/README.md.tpl +50 -19
  26. package/templates/minimal-app/apps/e2e/package.json.tpl +23 -23
  27. package/templates/minimal-app/apps/e2e/playwright.config.ts.tpl +51 -39
  28. package/templates/minimal-app/apps/e2e/playwright.expo.config.ts.tpl +38 -38
  29. package/templates/minimal-app/apps/e2e/servers.ts.tpl +136 -112
  30. package/templates/minimal-app/apps/e2e/tests/conversation.spec.ts.tpl +22 -0
  31. package/templates/minimal-app/apps/e2e/tests/email.spec.ts.tpl +47 -47
  32. package/templates/minimal-app/apps/e2e/tests/expo-helpers.ts.tpl +73 -73
  33. package/templates/minimal-app/apps/e2e/tests/expo-standard.spec.ts.tpl +517 -517
  34. package/templates/minimal-app/apps/e2e/tests/expo-waitlist.spec.ts.tpl +94 -94
  35. package/templates/minimal-app/apps/e2e/tests/files.spec.ts.tpl +35 -0
  36. package/templates/minimal-app/apps/e2e/tests/helpers.ts.tpl +289 -289
  37. package/templates/minimal-app/apps/e2e/tests/standard.spec.ts.tpl +516 -516
  38. package/templates/minimal-app/apps/e2e/tests/waitlist.spec.ts.tpl +107 -107
  39. package/templates/minimal-app/apps/e2e/tests/workflow.spec.ts.tpl +26 -0
  40. package/templates/minimal-app/apps/e2e/tsconfig.json.tpl +10 -10
  41. package/templates/minimal-app/apps/email/package.json.tpl +34 -34
  42. package/templates/minimal-app/apps/email/src/emails/trialEndingEmail.tsx.tpl +40 -0
  43. package/templates/minimal-app/apps/email/src/index.ts.tpl +7 -0
  44. package/templates/minimal-app/apps/email/src/resources.ts.tpl +72 -65
  45. package/templates/minimal-app/apps/expo/app.json.tpl +36 -36
  46. package/templates/minimal-app/apps/expo/eslint.config.js.tpl +8 -8
  47. package/templates/minimal-app/apps/expo/metro.config.js.tpl +16 -16
  48. package/templates/minimal-app/apps/expo/src/app/_layout.tsx.tpl +31 -31
  49. package/templates/minimal-app/apps/expo/src/app/claim-account.tsx.tpl +151 -151
  50. package/templates/minimal-app/apps/expo/src/app/forgot-password.tsx.tpl +53 -53
  51. package/templates/minimal-app/apps/expo/src/app/index.tsx.tpl +8 -8
  52. package/templates/minimal-app/apps/expo/src/app/login.tsx.tpl +71 -71
  53. package/templates/minimal-app/apps/expo/src/app/logout.tsx.tpl +19 -19
  54. package/templates/minimal-app/apps/expo/src/app/organization/accept-invitation.tsx.tpl +85 -85
  55. package/templates/minimal-app/apps/expo/src/app/posts.tsx.tpl +40 -40
  56. package/templates/minimal-app/apps/expo/src/app/reset-password.tsx.tpl +75 -75
  57. package/templates/minimal-app/apps/expo/src/app/signup.tsx.tpl +193 -193
  58. package/templates/minimal-app/apps/expo/src/components/AuthScaffold.tsx.tpl +34 -34
  59. package/templates/minimal-app/apps/expo/src/components/FormTextField.tsx.tpl +37 -37
  60. package/templates/minimal-app/apps/expo/src/components/LoadingScreen.tsx.tpl +10 -10
  61. package/templates/minimal-app/apps/expo/src/components/StatusText.tsx.tpl +22 -22
  62. package/templates/minimal-app/apps/expo/src/config.ts.tpl +9 -9
  63. package/templates/minimal-app/apps/expo/src/global.css.tpl +11 -11
  64. package/templates/minimal-app/apps/expo/src/lib/trpc.ts.tpl +20 -20
  65. package/templates/minimal-app/apps/expo/tsconfig.json.tpl +11 -11
  66. package/templates/minimal-app/apps/expo/uniwind-env.d.ts.tpl +1 -1
  67. package/templates/minimal-app/apps/landing/.env.production.example.tpl +7 -0
  68. package/templates/minimal-app/apps/landing/Dockerfile.tpl +39 -0
  69. package/templates/minimal-app/apps/landing/fly.toml.tpl +20 -0
  70. package/templates/minimal-app/apps/landing/index.html.tpl +35 -0
  71. package/templates/minimal-app/apps/landing/package.json.tpl +34 -0
  72. package/templates/minimal-app/apps/landing/scripts/fly-deploy.mjs.tpl +75 -0
  73. package/templates/minimal-app/apps/landing/scripts/fly-secrets.mjs.tpl +31 -0
  74. package/templates/minimal-app/apps/landing/src/App.tsx.tpl +12 -0
  75. package/templates/minimal-app/apps/landing/src/LandingPage.tsx.tpl +37 -0
  76. package/templates/minimal-app/apps/landing/src/index.css.tpl +24 -0
  77. package/templates/minimal-app/apps/landing/src/main.tsx.tpl +16 -0
  78. package/templates/minimal-app/apps/landing/src/vite-env.d.ts.tpl +11 -0
  79. package/templates/minimal-app/apps/landing/tsconfig.json.tpl +12 -0
  80. package/templates/minimal-app/apps/landing/vite.config.ts.tpl +25 -0
  81. package/templates/minimal-app/apps/server/AGENTS.md.tpl +54 -46
  82. package/templates/minimal-app/apps/server/{drizzle/seed.e2e.ts.tpl → db.e2e.ts.tpl} +57 -40
  83. package/templates/minimal-app/apps/server/{drizzle/seed.ts.tpl → db.ts.tpl} +27 -20
  84. package/templates/minimal-app/apps/server/drizzle/0003_silly_the_liberteens.sql +27 -0
  85. package/templates/minimal-app/apps/server/drizzle/meta/0000_snapshot.json.tpl +56 -166
  86. package/templates/minimal-app/apps/server/drizzle/meta/0001_snapshot.json.tpl +1796 -1910
  87. package/templates/minimal-app/apps/server/drizzle/meta/0002_snapshot.json.tpl +1818 -1932
  88. package/templates/minimal-app/apps/server/drizzle/meta/0003_snapshot.json.tpl +2137 -0
  89. package/templates/minimal-app/apps/server/drizzle/meta/_journal.json.tpl +8 -1
  90. package/templates/minimal-app/apps/server/drizzle.config.ts.tpl +3 -33
  91. package/templates/minimal-app/apps/server/package.json.tpl +5 -3
  92. package/templates/minimal-app/apps/server/src/app.ts.tpl +36 -0
  93. package/templates/minimal-app/apps/server/src/modules/conversation/conversation.mastra.ts.tpl +26 -0
  94. package/templates/minimal-app/apps/server/src/modules/demo-workflow/demo-workflow.module.ts.tpl +47 -0
  95. package/templates/minimal-app/apps/server/src/modules/demo-workflow/demo-workflow.service.ts.tpl +43 -0
  96. package/templates/minimal-app/apps/server/src/modules/demo-workflow/demo-workflow.trpc.ts.tpl +16 -0
  97. package/templates/minimal-app/apps/server/src/modules/posts/posts.db.ts.tpl +28 -28
  98. package/templates/minimal-app/apps/server/src/modules/posts/posts.grants.ts.tpl +28 -28
  99. package/templates/minimal-app/apps/server/src/modules/posts/posts.module.ts.tpl +54 -54
  100. package/templates/minimal-app/apps/server/src/modules/posts/posts.repository.ts.tpl +67 -67
  101. package/templates/minimal-app/apps/server/src/modules/posts/posts.service.ts.tpl +116 -116
  102. package/templates/minimal-app/apps/server/src/modules/posts/posts.trpc.ts.tpl +37 -37
  103. package/templates/minimal-app/apps/server/src/modules/test-harness/test-harness.module.ts.tpl +279 -279
  104. package/templates/minimal-app/apps/server/src/schema.ts.tpl +31 -20
  105. package/templates/minimal-app/apps/server/src/types.ts.tpl +12 -12
  106. package/templates/minimal-app/apps/server/tsconfig.json.tpl +1 -1
  107. package/templates/minimal-app/apps/server/tsup.config.ts.tpl +23 -9
  108. package/templates/minimal-app/apps/shared/.env.example.tpl +5 -0
  109. package/templates/minimal-app/apps/shared/.env.production.example.tpl +23 -0
  110. package/templates/minimal-app/apps/shared/.env.tpl +5 -0
  111. package/templates/minimal-app/apps/shared/Dockerfile.tpl +48 -0
  112. package/templates/minimal-app/apps/shared/fly.toml.tpl +24 -0
  113. package/templates/minimal-app/apps/shared/package.json.tpl +25 -24
  114. package/templates/minimal-app/apps/shared/scripts/fly-deploy.mjs.tpl +75 -0
  115. package/templates/minimal-app/apps/shared/scripts/fly-secrets.mjs.tpl +31 -0
  116. package/templates/minimal-app/apps/shared/src/modules/app/app.constants.ts.tpl +28 -28
  117. package/templates/minimal-app/apps/shared/src/modules/conversation/conversation.constants.ts.tpl +1 -0
  118. package/templates/minimal-app/apps/shared/src/modules/notification/notification.schema.ts.tpl +3 -3
  119. package/templates/minimal-app/apps/shared/src/modules/posts/posts.constants.ts.tpl +5 -5
  120. package/templates/minimal-app/apps/shared/src/modules/posts/posts.schema.ts.tpl +25 -25
  121. package/templates/minimal-app/apps/webapp/package.json.tpl +53 -53
  122. package/templates/minimal-app/apps/webapp/public/push-sw.js.tpl +34 -34
  123. package/templates/minimal-app/apps/webapp/src/App.tsx.tpl +46 -44
  124. package/templates/minimal-app/apps/webapp/src/Layout.tsx.tpl +96 -65
  125. package/templates/minimal-app/apps/webapp/src/Router.tsx.tpl +114 -93
  126. package/templates/minimal-app/apps/webapp/src/index.css.tpl +15 -15
  127. package/templates/minimal-app/apps/webapp/src/main.tsx.tpl +26 -26
  128. package/templates/minimal-app/apps/webapp/src/modules/conversation/ConversationRoute.tsx.tpl +36 -0
  129. package/templates/minimal-app/apps/webapp/src/modules/files/FilesRoute.tsx.tpl +88 -0
  130. package/templates/minimal-app/apps/webapp/src/modules/files/hooks/useFilesRoute.ts.tpl +50 -0
  131. package/templates/minimal-app/apps/webapp/src/modules/workflows/WorkflowsRoute.tsx.tpl +97 -0
  132. package/templates/minimal-app/apps/webapp/src/modules/workflows/hooks/useWorkflowsRoute.ts.tpl +64 -0
  133. package/templates/minimal-app/apps/webapp/src/utils/i18n.ts.tpl +13 -13
  134. package/templates/minimal-app/apps/webapp/src/utils/trpc.ts.tpl +10 -10
  135. package/templates/minimal-app/apps/webapp/src/vite-env.d.ts.tpl +1 -1
  136. package/templates/minimal-app/apps/webapp/translations/en/app.json.tpl +7 -7
  137. package/templates/minimal-app/apps/webapp/translations/en/{{APP_SLUG}}.json.tpl +193 -135
  138. package/templates/minimal-app/apps/webapp/tsconfig.json.tpl +17 -17
  139. package/templates/minimal-app/apps/webapp/vite.config.ts.tpl +31 -31
  140. package/templates/minimal-app/biome.json.tpl +17 -12
  141. package/templates/minimal-app/package.json.tpl +6 -2
  142. package/templates/minimal-app/pnpm-workspace.yaml.tpl +14 -7
  143. package/templates/minimal-app/template.manifest.json +92 -2
  144. package/templates/minimal-app/apps/server/drizzle/db.ts.tpl +0 -26
  145. package/templates/minimal-app/apps/server/drizzle/guard.ts.tpl +0 -36
  146. package/templates/minimal-app/apps/server/drizzle/reset.ts.tpl +0 -40
  147. package/templates/minimal-app/apps/server/drizzle/sync.ts.tpl +0 -16
@@ -1,116 +1,116 @@
1
- import { BasePermissionService } from "@m5kdev/backend/modules/base/base.service";
2
- import { serializeSpanValue, withSpan } from "@m5kdev/backend/utils/telemetry";
3
- import type { Context } from "@m5kdev/backend/utils/trpc";
4
- import { err, ok } from "neverthrow";
5
- import { postSchemas } from "./posts.dto";
6
- import type { PostsRepository } from "./posts.repository";
7
- import { createExcerpt, slugify } from "./posts.utils";
8
-
9
- export class PostsService extends BasePermissionService<
10
- { posts: PostsRepository },
11
- Record<string, never>,
12
- Context
13
- > {
14
- readonly list = this.procedure("list")
15
- .input(postSchemas.input.list)
16
- .output(postSchemas.output.list)
17
- .requireAuth("organization")
18
- .addContextFilter(["organization"])
19
- .handle(async ({ input }) => {
20
- return withSpan(
21
- {
22
- name: "posts.list.query",
23
- attributes: { input: serializeSpanValue(input) },
24
- },
25
- (span) => {
26
- span.addEvent("span started");
27
- return this.repository.posts.queryList(input, {
28
- globalSearchColumns: ["title", "excerpt", "content"],
29
- });
30
- }
31
- );
32
- });
33
-
34
- readonly create = this.procedure("create")
35
- .requireAuth("organization")
36
- .input(postSchemas.input.create)
37
- .output(postSchemas.output.single)
38
- .access({
39
- action: "write",
40
- })
41
- .handle(async ({ input, ctx }) => {
42
- const uniqueSlug = await this.repository.posts.resolveUniqueSlug({
43
- candidate: slugify(input.slug ?? input.title),
44
- });
45
- if (uniqueSlug.isErr()) {
46
- return err(uniqueSlug.error);
47
- }
48
-
49
- return this.repository.posts.create({
50
- authorUserId: ctx.user.id,
51
- memberId: ctx.actor.memberId ?? null,
52
- organizationId: ctx.session.activeOrganizationId ?? null,
53
- teamId: ctx.session.activeTeamId ?? null,
54
- title: input.title.trim(),
55
- slug: uniqueSlug.value,
56
- excerpt: createExcerpt(input.excerpt, input.content),
57
- content: input.content.trim(),
58
- status: "draft",
59
- });
60
- });
61
-
62
- readonly update = this.procedure("update")
63
- .requireAuth("organization")
64
- .input(postSchemas.input.update)
65
- .output(postSchemas.output.single)
66
- .loadResource("post", ({ input }) => this.repository.posts.findById(input.id))
67
- .access({
68
- action: "write",
69
- entityStep: "post",
70
- })
71
- .handle(async ({ input, state }) => {
72
- const content = input.content?.trim() ?? state.post.content;
73
-
74
- return this.repository.posts.update({
75
- id: input.id,
76
- title: input.title ? input.title.trim() : state.post.title,
77
- excerpt: createExcerpt(input.excerpt, content),
78
- content: content.trim(),
79
- });
80
- });
81
-
82
- readonly publish = this.procedure("publish")
83
- .input(postSchemas.input.publish)
84
- .output(postSchemas.output.single)
85
- .requireAuth("organization")
86
- .loadResource("post", ({ input }) => this.repository.posts.findById(input.id))
87
- .access({
88
- action: "publish",
89
- entityStep: "post",
90
- })
91
- .handle(({ input, state }) => {
92
- return this.repository.posts.update({
93
- id: input.id,
94
- status: "published",
95
- publishedAt: state.post?.publishedAt ?? new Date(),
96
- });
97
- });
98
-
99
- readonly softDelete = this.procedure("softDelete")
100
- .input(postSchemas.input.delete)
101
- .output(postSchemas.output.uuid)
102
- .requireAuth("organization")
103
- .loadResource("post", ({ input }) => this.repository.posts.findById(input.id))
104
- .access({
105
- action: "delete",
106
- entityStep: "post",
107
- })
108
- .handle(async ({ input }) => {
109
- const updated = await this.repository.posts.update({
110
- id: input.id,
111
- deletedAt: new Date(),
112
- });
113
- if (updated.isErr()) return err(updated.error);
114
- return ok({ id: updated.value.id });
115
- });
116
- }
1
+ import { BasePermissionService } from "@m5kdev/backend/modules/base/base.service";
2
+ import { serializeSpanValue, withSpan } from "@m5kdev/backend/utils/telemetry";
3
+ import type { Context } from "@m5kdev/backend/utils/trpc";
4
+ import { err, ok } from "neverthrow";
5
+ import { postSchemas } from "./posts.dto";
6
+ import type { PostsRepository } from "./posts.repository";
7
+ import { createExcerpt, slugify } from "./posts.utils";
8
+
9
+ export class PostsService extends BasePermissionService<
10
+ { posts: PostsRepository },
11
+ Record<string, never>,
12
+ Context
13
+ > {
14
+ readonly list = this.procedure("list")
15
+ .input(postSchemas.input.list)
16
+ .output(postSchemas.output.list)
17
+ .requireAuth("organization")
18
+ .addContextFilter(["organization"])
19
+ .handle(async ({ input }) => {
20
+ return withSpan(
21
+ {
22
+ name: "posts.list.query",
23
+ attributes: { input: serializeSpanValue(input) },
24
+ },
25
+ (span) => {
26
+ span.addEvent("span started");
27
+ return this.repository.posts.queryList(input, {
28
+ globalSearchColumns: ["title", "excerpt", "content"],
29
+ });
30
+ }
31
+ );
32
+ });
33
+
34
+ readonly create = this.procedure("create")
35
+ .requireAuth("organization")
36
+ .input(postSchemas.input.create)
37
+ .output(postSchemas.output.single)
38
+ .access({
39
+ action: "write",
40
+ })
41
+ .handle(async ({ input, ctx }) => {
42
+ const uniqueSlug = await this.repository.posts.resolveUniqueSlug({
43
+ candidate: slugify(input.slug ?? input.title),
44
+ });
45
+ if (uniqueSlug.isErr()) {
46
+ return err(uniqueSlug.error);
47
+ }
48
+
49
+ return this.repository.posts.create({
50
+ authorUserId: ctx.user.id,
51
+ memberId: ctx.actor.memberId ?? null,
52
+ organizationId: ctx.session.activeOrganizationId ?? null,
53
+ teamId: ctx.session.activeTeamId ?? null,
54
+ title: input.title.trim(),
55
+ slug: uniqueSlug.value,
56
+ excerpt: createExcerpt(input.excerpt, input.content),
57
+ content: input.content.trim(),
58
+ status: "draft",
59
+ });
60
+ });
61
+
62
+ readonly update = this.procedure("update")
63
+ .requireAuth("organization")
64
+ .input(postSchemas.input.update)
65
+ .output(postSchemas.output.single)
66
+ .loadResource("post", ({ input }) => this.repository.posts.findById(input.id))
67
+ .access({
68
+ action: "write",
69
+ entityStep: "post",
70
+ })
71
+ .handle(async ({ input, state }) => {
72
+ const content = input.content?.trim() ?? state.post.content;
73
+
74
+ return this.repository.posts.update({
75
+ id: input.id,
76
+ title: input.title ? input.title.trim() : state.post.title,
77
+ excerpt: createExcerpt(input.excerpt, content),
78
+ content: content.trim(),
79
+ });
80
+ });
81
+
82
+ readonly publish = this.procedure("publish")
83
+ .input(postSchemas.input.publish)
84
+ .output(postSchemas.output.single)
85
+ .requireAuth("organization")
86
+ .loadResource("post", ({ input }) => this.repository.posts.findById(input.id))
87
+ .access({
88
+ action: "publish",
89
+ entityStep: "post",
90
+ })
91
+ .handle(({ input, state }) => {
92
+ return this.repository.posts.update({
93
+ id: input.id,
94
+ status: "published",
95
+ publishedAt: state.post?.publishedAt ?? new Date(),
96
+ });
97
+ });
98
+
99
+ readonly softDelete = this.procedure("softDelete")
100
+ .input(postSchemas.input.delete)
101
+ .output(postSchemas.output.uuid)
102
+ .requireAuth("organization")
103
+ .loadResource("post", ({ input }) => this.repository.posts.findById(input.id))
104
+ .access({
105
+ action: "delete",
106
+ entityStep: "post",
107
+ })
108
+ .handle(async ({ input }) => {
109
+ const updated = await this.repository.posts.update({
110
+ id: input.id,
111
+ deletedAt: new Date(),
112
+ });
113
+ if (updated.isErr()) return err(updated.error);
114
+ return ok({ id: updated.value.id });
115
+ });
116
+ }
@@ -1,37 +1,37 @@
1
- import { handleTRPCResult, type TRPCMethods } from "@m5kdev/backend/utils/trpc";
2
- import { postSchemas } from "./posts.dto";
3
- import type { PostsService } from "./posts.service";
4
-
5
- export function createPostsTRPC(
6
- { router, organizationProcedure: procedure }: TRPCMethods,
7
- postsService: PostsService
8
- ) {
9
- return router({
10
- list: procedure
11
- .input(postSchemas.input.list)
12
- .output(postSchemas.output.list)
13
- .query(async ({ ctx, input }) => handleTRPCResult(await postsService.list(input ?? {}, ctx))),
14
-
15
- create: procedure
16
- .input(postSchemas.input.create)
17
- .output(postSchemas.output.single)
18
- .mutation(async ({ ctx, input }) => handleTRPCResult(await postsService.create(input, ctx))),
19
-
20
- update: procedure
21
- .input(postSchemas.input.update)
22
- .output(postSchemas.output.single)
23
- .mutation(async ({ ctx, input }) => handleTRPCResult(await postsService.update(input, ctx))),
24
-
25
- publish: procedure
26
- .input(postSchemas.input.publish)
27
- .output(postSchemas.output.single)
28
- .mutation(async ({ ctx, input }) => handleTRPCResult(await postsService.publish(input, ctx))),
29
-
30
- softDelete: procedure
31
- .input(postSchemas.input.delete)
32
- .output(postSchemas.output.uuid)
33
- .mutation(async ({ ctx, input }) =>
34
- handleTRPCResult(await postsService.softDelete(input, ctx))
35
- ),
36
- });
37
- }
1
+ import { handleTRPCResult, type TRPCMethods } from "@m5kdev/backend/utils/trpc";
2
+ import { postSchemas } from "./posts.dto";
3
+ import type { PostsService } from "./posts.service";
4
+
5
+ export function createPostsTRPC(
6
+ { router, organizationProcedure: procedure }: TRPCMethods,
7
+ postsService: PostsService
8
+ ) {
9
+ return router({
10
+ list: procedure
11
+ .input(postSchemas.input.list)
12
+ .output(postSchemas.output.list)
13
+ .query(async ({ ctx, input }) => handleTRPCResult(await postsService.list(input ?? {}, ctx))),
14
+
15
+ create: procedure
16
+ .input(postSchemas.input.create)
17
+ .output(postSchemas.output.single)
18
+ .mutation(async ({ ctx, input }) => handleTRPCResult(await postsService.create(input, ctx))),
19
+
20
+ update: procedure
21
+ .input(postSchemas.input.update)
22
+ .output(postSchemas.output.single)
23
+ .mutation(async ({ ctx, input }) => handleTRPCResult(await postsService.update(input, ctx))),
24
+
25
+ publish: procedure
26
+ .input(postSchemas.input.publish)
27
+ .output(postSchemas.output.single)
28
+ .mutation(async ({ ctx, input }) => handleTRPCResult(await postsService.publish(input, ctx))),
29
+
30
+ softDelete: procedure
31
+ .input(postSchemas.input.delete)
32
+ .output(postSchemas.output.uuid)
33
+ .mutation(async ({ ctx, input }) =>
34
+ handleTRPCResult(await postsService.softDelete(input, ctx))
35
+ ),
36
+ });
37
+ }