diff --git a/src/content/docs/d1/tutorials/d1-and-orange-orm/index.mdx b/src/content/docs/d1/tutorials/d1-and-orange-orm/index.mdx new file mode 100644 index 000000000000000..cb8c8070dcc9b0d --- /dev/null +++ b/src/content/docs/d1/tutorials/d1-and-orange-orm/index.mdx @@ -0,0 +1,276 @@ +--- +updated: 2025-02-21 +difficulty: Beginner +content_type: Tutorial +pcx_content_type: tutorial +title: Query D1 using Orange ORM +description: Use Orange ORM to query a D1 database. +products: + - Workers +languages: + - TypeScript + - SQL +--- + +import { WranglerConfig, PackageManagers, Render, FileTree } from "~/components"; + +:::note +This is a community-created tutorial. +::: + +## What is Orange ORM? + +Orange ORM is an Object Relational Mapper for TypeScript, offering seamless integration with a variety of popular databases. Orange ORM supports both TypeScript and JavaScript, including both CommonJS and ECMAScript. + +Refer to the full [Orange ORM documentation](https://github.com/alfateam/orange-orm) for more information. + + +## Query D1 from a Cloudflare Worker using Orange ORM + +This example shows you how to set up and deploy a Cloudflare Worker that is accessing a D1 database from scratch. + +### Prerequisites + +- [`Node.js`](https://nodejs.org/en/) and [`npm`](https://docs.npmjs.com/getting-started) installed on your machine. +- A [Cloudflare account](https://dash.cloudflare.com). + +### 1. Create a Cloudflare Worker + +Open your terminal and create a Cloudflare Worker: + +1. Create a Worker named `orange-d1-example` by running: + + + + + +2. Change into your new project directory to start developing: + + ```sh + cd orange-d1-example + ``` + +### 2. Install Orange ORM + +:::note + +D1 is supported in Orange ORM as of [v4.5.0](https://github.com/alfateam/orange-orm/releases/tag/v4.5.0). + +::: + +```sh +npm install orange-orm +``` + + +### 3. Create your D1 database + +You can create a D1 database via the [Cloudflare dashboard](https://dash.cloudflare.com), or via `wrangler`. This tutorial uses the `wrangler` CLI. + +Open your terminal and run the following command: + +```sh +npx wrangler d1 create orange-demo-db +``` + +You should receive the following output on your terminal: + +```txt +✅ Successfully created DB 'orange-demo-db' in region EEUR +Created your database using D1's new storage backend. The new storage backend is not yet recommended for production workloads, but backs up your data via +point-in-time restore. + +{ + "d1_databases": [ + { + "binding": "DB", + "database_name": "orange-demo-db", + "database_id": "" + } + ] +} +``` + +You now have a D1 database in your Cloudflare account with a binding to your Cloudflare Worker. + +Copy the JSON snippet from the command output and paste it into your `wrangler.jsonc` file. Your `wrangler.jsonc` file should look similar to the following: + + + +```jsonc +{ + "$schema": "node_modules/wrangler/config-schema.json", + "name": "orange-d1-example", + "main": "src/index.ts", + "compatibility_date": "2025-02-14", + "observability": { + "enabled": true + }, + "d1_databases": [ + { + "binding": "DB", + "database_name": "orange-demo-db", + "database_id": "" + } + ] +} +``` + + + +Replace `` with the database ID of your D1 instance. If you were not able to fetch this ID from the terminal output, you can also find it in the [Cloudflare dashboard](https://dash.cloudflare.com/), or by running `npx wrangler d1 info orange-demo-db` in your terminal. + +Next, create a database table in the database to send queries to D1 using Orange ORM. + +### 4. Create a table in the database + +D1 has a [migration system](/d1/reference/migrations/), and in the following steps, you will use D1's migration system to create and run a migration against your database. + +1. Create a new migration using `wrangler`: + +```sh +npx wrangler d1 migrations create orange-demo-db create_user_table +``` + +2. When asked to create a new folder called `migrations`, enter `Y`. + +The command has now created a new directory called `migrations` and an empty file called `0001_create_user_table.sql` inside of it: + + +- migrations + - **0001_create_user_table.sql** + + +3. Edit the file so it looks like this: + +```sql +-- CreateTable +CREATE TABLE "User" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "email" TEXT NOT NULL, + "name" TEXT +); + +-- CreateIndex +CREATE UNIQUE INDEX "User_email_key" ON "User"("email"); +``` + +You now need to use the `wrangler d1 migrations apply` command to send this SQL statement to D1. This command accepts two flags: + +- `--local`: Executes the statement against a local version of D1. This local version of D1 is a SQLite database file that will be located in the `.wrangler/state` directory of your project. Use this approach when you want to develop and test your Worker on your local machine. Refer to [Local development](/d1/best-practices/local-development/) to learn more. +- `--remote`: Executes the statement against your remote version of D1. This version is used by your deployed Cloudflare Workers. Refer to [Remote development](/d1/best-practices/remote-development/) to learn more. + +In this tutorial, you will first test the Worker locally, then deploy your Worker. + +4. Open your terminal, and run both commands: + +```sh +# For the local database +npx wrangler d1 migrations apply orange-demo-db --local +``` + +```sh +# For the remote database +npx wrangler d1 migrations apply orange-demo-db --remote +``` + +Choose `Yes` both times when you are prompted to confirm that the migration should be applied. + +5. Next, create some data that you can query once the Worker is running. This time, you will run the SQL statement without storing it in a file. Run the following commands: + +```sh +# For the local database +npx wrangler d1 execute orange-demo-db --command "INSERT INTO \"User\" (\"email\", \"name\") VALUES ('jane@orange-orm.io', 'Jane Doe (Local)');" --local +``` + +```sh +# For the remote database +npx wrangler d1 execute orange-demo-db --command "INSERT INTO \"User\" (\"email\", \"name\") VALUES ('jane@orange-orm.io', 'Jane Doe (Remote)');" --remote +``` + +### 5. Query your database from the Worker + +To query your database from the Worker using Orange ORM, you need to: + +1. Create a `src/map.ts` file with the following code: + +```ts +import orange from 'orange-orm'; + +const map = orange.map(x => ({ + user: x.table('user').map(({ column }) => ({ + id: column('id').numeric().primary(), + email: column('email').string(), + name: column('name').string(), + })) +})); + +export default map; +``` + +2. Instantiate the `orange-orm` with the D1 instance, then send a query using the Orange client and return the result. To do this in the code, open `src/index.ts` and replace the entire content with the following: + +```ts +import map from './map'; + +export interface Env { + DB: D1Database; +} +export default { + async fetch(request, env, ctx): Promise { + const db = map.d1(env.DB); + const users = await db.user.getAll(); + return Response.json(users); + }, +} satisfies ExportedHandler; +``` + + + +### 6. Run the Worker locally + +1. Run the Worker locally by running the following command: + +```sh +npm run dev +``` + +2. Open your browser at [`http://localhost:8787`](http://localhost:8787/) to check the result of the database query. You should see the following JSON block: + +```json +[{ "id": 1, "email": "jane@orange-orm.io", "name": "Jane Doe (Local)" }] +``` + +### 7. Deploy the Worker + +To deploy the Worker, run the following command: + +```sh +npm run deploy +``` + +Access your Worker at `https://orange-d1-example.USERNAME.workers.dev`. Your browser should display the following data queried from your remote D1 database: + +```json +[{ "id": 1, "email": "jane@orange-orm.io", "name": "Jane Doe (Remote)" }] +``` + +### Summary + +By finishing this tutorial, you have deployed a Cloudflare Worker using D1 as a database and querying it via Orange ORM. + +## Related resources + +- [Orange ORM documentation](https://github.com/alfateam/orange-orm). +- To get help, open a new [GitHub Discussion](https://github.com/alfateam/orange-orm/discussions). +- Check out the [Discord](https://discord.gg/QjuEgvQXzd). +- Watch the [youtube video](https://youtu.be/1IwwjPr2lMs). +- Watch the [interview with the author](https://www.youtube.com/watch?v=roCK6HQlyHQ).