@koishijs/plugin-database-memory 1.0.0-beta.3 → 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/lib/browser.js CHANGED
@@ -1,14 +1,11 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
- var __require = typeof require !== "undefined" ? require : (x) => {
4
- throw new Error('Dynamic require of "' + x + '" is not supported');
5
- };
6
3
 
7
- // plugins/database/src/index.ts
8
- import { Database, Query, Tables, clone, makeArray, pick, valueMap, Schema } from "koishi";
9
- import { executeEval, executeQuery } from "@koishijs/orm-utils";
4
+ // plugins/database/memory/src/index.ts
5
+ import { Database, Query, clone, makeArray, pick, Model, noop, KoishiError } from "koishi";
6
+ import { executeQuery, executeEval, executeUpdate, executeSort } from "@koishijs/orm-utils";
10
7
 
11
- // plugins/database/src/storage/browser.ts
8
+ // plugins/database/memory/src/storage/browser.ts
12
9
  var Storage = class {
13
10
  constructor(ctx, config) {
14
11
  this.config = config;
@@ -28,9 +25,9 @@ var Storage = class {
28
25
  }
29
26
  }
30
27
  }
31
- async drop(name2) {
32
- if (name2) {
33
- localStorage.removeItem(this.config.prefix + name2);
28
+ async drop(name) {
29
+ if (name) {
30
+ localStorage.removeItem(this.config.prefix + name);
34
31
  return;
35
32
  }
36
33
  for (const key in localStorage) {
@@ -39,118 +36,110 @@ var Storage = class {
39
36
  }
40
37
  }
41
38
  }
42
- async save(name2, table) {
39
+ async save(name, table) {
43
40
  try {
44
41
  const buffer = JSON.stringify(table);
45
- localStorage.setItem(this.config.prefix + name2, buffer);
42
+ localStorage.setItem(this.config.prefix + name, buffer);
46
43
  } catch {
47
44
  }
48
45
  }
49
46
  };
50
47
  __name(Storage, "Storage");
51
48
 
52
- // plugins/database/src/index.ts
49
+ // plugins/database/memory/src/index.ts
53
50
  var MemoryDatabase = class extends Database {
54
51
  constructor(ctx, config = {}) {
55
52
  super(ctx);
56
53
  this.ctx = ctx;
57
54
  this.config = config;
58
55
  this.memory = this;
59
- this.$store = {};
56
+ this.#store = {};
60
57
  if (config.storage) {
61
- this._storage = new Storage(ctx, config);
58
+ this.#loader = new Storage(ctx, config);
62
59
  }
63
60
  }
61
+ #store;
62
+ #loader;
64
63
  async start() {
65
- await this._storage?.start(this.$store);
66
- }
67
- async $drop(name2) {
68
- await this._storage?.drop(name2);
64
+ await this.#loader?.start(this.#store);
69
65
  }
70
- async $save(name2) {
71
- await this._storage?.save(name2, this.$store[name2]);
66
+ async $save(name) {
67
+ await this.#loader?.save(name, this.#store[name]);
72
68
  }
73
69
  stop() {
74
70
  }
75
71
  $table(table) {
76
- return this.$store[table] ||= [];
72
+ return this.#store[table] ||= [];
77
73
  }
78
- };
79
- __name(MemoryDatabase, "MemoryDatabase");
80
- Database.extend(MemoryDatabase, {
81
- async drop(name2) {
82
- if (name2) {
83
- delete this.$store[name2];
84
- } else {
85
- this.$store = {};
86
- }
87
- await this.$drop(name2);
88
- },
89
- async get(name2, query, modifier) {
90
- const expr = Query.resolve(name2, query);
91
- const { fields, limit = Infinity, offset = 0 } = Query.resolveModifier(modifier);
92
- return this.$table(name2).filter((row) => executeQuery(expr, row)).map((row) => clone(pick(row, fields))).slice(offset, offset + limit);
93
- },
94
- async set(name2, query, data) {
95
- const expr = Query.resolve(name2, query);
96
- this.$table(name2).filter((row) => executeQuery(expr, row)).forEach((row) => Object.assign(row, data));
97
- this.$save(name2);
98
- },
99
- async remove(name2, query) {
100
- const expr = Query.resolve(name2, query);
101
- this.$store[name2] = this.$table(name2).filter((row) => !executeQuery(expr, row));
102
- this.$save(name2);
103
- },
104
- async create(name2, data) {
105
- const store = this.$table(name2);
106
- const { primary, fields, autoInc } = Tables.config[name2];
74
+ async drop() {
75
+ this.#store = {};
76
+ await this.#loader?.drop();
77
+ }
78
+ async stats() {
79
+ return {};
80
+ }
81
+ $query(name, query) {
82
+ const expr = this.ctx.model.resolveQuery(name, query);
83
+ return this.$table(name).filter((row) => executeQuery(row, expr));
84
+ }
85
+ async get(name, query, modifier) {
86
+ const { fields, limit = Infinity, offset = 0, sort = {} } = Query.resolveModifier(modifier);
87
+ return executeSort(this.$query(name, query), sort).map((row) => clone(pick(row, fields))).slice(offset, offset + limit);
88
+ }
89
+ async set(name, query, data) {
90
+ this.$query(name, query).forEach((row) => executeUpdate(row, data));
91
+ this.$save(name);
92
+ }
93
+ async remove(name, query) {
94
+ const expr = this.ctx.model.resolveQuery(name, query);
95
+ this.#store[name] = this.$table(name).filter((row) => !executeQuery(row, expr));
96
+ this.$save(name);
97
+ }
98
+ async create(name, data) {
99
+ const store = this.$table(name);
100
+ const { primary, fields, autoInc } = this.ctx.model.config[name];
107
101
  data = clone(data);
108
102
  if (!Array.isArray(primary) && autoInc && !(primary in data)) {
109
103
  const max = store.length ? Math.max(...store.map((row) => +row[primary])) : 0;
110
104
  data[primary] = max + 1;
111
- if (Tables.Field.string.includes(fields[primary].type)) {
105
+ if (Model.Field.string.includes(fields[primary].type)) {
112
106
  data[primary] += "";
113
107
  }
114
108
  } else {
115
- const duplicated = await this.get(name2, pick(data, makeArray(primary)));
116
- if (duplicated.length)
117
- return;
109
+ const duplicated = await this.get(name, pick(data, makeArray(primary)));
110
+ if (duplicated.length) {
111
+ throw new KoishiError("duplicate entry", "database.duplicate-entry");
112
+ }
118
113
  }
119
- const copy = { ...Tables.create(name2), ...data };
114
+ const copy = { ...this.ctx.model.create(name), ...data };
120
115
  store.push(copy);
121
- this.$save(name2);
122
- return copy;
123
- },
124
- async upsert(name2, data, key) {
125
- const keys = makeArray(key || Tables.config[name2].primary);
116
+ this.$save(name);
117
+ return clone(copy);
118
+ }
119
+ async upsert(name, data, key) {
120
+ const keys = makeArray(key || this.ctx.model.config[name].primary);
126
121
  for (const item of data) {
127
- const row = this.$table(name2).find((row2) => {
122
+ const row = this.$table(name).find((row2) => {
128
123
  return keys.every((key2) => row2[key2] === item[key2]);
129
124
  });
130
125
  if (row) {
131
- Object.assign(row, clone(item));
126
+ executeUpdate(row, item);
132
127
  } else {
133
- await this.create(name2, item);
128
+ const data2 = this.ctx.model.create(name);
129
+ await this.create(name, executeUpdate(data2, item)).catch(noop);
134
130
  }
135
131
  }
136
- this.$save(name2);
137
- },
138
- async aggregate(name2, fields, query) {
139
- const expr = Query.resolve(name2, query);
140
- const table = this.$table(name2).filter((row) => executeQuery(expr, row));
141
- return valueMap(fields, (expr2) => executeEval(expr2, table));
142
- }
143
- });
144
- var name = "database";
145
- var schema = Schema.object({});
146
- function apply(ctx, config = {}) {
147
- ctx.database = new MemoryDatabase(ctx, config);
148
- }
149
- __name(apply, "apply");
132
+ this.$save(name);
133
+ }
134
+ async eval(name, expr, query) {
135
+ const table = this.$query(name, query);
136
+ return executeEval(table, expr);
137
+ }
138
+ };
139
+ __name(MemoryDatabase, "MemoryDatabase");
140
+ var src_default = MemoryDatabase;
150
141
  export {
151
142
  MemoryDatabase,
152
- apply,
153
- name,
154
- schema
143
+ src_default as default
155
144
  };
156
145
  //# sourceMappingURL=browser.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts", "../src/storage/browser.ts"],
4
- "sourcesContent": ["import { Context, Database, Query, Tables, TableType, clone, makeArray, pick, Dict, valueMap, Schema } 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: 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\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 const name = 'database'\n\nexport const schema: Schema<Config> = Schema.object({})\n\nexport function apply(ctx: Context, config: Config = {}) {\n ctx.database = new MemoryDatabase(ctx, config)\n}\n", "import { Context } from 'koishi'\n\nexport interface Config {\n prefix?: string\n}\n\nexport class Storage {\n constructor(ctx: Context, private config: Config) {\n config.prefix ||= 'koishi.database.'\n }\n\n async start(tables: Record<string, any[]>) {\n for (const key in localStorage) {\n if (!key.startsWith(this.config.prefix)) break\n const buffer = localStorage.getItem(key)\n if (!buffer) return\n try {\n const data = JSON.parse(buffer)\n tables[key.slice(this.config.prefix.length)] = data\n } catch {}\n }\n }\n\n async drop(name?: string) {\n if (name) {\n localStorage.removeItem(this.config.prefix + name)\n return\n }\n\n for (const key in localStorage) {\n if (key.startsWith(this.config.prefix)) {\n localStorage.removeItem(key)\n }\n }\n }\n\n async save(name: string, table: any[]) {\n try {\n const buffer = JSON.stringify(table)\n localStorage.setItem(this.config.prefix + name, buffer)\n } catch {}\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { Context, Database, Query, TableType, clone, makeArray, pick, Dict, 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 eval(name: TableType, expr: any, query: Query) {\n const table = this.$query(name, query)\n return executeEval(table, expr)\n }\n}\n\nexport default MemoryDatabase\n", "import { Context } from 'koishi'\n\nexport interface Config {\n prefix?: string\n}\n\nexport class Storage {\n constructor(ctx: Context, private config: Config) {\n config.prefix ||= 'koishi.database.'\n }\n\n async start(tables: Record<string, any[]>) {\n for (const key in localStorage) {\n if (!key.startsWith(this.config.prefix)) break\n const buffer = localStorage.getItem(key)\n if (!buffer) return\n try {\n const data = JSON.parse(buffer)\n tables[key.slice(this.config.prefix.length)] = data\n } catch {}\n }\n }\n\n async drop(name?: string) {\n if (name) {\n localStorage.removeItem(this.config.prefix + name)\n return\n }\n\n for (const key in localStorage) {\n if (key.startsWith(this.config.prefix)) {\n localStorage.removeItem(key)\n }\n }\n }\n\n async save(name: string, table: any[]) {\n try {\n const buffer = JSON.stringify(table)\n localStorage.setItem(this.config.prefix + name, buffer)\n } catch {}\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/lib/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /// <reference types="koishi/lib" />
2
- import { Context, Database, Query, 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,22 +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
19
  $save(name: string): Promise<void>;
21
20
  stop(): void;
22
21
  $table<K extends TableType>(table: K): any[];
23
- drop(name: TableType): Promise<void>;
22
+ drop(): Promise<void>;
23
+ stats(): Promise<{}>;
24
+ $query(name: TableType, query: Query): any[];
24
25
  get(name: TableType, query: Query, modifier?: Query.Modifier): Promise<Pick<any, string>[]>;
25
26
  set(name: TableType, query: Query, data: {}): Promise<void>;
26
27
  remove(name: TableType, query: Query): Promise<void>;
27
28
  create(name: TableType, data: any): Promise<any>;
28
29
  upsert(name: TableType, data: any[], key: string | string[]): Promise<void>;
29
- aggregate(name: TableType, fields: {}, query: Query): Promise<any>;
30
+ eval(name: TableType, expr: any, query: Query): Promise<any>;
30
31
  }
31
32
  export default MemoryDatabase;
package/lib/index.js CHANGED
@@ -36,6 +36,24 @@ var __reExport = (target, module2, desc) => {
36
36
  var __toModule = (module2) => {
37
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);
38
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
+ };
39
57
 
40
58
  // plugins/database/memory/src/index.ts
41
59
  __export(exports, {
@@ -111,53 +129,56 @@ var Storage = class {
111
129
  __name(Storage, "Storage");
112
130
 
113
131
  // plugins/database/memory/src/index.ts
132
+ var _store, _loader;
114
133
  var MemoryDatabase = class extends import_koishi.Database {
115
134
  constructor(ctx, config = {}) {
116
135
  super(ctx);
117
136
  this.ctx = ctx;
118
137
  this.config = config;
119
138
  this.memory = this;
120
- this.$store = {};
139
+ __privateAdd(this, _store, {});
140
+ __privateAdd(this, _loader, void 0);
121
141
  if (config.storage) {
122
- this._storage = new Storage(ctx, config);
142
+ __privateSet(this, _loader, new Storage(ctx, config));
123
143
  }
124
144
  }
125
145
  async start() {
126
146
  var _a;
127
- await ((_a = this._storage) == null ? void 0 : _a.start(this.$store));
147
+ await ((_a = __privateGet(this, _loader)) == null ? void 0 : _a.start(__privateGet(this, _store)));
128
148
  }
129
149
  async $save(name) {
130
150
  var _a;
131
- 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]));
132
152
  }
133
153
  stop() {
134
154
  }
135
155
  $table(table) {
136
156
  var _a;
137
- return (_a = this.$store)[table] || (_a[table] = []);
157
+ return (_a = __privateGet(this, _store))[table] || (_a[table] = []);
138
158
  }
139
- async drop(name) {
159
+ async drop() {
140
160
  var _a;
141
- if (name) {
142
- delete this.$store[name];
143
- } else {
144
- this.$store = {};
145
- }
146
- await ((_a = this._storage) == null ? void 0 : _a.drop(name));
161
+ __privateSet(this, _store, {});
162
+ await ((_a = __privateGet(this, _loader)) == null ? void 0 : _a.drop());
147
163
  }
148
- async get(name, query, modifier) {
164
+ async stats() {
165
+ return {};
166
+ }
167
+ $query(name, query) {
149
168
  const expr = this.ctx.model.resolveQuery(name, query);
150
- const { fields, limit = Infinity, offset = 0 } = import_koishi.Query.resolveModifier(modifier);
151
- 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);
169
+ return this.$table(name).filter((row) => (0, import_orm_utils.executeQuery)(row, expr));
170
+ }
171
+ async get(name, query, modifier) {
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);
152
174
  }
153
175
  async set(name, query, data) {
154
- const expr = this.ctx.model.resolveQuery(name, query);
155
- 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));
156
177
  this.$save(name);
157
178
  }
158
179
  async remove(name, query) {
159
180
  const expr = this.ctx.model.resolveQuery(name, query);
160
- this.$store[name] = this.$table(name).filter((row) => !(0, import_orm_utils.executeQuery)(expr, row));
181
+ __privateGet(this, _store)[name] = this.$table(name).filter((row) => !(0, import_orm_utils.executeQuery)(row, expr));
161
182
  this.$save(name);
162
183
  }
163
184
  async create(name, data) {
@@ -172,13 +193,14 @@ var MemoryDatabase = class extends import_koishi.Database {
172
193
  }
173
194
  } else {
174
195
  const duplicated = await this.get(name, (0, import_koishi.pick)(data, (0, import_koishi.makeArray)(primary)));
175
- if (duplicated.length)
176
- return;
196
+ if (duplicated.length) {
197
+ throw new import_koishi.KoishiError("duplicate entry", "database.duplicate-entry");
198
+ }
177
199
  }
178
200
  const copy = __spreadValues(__spreadValues({}, this.ctx.model.create(name)), data);
179
201
  store.push(copy);
180
202
  this.$save(name);
181
- return copy;
203
+ return (0, import_koishi.clone)(copy);
182
204
  }
183
205
  async upsert(name, data, key) {
184
206
  const keys = (0, import_koishi.makeArray)(key || this.ctx.model.config[name].primary);
@@ -187,20 +209,22 @@ var MemoryDatabase = class extends import_koishi.Database {
187
209
  return keys.every((key2) => row2[key2] === item[key2]);
188
210
  });
189
211
  if (row) {
190
- Object.assign(row, (0, import_koishi.clone)(item));
212
+ (0, import_orm_utils.executeUpdate)(row, item);
191
213
  } else {
192
- 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);
193
216
  }
194
217
  }
195
218
  this.$save(name);
196
219
  }
197
220
  async aggregate(name, fields, query) {
198
- const expr = this.ctx.model.resolveQuery(name, query);
199
- const table = this.$table(name).filter((row) => (0, import_orm_utils.executeQuery)(expr, row));
200
- 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));
201
223
  }
