mevn-orm 4.0.1 → 4.0.3

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.
Files changed (2) hide show
  1. package/README.md +78 -170
  2. package/package.json +2 -2
package/README.md CHANGED
@@ -8,10 +8,10 @@ Mevn ORM is a small ActiveRecord-style ORM built on top of Knex.
8
8
 
9
9
  It exports:
10
10
  - `Model`: base class for your models
11
- - `configureDatabase`: initialize with simple DB options by dialect
12
- - `configure`: initialize with raw Knex config (advanced)
11
+ - `configureDatabase`: initialise with simple DB options by `client`
12
+ - `configure`: initialise with raw Knex config (advanced)
13
13
  - migration helpers: `makeMigration`, `migrateLatest`, `migrateRollback`, `migrateList`, `migrateCurrentVersion`
14
- - `DB`: initialized Knex instance (after `configure`)
14
+ - `DB`: initialised Knex instance (after `configure`)
15
15
 
16
16
  ## Status
17
17
 
@@ -20,18 +20,21 @@ This project is in maintenance mode. Core functionality works, but new features
20
20
  ## Requirements
21
21
 
22
22
  - Node.js 20+ (ESM runtime)
23
- - Database driver for your selected client (`mysql2`, `sqlite3`, etc.)
23
+ - Database driver for your selected client (`mysql2`, `pg`, `sqlite3`, etc.)
24
24
 
25
25
  ## Installation
26
26
 
27
27
  ```bash
28
- npm install mevn-orm knex mysql2
29
- ```
28
+ npm install mevn-orm knex
29
+ npm install mysql2
30
+ ````
30
31
 
31
32
  For SQLite development/testing:
32
33
 
33
34
  ```bash
34
35
  npm install sqlite3
36
+ # or:
37
+ npm install better-sqlite3
35
38
  ```
36
39
 
37
40
  ## Quick Start
@@ -42,23 +45,26 @@ npm install sqlite3
42
45
  import { configureDatabase } from 'mevn-orm'
43
46
 
44
47
  configureDatabase({
45
- dialect: 'sqlite',
46
- filename: './dev.sqlite'
48
+ client: 'sqlite3',
49
+ connection: {
50
+ filename: './dev.sqlite'
51
+ }
47
52
  })
48
53
  ```
49
54
 
50
- Supported dialects:
51
- - `sqlite`, `better-sqlite3`
52
- - `mysql`, `mysql2`
53
- - `postgres`, `postgresql`, `pg`, `pgnative`
54
- - `cockroachdb`, `redshift`
55
- - `mssql`
56
- - `oracledb`, `oracle`
55
+ Supported clients (canonical Knex client names):
56
+
57
+ * `sqlite3`, `better-sqlite3`
58
+ * `mysql2`
59
+ * `pg` (also used for CockroachDB/Redshift via the pg driver)
60
+ * `mssql`
61
+ * `oracledb`
57
62
 
58
63
  Connection styles:
59
- - `connectionString` for one-string connection setup
60
- - field-based setup (`host`, `port`, `user`, `password`, `database`)
61
- - sqlite file setup via `filename`
64
+
65
+ * connection string: `connection: process.env.DATABASE_URL`
66
+ * object: `connection: { host, port, user, password, database }`
67
+ * sqlite file: `connection: { filename }`
62
68
 
63
69
  ### 2) Define a model
64
70
 
@@ -88,58 +94,19 @@ await found?.update({ name: 'Jane Updated' })
88
94
 
89
95
  ### Exports
90
96
 
91
- - `Model`
92
- - `configureDatabase(config): Knex`
93
- - `createKnexConfig(config): Knex.Config`
94
- - `configure(config: Knex.Config | Knex): Knex`
95
- - `getDB(): Knex`
96
- - `DB` (Knex instance once configured)
97
- - `setMigrationConfig(config): MigrationConfig`
98
- - `getMigrationConfig(): MigrationConfig`
99
- - `makeMigration(name, config?): Promise<string>`
100
- - `migrateLatest(config?): Promise<{ batch: number; log: string[] }>`
101
- - `migrateRollback(config?, all?): Promise<{ batch: number; log: string[] }>`
102
- - `migrateCurrentVersion(config?): Promise<string>`
103
- - `migrateList(config?): Promise<{ completed: string[]; pending: string[] }>`
104
-
105
- ### Model instance members
106
-
107
- - `fillable: string[]`
108
- - Attributes allowed through `save()`.
109
- - `hidden: string[]`
110
- - Attributes removed when serializing model results.
111
- - `table: string`
112
- - Inferred from class name using pluralization (for `User` -> `users`).
113
- - `id?: number`
114
-
115
- ### Instance methods
116
-
117
- - `save(): Promise<this>`
118
- - Inserts record using only `fillable` fields.
119
- - `update(properties): Promise<this>`
120
- - Updates by `id`, then reloads from DB.
121
- - `delete(): Promise<void>`
122
- - Deletes current row by `id`.
123
- - `hasOne(RelatedModel, localKey?, foreignKey?): Promise<Model | null>`
124
- - Loads one related record.
125
- - `hasMany(RelatedModel, localKey?, foreignKey?): Promise<Model[]>`
126
- - Loads related records by foreign key.
127
- - `belongsTo(RelatedModel, foreignKey?, ownerKey?): Promise<Model | null>`
128
- - Loads the owning/parent record.
129
-
130
- ### Static methods
131
-
132
- - `find(id, columns = '*'): Promise<Model | null>`
133
- - `findOrFail(id, columns = '*'): Promise<Model>`
134
- - `create(properties): Promise<Model>`
135
- - `createMany(properties[]): Promise<Model[]>`
136
- - `firstOrCreate(attributes, values = {}): Promise<Model>`
137
- - `where(conditions = {}): typeof Model`
138
- - `first(columns = '*'): Promise<Model | null>`
139
- - `all(columns = '*'): Promise<Model[]>`
140
- - `count(column = '*'): Promise<number>`
141
- - `update(properties): Promise<number | undefined>`
142
- - `destroy(): Promise<number | undefined>`
97
+ * `Model`
98
+ * `configureDatabase(config): Knex`
99
+ * `createKnexConfig(config): Knex.Config`
100
+ * `configure(config: Knex.Config | Knex): Knex`
101
+ * `getDB(): Knex`
102
+ * `DB` (Knex instance once configured)
103
+ * `setMigrationConfig(config): MigrationConfig`
104
+ * `getMigrationConfig(): MigrationConfig`
105
+ * `makeMigration(name, config?): Promise<string>`
106
+ * `migrateLatest(config?): Promise<{ batch: number; log: string[] }>`
107
+ * `migrateRollback(config?, all?): Promise<{ batch: number; log: string[] }>`
108
+ * `migrateCurrentVersion(config?): Promise<string>`
109
+ * `migrateList(config?): Promise<{ completed: string[]; pending: string[] }>`
143
110
 
144
111
  ## Using `DB` directly
145
112
 
@@ -149,9 +116,12 @@ You can always drop down to Knex after configuration:
149
116
  import { configureDatabase, DB } from 'mevn-orm'
150
117
 
151
118
  configureDatabase({
152
- dialect: 'sqlite',
153
- filename: './dev.sqlite'
119
+ client: 'sqlite3',
120
+ connection: {
121
+ filename: './dev.sqlite'
122
+ }
154
123
  })
124
+
155
125
  const users = await DB('users').select('*')
156
126
  ```
