@koishijs/plugin-database-mongo 3.0.3 → 3.1.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/lib/index.d.ts CHANGED
@@ -1,14 +1,14 @@
1
1
  /// <reference types="koishi/lib" />
2
2
  /// <reference types="node" />
3
- import { MongoClient, Db } from 'mongodb';
4
- import { Context, Database, Tables, Schema, Query } from 'koishi';
3
+ import { Db, MongoClient } from 'mongodb';
4
+ import { Context, Database, Schema, Tables } from 'koishi';
5
+ import { Modifier, Query } from '@koishijs/orm';
5
6
  import { URLSearchParams } from 'url';
6
7
  declare module 'koishi' {
7
8
  interface Database {
8
9
  mongo: MongoDatabase;
9
10
  }
10
11
  }
11
- declare type TableType = keyof Tables;
12
12
  declare class MongoDatabase extends Database {
13
13
  ctx: Context;
14
14
  private config;
@@ -37,13 +37,13 @@ declare class MongoDatabase extends Database {
37
37
  };
38
38
  };
39
39
  }>;
40
- get(name: TableType, query: Query, modifier: Query.Modifier): Promise<any>;
41
- set(name: TableType, query: Query, update: {}): Promise<void>;
42
- remove(name: TableType, query: Query): Promise<void>;
40
+ get(name: keyof Tables, query: Query, modifier: Modifier): Promise<any>;
41
+ set(name: keyof Tables, query: Query, update: {}): Promise<void>;
42
+ remove(name: keyof Tables, query: Query): Promise<void>;
43
43
  private queue;
44
- create(name: TableType, data: any): Promise<any>;
45
- upsert(name: TableType, data: any[], keys: string | string[]): Promise<void>;
46
- eval(table: TableType, expr: any, query: Query): Promise<any>;
44
+ create<T extends keyof Tables>(name: T, data: any): Promise<any>;
45
+ upsert(name: keyof Tables, data: any[], keys: string | string[]): Promise<void>;
46
+ eval(table: keyof Tables, expr: any, query: Query): Promise<any>;
47
47
  private _flushEvalTasks;
48
48
  }
49
49
  declare namespace MongoDatabase {
@@ -69,17 +69,13 @@ declare namespace MongoDatabase {
69
69
  username?: string;
70
70
  password?: string;
71
71
  database?: string;
72
- } & {
73
- [x: string]: any;
74
- }, {
72
+ } & import("schemastery").Dict<any, string>, {
75
73
  protocol?: string;
76
74
  host?: string;
77
75
  port?: number;
78
76
  username?: string;
79
77
  password?: string;
80
78
  database?: string;
81
- } & {
82
- [x: string]: any;
83
- }>;
79
+ } & import("schemastery").Dict<any, string>>;
84
80
  }
85
81
  export default MongoDatabase;
package/lib/index.js CHANGED
@@ -2,22 +2,8 @@ var __create = Object.create;
2
2
  var __defProp = Object.defineProperty;
3
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
6
5
  var __getProtoOf = Object.getPrototypeOf;
7
6
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
9
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
10
- var __spreadValues = (a, b) => {
11
- for (var prop in b || (b = {}))
12
- if (__hasOwnProp.call(b, prop))
13
- __defNormalProp(a, prop, b[prop]);
14
- if (__getOwnPropSymbols)
15
- for (var prop of __getOwnPropSymbols(b)) {
16
- if (__propIsEnum.call(b, prop))
17
- __defNormalProp(a, prop, b[prop]);
18
- }
19
- return a;
20
- };
21
7
  var __markAsModule = (target) => __defProp(target, "__esModule", { value: true });
