@koishijs/plugin-database-memory 1.0.0-beta.0 → 1.0.0-beta.4

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,5 +1,5 @@
1
1
  /// <reference types="koishi/lib" />
2
- import { Context, Database, TableType, Dict } from 'koishi';
2
+ import { Context, Database, Query, TableType } from 'koishi';
3
3
  import { Config } from './storage';
4
4
  declare module 'koishi' {
5
5
  interface Database {
@@ -10,19 +10,23 @@ declare module 'koishi' {
10
10
  }
11
11
  }
12
12
  export declare class MemoryDatabase extends Database {
13
+ #private;
13
14
  ctx: Context;
14
15
  config: Config;
15
16
  memory: this;
16
- $store: Dict<any[]>;
17
- private _storage;
18
17
  constructor(ctx: Context, config?: Config);
19
18
  start(): Promise<void>;
20
- $drop(name?: string): Promise<void>;
21
19
  $save(name: string): Promise<void>;
22
20
  stop(): void;
23
21
  $table<K extends TableType>(table: K): any[];
24
- }
25
- export declare namespace MemoryDatabase {
26
- const name = "database-memory";
22
+ drop(): Promise<void>;
23
+ stats(): Promise<{}>;
24
+ $query(name: TableType, query: Query): any[];
25
+ get(name: TableType, query: Query, modifier?: Query.Modifier): Promise<Pick<any, string>[]>;
26
+ set(name: TableType, query: Query, data: {}): Promise<void>;
27
+ remove(name: TableType, query: Query): Promise<void>;
28
+ create(name: TableType, data: any): Promise<any>;
29
+ upsert(name: TableType, data: any[], key: string | string[]): Promise<void>;
30
+ aggregate(name: TableType, fields: {}, query: Query): Promise<any>;
27
31
  }
28
32
  export default MemoryDatabase;
package/lib/index.js CHANGED
@@ -20,9 +20,6 @@ var __spreadValues = (a, b) => {
20
20
  };
21
21
  var __markAsModule = (target) => __defProp(target, "__esModule", { value: true });
22
22
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
23
- var __require = typeof require !== "undefined" ? require : (x) => {
24
- throw new Error('Dynamic require of "' + x + '" is not supported');
25
- };
26
23
  var __export = (target, all) => {
27
24
  __markAsModule(target);
28
25
  for (var name in all)
@@ -39,6 +36,24 @@ var __reExport = (target, module2, desc) => {
39
36
  var __toModule = (module2) => {
40
37
  return __reExport(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", module2 && module2.__esModule && "default" in module2 ? { get: () => module2.default, enumerable: true } : { value: module2, enumerable: true })), module2);
41
38
  };
39
+ var __accessCheck = (obj, member, msg) => {
40
+ if (!member.has(obj))
41
+ throw TypeError("Cannot " + msg);
42
+ };
43
+ var __privateGet = (obj, member, getter) => {
44
+ __accessCheck(obj, member, "read from private field");
45
+ return getter ? getter.call(obj) : member.get(obj);
46
+ };
47
+ var __privateAdd = (obj, member, value) => {
48
+ if (member.has(obj))
49
+ throw TypeError("Cannot add the same private member more than once");
50
+ member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
51
+ };
52
+ var __privateSet = (obj, member, value, setter) => {
53
+ __accessCheck(obj, member, "write to private field");
54
+ setter ? setter.call(obj, value) : member.set(obj, value);
55
+ return value;
56
+ };
42
57
 
43
58
  // plugins/database/memory/src/index.ts
44
59
  __export(exports, {
@@ -114,104 +129,102 @@ var Storage = class {
114
129
  __name(Storage, "Storage");
115
130
 
116
131
  // plugins/database/memory/src/index.ts
132
+ var _store, _loader;
117
133
  var MemoryDatabase = class extends import_koishi.Database {
118
134
  constructor(ctx, config = {}) {
119
135
  super(ctx);
120
136
  this.ctx = ctx;
121
137
  this.config = config;
122
138
  this.memory = this;
123
- this.$store = {};
139
+ __privateAdd(this, _store, {});
140
+ __privateAdd(this, _loader, void 0);
124
141
  if (config.storage) {
125
- this._storage = new Storage(ctx, config);
142
+ __privateSet(this, _loader, new Storage(ctx, config));
126
143
  }
127
144
  }
128
145
  async start() {
129
146
  var _a;
130
- await ((_a = this._storage) == null ? void 0 : _a.start(this.$store));
131
- }
132
- async $drop(name) {
133
- var _a;
134
- await ((_a = this._storage) == null ? void 0 : _a.drop(name));
147
+ await ((_a = __privateGet(this, _loader)) == null ? void 0 : _a.start(__privateGet(this, _store)));
135
148
  }
136
149
  async $save(name) {
137
150
  var _a;
138
- await ((_a = this._storage) == null ? void 0 : _a.save(name, this.$store[name]));
151
+ await ((_a = __privateGet(this, _loader)) == null ? void 0 : _a.save(name, __privateGet(this, _store)[name]));
139
152
  }
140
153
  stop() {
141
154
  }
142
155
  $table(table) {
143
156
  var _a;
144
- return (_a = this.$store)[table] || (_a[table] = []);
157
+ return (_a = __privateGet(this, _store))[table] || (_a[table] = []);
158
+ }
159
+ async drop() {
160
+ var _a;
161
+ __privateSet(this, _store, {});
162
+ await ((_a = __privateGet(this, _loader)) == null ? void 0 : _a.drop());
163
+ }
164
+ async stats() {
165
+ return {};
166
+ }
167
+ $query(name, query) {
168
+ const expr = this.ctx.model.resolveQuery(name, query);
169
+ return this.$table(name).filter((row) => (0, import_orm_utils.executeQuery)(row, expr));
145
170
  }
146
- };
147
- __name(MemoryDatabase, "MemoryDatabase");
148
- (function(MemoryDatabase2) {
149
- MemoryDatabase2.name = "database-memory";
150
- })(MemoryDatabase || (MemoryDatabase = {}));
151
- import_koishi.Database.extend(MemoryDatabase, {
152
- async drop(name) {
153
- if (name) {
154
- delete this.$store[name];
155
- } else {
156
- this.$store = {};
157
- }
158
- await this.$drop(name);
159
- },
160
171
  async get(name, query, modifier) {
161
- const expr = import_koishi.Query.resolve(name, query);
162
- const { fields, limit = Infinity, offset = 0 } = import_koishi.Query.resolveModifier(modifier);
163
- return this.$table(name).filter((row) => (0, import_orm_utils.executeQuery)(expr, row)).map((row) => (0, import_koishi.clone)((0, import_koishi.pick)(row, fields))).slice(offset, offset + limit);
164
- },
172
+ const { fields, limit = Infinity, offset = 0, sort = {} } = import_koishi.Query.resolveModifier(modifier);
173
+ return (0, import_orm_utils.executeSort)(this.$query(name, query), sort).map((row) => (0, import_koishi.clone)((0, import_koishi.pick)(row, fields))).slice(offset, offset + limit);
174
+ }
165
175
  async set(name, query, data) {
166
- const expr = import_koishi.Query.resolve(name, query);
167
- this.$table(name).filter((row) => (0, import_orm_utils.executeQuery)(expr, row)).forEach((row) => Object.assign(row, data));
176
+ this.$query(name, query).forEach((row) => (0, import_orm_utils.executeUpdate)(row, data));
168
177
  this.$save(name);
169
- },
178
+ }
170
179
  async remove(name, query) {
171
- const expr = import_koishi.Query.resolve(name, query);
172
- this.$store[name] = this.$table(name).filter((row) => !(0, import_orm_utils.executeQuery)(expr, row));
180
+ const expr = this.ctx.model.resolveQuery(name, query);
181
+ __privateGet(this, _store)[name] = this.$table(name).filter((row) => !(0, import_orm_utils.executeQuery)(row, expr));
173
182
  this.$save(name);
174
- },
183
+ }
175
184
  async create(name, data) {
176
185
  const store = this.$table(name);
177
- const { primary, fields, autoInc } = import_koishi.Tables.config[name];
186
+ const { primary, fields, autoInc } = this.ctx.model.config[name];
178
187
  data = (0, import_koishi.clone)(data);
179
188
  if (!Array.isArray(primary) && autoInc && !(primary in data)) {
180
189
  const max = store.length ? Math.max(...store.map((row) => +row[primary])) : 0;
181
190
  data[primary] = max + 1;
182
- if (import_koishi.Tables.Field.string.includes(fields[primary].type)) {
191
+ if (import_koishi.Model.Field.string.includes(fields[primary].type)) {
183
192
  data[primary] += "";
184
193
  }
185
194
  } else {
186
195
  const duplicated = await this.get(name, (0, import_koishi.pick)(data, (0, import_koishi.makeArray)(primary)));
187
- if (duplicated.length)
188
- return;
196
+ if (duplicated.length) {
197
+ throw new import_koishi.KoishiError("duplicate entry", "database.duplicate-entry");
198
+ }
189
199
  }
190
- const copy = __spreadValues(__spreadValues({}, import_koishi.Tables.create(name)), data);
200
+ const copy = __spreadValues(__spreadValues({}, this.ctx.model.create(name)), data);
191
201
  store.push(copy);
192
202
  this.$save(name);
193
- return copy;
194
- },
203
+ return (0, import_koishi.clone)(copy);
204
+ }
195
205
  async upsert(name, data, key) {
196
- const keys = (0, import_koishi.makeArray)(key || import_koishi.Tables.config[name].primary);
206
+ const keys = (0, import_koishi.makeArray)(key || this.ctx.model.config[name].primary);
197
207
  for (const item of data) {
198
208
  const row = this.$table(name).find((row2) => {
199
209
  return keys.every((key2) => row2[key2] === item[key2]);
200
210
  });
201
211
  if (row) {
202
- Object.assign(row, (0, import_koishi.clone)(item));
212
+ (0, import_orm_utils.executeUpdate)(row, item);
203
213
  } else {
204
- await this.create(name, item);
214
+ const data2 = this.ctx.model.create(name);
215
+ await this.create(name, (0, import_orm_utils.executeUpdate)(data2, item)).catch(import_koishi.noop);
205
216
  }
206
217
  }
207
218
  this.$save(name);
208
- },
219
+ }
209
220
  async aggregate(name, fields, query) {
210
- const expr = import_koishi.Query.resolve(name, query);
211
- const table = this.$table(name).filter((row) => (0, import_orm_utils.executeQuery)(expr, row));
212
- return (0, import_koishi.valueMap)(fields, (expr2) => (0, import_orm_utils.executeEval)(expr2, table));
221
+ const table = this.$query(name, query);
222
+ return (0, import_koishi.valueMap)(fields, (value) => (0, import_orm_utils.executeEval)(table, value));
213
223
  }
214
- });
224
+ };
225
+ __name(MemoryDatabase, "MemoryDatabase");
226
+ _store = new WeakMap();
227
+ _loader = new WeakMap();
215
228
  var src_default = MemoryDatabase;
216
229
  // Annotate the CommonJS export names for ESM import in node:
217
230
  0 && (module.exports = {
package/lib/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts", "../src/storage/node.ts"],
4
- "sourcesContent": ["import { Context, Database, Query, Tables, TableType, clone, makeArray, pick, Dict, valueMap } from 'koishi'\nimport { executeEval, executeQuery } from '@koishijs/orm-utils'\nimport { Storage, Config } from './storage'\n\ndeclare module 'koishi' {\n interface Database {\n memory: MemoryDatabase\n }\n\n interface Modules {\n 'database-memory': typeof import('.')\n }\n}\n\nexport class MemoryDatabase extends Database {\n public memory = this\n public $store: Dict<any[]> = {}\n\n private _storage: Storage\n\n constructor(public ctx: Context, public config: Config = {}) {\n super(ctx)\n\n if (config.storage) {\n this._storage = new Storage(ctx, config)\n }\n }\n\n async start() {\n await this._storage?.start(this.$store)\n }\n\n async $drop(name?: string) {\n await this._storage?.drop(name)\n }\n\n async $save(name: string) {\n await this._storage?.save(name, this.$store[name])\n }\n\n stop() {}\n\n $table<K extends TableType>(table: K) {\n return this.$store[table] ||= []\n }\n}\n\nexport namespace MemoryDatabase {\n export const name = 'database-memory'\n}\n\nDatabase.extend(MemoryDatabase, {\n async drop(name) {\n if (name) {\n delete this.$store[name]\n } else {\n this.$store = {}\n }\n await this.$drop(name)\n },\n\n async get(name, query, modifier) {\n const expr = Query.resolve(name, query)\n const { fields, limit = Infinity, offset = 0 } = Query.resolveModifier(modifier)\n return this.$table(name)\n .filter(row => executeQuery(expr, row))\n .map(row => clone(pick(row, fields)))\n .slice(offset, offset + limit)\n },\n\n async set(name, query, data) {\n const expr = Query.resolve(name, query)\n this.$table(name)\n .filter(row => executeQuery(expr, row))\n .forEach(row => Object.assign(row, data))\n this.$save(name)\n },\n\n async remove(name, query) {\n const expr = Query.resolve(name, query)\n this.$store[name] = this.$table(name)\n .filter(row => !executeQuery(expr, row))\n this.$save(name)\n },\n\n async create(name, data: any) {\n const store = this.$table(name)\n const { primary, fields, autoInc } = Tables.config[name] as Tables.Config\n data = clone(data)\n if (!Array.isArray(primary) && autoInc && !(primary in data)) {\n const max = store.length ? Math.max(...store.map(row => +row[primary])) : 0\n data[primary] = max + 1\n if (Tables.Field.string.includes(fields[primary].type)) {\n data[primary] += ''\n }\n } else {\n const duplicated = await this.get(name, pick(data, makeArray(primary)))\n if (duplicated.length) return\n }\n const copy = { ...Tables.create(name), ...data }\n store.push(copy)\n this.$save(name)\n return copy\n },\n\n async upsert(name, data, key) {\n const keys = makeArray(key || Tables.config[name].primary)\n for (const item of data) {\n const row = this.$table(name).find(row => {\n return keys.every(key => row[key] === item[key])\n })\n if (row) {\n Object.assign(row, clone(item))\n } else {\n await this.create(name, item)\n }\n }\n this.$save(name)\n },\n\n async aggregate(name, fields, query) {\n const expr = Query.resolve(name, query)\n const table = this.$table(name).filter(row => executeQuery(expr, row))\n return valueMap(fields, expr => executeEval(expr, table))\n },\n})\n\nexport default MemoryDatabase\n", "import type * as yaml from 'js-yaml'\nimport { Context } from 'koishi'\nimport { promises as fs } from 'fs'\nimport { extname, resolve } from 'path'\n\ntype Loader = 'json' | 'yaml' | 'yml'\nconst loaders = ['json', 'yaml', 'yml']\n\nexport interface Config {\n loader?: Loader\n root?: string\n}\n\nexport class Storage {\n constructor(ctx: Context, private config: Config) {\n config.loader ||= 'json'\n config.root ||= resolve(ctx.app.options.baseDir, '.koishi/database')\n if (!loaders.includes(config.loader)) {\n throw new Error(`unsupported loader \"${config.loader}\"`)\n }\n }\n\n async start(tables: Record<string, any[]>) {\n const { root, loader } = this.config\n await fs.mkdir(root, { recursive: true })\n const files = await fs.readdir(root)\n await Promise.all(files.map(async (filename) => {\n const extension = extname(filename)\n if (extension !== loader) return\n const buffer = await fs.readFile(filename)\n try {\n const data = await this.load(buffer, loader)\n const name = filename.slice(0, -1 - extension.length)\n tables[name] = data\n } catch {}\n }))\n }\n\n async load(buffer: Buffer, loader: Loader) {\n if (loader === 'json') {\n return JSON.parse(buffer.toString())\n } else if (loader === 'yaml' || loader === 'yml') {\n const { load } = require('js-yaml') as typeof yaml\n return load(buffer.toString())\n }\n }\n\n async drop(name?: string) {\n const { root, loader } = this.config\n if (name) {\n await fs.rm(resolve(root, `${name}.${loader}`))\n } else {\n await fs.rm(root, { recursive: true, force: true })\n }\n }\n\n async save(name: string, table: any[]) {\n const { root, loader } = this.config\n try {\n const buffer = await this.dump(table, loader)\n await fs.writeFile(resolve(root, `${name}.${loader}`), buffer)\n } catch {}\n }\n\n async dump(data: any, loader: Loader) {\n if (loader === 'json') {\n return JSON.stringify(data)\n } else if (loader === 'yaml' || loader === 'yml') {\n const { dump } = require('js-yaml') as typeof yaml\n return dump(data)\n }\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { Context, Database, Query, TableType, clone, makeArray, pick, Dict, valueMap, Model, noop, KoishiError } from 'koishi'\nimport { executeQuery, executeEval, executeUpdate, executeSort } from '@koishijs/orm-utils'\nimport { Storage, Config } from './storage'\n\ndeclare module 'koishi' {\n interface Database {\n memory: MemoryDatabase\n }\n\n interface Modules {\n 'database-memory': typeof import('.')\n }\n}\n\nexport class MemoryDatabase extends Database {\n public memory = this\n\n #store: Dict<any[]> = {}\n #loader: Storage\n\n constructor(public ctx: Context, public config: Config = {}) {\n super(ctx)\n\n if (config.storage) {\n this.#loader = new Storage(ctx, config)\n }\n }\n\n async start() {\n await this.#loader?.start(this.#store)\n }\n\n async $save(name: string) {\n await this.#loader?.save(name, this.#store[name])\n }\n\n stop() {}\n\n $table<K extends TableType>(table: K) {\n return this.#store[table] ||= []\n }\n\n async drop() {\n this.#store = {}\n await this.#loader?.drop()\n }\n\n async stats() {\n return {}\n }\n\n $query(name: TableType, query: Query) {\n const expr = this.ctx.model.resolveQuery(name, query)\n return this.$table(name).filter(row => executeQuery(row, expr))\n }\n\n async get(name: TableType, query: Query, modifier?: Query.Modifier) {\n const { fields, limit = Infinity, offset = 0, sort = {} } = Query.resolveModifier(modifier)\n return executeSort(this.$query(name, query), sort)\n .map(row => clone(pick(row, fields)))\n .slice(offset, offset + limit)\n }\n\n async set(name: TableType, query: Query, data: {}) {\n this.$query(name, query).forEach(row => executeUpdate(row, data))\n this.$save(name)\n }\n\n async remove(name: TableType, query: Query) {\n const expr = this.ctx.model.resolveQuery(name, query)\n this.#store[name] = this.$table(name)\n .filter(row => !executeQuery(row, expr))\n this.$save(name)\n }\n\n async create(name: TableType, data: any) {\n const store = this.$table(name)\n const { primary, fields, autoInc } = this.ctx.model.config[name]\n data = clone(data)\n if (!Array.isArray(primary) && autoInc && !(primary in data)) {\n const max = store.length ? Math.max(...store.map(row => +row[primary])) : 0\n data[primary] = max + 1\n if (Model.Field.string.includes(fields[primary].type)) {\n data[primary] += ''\n }\n } else {\n const duplicated = await this.get(name, pick(data, makeArray(primary)))\n if (duplicated.length) {\n throw new KoishiError('duplicate entry', 'database.duplicate-entry')\n }\n }\n const copy = { ...this.ctx.model.create(name), ...data }\n store.push(copy)\n this.$save(name)\n return clone(copy)\n }\n\n async upsert(name: TableType, data: any[], key: string | string[]) {\n const keys = makeArray(key || this.ctx.model.config[name].primary)\n for (const item of data) {\n const row = this.$table(name).find(row => {\n return keys.every(key => row[key] === item[key])\n })\n if (row) {\n executeUpdate(row, item)\n } else {\n const data = this.ctx.model.create(name)\n await this.create(name, executeUpdate(data, item)).catch(noop)\n }\n }\n this.$save(name)\n }\n\n async aggregate(name: TableType, fields: {}, query: Query) {\n const table = this.$query(name, query)\n return valueMap(fields, value => executeEval(table, value)) as any\n }\n}\n\nexport default MemoryDatabase\n", "import type * as yaml from 'js-yaml'\nimport { Context } from 'koishi'\nimport { promises as fs } from 'fs'\nimport { extname, resolve } from 'path'\n\ntype Loader = 'json' | 'yaml' | 'yml'\nconst loaders = ['json', 'yaml', 'yml']\n\nexport interface Config {\n loader?: Loader\n root?: string\n}\n\nexport class Storage {\n constructor(ctx: Context, private config: Config) {\n config.loader ||= 'json'\n config.root ||= resolve(ctx.app.options.baseDir, '.koishi/database')\n if (!loaders.includes(config.loader)) {\n throw new Error(`unsupported loader \"${config.loader}\"`)\n }\n }\n\n async start(tables: Record<string, any[]>) {\n const { root, loader } = this.config\n await fs.mkdir(root, { recursive: true })\n const files = await fs.readdir(root)\n await Promise.all(files.map(async (filename) => {\n const extension = extname(filename)\n if (extension !== loader) return\n const buffer = await fs.readFile(filename)\n try {\n const data = await this.load(buffer, loader)\n const name = filename.slice(0, -1 - extension.length)\n tables[name] = data\n } catch {}\n }))\n }\n\n async load(buffer: Buffer, loader: Loader) {\n if (loader === 'json') {\n return JSON.parse(buffer.toString())\n } else if (loader === 'yaml' || loader === 'yml') {\n const { load } = require('js-yaml') as typeof yaml\n return load(buffer.toString())\n }\n }\n\n async drop(name?: string) {\n const { root, loader } = this.config\n if (name) {\n await fs.rm(resolve(root, `${name}.${loader}`))\n } else {\n await fs.rm(root, { recursive: true, force: true })\n }\n }\n\n async save(name: string, table: any[]) {\n const { root, loader } = this.config\n try {\n const buffer = await this.dump(table, loader)\n await fs.writeFile(resolve(root, `${name}.${loader}`), buffer)\n } catch {}\n }\n\n async dump(data: any, loader: Loader) {\n if (loader === 'json') {\n return JSON.stringify(data)\n } else if (loader === 'yaml' || loader === 'yml') {\n const { dump } = require('js-yaml') as typeof yaml\n return dump(data)\n }\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@koishijs/plugin-database-memory",
3
3
  "description": "A in-memory database implementation for Koishi",
4
- "version": "1.0.0-beta.0",
4
+ "version": "1.0.0-beta.4",
5
5
  "main": "lib/node.js",
6
6
  "module": "lib/browser.js",
7
7
  "typings": "lib/index.d.ts",
8
8
  "files": [
9
9
  "lib"
10
10
  ],
11
- "author": "Shigma <1700011071@pku.edu.cn>",
11
+ "author": "Shigma <shigma10826@gmail.com>",
12
12
  "license": "MIT",
13
13
  "repository": {
14
14
  "type": "git",
@@ -30,13 +30,15 @@
30
30
  "server"
31
31
  ],
32
32
  "peerDependencies": {
33
- "koishi": "^4.0.0-beta.0"
33
+ "koishi": "^4.0.0-beta.6"
34
34
  },
35
35
  "devDependencies": {
36
+ "@koishijs/plugin-mock": "^1.0.0-beta.2",
37
+ "@koishijs/test-utils": "^8.0.0-beta.6",
36
38
  "@types/js-yaml": "^4.0.3",
37
39
  "js-yaml": "^4.1.0"
38
40
  },
39
41
  "dependencies": {
40
- "@koishijs/orm-utils": "^1.0.0-beta.0"
42
+ "@koishijs/orm-utils": "^1.0.0-beta.4"
41
43
  }
42
44
  }