@gravito/dark-matter 1.0.0-beta.1 → 1.0.0
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 +79 -21
- package/README.zh-TW.md +208 -0
- package/dist/index.cjs +917 -165
- package/dist/index.d.cts +940 -180
- package/dist/index.d.ts +940 -180
- package/dist/index.js +915 -165
- package/package.json +14 -3
package/README.md
CHANGED
|
@@ -42,6 +42,10 @@ await Mongo.disconnect()
|
|
|
42
42
|
- 🔍 **Query Builder** - Type-safe query building
|
|
43
43
|
- 📊 **Aggregation Pipeline** - Fluent aggregation API
|
|
44
44
|
- 🔌 **Multi-connection** - Named connections support
|
|
45
|
+
- 🛡️ **Transactions** - ACID transactions with convenient API
|
|
46
|
+
- 📦 **GridFS** - Handle large file uploads/downloads
|
|
47
|
+
- ⚡ **Change Streams** - Real-time database event listening
|
|
48
|
+
- ✅ **Schema Validation** - JSON Schema enforcement
|
|
45
49
|
|
|
46
50
|
## API Reference
|
|
47
51
|
|
|
@@ -111,6 +115,12 @@ await Mongo.collection('users')
|
|
|
111
115
|
await Mongo.collection('users')
|
|
112
116
|
.where('status', 'deleted')
|
|
113
117
|
.deleteMany()
|
|
118
|
+
|
|
119
|
+
// Bulk Write
|
|
120
|
+
await Mongo.collection('logs').bulkWrite([
|
|
121
|
+
{ insertOne: { document: { event: 'login' } } },
|
|
122
|
+
{ deleteOne: { filter: { status: 'old' } } }
|
|
123
|
+
])
|
|
114
124
|
```
|
|
115
125
|
|
|
116
126
|
### Aggregation Pipeline
|
|
@@ -140,42 +150,90 @@ const ordersWithCustomers = await Mongo.collection('orders')
|
|
|
140
150
|
})
|
|
141
151
|
.unwind('$customer')
|
|
142
152
|
.get()
|
|
153
|
+
```
|
|
143
154
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
155
|
+
### Advanced Features
|
|
156
|
+
|
|
157
|
+
#### Transactions
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
await Mongo.connection().withTransaction(async (session) => {
|
|
161
|
+
// Deduct from sender
|
|
162
|
+
await session.collection('accounts')
|
|
163
|
+
.where('_id', senderId)
|
|
164
|
+
.update({ $inc: { balance: -100 } })
|
|
165
|
+
|
|
166
|
+
// Add to receiver
|
|
167
|
+
await session.collection('accounts')
|
|
168
|
+
.where('_id', receiverId)
|
|
169
|
+
.update({ $inc: { balance: 100 } })
|
|
170
|
+
})
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
#### Change Streams
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
const stream = Mongo.collection('orders').watch(
|
|
177
|
+
[{ $match: { 'fullDocument.amount': { $gt: 1000 } } }]
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
for await (const event of stream) {
|
|
181
|
+
console.log('High value order:', event.fullDocument)
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
#### GridFS (File Storage)
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
const grid = new MongoGridFS(Mongo.database())
|
|
189
|
+
|
|
190
|
+
// Upload
|
|
191
|
+
const fileId = await grid.upload(Buffer.from('Hello'), { filename: 'hello.txt' })
|
|
192
|
+
|
|
193
|
+
// Download
|
|
194
|
+
const content = await grid.download(fileId)
|
|
153
195
|
```
|
|
154
196
|
|
|
155
|
-
|
|
197
|
+
#### Schema Validation
|
|
156
198
|
|
|
157
199
|
```typescript
|
|
200
|
+
await Mongo.database().createCollection('users', {
|
|
201
|
+
schema: {
|
|
202
|
+
validator: {
|
|
203
|
+
$jsonSchema: {
|
|
204
|
+
required: ['username'],
|
|
205
|
+
properties: { username: { bsonType: 'string' } }
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
validationAction: 'error'
|
|
209
|
+
}
|
|
210
|
+
})
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Connection Management
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
// Configure multiple connections
|
|
158
217
|
Mongo.configure({
|
|
159
218
|
default: 'main',
|
|
160
219
|
connections: {
|
|
161
|
-
main: { uri: 'mongodb://localhost:27017
|
|
162
|
-
analytics: { uri: 'mongodb://
|
|
220
|
+
main: { uri: 'mongodb://localhost:27017/app' },
|
|
221
|
+
analytics: { uri: 'mongodb://stats-db:27017/stats' }
|
|
163
222
|
}
|
|
164
223
|
})
|
|
165
224
|
|
|
166
|
-
//
|
|
167
|
-
const
|
|
168
|
-
|
|
169
|
-
.where('type', 'pageview')
|
|
170
|
-
.get()
|
|
225
|
+
// Check health
|
|
226
|
+
const health = await Mongo.connection().getHealthStatus()
|
|
227
|
+
console.log(health.latencyMs) // e.g. 15
|
|
171
228
|
```
|
|
172
229
|
|
|
173
230
|
## Roadmap
|
|
174
231
|
|
|
175
|
-
- [
|
|
176
|
-
- [
|
|
177
|
-
- [
|
|
178
|
-
- [
|
|
232
|
+
- [x] Connection retry & health check
|
|
233
|
+
- [x] Transactions
|
|
234
|
+
- [x] Schema validation
|
|
235
|
+
- [x] Change streams
|
|
236
|
+
- [x] GridFS support
|
|
179
237
|
|
|
180
238
|
## License
|
|
181
239
|
|
package/README.zh-TW.md
CHANGED
|
@@ -13,6 +13,7 @@ bun add @gravito/dark-matter mongodb
|
|
|
13
13
|
```typescript
|
|
14
14
|
import { Mongo } from '@gravito/dark-matter'
|
|
15
15
|
|
|
16
|
+
// 設定
|
|
16
17
|
Mongo.configure({
|
|
17
18
|
default: 'main',
|
|
18
19
|
connections: {
|
|
@@ -20,13 +21,220 @@ Mongo.configure({
|
|
|
20
21
|
}
|
|
21
22
|
})
|
|
22
23
|
|
|
24
|
+
// 連線
|
|
23
25
|
await Mongo.connect()
|
|
24
26
|
|
|
27
|
+
// 使用
|
|
25
28
|
const users = await Mongo.collection('users')
|
|
26
29
|
.where('status', 'active')
|
|
27
30
|
.orderBy('createdAt', 'desc')
|
|
28
31
|
.limit(10)
|
|
29
32
|
.get()
|
|
30
33
|
|
|
34
|
+
// 斷線
|
|
31
35
|
await Mongo.disconnect()
|
|
32
36
|
```
|
|
37
|
+
|
|
38
|
+
## 功能特色
|
|
39
|
+
|
|
40
|
+
- 🚀 **Bun 原生** - 針對 Bun runtime 最佳化
|
|
41
|
+
- 🎯 **Laravel 風格 API** - 熟悉且直觀的 Fluent Interface
|
|
42
|
+
- 🔍 **Query Builder** - 類型安全的查詢建構器
|
|
43
|
+
- 📊 **Aggregation Pipeline** - 流暢的聚合管道 API
|
|
44
|
+
- 🔌 **多連線支援** - 支援多個具名資料庫連線
|
|
45
|
+
- 🛡️ **Transactions** - 支援 ACID 交易與簡便的 API
|
|
46
|
+
- 📦 **GridFS** - 支援大檔案上傳與下載
|
|
47
|
+
- ⚡ **Change Streams** - 即時監聽資料庫變更事件
|
|
48
|
+
- ✅ **Schema Validation** - JSON Schema 資料驗證支援
|
|
49
|
+
|
|
50
|
+
## API 參考
|
|
51
|
+
|
|
52
|
+
### 查詢建構器 (Query Builder)
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
// 基本查詢
|
|
56
|
+
const users = await Mongo.collection('users')
|
|
57
|
+
.where('status', 'active')
|
|
58
|
+
.where('age', '>', 18)
|
|
59
|
+
.whereIn('role', ['admin', 'editor'])
|
|
60
|
+
.get()
|
|
61
|
+
|
|
62
|
+
// 排序與分頁
|
|
63
|
+
const latest = await Mongo.collection('posts')
|
|
64
|
+
.orderBy('createdAt', 'desc')
|
|
65
|
+
.limit(10)
|
|
66
|
+
.skip(20)
|
|
67
|
+
.get()
|
|
68
|
+
|
|
69
|
+
// 選擇特定欄位
|
|
70
|
+
const names = await Mongo.collection('users')
|
|
71
|
+
.select('name', 'email')
|
|
72
|
+
.get()
|
|
73
|
+
|
|
74
|
+
// 根據 ID 查詢
|
|
75
|
+
const user = await Mongo.collection('users').find('507f1f77bcf86cd799439011')
|
|
76
|
+
|
|
77
|
+
// 計數與存在檢查
|
|
78
|
+
const count = await Mongo.collection('users').where('status', 'active').count()
|
|
79
|
+
const exists = await Mongo.collection('users').where('email', 'john@example.com').exists()
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### CRUD 操作
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
// 新增
|
|
86
|
+
const result = await Mongo.collection('users').insert({
|
|
87
|
+
name: 'John',
|
|
88
|
+
email: 'john@example.com',
|
|
89
|
+
createdAt: new Date()
|
|
90
|
+
})
|
|
91
|
+
console.log(result.insertedId)
|
|
92
|
+
|
|
93
|
+
// 批次新增
|
|
94
|
+
const results = await Mongo.collection('users').insertMany([
|
|
95
|
+
{ name: 'Alice' },
|
|
96
|
+
{ name: 'Bob' }
|
|
97
|
+
])
|
|
98
|
+
|
|
99
|
+
// 更新
|
|
100
|
+
await Mongo.collection('users')
|
|
101
|
+
.where('_id', userId)
|
|
102
|
+
.update({ status: 'inactive' })
|
|
103
|
+
|
|
104
|
+
// 批次更新
|
|
105
|
+
await Mongo.collection('users')
|
|
106
|
+
.where('status', 'pending')
|
|
107
|
+
.updateMany({ status: 'active' })
|
|
108
|
+
|
|
109
|
+
// 刪除
|
|
110
|
+
await Mongo.collection('users')
|
|
111
|
+
.where('_id', userId)
|
|
112
|
+
.delete()
|
|
113
|
+
|
|
114
|
+
// 批次刪除
|
|
115
|
+
await Mongo.collection('users')
|
|
116
|
+
.where('status', 'deleted')
|
|
117
|
+
.deleteMany()
|
|
118
|
+
|
|
119
|
+
// 批次寫入 (Bulk Write)
|
|
120
|
+
await Mongo.collection('logs').bulkWrite([
|
|
121
|
+
{ insertOne: { document: { event: 'login' } } },
|
|
122
|
+
{ deleteOne: { filter: { status: 'old' } } }
|
|
123
|
+
])
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### 聚合管道 (Aggregation Pipeline)
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
// 分組與統計
|
|
130
|
+
const stats = await Mongo.collection('orders')
|
|
131
|
+
.aggregate()
|
|
132
|
+
.match({ status: 'completed' })
|
|
133
|
+
.group({
|
|
134
|
+
_id: '$customerId',
|
|
135
|
+
totalOrders: { $sum: 1 },
|
|
136
|
+
totalAmount: { $sum: '$amount' }
|
|
137
|
+
})
|
|
138
|
+
.sort({ totalAmount: 'desc' })
|
|
139
|
+
.limit(10)
|
|
140
|
+
.get()
|
|
141
|
+
|
|
142
|
+
// 關聯查詢 (Lookup / JOIN)
|
|
143
|
+
const ordersWithCustomers = await Mongo.collection('orders')
|
|
144
|
+
.aggregate()
|
|
145
|
+
.lookup({
|
|
146
|
+
from: 'customers',
|
|
147
|
+
localField: 'customerId',
|
|
148
|
+
foreignField: '_id',
|
|
149
|
+
as: 'customer'
|
|
150
|
+
})
|
|
151
|
+
.unwind('$customer')
|
|
152
|
+
.get()
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### 進階功能
|
|
156
|
+
|
|
157
|
+
#### 交易 (Transactions)
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
await Mongo.connection().withTransaction(async (session) => {
|
|
161
|
+
// 從發送者扣款
|
|
162
|
+
await session.collection('accounts')
|
|
163
|
+
.where('_id', senderId)
|
|
164
|
+
.update({ $inc: { balance: -100 } })
|
|
165
|
+
|
|
166
|
+
// 增加到接收者
|
|
167
|
+
await session.collection('accounts')
|
|
168
|
+
.where('_id', receiverId)
|
|
169
|
+
.update({ $inc: { balance: 100 } })
|
|
170
|
+
})
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
#### Change Streams (即時變更流)
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
const stream = Mongo.collection('orders').watch(
|
|
177
|
+
[{ $match: { 'fullDocument.amount': { $gt: 1000 } } }]
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
for await (const event of stream) {
|
|
181
|
+
console.log('高額訂單:', event.fullDocument)
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
#### GridFS (檔案儲存)
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
const grid = new MongoGridFS(Mongo.database())
|
|
189
|
+
|
|
190
|
+
// 上傳
|
|
191
|
+
const fileId = await grid.upload(Buffer.from('Hello'), { filename: 'hello.txt' })
|
|
192
|
+
|
|
193
|
+
// 下載
|
|
194
|
+
const content = await grid.download(fileId)
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
#### Schema Validation (資料驗證)
|
|
198
|
+
|
|
199
|
+
```typescript
|
|
200
|
+
await Mongo.database().createCollection('users', {
|
|
201
|
+
schema: {
|
|
202
|
+
validator: {
|
|
203
|
+
$jsonSchema: {
|
|
204
|
+
required: ['username'],
|
|
205
|
+
properties: { username: { bsonType: 'string' } }
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
validationAction: 'error'
|
|
209
|
+
}
|
|
210
|
+
})
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### 連線管理
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
// 設定多重連線
|
|
217
|
+
Mongo.configure({
|
|
218
|
+
default: 'main',
|
|
219
|
+
connections: {
|
|
220
|
+
main: { uri: 'mongodb://localhost:27017/app' },
|
|
221
|
+
analytics: { uri: 'mongodb://stats-db:27017/stats' }
|
|
222
|
+
}
|
|
223
|
+
})
|
|
224
|
+
|
|
225
|
+
// 檢查連線健康狀態
|
|
226
|
+
const health = await Mongo.connection().getHealthStatus()
|
|
227
|
+
console.log(health.latencyMs) // 例如: 15
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## 開發路線圖 (Roadmap)
|
|
231
|
+
|
|
232
|
+
- [x] 連線重試與健康檢查
|
|
233
|
+
- [x] 交易 (Transactions) 支援
|
|
234
|
+
- [x] Schema Validation
|
|
235
|
+
- [x] Change Streams
|
|
236
|
+
- [x] GridFS 支援
|
|
237
|
+
|
|
238
|
+
## 授權
|
|
239
|
+
|
|
240
|
+
MIT
|