157
127
 
@@ -162,34 +132,41 @@ import { configureDatabase } from 'mevn-orm'
162
132
 
163
133
  // MySQL / mysql2
164
134
  configureDatabase({
165
- dialect: 'mysql',
166
- host: '127.0.0.1',
167
- port: 3306,
168
- user: 'root',
169
- password: 'secret',
170
- database: 'app_db'
135
+ client: 'mysql2',
136
+ connection: {
137
+ host: '127.0.0.1',
138
+ port: 3306,
139
+ user: 'root',
140
+ password: 'secret',
141
+ database: 'app_db'
142
+ }
171
143
  })
172
144
 
173
- // Postgres
145
+ // Postgres (connection string)
174
146
  configureDatabase({
175
- dialect: 'postgres',
176
- connectionString: process.env.DATABASE_URL
147
+ client: 'pg',
148
+ connection: process.env.DATABASE_URL
177
149
  })
178
150
 
179
151
  // MSSQL
180
152
  configureDatabase({
181
- dialect: 'mssql',
182
- host: '127.0.0.1',
183
- user: 'sa',
184
- password: 'StrongPassword!',
185
- database: 'app_db',
186
- ssl: true
153
+ client: 'mssql',
154
+ connection: {
155
+ host: '127.0.0.1',
156
+ user: 'sa',
157
+ password: 'StrongPassword!',
158
+ database: 'app_db',
159
+ // MSSQL driver options live under `options` (passed through to tedious)
160
+ options: {
161
+ encrypt: true
162
+ }
163
+ }
187
164
  })
