I had some troubles in past days in setting up MikroORM (Archived) with SvelteKit (Archived) so that I would like to share how I finally managed to do it.
First we need to start a new SvelteKit project without typescript1, and install a couple of MikroORM and Vite-related packages.
npm init svelte@next sveltekit-mikroorm
# Use a Skeleton project with Typescript
npm install --save @mikro-orm/core @mikro-orm/sqlite @mikro-orm/migrations vite-plugin-ts uuid
Then we have to change the typescript configuration by adding the following lines to tsconfig.json
under compilerOptions
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
and by adding the typescript plugin to the Vite config in vite.config.js
import { sveltekit } from '@sveltejs/kit/vite'
import viteTs from 'vite-plugin-ts'
/** @type {import('vite').UserConfig} */
const config = {
plugins: [
viteTs(),
sveltekit(),
]
}
export default config
Then we can start by defining our entity, like a simple Post structure
// src/lib/entities/Post.ts
import { Entity, Property, PrimaryKey } from '@mikro-orm/core'
import { v4 } from 'uuid'
@Entity()
export default class Post {
@PrimaryKey()
id!: string = v4()
@Property()
title!: string
@Property()
body!: string
constructor (title: string, body: string) {
this.title = title
this.body = body
}
}
and also write the database layer, which also takes care of creating and applying all migrations.
// src/lib/database.ts
import 'reflect-metadata'
import { MikroORM } from '@mikro-orm/core'
import Post from '$lib/entities/Post.ts'
const orm = await MikroORM.init({
entities: [Post],
dbName: "data.sqlite3",
type: "sqlite",
migrations: {
emit: "js",
},
})
// Create the new migrations, then apply them
const migrator = orm.getMigrator()
await migrator.createMigration()
await migrator.up()
// Export the orm as default
export default orm
Then create the migrations
folder in the repository root and add migrations/package.json
specifying that the file inside of it are in CJS format.
{
"type": "commonjs"
}
Now we can add our custom index view and relative backend functions to display available posts and to add new ones.
<script>
// src/routes/index.svelte
export let posts
</script>
<h1>List of Posts ({posts.length})</h1>
{#each posts as post}
<h2>{post.title}</h2>
<p>{post.body}</p>
{/each}
<form method="POST">
<label for="title">Title</label>
<input type="text" name="title" placeholder="Post Title" />
<br/>
<textarea name="body" placeholder="Post Content"></textarea>
<br/>
<input type="submit" value="New Post" />
</form>
// src/routes/index.js
import orm from '$lib/database.ts'
import Post from '$lib/entities/Post.ts'
export async function GET() {
const em = orm.em.fork()
let posts = await em.find(Post, {})
return { body: { posts } }
}
export async function POST({ request }) {
const em = orm.em.fork()
const form = await request.formData()
const data = Object.fromEntries(form)
const post = new Post(data.title, data.body)
await em.persistAndFlush([post])
return await GET()
}
So that now you have a simple website that persists posts into a database and allows everyone to add them. If you are interested in all the fine details, you can look at the commit diff (Archived).
Footnotes
-
If you have an already existing project with Typescript you have to remove
vitePreprocess
fromsvelte.config.js
and removetslib
,typescript
fromdevDependencies
. ↩