22
8
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
23
9
  var __export = (target, all) => {
@@ -43,8 +29,8 @@ __export(exports, {
43
29
  });
44
30
  var import_mongodb = __toModule(require("mongodb"));
45
31
  var import_koishi2 = __toModule(require("koishi"));
32
+ var import_orm = __toModule(require("@koishijs/orm"));
46
33
  var import_url = __toModule(require("url"));
47
- var import_orm_utils = __toModule(require("@koishijs/orm-utils"));
48
34
 
49
35
  // plugins/database/mongo/src/utils.ts
50
36
  var import_koishi = __toModule(require("koishi"));
@@ -228,7 +214,7 @@ var MongoDatabase = class extends import_koishi2.Database {
228
214
  const mongourl = this.config.uri || this.connectionStringFromConfig();
229
215
  this.client = await import_mongodb.MongoClient.connect(mongourl);
230
216
  this.db = this.client.db(this.config.database);
231
- for (const name in this.ctx.model.config) {
217
+ for (const name in this.model.config) {
232
218
  this._tableTasks[name] = this._syncTable(name);
233
219
  }
234
220
  this.ctx.on("model", (name) => {
@@ -239,7 +225,7 @@ var MongoDatabase = class extends import_koishi2.Database {
239
225
  return this.client.close();
240
226
  }
241
227
  async _createIndexes(name) {
242
- const { primary, unique } = this.ctx.model.config[name];
228
+ const { primary, unique } = this.model.config[name];
243
229
  const coll = this.db.collection(name);
244
230
  const newSpecs = [];
245
231
  const oldSpecs = await coll.indexes();
@@ -260,7 +246,7 @@ var MongoDatabase = class extends import_koishi2.Database {
260
246
  await coll.createIndexes(newSpecs);
261
247
  }
262
248
  async _createFields(name) {
263
- const { fields } = this.ctx.model.config[name];
249
+ const { fields } = this.model.config[name];
264
250
  const coll = this.db.collection(name);
265
251
  await Promise.all(Object.keys(fields).map((key) => {
266
252
  if ((0, import_koishi2.isNullable)(fields[key].initial))
@@ -277,13 +263,13 @@ var MongoDatabase = class extends import_koishi2.Database {
277
263
  ]);
278
264
  }
279
265
  _createFilter(name, query) {
280
- return transformQuery(this.ctx.model.resolveQuery(name, query));
266
+ return transformQuery(this.resolveQuery(name, query));
281
267
  }
282
268
  async drop() {
283
- await Promise.all(Object.keys(this.ctx.model.config).map((name) => this.db.dropCollection(name)));
269
+ await Promise.all(Object.keys(this.model.config).map((name) => this.db.dropCollection(name)));
284
270
  }
285
271
  async _collStats() {
286
- const tables = Object.keys(this.ctx.model.config);
272
+ const tables = Object.keys(this.model.config);
287
273
  const entries = await Promise.all(tables.map(async (name) => {
288
274
  const coll = this.db.collection(name);
289
275
  const { count, size } = await coll.stats();
@@ -304,31 +290,33 @@ var MongoDatabase = class extends import_koishi2.Database {
304
290
  return [];
305
291
  await this._tableTasks[name];
306
292
  let cursor = this.db.collection(name).find(filter);
307
- const { fields, limit, offset = 0, sort } = import_koishi2.Query.resolveModifier(modifier);
308
- cursor = cursor.project(__spreadValues({ _id: 0 }, Object.fromEntries((fields != null ? fields : []).map((key) => [key, 1]))));
293
+ const { fields, limit, offset = 0, sort } = this.resolveModifier(name, modifier);
309
294
  if (offset)
310
295
  cursor = cursor.skip(offset);
311
296
  if (limit)
312
297
  cursor = cursor.limit(offset + limit);
313
298
  if (sort)
314
299
  cursor = cursor.sort(sort);
315
- return await cursor.toArray();
300
+ return (await cursor.toArray()).map((row) => this.resolveData(name, row, fields));
316
301
  }
317
302
  async set(name, query, update) {
318
303
  const filter = this._createFilter(name, query);
319
304
  if (!filter)
320
305
  return;
321
306
  await this._tableTasks[name];
322
- const { primary } = this.ctx.model.config[name];
307
+ const { primary } = this.model.config[name];
323
308
  const indexFields = (0, import_koishi2.makeArray)(primary);
324
- const updateFields = new Set(Object.keys(update).map((key) => key.split(".", 1)[0]));
325
309
  const coll = this.db.collection(name);
326
310
  const original = await coll.find(filter).toArray();
327
311
  if (!original.length)
328
312
  return;
313
+ update = this.model.format(name, update);
314
+ const updateFields = new Set(Object.keys(update).map((key) => key.split(".", 1)[0]));
329
315
  const bulk = coll.initializeUnorderedBulkOp();
330
316
  for (const item of original) {
331
- bulk.find((0, import_koishi2.pick)(item, indexFields)).updateOne({ $set: (0, import_koishi2.pick)((0, import_orm_utils.executeUpdate)(item, update), updateFields) });
317
+ bulk.find((0, import_koishi2.pick)(item, indexFields)).updateOne({
318
+ $set: (0, import_koishi2.pick)((0, import_orm.executeUpdate)(item, update), updateFields)
319
+ });
332
320
  }
333
321
  await bulk.execute();
334
322
  }
@@ -344,7 +332,7 @@ var MongoDatabase = class extends import_koishi2.Database {
344
332
  async create(name, data) {
345
333
  const coll = this.db.collection(name);
346
334
  return this.queue(name, async () => {
347
- const { primary, fields, autoInc } = this.ctx.model.config[name];
335
+ const { primary, fields, autoInc } = this.model.config[name];
348
336
  if (autoInc && !Array.isArray(primary) && !(primary in data)) {
349
337
  const [latest] = await coll.find().sort(primary, -1).limit(1).toArray();
350
338
  data[primary] = latest ? +latest[primary] + 1 : 1;
@@ -353,14 +341,14 @@ var MongoDatabase = class extends import_koishi2.Database {
353
341
  data[primary] = data[primary].padStart(8, "0");
354
342
  }
355
343
  }
356
- const copy = __spreadValues(__spreadValues({}, this.ctx.model.create(name)), data);
344
+ const copy = this.model.create(name, data);
357
345
  try {
358
346
  await coll.insertOne(copy);
359
- delete copy._id;
347
+ delete copy["_id"];
360
348
  return copy;
361
349
  } catch (err) {
362
350
  if (err instanceof import_mongodb.MongoError && err.code === 11e3) {
363
- throw new import_koishi2.KoishiError(err.message, "database.duplicate-entry");
351
+ throw new import_koishi2.DriverError("duplicate-entry", err.message);
364
352
  }
365
353
  throw err;
366
354
  }
@@ -370,20 +358,21 @@ var MongoDatabase = class extends import_koishi2.Database {
370
358
  if (!data.length)
371
359
  return;
372
360
  if (!keys)
373
- keys = this.ctx.model.config[name].primary;
361
+ keys = this.model.config[name].primary;
374
362
  const indexFields = (0, import_koishi2.makeArray)(keys);
375
363
  await this._tableTasks[name];
376
364
  const coll = this.db.collection(name);
377
365
  const original = await coll.find({ $or: data.map((item) => (0, import_koishi2.pick)(item, indexFields)) }).toArray();
378
366
  const bulk = coll.initializeUnorderedBulkOp();
379
- for (const update of data) {
367
+ for (const _item of data) {
368
+ const update = this.model.format(name, _item);
380
369
  const item = original.find((item2) => indexFields.every((key) => item2[key].valueOf() === update[key].valueOf()));
381
370
  if (item) {
382
371
  const updateFields = new Set(Object.keys(update).map((key) => key.split(".", 1)[0]));
383
- const override = (0, import_koishi2.omit)((0, import_koishi2.pick)((0, import_orm_utils.executeUpdate)(item, update), updateFields), indexFields);
372
+ const override = (0, import_koishi2.omit)((0, import_koishi2.pick)((0, import_orm.executeUpdate)(item, update), updateFields), indexFields);
384
373
  bulk.find((0, import_koishi2.pick)(item, indexFields)).updateOne({ $set: override });
385
374
  } else {
386
- bulk.insert((0, import_orm_utils.executeUpdate)(this.ctx.model.create(name), update));
375
+ bulk.insert((0, import_orm.executeUpdate)(this.model.create(name), update));
387
376
  }
388
377
  }
389
378
  await bulk.execute();
@@ -418,7 +407,7 @@ var MongoDatabase = class extends import_koishi2.Database {
418
407
  }
419
408
  for (const { expr, resolve, reject } of tasks) {
420
409
  try {
421
- resolve((0, import_orm_utils.executeEval)(data, expr));
410
+ resolve((0, import_orm.executeEval)(data, expr));
422
411
  } catch (error) {
423
412
  reject(error);
424
413
  }
@@ -431,7 +420,7 @@ __name(MongoDatabase, "MongoDatabase");
431
420
  MongoDatabase2.Config = import_koishi2.Schema.object({
432
421
  protocol: import_koishi2.Schema.string().description("要使用的协议名。").default("mongodb"),
433
422
  host: import_koishi2.Schema.string().description("要连接到的主机名。").default("localhost"),
434
- port: import_koishi2.Schema.number().description("要连接到的端口号。"),
423
+ port: import_koishi2.Schema.natural().max(65535).description("要连接到的端口号。"),
435
424
  username: import_koishi2.Schema.string().description("要使用的用户名。"),
436
425
  password: import_koishi2.Schema.string().description("要使用的密码。").role("secret"),
437
426
  database: import_koishi2.Schema.string().description("要访问的数据库名。").default("koishi")
package/lib/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts", "../src/utils.ts"],
4
- "sourcesContent": ["import { MongoClient, Db, MongoError, IndexDescription } from 'mongodb'\nimport { Context, Database, Tables, makeArray, Schema, pick, omit, Query, Model, Dict, noop, KoishiError, isNullable } from 'koishi'\nimport { URLSearchParams } from 'url'\nimport { executeUpdate, executeEval } from '@koishijs/orm-utils'\nimport { transformQuery, transformEval } from './utils'\n\ndeclare module 'koishi' {\n interface Database {\n mongo: MongoDatabase\n }\n}\n\ntype TableType = keyof Tables\n\ninterface EvalTask {\n expr: any\n table: TableType\n query: Query\n resolve: (value: any) => void\n reject: (error: Error) => void\n}\n\nclass MongoDatabase extends Database {\n public client: MongoClient\n public db: Db\n public mongo = this\n private _tableTasks: Dict<Promise<any>> = {}\n private _evalTasks: EvalTask[] = []\n\n constructor(public ctx: Context, private config: MongoDatabase.Config) {\n super(ctx)\n }\n\n private connectionStringFromConfig() {\n const { authDatabase, connectOptions, host, database: name, password, port, protocol, username } = this.config\n let mongourl = `${protocol}://`\n if (username) mongourl += `${encodeURIComponent(username)}${password ? `:${encodeURIComponent(password)}` : ''}@`\n mongourl += `${host}${port ? `:${port}` : ''}/${authDatabase || name}`\n if (connectOptions) {\n const params = new URLSearchParams(connectOptions)\n mongourl += `?${params}`\n }\n return mongourl\n }\n\n async start() {\n const mongourl = this.config.uri || this.connectionStringFromConfig()\n this.client = await MongoClient.connect(mongourl)\n this.db = this.client.db(this.config.database)\n\n for (const name in this.ctx.model.config) {\n this._tableTasks[name] = this._syncTable(name)\n }\n\n this.ctx.on('model', (name) => {\n this._tableTasks[name] = this._syncTable(name)\n })\n }\n\n stop() {\n return this.client.close()\n }\n\n private async _createIndexes(name: string) {\n const { primary, unique } = this.ctx.model.config[name]\n const coll = this.db.collection(name)\n const newSpecs: IndexDescription[] = []\n const oldSpecs = await coll.indexes()\n ;[primary, ...unique].forEach((keys, index) => {\n keys = makeArray(keys)\n const name = (index ? 'unique:' : 'primary:') + keys.join('+')\n if (oldSpecs.find(spec => spec.name === name)) return\n newSpecs.push({\n name,\n key: Object.fromEntries(keys.map(key => [key, 1])),\n unique: true,\n // https://docs.mongodb.com/manual/core/index-partial/#std-label-partial-index-with-unique-constraints\n partialFilterExpression: Object.fromEntries(keys.map(key => [key, { $exists: true }])),\n })\n })\n if (!newSpecs.length) return\n await coll.createIndexes(newSpecs)\n }\n\n private async _createFields(name: string) {\n const { fields } = this.ctx.model.config[name]\n const coll = this.db.collection(name)\n await Promise.all(Object.keys(fields).map((key) => {\n if (isNullable(fields[key].initial)) return\n return coll.updateMany({ [key]: { $exists: false } }, { $set: { [key]: fields[key].initial } })\n }))\n }\n\n /** synchronize table schema */\n private async _syncTable(name: string) {\n await this._tableTasks[name]\n await this.db.createCollection(name).catch(noop)\n await Promise.all([\n this._createIndexes(name),\n this._createFields(name),\n ])\n }\n\n private _createFilter(name: string, query: Query) {\n return transformQuery(this.ctx.model.resolveQuery(name, query))\n }\n\n async drop() {\n await Promise.all(Object.keys(this.ctx.model.config).map(name => this.db.dropCollection(name)))\n }\n\n private async _collStats() {\n const tables = Object.keys(this.ctx.model.config)\n const entries = await Promise.all(tables.map(async (name) => {\n const coll = this.db.collection(name)\n const { count, size } = await coll.stats()\n return [coll.collectionName, { count, size }] as const\n }))\n return Object.fromEntries(entries)\n }\n\n async stats() {\n // https://docs.mongodb.com/manual/reference/command/dbStats/#std-label-dbstats-output\n const [{ totalSize }, tables] = await Promise.all([\n this.db.stats(),\n this._collStats(),\n ])\n return { size: totalSize, tables }\n }\n\n async get(name: TableType, query: Query, modifier: Query.Modifier) {\n const filter = this._createFilter(name, query)\n if (!filter) return []\n await this._tableTasks[name]\n let cursor = this.db.collection(name).find(filter)\n const { fields, limit, offset = 0, sort } = Query.resolveModifier(modifier)\n cursor = cursor.project({ _id: 0, ...Object.fromEntries((fields ?? []).map(key => [key, 1])) })\n if (offset) cursor = cursor.skip(offset)\n if (limit) cursor = cursor.limit(offset + limit)\n if (sort) cursor = cursor.sort(sort)\n return await cursor.toArray() as any\n }\n\n async set(name: TableType, query: Query, update: {}) {\n const filter = this._createFilter(name, query)\n if (!filter) return\n await this._tableTasks[name]\n const { primary } = this.ctx.model.config[name]\n const indexFields = makeArray(primary)\n const updateFields = new Set(Object.keys(update).map(key => key.split('.', 1)[0]))\n const coll = this.db.collection(name)\n const original = await coll.find(filter).toArray()\n if (!original.length) return\n const bulk = coll.initializeUnorderedBulkOp()\n for (const item of original) {\n bulk.find(pick(item, indexFields)).updateOne({ $set: pick(executeUpdate(item, update), updateFields) })\n }\n await bulk.execute()\n }\n\n async remove(name: TableType, query: Query) {\n const filter = this._createFilter(name, query)\n if (!filter) return\n await this.db.collection(name).deleteMany(filter)\n }\n\n private queue(name: TableType, callback: () => Promise<any>) {\n return this._tableTasks[name] = Promise.resolve(this._tableTasks[name]).catch(noop).then(callback)\n }\n\n async create(name: TableType, data: any) {\n const coll = this.db.collection(name)\n return this.queue(name, async () => {\n const { primary, fields, autoInc } = this.ctx.model.config[name]\n if (autoInc && !Array.isArray(primary) && !(primary in data)) {\n const [latest] = await coll.find().sort(primary, -1).limit(1).toArray()\n data[primary] = latest ? +latest[primary] + 1 : 1\n if (Model.Field.string.includes(fields[primary].type)) {\n data[primary] += ''\n data[primary] = data[primary].padStart(8, '0')\n }\n }\n const copy = { ...this.ctx.model.create(name), ...data }\n try {\n await coll.insertOne(copy)\n delete copy._id\n return copy\n } catch (err) {\n if (err instanceof MongoError && err.code === 11000) {\n throw new KoishiError(err.message, 'database.duplicate-entry')\n }\n throw err\n }\n })\n }\n\n async upsert(name: TableType, data: any[], keys: string | string[]) {\n if (!data.length) return\n if (!keys) keys = this.ctx.model.config[name].primary\n const indexFields = makeArray(keys)\n await this._tableTasks[name]\n const coll = this.db.collection(name)\n const original = await coll.find({ $or: data.map(item => pick(item, indexFields)) }).toArray()\n const bulk = coll.initializeUnorderedBulkOp()\n for (const update of data) {\n const item = original.find(item => indexFields.every(key => item[key].valueOf() === update[key].valueOf()))\n if (item) {\n const updateFields = new Set(Object.keys(update).map(key => key.split('.', 1)[0]))\n const override = omit(pick(executeUpdate(item, update), updateFields), indexFields)\n bulk.find(pick(item, indexFields)).updateOne({ $set: override })\n } else {\n bulk.insert(executeUpdate(this.ctx.model.create(name), update))\n }\n }\n await bulk.execute()\n }\n\n eval(table: TableType, expr: any, query: Query) {\n return new Promise<any>((resolve, reject) => {\n this._evalTasks.push({ expr, table, query, resolve, reject })\n process.nextTick(() => this._flushEvalTasks())\n })\n }\n\n private async _flushEvalTasks() {\n const tasks = this._evalTasks\n if (!tasks.length) return\n this._evalTasks = []\n\n const stages: any[] = [{ $match: { _id: null } }]\n for (const task of tasks) {\n const { expr, table, query } = task\n task.expr = transformEval(expr, (pipeline) => {\n const filter = this._createFilter(table, query) || { _id: null }\n pipeline.unshift({ $match: filter })\n stages.push({ $unionWith: { coll: table, pipeline } })\n })\n }\n\n let data: any\n try {\n const results = await this.db.collection('user').aggregate(stages).toArray()\n data = Object.assign({}, ...results)\n } catch (error) {\n tasks.forEach(task => task.reject(error))\n return\n }\n\n for (const { expr, resolve, reject } of tasks) {\n try {\n resolve(executeEval(data, expr))\n } catch (error) {\n reject(error)\n }\n }\n }\n}\n\nnamespace MongoDatabase {\n export const name = 'database-mongo'\n\n export interface Config {\n username?: string\n password?: string\n protocol?: string\n host?: string\n port?: number\n /** database name */\n database?: string\n /** default auth database */\n authDatabase?: string\n connectOptions?: ConstructorParameters<typeof URLSearchParams>[0]\n /** connection string (will overwrite all configs except 'name') */\n uri?: string\n }\n\n export const Config = Schema.object({\n protocol: Schema.string().description('要使用的协议名。').default('mongodb'),\n host: Schema.string().description('要连接到的主机名。').default('localhost'),\n port: Schema.number().description('要连接到的端口号。'),\n username: Schema.string().description('要使用的用户名。'),\n password: Schema.string().description('要使用的密码。').role('secret'),\n database: Schema.string().description('要访问的数据库名。').default('koishi'),\n })\n}\n\nexport default MongoDatabase\n", "import { Query, Random, valueMap } from 'koishi'\nimport { Filter, FilterOperators } from 'mongodb'\n\nfunction createFieldFilter(query: Query.FieldQuery, key: string) {\n const filters: Filter<any>[] = []\n const result: Filter<any> = {}\n const child = transformFieldQuery(query, key, filters)\n if (child === false) return false\n if (child !== true) result[key] = child\n if (filters.length) result.$and = filters\n if (Object.keys(result).length) return result\n return true\n}\n\nfunction transformFieldQuery(query: Query.FieldQuery, key: string, filters: Filter<any>[]) {\n // shorthand syntax\n if (typeof query === 'string' || typeof query === 'number' || query instanceof Date) {\n return { $eq: query }\n } else if (Array.isArray(query)) {\n if (!query.length) return false\n return { $in: query }\n } else if (query instanceof RegExp) {\n return { $regex: query }\n }\n\n // query operators\n const result: FilterOperators<any> = {}\n for (const prop in query) {\n if (prop === '$and') {\n for (const item of query[prop]) {\n const child = createFieldFilter(item, key)\n if (child === false) return false\n if (child !== true) filters.push(child)\n }\n } else if (prop === '$or') {\n const $or: Filter<any>[] = []\n if (!query[prop].length) return false\n const always = query[prop].some((item) => {\n const child = createFieldFilter(item, key)\n if (typeof child === 'boolean') return child\n $or.push(child)\n })\n if (!always) filters.push({ $or })\n } else if (prop === '$not') {\n const child = createFieldFilter(query[prop], key)\n if (child === true) return false\n if (child !== false) filters.push({ $nor: [child] })\n } else if (prop === '$el') {\n const child = transformFieldQuery(query[prop], key, filters)\n if (child === false) return false\n if (child !== true) result.$elemMatch = child\n } else if (prop === '$regexFor') {\n filters.push({\n $expr: {\n $function: {\n body: function (data: string, value: string) {\n return new RegExp(data, 'i').test(value)\n }.toString(),\n args: ['$' + key, query.$regexFor],\n lang: 'js',\n },\n },\n })\n } else {\n result[prop] = query[prop]\n }\n }\n if (!Object.keys(result).length) return true\n return result\n}\n\nexport function transformQuery(query: Query.Expr) {\n const filter: Filter<any> = {}\n const additional: Filter<any>[] = []\n for (const key in query) {\n const value = query[key]\n if (key === '$and' || key === '$or') {\n // MongoError: $and/$or/$nor must be a nonempty array\n // { $and: [] } matches everything\n // { $or: [] } matches nothing\n if (value.length) {\n filter[key] = value.map(transformQuery)\n } else if (key === '$or') {\n return\n }\n } else if (key === '$not') {\n // MongoError: unknown top level operator: $not\n // https://stackoverflow.com/questions/25270396/mongodb-how-to-invert-query-with-not\n // this may solve this problem but lead to performance degradation\n const query = transformQuery(value)\n if (query) filter.$nor = [query]\n } else if (key === '$expr') {\n additional.push({ $expr: transformEval(value) })\n } else {\n const query = transformFieldQuery(value, key, additional)\n if (query === false) return\n if (query !== true) filter[key] = query\n }\n }\n if (additional.length) {\n (filter.$and ||= []).push(...additional)\n }\n return filter\n}\n\nfunction transformEvalExpr(expr: any, onAggr?: (pipeline: any[]) => void) {\n return valueMap(expr as any, (value) => {\n if (Array.isArray(value)) {\n return value.map(val => transformEval(val, onAggr))\n } else {\n return transformEval(value, onAggr)\n }\n })\n}\n\nfunction transformAggr(expr: any) {\n if (typeof expr === 'string') {\n return '$' + expr\n }\n return transformEvalExpr(expr)\n}\n\nconst aggrKeys = ['$sum', '$avg', '$min', '$max', '$count']\n\nexport function transformEval(expr: any, onAggr?: (pipeline: any[]) => void) {\n if (typeof expr === 'number' || typeof expr === 'string' || typeof expr === 'boolean') {\n return expr\n } else if (expr.$) {\n return '$' + expr.$\n }\n\n for (const key of aggrKeys) {\n if (!expr[key]) continue\n const value = transformAggr(expr[key])\n const $ = Random.id()\n if (key === '$count') {\n onAggr([\n { $group: { _id: value } },\n { $group: { _id: null, [$]: { $count: {} } } }\n ])\n } else {\n onAggr([{ $group: { _id: null, [$]: { [key]: value } } }])\n }\n return { $ }\n }\n\n return transformEvalExpr(expr, onAggr)\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { Db, IndexDescription, MongoClient, MongoError } from 'mongodb'\nimport { Context, Database, Dict, DriverError, isNullable, makeArray, Model, noop, omit, pick, Schema, Tables } from 'koishi'\nimport { executeEval, executeUpdate, Modifier, Query } from '@koishijs/orm'\nimport { URLSearchParams } from 'url'\nimport { transformEval, transformQuery } from './utils'\n\ndeclare module 'koishi' {\n interface Database {\n mongo: MongoDatabase\n }\n}\n\ninterface EvalTask {\n expr: any\n table: keyof Tables\n query: Query\n resolve: (value: any) => void\n reject: (error: Error) => void\n}\n\nclass MongoDatabase extends Database {\n public client: MongoClient\n public db: Db\n public mongo = this\n private _tableTasks: Dict<Promise<any>> = {}\n private _evalTasks: EvalTask[] = []\n\n constructor(public ctx: Context, private config: MongoDatabase.Config) {\n super(ctx)\n }\n\n private connectionStringFromConfig() {\n const { authDatabase, connectOptions, host, database: name, password, port, protocol, username } = this.config\n let mongourl = `${protocol}://`\n if (username) mongourl += `${encodeURIComponent(username)}${password ? `:${encodeURIComponent(password)}` : ''}@`\n mongourl += `${host}${port ? `:${port}` : ''}/${authDatabase || name}`\n if (connectOptions) {\n const params = new URLSearchParams(connectOptions)\n mongourl += `?${params}`\n }\n return mongourl\n }\n\n async start() {\n const mongourl = this.config.uri || this.connectionStringFromConfig()\n this.client = await MongoClient.connect(mongourl)\n this.db = this.client.db(this.config.database)\n\n for (const name in this.model.config) {\n this._tableTasks[name] = this._syncTable(name)\n }\n\n this.ctx.on('model', (name) => {\n this._tableTasks[name] = this._syncTable(name)\n })\n }\n\n stop() {\n return this.client.close()\n }\n\n private async _createIndexes(name: string) {\n const { primary, unique } = this.model.config[name]\n const coll = this.db.collection(name)\n const newSpecs: IndexDescription[] = []\n const oldSpecs = await coll.indexes()\n ;[primary, ...unique].forEach((keys, index) => {\n keys = makeArray(keys)\n const name = (index ? 'unique:' : 'primary:') + keys.join('+')\n if (oldSpecs.find(spec => spec.name === name)) return\n newSpecs.push({\n name,\n key: Object.fromEntries(keys.map(key => [key, 1])),\n unique: true,\n // https://docs.mongodb.com/manual/core/index-partial/#std-label-partial-index-with-unique-constraints\n partialFilterExpression: Object.fromEntries(keys.map(key => [key, { $exists: true }])),\n })\n })\n if (!newSpecs.length) return\n await coll.createIndexes(newSpecs)\n }\n\n private async _createFields(name: string) {\n const { fields } = this.model.config[name]\n const coll = this.db.collection(name)\n await Promise.all(Object.keys(fields).map((key) => {\n if (isNullable(fields[key].initial)) return\n return coll.updateMany({ [key]: { $exists: false } }, { $set: { [key]: fields[key].initial } })\n }))\n }\n\n /** synchronize table schema */\n private async _syncTable(name: string) {\n await this._tableTasks[name]\n await this.db.createCollection(name).catch(noop)\n await Promise.all([\n this._createIndexes(name),\n this._createFields(name),\n ])\n }\n\n private _createFilter(name: keyof Tables, query: Query) {\n return transformQuery(this.resolveQuery(name, query))\n }\n\n async drop() {\n await Promise.all(Object.keys(this.model.config).map(name => this.db.dropCollection(name)))\n }\n\n private async _collStats() {\n const tables = Object.keys(this.model.config)\n const entries = await Promise.all(tables.map(async (name) => {\n const coll = this.db.collection(name)\n const { count, size } = await coll.stats()\n return [coll.collectionName, { count, size }] as const\n }))\n return Object.fromEntries(entries)\n }\n\n async stats() {\n // https://docs.mongodb.com/manual/reference/command/dbStats/#std-label-dbstats-output\n const [{ totalSize }, tables] = await Promise.all([\n this.db.stats(),\n this._collStats(),\n ])\n return { size: totalSize, tables }\n }\n\n async get(name: keyof Tables, query: Query, modifier: Modifier) {\n const filter = this._createFilter(name, query)\n if (!filter) return []\n await this._tableTasks[name]\n let cursor = this.db.collection(name).find(filter)\n const { fields, limit, offset = 0, sort } = this.resolveModifier(name, modifier)\n if (offset) cursor = cursor.skip(offset)\n if (limit) cursor = cursor.limit(offset + limit)\n if (sort) cursor = cursor.sort(sort)\n return (await cursor.toArray()).map(row => this.resolveData(name, row, fields)) as any\n }\n\n async set(name: keyof Tables, query: Query, update: {}) {\n const filter = this._createFilter(name, query)\n if (!filter) return\n await this._tableTasks[name]\n const { primary } = this.model.config[name]\n const indexFields = makeArray(primary)\n const coll = this.db.collection(name)\n const original = await coll.find(filter).toArray()\n if (!original.length) return\n update = this.model.format(name, update)\n const updateFields = new Set(Object.keys(update).map(key => key.split('.', 1)[0]))\n const bulk = coll.initializeUnorderedBulkOp()\n for (const item of original) {\n bulk.find(pick(item, indexFields)).updateOne({\n $set: pick(executeUpdate(item, update), updateFields),\n })\n }\n await bulk.execute()\n }\n\n async remove(name: keyof Tables, query: Query) {\n const filter = this._createFilter(name, query)\n if (!filter) return\n await this.db.collection(name).deleteMany(filter)\n }\n\n private queue(name: keyof Tables, callback: () => Promise<any>) {\n return this._tableTasks[name] = Promise.resolve(this._tableTasks[name]).catch(noop).then(callback)\n }\n\n async create<T extends keyof Tables>(name: T, data: any) {\n const coll = this.db.collection(name)\n return this.queue(name, async () => {\n const { primary, fields, autoInc } = this.model.config[name]\n if (autoInc && !Array.isArray(primary) && !(primary in data)) {\n const [latest] = await coll.find().sort(primary, -1).limit(1).toArray()\n data[primary] = latest ? +latest[primary] + 1 : 1\n if (Model.Field.string.includes(fields[primary].type)) {\n data[primary] += ''\n data[primary] = data[primary].padStart(8, '0')\n }\n }\n const copy = this.model.create(name, data)\n try {\n await coll.insertOne(copy)\n delete copy['_id']\n return copy\n } catch (err) {\n if (err instanceof MongoError && err.code === 11000) {\n throw new DriverError('duplicate-entry', err.message)\n }\n throw err\n }\n })\n }\n\n async upsert(name: keyof Tables, data: any[], keys: string | string[]) {\n if (!data.length) return\n if (!keys) keys = this.model.config[name].primary\n const indexFields = makeArray(keys)\n await this._tableTasks[name]\n const coll = this.db.collection(name)\n const original = await coll.find({ $or: data.map(item => pick(item, indexFields)) }).toArray()\n const bulk = coll.initializeUnorderedBulkOp()\n for (const _item of data) {\n const update = this.model.format(name, _item)\n const item = original.find(item => indexFields.every(key => item[key].valueOf() === update[key].valueOf()))\n if (item) {\n const updateFields = new Set(Object.keys(update).map(key => key.split('.', 1)[0]))\n const override = omit(pick(executeUpdate(item, update), updateFields), indexFields)\n bulk.find(pick(item, indexFields)).updateOne({ $set: override })\n } else {\n bulk.insert(executeUpdate(this.model.create(name), update))\n }\n }\n await bulk.execute()\n }\n\n eval(table: keyof Tables, expr: any, query: Query) {\n return new Promise<any>((resolve, reject) => {\n this._evalTasks.push({ expr, table, query, resolve, reject })\n process.nextTick(() => this._flushEvalTasks())\n })\n }\n\n private async _flushEvalTasks() {\n const tasks = this._evalTasks\n if (!tasks.length) return\n this._evalTasks = []\n\n const stages: any[] = [{ $match: { _id: null } }]\n for (const task of tasks) {\n const { expr, table, query } = task\n task.expr = transformEval(expr, (pipeline) => {\n const filter = this._createFilter(table, query) || { _id: null }\n pipeline.unshift({ $match: filter })\n stages.push({ $unionWith: { coll: table, pipeline } })\n })\n }\n\n let data: any\n try {\n const results = await this.db.collection('user').aggregate(stages).toArray()\n data = Object.assign({}, ...results)\n } catch (error) {\n tasks.forEach(task => task.reject(error))\n return\n }\n\n for (const { expr, resolve, reject } of tasks) {\n try {\n resolve(executeEval(data, expr))\n } catch (error) {\n reject(error)\n }\n }\n }\n}\n\nnamespace MongoDatabase {\n export const name = 'database-mongo'\n\n export interface Config {\n username?: string\n password?: string\n protocol?: string\n host?: string\n port?: number\n /** database name */\n database?: string\n /** default auth database */\n authDatabase?: string\n connectOptions?: ConstructorParameters<typeof URLSearchParams>[0]\n /** connection string (will overwrite all configs except 'name') */\n uri?: string\n }\n\n export const Config = Schema.object({\n protocol: Schema.string().description('要使用的协议名。').default('mongodb'),\n host: Schema.string().description('要连接到的主机名。').default('localhost'),\n port: Schema.natural().max(65535).description('要连接到的端口号。'),\n username: Schema.string().description('要使用的用户名。'),\n password: Schema.string().description('要使用的密码。').role('secret'),\n database: Schema.string().description('要访问的数据库名。').default('koishi'),\n })\n}\n\nexport default MongoDatabase\n", "import { Random, valueMap } from 'koishi'\nimport { Query } from '@koishijs/orm'\nimport { Filter, FilterOperators } from 'mongodb'\n\nfunction createFieldFilter(query: Query.FieldQuery, key: string) {\n const filters: Filter<any>[] = []\n const result: Filter<any> = {}\n const child = transformFieldQuery(query, key, filters)\n if (child === false) return false\n if (child !== true) result[key] = child\n if (filters.length) result.$and = filters\n if (Object.keys(result).length) return result\n return true\n}\n\nfunction transformFieldQuery(query: Query.FieldQuery, key: string, filters: Filter<any>[]) {\n // shorthand syntax\n if (typeof query === 'string' || typeof query === 'number' || query instanceof Date) {\n return { $eq: query }\n } else if (Array.isArray(query)) {\n if (!query.length) return false\n return { $in: query }\n } else if (query instanceof RegExp) {\n return { $regex: query }\n }\n\n // query operators\n const result: FilterOperators<any> = {}\n for (const prop in query) {\n if (prop === '$and') {\n for (const item of query[prop]) {\n const child = createFieldFilter(item, key)\n if (child === false) return false\n if (child !== true) filters.push(child)\n }\n } else if (prop === '$or') {\n const $or: Filter<any>[] = []\n if (!query[prop].length) return false\n const always = query[prop].some((item) => {\n const child = createFieldFilter(item, key)\n if (typeof child === 'boolean') return child\n $or.push(child)\n })\n if (!always) filters.push({ $or })\n } else if (prop === '$not') {\n const child = createFieldFilter(query[prop], key)\n if (child === true) return false\n if (child !== false) filters.push({ $nor: [child] })\n } else if (prop === '$el') {\n const child = transformFieldQuery(query[prop], key, filters)\n if (child === false) return false\n if (child !== true) result.$elemMatch = child\n } else if (prop === '$regexFor') {\n filters.push({\n $expr: {\n $function: {\n body: function (data: string, value: string) {\n return new RegExp(data, 'i').test(value)\n }.toString(),\n args: ['$' + key, query.$regexFor],\n lang: 'js',\n },\n },\n })\n } else {\n result[prop] = query[prop]\n }\n }\n if (!Object.keys(result).length) return true\n return result\n}\n\nexport function transformQuery(query: Query.Expr) {\n const filter: Filter<any> = {}\n const additional: Filter<any>[] = []\n for (const key in query) {\n const value = query[key]\n if (key === '$and' || key === '$or') {\n // MongoError: $and/$or/$nor must be a nonempty array\n // { $and: [] } matches everything\n // { $or: [] } matches nothing\n if (value.length) {\n filter[key] = value.map(transformQuery)\n } else if (key === '$or') {\n return\n }\n } else if (key === '$not') {\n // MongoError: unknown top level operator: $not\n // https://stackoverflow.com/questions/25270396/mongodb-how-to-invert-query-with-not\n // this may solve this problem but lead to performance degradation\n const query = transformQuery(value)\n if (query) filter.$nor = [query]\n } else if (key === '$expr') {\n additional.push({ $expr: transformEval(value) })\n } else {\n const query = transformFieldQuery(value, key, additional)\n if (query === false) return\n if (query !== true) filter[key] = query\n }\n }\n if (additional.length) {\n (filter.$and ||= []).push(...additional)\n }\n return filter\n}\n\nfunction transformEvalExpr(expr: any, onAggr?: (pipeline: any[]) => void) {\n return valueMap(expr as any, (value) => {\n if (Array.isArray(value)) {\n return value.map(val => transformEval(val, onAggr))\n } else {\n return transformEval(value, onAggr)\n }\n })\n}\n\nfunction transformAggr(expr: any) {\n if (typeof expr === 'string') {\n return '$' + expr\n }\n return transformEvalExpr(expr)\n}\n\nconst aggrKeys = ['$sum', '$avg', '$min', '$max', '$count']\n\nexport function transformEval(expr: any, onAggr?: (pipeline: any[]) => void) {\n if (typeof expr === 'number' || typeof expr === 'string' || typeof expr === 'boolean') {\n return expr\n } else if (expr.$) {\n return '$' + expr.$\n }\n\n for (const key of aggrKeys) {\n if (!expr[key]) continue\n const value = transformAggr(expr[key])\n const $ = Random.id()\n if (key === '$count') {\n onAggr([\n { $group: { _id: value } },\n { $group: { _id: null, [$]: { $count: {} } } },\n ])\n } else {\n onAggr([{ $group: { _id: null, [$]: { [key]: value } } }])\n }\n return { $ }\n }\n\n return transformEvalExpr(expr, onAggr)\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/lib/utils.d.ts CHANGED
@@ -1,5 +1,4 @@
1
- /// <reference types="koishi/lib" />
2
- import { Query } from 'koishi';
1
+ import { Query } from '@koishijs/orm';
3
2
  import { Filter } from 'mongodb';
4
3
  export declare function transformQuery(query: Query.Expr): Filter<any>;
5
4
  export declare function transformEval(expr: any, onAggr?: (pipeline: any[]) => void): any;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@koishijs/plugin-database-mongo",
3
3
  "description": "MongoDB support for Koishi",
4
- "version": "3.0.3",
4
+ "version": "3.1.0",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [
@@ -23,23 +23,21 @@
23
23
  "homepage": "https://koishi.js.org/api/database/mongo.html",
24
24
  "keywords": [
25
25
  "bot",
26
- "qqbot",
27
- "cqhttp",
28
- "coolq",
29
26
  "chatbot",
30
27
  "koishi",
31
28
  "database",
32
- "mysql"
29
+ "mysql",
30
+ "impl:database"
33
31
  ],
34
32
  "devDependencies": {
35
33
  "@koishijs/database-tests": "^1.0.0",
36
- "@koishijs/plugin-mock": "^1.0.1"
34
+ "@koishijs/plugin-mock": "^1.0.3"
37
35
  },
38
36
  "peerDependencies": {
39
- "koishi": "^4.1.2"
37
+ "koishi": "^4.5.0"
40
38
  },
41
39
  "dependencies": {
42
- "@koishijs/orm-utils": "^1.0.0",
43
- "mongodb": "^4.3.0"
40
+ "@koishijs/orm": "^1.0.0",
41
+ "mongodb": "^4.4.1"
44
42
  }
45
- }
43
+ }