@tatara/cli 0.0.0-stage → 0.1.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 (171) hide show
  1. package/LICENSE +21 -0
  2. package/dist/bin.mjs +2910 -0
  3. package/package.json +32 -3
  4. package/templates/features/admin/files/src/apps/admin/app.ts +4 -0
  5. package/templates/features/admin/files/src/apps/admin/server.ts +5 -0
  6. package/templates/features/admin/files/src/modules/example/routes/admin-greeting.routes.ts +24 -0
  7. package/templates/features/admin/files/src/modules/example/tests/admin.test.ts +20 -0
  8. package/templates/features/auth/files/src/core/auth/middleware.ts +29 -0
  9. package/templates/features/auth/files/src/core/auth/routes/me.routes.ts +36 -0
  10. package/templates/features/auth/files/src/core/auth/tests/me.test.ts +25 -0
  11. package/templates/features/auth-orgs/files+drizzle+mysql/src/core/auth/db/organization.schema.ts +38 -0
  12. package/templates/features/auth-orgs/files+drizzle+postgres/src/core/auth/db/organization.schema.ts +38 -0
  13. package/templates/features/auth-orgs/files+prisma/prisma/models/organization.prisma +41 -0
  14. package/templates/features/authz/files/src/core/authz/cache.ts +31 -0
  15. package/templates/features/authz/files/src/core/authz/catalog.ts +85 -0
  16. package/templates/features/authz/files/src/core/authz/commands/grant-role.ts +21 -0
  17. package/templates/features/authz/files/src/core/authz/commands/sync-permissions.ts +11 -0
  18. package/templates/features/authz/files/src/core/authz/constants.ts +28 -0
  19. package/templates/features/authz/files/src/core/authz/db/seed.ts +10 -0
  20. package/templates/features/authz/files/src/core/authz/middleware.ts +21 -0
  21. package/templates/features/authz/files/src/core/authz/permissions.ts +31 -0
  22. package/templates/features/authz/files/src/core/authz/resolver.ts +98 -0
  23. package/templates/features/authz/files/src/core/authz/routes/authorization.routes.ts +281 -0
  24. package/templates/features/authz/files/src/core/authz/services/audit.ts +24 -0
  25. package/templates/features/authz/files/src/core/authz/services/grants.ts +29 -0
  26. package/templates/features/authz/files/src/core/authz/services/members.ts +68 -0
  27. package/templates/features/authz/files/src/core/authz/services/roles.ts +73 -0
  28. package/templates/features/authz/files/src/core/authz/services/sync.ts +34 -0
  29. package/templates/features/authz/files/src/core/authz/system-roles.ts +9 -0
  30. package/templates/features/authz/files/src/core/authz/tests/authz.test.ts +146 -0
  31. package/templates/features/authz/files/src/core/authz/types.ts +85 -0
  32. package/templates/features/authz/files/src/core/authz/validators.ts +99 -0
  33. package/templates/features/authz/files/tests/helpers/authz.ts +30 -0
  34. package/templates/features/authz/files+drizzle/src/core/authz/db/store.ts +262 -0
  35. package/templates/features/authz/files+drizzle+mysql/src/core/authz/db/authz.schema.ts +90 -0
  36. package/templates/features/authz/files+drizzle+postgres/src/core/authz/db/authz.schema.ts +88 -0
  37. package/templates/features/authz/files+prisma/prisma/models/authz.prisma +75 -0
  38. package/templates/features/authz/files+prisma/src/core/authz/db/store.ts +229 -0
  39. package/templates/features/base/files/AGENTS.md +69 -0
  40. package/templates/features/base/files/CLAUDE.md +1 -0
  41. package/templates/features/base/files/Dockerfile +15 -0
  42. package/templates/features/base/files/README.md +31 -0
  43. package/templates/features/base/files/_github/workflows/ci.yml +16 -0
  44. package/templates/features/base/files/biome.template.json +20 -0
  45. package/templates/features/base/files/dockerignore +8 -0
  46. package/templates/features/base/files/gitignore +9 -0
  47. package/templates/features/base/files/src/apps/api/app.ts +3 -0
  48. package/templates/features/base/files/src/apps/api/server.ts +5 -0
  49. package/templates/features/base/files/src/apps/cli/index.ts +6 -0
  50. package/templates/features/base/files/src/core/commands/define.ts +25 -0
  51. package/templates/features/base/files/src/core/commands/runner.ts +54 -0
  52. package/templates/features/base/files/src/core/http/app.ts +52 -0
  53. package/templates/features/base/files/src/core/http/context.ts +18 -0
  54. package/templates/features/base/files/src/core/http/errors.ts +51 -0
  55. package/templates/features/base/files/src/core/http/health.ts +25 -0
  56. package/templates/features/base/files/src/core/http/middleware/error-handler.ts +36 -0
  57. package/templates/features/base/files/src/core/http/middleware/request-context.ts +24 -0
  58. package/templates/features/base/files/src/core/http/middleware/validation.ts +17 -0
  59. package/templates/features/base/files/src/core/http/response.ts +67 -0
  60. package/templates/features/base/files/src/core/http/routes.ts +28 -0
  61. package/templates/features/base/files/src/core/http/server.ts +15 -0
  62. package/templates/features/base/files/src/core/logging/logger.ts +17 -0
  63. package/templates/features/base/files/src/core/process/lifecycle.ts +34 -0
  64. package/templates/features/base/files/src/modules/example/routes/greeting.routes.ts +27 -0
  65. package/templates/features/base/files/src/modules/example/services/greeting.service.ts +3 -0
  66. package/templates/features/base/files/src/modules/example/tests/greeting.test.ts +21 -0
  67. package/templates/features/base/files/src/modules/example/validators/greeting.validators.ts +9 -0
  68. package/templates/features/base/files/tests/helpers/api.ts +54 -0
  69. package/templates/features/base/files/tests/setup.ts +2 -0
  70. package/templates/features/base/files/tsconfig.json +20 -0
  71. package/templates/features/base/files/tsdown.config.ts +15 -0
  72. package/templates/features/base/files/vitest.config.ts +16 -0
  73. package/templates/features/better-auth/files/src/core/auth/auth.ts +26 -0
  74. package/templates/features/better-auth/files/src/core/auth/db/seed.ts +24 -0
  75. package/templates/features/better-auth/files/src/core/auth/delivery.ts +48 -0
  76. package/templates/features/better-auth/files/src/core/auth/principal.ts +23 -0
  77. package/templates/features/better-auth/files/src/core/auth/sms.ts +14 -0
  78. package/templates/features/better-auth/files/tests/helpers/auth.ts +40 -0
  79. package/templates/features/better-auth/files+drizzle+mysql/src/core/auth/adapter.ts +15 -0
  80. package/templates/features/better-auth/files+drizzle+mysql/src/core/auth/db/auth.schema.ts +57 -0
  81. package/templates/features/better-auth/files+drizzle+postgres/src/core/auth/adapter.ts +15 -0
  82. package/templates/features/better-auth/files+drizzle+postgres/src/core/auth/db/auth.schema.ts +56 -0
  83. package/templates/features/better-auth/files+prisma/prisma/models/auth.prisma +62 -0
  84. package/templates/features/better-auth/files+prisma+mysql/src/core/auth/adapter.ts +4 -0
  85. package/templates/features/better-auth/files+prisma+postgres/src/core/auth/adapter.ts +4 -0
  86. package/templates/features/db/files/src/core/db/commands/migrate.ts +12 -0
  87. package/templates/features/db/files/src/core/db/commands/reset.ts +19 -0
  88. package/templates/features/db/files/src/core/db/commands/seed.ts +13 -0
  89. package/templates/features/db/files/src/core/db/id.ts +13 -0
  90. package/templates/features/db/files/src/core/db/seed.ts +14 -0
  91. package/templates/features/db/files/tests/global-setup.ts +27 -0
  92. package/templates/features/db/files/tests/helpers/database-url.ts +9 -0
  93. package/templates/features/db/files/tests/helpers/db.ts +7 -0
  94. package/templates/features/db/files+mysql+drizzle/src/core/db/admin.ts +53 -0
  95. package/templates/features/db/files+mysql+prisma/src/core/db/admin.ts +78 -0
  96. package/templates/features/db/files+postgres/src/core/db/admin.ts +50 -0
  97. package/templates/features/drizzle/files+mysql/drizzle.config.ts +12 -0
  98. package/templates/features/drizzle/files+mysql/src/core/db/client.ts +20 -0
  99. package/templates/features/drizzle/files+mysql/src/core/db/migrate.ts +13 -0
  100. package/templates/features/drizzle/files+postgres/drizzle.config.ts +12 -0
  101. package/templates/features/drizzle/files+postgres/src/core/db/client.ts +20 -0
  102. package/templates/features/drizzle/files+postgres/src/core/db/migrate.ts +13 -0
  103. package/templates/features/email/files/src/core/email/commands/send-test.ts +13 -0
  104. package/templates/features/email/files/src/core/email/send.ts +22 -0
  105. package/templates/features/email/files/src/core/email/tests/email.test.ts +8 -0
  106. package/templates/features/i18n/files/src/core/i18n/index.ts +41 -0
  107. package/templates/features/i18n/files/src/core/i18n/tests/i18n.test.ts +21 -0
  108. package/templates/features/i18n/files/src/locales/ar.json +10 -0
  109. package/templates/features/i18n/files/src/locales/en.json +10 -0
  110. package/templates/features/jobs/files/src/apps/cron/index.ts +25 -0
  111. package/templates/features/jobs/files/src/apps/worker/index.ts +24 -0
  112. package/templates/features/jobs/files/src/core/jobs/commands/enqueue.ts +13 -0
  113. package/templates/features/jobs/files/src/core/jobs/define.ts +37 -0
  114. package/templates/features/jobs/files/src/core/jobs/lock.ts +17 -0
  115. package/templates/features/jobs/files/src/core/jobs/process.ts +19 -0
  116. package/templates/features/jobs/files/src/core/jobs/queue.ts +29 -0
  117. package/templates/features/jobs/files/src/core/jobs/redis.ts +17 -0
  118. package/templates/features/jobs/files/src/modules/example/consumers/send-welcome.ts +11 -0
  119. package/templates/features/jobs/files/src/modules/example/schedules/heartbeat.ts +9 -0
  120. package/templates/features/jobs/files/src/modules/example/tests/jobs.test.ts +29 -0
  121. package/templates/features/keycloak/files/keycloak/realm.json +83 -0
  122. package/templates/features/keycloak/files/src/core/auth/commands/keycloak-token.ts +32 -0
  123. package/templates/features/keycloak/files/src/core/auth/keycloak.ts +58 -0
  124. package/templates/features/keycloak/files/src/core/auth/principal.ts +27 -0
  125. package/templates/features/keycloak/files/tests/helpers/auth.ts +52 -0
  126. package/templates/features/keycloak/files+drizzle/src/core/auth/users.ts +18 -0
  127. package/templates/features/keycloak/files+drizzle+mysql/src/core/auth/db/user.schema.ts +10 -0
  128. package/templates/features/keycloak/files+drizzle+postgres/src/core/auth/db/user.schema.ts +10 -0
  129. package/templates/features/keycloak/files+prisma/prisma/models/user.prisma +10 -0
  130. package/templates/features/keycloak/files+prisma/src/core/auth/users.ts +13 -0
  131. package/templates/features/prisma/files/prisma/models/.gitkeep +0 -0
  132. package/templates/features/prisma/files/prisma.config.ts +10 -0
  133. package/templates/features/prisma/files/src/core/db/migrate.ts +13 -0
  134. package/templates/features/prisma/files+mysql/prisma/schema.prisma +11 -0
  135. package/templates/features/prisma/files+mysql/src/core/db/client.ts +23 -0
  136. package/templates/features/prisma/files+postgres/prisma/schema.prisma +11 -0
  137. package/templates/features/prisma/files+postgres/src/core/db/client.ts +19 -0
  138. package/templates/features/storage/files/src/core/storage/commands/check.ts +18 -0
  139. package/templates/features/storage/files/src/core/storage/index.ts +8 -0
  140. package/templates/features/storage/files/src/core/storage/local.ts +34 -0
  141. package/templates/features/storage/files/src/core/storage/s3.ts +66 -0
  142. package/templates/features/storage/files/src/core/storage/storage.ts +21 -0
  143. package/templates/features/storage/files/src/core/storage/tests/storage.test.ts +22 -0
  144. package/templates/generators/command/files/src/modules/__moduleKebab__/commands/__nameKebab__.ts +11 -0
  145. package/templates/generators/consumer/files/src/modules/__moduleKebab__/consumers/__nameKebab__.ts +14 -0
  146. package/templates/generators/consumer/files/src/modules/__moduleKebab__/tests/__nameKebab__.consumer.test.ts +12 -0
  147. package/templates/generators/module/files/src/modules/__moduleKebab__/routes/__moduleKebab__.routes.ts +20 -0
  148. package/templates/generators/module/files/src/modules/__moduleKebab__/services/__moduleKebab__.service.ts +4 -0
  149. package/templates/generators/module/files/src/modules/__moduleKebab__/tests/__moduleKebab__.test.ts +10 -0
  150. package/templates/generators/module/files/src/modules/__moduleKebab__/validators/__moduleKebab__.validators.ts +5 -0
  151. package/templates/generators/permission/files/src/modules/__moduleKebab__/permissions/__nameKebab__.permissions.ts +18 -0
  152. package/templates/generators/resource/files/src/modules/__moduleKebab__/routes/__nameKebab__.routes.ts +126 -0
  153. package/templates/generators/resource/files/src/modules/__moduleKebab__/tests/__nameKebab__.routes.test.ts +59 -0
  154. package/templates/generators/resource/files/src/modules/__moduleKebab__/validators/__nameKebab__.validators.ts +30 -0
  155. package/templates/generators/resource/files+authz/src/modules/__moduleKebab__/permissions/__nameKebab__.permissions.ts +21 -0
  156. package/templates/generators/resource/files+drizzle/src/modules/__moduleKebab__/services/__nameKebab__.service.ts +78 -0
  157. package/templates/generators/resource/files+drizzle+mysql/src/modules/__moduleKebab__/db/__nameKebab__.schema.ts +9 -0
  158. package/templates/generators/resource/files+drizzle+postgres/src/modules/__moduleKebab__/db/__nameKebab__.schema.ts +9 -0
  159. package/templates/generators/resource/files+prisma/prisma/models/__nameKebab__.prisma +9 -0
  160. package/templates/generators/resource/files+prisma/src/modules/__moduleKebab__/services/__nameKebab__.service.ts +73 -0
  161. package/templates/generators/route/files/src/modules/__moduleKebab__/routes/__nameKebab__.routes.ts +29 -0
  162. package/templates/generators/route/files/src/modules/__moduleKebab__/validators/__nameKebab__.validators.ts +9 -0
  163. package/templates/generators/route/files+authz/src/modules/__moduleKebab__/permissions/__nameKebab__.permissions.ts +13 -0
  164. package/templates/generators/schedule/files/src/modules/__moduleKebab__/schedules/__nameKebab__.ts +11 -0
  165. package/templates/generators/schema/files+drizzle+mysql/src/modules/__moduleKebab__/db/__nameKebab__.schema.ts +9 -0
  166. package/templates/generators/schema/files+drizzle+postgres/src/modules/__moduleKebab__/db/__nameKebab__.schema.ts +9 -0
  167. package/templates/generators/schema/files+prisma/prisma/models/__nameKebab__.prisma +9 -0
  168. package/templates/generators/service/files/src/modules/__moduleKebab__/services/__nameKebab__.service.ts +4 -0
  169. package/templates/generators/service/files/src/modules/__moduleKebab__/tests/__nameKebab__.service.test.ts +8 -0
  170. package/templates/versions.json +34 -0
  171. package/README.md +0 -3