202
224
  };
203
225
  __name(MemoryDatabase, "MemoryDatabase");
226
+ _store = new WeakMap();
227
+ _loader = new WeakMap();
204
228
  var src_default = MemoryDatabase;
205
229
  // Annotate the CommonJS export names for ESM import in node:
206
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, TableType, clone, makeArray, pick, Dict, valueMap, Model } 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 $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 async drop(name: TableType) {\n if (name) {\n delete this.$store[name]\n } else {\n this.$store = {}\n }\n await this._storage?.drop(name)\n }\n\n async get(name: TableType, query: Query, modifier?: Query.Modifier) {\n const expr = this.ctx.model.resolveQuery(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: TableType, query: Query, data: {}) {\n const expr = this.ctx.model.resolveQuery(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: TableType, query: Query) {\n const expr = this.ctx.model.resolveQuery(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: 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) return\n }\n const copy = { ...this.ctx.model.create(name), ...data }\n store.push(copy)\n this.$save(name)\n return 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 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: TableType, fields: {}, query: Query) {\n const expr = this.ctx.model.resolveQuery(name, query)\n const table = this.$table(name).filter(row => executeQuery(expr, row))\n return valueMap(fields, expr => executeEval(expr, table)) 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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",
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/lib/node.js CHANGED
@@ -20,13 +20,10 @@ 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
- for (var name2 in all)
29
- __defProp(target, name2, { get: all[name2], enumerable: true });
25
+ for (var name in all)
26
+ __defProp(target, name, { get: all[name], enumerable: true });
30
27
  };
31
28
  var __reExport = (target, module2, desc) => {
32
29
  if (module2 && typeof module2 === "object" || typeof module2 === "function") {
@@ -39,18 +36,34 @@ 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
- // plugins/database/src/index.ts
58
+ // plugins/database/memory/src/index.ts
44
59
  __export(exports, {
45
60
  MemoryDatabase: () => MemoryDatabase,
46
- apply: () => apply,
47
- name: () => name,
48
- schema: () => schema
61
+ default: () => src_default
49
62
  });
50
63
  var import_koishi = __toModule(require("koishi"));
51
64
  var import_orm_utils = __toModule(require("@koishijs/orm-utils"));
52
65
 
53
- // plugins/database/src/storage/node.ts
66
+ // plugins/database/memory/src/storage/node.ts
54
67
  var import_fs = __toModule(require("fs"));
55
68
  var import_path = __toModule(require("path"));
56
69
  var loaders = ["json", "yaml", "yml"];
@@ -58,7 +71,7 @@ var Storage = class {
58
71
  constructor(ctx, config) {
59
72
  this.config = config;
60
73
  config.loader || (config.loader = "json");
61
- config.root || (config.root = (0, import_path.resolve)(ctx.app.options.baseDir, ".koishi/database"));
74
+ config.root || (config.root = (0, import_path.resolve)(ctx.app.baseDir, ".koishi/database"));
62
75
  if (!loaders.includes(config.loader)) {
63
76
  throw new Error(`unsupported loader "${config.loader}"`);
64
77
  }
@@ -74,8 +87,8 @@ var Storage = class {
74
87
  const buffer = await import_fs.promises.readFile(filename);
75
88
  try {
76
89
  const data = await this.load(buffer, loader);
77
- const name2 = filename.slice(0, -1 - extension.length);
78
- tables[name2] = data;
90
+ const name = filename.slice(0, -1 - extension.length);
91
+ tables[name] = data;
79
92
  } catch {
80
93
  }
81
94
  }));
@@ -88,19 +101,19 @@ var Storage = class {
88
101
  return load(buffer.toString());
89
102
  }
90
103
  }
91
- async drop(name2) {
104
+ async drop(name) {
92
105
  const { root, loader } = this.config;
93
- if (name2) {
94
- await import_fs.promises.rm((0, import_path.resolve)(root, `${name2}.${loader}`));
106
+ if (name) {
107
+ await import_fs.promises.rm((0, import_path.resolve)(root, `${name}.${loader}`));
95
108
  } else {
96
109
  await import_fs.promises.rm(root, { recursive: true, force: true });
97
110
  }
98
111
  }
99
- async save(name2, table) {
112
+ async save(name, table) {
100
113
  const { root, loader } = this.config;
101
114
  try {
102
115
  const buffer = await this.dump(table, loader);
103
- await import_fs.promises.writeFile((0, import_path.resolve)(root, `${name2}.${loader}`), buffer);
116
+ await import_fs.promises.writeFile((0, import_path.resolve)(root, `${name}.${loader}`), buffer);
104
117
  } catch {
105
118
  }
106
119
  }
@@ -115,113 +128,106 @@ var Storage = class {
115
128
  };
116
129
  __name(Storage, "Storage");
117
130
 
118
- // plugins/database/src/index.ts
131
+ // plugins/database/memory/src/index.ts
132
+ var _store, _loader;
119
133
  var MemoryDatabase = class extends import_koishi.Database {
120
134
  constructor(ctx, config = {}) {
121
135
  super(ctx);
122
136
  this.ctx = ctx;
123
137
  this.config = config;
124
138
  this.memory = this;
125
- this.$store = {};
139
+ __privateAdd(this, _store, {});
140
+ __privateAdd(this, _loader, void 0);
126
141
  if (config.storage) {
127
- this._storage = new Storage(ctx, config);
142
+ __privateSet(this, _loader, new Storage(ctx, config));
128
143
  }
129
144
  }
130
145
  async start() {
131
146
  var _a;
132
- await ((_a = this._storage) == null ? void 0 : _a.start(this.$store));
133
- }
134
- async $drop(name2) {
135
- var _a;
136
- await ((_a = this._storage) == null ? void 0 : _a.drop(name2));
147
+ await ((_a = __privateGet(this, _loader)) == null ? void 0 : _a.start(__privateGet(this, _store)));
137
148
  }
138
- async $save(name2) {
149
+ async $save(name) {
139
150
  var _a;
140
- await ((_a = this._storage) == null ? void 0 : _a.save(name2, this.$store[name2]));
151
+ await ((_a = __privateGet(this, _loader)) == null ? void 0 : _a.save(name, __privateGet(this, _store)[name]));
141
152
  }
142
153
  stop() {
143
154
  }
144
155
  $table(table) {
145
156
  var _a;
146
- return (_a = this.$store)[table] || (_a[table] = []);
157
+ return (_a = __privateGet(this, _store))[table] || (_a[table] = []);
147
158
  }
148
- };
149
- __name(MemoryDatabase, "MemoryDatabase");
150
- import_koishi.Database.extend(MemoryDatabase, {
151
- async drop(name2) {
152
- if (name2) {
153
- delete this.$store[name2];
154
- } else {
155
- this.$store = {};
156
- }
157
- await this.$drop(name2);
158
- },
159
- async get(name2, query, modifier) {
160
- const expr = import_koishi.Query.resolve(name2, query);
161
- const { fields, limit = Infinity, offset = 0 } = import_koishi.Query.resolveModifier(modifier);
162
- return this.$table(name2).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);
163
- },
164
- async set(name2, query, data) {
165
- const expr = import_koishi.Query.resolve(name2, query);
166
- this.$table(name2).filter((row) => (0, import_orm_utils.executeQuery)(expr, row)).forEach((row) => Object.assign(row, data));
167
- this.$save(name2);
168
- },
169
- async remove(name2, query) {
170
- const expr = import_koishi.Query.resolve(name2, query);
171
- this.$store[name2] = this.$table(name2).filter((row) => !(0, import_orm_utils.executeQuery)(expr, row));
172
- this.$save(name2);
173
- },
174
- async create(name2, data) {
175
- const store = this.$table(name2);
176
- const { primary, fields, autoInc } = import_koishi.Tables.config[name2];
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));
170
+ }
171
+ async get(name, query, modifier) {
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
+ }
175
+ async set(name, query, data) {
176
+ this.$query(name, query).forEach((row) => (0, import_orm_utils.executeUpdate)(row, data));
177
+ this.$save(name);
178
+ }
179
+ async remove(name, query) {
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));
182
+ this.$save(name);
183
+ }
184
+ async create(name, data) {
185
+ const store = this.$table(name);
186
+ const { primary, fields, autoInc } = this.ctx.model.config[name];
177
187
  data = (0, import_koishi.clone)(data);
178
188
  if (!Array.isArray(primary) && autoInc && !(primary in data)) {
179
189
  const max = store.length ? Math.max(...store.map((row) => +row[primary])) : 0;
180
190
  data[primary] = max + 1;
181
- if (import_koishi.Tables.Field.string.includes(fields[primary].type)) {
191
+ if (import_koishi.Model.Field.string.includes(fields[primary].type)) {
182
192
  data[primary] += "";
183
193
  }
184
194
  } else {
185
- const duplicated = await this.get(name2, (0, import_koishi.pick)(data, (0, import_koishi.makeArray)(primary)));
186
- if (duplicated.length)
187
- return;
195
+ const duplicated = await this.get(name, (0, import_koishi.pick)(data, (0, import_koishi.makeArray)(primary)));
196
+ if (duplicated.length) {
197
+ throw new import_koishi.KoishiError("duplicate entry", "database.duplicate-entry");
198
+ }
188
199
  }
189
- const copy = __spreadValues(__spreadValues({}, import_koishi.Tables.create(name2)), data);
200
+ const copy = __spreadValues(__spreadValues({}, this.ctx.model.create(name)), data);
190
201
  store.push(copy);
191
- this.$save(name2);
192
- return copy;
193
- },
194
- async upsert(name2, data, key) {
195
- const keys = (0, import_koishi.makeArray)(key || import_koishi.Tables.config[name2].primary);
202
+ this.$save(name);
203
+ return (0, import_koishi.clone)(copy);
204
+ }
205
+ async upsert(name, data, key) {
206
+ const keys = (0, import_koishi.makeArray)(key || this.ctx.model.config[name].primary);
196
207
  for (const item of data) {
197
- const row = this.$table(name2).find((row2) => {
208
+ const row = this.$table(name).find((row2) => {
198
209
  return keys.every((key2) => row2[key2] === item[key2]);
199
210
  });
200
211
  if (row) {
201
- Object.assign(row, (0, import_koishi.clone)(item));
212
+ (0, import_orm_utils.executeUpdate)(row, item);
202
213
  } else {
203
- await this.create(name2, 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);
204
216
  }
205
217
  }
206
- this.$save(name2);
207
- },
208
- async aggregate(name2, fields, query) {
209
- const expr = import_koishi.Query.resolve(name2, query);
210
- const table = this.$table(name2).filter((row) => (0, import_orm_utils.executeQuery)(expr, row));
211
- return (0, import_koishi.valueMap)(fields, (expr2) => (0, import_orm_utils.executeEval)(expr2, table));
218
+ this.$save(name);
212
219
  }
213
- });
214
- var name = "database";
215
- var schema = import_koishi.Schema.object({});
216
- function apply(ctx, config = {}) {
217
- ctx.database = new MemoryDatabase(ctx, config);
218
- }
219
- __name(apply, "apply");
220
+ async eval(name, expr, query) {
221
+ const table = this.$query(name, query);
222
+ return (0, import_orm_utils.executeEval)(table, expr);
223
+ }
224
+ };
225
+ __name(MemoryDatabase, "MemoryDatabase");
226
+ _store = new WeakMap();
227
+ _loader = new WeakMap();
228
+ var src_default = MemoryDatabase;
220
229
  // Annotate the CommonJS export names for ESM import in node:
221
230
  0 && (module.exports = {
222
- MemoryDatabase,
223
- apply,
224
- name,
225
- schema
231
+ MemoryDatabase
226
232
  });
227
233
  //# sourceMappingURL=node.js.map
package/lib/node.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, Schema } 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: 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\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 const name = 'database'\n\nexport const schema: Schema<Config> = Schema.object({})\n\nexport function apply(ctx: Context, config: Config = {}) {\n ctx.database = new MemoryDatabase(ctx, config)\n}\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, 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 eval(name: TableType, expr: any, query: Query) {\n const table = this.$query(name, query)\n return executeEval(table, expr)\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.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": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA,oBAA4G;AAC5G,uBAAsE;;;ACCtE,gBAA+B;AAC/B,kBAAiC;AAGjC,IAAM,UAAU,CAAC,QAAQ,QAAQ;AAO1B,oBAAc;AAAA,EACnB,YAAY,KAAsB,QAAgB;AAAhB;AAChC,WAAO,UAAP,QAAO,SAAW;AAClB,WAAO,QAAP,QAAO,OAAS,yBAAQ,IAAI,IAAI,SAAS;AACzC,QAAI,CAAC,QAAQ,SAAS,OAAO,SAAS;AACpC,YAAM,IAAI,MAAM,uBAAuB,OAAO;AAAA;AAAA;AAAA,QAI5C,MAAM,QAA+B;AACzC,UAAM,EAAE,MAAM,WAAW,KAAK;AAC9B,UAAM,mBAAG,MAAM,MAAM,EAAE,WAAW;AAClC,UAAM,QAAQ,MAAM,mBAAG,QAAQ;AAC/B,UAAM,QAAQ,IAAI,MAAM,IAAI,OAAO,aAAa;AAC9C,YAAM,YAAY,yBAAQ;AAC1B,UAAI,cAAc;AAAQ;AAC1B,YAAM,SAAS,MAAM,mBAAG,SAAS;AACjC,UAAI;AACF,cAAM,OAAO,MAAM,KAAK,KAAK,QAAQ;AACrC,cAAM,OAAO,SAAS,MAAM,GAAG,KAAK,UAAU;AAC9C,eAAO,QAAQ;AAAA,cACf;AAAA;AAAA;AAAA;AAAA,QAIA,KAAK,QAAgB,QAAgB;AACzC,QAAI,WAAW,QAAQ;AACrB,aAAO,KAAK,MAAM,OAAO;AAAA,eAChB,WAAW,UAAU,WAAW,OAAO;AAChD,YAAM,EAAE,SAAS,QAAQ;AACzB,aAAO,KAAK,OAAO;AAAA;AAAA;AAAA,QAIjB,KAAK,MAAe;AACxB,UAAM,EAAE,MAAM,WAAW,KAAK;AAC9B,QAAI,MAAM;AACR,YAAM,mBAAG,GAAG,yBAAQ,MAAM,GAAG,QAAQ;AAAA,WAChC;AACL,YAAM,mBAAG,GAAG,MAAM,EAAE,WAAW,MAAM,OAAO;AAAA;AAAA;AAAA,QAI1C,KAAK,MAAc,OAAc;AACrC,UAAM,EAAE,MAAM,WAAW,KAAK;AAC9B,QAAI;AACF,YAAM,SAAS,MAAM,KAAK,KAAK,OAAO;AACtC,YAAM,mBAAG,UAAU,yBAAQ,MAAM,GAAG,QAAQ,WAAW;AAAA,YACvD;AAAA;AAAA;AAAA,QAGE,KAAK,MAAW,QAAgB;AACpC,QAAI,WAAW,QAAQ;AACrB,aAAO,KAAK,UAAU;AAAA,eACb,WAAW,UAAU,WAAW,OAAO;AAChD,YAAM,EAAE,SAAS,QAAQ;AACzB,aAAO,KAAK;AAAA;AAAA;AAAA;AAxDX;;;ADbP;AAcO,mCAA6B,uBAAS;AAAA,EAM3C,YAAmB,KAAqB,SAAiB,IAAI;AAC3D,UAAM;AADW;AAAqB;AALjC,kBAAS;AAEhB,+BAAsB;AACtB;AAKE,QAAI,OAAO,SAAS;AAClB,yBAAK,SAAU,IAAI,QAAQ,KAAK;AAAA;AAAA;AAAA,QAI9B,QAAQ;AA5BhB;AA6BI,UAAM,0BAAK,aAAL,mBAAc,MAAM,mBAAK;AAAA;AAAA,QAG3B,MAAM,MAAc;AAhC5B;AAiCI,UAAM,0BAAK,aAAL,mBAAc,KAAK,MAAM,mBAAK,QAAO;AAAA;AAAA,EAG7C,OAAO;AAAA;AAAA,EAEP,OAA4B,OAAU;AAtCxC;AAuCI,WAAO,yBAAK,SAAL,uBAAuB;AAAA;AAAA,QAG1B,OAAO;AA1Cf;AA2CI,uBAAK,QAAS;AACd,UAAM,0BAAK,aAAL,mBAAc;AAAA;AAAA,QAGhB,QAAQ;AACZ,WAAO;AAAA;AAAA,EAGT,OAAO,MAAiB,OAAc;AACpC,UAAM,OAAO,KAAK,IAAI,MAAM,aAAa,MAAM;AAC/C,WAAO,KAAK,OAAO,MAAM,OAAO,SAAO,mCAAa,KAAK;AAAA;AAAA,QAGrD,IAAI,MAAiB,OAAc,UAA2B;AAClE,UAAM,EAAE,QAAQ,QAAQ,UAAU,SAAS,GAAG,OAAO,OAAO,oBAAM,gBAAgB;AAClF,WAAO,kCAAY,KAAK,OAAO,MAAM,QAAQ,MAC1C,IAAI,SAAO,yBAAM,wBAAK,KAAK,UAC3B,MAAM,QAAQ,SAAS;AAAA;AAAA,QAGtB,IAAI,MAAiB,OAAc,MAAU;AACjD,SAAK,OAAO,MAAM,OAAO,QAAQ,SAAO,oCAAc,KAAK;AAC3D,SAAK,MAAM;AAAA;AAAA,QAGP,OAAO,MAAiB,OAAc;AAC1C,UAAM,OAAO,KAAK,IAAI,MAAM,aAAa,MAAM;AAC/C,uBAAK,QAAO,QAAQ,KAAK,OAAO,MAC7B,OAAO,SAAO,CAAC,mCAAa,KAAK;AACpC,SAAK,MAAM;AAAA;AAAA,QAGP,OAAO,MAAiB,MAAW;AACvC,UAAM,QAAQ,KAAK,OAAO;AAC1B,UAAM,EAAE,SAAS,QAAQ,YAAY,KAAK,IAAI,MAAM,OAAO;AAC3D,WAAO,yBAAM;AACb,QAAI,CAAC,MAAM,QAAQ,YAAY,WAAW,CAAE,YAAW,OAAO;AAC5D,YAAM,MAAM,MAAM,SAAS,KAAK,IAAI,GAAG,MAAM,IAAI,SAAO,CAAC,IAAI,aAAa;AAC1E,WAAK,WAAW,MAAM;AACtB,UAAI,oBAAM,MAAM,OAAO,SAAS,OAAO,SAAS,OAAO;AACrD,aAAK,YAAY;AAAA;AAAA,WAEd;AACL,YAAM,aAAa,MAAM,KAAK,IAAI,MAAM,wBAAK,MAAM,6BAAU;AAC7D,UAAI,WAAW,QAAQ;AACrB,cAAM,IAAI,0BAAY,mBAAmB;AAAA;AAAA;AAG7C,UAAM,OAAO,kCAAK,KAAK,IAAI,MAAM,OAAO,QAAU;AAClD,UAAM,KAAK;AACX,SAAK,MAAM;AACX,WAAO,yBAAM;AAAA;AAAA,QAGT,OAAO,MAAiB,MAAa,KAAwB;AACjE,UAAM,OAAO,6BAAU,OAAO,KAAK,IAAI,MAAM,OAAO,MAAM;AAC1D,eAAW,QAAQ,MAAM;AACvB,YAAM,MAAM,KAAK,OAAO,MAAM,KAAK,UAAO;AACxC,eAAO,KAAK,MAAM,UAAO,KAAI,UAAS,KAAK;AAAA;AAE7C,UAAI,KAAK;AACP,4CAAc,KAAK;AAAA,aACd;AACL,cAAM,QAAO,KAAK,IAAI,MAAM,OAAO;AACnC,cAAM,KAAK,OAAO,MAAM,oCAAc,OAAM,OAAO,MAAM;AAAA;AAAA;AAG7D,SAAK,MAAM;AAAA;AAAA,QAGP,KAAK,MAAiB,MAAW,OAAc;AACnD,UAAM,QAAQ,KAAK,OAAO,MAAM;AAChC,WAAO,kCAAY,OAAO;AAAA;AAAA;AArGvB;AAGL;AACA;AAqGF,IAAO,cAAQ;",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
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.3",
4
+ "version": "1.0.0",
5
5
  "main": "lib/node.js",
6
6
  "module": "lib/browser.js",
7
7
  "typings": "lib/index.d.ts",
@@ -30,15 +30,15 @@
30
30
  "server"
31
31
  ],
32
32
  "peerDependencies": {
33
- "koishi": "^4.0.0-beta.5"
33
+ "koishi": "^4.0.0-rc.3"
34
34
  },
35
35
  "devDependencies": {
36
- "@koishijs/plugin-mock": "^1.0.0-beta.1",
37
- "@koishijs/test-utils": "^8.0.0-beta.5",
36
+ "@koishijs/plugin-mock": "^1.0.0",
37
+ "@koishijs/test-utils": "^8.0.0-rc.1",
38
38
  "@types/js-yaml": "^4.0.3",
39
39
  "js-yaml": "^4.1.0"
40
40
  },
41
41
  "dependencies": {
42
- "@koishijs/orm-utils": "^1.0.0-beta.3"
42
+ "@koishijs/orm-utils": "^1.0.0"
43
43
  }
44
44
  }