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.
- package/dist/index.mjs +362 -119
- package/package.json +2 -3
- package/templates/elysia/AGENTS.md +56 -0
- package/templates/elysia/CLAUDE.md +39 -0
- package/templates/elysia/Dockerfile +24 -0
- package/templates/elysia/README.md +148 -0
- package/templates/elysia/docker/init-extensions.sql +11 -0
- package/templates/elysia/docker-compose.yml +21 -0
- package/templates/elysia/env.example +16 -0
- package/templates/elysia/gitignore +6 -0
- package/templates/elysia/package.json +47 -0
- package/templates/elysia/questpie.config.ts +12 -0
- package/templates/elysia/src/index.ts +21 -0
- package/templates/elysia/src/lib/auth-client.ts +32 -0
- package/templates/elysia/src/lib/client.ts +13 -0
- package/templates/elysia/src/lib/env.ts +24 -0
- package/templates/elysia/src/lib/query-client.ts +18 -0
- package/templates/elysia/src/lib/query.ts +18 -0
- package/templates/elysia/src/questpie/server/.generated/context.gen.ts +200 -0
- package/templates/elysia/src/questpie/server/.generated/entities.gen.ts +84 -0
- package/templates/elysia/src/questpie/server/.generated/factories.ts +65 -0
- package/templates/elysia/src/questpie/server/.generated/index.ts +131 -0
- package/templates/elysia/src/questpie/server/.generated/names.gen.ts +25 -0
- package/templates/elysia/src/questpie/server/app.ts +10 -0
- package/templates/elysia/src/questpie/server/collections/index.ts +1 -0
- package/templates/elysia/src/questpie/server/collections/posts.collection.ts +10 -0
- package/templates/elysia/src/questpie/server/config/auth.ts +8 -0
- package/templates/elysia/src/questpie/server/config/openapi.ts +10 -0
- package/templates/elysia/src/questpie/server/globals/index.ts +1 -0
- package/templates/elysia/src/questpie/server/globals/site-settings.global.ts +10 -0
- package/templates/elysia/src/questpie/server/modules.ts +8 -0
- package/templates/elysia/src/questpie/server/questpie.config.ts +21 -0
- package/templates/elysia/tsconfig.json +28 -0
- package/templates/hono/AGENTS.md +56 -0
- package/templates/hono/CLAUDE.md +39 -0
- package/templates/hono/Dockerfile +24 -0
- package/templates/hono/README.md +148 -0
- package/templates/hono/docker/init-extensions.sql +11 -0
- package/templates/hono/docker-compose.yml +21 -0
- package/templates/hono/env.example +16 -0
- package/templates/hono/gitignore +6 -0
- package/templates/hono/package.json +47 -0
- package/templates/hono/questpie.config.ts +12 -0
- package/templates/hono/src/index.ts +30 -0
- package/templates/hono/src/lib/auth-client.ts +32 -0
- package/templates/hono/src/lib/client.ts +13 -0
- package/templates/hono/src/lib/env.ts +24 -0
- package/templates/hono/src/lib/query-client.ts +18 -0
- package/templates/hono/src/lib/query.ts +18 -0
- package/templates/hono/src/questpie/server/.generated/context.gen.ts +200 -0
- package/templates/hono/src/questpie/server/.generated/entities.gen.ts +84 -0
- package/templates/hono/src/questpie/server/.generated/factories.ts +65 -0
- package/templates/hono/src/questpie/server/.generated/index.ts +131 -0
- package/templates/hono/src/questpie/server/.generated/names.gen.ts +25 -0
- package/templates/hono/src/questpie/server/app.ts +10 -0
- package/templates/hono/src/questpie/server/collections/index.ts +1 -0
- package/templates/hono/src/questpie/server/collections/posts.collection.ts +10 -0
- package/templates/hono/src/questpie/server/config/auth.ts +8 -0
- package/templates/hono/src/questpie/server/config/openapi.ts +10 -0
- package/templates/hono/src/questpie/server/globals/index.ts +1 -0
- package/templates/hono/src/questpie/server/globals/site-settings.global.ts +10 -0
- package/templates/hono/src/questpie/server/modules.ts +8 -0
- package/templates/hono/src/questpie/server/questpie.config.ts +21 -0
- package/templates/hono/tsconfig.json +28 -0
- package/templates/next/AGENTS.md +55 -0
- package/templates/next/CLAUDE.md +39 -0
- package/templates/next/Dockerfile +25 -0
- package/templates/next/README.md +148 -0
- package/templates/next/components.json +22 -0
- package/templates/next/docker/init-extensions.sql +11 -0
- package/templates/next/docker-compose.yml +21 -0
- package/templates/next/env.example +16 -0
- package/templates/next/gitignore +10 -0
- package/templates/next/next-env.d.ts +5 -0
- package/templates/next/next.config.ts +20 -0
- package/templates/next/package.json +54 -0
- package/templates/next/postcss.config.mjs +8 -0
- package/templates/next/public/.gitkeep +0 -0
- package/templates/next/questpie.config.ts +12 -0
- package/templates/next/src/app/admin/[[...all]]/page.tsx +34 -0
- package/templates/next/src/app/admin/admin.css +4 -0
- package/templates/next/src/app/admin/layout.tsx +63 -0
- package/templates/next/src/app/api/[...all]/route.ts +24 -0
- package/templates/next/src/app/layout.tsx +24 -0
- package/templates/next/src/app/not-found.tsx +18 -0
- package/templates/next/src/app/page.tsx +74 -0
- package/templates/next/src/app/providers.tsx +11 -0
- package/templates/next/src/lib/auth-client.ts +12 -0
- package/templates/next/src/lib/client.ts +13 -0
- package/templates/next/src/lib/env.ts +24 -0
- package/templates/next/src/lib/query-client.ts +18 -0
- package/templates/next/src/lib/query.ts +18 -0
- package/templates/next/src/questpie/admin/.generated/client.ts +13 -0
- package/templates/next/src/questpie/admin/admin.ts +9 -0
- package/templates/next/src/questpie/admin/modules.ts +3 -0
- package/templates/next/src/questpie/server/.generated/context.gen.ts +204 -0
- package/templates/next/src/questpie/server/.generated/entities.gen.ts +100 -0
- package/templates/next/src/questpie/server/.generated/factories.ts +204 -0
- package/templates/next/src/questpie/server/.generated/index.ts +139 -0
- package/templates/next/src/questpie/server/.generated/names.gen.ts +31 -0
- package/templates/next/src/questpie/server/app.ts +10 -0
- package/templates/next/src/questpie/server/collections/index.ts +1 -0
- package/templates/next/src/questpie/server/collections/posts.collection.ts +58 -0
- package/templates/next/src/questpie/server/config/admin.ts +80 -0
- package/templates/next/src/questpie/server/config/auth.ts +8 -0
- package/templates/next/src/questpie/server/config/openapi.ts +10 -0
- package/templates/next/src/questpie/server/globals/index.ts +1 -0
- package/templates/next/src/questpie/server/globals/site-settings.global.ts +19 -0
- package/templates/next/src/questpie/server/modules.ts +9 -0
- package/templates/next/src/questpie/server/questpie.config.ts +21 -0
- package/templates/next/src/styles.css +125 -0
- package/templates/next/tsconfig.json +37 -0
- package/templates/tanstack-start/AGENTS.md +35 -607
- package/templates/tanstack-start/CLAUDE.md +26 -134
- package/templates/tanstack-start/README.md +13 -1
- package/templates/tanstack-start/docker/init-extensions.sql +11 -0
- package/templates/tanstack-start/docker-compose.yml +1 -0
- package/templates/tanstack-start/src/lib/auth-client.ts +1 -1
- package/templates/tanstack-start/src/lib/client.ts +1 -1
- package/templates/tanstack-start/src/lib/query.ts +18 -0
- package/templates/tanstack-start/src/questpie/server/collections/index.ts +1 -1
- package/templates/tanstack-start/src/questpie/server/globals/index.ts +1 -1
- package/templates/tanstack-start/src/questpie/server/questpie.config.ts +1 -1
- package/templates/tanstack-start/src/routes/__root.tsx +31 -1
- package/templates/tanstack-start/src/routes/api/$.ts +1 -1
- package/templates/tanstack-start/src/routes/index.tsx +97 -0
- package/skills/questpie/AGENTS.md +0 -2871
- package/skills/questpie/SKILL.md +0 -293
- package/skills/questpie/coverage.json +0 -213
- package/skills/questpie/references/auth.md +0 -236
- package/skills/questpie/references/business-logic.md +0 -620
- package/skills/questpie/references/codegen-plugin-api.md +0 -382
- package/skills/questpie/references/crud-api.md +0 -580
- package/skills/questpie/references/data-modeling.md +0 -509
- package/skills/questpie/references/extend.md +0 -584
- package/skills/questpie/references/field-types.md +0 -398
- package/skills/questpie/references/infrastructure-adapters.md +0 -720
- package/skills/questpie/references/mcp.md +0 -147
- package/skills/questpie/references/multi-tenancy.md +0 -363
- package/skills/questpie/references/production.md +0 -640
- package/skills/questpie/references/query-operators.md +0 -125
- package/skills/questpie/references/quickstart.md +0 -562
- package/skills/questpie/references/rules.md +0 -454
- package/skills/questpie/references/sandbox.md +0 -110
- package/skills/questpie/references/tanstack-query.md +0 -543
- package/skills/questpie/references/type-inference.md +0 -167
- package/skills/questpie/references/workflows.md +0 -155
- package/skills/questpie-admin/AGENTS.md +0 -1515
- package/skills/questpie-admin/SKILL.md +0 -443
- package/skills/questpie-admin/references/blocks.md +0 -331
- package/skills/questpie-admin/references/custom-ui.md +0 -305
- package/skills/questpie-admin/references/views.md +0 -449
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
Guidance for AI agents working in this [QUESTPIE](https://questpie.com) project.
|
|
4
|
+
|
|
5
|
+
## Use the QUESTPIE skills
|
|
6
|
+
|
|
7
|
+
This project is built on QUESTPIE. Do not work from memory — the framework is
|
|
8
|
+
codegen-driven and the APIs evolve. Lean on the installed skill:
|
|
9
|
+
|
|
10
|
+
- **`questpie`** — collections, globals, routes, jobs, codegen, auth, business
|
|
11
|
+
logic, the typed client + TanStack Query. Invoke it for any server/data work.
|
|
12
|
+
|
|
13
|
+
Invoke skills by name (the `/skill` convention) — they are commands, not files
|
|
14
|
+
to read. This is a **headless API** template (no admin UI), so the
|
|
15
|
+
`questpie-admin` skill does not apply here.
|
|
16
|
+
|
|
17
|
+
**If the skill is NOT installed**, install it first, then trim this file:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
bunx skills add questpie/questpie
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
After installing, replace the body of this file with a one-line pointer to the
|
|
24
|
+
skill above — it is the always-current source of truth and this doc should not
|
|
25
|
+
duplicate it.
|
|
26
|
+
|
|
27
|
+
## Docs for LLMs
|
|
28
|
+
|
|
29
|
+
When the skill isn't enough, consult:
|
|
30
|
+
|
|
31
|
+
- https://questpie.com/llms.txt — doc sitemap
|
|
32
|
+
- https://questpie.com/llms-full.txt — full docs in one LLM-optimized file
|
|
33
|
+
- http://localhost:3000/api/docs — live API reference (Scalar, dev server running)
|
|
34
|
+
|
|
35
|
+
## This project
|
|
36
|
+
|
|
37
|
+
- **Runtime**: Elysia on **Bun** (no bundler — the QUESTPIE `.js` ESM import
|
|
38
|
+
convention resolves natively). Package manager **Bun**.
|
|
39
|
+
- **Shape**: headless API only — no admin UI, no React. The fetch handler is
|
|
40
|
+
mounted at `src/index.ts` under `/api`.
|
|
41
|
+
- **Database**: PostgreSQL via Drizzle ORM (Postgres extensions are not
|
|
42
|
+
auto-created — see `README.md`)
|
|
43
|
+
- **Auth**: Better Auth (email/password). The typed `better-auth/client` lives
|
|
44
|
+
in `src/lib/auth-client.ts` for a consuming frontend or scripts.
|
|
45
|
+
- **Validation**: Zod **v4** (not v3)
|
|
46
|
+
- **Source layout**: server contracts in `src/questpie/server/`, HTTP mount in
|
|
47
|
+
`src/index.ts`, typed client + TanStack Query in `src/lib/`
|
|
48
|
+
|
|
49
|
+
## Key scripts
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
bun dev # Start dev server with watch (port 3000)
|
|
53
|
+
bun run scaffold:verify # Regenerate codegen + type-check
|
|
54
|
+
bun run db:push # Push schema to the local dev database
|
|
55
|
+
bun questpie add collection <name> # Scaffold an entity (auto-runs codegen)
|
|
56
|
+
```
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This is a [QUESTPIE](https://questpie.com) project. See **`AGENTS.md`** for the
|
|
4
|
+
full agent guide — it is the source of truth and this file mirrors it.
|
|
5
|
+
|
|
6
|
+
## Use the QUESTPIE skill
|
|
7
|
+
|
|
8
|
+
- **`questpie`** — collections, globals, routes, jobs, codegen, auth, business
|
|
9
|
+
logic, typed client + TanStack Query.
|
|
10
|
+
|
|
11
|
+
Invoke skills by name (the `/skill` convention); don't work from memory. This is
|
|
12
|
+
a **headless API** template (no admin UI), so `questpie-admin` does not apply.
|
|
13
|
+
|
|
14
|
+
**If it isn't installed**, install it and then trim this file to a pointer:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
bunx skills add questpie/questpie
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Docs for LLMs
|
|
21
|
+
|
|
22
|
+
- https://questpie.com/llms.txt — doc sitemap
|
|
23
|
+
- https://questpie.com/llms-full.txt — full docs in one LLM-optimized file
|
|
24
|
+
- http://localhost:3000/api/docs — live API reference (dev server running)
|
|
25
|
+
|
|
26
|
+
## This project
|
|
27
|
+
|
|
28
|
+
- **Runtime**: Elysia on **Bun** (no bundler — `.js` ESM imports resolve natively)
|
|
29
|
+
- **Shape**: headless API — no admin UI, no React; fetch handler at `src/index.ts`
|
|
30
|
+
- **Database**: PostgreSQL (Drizzle ORM)
|
|
31
|
+
- **Auth**: Better Auth (email/password); typed `better-auth/client` in `src/lib/`
|
|
32
|
+
- **Validation**: Zod **v4**
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
bun dev # Dev server with watch (port 3000)
|
|
36
|
+
bun run scaffold:verify # Regenerate codegen + type-check
|
|
37
|
+
bun run db:push # Push schema to local dev DB
|
|
38
|
+
bun questpie add collection <name> # Scaffold an entity (auto-runs codegen)
|
|
39
|
+
```
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
FROM oven/bun:1.3-alpine AS base
|
|
2
|
+
|
|
3
|
+
WORKDIR /app
|
|
4
|
+
|
|
5
|
+
# Install dependencies
|
|
6
|
+
FROM base AS deps
|
|
7
|
+
COPY package.json bun.lock* ./
|
|
8
|
+
RUN bun install --frozen-lockfile
|
|
9
|
+
|
|
10
|
+
# Build application (bundles the entry to dist/ with the Bun target)
|
|
11
|
+
FROM base AS builder
|
|
12
|
+
COPY --from=deps /app/node_modules ./node_modules
|
|
13
|
+
COPY . .
|
|
14
|
+
RUN bun run scaffold:generate
|
|
15
|
+
RUN bun run build
|
|
16
|
+
|
|
17
|
+
# Production image
|
|
18
|
+
FROM base AS runner
|
|
19
|
+
ENV NODE_ENV=production
|
|
20
|
+
ENV PORT=3000
|
|
21
|
+
COPY --from=builder /app/dist ./dist
|
|
22
|
+
COPY --from=builder /app/package.json ./package.json
|
|
23
|
+
EXPOSE 3000
|
|
24
|
+
CMD ["bun", "run", "dist/index.js"]
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# {{projectName}}
|
|
2
|
+
|
|
3
|
+
A [QUESTPIE](https://questpie.com) **headless API** built with [Elysia](https://elysiajs.com),
|
|
4
|
+
running on [Bun](https://bun.sh). No admin UI, no React — just a typed REST API
|
|
5
|
+
with Scalar docs and a typed client you can consume from any frontend.
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
### Prerequisites
|
|
10
|
+
|
|
11
|
+
- [Bun](https://bun.sh) v1.3+
|
|
12
|
+
- [Docker](https://docker.com) (for local PostgreSQL)
|
|
13
|
+
|
|
14
|
+
### Setup
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
# 1) Start PostgreSQL (also provisions required extensions for local dev)
|
|
18
|
+
docker compose up -d
|
|
19
|
+
|
|
20
|
+
# 2) Regenerate codegen and type-check
|
|
21
|
+
bun run scaffold:verify
|
|
22
|
+
|
|
23
|
+
# 3) Create local database tables
|
|
24
|
+
bun run db:push
|
|
25
|
+
|
|
26
|
+
# 4) Start the development server (watch mode)
|
|
27
|
+
bun dev
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
- API docs (Scalar): `http://localhost:3000/api/docs` (the root `/` redirects here)
|
|
31
|
+
- REST API: `http://localhost:3000/api/*`
|
|
32
|
+
|
|
33
|
+
## What you get
|
|
34
|
+
|
|
35
|
+
- **Headless REST API** — every collection and global is exposed under `/api`.
|
|
36
|
+
- **Scalar API reference** at `/api/docs` (the `openapi` module).
|
|
37
|
+
- **Auth** — Better Auth (email/password) mounted at `/api/auth`.
|
|
38
|
+
- **Typed client + TanStack Query** in `src/lib/` — `client.ts`
|
|
39
|
+
(`createClient<AppConfig>`), `query.ts` (`createQuestpieQueryOptions`), and
|
|
40
|
+
`auth-client.ts` (`better-auth/client`). A separate frontend or scripts import
|
|
41
|
+
these for end-to-end type safety against your server schema.
|
|
42
|
+
|
|
43
|
+
## Running on Node instead of Bun
|
|
44
|
+
|
|
45
|
+
The entry (`src/index.ts`) calls `.listen()`, which serves on Bun directly. To
|
|
46
|
+
run on Node, install `@elysiajs/node` and pass its adapter:
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
import { node } from "@elysiajs/node";
|
|
50
|
+
new Elysia({ adapter: node() }) /* …routes… */ .listen(env.PORT ?? 3000);
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Database extensions
|
|
54
|
+
|
|
55
|
+
QUESTPIE is drizzle-native and does **not** auto-create Postgres extensions. The
|
|
56
|
+
starter's full-text search relies on `pg_trgm` (trigram matching).
|
|
57
|
+
|
|
58
|
+
- **Local dev:** `docker compose up` provisions `pg_trgm` via
|
|
59
|
+
`docker/init-extensions.sql`, mounted into the postgres container's
|
|
60
|
+
`/docker-entrypoint-initdb.d/` and run once on first cluster init — so
|
|
61
|
+
`db:push` works out of the box.
|
|
62
|
+
- **Managed Postgres:** enable required extensions through your provider before
|
|
63
|
+
deploying. See [the QUESTPIE docs](https://questpie.com/docs/deployment) for details.
|
|
64
|
+
|
|
65
|
+
## Project Structure
|
|
66
|
+
|
|
67
|
+
```text
|
|
68
|
+
src/
|
|
69
|
+
index.ts # Elysia entry — mounts the fetch handler at /api
|
|
70
|
+
questpie/
|
|
71
|
+
server/
|
|
72
|
+
questpie.config.ts # Runtime config
|
|
73
|
+
modules.ts # Module list (openapi/...)
|
|
74
|
+
config/
|
|
75
|
+
auth.ts # Auth config
|
|
76
|
+
openapi.ts # OpenAPI/Scalar config
|
|
77
|
+
app.ts # Re-export of generated app
|
|
78
|
+
.generated/ # Codegen output (do not edit manually)
|
|
79
|
+
collections/
|
|
80
|
+
posts.collection.ts
|
|
81
|
+
globals/
|
|
82
|
+
site-settings.global.ts
|
|
83
|
+
lib/
|
|
84
|
+
env.ts
|
|
85
|
+
client.ts # Typed REST client (createClient<AppConfig>)
|
|
86
|
+
auth-client.ts # Typed Better Auth client
|
|
87
|
+
query.ts # TanStack Query option builders
|
|
88
|
+
query-client.ts
|
|
89
|
+
migrations/
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Scripts
|
|
93
|
+
|
|
94
|
+
| Command | Description |
|
|
95
|
+
| -------------------------------- | --------------------------------------------- |
|
|
96
|
+
| `bun dev` | Start development server (watch) |
|
|
97
|
+
| `bun run build` | Bundle the entry to `dist/` |
|
|
98
|
+
| `bun run start` | Run the server (no watch) |
|
|
99
|
+
| `bun run check-types` | Type check |
|
|
100
|
+
| `bun run scaffold:generate` | Regenerate QUESTPIE codegen |
|
|
101
|
+
| `bun run scaffold:verify` | Regenerate codegen and type-check |
|
|
102
|
+
| `bun run questpie:generate` | Regenerate `src/questpie/server/.generated/*` |
|
|
103
|
+
| `bun questpie add <type> <name>` | Scaffold entity files (auto-runs codegen) |
|
|
104
|
+
| `bun run db:push` | Push schema directly to local dev database |
|
|
105
|
+
| `bun run migrate` | Run migrations |
|
|
106
|
+
| `bun run migrate:create` | Create migration |
|
|
107
|
+
|
|
108
|
+
## Learn more
|
|
109
|
+
|
|
110
|
+
- [Quickstart](https://questpie.com/docs/quickstart)
|
|
111
|
+
- [Data modeling](https://questpie.com/docs/data-modeling)
|
|
112
|
+
- [Auth](https://questpie.com/docs/auth)
|
|
113
|
+
- [TanStack Query](https://questpie.com/docs/tanstack-query)
|
|
114
|
+
- [Deployment](https://questpie.com/docs/deployment)
|
|
115
|
+
|
|
116
|
+
## Adding a Collection
|
|
117
|
+
|
|
118
|
+
Preferred workflow:
|
|
119
|
+
|
|
120
|
+
1. Run `bun questpie add collection products`.
|
|
121
|
+
2. The CLI creates the file and runs codegen automatically.
|
|
122
|
+
3. Run `bun run db:push` for local development, or `bun run migrate:create` for production migrations.
|
|
123
|
+
|
|
124
|
+
Manual workflow (when you create files by hand):
|
|
125
|
+
|
|
126
|
+
1. Create a file in `src/questpie/server/collections/`.
|
|
127
|
+
2. Export a collection builder from that file.
|
|
128
|
+
3. Run `bun run questpie:generate`.
|
|
129
|
+
4. Run `bun run db:push` for local development, or `bun run migrate:create` for production migrations.
|
|
130
|
+
|
|
131
|
+
Collections are discovered automatically by codegen. No manual `app.ts` registration is required.
|
|
132
|
+
|
|
133
|
+
## Adding a Global
|
|
134
|
+
|
|
135
|
+
Preferred workflow:
|
|
136
|
+
|
|
137
|
+
1. Run `bun questpie add global marketing`.
|
|
138
|
+
2. The CLI creates the file and runs codegen automatically.
|
|
139
|
+
3. Run `bun run db:push` for local development, or `bun run migrate:create` for production migrations.
|
|
140
|
+
|
|
141
|
+
Manual workflow (when you create files by hand):
|
|
142
|
+
|
|
143
|
+
1. Create a file in `src/questpie/server/globals/`.
|
|
144
|
+
2. Export a global builder from that file.
|
|
145
|
+
3. Run `bun run questpie:generate`.
|
|
146
|
+
4. Run `bun run db:push` for local development, or `bun run migrate:create` for production migrations.
|
|
147
|
+
|
|
148
|
+
Globals are discovered automatically by codegen. No manual `app.ts` registration is required.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
-- Postgres extensions provisioned for local development.
|
|
2
|
+
-- Mounted into the postgres container at /docker-entrypoint-initdb.d/ and run
|
|
3
|
+
-- once, on first cluster init, before the app connects.
|
|
4
|
+
--
|
|
5
|
+
-- QUESTPIE is drizzle-native: the app does NOT auto-create extensions. The
|
|
6
|
+
-- starter's full-text search uses pg_trgm (trigram matching), so we provision
|
|
7
|
+
-- it here to keep `db:push` working out-of-the-box while you prototype.
|
|
8
|
+
--
|
|
9
|
+
-- On managed Postgres, enable required extensions via your provider instead.
|
|
10
|
+
-- See https://questpie.com/docs for details.
|
|
11
|
+
CREATE EXTENSION IF NOT EXISTS "pg_trgm";
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
services:
|
|
2
|
+
postgres:
|
|
3
|
+
image: postgres:17
|
|
4
|
+
container_name: {{projectName}}-postgres
|
|
5
|
+
environment:
|
|
6
|
+
POSTGRES_DB: {{databaseName}}
|
|
7
|
+
POSTGRES_USER: {{databaseUser}}
|
|
8
|
+
POSTGRES_PASSWORD: {{databasePassword}}
|
|
9
|
+
ports:
|
|
10
|
+
- "5432:5432"
|
|
11
|
+
volumes:
|
|
12
|
+
- postgres_data:/var/lib/postgresql/data
|
|
13
|
+
- ./docker/init-extensions.sql:/docker-entrypoint-initdb.d/init-extensions.sql:ro
|
|
14
|
+
healthcheck:
|
|
15
|
+
test: ["CMD-SHELL", "pg_isready -U {{databaseUser}}"]
|
|
16
|
+
interval: 5s
|
|
17
|
+
timeout: 5s
|
|
18
|
+
retries: 5
|
|
19
|
+
|
|
20
|
+
volumes:
|
|
21
|
+
postgres_data:
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Database
|
|
2
|
+
DATABASE_URL=postgresql://{{databaseUser}}:{{databasePassword}}@localhost:5432/{{databaseName}}
|
|
3
|
+
|
|
4
|
+
# Application
|
|
5
|
+
APP_URL=http://localhost:3000
|
|
6
|
+
PORT=3000
|
|
7
|
+
|
|
8
|
+
# Auth (Better Auth)
|
|
9
|
+
BETTER_AUTH_SECRET={{authSecret}}
|
|
10
|
+
|
|
11
|
+
# Email Adapter (console | smtp)
|
|
12
|
+
MAIL_ADAPTER=console
|
|
13
|
+
|
|
14
|
+
# SMTP (if using smtp adapter)
|
|
15
|
+
# SMTP_HOST=localhost
|
|
16
|
+
# SMTP_PORT=1025
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{projectName}}",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"imports": {
|
|
7
|
+
"#questpie": "./src/questpie/server/.generated/index.ts",
|
|
8
|
+
"#questpie/*": "./src/questpie/server/.generated/*"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"dev": "bun --watch src/index.ts",
|
|
12
|
+
"start": "bun run src/index.ts",
|
|
13
|
+
"build": "bun build src/index.ts --target=bun --outdir=dist",
|
|
14
|
+
"check-types": "tsc --noEmit",
|
|
15
|
+
"questpie:generate": "questpie generate -c src/questpie/server/questpie.config.ts",
|
|
16
|
+
"scaffold:generate": "bun run questpie:generate",
|
|
17
|
+
"db:push": "questpie push -c questpie.config.ts",
|
|
18
|
+
"migrate": "questpie migrate -c questpie.config.ts",
|
|
19
|
+
"migrate:create": "questpie migrate:create -c questpie.config.ts",
|
|
20
|
+
"migrate:status": "questpie migrate:status -c questpie.config.ts",
|
|
21
|
+
"migrate:down": "questpie migrate:down -c questpie.config.ts",
|
|
22
|
+
"migrate:reset": "questpie migrate:reset -c questpie.config.ts",
|
|
23
|
+
"migrate:fresh": "questpie migrate:fresh -c questpie.config.ts",
|
|
24
|
+
"scaffold:verify": "bun run scaffold:generate && bun run check-types"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@electric-sql/pglite": "^0.3.14",
|
|
28
|
+
"@questpie/openapi": "latest",
|
|
29
|
+
"@questpie/tanstack-query": "latest",
|
|
30
|
+
"@t3-oss/env-core": "^0.12.0",
|
|
31
|
+
"@tanstack/react-query": "^5.62.11",
|
|
32
|
+
"better-auth": "^1.6.11",
|
|
33
|
+
"drizzle-orm": "1.0.0-beta.6-4414a19",
|
|
34
|
+
"elysia": "^1.4.29",
|
|
35
|
+
"nodemailer": "^7.0.12",
|
|
36
|
+
"pg": "^8.13.1",
|
|
37
|
+
"pg-boss": "^12.5.4",
|
|
38
|
+
"questpie": "latest",
|
|
39
|
+
"zod": "^4.2.1"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@types/pg": "^8.11.10",
|
|
43
|
+
"bun-types": "latest",
|
|
44
|
+
"drizzle-kit": "1.0.0-beta.6-4414a19",
|
|
45
|
+
"typescript": "^5.9.2"
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Elysia entrypoint (headless QUESTPIE API).
|
|
3
|
+
*
|
|
4
|
+
* Mounts the framework-agnostic fetch handler under `/api` and redirects the
|
|
5
|
+
* root to the Scalar API reference. Elysia runs on Bun and begins serving as
|
|
6
|
+
* soon as `.listen()` is called — `bun run src/index.ts` boots the server.
|
|
7
|
+
*/
|
|
8
|
+
import { Elysia } from "elysia";
|
|
9
|
+
import { createFetchHandler } from "questpie/http";
|
|
10
|
+
|
|
11
|
+
import { env } from "@/lib/env";
|
|
12
|
+
import { app as questpie } from "@/questpie/server/app";
|
|
13
|
+
|
|
14
|
+
const handler = createFetchHandler(questpie, { basePath: "/api" });
|
|
15
|
+
|
|
16
|
+
new Elysia()
|
|
17
|
+
.all("/api/*", async ({ request }) => (await handler(request)) ?? new Response("Not Found", { status: 404 }))
|
|
18
|
+
.get("/", () => new Response(null, { status: 302, headers: { Location: "/api/docs" } }))
|
|
19
|
+
.listen(env.PORT ?? 3000);
|
|
20
|
+
|
|
21
|
+
console.log(`🚀 QUESTPIE headless API on http://localhost:${env.PORT ?? 3000}`);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { BetterAuthOptions } from "better-auth";
|
|
2
|
+
import { createAuthClient } from "better-auth/client";
|
|
3
|
+
|
|
4
|
+
import type { AppConfig } from "@/questpie/server/app";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Type-safe Better Auth client (vanilla, no React).
|
|
8
|
+
*
|
|
9
|
+
* `signIn`, `signUp`, `signOut`, `getSession`, etc. are fully typed from the
|
|
10
|
+
* app's auth configuration via `AppConfig["auth"]`. This headless template
|
|
11
|
+
* ships the framework-agnostic `better-auth/client` so a separate frontend or
|
|
12
|
+
* scripts can consume it.
|
|
13
|
+
*/
|
|
14
|
+
type AppAuthOptions = AppConfig["auth"] extends BetterAuthOptions
|
|
15
|
+
? AppConfig["auth"]
|
|
16
|
+
: BetterAuthOptions;
|
|
17
|
+
|
|
18
|
+
type AuthClientOptions = {
|
|
19
|
+
baseURL: string;
|
|
20
|
+
fetchOptions?: { credentials?: RequestCredentials };
|
|
21
|
+
$InferAuth: AppAuthOptions;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const authClient = createAuthClient<AuthClientOptions>({
|
|
25
|
+
baseURL:
|
|
26
|
+
typeof window !== "undefined"
|
|
27
|
+
? `${window.location.origin}/api/auth`
|
|
28
|
+
: `${process.env.APP_URL || "http://localhost:3000"}/api/auth`,
|
|
29
|
+
fetchOptions: { credentials: "include" },
|
|
30
|
+
} as AuthClientOptions);
|
|
31
|
+
|
|
32
|
+
export type AuthClient = typeof authClient;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { createClient } from "questpie/client";
|
|
2
|
+
|
|
3
|
+
import type { AppConfig } from "@/questpie/server/app";
|
|
4
|
+
|
|
5
|
+
export const client = createClient<AppConfig>({
|
|
6
|
+
baseURL:
|
|
7
|
+
typeof window !== "undefined"
|
|
8
|
+
? window.location.origin
|
|
9
|
+
: process.env.APP_URL || "http://localhost:3000",
|
|
10
|
+
basePath: "/api",
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export type AppClient = typeof client;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { createEnv } from "@t3-oss/env-core";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
export const env = createEnv({
|
|
5
|
+
server: {
|
|
6
|
+
DATABASE_URL: z.string().url(),
|
|
7
|
+
APP_URL: z.string().url().default("http://localhost:3000"),
|
|
8
|
+
PORT: z
|
|
9
|
+
.string()
|
|
10
|
+
.transform(Number)
|
|
11
|
+
.pipe(z.number().int().positive())
|
|
12
|
+
.default(3000),
|
|
13
|
+
BETTER_AUTH_SECRET: z.string().min(1).default("change-me-in-production"),
|
|
14
|
+
MAIL_ADAPTER: z.enum(["console", "smtp"]).default("console"),
|
|
15
|
+
SMTP_HOST: z.string().optional(),
|
|
16
|
+
SMTP_PORT: z
|
|
17
|
+
.string()
|
|
18
|
+
.transform(Number)
|
|
19
|
+
.pipe(z.number().int().positive())
|
|
20
|
+
.optional(),
|
|
21
|
+
},
|
|
22
|
+
runtimeEnv: process.env,
|
|
23
|
+
emptyStringAsUndefined: true,
|
|
24
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { QueryClient } from "@tanstack/react-query";
|
|
2
|
+
|
|
3
|
+
const ONE_MINUTE = 60 * 1000;
|
|
4
|
+
const FIVE_MINUTES = 5 * ONE_MINUTE;
|
|
5
|
+
|
|
6
|
+
export const queryClient = new QueryClient({
|
|
7
|
+
defaultOptions: {
|
|
8
|
+
queries: {
|
|
9
|
+
staleTime: ONE_MINUTE,
|
|
10
|
+
gcTime: FIVE_MINUTES,
|
|
11
|
+
refetchOnWindowFocus: false,
|
|
12
|
+
retry: 1,
|
|
13
|
+
},
|
|
14
|
+
mutations: {
|
|
15
|
+
retry: 0,
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { createQuestpieQueryOptions } from "@questpie/tanstack-query";
|
|
2
|
+
|
|
3
|
+
import { client } from "@/lib/client";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Typed TanStack Query option builders for this project.
|
|
7
|
+
*
|
|
8
|
+
* `q.collections.*`, `q.globals.*`, and `q.routes.*` return `queryOptions()` /
|
|
9
|
+
* `mutationOptions()` objects you pass straight into `useQuery` / `useMutation`.
|
|
10
|
+
* Full type inference flows from the server schema via `AppConfig`.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* const { data } = useQuery(q.collections.posts.find({ limit: 10 }));
|
|
14
|
+
* const create = useMutation(q.collections.posts.create());
|
|
15
|
+
*/
|
|
16
|
+
export const q = createQuestpieQueryOptions(client);
|
|
17
|
+
|
|
18
|
+
export type QueryOptions = typeof q;
|