188
165
  ```
189
166
 
190
167
  ## Nuxt/Nitro Example
191
168
 
192
- Use a server plugin to initialize the ORM once at Nitro startup.
169
+ Use a server plugin to initialise the ORM once at Nitro startup.
193
170
  You can also run idempotent migrations (and optional rollback) during boot.
194
171
 
195
172
  Because Nitro bundles server code, migration files must be copied into the build output.
@@ -225,7 +202,9 @@ import {
225
202
  } from 'mevn-orm'
226
203
 
227
204
  const isIgnorableMigrationError = (error: unknown): boolean => {
228
- const message = error instanceof Error ? error.message.toLowerCase() : String(error).toLowerCase()
205
+ const message =
206
+ error instanceof Error ? error.message.toLowerCase() : String(error).toLowerCase()
207
+
229
208
  return (
230
209
  message.includes('already exists') ||
231
210
  message.includes('duplicate') ||
@@ -237,8 +216,8 @@ const isIgnorableMigrationError = (error: unknown): boolean => {
237
216
 
238
217
  export default defineNitroPlugin(async () => {
239
218
  configureDatabase({
240
- dialect: 'postgres',
241
- connectionString: process.env.DATABASE_URL
219
+ client: 'pg',
220
+ connection: process.env.DATABASE_URL
242
221
  })
243
222
 
244
223
  // Nitro runtime path differs in dev vs built server.
@@ -255,9 +234,7 @@ export default defineNitroPlugin(async () => {
255
234
  try {
256
235
  await migrateLatest()
257
236
  } catch (error) {
258
- if (!isIgnorableMigrationError(error)) {
259
- throw error
260
- }
237
+ if (!isIgnorableMigrationError(error)) throw error
261
238
  }
262
239
 
263
240
  // Optional rollback at boot (usually only for dev/preview).
@@ -265,63 +242,7 @@ export default defineNitroPlugin(async () => {
265
242
  try {
266
243
  await migrateRollback(undefined, false)
267
244
  } catch (error) {
268
- if (!isIgnorableMigrationError(error)) {
269
- throw error
270
- }
271
- }
272
- }
273
- })
274
- ```
275
-
276
- For fully idempotent behavior across SQL dialects, write migrations with guards
277
- (`createTableIfNotExists`, checking column existence, or raw `IF EXISTS/IF NOT EXISTS`).
278
-
279
- `server/models/User.ts`:
280
-
281
- ```ts
282
- import { Model } from 'mevn-orm'
283
-
284
- export class User extends Model {
285
- override fillable = ['name', 'email', 'password']
286
- override hidden = ['password']
287
- }
288
- ```
289
-
290
- `server/api/users.get.ts`:
291
-
292
- ```ts
293
- import { User } from '../models/User'
294
-
295
- export default defineEventHandler(async () => {
296
- return await User.all()
297
- })
298
- ```
299
-
300
- `server/api/users.post.ts`:
301
-
302
- ```ts
303
- import { User } from '../models/User'
304
-
305
- export default defineEventHandler(async (event) => {
306
- const body = await readBody(event)
307
- return await User.create({
308
- name: body.name,
309
- email: body.email,
310
- password: body.password // hash before storing
311
- })
312
- })
313
- ```
314
-
315
- If you prefer Nuxt runtime config:
316
-
317
- `nuxt.config.ts`:
318
-
319
- ```ts
320
- export default defineNuxtConfig({
321
- runtimeConfig: {
322
- db: {
323
- dialect: 'postgres',
324
- connectionString: process.env.DATABASE_URL
245
+ if (!isIgnorableMigrationError(error)) throw error
325
246
  }
326
247
  }
327
248
  })
@@ -329,7 +250,7 @@ export default defineNuxtConfig({
329
250
 
330
251
  ## Migrations
331
252
 
332
- Migrations are now programmatic and use Knex’s migration API under the hood.
253
+ Migrations are programmatic and use Knex’s migration API under the hood.
333
254
 
334
255
  ```ts
335
256
  import {
@@ -342,8 +263,8 @@ import {
342
263
  } from 'mevn-orm'
343
264
 
344
265
  configureDatabase({
345
- dialect: 'sqlite',
346
- filename: './dev.sqlite'
266
+ client: 'sqlite3',
267
+ connection: { filename: './dev.sqlite' }
347
268
  })
348
269
 
349
270
  setMigrationConfig({
@@ -369,19 +290,6 @@ pnpm run migrate:version
369
290
 
370
291
  ## Security Notes
371
292
 
372
- - Hash passwords before calling `create()` or `save()`.
373
- - Validate and sanitize input before persisting.
374
- - Keep `knex`, DB drivers, and Node.js versions up to date.
375
-
376
- ## Development (Repository)
377
-
378
- ```bash
379
- pnpm install
380
- pnpm run migrate
381
- pnpm run test
382
- pnpm run typecheck
383
- ```
384
-
385
- ## License
386
-
387
- [MIT](./LICENSE)
293
+ * Hash passwords before calling `create()` or `save()`.
294
+ * Validate and sanitise input before persisting.
295
+ * Keep `knex`, DB drivers, and Node.js versions up to date.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mevn-orm",
3
- "version": "4.0.1",
3
+ "version": "4.0.3",
4
4
  "description": "simple ORM for express js",
5
5
  "type": "module",
6
6
  "peerDependencies": {
@@ -35,7 +35,7 @@
35
35
  "@babel/core": "^7.24.5",
36
36
  "@babel/eslint-parser": "^7.24.3",
37
37
  "@babel/eslint-plugin": "^7.24.0",
38
- "@types/node": "^24.6.0",
38
+ "@types/node": "^25.3.3",
39
39
  "@faker-js/faker": "^10.0.0",
40
40
  "dotenv": "^17.0.1",
41
41
  "knex": "^3.0.0",