@3lineas/d1-orm 1.0.7 → 1.0.9
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/README.md +41 -148
- package/dist/chunk-N3G6NOJP.js +127 -0
- package/dist/cli/index.cjs +794 -0
- package/dist/cli/index.js +260 -257
- package/dist/{index.mjs → index.cjs} +159 -14
- package/dist/{index.d.mts → index.d.cts} +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +6 -157
- package/package.json +2 -2
- package/dist/chunk-5BBZKUNZ.mjs +0 -147
- package/dist/cli/index.mjs +0 -559
- /package/dist/cli/{index.d.mts → index.d.cts} +0 -0
package/README.md
CHANGED
|
@@ -20,196 +20,92 @@ pnpm add @3lineas/d1-orm
|
|
|
20
20
|
|
|
21
21
|
## Initial Setup
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
By default, the ORM attempts to **auto-initialize** itself if your D1 binding is named `DB`.
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
import { Database } from "@3lineas/d1-orm";
|
|
27
|
-
|
|
28
|
-
export default {
|
|
29
|
-
async fetch(request, env, ctx) {
|
|
30
|
-
// Initialize the D1 connection (assuming it's named DB in wrangler.toml)
|
|
31
|
-
Database.setup(env.DB);
|
|
32
|
-
|
|
33
|
-
// ... your routing logic
|
|
34
|
-
},
|
|
35
|
-
};
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
## Defining Models
|
|
39
|
-
|
|
40
|
-
Define your models by extending the `Model` class. By default, the ORM assumes the table name is the lowercase plural form of the class name (e.g., `User` -> `users`).
|
|
25
|
+
For zero-configuration setup in Cloudflare Workers or Next.js:
|
|
41
26
|
|
|
42
27
|
```typescript
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
export class User extends Model {
|
|
46
|
-
// Optional: Custom table name
|
|
47
|
-
// protected static table = 'my_users';
|
|
48
|
-
|
|
49
|
-
// Optional: Define attributes for typing (recommended)
|
|
50
|
-
declare id: number;
|
|
51
|
-
declare name: string;
|
|
52
|
-
declare email: string;
|
|
53
|
-
declare created_at: string;
|
|
54
|
-
}
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
## CRUD Operations
|
|
58
|
-
|
|
59
|
-
### Create
|
|
60
|
-
|
|
61
|
-
```typescript
|
|
62
|
-
const user = await User.create({
|
|
63
|
-
name: "John Doe",
|
|
64
|
-
email: "john@example.com",
|
|
65
|
-
});
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
### Read
|
|
69
|
-
|
|
70
|
-
```typescript
|
|
71
|
-
// Get all records
|
|
28
|
+
// No manual setup required if binding name is 'DB'!
|
|
72
29
|
const users = await User.all();
|
|
73
|
-
|
|
74
|
-
// Find by ID
|
|
75
|
-
const user = await User.find(1);
|
|
76
|
-
|
|
77
|
-
// Custom queries
|
|
78
|
-
const activeUsers = await User.where("status", "=", "active")
|
|
79
|
-
.orderBy("created_at", "desc")
|
|
80
|
-
.get();
|
|
81
|
-
|
|
82
|
-
// Get the first result
|
|
83
|
-
const firstUser = await User.where("email", "john@example.com").first();
|
|
84
30
|
```
|
|
85
31
|
|
|
86
|
-
|
|
32
|
+
If you use a custom binding name or want manual control:
|
|
87
33
|
|
|
88
34
|
```typescript
|
|
89
|
-
|
|
90
|
-
if (user) {
|
|
91
|
-
user.fill({ name: "Updated Name" });
|
|
92
|
-
await user.save();
|
|
93
|
-
}
|
|
35
|
+
import { Database } from "@3lineas/d1-orm";
|
|
94
36
|
|
|
95
|
-
|
|
96
|
-
|
|
37
|
+
export default {
|
|
38
|
+
async fetch(request, env, ctx) {
|
|
39
|
+
Database.setup(env.MY_CUSTOM_DB);
|
|
40
|
+
// ...
|
|
41
|
+
},
|
|
42
|
+
};
|
|
97
43
|
```
|
|
98
44
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
```typescript
|
|
102
|
-
const user = await User.find(1);
|
|
103
|
-
if (user) {
|
|
104
|
-
await user.delete();
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// Or delete directly via query
|
|
108
|
-
await User.where("status", "banned").delete();
|
|
109
|
-
```
|
|
45
|
+
## Directory Structure
|
|
110
46
|
|
|
111
|
-
|
|
47
|
+
When you run `init`, the ORM creates a unified structure in `src/database` (if `src` exists) or `database/`:
|
|
112
48
|
|
|
113
|
-
|
|
49
|
+
- `database/models/`: Your Eloquent-style models.
|
|
50
|
+
- `database/migrations/`: SQL migration files.
|
|
51
|
+
- `database/seeders/`: Data seeders.
|
|
52
|
+
- `database/config.ts`: Central configuration.
|
|
114
53
|
|
|
115
|
-
###
|
|
54
|
+
### Configuration (`database/config.ts`)
|
|
116
55
|
|
|
117
56
|
```typescript
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// Usage
|
|
124
|
-
const profile = await user.hasOneProfile().get();
|
|
57
|
+
export default {
|
|
58
|
+
binding: "DB", // The name of your D1 binding
|
|
59
|
+
};
|
|
125
60
|
```
|
|
126
61
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
```typescript
|
|
130
|
-
// In User Model
|
|
131
|
-
posts() {
|
|
132
|
-
return this.hasMany(Post);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// Usage
|
|
136
|
-
const posts = await user.posts().get();
|
|
137
|
-
```
|
|
62
|
+
## Defining Models
|
|
138
63
|
|
|
139
|
-
|
|
64
|
+
Define your models by extending the `Model` class. Models are typically placed in `database/models/`.
|
|
140
65
|
|
|
141
66
|
```typescript
|
|
142
|
-
|
|
143
|
-
user() {
|
|
144
|
-
return this.belongsTo(User);
|
|
145
|
-
}
|
|
67
|
+
import { Model } from "@3lineas/d1-orm";
|
|
146
68
|
|
|
147
|
-
|
|
148
|
-
|
|
69
|
+
export class User extends Model {
|
|
70
|
+
declare id: number;
|
|
71
|
+
declare name: string;
|
|
72
|
+
}
|
|
149
73
|
```
|
|
150
74
|
|
|
151
75
|
## CLI & Migrations
|
|
152
76
|
|
|
153
|
-
The ORM includes a CLI
|
|
154
|
-
|
|
155
|
-
### Automatic Configuration
|
|
77
|
+
The ORM includes a modern, Astro-style CLI for database management.
|
|
156
78
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
To run the initial command (before the script is added):
|
|
79
|
+
### Initialization
|
|
160
80
|
|
|
161
81
|
```bash
|
|
162
|
-
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
Once executed, the `orm` script will be added to your `package.json`:
|
|
166
|
-
|
|
167
|
-
```json
|
|
168
|
-
"scripts": {
|
|
169
|
-
"orm": "d1-orm"
|
|
170
|
-
}
|
|
82
|
+
pnpm d1-orm init
|
|
171
83
|
```
|
|
172
84
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
```bash
|
|
176
|
-
pnpm orm ...
|
|
177
|
-
```
|
|
85
|
+
This command is non-interactive and automatically detects your project structure.
|
|
178
86
|
|
|
179
87
|
### Available Commands
|
|
180
88
|
|
|
181
|
-
####
|
|
182
|
-
|
|
183
|
-
An interactive command that sets up your project. It will ask where you want to keep your models and will automatically generate the directory structure, an example `User` model, its migration, and a seeder.
|
|
184
|
-
|
|
185
|
-
#### Create a Model
|
|
186
|
-
|
|
187
|
-
Generate a model file interactively. It allows you to optionally create a linked migration and seeder.
|
|
89
|
+
#### Create Files
|
|
188
90
|
|
|
189
91
|
```bash
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
#### Create a Migration
|
|
92
|
+
# Create a model (and optionally migration/seeder)
|
|
93
|
+
pnpm orm make:model User
|
|
194
94
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
```bash
|
|
198
|
-
pnpm orm make:migration
|
|
95
|
+
# Create a standalone migration
|
|
96
|
+
pnpm orm make:migration create_posts_table
|
|
199
97
|
```
|
|
200
98
|
|
|
201
99
|
#### Run Migrations
|
|
202
100
|
|
|
203
|
-
Run pending migrations.
|
|
204
|
-
|
|
205
101
|
```bash
|
|
206
|
-
# Local
|
|
102
|
+
# Local
|
|
207
103
|
pnpm orm migrate
|
|
208
104
|
|
|
209
|
-
# Remote
|
|
105
|
+
# Remote
|
|
210
106
|
pnpm orm migrate --remote
|
|
211
107
|
|
|
212
|
-
#
|
|
108
|
+
# Migrate and then seed
|
|
213
109
|
pnpm orm migrate --seed
|
|
214
110
|
```
|
|
215
111
|
|
|
@@ -230,12 +126,9 @@ Run seeders defined in `database/seeders`.
|
|
|
230
126
|
|
|
231
127
|
```bash
|
|
232
128
|
pnpm orm db:seed
|
|
233
|
-
|
|
234
|
-
# Remote
|
|
235
|
-
pnpm orm db:seed --remote
|
|
236
129
|
```
|
|
237
130
|
|
|
238
|
-
> **Note:**
|
|
131
|
+
> **Note:** The CLI automatically detects your `wrangler.jsonc`, `wrangler.json` or `wrangler.toml` to find your D1 binding.
|
|
239
132
|
|
|
240
133
|
---
|
|
241
134
|
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
// src/core/connection.ts
|
|
2
|
+
var Connection = class {
|
|
3
|
+
/**
|
|
4
|
+
* The underlying D1Database instance.
|
|
5
|
+
*/
|
|
6
|
+
db;
|
|
7
|
+
/**
|
|
8
|
+
* Create a new Connection instance.
|
|
9
|
+
*
|
|
10
|
+
* @param database - The D1Database instance.
|
|
11
|
+
*/
|
|
12
|
+
constructor(database) {
|
|
13
|
+
this.db = database;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Execute a SELECT statement.
|
|
17
|
+
*
|
|
18
|
+
* @param query - The SQL query string.
|
|
19
|
+
* @param bindings - The parameter bindings.
|
|
20
|
+
* @returns A promise that resolves to an array of results.
|
|
21
|
+
*/
|
|
22
|
+
async select(query, bindings = []) {
|
|
23
|
+
const stmt = this.db.prepare(query).bind(...bindings);
|
|
24
|
+
const result = await stmt.all();
|
|
25
|
+
return result.results || [];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Execute an INSERT statement.
|
|
29
|
+
*
|
|
30
|
+
* @param query - The SQL query string.
|
|
31
|
+
* @param bindings - The parameter bindings.
|
|
32
|
+
* @returns A promise that resolves to true on success.
|
|
33
|
+
*/
|
|
34
|
+
async insert(query, bindings = []) {
|
|
35
|
+
const stmt = this.db.prepare(query).bind(...bindings);
|
|
36
|
+
const result = await stmt.run();
|
|
37
|
+
return result.success;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Execute an UPDATE statement.
|
|
41
|
+
*
|
|
42
|
+
* @param query - The SQL query string.
|
|
43
|
+
* @param bindings - The parameter bindings.
|
|
44
|
+
* @returns A promise that resolves to true on success.
|
|
45
|
+
*/
|
|
46
|
+
async update(query, bindings = []) {
|
|
47
|
+
const stmt = this.db.prepare(query).bind(...bindings);
|
|
48
|
+
const result = await stmt.run();
|
|
49
|
+
return result.success;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Execute a DELETE statement.
|
|
53
|
+
*
|
|
54
|
+
* @param query - The SQL query string.
|
|
55
|
+
* @param bindings - The parameter bindings.
|
|
56
|
+
* @returns A promise that resolves to true on success.
|
|
57
|
+
*/
|
|
58
|
+
async delete(query, bindings = []) {
|
|
59
|
+
const stmt = this.db.prepare(query).bind(...bindings);
|
|
60
|
+
const result = await stmt.run();
|
|
61
|
+
return result.success;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Execute an arbitrary SQL statement.
|
|
65
|
+
*
|
|
66
|
+
* @param query - The SQL query string.
|
|
67
|
+
* @param bindings - The parameter bindings.
|
|
68
|
+
* @returns A promise that resolves to true on success.
|
|
69
|
+
*/
|
|
70
|
+
async statement(query, bindings = []) {
|
|
71
|
+
const stmt = this.db.prepare(query).bind(...bindings);
|
|
72
|
+
const result = await stmt.run();
|
|
73
|
+
return result.success;
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
// src/core/database.ts
|
|
78
|
+
var Database = class _Database {
|
|
79
|
+
/**
|
|
80
|
+
* Symbol for global singleton access.
|
|
81
|
+
*/
|
|
82
|
+
static INSTANCE_KEY = /* @__PURE__ */ Symbol.for("d1-orm-instance");
|
|
83
|
+
/**
|
|
84
|
+
* The active database connection.
|
|
85
|
+
*/
|
|
86
|
+
connection;
|
|
87
|
+
/**
|
|
88
|
+
* Private constructor to enforce singleton pattern.
|
|
89
|
+
*
|
|
90
|
+
* @param d1 - The D1Database instance from Cloudflare.
|
|
91
|
+
*/
|
|
92
|
+
constructor(d1) {
|
|
93
|
+
this.connection = new Connection(d1);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Setup the database connection.
|
|
97
|
+
*
|
|
98
|
+
* @param d1 - The D1Database instance from Cloudflare environment (env.DB).
|
|
99
|
+
*/
|
|
100
|
+
static setup(d1) {
|
|
101
|
+
globalThis[_Database.INSTANCE_KEY] = new _Database(d1);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Get the singleton Database instance.
|
|
105
|
+
*
|
|
106
|
+
* @throws Error if setup() has not been called and auto-init fails.
|
|
107
|
+
* @returns The Database instance.
|
|
108
|
+
*/
|
|
109
|
+
static getInstance() {
|
|
110
|
+
const instance = globalThis[_Database.INSTANCE_KEY];
|
|
111
|
+
if (!instance) {
|
|
112
|
+
if (globalThis["DB"] && typeof globalThis["DB"].prepare === "function") {
|
|
113
|
+
_Database.setup(globalThis["DB"]);
|
|
114
|
+
return globalThis[_Database.INSTANCE_KEY];
|
|
115
|
+
}
|
|
116
|
+
throw new Error(
|
|
117
|
+
"Database not initialized. Call Database.setup(env.DB) first or ensure your D1 binding is named 'DB'."
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
return instance;
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
export {
|
|
125
|
+
Connection,
|
|
126
|
+
Database
|
|
127
|
+
};
|