@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.
- package/LICENSE +21 -0
- package/dist/bin.mjs +2910 -0
- package/package.json +32 -3
- package/templates/features/admin/files/src/apps/admin/app.ts +4 -0
- package/templates/features/admin/files/src/apps/admin/server.ts +5 -0
- package/templates/features/admin/files/src/modules/example/routes/admin-greeting.routes.ts +24 -0
- package/templates/features/admin/files/src/modules/example/tests/admin.test.ts +20 -0
- package/templates/features/auth/files/src/core/auth/middleware.ts +29 -0
- package/templates/features/auth/files/src/core/auth/routes/me.routes.ts +36 -0
- package/templates/features/auth/files/src/core/auth/tests/me.test.ts +25 -0
- package/templates/features/auth-orgs/files+drizzle+mysql/src/core/auth/db/organization.schema.ts +38 -0
- package/templates/features/auth-orgs/files+drizzle+postgres/src/core/auth/db/organization.schema.ts +38 -0
- package/templates/features/auth-orgs/files+prisma/prisma/models/organization.prisma +41 -0
- package/templates/features/authz/files/src/core/authz/cache.ts +31 -0
- package/templates/features/authz/files/src/core/authz/catalog.ts +85 -0
- package/templates/features/authz/files/src/core/authz/commands/grant-role.ts +21 -0
- package/templates/features/authz/files/src/core/authz/commands/sync-permissions.ts +11 -0
- package/templates/features/authz/files/src/core/authz/constants.ts +28 -0
- package/templates/features/authz/files/src/core/authz/db/seed.ts +10 -0
- package/templates/features/authz/files/src/core/authz/middleware.ts +21 -0
- package/templates/features/authz/files/src/core/authz/permissions.ts +31 -0
- package/templates/features/authz/files/src/core/authz/resolver.ts +98 -0
- package/templates/features/authz/files/src/core/authz/routes/authorization.routes.ts +281 -0
- package/templates/features/authz/files/src/core/authz/services/audit.ts +24 -0
- package/templates/features/authz/files/src/core/authz/services/grants.ts +29 -0
- package/templates/features/authz/files/src/core/authz/services/members.ts +68 -0
- package/templates/features/authz/files/src/core/authz/services/roles.ts +73 -0
- package/templates/features/authz/files/src/core/authz/services/sync.ts +34 -0
- package/templates/features/authz/files/src/core/authz/system-roles.ts +9 -0
- package/templates/features/authz/files/src/core/authz/tests/authz.test.ts +146 -0
- package/templates/features/authz/files/src/core/authz/types.ts +85 -0
- package/templates/features/authz/files/src/core/authz/validators.ts +99 -0
- package/templates/features/authz/files/tests/helpers/authz.ts +30 -0
- package/templates/features/authz/files+drizzle/src/core/authz/db/store.ts +262 -0
- package/templates/features/authz/files+drizzle+mysql/src/core/authz/db/authz.schema.ts +90 -0
- package/templates/features/authz/files+drizzle+postgres/src/core/authz/db/authz.schema.ts +88 -0
- package/templates/features/authz/files+prisma/prisma/models/authz.prisma +75 -0
- package/templates/features/authz/files+prisma/src/core/authz/db/store.ts +229 -0
- package/templates/features/base/files/AGENTS.md +69 -0
- package/templates/features/base/files/CLAUDE.md +1 -0
- package/templates/features/base/files/Dockerfile +15 -0
- package/templates/features/base/files/README.md +31 -0
- package/templates/features/base/files/_github/workflows/ci.yml +16 -0
- package/templates/features/base/files/biome.template.json +20 -0
- package/templates/features/base/files/dockerignore +8 -0
- package/templates/features/base/files/gitignore +9 -0
- package/templates/features/base/files/src/apps/api/app.ts +3 -0
- package/templates/features/base/files/src/apps/api/server.ts +5 -0
- package/templates/features/base/files/src/apps/cli/index.ts +6 -0
- package/templates/features/base/files/src/core/commands/define.ts +25 -0
- package/templates/features/base/files/src/core/commands/runner.ts +54 -0
- package/templates/features/base/files/src/core/http/app.ts +52 -0
- package/templates/features/base/files/src/core/http/context.ts +18 -0
- package/templates/features/base/files/src/core/http/errors.ts +51 -0
- package/templates/features/base/files/src/core/http/health.ts +25 -0
- package/templates/features/base/files/src/core/http/middleware/error-handler.ts +36 -0
- package/templates/features/base/files/src/core/http/middleware/request-context.ts +24 -0
- package/templates/features/base/files/src/core/http/middleware/validation.ts +17 -0
- package/templates/features/base/files/src/core/http/response.ts +67 -0
- package/templates/features/base/files/src/core/http/routes.ts +28 -0
- package/templates/features/base/files/src/core/http/server.ts +15 -0
- package/templates/features/base/files/src/core/logging/logger.ts +17 -0
- package/templates/features/base/files/src/core/process/lifecycle.ts +34 -0
- package/templates/features/base/files/src/modules/example/routes/greeting.routes.ts +27 -0
- package/templates/features/base/files/src/modules/example/services/greeting.service.ts +3 -0
- package/templates/features/base/files/src/modules/example/tests/greeting.test.ts +21 -0
- package/templates/features/base/files/src/modules/example/validators/greeting.validators.ts +9 -0
- package/templates/features/base/files/tests/helpers/api.ts +54 -0
- package/templates/features/base/files/tests/setup.ts +2 -0
- package/templates/features/base/files/tsconfig.json +20 -0
- package/templates/features/base/files/tsdown.config.ts +15 -0
- package/templates/features/base/files/vitest.config.ts +16 -0
- package/templates/features/better-auth/files/src/core/auth/auth.ts +26 -0
- package/templates/features/better-auth/files/src/core/auth/db/seed.ts +24 -0
- package/templates/features/better-auth/files/src/core/auth/delivery.ts +48 -0
- package/templates/features/better-auth/files/src/core/auth/principal.ts +23 -0
- package/templates/features/better-auth/files/src/core/auth/sms.ts +14 -0
- package/templates/features/better-auth/files/tests/helpers/auth.ts +40 -0
- package/templates/features/better-auth/files+drizzle+mysql/src/core/auth/adapter.ts +15 -0
- package/templates/features/better-auth/files+drizzle+mysql/src/core/auth/db/auth.schema.ts +57 -0
- package/templates/features/better-auth/files+drizzle+postgres/src/core/auth/adapter.ts +15 -0
- package/templates/features/better-auth/files+drizzle+postgres/src/core/auth/db/auth.schema.ts +56 -0
- package/templates/features/better-auth/files+prisma/prisma/models/auth.prisma +62 -0
- package/templates/features/better-auth/files+prisma+mysql/src/core/auth/adapter.ts +4 -0
- package/templates/features/better-auth/files+prisma+postgres/src/core/auth/adapter.ts +4 -0
- package/templates/features/db/files/src/core/db/commands/migrate.ts +12 -0
- package/templates/features/db/files/src/core/db/commands/reset.ts +19 -0
- package/templates/features/db/files/src/core/db/commands/seed.ts +13 -0
- package/templates/features/db/files/src/core/db/id.ts +13 -0
- package/templates/features/db/files/src/core/db/seed.ts +14 -0
- package/templates/features/db/files/tests/global-setup.ts +27 -0
- package/templates/features/db/files/tests/helpers/database-url.ts +9 -0
- package/templates/features/db/files/tests/helpers/db.ts +7 -0
- package/templates/features/db/files+mysql+drizzle/src/core/db/admin.ts +53 -0
- package/templates/features/db/files+mysql+prisma/src/core/db/admin.ts +78 -0
- package/templates/features/db/files+postgres/src/core/db/admin.ts +50 -0
- package/templates/features/drizzle/files+mysql/drizzle.config.ts +12 -0
- package/templates/features/drizzle/files+mysql/src/core/db/client.ts +20 -0
- package/templates/features/drizzle/files+mysql/src/core/db/migrate.ts +13 -0
- package/templates/features/drizzle/files+postgres/drizzle.config.ts +12 -0
- package/templates/features/drizzle/files+postgres/src/core/db/client.ts +20 -0
- package/templates/features/drizzle/files+postgres/src/core/db/migrate.ts +13 -0
- package/templates/features/email/files/src/core/email/commands/send-test.ts +13 -0
- package/templates/features/email/files/src/core/email/send.ts +22 -0
- package/templates/features/email/files/src/core/email/tests/email.test.ts +8 -0
- package/templates/features/i18n/files/src/core/i18n/index.ts +41 -0
- package/templates/features/i18n/files/src/core/i18n/tests/i18n.test.ts +21 -0
- package/templates/features/i18n/files/src/locales/ar.json +10 -0
- package/templates/features/i18n/files/src/locales/en.json +10 -0
- package/templates/features/jobs/files/src/apps/cron/index.ts +25 -0
- package/templates/features/jobs/files/src/apps/worker/index.ts +24 -0
- package/templates/features/jobs/files/src/core/jobs/commands/enqueue.ts +13 -0
- package/templates/features/jobs/files/src/core/jobs/define.ts +37 -0
- package/templates/features/jobs/files/src/core/jobs/lock.ts +17 -0
- package/templates/features/jobs/files/src/core/jobs/process.ts +19 -0
- package/templates/features/jobs/files/src/core/jobs/queue.ts +29 -0
- package/templates/features/jobs/files/src/core/jobs/redis.ts +17 -0
- package/templates/features/jobs/files/src/modules/example/consumers/send-welcome.ts +11 -0
- package/templates/features/jobs/files/src/modules/example/schedules/heartbeat.ts +9 -0
- package/templates/features/jobs/files/src/modules/example/tests/jobs.test.ts +29 -0
- package/templates/features/keycloak/files/keycloak/realm.json +83 -0
- package/templates/features/keycloak/files/src/core/auth/commands/keycloak-token.ts +32 -0
- package/templates/features/keycloak/files/src/core/auth/keycloak.ts +58 -0
- package/templates/features/keycloak/files/src/core/auth/principal.ts +27 -0
- package/templates/features/keycloak/files/tests/helpers/auth.ts +52 -0
- package/templates/features/keycloak/files+drizzle/src/core/auth/users.ts +18 -0
- package/templates/features/keycloak/files+drizzle+mysql/src/core/auth/db/user.schema.ts +10 -0
- package/templates/features/keycloak/files+drizzle+postgres/src/core/auth/db/user.schema.ts +10 -0
- package/templates/features/keycloak/files+prisma/prisma/models/user.prisma +10 -0
- package/templates/features/keycloak/files+prisma/src/core/auth/users.ts +13 -0
- package/templates/features/prisma/files/prisma/models/.gitkeep +0 -0
- package/templates/features/prisma/files/prisma.config.ts +10 -0
- package/templates/features/prisma/files/src/core/db/migrate.ts +13 -0
- package/templates/features/prisma/files+mysql/prisma/schema.prisma +11 -0
- package/templates/features/prisma/files+mysql/src/core/db/client.ts +23 -0
- package/templates/features/prisma/files+postgres/prisma/schema.prisma +11 -0
- package/templates/features/prisma/files+postgres/src/core/db/client.ts +19 -0
- package/templates/features/storage/files/src/core/storage/commands/check.ts +18 -0
- package/templates/features/storage/files/src/core/storage/index.ts +8 -0
- package/templates/features/storage/files/src/core/storage/local.ts +34 -0
- package/templates/features/storage/files/src/core/storage/s3.ts +66 -0
- package/templates/features/storage/files/src/core/storage/storage.ts +21 -0
- package/templates/features/storage/files/src/core/storage/tests/storage.test.ts +22 -0
- package/templates/generators/command/files/src/modules/__moduleKebab__/commands/__nameKebab__.ts +11 -0
- package/templates/generators/consumer/files/src/modules/__moduleKebab__/consumers/__nameKebab__.ts +14 -0
- package/templates/generators/consumer/files/src/modules/__moduleKebab__/tests/__nameKebab__.consumer.test.ts +12 -0
- package/templates/generators/module/files/src/modules/__moduleKebab__/routes/__moduleKebab__.routes.ts +20 -0
- package/templates/generators/module/files/src/modules/__moduleKebab__/services/__moduleKebab__.service.ts +4 -0
- package/templates/generators/module/files/src/modules/__moduleKebab__/tests/__moduleKebab__.test.ts +10 -0
- package/templates/generators/module/files/src/modules/__moduleKebab__/validators/__moduleKebab__.validators.ts +5 -0
- package/templates/generators/permission/files/src/modules/__moduleKebab__/permissions/__nameKebab__.permissions.ts +18 -0
- package/templates/generators/resource/files/src/modules/__moduleKebab__/routes/__nameKebab__.routes.ts +126 -0
- package/templates/generators/resource/files/src/modules/__moduleKebab__/tests/__nameKebab__.routes.test.ts +59 -0
- package/templates/generators/resource/files/src/modules/__moduleKebab__/validators/__nameKebab__.validators.ts +30 -0
- package/templates/generators/resource/files+authz/src/modules/__moduleKebab__/permissions/__nameKebab__.permissions.ts +21 -0
- package/templates/generators/resource/files+drizzle/src/modules/__moduleKebab__/services/__nameKebab__.service.ts +78 -0
- package/templates/generators/resource/files+drizzle+mysql/src/modules/__moduleKebab__/db/__nameKebab__.schema.ts +9 -0
- package/templates/generators/resource/files+drizzle+postgres/src/modules/__moduleKebab__/db/__nameKebab__.schema.ts +9 -0
- package/templates/generators/resource/files+prisma/prisma/models/__nameKebab__.prisma +9 -0
- package/templates/generators/resource/files+prisma/src/modules/__moduleKebab__/services/__nameKebab__.service.ts +73 -0
- package/templates/generators/route/files/src/modules/__moduleKebab__/routes/__nameKebab__.routes.ts +29 -0
- package/templates/generators/route/files/src/modules/__moduleKebab__/validators/__nameKebab__.validators.ts +9 -0
- package/templates/generators/route/files+authz/src/modules/__moduleKebab__/permissions/__nameKebab__.permissions.ts +13 -0
- package/templates/generators/schedule/files/src/modules/__moduleKebab__/schedules/__nameKebab__.ts +11 -0
- package/templates/generators/schema/files+drizzle+mysql/src/modules/__moduleKebab__/db/__nameKebab__.schema.ts +9 -0
- package/templates/generators/schema/files+drizzle+postgres/src/modules/__moduleKebab__/db/__nameKebab__.schema.ts +9 -0
- package/templates/generators/schema/files+prisma/prisma/models/__nameKebab__.prisma +9 -0
- package/templates/generators/service/files/src/modules/__moduleKebab__/services/__nameKebab__.service.ts +4 -0
- package/templates/generators/service/files/src/modules/__moduleKebab__/tests/__nameKebab__.service.test.ts +8 -0
- package/templates/versions.json +34 -0
- 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
|
+
}
|
package/templates/generators/route/files/src/modules/__moduleKebab__/routes/__nameKebab__.routes.ts
ADDED
|
@@ -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,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
|
+
});
|
package/templates/generators/schedule/files/src/modules/__moduleKebab__/schedules/__nameKebab__.ts
ADDED
|
@@ -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,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