create-questpie 2.0.4 → 2.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 (152) hide show
  1. package/dist/index.mjs +362 -119
  2. package/package.json +2 -3
  3. package/templates/elysia/AGENTS.md +56 -0
  4. package/templates/elysia/CLAUDE.md +39 -0
  5. package/templates/elysia/Dockerfile +24 -0
  6. package/templates/elysia/README.md +148 -0
  7. package/templates/elysia/docker/init-extensions.sql +11 -0
  8. package/templates/elysia/docker-compose.yml +21 -0
  9. package/templates/elysia/env.example +16 -0
  10. package/templates/elysia/gitignore +6 -0
  11. package/templates/elysia/package.json +47 -0
  12. package/templates/elysia/questpie.config.ts +12 -0
  13. package/templates/elysia/src/index.ts +21 -0
  14. package/templates/elysia/src/lib/auth-client.ts +32 -0
  15. package/templates/elysia/src/lib/client.ts +13 -0
  16. package/templates/elysia/src/lib/env.ts +24 -0
  17. package/templates/elysia/src/lib/query-client.ts +18 -0
  18. package/templates/elysia/src/lib/query.ts +18 -0
  19. package/templates/elysia/src/questpie/server/.generated/context.gen.ts +200 -0
  20. package/templates/elysia/src/questpie/server/.generated/entities.gen.ts +84 -0
  21. package/templates/elysia/src/questpie/server/.generated/factories.ts +65 -0
  22. package/templates/elysia/src/questpie/server/.generated/index.ts +131 -0
  23. package/templates/elysia/src/questpie/server/.generated/names.gen.ts +25 -0
  24. package/templates/elysia/src/questpie/server/app.ts +10 -0
  25. package/templates/elysia/src/questpie/server/collections/index.ts +1 -0
  26. package/templates/elysia/src/questpie/server/collections/posts.collection.ts +10 -0
  27. package/templates/elysia/src/questpie/server/config/auth.ts +8 -0
  28. package/templates/elysia/src/questpie/server/config/openapi.ts +10 -0
  29. package/templates/elysia/src/questpie/server/globals/index.ts +1 -0
  30. package/templates/elysia/src/questpie/server/globals/site-settings.global.ts +10 -0
  31. package/templates/elysia/src/questpie/server/modules.ts +8 -0
  32. package/templates/elysia/src/questpie/server/questpie.config.ts +21 -0
  33. package/templates/elysia/tsconfig.json +28 -0
  34. package/templates/hono/AGENTS.md +56 -0
  35. package/templates/hono/CLAUDE.md +39 -0
  36. package/templates/hono/Dockerfile +24 -0
  37. package/templates/hono/README.md +148 -0
  38. package/templates/hono/docker/init-extensions.sql +11 -0
  39. package/templates/hono/docker-compose.yml +21 -0
  40. package/templates/hono/env.example +16 -0
  41. package/templates/hono/gitignore +6 -0
  42. package/templates/hono/package.json +47 -0
  43. package/templates/hono/questpie.config.ts +12 -0
  44. package/templates/hono/src/index.ts +30 -0
  45. package/templates/hono/src/lib/auth-client.ts +32 -0
  46. package/templates/hono/src/lib/client.ts +13 -0
  47. package/templates/hono/src/lib/env.ts +24 -0
  48. package/templates/hono/src/lib/query-client.ts +18 -0
  49. package/templates/hono/src/lib/query.ts +18 -0
  50. package/templates/hono/src/questpie/server/.generated/context.gen.ts +200 -0
  51. package/templates/hono/src/questpie/server/.generated/entities.gen.ts +84 -0
  52. package/templates/hono/src/questpie/server/.generated/factories.ts +65 -0
  53. package/templates/hono/src/questpie/server/.generated/index.ts +131 -0
  54. package/templates/hono/src/questpie/server/.generated/names.gen.ts +25 -0
  55. package/templates/hono/src/questpie/server/app.ts +10 -0
  56. package/templates/hono/src/questpie/server/collections/index.ts +1 -0
  57. package/templates/hono/src/questpie/server/collections/posts.collection.ts +10 -0
  58. package/templates/hono/src/questpie/server/config/auth.ts +8 -0
  59. package/templates/hono/src/questpie/server/config/openapi.ts +10 -0
  60. package/templates/hono/src/questpie/server/globals/index.ts +1 -0
  61. package/templates/hono/src/questpie/server/globals/site-settings.global.ts +10 -0
  62. package/templates/hono/src/questpie/server/modules.ts +8 -0
  63. package/templates/hono/src/questpie/server/questpie.config.ts +21 -0
  64. package/templates/hono/tsconfig.json +28 -0
  65. package/templates/next/AGENTS.md +55 -0
  66. package/templates/next/CLAUDE.md +39 -0
  67. package/templates/next/Dockerfile +25 -0
  68. package/templates/next/README.md +148 -0
  69. package/templates/next/components.json +22 -0
  70. package/templates/next/docker/init-extensions.sql +11 -0
  71. package/templates/next/docker-compose.yml +21 -0
  72. package/templates/next/env.example +16 -0
  73. package/templates/next/gitignore +10 -0
  74. package/templates/next/next-env.d.ts +5 -0
  75. package/templates/next/next.config.ts +20 -0
  76. package/templates/next/package.json +54 -0
  77. package/templates/next/postcss.config.mjs +8 -0
  78. package/templates/next/public/.gitkeep +0 -0
  79. package/templates/next/questpie.config.ts +12 -0
  80. package/templates/next/src/app/admin/[[...all]]/page.tsx +34 -0
  81. package/templates/next/src/app/admin/admin.css +4 -0
  82. package/templates/next/src/app/admin/layout.tsx +63 -0
  83. package/templates/next/src/app/api/[...all]/route.ts +24 -0
  84. package/templates/next/src/app/layout.tsx +24 -0
  85. package/templates/next/src/app/not-found.tsx +18 -0
  86. package/templates/next/src/app/page.tsx +74 -0
  87. package/templates/next/src/app/providers.tsx +11 -0
  88. package/templates/next/src/lib/auth-client.ts +12 -0
  89. package/templates/next/src/lib/client.ts +13 -0
  90. package/templates/next/src/lib/env.ts +24 -0
  91. package/templates/next/src/lib/query-client.ts +18 -0
  92. package/templates/next/src/lib/query.ts +18 -0
  93. package/templates/next/src/questpie/admin/.generated/client.ts +13 -0
  94. package/templates/next/src/questpie/admin/admin.ts +9 -0
  95. package/templates/next/src/questpie/admin/modules.ts +3 -0
  96. package/templates/next/src/questpie/server/.generated/context.gen.ts +204 -0
  97. package/templates/next/src/questpie/server/.generated/entities.gen.ts +100 -0
  98. package/templates/next/src/questpie/server/.generated/factories.ts +204 -0
  99. package/templates/next/src/questpie/server/.generated/index.ts +139 -0
  100. package/templates/next/src/questpie/server/.generated/names.gen.ts +31 -0
  101. package/templates/next/src/questpie/server/app.ts +10 -0
  102. package/templates/next/src/questpie/server/collections/index.ts +1 -0
  103. package/templates/next/src/questpie/server/collections/posts.collection.ts +58 -0
  104. package/templates/next/src/questpie/server/config/admin.ts +80 -0
  105. package/templates/next/src/questpie/server/config/auth.ts +8 -0
  106. package/templates/next/src/questpie/server/config/openapi.ts +10 -0
  107. package/templates/next/src/questpie/server/globals/index.ts +1 -0
  108. package/templates/next/src/questpie/server/globals/site-settings.global.ts +19 -0
  109. package/templates/next/src/questpie/server/modules.ts +9 -0
  110. package/templates/next/src/questpie/server/questpie.config.ts +21 -0
  111. package/templates/next/src/styles.css +125 -0
  112. package/templates/next/tsconfig.json +37 -0
  113. package/templates/tanstack-start/AGENTS.md +35 -607
  114. package/templates/tanstack-start/CLAUDE.md +26 -134
  115. package/templates/tanstack-start/README.md +13 -1
  116. package/templates/tanstack-start/docker/init-extensions.sql +11 -0
  117. package/templates/tanstack-start/docker-compose.yml +1 -0
  118. package/templates/tanstack-start/src/lib/auth-client.ts +1 -1
  119. package/templates/tanstack-start/src/lib/client.ts +1 -1
  120. package/templates/tanstack-start/src/lib/query.ts +18 -0
  121. package/templates/tanstack-start/src/questpie/server/collections/index.ts +1 -1
  122. package/templates/tanstack-start/src/questpie/server/globals/index.ts +1 -1
  123. package/templates/tanstack-start/src/questpie/server/questpie.config.ts +1 -1
  124. package/templates/tanstack-start/src/routes/__root.tsx +31 -1
  125. package/templates/tanstack-start/src/routes/api/$.ts +1 -1
  126. package/templates/tanstack-start/src/routes/index.tsx +97 -0
  127. package/skills/questpie/AGENTS.md +0 -2871
  128. package/skills/questpie/SKILL.md +0 -293
  129. package/skills/questpie/coverage.json +0 -213
  130. package/skills/questpie/references/auth.md +0 -236
  131. package/skills/questpie/references/business-logic.md +0 -620
  132. package/skills/questpie/references/codegen-plugin-api.md +0 -382
  133. package/skills/questpie/references/crud-api.md +0 -580
  134. package/skills/questpie/references/data-modeling.md +0 -509
  135. package/skills/questpie/references/extend.md +0 -584
  136. package/skills/questpie/references/field-types.md +0 -398
  137. package/skills/questpie/references/infrastructure-adapters.md +0 -720
  138. package/skills/questpie/references/mcp.md +0 -147
  139. package/skills/questpie/references/multi-tenancy.md +0 -363
  140. package/skills/questpie/references/production.md +0 -640
  141. package/skills/questpie/references/query-operators.md +0 -125
  142. package/skills/questpie/references/quickstart.md +0 -562
  143. package/skills/questpie/references/rules.md +0 -454
  144. package/skills/questpie/references/sandbox.md +0 -110
  145. package/skills/questpie/references/tanstack-query.md +0 -543
  146. package/skills/questpie/references/type-inference.md +0 -167
  147. package/skills/questpie/references/workflows.md +0 -155
  148. package/skills/questpie-admin/AGENTS.md +0 -1515
  149. package/skills/questpie-admin/SKILL.md +0 -443
  150. package/skills/questpie-admin/references/blocks.md +0 -331
  151. package/skills/questpie-admin/references/custom-ui.md +0 -305
  152. package/skills/questpie-admin/references/views.md +0 -449
