Skip to content

Commit f986348

Browse files
committed
feat(init): init project
0 parents  commit f986348

33 files changed

Lines changed: 14222 additions & 0 deletions

.editorconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
root = true
2+
3+
[*]
4+
indent_size = 2
5+
indent_style = space
6+
end_of_line = lf
7+
charset = utf-8
8+
trim_trailing_whitespace = true
9+
insert_final_newline = true
10+
11+
[*.md]
12+
trim_trailing_whitespace = false

.eslintignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
dist
2+
node_modules

.eslintrc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"root": true,
3+
"extends": ["@nuxt/eslint-config"]
4+
}

.gitignore

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Dependencies
2+
node_modules
3+
4+
# Logs
5+
*.log*
6+
7+
# Temp directories
8+
.temp
9+
.tmp
10+
.cache
11+
12+
# Yarn
13+
**/.yarn/cache
14+
**/.yarn/*state*
15+
16+
# Generated dirs
17+
dist
18+
19+
# Nuxt
20+
.nuxt
21+
.output
22+
.data
23+
.vercel_build_output
24+
.build-*
25+
.netlify
26+
27+
# Env
28+
.env
29+
30+
# Testing
31+
reports
32+
coverage
33+
*.lcov
34+
.nyc_output
35+
36+
# VSCode
37+
.vscode/*
38+
!.vscode/settings.json
39+
!.vscode/tasks.json
40+
!.vscode/launch.json
41+
!.vscode/extensions.json
42+
!.vscode/*.code-snippets
43+
44+
# Intellij idea
45+
*.iml
46+
.idea
47+
48+
# OSX
49+
.DS_Store
50+
.AppleDouble
51+
.LSOverride
52+
.AppleDB
53+
.AppleDesktop
54+
Network Trash Folder
55+
Temporary Items
56+
.apdisk
57+
58+
# EdgeDB
59+
**/*.edgeql.ts
60+
**/dbschema/queries.*
61+
**/dbschema/query-builder
62+
**/queries/*.edgeql.ts

.npmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
shamefully-hoist=true

README.md

Lines changed: 298 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,298 @@
1+
# Nuxt EdgeDB
2+
3+
[![npm version][npm-version-src]][npm-version-href]
4+
[![npm downloads][npm-downloads-src]][npm-downloads-href]
5+
[![License][license-src]][license-href]
6+
[![Nuxt][nuxt-src]][nuxt-href]
7+
8+
[Nuxt 3](https://nuxt.com) integration for [EdgeDB](https://www.edgedb.com) that aims at being the fastest way to add a fully typed database layer to your Nuxt 3 project.
9+
10+
- [ Release Notes](/CHANGELOG.md)
11+
12+
## Features
13+
14+
- 🍱  Zero-config setup; just add `nuxt-edgedb` to your `modules`
15+
- 🧙  [EdgeDB CLI install](https://www.edgedb.com/docs/cli/index) and [project init](https://www.edgedb.com/docs/cli/edgedb_project/edgedb_project_init) wizards
16+
- 🎩  Watchers on `dbschema/*`, `queries/*`, `dbschema/migrations/*` bringing _HMR_ to your database
17+
- 🛟  Auto-imported typed database query client provided by [`@edgedb/generate`](https://www.edgedb.com/docs/clients/js/generation)
18+
- 🍩  [`edgedb ui`](https://www.edgedb.com/docs/cli/edgedb_ui) injected into [Nuxt Devtools](https://github.com/nuxt/devtools)
19+
20+
## Quick Setup
21+
22+
1. Add `nuxt-edgedb` dependency to your project
23+
24+
```bash
25+
# Using pnpm
26+
pnpm add -D nuxt-edgedb
27+
28+
# Using yarn
29+
yarn add --dev nuxt-edgedb
30+
31+
# Using npm
32+
npm install --save-dev nuxt-edgedb
33+
```
34+
35+
2. Add `nuxt-edgedb` to the `modules` section of `nuxt.config.ts`
36+
37+
```js
38+
export default defineNuxtConfig({
39+
modules: [
40+
'nuxt-edgedb'
41+
],
42+
// Optional, all options has sufficient defaults.
43+
edgedb: {
44+
devtools: true,
45+
watch: true,
46+
dbschemaDir: 'dbschema',
47+
queriesDir: 'queries',
48+
generateInterfaces: true,
49+
generateQueries: true,
50+
generateQueryBuilder: true,
51+
}
52+
})
53+
```
54+
55+
That's it! You can now use Nuxt EdgeDB in your Nuxt app. ✨
56+
57+
If you do not already have [EdgeDB](https://www.edgedb.com) installed on your machine, the install wizard will prompt you to install it. 🧙
58+
59+
## Usage
60+
61+
The module provides 2 auto-imported composables available anywhere inside `server/` context of your Nuxt app.
62+
63+
### useEdgeDb
64+
65+
`useEdgeDb` exposes the raw client from `edgedb` import, that properly uses your Nuxt environment configuration.
66+
67+
```typescript
68+
// server/api/blogpost/[id].ts
69+
import { defineEventHandler, getRouterParams } from 'h3'
70+
71+
export default defineEventHandler(async (req) => {
72+
const params = getRouterParams(req)
73+
74+
const id = params.id
75+
76+
const client = useEdgeDb()
77+
78+
const blogpost = await client.querySingle(`
79+
select BlogPost {
80+
title,
81+
description
82+
} filter .id = ${id}
83+
`)
84+
85+
return blogpost
86+
})
87+
```
88+
89+
### useEdgeDbQueries
90+
91+
`useEdgeDbQueries` exposes all your queries from `dbschema/queries.ts` except you do not need to pass them a client.
92+
93+
They will use the one generated by `useEdgeDb` and is scoped to the current request.
94+
95+
```esdl
96+
// queries/getBlogPost.edgeql
97+
select BlogPost {
98+
title,
99+
description
100+
} filter .id = <uuid>$blogpost_id
101+
```
102+
103+
```typescript
104+
// server/api/blogpost/[id].ts
105+
import { defineEventHandler, getRouterParams } from 'h3'
106+
107+
export default defineEventHandler(async (req) => {
108+
const params = getRouterParams(req)
109+
110+
const id = params.id
111+
112+
const { getBlogpPost } = useEdgeDbQueries()
113+
114+
const blogPost = await getBlogpost({ blogpost_id: id })
115+
116+
return blogpost
117+
})
118+
```
119+
120+
You can still import [queries](https://www.edgedb.com/docs/clients/js/queries) directly from `@db/queries` and pass them the client from `useEdgeDb()`.
121+
122+
```typescript
123+
// server/api/blogpost/[id].ts
124+
import { getBlogPost } from '@db/queries'
125+
import { defineEventHandler, getRouterParams } from 'h3'
126+
127+
export default defineEventHandler(async (req) => {
128+
const params = getRouterParams(req)
129+
130+
const id = params.id
131+
132+
const client = useEdgeDb()
133+
134+
const blogPost = await getBlogpost(client, { blogpost_id: id })
135+
136+
return blogpost
137+
})
138+
```
139+
140+
### useEdgeDbQueryBuilder
141+
142+
`useEdgeDbQueryBuilder` exposes the generated [query builder](https://www.edgedb.com/docs/clients/js/querybuilder) directly to your `server/` context.
143+
144+
```typescript
145+
// server/api/blogpost/[id].ts
146+
import { defineEventHandler, getRouterParams } from 'h3'
147+
148+
export default defineEventHandler(async (req) => {
149+
const params = getRouterParams(req)
150+
151+
const id = params.id
152+
153+
const client = useEdgeDb()
154+
const e = useEdgeDbQueryBuilder()
155+
156+
const blogPostQuery = e.select(
157+
e.BlogPost,
158+
(blogPost) => ({
159+
id: true,
160+
title: true,
161+
description: true,
162+
filter_single: { id }
163+
})
164+
)
165+
166+
const blogPost = await blogPostQuery.run(client)
167+
168+
return blogpost
169+
})
170+
```
171+
172+
### Typings
173+
174+
All the interfaces generated by EdgeDB are available throuh imports via `@db/interfaces`.
175+
176+
```vue
177+
<script setup lang="ts">
178+
import type { BlogPost } from '@db/interfaces'
179+
180+
defineProps<{ blogPost: BlogPost }>()
181+
</script>
182+
```
183+
184+
## Production
185+
186+
If you want to get out of development and deploy your database to prodution, you must follow [EdgeDB guides](https://www.edgedb.com/docs/guides/deployment/index).
187+
188+
[EdgeDB](https://www.edgedb.com) is an open-source database that is designed to be self-hosted.
189+
190+
However, they also offer a [Cloud](https://www.edgedb.com/docs/guides/cloud), which is fully compatible with this module thanks to environment variables.
191+
192+
## Q&A
193+
194+
### Will my database client be exposed in userland?
195+
196+
No, `useEdgeDb` and `useEdgeDbQueries` are only available in [server/](https://nuxt.com/docs/guide/directory-structure/server) context of Nuxt.
197+
198+
You can, as an **opt-in** feature, import queries from `@dbschema/queries` on the client.
199+
200+
You will need to provide these queries with a client from `createClient()`.
201+
202+
```vue
203+
<script setup lang="ts">
204+
import { createClient } from 'edgedb'
205+
import { getUser } from '@dbschema/queries'
206+
207+
const client = createClient()
208+
209+
const user = await getUser(client, 42)
210+
</script>
211+
```
212+
213+
You can also, still as an **opt-in** feature, import the query builder to the client.
214+
215+
I guess that can be useful for a super-admin/internal dashboard, but use it at your own risks in terms of security access.
216+
217+
```vue
218+
<script setup lang="ts">
219+
import e, { type $infer } from '@db/builder'
220+
221+
const query = e.select(e.Movie, () => ({ id: true, title: true }));
222+
type result = $infer<typeof query>;
223+
// ^ { id: string; title: string }[]
224+
</script>
225+
```
226+
227+
Be careful with these imports, as if you import wrong queries, you might end up with write operations available to the client, potentially exposing your database.
228+
229+
### How do I run my migrations in production?
230+
231+
- Clone your Nuxt project on your production environment
232+
- Ensure you have [EdgeDB CLI](https://www.edgedb.com/docs/cli/index) installed on the server
233+
- Add `edgedb migrate --quiet` to your CLI script
234+
235+
### Should I version generated files?
236+
237+
No, as they are generated with your Nuxt client, you should add them to your `.gitignore`
238+
239+
```.gitignore
240+
**/*.edgeql.ts
241+
dbschema/queries.*
242+
dbschema/query-builder
243+
```
244+
245+
You must change these paths accordingly if you change the `**Dir` options.
246+
247+
### Is HMR for my database schema really safe?
248+
249+
Well, it depends on when you want to use it.
250+
251+
I would suggest keeping `watchPrompt` enabled while you casually dev on your project.
252+
253+
That will prevent from running any unwanted migration, and will only prompt when you add new things to your schemas.
254+
255+
If you want to go fast and know what you are doing, you can set `watchPrompt` to false, and profit from automatic migration creation and applying on any change on your schemas.
256+
257+
If you do not want any of these features, just set `watch` to false and you are free to feel safe about changes applied to your development database.
258+
259+
> HMR on your database obviously has **NO** effect in production context.
260+
261+
## Development
262+
263+
```bash
264+
# Install dependencies
265+
npm install
266+
267+
# Generate type stubs
268+
npm run dev:prepare
269+
270+
# Develop with the playground
271+
npm run dev
272+
273+
# Build the playground
274+
npm run dev:build
275+
276+
# Run ESLint
277+
npm run lint
278+
279+
# Run Vitest
280+
npm run test
281+
npm run test:watch
282+
283+
# Release new version
284+
npm run release
285+
```
286+
287+
<!-- Badges -->
288+
[npm-version-src]: https://img.shields.io/npm/v/nuxt-edgedb/latest.svg?style=flat&colorA=18181B&colorB=28CF8D
289+
[npm-version-href]: https://npmjs.com/package/nuxt-edgedb
290+
291+
[npm-downloads-src]: https://img.shields.io/npm/dm/nuxt-edgedb.svg?style=flat&colorA=18181B&colorB=28CF8D
292+
[npm-downloads-href]: https://npmjs.com/package/nuxt-edgedb
293+
294+
[license-src]: https://img.shields.io/npm/l/nuxt-edgedb.svg?style=flat&colorA=18181B&colorB=28CF8D
295+
[license-href]: https://npmjs.com/package/nuxt-edgedb
296+
297+
[nuxt-src]: https://img.shields.io/badge/Nuxt-18181B?logo=nuxt.js
298+
[nuxt-href]: https://nuxt.com

0 commit comments

Comments
 (0)