@@ -0,0 +1,30 @@
1
+ import { z } from "@hono/zod-openapi";
2
+
3
+ export const __nameCamel__Schema = z
4
+ .object({
5
+ id: z.string().openapi({ example: "01920000-0000-7000-8000-000000000000" }),
6
+ name: z.string().openapi({ example: "My __nameTitle__" }),
7
+ description: z.string().nullable(),
8
+ createdAt: z.string().openapi({ format: "date-time" }),
9
+ updatedAt: z.string().openapi({ format: "date-time" }),
10
+ })
11
+ .openapi("__namePascal__");
12
+
13
+ export const create__namePascal__Schema = z
14
+ .object({
15
+ name: z.string().trim().min(1).max(200),
16
+ description: z.string().max(5000).nullable().optional(),
17
+ })
18
+ .openapi("Create__namePascal__");
19
+
20
+ export const update__namePascal__Schema = create__namePascal__Schema
21
+ .partial()
22
+ .openapi("Update__namePascal__");
23
+
24
+ export const __nameCamel__ParamsSchema = z.object({
25
+ id: z.string().min(1).openapi({ param: { name: "id", in: "path" } }),
26
+ });
27
+
28
+ export type __namePascal__ = z.infer<typeof __nameCamel__Schema>;
29
+ export type Create__namePascal__Input = z.infer<typeof create__namePascal__Schema>;
30
+ export type Update__namePascal__Input = z.infer<typeof update__namePascal__Schema>;
@@ -0,0 +1,21 @@
1
+ import { definePermissions } from "#core/authz/catalog";
2
+
3
+ export default definePermissions({
4
+ resources: {
5
+ "__nameKebab__": {
6
+ read: { scoped: false },
7
+ create: { scoped: false },
8
+ update: { scoped: false },
9
+ delete: { scoped: false },
10
+ },
11
+ },
12
+ roleGrants: {
13
+ admin: [
14
+ ["__nameKebab__", "read"],
15
+ ["__nameKebab__", "create"],
16
+ ["__nameKebab__", "update"],
17
+ ["__nameKebab__", "delete"],
18
+ ],
19
+ member: [["__nameKebab__", "read"]],
20
+ },
21
+ });
@@ -0,0 +1,78 @@
1
+ import { count, desc, eq } from "drizzle-orm";
2
+ import { db, type Executor } from "#core/db/client";
3
+ import { newId } from "#core/db/id";
4
+ import { NotFoundError } from "#core/http/errors";
5
+ import type { PaginationQuery } from "#core/http/response";
6
+ import { __namePluralCamel__ } from "#modules/__moduleKebab__/db/__nameKebab__.schema";
7
+ import type {
8
+ Create__namePascal__Input,
9
+ __namePascal__,
10
+ Update__namePascal__Input,
11
+ } from "#modules/__moduleKebab__/validators/__nameKebab__.validators";
12
+
13
+ type Row = typeof __namePluralCamel__.$inferSelect;
14
+
15
+ function to__namePascal__(row: Row): __namePascal__ {
16
+ return {
17
+ id: row.id,
18
+ name: row.name,
19
+ description: row.description,
20
+ createdAt: row.createdAt.toISOString(),
21
+ updatedAt: row.updatedAt.toISOString(),
22
+ };
23
+ }
24
+
25
+ export async function list__namePluralPascal__(
26
+ { page, pageSize }: PaginationQuery,
27
+ executor: Executor = db,
28
+ ) {
29
+ const [rows, totals] = await Promise.all([
30
+ executor
31
+ .select()
32
+ .from(__namePluralCamel__)
33
+ .orderBy(desc(__namePluralCamel__.id))
34
+ .limit(pageSize)
35
+ .offset((page - 1) * pageSize),
36
+ executor.select({ total: count() }).from(__namePluralCamel__),
37
+ ]);
38
+ return { items: rows.map(to__namePascal__), total: totals[0]?.total ?? 0 };
39
+ }
40
+
41
+ export async function get__namePascal__(id: string, executor: Executor = db): Promise<__namePascal__> {
42
+ const [row] = await executor
43
+ .select()
44
+ .from(__namePluralCamel__)
45
+ .where(eq(__namePluralCamel__.id, id))
46
+ .limit(1);
47
+ if (!row) throw new NotFoundError("__nameTitle__");
48
+ return to__namePascal__(row);
49
+ }
50
+
51
+ export async function create__namePascal__(
52
+ input: Create__namePascal__Input,
53
+ executor: Executor = db,
54
+ ): Promise<__namePascal__> {
55
+ const id = newId();
56
+ await executor
57
+ .insert(__namePluralCamel__)
58
+ .values({ id, name: input.name, description: input.description ?? null });
59
+ return get__namePascal__(id, executor);
60
+ }
61
+
62
+ export async function update__namePascal__(
63
+ id: string,
64
+ input: Update__namePascal__Input,
65
+ executor: Executor = db,
66
+ ): Promise<__namePascal__> {
67
+ await get__namePascal__(id, executor);
68
+ await executor
69
+ .update(__namePluralCamel__)
70
+ .set({ ...input, updatedAt: new Date() })
71
+ .where(eq(__namePluralCamel__.id, id));
72
+ return get__namePascal__(id, executor);
73
+ }
74
+
75
+ export async function remove__namePascal__(id: string, executor: Executor = db): Promise<void> {
76
+ await get__namePascal__(id, executor);
77
+ await executor.delete(__namePluralCamel__).where(eq(__namePluralCamel__.id, id));
78
+ }
@@ -0,0 +1,9 @@
1
+ import { mysqlTable, text, timestamp, varchar } from "drizzle-orm/mysql-core";
2
+
3
+ export const __namePluralCamel__ = mysqlTable("__namePluralSnake__", {
4
+ id: varchar({ length: 36 }).primaryKey(),
5
+ name: varchar({ length: 200 }).notNull(),
6
+ description: text(),
7
+ createdAt: timestamp({ fsp: 3, mode: "date" }).notNull().defaultNow(),
8
+ updatedAt: timestamp({ fsp: 3, mode: "date" }).notNull().defaultNow(),
9
+ });
@@ -0,0 +1,9 @@
1
+ import { pgTable, text, timestamp, uuid, varchar } from "drizzle-orm/pg-core";
2
+
3
+ export const __namePluralCamel__ = pgTable("__namePluralSnake__", {
4
+ id: uuid().primaryKey(),
5
+ name: varchar({ length: 200 }).notNull(),
6
+ description: text(),
7
+ createdAt: timestamp({ withTimezone: true, mode: "date" }).notNull().defaultNow(),
8
+ updatedAt: timestamp({ withTimezone: true, mode: "date" }).notNull().defaultNow(),
9
+ });
@@ -0,0 +1,9 @@
1
+ model __namePascal__ {
2
+ id String @id @db.VarChar(36)
3
+ name String @db.VarChar(200)
4
+ description String? @db.Text
5
+ createdAt DateTime @default(now()) @map("created_at")
6
+ updatedAt DateTime @default(now()) @updatedAt @map("updated_at")
7
+
8
+ @@map("__namePluralSnake__")
9
+ }
@@ -0,0 +1,73 @@
1
+ import { db, type Executor } from "#core/db/client";
2
+ import { newId } from "#core/db/id";
3
+ import { NotFoundError } from "#core/http/errors";
4
+ import type { PaginationQuery } from "#core/http/response";
5
+ import type {
6
+ Create__namePascal__Input,
7
+ __namePascal__,
8
+ Update__namePascal__Input,
9
+ } from "#modules/__moduleKebab__/validators/__nameKebab__.validators";
10
+
11
+ interface Row {
12
+ id: string;
13
+ name: string;
14
+ description: string | null;
15
+ createdAt: Date;
16
+ updatedAt: Date;
17
+ }
18
+
19
+ function to__namePascal__(row: Row): __namePascal__ {
20
+ return {
21
+ id: row.id,
22
+ name: row.name,
23
+ description: row.description,
24
+ createdAt: row.createdAt.toISOString(),
25
+ updatedAt: row.updatedAt.toISOString(),
26
+ };
27
+ }
28
+
29
+ export async function list__namePluralPascal__(
30
+ { page, pageSize }: PaginationQuery,
31
+ executor: Executor = db,
32
+ ) {
33
+ const [rows, total] = await Promise.all([
34
+ executor.__nameCamel__.findMany({
35
+ orderBy: { id: "desc" },
36
+ skip: (page - 1) * pageSize,
37
+ take: pageSize,
38
+ }),
39
+ executor.__nameCamel__.count(),
40
+ ]);
41
+ return { items: rows.map(to__namePascal__), total };
42
+ }
43
+
44
+ export async function get__namePascal__(id: string, executor: Executor = db): Promise<__namePascal__> {
45
+ const row = await executor.__nameCamel__.findUnique({ where: { id } });
46
+ if (!row) throw new NotFoundError("__nameTitle__");
47
+ return to__namePascal__(row);
48
+ }
49
+
50
+ export async function create__namePascal__(
51
+ input: Create__namePascal__Input,
52
+ executor: Executor = db,
53
+ ): Promise<__namePascal__> {
54
+ const row = await executor.__nameCamel__.create({
55
+ data: { id: newId(), name: input.name, description: input.description ?? null },
56
+ });
57
+ return to__namePascal__(row);
58
+ }
59
+
60
+ export async function update__namePascal__(
61
+ id: string,
62
+ input: Update__namePascal__Input,
63
+ executor: Executor = db,
64
+ ): Promise<__namePascal__> {
65
+ await get__namePascal__(id, executor);
66
+ const row = await executor.__nameCamel__.update({ where: { id }, data: input });
67
+ return to__namePascal__(row);
68
+ }
69
+
70
+ export async function remove__namePascal__(id: string, executor: Executor = db): Promise<void> {
71
+ await get__namePascal__(id, executor);
72
+ await executor.__nameCamel__.delete({ where: { id } });
73
+ }
@@ -0,0 +1,29 @@
1
+ import { createRoute } from "@hono/zod-openapi";
2
+ import { errorResponses, jsonContent, success, successSchema } from "#core/http/response";
3
+ import { createRouter, defineRoutes } from "#core/http/routes";
4
+ // tatara:slot imports
5
+ import {
6
+ __nameCamel__QuerySchema,
7
+ __nameCamel__ResponseSchema,
8
+ } from "#modules/__moduleKebab__/validators/__nameKebab__.validators";
9
+
10
+ const router = createRouter();
11
+
12
+ router.openapi(
13
+ createRoute({
14
+ method: "get",
15
+ path: "/",
16
+ tags: ["__modulePascal__"],
17
+ summary: "__nameTitle__",
18
+ // tatara:slot guard-read
19
+ request: { query: __nameCamel__QuerySchema },
20
+ responses: {
21
+ 200: jsonContent(successSchema(__nameCamel__ResponseSchema), "__nameTitle__"),
22
+ ...errorResponses(400),
23
+ // tatara:slot auth-errors
24
+ },
25
+ }),
26
+ (c) => c.json(success({ message: `__nameKebab__: ${c.req.valid("query").q ?? "ok"}` }), 200),
27
+ );
28
+
29
+ export default defineRoutes({ app: "api", basePath: "/__nameKebab__", router });
@@ -0,0 +1,9 @@
1
+ import { z } from "@hono/zod-openapi";
2
+
3
+ export const __nameCamel__QuerySchema = z.object({
4
+ q: z.string().max(100).optional(),
5
+ });
6
+
7
+ export const __nameCamel__ResponseSchema = z
8
+ .object({ message: z.string() })
9
+ .openapi("__namePascal__Response");
@@ -0,0 +1,13 @@
1
+ import { definePermissions } from "#core/authz/catalog";
2
+
3
+ export default definePermissions({
4
+ resources: {
5
+ "__nameKebab__": {
6
+ read: { scoped: false },
7
+ },
8
+ },
9
+ roleGrants: {
10
+ admin: [["__nameKebab__", "read"]],
11
+ member: [["__nameKebab__", "read"]],
12
+ },
13
+ });
@@ -0,0 +1,11 @@
1
+ import { defineSchedule } from "#core/jobs/define";
2
+
3
+ export default defineSchedule({
4
+ name: "__moduleKebab__.__nameKebab__",
5
+ // every day at 02:00 UTC
6
+ cron: "0 2 * * *",
7
+ lockTtlMs: 10 * 60_000,
8
+ async run({ logger }) {
9
+ logger.info("__moduleKebab__.__nameKebab__ ran");
10
+ },
11
+ });
@@ -0,0 +1,9 @@
1
+ import { mysqlTable, text, timestamp, varchar } from "drizzle-orm/mysql-core";
2
+
3
+ export const __namePluralCamel__ = mysqlTable("__namePluralSnake__", {
4
+ id: varchar({ length: 36 }).primaryKey(),
5
+ name: varchar({ length: 200 }).notNull(),
6
+ description: text(),
7
+ createdAt: timestamp({ fsp: 3, mode: "date" }).notNull().defaultNow(),
8
+ updatedAt: timestamp({ fsp: 3, mode: "date" }).notNull().defaultNow(),
9
+ });
@@ -0,0 +1,9 @@
1
+ import { pgTable, text, timestamp, uuid, varchar } from "drizzle-orm/pg-core";
2
+
3
+ export const __namePluralCamel__ = pgTable("__namePluralSnake__", {
4
+ id: uuid().primaryKey(),
5
+ name: varchar({ length: 200 }).notNull(),
6
+ description: text(),
7
+ createdAt: timestamp({ withTimezone: true, mode: "date" }).notNull().defaultNow(),
8
+ updatedAt: timestamp({ withTimezone: true, mode: "date" }).notNull().defaultNow(),
9
+ });
@@ -0,0 +1,9 @@
1
+ model __namePascal__ {
2
+ id String @id @db.VarChar(36)
3
+ name String @db.VarChar(200)
4
+ description String? @db.Text
5
+ createdAt DateTime @default(now()) @map("created_at")
6
+ updatedAt DateTime @default(now()) @updatedAt @map("updated_at")
7
+
8
+ @@map("__namePluralSnake__")
9
+ }
@@ -0,0 +1,4 @@
1
+ /** __nameTitle__: business logic for the __moduleKebab__ module. */
2
+ export function __nameCamel__(input: { value: string }): { result: string } {
3
+ return { result: input.value };
4
+ }
@@ -0,0 +1,8 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { __nameCamel__ } from "#modules/__moduleKebab__/services/__nameKebab__.service";
3
+
4
+ describe("__nameCamel__", () => {
5
+ it("returns a result", () => {
6
+ expect(__nameCamel__({ value: "x" })).toEqual({ result: "x" });
7
+ });
8
+ });
@@ -0,0 +1,34 @@
1
+ {
2
+ "hono": "4.13.13",
3
+ "@hono/node-server": "2.1.5",
4
+ "@hono/zod-openapi": "1.6.3",
5
+ "@scalar/hono-api-reference": "0.12.12",
6
+ "zod": "4.6.7",
7
+ "@t3-oss/env-core": "0.13.11",
8
+ "pino": "10.4.0",
9
+ "pino-pretty": "13.2.0",
10
+ "typescript": "7.0.2",
11
+ "@types/node": "24.19.2",
12
+ "vitest": "5.0.4",
13
+ "tsdown": "0.23.1",
14
+ "@biomejs/biome": "2.5.15",
15
+ "pg": "8.23.1",
16
+ "@types/pg": "8.23.1",
17
+ "mysql2": "3.24.6",
18
+ "mariadb": "3.4.5",
19
+ "drizzle-orm": "0.45.4",
20
+ "drizzle-kit": "0.31.11",
21
+ "prisma": "7.10.0",
22
+ "@prisma/client": "7.10.0",
23
+ "@prisma/adapter-pg": "7.10.0",
24
+ "@prisma/adapter-mariadb": "7.10.0",
25
+ "better-auth": "1.7.8",
26
+ "jose": "6.2.12",
27
+ "bullmq": "6.3.15",
28
+ "ioredis": "6.0.0",
29
+ "croner": "10.0.1",
30
+ "@aws-sdk/client-s3": "3.1152.0",
31
+ "@aws-sdk/s3-request-presigner": "3.1152.0",
32
+ "nodemailer": "10.1.1",
33
+ "@types/nodemailer": "8.0.2"
34
+ }
package/README.md DELETED
@@ -1,3 +0,0 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.