-
Notifications
You must be signed in to change notification settings - Fork 10k
Orange ORM with D1 tutorial #20165
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Orange ORM with D1 tutorial #20165
Changes from 16 commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
190c954
orange tutorial
lroal b5db0d7
typos
lroal 10d0496
jsonc
lroal 7f839dc
typos
lroal c107730
Update src/content/docs/d1/tutorials/d1-and-orange-orm/index.mdx
lroal 4ccae3e
Update src/content/docs/d1/tutorials/d1-and-orange-orm/index.mdx
lroal e45f161
Update src/content/docs/d1/tutorials/d1-and-orange-orm/index.mdx
Oxyjun becc38d
Update src/content/docs/d1/tutorials/d1-and-orange-orm/index.mdx
Oxyjun c1c721c
Update src/content/docs/d1/tutorials/d1-and-orange-orm/index.mdx
Oxyjun e94698a
Update src/content/docs/d1/tutorials/d1-and-orange-orm/index.mdx
Oxyjun 8b22133
Update src/content/docs/d1/tutorials/d1-and-orange-orm/index.mdx
Oxyjun bd95525
Apply suggestions from code review
Oxyjun 5e17422
Apply suggestions from code review
Oxyjun cce3a72
Apply suggestions from code review
Oxyjun d8d5a2f
Apply suggestions from code review
Oxyjun 9d6d19d
Apply suggestions from code review
Oxyjun f15cc37
Apply suggestions from code review
Oxyjun 70e04cc
Update src/content/docs/d1/tutorials/d1-and-orange-orm/index.mdx
Oxyjun 9c3a2e1
Apply suggestions from code review
Oxyjun 86ab52c
Update src/content/docs/d1/tutorials/d1-and-orange-orm/index.mdx
Oxyjun d773abf
Apply suggestions from code review part 1
Oxyjun b217f70
Apply suggestions from code review part 2
Oxyjun d815c8e
Update src/content/docs/d1/tutorials/d1-and-orange-orm/index.mdx
Oxyjun 0e32987
Update src/content/docs/d1/tutorials/d1-and-orange-orm/index.mdx
Oxyjun File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
277 changes: 277 additions & 0 deletions
277
src/content/docs/d1/tutorials/d1-and-orange-orm/index.mdx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,277 @@ | ||
| --- | ||
| updated: 2025-02-21 | ||
| difficulty: Beginner | ||
| content_type: Tutorial | ||
| pcx_content_type: tutorial | ||
| title: Query D1 using Orange ORM | ||
| products: | ||
| - Workers | ||
| languages: | ||
| - TypeScript | ||
| - SQL | ||
| --- | ||
|
|
||
| import { WranglerConfig, PackageManagers, Render, FileTree } from "~/components"; | ||
|
|
||
Oxyjun marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ## What is Orange ORM? | ||
|
|
||
| [Orange ORM](https://github.com/alfateam/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. | ||
Oxyjun marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| - **Rich Querying Model**: Orange provides a powerful and intuitive querying model, making it easy to retrieve, filter, and manipulate data from your databases. | ||
| - **Active Record**: With a concise and expressive syntax, Orange enables you to interact with your database using the [*Active Record Pattern*](https://en.wikipedia.org/wiki/Active_record_pattern). | ||
| - **No Code Generation Required**: Enjoy full IntelliSense, even in table mappings, without the need for cumbersome code generation. | ||
| - **TypeScript and JavaScript Support**: Orange fully supports both TypeScript and JavaScript, allowing you to leverage the benefits of static typing and modern ECMAScript features. | ||
| - **Works in the Browser**: You can securely use Orange in the browser by utilizing the Express.js plugin, which serves to safeguard sensitive database credentials from exposure at the client level and protect against SQL injection. This method mirrors a traditional REST API, augmented with advanced TypeScript tooling for enhanced functionality. | ||
Oxyjun marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
|
|
||
| ## 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 run the following command to create a Cloudflare Worker using Cloudflare's [`hello-world`](https://github.com/cloudflare/workers-sdk/tree/4fdd8987772d914cf50725e9fa8cb91a82a6870d/packages/create-cloudflare/templates/hello-world) template: | ||
Oxyjun marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
Oxyjun marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| 1. Create a Worker named `d1-http` by running: | ||
Oxyjun marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
Oxyjun marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| <PackageManagers type="create" pkg="cloudflare@latest" args={"orange-d1-example"} /> | ||
|
|
||
| <Render | ||
| file="c3-post-run-steps" | ||
| product="workers" | ||
| params={{ | ||
| category: "hello-world", | ||
| type: "Hello World Worker", | ||
| lang: "TypeScript", | ||
| }} | ||
| /> | ||
|
|
||
| 2. Change into your new project directory to start developing: | ||
|
|
||
| ```sh frame="none" | ||
Oxyjun marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
Oxyjun marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| cd orange-d1-example | ||
| ``` | ||
|
|
||
| ```sh frame="none" | ||
| cd orange-d1-example | ||
| ``` | ||
|
|
||
Oxyjun marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| ### 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 | ||
| cd orange-d1-example | ||
Oxyjun marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| npm install orange-orm | ||
Oxyjun marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| You can create a D1 database via the [Cloudflare dashboard](https://dash.cloudflare.com), or via `wrangler`. This tutorial uses the `wrangler` CLI. | ||
Oxyjun marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ### 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: | ||
|
|
||
| ``` | ||
Oxyjun marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| ✅ 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": "<YOUR_D1_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: | ||
Oxyjun marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| <WranglerConfig> | ||
|
|
||
| ```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": "<YOUR_D1_DATABASE_ID>" | ||
| } | ||
| ] | ||
| } | ||
| ``` | ||
|
|
||
| </WranglerConfig> | ||
|
|
||
| `<YOUR_D1_DATABASE_ID>` should be replaced 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. | ||
Oxyjun marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| Next, create a database table in the database to send queries to D1 using Orange ORM. | ||
|
|
||
| ### 4. Create a table in the database | ||
|
|
||
Oxyjun marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| 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. | ||
Oxyjun marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| 1. First, create a new migration using `wrangler`: | ||
Oxyjun marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ```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: | ||
|
|
||
| <FileTree> | ||
| - migrations | ||
| - **0001_create_user_table.sql** | ||
| </FileTree> | ||
|
|
||
| 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"); | ||
| ``` | ||
|
|
||
Oxyjun marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| 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 afterwards. | ||
Oxyjun marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| 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 ('[email protected]', 'Jane Doe (Local)');" --local | ||
| ``` | ||
|
|
||
| ```sh | ||
| # For the remote database | ||
| npx wrangler d1 execute orange-demo-db --command "INSERT INTO \"User\" (\"email\", \"name\") VALUES ('[email protected]', '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` with the following code: | ||
Oxyjun marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ```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; | ||
Oxyjun marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| 2. Instantiate the orange-orm with the D1 instance. Open `src/index.ts` and replace the entire content with the following: | ||
Oxyjun marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
Oxyjun marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ```ts | ||
| import map from './map'; | ||
|
|
||
| export interface Env { | ||
| DB: D1Database; | ||
| } | ||
| export default { | ||
| async fetch(request, env, ctx): Promise<Response> { | ||
| const db = map.d1(env.DB); | ||
| const users = await db.user.getAll(); | ||
| return Response.json(users); | ||
| }, | ||
| } satisfies ExportedHandler<Env>; | ||
Oxyjun marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| 3. Send a query using the orange client and return the result. | ||
Oxyjun marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
Oxyjun marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
|
|
||
| ### 6. Run the Worker locally | ||
|
|
||
Oxyjun marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| 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: | ||
Oxyjun marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ```json | ||
| [{ "id": 1, "email": "[email protected]", "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": "[email protected]", "name": "Jane Doe (Remote)" }] | ||
| ``` | ||
|
|
||
Oxyjun marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ### 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). | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.