archetype-engine 2.0.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/README.md +241 -0
- package/dist/src/ai/adapters/anthropic.d.ts +31 -0
- package/dist/src/ai/adapters/anthropic.d.ts.map +1 -0
- package/dist/src/ai/adapters/anthropic.js +75 -0
- package/dist/src/ai/adapters/openai.d.ts +33 -0
- package/dist/src/ai/adapters/openai.d.ts.map +1 -0
- package/dist/src/ai/adapters/openai.js +120 -0
- package/dist/src/ai/adapters/vercel.d.ts +434 -0
- package/dist/src/ai/adapters/vercel.d.ts.map +1 -0
- package/dist/src/ai/adapters/vercel.js +162 -0
- package/dist/src/ai/index.d.ts +492 -0
- package/dist/src/ai/index.d.ts.map +1 -0
- package/dist/src/ai/index.js +71 -0
- package/dist/src/ai/state.d.ts +13 -0
- package/dist/src/ai/state.d.ts.map +1 -0
- package/dist/src/ai/state.js +215 -0
- package/dist/src/ai/tools.d.ts +13 -0
- package/dist/src/ai/tools.d.ts.map +1 -0
- package/dist/src/ai/tools.js +257 -0
- package/dist/src/ai/types.d.ts +196 -0
- package/dist/src/ai/types.d.ts.map +1 -0
- package/dist/src/ai/types.js +9 -0
- package/dist/src/cli.d.ts +3 -0
- package/dist/src/cli.d.ts.map +1 -0
- package/dist/src/cli.js +540 -0
- package/dist/src/core/utils.d.ts +27 -0
- package/dist/src/core/utils.d.ts.map +1 -0
- package/dist/src/core/utils.js +56 -0
- package/dist/src/entity.d.ts +165 -0
- package/dist/src/entity.d.ts.map +1 -0
- package/dist/src/entity.js +108 -0
- package/dist/src/fields.d.ts +207 -0
- package/dist/src/fields.d.ts.map +1 -0
- package/dist/src/fields.js +291 -0
- package/dist/src/generators/erd-ir.d.ts +10 -0
- package/dist/src/generators/erd-ir.d.ts.map +1 -0
- package/dist/src/generators/erd-ir.js +119 -0
- package/dist/src/index.d.ts +51 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +101 -0
- package/dist/src/init/dependencies.d.ts +31 -0
- package/dist/src/init/dependencies.d.ts.map +1 -0
- package/dist/src/init/dependencies.js +101 -0
- package/dist/src/init/entity-templates.d.ts +42 -0
- package/dist/src/init/entity-templates.d.ts.map +1 -0
- package/dist/src/init/entity-templates.js +367 -0
- package/dist/src/init/index.d.ts +10 -0
- package/dist/src/init/index.d.ts.map +1 -0
- package/dist/src/init/index.js +250 -0
- package/dist/src/init/prompts.d.ts +11 -0
- package/dist/src/init/prompts.d.ts.map +1 -0
- package/dist/src/init/prompts.js +275 -0
- package/dist/src/init/templates.d.ts +24 -0
- package/dist/src/init/templates.d.ts.map +1 -0
- package/dist/src/init/templates.js +587 -0
- package/dist/src/json/index.d.ts +11 -0
- package/dist/src/json/index.d.ts.map +1 -0
- package/dist/src/json/index.js +26 -0
- package/dist/src/json/parser.d.ts +61 -0
- package/dist/src/json/parser.d.ts.map +1 -0
- package/dist/src/json/parser.js +309 -0
- package/dist/src/json/types.d.ts +275 -0
- package/dist/src/json/types.d.ts.map +1 -0
- package/dist/src/json/types.js +10 -0
- package/dist/src/manifest.d.ts +147 -0
- package/dist/src/manifest.d.ts.map +1 -0
- package/dist/src/manifest.js +104 -0
- package/dist/src/relations.d.ts +96 -0
- package/dist/src/relations.d.ts.map +1 -0
- package/dist/src/relations.js +108 -0
- package/dist/src/source.d.ts +93 -0
- package/dist/src/source.d.ts.map +1 -0
- package/dist/src/source.js +89 -0
- package/dist/src/template/context.d.ts +34 -0
- package/dist/src/template/context.d.ts.map +1 -0
- package/dist/src/template/context.js +31 -0
- package/dist/src/template/index.d.ts +6 -0
- package/dist/src/template/index.d.ts.map +1 -0
- package/dist/src/template/index.js +12 -0
- package/dist/src/template/registry.d.ts +18 -0
- package/dist/src/template/registry.d.ts.map +1 -0
- package/dist/src/template/registry.js +89 -0
- package/dist/src/template/runner.d.ts +9 -0
- package/dist/src/template/runner.d.ts.map +1 -0
- package/dist/src/template/runner.js +125 -0
- package/dist/src/template/types.d.ts +73 -0
- package/dist/src/template/types.d.ts.map +1 -0
- package/dist/src/template/types.js +3 -0
- package/dist/src/templates/nextjs-drizzle-trpc/generators/api.d.ts +22 -0
- package/dist/src/templates/nextjs-drizzle-trpc/generators/api.d.ts.map +1 -0
- package/dist/src/templates/nextjs-drizzle-trpc/generators/api.js +866 -0
- package/dist/src/templates/nextjs-drizzle-trpc/generators/auth.d.ts +20 -0
- package/dist/src/templates/nextjs-drizzle-trpc/generators/auth.d.ts.map +1 -0
- package/dist/src/templates/nextjs-drizzle-trpc/generators/auth.js +273 -0
- package/dist/src/templates/nextjs-drizzle-trpc/generators/crud-hooks.d.ts +22 -0
- package/dist/src/templates/nextjs-drizzle-trpc/generators/crud-hooks.d.ts.map +1 -0
- package/dist/src/templates/nextjs-drizzle-trpc/generators/crud-hooks.js +237 -0
- package/dist/src/templates/nextjs-drizzle-trpc/generators/hooks.d.ts +30 -0
- package/dist/src/templates/nextjs-drizzle-trpc/generators/hooks.d.ts.map +1 -0
- package/dist/src/templates/nextjs-drizzle-trpc/generators/hooks.js +345 -0
- package/dist/src/templates/nextjs-drizzle-trpc/generators/i18n.d.ts +25 -0
- package/dist/src/templates/nextjs-drizzle-trpc/generators/i18n.d.ts.map +1 -0
- package/dist/src/templates/nextjs-drizzle-trpc/generators/i18n.js +199 -0
- package/dist/src/templates/nextjs-drizzle-trpc/generators/index.d.ts +8 -0
- package/dist/src/templates/nextjs-drizzle-trpc/generators/index.d.ts.map +1 -0
- package/dist/src/templates/nextjs-drizzle-trpc/generators/index.js +18 -0
- package/dist/src/templates/nextjs-drizzle-trpc/generators/schema.d.ts +22 -0
- package/dist/src/templates/nextjs-drizzle-trpc/generators/schema.d.ts.map +1 -0
- package/dist/src/templates/nextjs-drizzle-trpc/generators/schema.js +270 -0
- package/dist/src/templates/nextjs-drizzle-trpc/generators/service.d.ts +23 -0
- package/dist/src/templates/nextjs-drizzle-trpc/generators/service.d.ts.map +1 -0
- package/dist/src/templates/nextjs-drizzle-trpc/generators/service.js +304 -0
- package/dist/src/templates/nextjs-drizzle-trpc/generators/validation.d.ts +21 -0
- package/dist/src/templates/nextjs-drizzle-trpc/generators/validation.d.ts.map +1 -0
- package/dist/src/templates/nextjs-drizzle-trpc/generators/validation.js +248 -0
- package/dist/src/templates/nextjs-drizzle-trpc/index.d.ts +30 -0
- package/dist/src/templates/nextjs-drizzle-trpc/index.d.ts.map +1 -0
- package/dist/src/templates/nextjs-drizzle-trpc/index.js +71 -0
- package/dist/src/validation/index.d.ts +71 -0
- package/dist/src/validation/index.d.ts.map +1 -0
- package/dist/src/validation/index.js +314 -0
- package/package.json +86 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth.js (next-auth v5) Schema Generator
|
|
3
|
+
*
|
|
4
|
+
* Generates database schema for Auth.js/NextAuth.js authentication tables.
|
|
5
|
+
* Only runs when auth.enabled is true in the manifest.
|
|
6
|
+
*
|
|
7
|
+
* Generated files:
|
|
8
|
+
* - db/auth-schema.ts - Auth tables (users, accounts, sessions, verificationTokens)
|
|
9
|
+
*
|
|
10
|
+
* Features:
|
|
11
|
+
* - Supports SQLite, PostgreSQL, and MySQL databases
|
|
12
|
+
* - Uses official Auth.js/Drizzle adapter schema format
|
|
13
|
+
* - Includes proper foreign key references with cascade delete
|
|
14
|
+
* - Uses composite primary keys for accounts and verification tokens
|
|
15
|
+
*
|
|
16
|
+
* @module generators/auth
|
|
17
|
+
*/
|
|
18
|
+
import type { Generator } from '../../../template/types';
|
|
19
|
+
export declare const authGenerator: Generator;
|
|
20
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../../../src/templates/nextjs-drizzle-trpc/generators/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAiB,MAAM,yBAAyB,CAAA;AAuOvE,eAAO,MAAM,aAAa,EAAE,SA4B3B,CAAA"}
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Auth.js (next-auth v5) Schema Generator
|
|
4
|
+
*
|
|
5
|
+
* Generates database schema for Auth.js/NextAuth.js authentication tables.
|
|
6
|
+
* Only runs when auth.enabled is true in the manifest.
|
|
7
|
+
*
|
|
8
|
+
* Generated files:
|
|
9
|
+
* - db/auth-schema.ts - Auth tables (users, accounts, sessions, verificationTokens)
|
|
10
|
+
*
|
|
11
|
+
* Features:
|
|
12
|
+
* - Supports SQLite, PostgreSQL, and MySQL databases
|
|
13
|
+
* - Uses official Auth.js/Drizzle adapter schema format
|
|
14
|
+
* - Includes proper foreign key references with cascade delete
|
|
15
|
+
* - Uses composite primary keys for accounts and verification tokens
|
|
16
|
+
*
|
|
17
|
+
* @module generators/auth
|
|
18
|
+
*/
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.authGenerator = void 0;
|
|
21
|
+
/**
|
|
22
|
+
* Generate SQLite-specific auth schema
|
|
23
|
+
*
|
|
24
|
+
* Uses sqliteTable with integer timestamps (timestamp_ms mode).
|
|
25
|
+
*
|
|
26
|
+
* @returns SQLite auth schema as string
|
|
27
|
+
*/
|
|
28
|
+
function generateSqliteAuthSchema() {
|
|
29
|
+
return `// Auto-generated Auth.js schema for SQLite
|
|
30
|
+
// Do not edit manually - regenerate with: npx archetype generate
|
|
31
|
+
|
|
32
|
+
import {
|
|
33
|
+
integer,
|
|
34
|
+
sqliteTable,
|
|
35
|
+
text,
|
|
36
|
+
primaryKey,
|
|
37
|
+
} from 'drizzle-orm/sqlite-core'
|
|
38
|
+
import type { AdapterAccountType } from 'next-auth/adapters'
|
|
39
|
+
|
|
40
|
+
export const users = sqliteTable('user', {
|
|
41
|
+
id: text('id')
|
|
42
|
+
.primaryKey()
|
|
43
|
+
.$defaultFn(() => crypto.randomUUID()),
|
|
44
|
+
name: text('name'),
|
|
45
|
+
email: text('email').unique(),
|
|
46
|
+
emailVerified: integer('emailVerified', { mode: 'timestamp_ms' }),
|
|
47
|
+
image: text('image'),
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
export const accounts = sqliteTable(
|
|
51
|
+
'account',
|
|
52
|
+
{
|
|
53
|
+
userId: text('userId')
|
|
54
|
+
.notNull()
|
|
55
|
+
.references(() => users.id, { onDelete: 'cascade' }),
|
|
56
|
+
type: text('type').$type<AdapterAccountType>().notNull(),
|
|
57
|
+
provider: text('provider').notNull(),
|
|
58
|
+
providerAccountId: text('providerAccountId').notNull(),
|
|
59
|
+
refresh_token: text('refresh_token'),
|
|
60
|
+
access_token: text('access_token'),
|
|
61
|
+
expires_at: integer('expires_at'),
|
|
62
|
+
token_type: text('token_type'),
|
|
63
|
+
scope: text('scope'),
|
|
64
|
+
id_token: text('id_token'),
|
|
65
|
+
session_state: text('session_state'),
|
|
66
|
+
},
|
|
67
|
+
(account) => ({
|
|
68
|
+
compoundKey: primaryKey({ columns: [account.provider, account.providerAccountId] }),
|
|
69
|
+
})
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
export const sessions = sqliteTable('session', {
|
|
73
|
+
sessionToken: text('sessionToken').primaryKey(),
|
|
74
|
+
userId: text('userId')
|
|
75
|
+
.notNull()
|
|
76
|
+
.references(() => users.id, { onDelete: 'cascade' }),
|
|
77
|
+
expires: integer('expires', { mode: 'timestamp_ms' }).notNull(),
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
export const verificationTokens = sqliteTable(
|
|
81
|
+
'verificationToken',
|
|
82
|
+
{
|
|
83
|
+
identifier: text('identifier').notNull(),
|
|
84
|
+
token: text('token').notNull(),
|
|
85
|
+
expires: integer('expires', { mode: 'timestamp_ms' }).notNull(),
|
|
86
|
+
},
|
|
87
|
+
(verificationToken) => ({
|
|
88
|
+
compositePk: primaryKey({
|
|
89
|
+
columns: [verificationToken.identifier, verificationToken.token],
|
|
90
|
+
}),
|
|
91
|
+
})
|
|
92
|
+
)
|
|
93
|
+
`;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Generate PostgreSQL-specific auth schema
|
|
97
|
+
*
|
|
98
|
+
* Uses pgTable with native timestamp columns (date mode).
|
|
99
|
+
*
|
|
100
|
+
* @returns PostgreSQL auth schema as string
|
|
101
|
+
*/
|
|
102
|
+
function generatePostgresAuthSchema() {
|
|
103
|
+
return `// Auto-generated Auth.js schema for PostgreSQL
|
|
104
|
+
// Do not edit manually - regenerate with: npx archetype generate
|
|
105
|
+
|
|
106
|
+
import {
|
|
107
|
+
integer,
|
|
108
|
+
pgTable,
|
|
109
|
+
primaryKey,
|
|
110
|
+
text,
|
|
111
|
+
timestamp,
|
|
112
|
+
} from 'drizzle-orm/pg-core'
|
|
113
|
+
import type { AdapterAccountType } from 'next-auth/adapters'
|
|
114
|
+
|
|
115
|
+
export const users = pgTable('user', {
|
|
116
|
+
id: text('id')
|
|
117
|
+
.primaryKey()
|
|
118
|
+
.$defaultFn(() => crypto.randomUUID()),
|
|
119
|
+
name: text('name'),
|
|
120
|
+
email: text('email').unique(),
|
|
121
|
+
emailVerified: timestamp('emailVerified', { mode: 'date' }),
|
|
122
|
+
image: text('image'),
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
export const accounts = pgTable(
|
|
126
|
+
'account',
|
|
127
|
+
{
|
|
128
|
+
userId: text('userId')
|
|
129
|
+
.notNull()
|
|
130
|
+
.references(() => users.id, { onDelete: 'cascade' }),
|
|
131
|
+
type: text('type').$type<AdapterAccountType>().notNull(),
|
|
132
|
+
provider: text('provider').notNull(),
|
|
133
|
+
providerAccountId: text('providerAccountId').notNull(),
|
|
134
|
+
refresh_token: text('refresh_token'),
|
|
135
|
+
access_token: text('access_token'),
|
|
136
|
+
expires_at: integer('expires_at'),
|
|
137
|
+
token_type: text('token_type'),
|
|
138
|
+
scope: text('scope'),
|
|
139
|
+
id_token: text('id_token'),
|
|
140
|
+
session_state: text('session_state'),
|
|
141
|
+
},
|
|
142
|
+
(account) => ({
|
|
143
|
+
compoundKey: primaryKey({ columns: [account.provider, account.providerAccountId] }),
|
|
144
|
+
})
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
export const sessions = pgTable('session', {
|
|
148
|
+
sessionToken: text('sessionToken').primaryKey(),
|
|
149
|
+
userId: text('userId')
|
|
150
|
+
.notNull()
|
|
151
|
+
.references(() => users.id, { onDelete: 'cascade' }),
|
|
152
|
+
expires: timestamp('expires', { mode: 'date' }).notNull(),
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
export const verificationTokens = pgTable(
|
|
156
|
+
'verificationToken',
|
|
157
|
+
{
|
|
158
|
+
identifier: text('identifier').notNull(),
|
|
159
|
+
token: text('token').notNull(),
|
|
160
|
+
expires: timestamp('expires', { mode: 'date' }).notNull(),
|
|
161
|
+
},
|
|
162
|
+
(verificationToken) => ({
|
|
163
|
+
compositePk: primaryKey({
|
|
164
|
+
columns: [verificationToken.identifier, verificationToken.token],
|
|
165
|
+
}),
|
|
166
|
+
})
|
|
167
|
+
)
|
|
168
|
+
`;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Generate MySQL-specific auth schema
|
|
172
|
+
*
|
|
173
|
+
* Uses mysqlTable with varchar fields (255 length) and timestamp columns.
|
|
174
|
+
*
|
|
175
|
+
* @returns MySQL auth schema as string
|
|
176
|
+
*/
|
|
177
|
+
function generateMysqlAuthSchema() {
|
|
178
|
+
return `// Auto-generated Auth.js schema for MySQL
|
|
179
|
+
// Do not edit manually - regenerate with: npx archetype generate
|
|
180
|
+
|
|
181
|
+
import {
|
|
182
|
+
int,
|
|
183
|
+
mysqlTable,
|
|
184
|
+
primaryKey,
|
|
185
|
+
varchar,
|
|
186
|
+
timestamp,
|
|
187
|
+
} from 'drizzle-orm/mysql-core'
|
|
188
|
+
import type { AdapterAccountType } from 'next-auth/adapters'
|
|
189
|
+
|
|
190
|
+
export const users = mysqlTable('user', {
|
|
191
|
+
id: varchar('id', { length: 255 })
|
|
192
|
+
.primaryKey()
|
|
193
|
+
.$defaultFn(() => crypto.randomUUID()),
|
|
194
|
+
name: varchar('name', { length: 255 }),
|
|
195
|
+
email: varchar('email', { length: 255 }).unique(),
|
|
196
|
+
emailVerified: timestamp('emailVerified', { fsp: 3, mode: 'date' }),
|
|
197
|
+
image: varchar('image', { length: 255 }),
|
|
198
|
+
})
|
|
199
|
+
|
|
200
|
+
export const accounts = mysqlTable(
|
|
201
|
+
'account',
|
|
202
|
+
{
|
|
203
|
+
userId: varchar('userId', { length: 255 })
|
|
204
|
+
.notNull()
|
|
205
|
+
.references(() => users.id, { onDelete: 'cascade' }),
|
|
206
|
+
type: varchar('type', { length: 255 }).$type<AdapterAccountType>().notNull(),
|
|
207
|
+
provider: varchar('provider', { length: 255 }).notNull(),
|
|
208
|
+
providerAccountId: varchar('providerAccountId', { length: 255 }).notNull(),
|
|
209
|
+
refresh_token: varchar('refresh_token', { length: 255 }),
|
|
210
|
+
access_token: varchar('access_token', { length: 255 }),
|
|
211
|
+
expires_at: int('expires_at'),
|
|
212
|
+
token_type: varchar('token_type', { length: 255 }),
|
|
213
|
+
scope: varchar('scope', { length: 255 }),
|
|
214
|
+
id_token: varchar('id_token', { length: 2048 }),
|
|
215
|
+
session_state: varchar('session_state', { length: 255 }),
|
|
216
|
+
},
|
|
217
|
+
(account) => ({
|
|
218
|
+
compoundKey: primaryKey({ columns: [account.provider, account.providerAccountId] }),
|
|
219
|
+
})
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
export const sessions = mysqlTable('session', {
|
|
223
|
+
sessionToken: varchar('sessionToken', { length: 255 }).primaryKey(),
|
|
224
|
+
userId: varchar('userId', { length: 255 })
|
|
225
|
+
.notNull()
|
|
226
|
+
.references(() => users.id, { onDelete: 'cascade' }),
|
|
227
|
+
expires: timestamp('expires', { mode: 'date' }).notNull(),
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
export const verificationTokens = mysqlTable(
|
|
231
|
+
'verificationToken',
|
|
232
|
+
{
|
|
233
|
+
identifier: varchar('identifier', { length: 255 }).notNull(),
|
|
234
|
+
token: varchar('token', { length: 255 }).notNull(),
|
|
235
|
+
expires: timestamp('expires', { mode: 'date' }).notNull(),
|
|
236
|
+
},
|
|
237
|
+
(verificationToken) => ({
|
|
238
|
+
compositePk: primaryKey({
|
|
239
|
+
columns: [verificationToken.identifier, verificationToken.token],
|
|
240
|
+
}),
|
|
241
|
+
})
|
|
242
|
+
)
|
|
243
|
+
`;
|
|
244
|
+
}
|
|
245
|
+
exports.authGenerator = {
|
|
246
|
+
name: 'auth-schema',
|
|
247
|
+
description: 'Generate Auth.js schema for next-auth',
|
|
248
|
+
generate(manifest, ctx) {
|
|
249
|
+
// Skip if auth is not enabled
|
|
250
|
+
if (!manifest.auth.enabled) {
|
|
251
|
+
return [];
|
|
252
|
+
}
|
|
253
|
+
// Generate auth schema based on database type
|
|
254
|
+
let schemaContent;
|
|
255
|
+
if (ctx.database.isSqlite) {
|
|
256
|
+
schemaContent = generateSqliteAuthSchema();
|
|
257
|
+
}
|
|
258
|
+
else if (ctx.database.isPostgres) {
|
|
259
|
+
schemaContent = generatePostgresAuthSchema();
|
|
260
|
+
}
|
|
261
|
+
else if (ctx.database.isMysql) {
|
|
262
|
+
schemaContent = generateMysqlAuthSchema();
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
// Default to SQLite for unknown
|
|
266
|
+
schemaContent = generateSqliteAuthSchema();
|
|
267
|
+
}
|
|
268
|
+
return [{
|
|
269
|
+
path: 'db/auth-schema.ts',
|
|
270
|
+
content: schemaContent,
|
|
271
|
+
}];
|
|
272
|
+
},
|
|
273
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CRUD Hooks Generator
|
|
3
|
+
*
|
|
4
|
+
* Generates type-safe hook files for CRUD operations.
|
|
5
|
+
* Users implement hooks in these files to add custom business logic.
|
|
6
|
+
*
|
|
7
|
+
* Generated files:
|
|
8
|
+
* - hooks/types.ts - Type definitions for all hook signatures
|
|
9
|
+
* - hooks/{entity}.ts - Hook implementations (user-editable)
|
|
10
|
+
*
|
|
11
|
+
* Features:
|
|
12
|
+
* - Type-safe hook signatures with proper input/output types
|
|
13
|
+
* - beforeCreate/afterCreate hooks for create operations
|
|
14
|
+
* - beforeUpdate/afterUpdate hooks for update operations
|
|
15
|
+
* - beforeRemove/afterRemove hooks for delete operations
|
|
16
|
+
* - Hooks can modify input (before*) or perform side effects (after*)
|
|
17
|
+
*
|
|
18
|
+
* @module generators/crud-hooks
|
|
19
|
+
*/
|
|
20
|
+
import type { Generator } from '../../../template/types';
|
|
21
|
+
export declare const crudHooksGenerator: Generator;
|
|
22
|
+
//# sourceMappingURL=crud-hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crud-hooks.d.ts","sourceRoot":"","sources":["../../../../../src/templates/nextjs-drizzle-trpc/generators/crud-hooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAiB,MAAM,yBAAyB,CAAA;AAiNvE,eAAO,MAAM,kBAAkB,EAAE,SA8BhC,CAAA"}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* CRUD Hooks Generator
|
|
4
|
+
*
|
|
5
|
+
* Generates type-safe hook files for CRUD operations.
|
|
6
|
+
* Users implement hooks in these files to add custom business logic.
|
|
7
|
+
*
|
|
8
|
+
* Generated files:
|
|
9
|
+
* - hooks/types.ts - Type definitions for all hook signatures
|
|
10
|
+
* - hooks/{entity}.ts - Hook implementations (user-editable)
|
|
11
|
+
*
|
|
12
|
+
* Features:
|
|
13
|
+
* - Type-safe hook signatures with proper input/output types
|
|
14
|
+
* - beforeCreate/afterCreate hooks for create operations
|
|
15
|
+
* - beforeUpdate/afterUpdate hooks for update operations
|
|
16
|
+
* - beforeRemove/afterRemove hooks for delete operations
|
|
17
|
+
* - Hooks can modify input (before*) or perform side effects (after*)
|
|
18
|
+
*
|
|
19
|
+
* @module generators/crud-hooks
|
|
20
|
+
*/
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.crudHooksGenerator = void 0;
|
|
23
|
+
/**
|
|
24
|
+
* Check if entity has any hooks enabled
|
|
25
|
+
*/
|
|
26
|
+
function hasAnyHooks(hooks) {
|
|
27
|
+
return Object.values(hooks).some(v => v);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Check if manifest has any entities with hooks
|
|
31
|
+
*/
|
|
32
|
+
function manifestHasHooks(manifest) {
|
|
33
|
+
return manifest.entities.some(e => hasAnyHooks(e.hooks));
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Generate the shared hooks types file
|
|
37
|
+
*/
|
|
38
|
+
function generateHooksTypes(manifest) {
|
|
39
|
+
const entityTypes = [];
|
|
40
|
+
for (const entity of manifest.entities) {
|
|
41
|
+
if (!hasAnyHooks(entity.hooks))
|
|
42
|
+
continue;
|
|
43
|
+
const name = entity.name;
|
|
44
|
+
const hooks = entity.hooks;
|
|
45
|
+
// Build field types for CreateInput
|
|
46
|
+
const createFields = Object.entries(entity.fields)
|
|
47
|
+
.filter(([_, f]) => f.type !== 'computed')
|
|
48
|
+
.map(([fieldName, config]) => {
|
|
49
|
+
const optional = !config.required ? '?' : '';
|
|
50
|
+
let type = 'string';
|
|
51
|
+
if (config.type === 'number')
|
|
52
|
+
type = 'number';
|
|
53
|
+
if (config.type === 'boolean')
|
|
54
|
+
type = 'boolean';
|
|
55
|
+
if (config.type === 'enum' && config.enumValues) {
|
|
56
|
+
type = config.enumValues.map(v => `'${v}'`).join(' | ');
|
|
57
|
+
}
|
|
58
|
+
return ` ${fieldName}${optional}: ${type}`;
|
|
59
|
+
})
|
|
60
|
+
.join('\n');
|
|
61
|
+
// Build field types for UpdateInput (all optional)
|
|
62
|
+
const updateFields = Object.entries(entity.fields)
|
|
63
|
+
.filter(([_, f]) => f.type !== 'computed')
|
|
64
|
+
.map(([fieldName, config]) => {
|
|
65
|
+
let type = 'string';
|
|
66
|
+
if (config.type === 'number')
|
|
67
|
+
type = 'number';
|
|
68
|
+
if (config.type === 'boolean')
|
|
69
|
+
type = 'boolean';
|
|
70
|
+
if (config.type === 'enum' && config.enumValues) {
|
|
71
|
+
type = config.enumValues.map(v => `'${v}'`).join(' | ');
|
|
72
|
+
}
|
|
73
|
+
return ` ${fieldName}?: ${type}`;
|
|
74
|
+
})
|
|
75
|
+
.join('\n');
|
|
76
|
+
// Build hook interface members
|
|
77
|
+
const hookMembers = [];
|
|
78
|
+
if (hooks.beforeCreate) {
|
|
79
|
+
hookMembers.push(` /** Called before creating. Return modified input or throw to abort. */
|
|
80
|
+
beforeCreate?: (input: ${name}CreateInput, ctx: HookContext) => Promise<${name}CreateInput> | ${name}CreateInput`);
|
|
81
|
+
}
|
|
82
|
+
if (hooks.afterCreate) {
|
|
83
|
+
hookMembers.push(` /** Called after creation. For side effects like sending emails. */
|
|
84
|
+
afterCreate?: (record: ${name}Record, ctx: HookContext) => Promise<void> | void`);
|
|
85
|
+
}
|
|
86
|
+
if (hooks.beforeUpdate) {
|
|
87
|
+
hookMembers.push(` /** Called before updating. Return modified input or throw to abort. */
|
|
88
|
+
beforeUpdate?: (id: string, input: ${name}UpdateInput, ctx: HookContext) => Promise<${name}UpdateInput> | ${name}UpdateInput`);
|
|
89
|
+
}
|
|
90
|
+
if (hooks.afterUpdate) {
|
|
91
|
+
hookMembers.push(` /** Called after update. For side effects. */
|
|
92
|
+
afterUpdate?: (record: ${name}Record, ctx: HookContext) => Promise<void> | void`);
|
|
93
|
+
}
|
|
94
|
+
if (hooks.beforeRemove) {
|
|
95
|
+
hookMembers.push(` /** Called before removal. Throw to abort deletion. */
|
|
96
|
+
beforeRemove?: (id: string, ctx: HookContext) => Promise<void> | void`);
|
|
97
|
+
}
|
|
98
|
+
if (hooks.afterRemove) {
|
|
99
|
+
hookMembers.push(` /** Called after removal. For cleanup/archival. */
|
|
100
|
+
afterRemove?: (record: ${name}Record, ctx: HookContext) => Promise<void> | void`);
|
|
101
|
+
}
|
|
102
|
+
entityTypes.push(`
|
|
103
|
+
// ============ ${name} Hooks ============
|
|
104
|
+
|
|
105
|
+
export interface ${name}CreateInput {
|
|
106
|
+
${createFields}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export interface ${name}UpdateInput {
|
|
110
|
+
${updateFields}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export interface ${name}Record extends ${name}CreateInput {
|
|
114
|
+
id: string
|
|
115
|
+
createdAt: string
|
|
116
|
+
updatedAt: string
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export interface ${name}Hooks {
|
|
120
|
+
${hookMembers.join('\n')}
|
|
121
|
+
}`);
|
|
122
|
+
}
|
|
123
|
+
return `// Auto-generated hook types
|
|
124
|
+
// Do not edit manually - regenerate with: npx archetype generate
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Hook context passed to all hooks
|
|
128
|
+
* Contains user session and other request context
|
|
129
|
+
*/
|
|
130
|
+
export interface HookContext {
|
|
131
|
+
/** User session (if authenticated) */
|
|
132
|
+
user?: {
|
|
133
|
+
id: string
|
|
134
|
+
email?: string
|
|
135
|
+
name?: string
|
|
136
|
+
}
|
|
137
|
+
/** Request headers */
|
|
138
|
+
headers?: Record<string, string>
|
|
139
|
+
}
|
|
140
|
+
${entityTypes.join('\n')}
|
|
141
|
+
`;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Generate a stub hooks file for an entity
|
|
145
|
+
*/
|
|
146
|
+
function generateEntityHooks(entity) {
|
|
147
|
+
const name = entity.name;
|
|
148
|
+
const lowerName = name.toLowerCase();
|
|
149
|
+
const hooks = entity.hooks;
|
|
150
|
+
const imports = [`${name}Hooks`, 'HookContext'];
|
|
151
|
+
if (hooks.beforeCreate || hooks.afterCreate) {
|
|
152
|
+
imports.push(`${name}CreateInput`);
|
|
153
|
+
}
|
|
154
|
+
if (hooks.beforeUpdate) {
|
|
155
|
+
imports.push(`${name}UpdateInput`);
|
|
156
|
+
}
|
|
157
|
+
if (hooks.afterCreate || hooks.afterUpdate || hooks.afterRemove) {
|
|
158
|
+
imports.push(`${name}Record`);
|
|
159
|
+
}
|
|
160
|
+
const hookImplementations = [];
|
|
161
|
+
if (hooks.beforeCreate) {
|
|
162
|
+
hookImplementations.push(`
|
|
163
|
+
async beforeCreate(input, ctx) {
|
|
164
|
+
// Validate business rules or modify input
|
|
165
|
+
// throw new Error('message') to abort
|
|
166
|
+
return input
|
|
167
|
+
},`);
|
|
168
|
+
}
|
|
169
|
+
if (hooks.afterCreate) {
|
|
170
|
+
hookImplementations.push(`
|
|
171
|
+
async afterCreate(record, ctx) {
|
|
172
|
+
// Side effects: send email, audit log, sync external system
|
|
173
|
+
},`);
|
|
174
|
+
}
|
|
175
|
+
if (hooks.beforeUpdate) {
|
|
176
|
+
hookImplementations.push(`
|
|
177
|
+
async beforeUpdate(id, input, ctx) {
|
|
178
|
+
// Validate business rules or modify input
|
|
179
|
+
// throw new Error('message') to abort
|
|
180
|
+
return input
|
|
181
|
+
},`);
|
|
182
|
+
}
|
|
183
|
+
if (hooks.afterUpdate) {
|
|
184
|
+
hookImplementations.push(`
|
|
185
|
+
async afterUpdate(record, ctx) {
|
|
186
|
+
// Side effects: sync external system, invalidate cache
|
|
187
|
+
},`);
|
|
188
|
+
}
|
|
189
|
+
if (hooks.beforeRemove) {
|
|
190
|
+
hookImplementations.push(`
|
|
191
|
+
async beforeRemove(id, ctx) {
|
|
192
|
+
// Check if deletion is allowed
|
|
193
|
+
// throw new Error('message') to abort
|
|
194
|
+
},`);
|
|
195
|
+
}
|
|
196
|
+
if (hooks.afterRemove) {
|
|
197
|
+
hookImplementations.push(`
|
|
198
|
+
async afterRemove(record, ctx) {
|
|
199
|
+
// Cleanup: archive data, remove related records
|
|
200
|
+
},`);
|
|
201
|
+
}
|
|
202
|
+
return `// ${name} CRUD Hooks
|
|
203
|
+
// Implement your business logic here
|
|
204
|
+
// This file is user-managed - it won't be overwritten by regenerate
|
|
205
|
+
|
|
206
|
+
import type { ${imports.join(', ')} } from './types'
|
|
207
|
+
|
|
208
|
+
export const ${lowerName}Hooks: ${name}Hooks = {${hookImplementations.join('')}
|
|
209
|
+
}
|
|
210
|
+
`;
|
|
211
|
+
}
|
|
212
|
+
exports.crudHooksGenerator = {
|
|
213
|
+
name: 'crud-hooks',
|
|
214
|
+
description: 'Generate CRUD hook files',
|
|
215
|
+
generate(manifest, ctx) {
|
|
216
|
+
// Only generate if at least one entity has hooks
|
|
217
|
+
if (!manifestHasHooks(manifest)) {
|
|
218
|
+
return [];
|
|
219
|
+
}
|
|
220
|
+
const files = [];
|
|
221
|
+
// Generate shared types file
|
|
222
|
+
files.push({
|
|
223
|
+
path: 'hooks/types.ts',
|
|
224
|
+
content: generateHooksTypes(manifest),
|
|
225
|
+
});
|
|
226
|
+
// Generate hook implementation files for entities with hooks
|
|
227
|
+
for (const entity of manifest.entities) {
|
|
228
|
+
if (hasAnyHooks(entity.hooks)) {
|
|
229
|
+
files.push({
|
|
230
|
+
path: `hooks/${entity.name.toLowerCase()}.ts`,
|
|
231
|
+
content: generateEntityHooks(entity),
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return files;
|
|
236
|
+
},
|
|
237
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React Hooks Generator
|
|
3
|
+
*
|
|
4
|
+
* Generates React hooks for data fetching and form handling using tRPC and React Hook Form.
|
|
5
|
+
* Provides a complete set of hooks for each entity's CRUD operations.
|
|
6
|
+
*
|
|
7
|
+
* Generated files:
|
|
8
|
+
* - hooks/use{Entity}.ts - Hooks for list, get, create, edit, and remove operations
|
|
9
|
+
*
|
|
10
|
+
* Generated hooks per entity:
|
|
11
|
+
* - use{Entity}s() - List all entities (useQuery)
|
|
12
|
+
* - use{Entity}(id) - Get single entity by ID (useQuery)
|
|
13
|
+
* - use{Entity}Form() - Create form with validation and mutation
|
|
14
|
+
* - use{Entity}EditForm(id) - Edit form with data loading and mutation
|
|
15
|
+
* - use{Entity}Remove() - Delete mutation with cache invalidation
|
|
16
|
+
* - useCreate{Entity}() - Create mutation without form
|
|
17
|
+
* - useUpdate{Entity}() - Update mutation without form
|
|
18
|
+
*
|
|
19
|
+
* Features:
|
|
20
|
+
* - Zod validation integration via zodResolver
|
|
21
|
+
* - Automatic tRPC cache invalidation on mutations
|
|
22
|
+
* - i18n support for validation messages when multiple languages configured
|
|
23
|
+
* - Form reset on successful create
|
|
24
|
+
* - Null-to-undefined conversion for form compatibility
|
|
25
|
+
*
|
|
26
|
+
* @module generators/hooks
|
|
27
|
+
*/
|
|
28
|
+
import type { Generator } from '../../../template/types';
|
|
29
|
+
export declare const hooksGenerator: Generator;
|
|
30
|
+
//# sourceMappingURL=hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../../../../src/templates/nextjs-drizzle-trpc/generators/hooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAiB,MAAM,yBAAyB,CAAA;AAmUvE,eAAO,MAAM,cAAc,EAAE,SAU5B,CAAA"}
|