@@ -1,236 +0,0 @@
1
- # Authentication Reference
2
-
3
- Detailed authentication configuration for QUESTPIE using Better Auth.
4
-
5
- ## File Convention
6
-
7
- Auth is configured via `config/auth.ts` using the `authConfig()` factory:
8
-
9
- ```ts
10
- // src/questpie/server/config/auth.ts
11
- import { authConfig } from "questpie/app";
12
- export default authConfig({
13
- emailAndPassword: {
14
- enabled: true,
15
- requireEmailVerification: false,
16
- },
17
- baseURL: process.env.APP_URL || "http://localhost:3000",
18
- basePath: "/api/auth",
19
- secret: process.env.BETTER_AUTH_SECRET || "change-me",
20
- });
21
- ```
22
-
23
- Codegen discovers this file automatically. No manual registration needed.
24
-
25
- ## Configuration Options
26
-
27
- | Option | Type | Default | Description |
28
- | ------------------------------------------- | --------- | ------------- | ----------------------------------------------------------- |
29
- | `emailAndPassword.enabled` | `boolean` | `false` | Enable email/password authentication |
30
- | `emailAndPassword.requireEmailVerification` | `boolean` | `false` | Require email verification before login |
31
- | `baseURL` | `string` | — | Application public URL (used for OAuth callbacks) |
32
- | `basePath` | `string` | `"/api/auth"` | Auth API route prefix |
33
- | `secret` | `string` | — | Session signing secret. **Must be 32+ chars in production** |
34
-
35
- ## Session Access
36
-
37
- ### In Routes
38
-
39
- ```ts
40
- import { route } from "questpie/services";
41
- import z from "zod";
42
-
43
- export default route()
44
- .post()
45
- .schema(z.object({ postId: z.string() }))
46
- .handler(async ({ input, session, collections }) => {
47
- if (!session) {
48
- throw new Error("Not authenticated");
49
- }
50
-
51
- const user = session.user;
52
- // user.id - unique user ID
53
- // user.email - user email address
54
- // user.name - user display name
55
-
56
- const post = await collections.posts.create({
57
- title: "My Post",
58
- author: user.id,
59
- });
60
-
61
- return post;
62
- });
63
- ```
64
-
65
- ### In Hooks
66
-
67
- ```ts
68
- .hooks({
69
- beforeChange: async ({ data, operation, session }) => {
70
- if (operation === "create") {
71
- if (!session) throw new Error("Must be logged in");
72
- data.createdBy = session.user.id;
73
- }
74
- return data;
75
- },
76
- })
77
- ```
78
-
79
- ### In Access Rules
80
-
81
- ```ts
82
- .access({
83
- // Public read
84
- read: true,
85
-
86
- // Authenticated users can create
87
- create: ({ session }) => !!session,
88
-
89
- // Only admins can update/delete
90
- update: ({ session }) => (session?.user as any)?.role === "admin",
91
- delete: ({ session }) => (session?.user as any)?.role === "admin",
92
- })
93
- ```
94
-
95
- ## User Collection
96
-
97
- The `adminModule` includes the starter auth model and provides the canonical Better Auth `user` collection. It stores:
98
-
99
- - `id` -- unique identifier
100
- - `email` -- email address
101
- - `name` -- display name
102
- - `image` -- avatar URL
103
- - `emailVerified` -- verification status
104
- - `role` -- admin access role (`admin` or `user`)
105
- - `avatar`, `banned`, `banReason`, `banExpires` -- admin-managed profile and access fields
106
-
107
- This collection is automatically created when you add the admin module to your config.
108
-
109
- Critical: the built-in admin setup route and admin `AuthGuard` depend on `user.role`. Setup checks whether any user has `role = "admin"`, and the admin UI expects `session.user.role === "admin"`. Do not replace `collection("user")` from scratch in an app that uses `adminModule`; merge `starterModule.collections.user` and extend it if custom user fields or admin layout are needed.
110
-
111
- ```ts
112
- import { starterModule } from "questpie/app";
113
- import { collection } from "#questpie/factories";
114
-
115
- export default collection("user")
116
- .merge(starterModule.collections.user)
117
- .fields(({ f }) => ({
118
- internalNotes: f.textarea(),
119
- }));
120
- ```
121
-
122
- `.fields()` is cumulative -- it adds to the merged starter fields and overrides them by key, never wipes them, so this recipe keeps the full starter user model.
123
-
124
- ### Anonymous Users (Better Auth plugin)
125
-
126
- Better Auth plugins that extend the user model follow the same recipe. For the anonymous plugin, register it in `auth.ts` (merged after the built-in plugins) and extend the starter user with the `isAnonymous` field the plugin expects:
127
-
128
- ```ts
129
- // auth.ts
130
- import { anonymous } from "better-auth/plugins";
131
- import type { AuthConfig } from "questpie/app";
132
-
133
- export default {
134
- plugins: [anonymous()],
135
- } satisfies AuthConfig;
136
- ```
137
-
138
- ```ts
139
- // collections/user.ts
140
- import { starterModule } from "questpie/app";
141
- import { collection } from "#questpie/factories";
142
-
143
- export default collection("user")
144
- .merge(starterModule.collections.user)
145
- .fields(({ f }) => ({
146
- isAnonymous: f.boolean().default(false),
147
- }));
148
- ```
149
-
150
- Run `questpie generate` and apply migrations to add the column. Anonymous sign-in (`authClient.signIn.anonymous()` on the client) creates throwaway users that Better Auth can later link to real accounts.
151
-
152
- ## Reaching the App from Better Auth Callbacks
153
-
154
- The `/auth/*` catch-all is a plain **raw route**, and raw routes execute their handler inside `runWithContext()` (the request's AsyncLocalStorage scope). That means every Better Auth callback — `onLinkAccount`, `databaseHooks`, `sendMagicLink`, plugin hooks — already runs inside the request scope, and `getContext<App>()` returns the live app, session, db, and locale.
155
-
156
- **Never build a module-level app singleton or a hand-rolled context bridge for auth callbacks.** The `App` import stays type-only, so there is no circular import:
157
-
158
- ```ts
159
- // config/auth.ts
160
- import { anonymous } from "better-auth/plugins";
161
- import { getContext } from "questpie";
162
- import { authConfig } from "questpie/app";
163
- import type { App } from "#questpie"; // type-only — no runtime cycle
164
-
165
- export default authConfig({
166
- plugins: [
167
- anonymous({
168
- // Fires when an anonymous user signs in with a real account —
169
- // re-point the guest's rows onto the new user before the plugin
170
- // deletes the anonymous user.
171
- onLinkAccount: async ({ anonymousUser, newUser }) => {
172
- const { app } = getContext<App>();
173
- // Bare { accessMode: "system" } elevates ONLY the mode —
174
- // session, db, and locale inherit from the request scope (ALS).
175
- await app.collections.memberships.updateMany(
176
- {
177
- where: { user: anonymousUser.user.id },
178
- data: { user: newUser.user.id },
179
- },
180
- { accessMode: "system" },
181
- );
182
- },
183
- }),
184
- ],
185
- });
186
- ```
187
-
188
- ### Partial Context Overrides
189
-
190
- CRUD context normalization merges what you pass with the ambient request scope — priority: explicit param → ALS scope → defaults (`accessMode: "system"`, `locale: "en"`). Passing only `{ accessMode: "system" }` elevates the mode while the request's session/db/locale ride along. The inverse also holds: `{ accessMode: "user" }` inside system-scoped code re-enables access rules against the inherited session without re-threading it:
191
-
192
- ```ts
193
- // Inside any handler — session comes from the request ALS scope
194
- await app.collections.posts.find({}, { accessMode: "user" }); // rules enforced for the current user
195
- await app.collections.posts.find({}, { accessMode: "system" }); // rules bypassed, same session/locale
196
- ```
197
-
198
- ## Client-Side Auth (authClient)
199
-
200
- For session state and sign-in/out on the frontend, create a typed Better Auth client. In admin-equipped apps use the typed wrapper (session includes your merged user fields):
201
-
202
- ```ts
203
- // src/lib/auth-client.ts
204
- import { createAdminAuthClient } from "@questpie/admin/client";
205
- import type { AppConfig } from "#questpie";
206
- import { env } from "#questpie/env.client.vite"; // generated from env.client.ts
207
-
208
- export const authClient = createAdminAuthClient<AppConfig>({
209
- baseURL: typeof window !== "undefined" ? window.location.origin : env.APP_URL,
210
- basePath: "/api/auth",
211
- });
212
- ```
213
-
214
- ```tsx
215
- const { data: session, isPending } = authClient.useSession();
216
- await authClient.signIn.email({ email, password });
217
- await authClient.signIn.anonymous(); // with the anonymous plugin
218
- await authClient.signOut();
219
- ```
220
-
221
- Apps without `@questpie/admin` use Better Auth's own `createAuthClient` from `better-auth/react` pointed at `${APP_URL}/api/auth` — same call surface, without the app-inferred session typing.
222
-
223
- ## Environment Variables
224
-
225
- | Variable | Required | Description |
226
- | -------------------- | ---------- | --------------------------------------------------------- |
227
- | `APP_URL` | Yes | Public URL -- used for OAuth callback URLs |
228
- | `BETTER_AUTH_SECRET` | Yes (prod) | Session signing secret. Use a random 32+ character string |
229
-
230
- ## Production Security Checklist
231
-
232
- 1. Set `BETTER_AUTH_SECRET` to a strong random value (32+ chars)
233
- 2. Set `APP_URL` to your production domain (HTTPS)
234
- 3. Enable `requireEmailVerification` if using email/password
235
- 4. Use HTTPS for all auth endpoints
236
- 5. Configure proper CORS if API and frontend are on different domains