@thisisagile/easy-mongo 15.23.6 → 15.24.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.
@@ -1,4 +1,4 @@
1
- import { Condition, Database, FetchOptions, Field, Id, Json, JsonValue, LogicalCondition, OneOrMore, PageList, Sort } from '@thisisagile/easy';
1
+ import { Condition, FetchOptions, Field, Id, Json, JsonValue, LogicalCondition, OneOrMore, PageList, Sort } from '@thisisagile/easy';
2
2
  import { AggregationCursor, Collection as MongoCollection, CreateIndexesOptions, Document, FindCursor, FindOptions as MongoFindOptions, IndexSpecification, MongoClient, StrictFilter as MongoFilter } from 'mongodb';
3
3
  import { Collection } from './Collection';
4
4
  export type Projection = Record<string, 0 | 1>;
@@ -16,13 +16,14 @@ export type IndexOptions = {
16
16
  export type Indexes = OneOrMore<string | Field | Sort | Record<string, 1 | -1>>;
17
17
  export declare class MongoProvider {
18
18
  readonly coll: Collection;
19
- protected client?: Promise<MongoClient> | undefined;
20
19
  protected static readonly clients: {
21
- [key: string]: Promise<MongoClient>;
20
+ [key: string]: MongoClient;
22
21
  };
23
- constructor(coll: Collection, client?: Promise<MongoClient> | undefined);
24
- static client(db: Database): Promise<MongoClient>;
22
+ constructor(coll: Collection);
25
23
  cluster(): Promise<MongoClient>;
24
+ collection<T extends Document = Document>(): Promise<MongoCollection<T>>;
25
+ private static connect;
26
+ static disconnect(): void;
26
27
  toMongoJson(query: Query): Json;
27
28
  find(query: Query, options?: FindOptions): Promise<PageList<Json>>;
28
29
  all(options?: FindOptions): Promise<PageList<Json>>;
@@ -37,7 +38,6 @@ export declare class MongoProvider {
37
38
  createIndex(indexes: Indexes, options?: IndexOptions): Promise<string>;
38
39
  createPartialIndex(indexes: Indexes, filter: Query, options?: Omit<IndexOptions, 'filter'>): Promise<string>;
39
40
  createTextIndex(indexes: OneOrMore<Field | string>, options?: IndexOptions): Promise<string>;
40
- collection<T extends Document = Document>(): Promise<MongoCollection<T>>;
41
41
  protected toFindOptions(options?: FindOptions): MongoFindOptions & {
42
42
  total: boolean;
43
43
  };
@@ -26,30 +26,36 @@ var import_mongodb = require("mongodb");
26
26
  var import_Utils = require("./Utils");
27
27
  const omitId = (j) => import_easy.json.delete(j, "_id");
28
28
  class MongoProvider {
29
- constructor(coll, client) {
29
+ constructor(coll) {
30
30
  this.coll = coll;
31
- this.client = client;
32
31
  }
33
32
  static clients = {};
34
- static client(db) {
35
- return (0, import_easy.when)(db.options?.cluster).not.isDefined.reject(import_easy.Exception.IsNotValid.because("Missing cluster in database options.")).then(
36
- (u) => MongoProvider.clients[u] = MongoProvider.clients[u] ?? import_mongodb.MongoClient.connect(u, {
37
- auth: {
38
- username: (0, import_easy.asString)(db.options?.user),
39
- password: (0, import_easy.asString)(db.options?.password)
40
- },
41
- ...db.options?.maxPoolSize && { maxPoolSize: db.options?.maxPoolSize },
42
- ...db.options?.minPoolSize && { minPoolSize: db.options?.minPoolSize },
43
- ...db.options?.maxIdleTimeMS && { maxIdleTimeMS: db.options?.maxIdleTimeMS }
44
- })
45
- );
46
- }
47
- cluster() {
48
- return Promise.resolve().then(() => this.client ?? (this.client = MongoProvider.client(this.coll.db))).catch((e) => {
49
- this.client = void 0;
50
- return (0, import_easy.reject)(e);
33
+ async cluster() {
34
+ const db = this.coll.db;
35
+ const c = await (0, import_easy.when)(db.options?.cluster).not.isDefined.reject(import_easy.Exception.IsNotValid.because("Missing cluster in database options."));
36
+ return MongoProvider.clients[c] ?? (MongoProvider.clients[c] = await MongoProvider.connect(c, db));
37
+ }
38
+ collection() {
39
+ return this.cluster().then((c) => c.db(this.coll.db.name)).then((db) => db.collection((0, import_easy.asString)(this.coll)));
40
+ }
41
+ static connect(u, db) {
42
+ return import_mongodb.MongoClient.connect(u, {
43
+ auth: {
44
+ username: (0, import_easy.asString)(db.options?.user),
45
+ password: (0, import_easy.asString)(db.options?.password)
46
+ },
47
+ ...db.options?.maxPoolSize && { maxPoolSize: db.options?.maxPoolSize },
48
+ ...db.options?.minPoolSize && { minPoolSize: db.options?.minPoolSize },
49
+ ...db.options?.maxIdleTimeMS && { maxIdleTimeMS: db.options?.maxIdleTimeMS }
50
+ }).then((c) => {
51
+ c.on("error", () => delete MongoProvider.clients[u]);
52
+ c.on("close", () => delete MongoProvider.clients[u]);
53
+ return c;
51
54
  });
52
55
  }
56
+ static disconnect() {
57
+ Object.values(MongoProvider.clients).forEach((c) => void c.close());
58
+ }
53
59
  toMongoJson(query) {
54
60
  return (0, import_Utils.toMongoType)((0, import_easy.asJson)(query));
55
61
  }
@@ -98,9 +104,6 @@ class MongoProvider {
98
104
  const ii = (0, import_easy.toArray)(indexes).reduce((i, f) => ({ ...i, [(0, import_easy.asString)(f)]: "text" }), {});
99
105
  return this.createIndex(ii, { unique: false, ...options });
100
106
  }
101
- collection() {
102
- return this.cluster().then((c) => c.db(this.coll.db.name)).then((db) => db.collection((0, import_easy.asString)(this.coll)));
103
- }
104
107
  toFindOptions(options) {
105
108
  return {
106
109
  limit: (0, import_easy.asNumber)(options?.take ?? 250),
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/MongoProvider.ts"],"sourcesContent":["import {\n asJson,\n asNumber,\n asString,\n choose,\n Condition,\n Database,\n Exception,\n FetchOptions,\n Field,\n Id,\n ifTrue,\n isArray,\n isDefined,\n isField,\n isSortCondition,\n json,\n Json,\n JsonValue,\n LogicalCondition,\n OneOrMore,\n PageList,\n reject,\n Sort,\n toArray,\n toPageList,\n tuple2,\n tuple3,\n when,\n} from '@thisisagile/easy';\nimport {\n AggregationCursor,\n Collection as MongoCollection,\n CreateIndexesOptions,\n Document,\n FindCursor,\n FindOptions as MongoFindOptions,\n IndexSpecification,\n MongoClient,\n StrictFilter as MongoFilter,\n} from 'mongodb';\nimport { Collection } from './Collection';\nimport { toMongoType } from './Utils';\n\nconst omitId = (j: Json): Json => json.delete(j, '_id');\n\nexport type Projection = Record<string, 0 | 1>;\nexport type FindOptions = FetchOptions & { projection?: Projection };\nexport type Filter<T = unknown> = MongoFilter<T>;\nexport type Query = Condition | LogicalCondition | Filter<any>;\n\nexport type IndexOptions = {\n unique?: boolean;\n filter?: Query;\n languageOverride?: string;\n languageDefault?: string;\n};\n\nexport type Indexes = OneOrMore<string | Field | Sort | Record<string, 1 | -1>>;\n\nexport class MongoProvider {\n protected static readonly clients: { [key: string]: Promise<MongoClient> } = {};\n\n constructor(readonly coll: Collection, protected client?: Promise<MongoClient>) {}\n\n static client(db: Database): Promise<MongoClient> {\n return when(db.options?.cluster)\n .not.isDefined.reject(Exception.IsNotValid.because('Missing cluster in database options.'))\n .then(\n u =>\n (MongoProvider.clients[u] =\n MongoProvider.clients[u] ??\n MongoClient.connect(u, {\n auth: {\n username: asString(db.options?.user),\n password: asString(db.options?.password),\n },\n ...(db.options?.maxPoolSize && { maxPoolSize: db.options?.maxPoolSize }),\n ...(db.options?.minPoolSize && { minPoolSize: db.options?.minPoolSize }),\n ...(db.options?.maxIdleTimeMS && { maxIdleTimeMS: db.options?.maxIdleTimeMS }),\n }))\n );\n }\n\n cluster(): Promise<MongoClient> {\n return Promise.resolve()\n .then(() => this.client ?? (this.client = MongoProvider.client(this.coll.db)))\n .catch(e => {\n this.client = undefined;\n return reject(e);\n });\n }\n\n toMongoJson(query: Query): Json {\n return toMongoType(asJson(query));\n }\n\n find(query: Query, options?: FindOptions): Promise<PageList<Json>> {\n return tuple3(this.collection(), this.toMongoJson(query), this.toFindOptions(options))\n .then(([c, q, o]) =>\n tuple2(\n c.find(q, o),\n ifTrue(o.total, () => c.countDocuments(q))\n )\n )\n .then(([res, total]) => this.toArray(res, { ...options, total }));\n }\n\n all(options?: FindOptions): Promise<PageList<Json>> {\n return this.find({}, options);\n }\n\n byId(id: Id, options?: FindOptions): Promise<Json> {\n return this.collection().then(c => c.findOne(this.toMongoJson({ id: id }), this.toFindOptions(options)) as Promise<Json>);\n }\n\n by(key: string, value: JsonValue, options?: FindOptions): Promise<PageList<Json>> {\n return this.find({ [key]: value }, options);\n }\n\n group(qs: Filter<any>[]): Promise<PageList<Json>> {\n return this.aggregate(qs);\n }\n\n aggregate(qs: Filter<any>[]): Promise<PageList<Json>> {\n return this.collection()\n .then(c => c.aggregate(qs.map(q => this.toMongoJson(q))))\n .then(res => this.toArray(res));\n }\n\n add(item: Json): Promise<Json> {\n return this.collection()\n .then(c => c.insertOne(omitId(item)))\n .then(() => omitId(item));\n }\n\n update(item: Json): Promise<Json> {\n return this.collection()\n .then(c => c.updateOne(this.toMongoJson({ id: item.id }), { $set: omitId(item) }))\n .then(() => this.byId(item.id as Id));\n }\n\n remove(id: Id): Promise<boolean> {\n return this.collection()\n .then(c => c.deleteOne(this.toMongoJson({ id })))\n .then(d => d.acknowledged);\n }\n\n count(query?: Query): Promise<number> {\n return this.collection().then(c => c.countDocuments(this.toMongoJson(query ?? {})));\n }\n\n createIndex(indexes: Indexes, options?: IndexOptions): Promise<string> {\n return this.collection().then(c => c.createIndex(this.toIndexSpecification(indexes), this.toCreateIndexesOptions(options)));\n }\n\n createPartialIndex(indexes: Indexes, filter: Query, options?: Omit<IndexOptions, 'filter'>): Promise<string> {\n return this.createIndex(indexes, { ...options, filter });\n }\n\n createTextIndex(indexes: OneOrMore<Field | string>, options?: IndexOptions): Promise<string> {\n const ii = toArray(indexes).reduce((i, f) => ({ ...i, [asString(f)]: 'text' }), {});\n return this.createIndex(ii, { unique: false, ...options });\n }\n\n collection<T extends Document = Document>(): Promise<MongoCollection<T>> {\n return this.cluster()\n .then(c => c.db(this.coll.db.name))\n .then(db => db.collection<T>(asString(this.coll)));\n }\n\n protected toFindOptions(options?: FindOptions): MongoFindOptions & { total: boolean } {\n return {\n limit: asNumber(options?.take ?? 250),\n ...(options?.skip && { skip: asNumber(options?.skip) }),\n ...((options?.sorts && { sort: options?.sorts }) || (options?.sort && { sort: this.coll.sort(...(options?.sort ?? [])) })),\n total: isDefined(options?.skip) || isDefined(options?.take),\n projection: options?.projection ?? { _id: 0 },\n };\n }\n\n protected toIndexSpecification(index: Indexes): IndexSpecification {\n return choose(index)\n .type(isField, f => f.property as IndexSpecification)\n .type(isSortCondition, s => s.toJSON() as IndexSpecification)\n .type(isArray, aa => aa.map(a => this.toIndexSpecification(a)) as IndexSpecification)\n .else(i => i as IndexSpecification);\n }\n\n protected toCreateIndexesOptions(options?: IndexOptions): CreateIndexesOptions {\n return {\n unique: options?.unique ?? true,\n ...(options?.languageOverride && { language_override: options.languageOverride }),\n ...(options?.languageDefault && { default_language: options.languageDefault }),\n ...(options?.filter && { partialFilterExpression: toMongoType(asJson(options.filter)) }),\n };\n }\n\n protected toArray(\n cursor: FindCursor<Document> | AggregationCursor<Document>,\n options?: { take?: number; skip?: number; total?: number }\n ): Promise<PageList<Json>> {\n return cursor.toArray().then(r => toPageList<Json>(r, options));\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/MongoProvider.ts"],"sourcesContent":["import {\n asJson,\n asNumber,\n asString,\n choose,\n Condition,\n Database,\n Exception,\n FetchOptions,\n Field,\n Id,\n ifTrue,\n isArray,\n isDefined,\n isField,\n isSortCondition,\n json,\n Json,\n JsonValue,\n LogicalCondition,\n OneOrMore,\n PageList,\n Sort,\n toArray,\n toPageList,\n tuple2,\n tuple3,\n when,\n} from '@thisisagile/easy';\nimport {\n AggregationCursor,\n Collection as MongoCollection,\n CreateIndexesOptions,\n Document,\n FindCursor,\n FindOptions as MongoFindOptions,\n IndexSpecification,\n MongoClient,\n StrictFilter as MongoFilter,\n} from 'mongodb';\nimport { Collection } from './Collection';\nimport { toMongoType } from './Utils';\n\nconst omitId = (j: Json): Json => json.delete(j, '_id');\n\nexport type Projection = Record<string, 0 | 1>;\nexport type FindOptions = FetchOptions & { projection?: Projection };\nexport type Filter<T = unknown> = MongoFilter<T>;\nexport type Query = Condition | LogicalCondition | Filter<any>;\n\nexport type IndexOptions = {\n unique?: boolean;\n filter?: Query;\n languageOverride?: string;\n languageDefault?: string;\n};\n\nexport type Indexes = OneOrMore<string | Field | Sort | Record<string, 1 | -1>>;\n\nexport class MongoProvider {\n protected static readonly clients: { [key: string]: MongoClient } = {};\n\n constructor(readonly coll: Collection) {}\n\n async cluster(): Promise<MongoClient> {\n const db = this.coll.db;\n const c = await when(db.options?.cluster).not.isDefined.reject(Exception.IsNotValid.because('Missing cluster in database options.'));\n return MongoProvider.clients[c] ?? (MongoProvider.clients[c] = await MongoProvider.connect(c, db));\n }\n\n collection<T extends Document = Document>(): Promise<MongoCollection<T>> {\n return this.cluster()\n .then(c => c.db(this.coll.db.name))\n .then(db => db.collection<T>(asString(this.coll)));\n }\n\n private static connect(u: string, db: Database) {\n return MongoClient.connect(u, {\n auth: {\n username: asString(db.options?.user),\n password: asString(db.options?.password),\n },\n ...(db.options?.maxPoolSize && { maxPoolSize: db.options?.maxPoolSize }),\n ...(db.options?.minPoolSize && { minPoolSize: db.options?.minPoolSize }),\n ...(db.options?.maxIdleTimeMS && { maxIdleTimeMS: db.options?.maxIdleTimeMS }),\n }).then(c => {\n c.on('error', () => delete MongoProvider.clients[u]);\n c.on('close', () => delete MongoProvider.clients[u]);\n return c;\n });\n }\n\n static disconnect() {\n Object.values(MongoProvider.clients).forEach(c => void c.close());\n }\n\n toMongoJson(query: Query): Json {\n return toMongoType(asJson(query));\n }\n\n find(query: Query, options?: FindOptions): Promise<PageList<Json>> {\n return tuple3(this.collection(), this.toMongoJson(query), this.toFindOptions(options))\n .then(([c, q, o]) =>\n tuple2(\n c.find(q, o),\n ifTrue(o.total, () => c.countDocuments(q))\n )\n )\n .then(([res, total]) => this.toArray(res, { ...options, total }));\n }\n\n all(options?: FindOptions): Promise<PageList<Json>> {\n return this.find({}, options);\n }\n\n byId(id: Id, options?: FindOptions): Promise<Json> {\n return this.collection().then(c => c.findOne(this.toMongoJson({ id: id }), this.toFindOptions(options)) as Promise<Json>);\n }\n\n by(key: string, value: JsonValue, options?: FindOptions): Promise<PageList<Json>> {\n return this.find({ [key]: value }, options);\n }\n\n group(qs: Filter<any>[]): Promise<PageList<Json>> {\n return this.aggregate(qs);\n }\n\n aggregate(qs: Filter<any>[]): Promise<PageList<Json>> {\n return this.collection()\n .then(c => c.aggregate(qs.map(q => this.toMongoJson(q))))\n .then(res => this.toArray(res));\n }\n\n add(item: Json): Promise<Json> {\n return this.collection()\n .then(c => c.insertOne(omitId(item)))\n .then(() => omitId(item));\n }\n\n update(item: Json): Promise<Json> {\n return this.collection()\n .then(c => c.updateOne(this.toMongoJson({ id: item.id }), { $set: omitId(item) }))\n .then(() => this.byId(item.id as Id));\n }\n\n remove(id: Id): Promise<boolean> {\n return this.collection()\n .then(c => c.deleteOne(this.toMongoJson({ id })))\n .then(d => d.acknowledged);\n }\n\n count(query?: Query): Promise<number> {\n return this.collection().then(c => c.countDocuments(this.toMongoJson(query ?? {})));\n }\n\n createIndex(indexes: Indexes, options?: IndexOptions): Promise<string> {\n return this.collection().then(c => c.createIndex(this.toIndexSpecification(indexes), this.toCreateIndexesOptions(options)));\n }\n\n createPartialIndex(indexes: Indexes, filter: Query, options?: Omit<IndexOptions, 'filter'>): Promise<string> {\n return this.createIndex(indexes, { ...options, filter });\n }\n\n createTextIndex(indexes: OneOrMore<Field | string>, options?: IndexOptions): Promise<string> {\n const ii = toArray(indexes).reduce((i, f) => ({ ...i, [asString(f)]: 'text' }), {});\n return this.createIndex(ii, { unique: false, ...options });\n }\n\n protected toFindOptions(options?: FindOptions): MongoFindOptions & { total: boolean } {\n return {\n limit: asNumber(options?.take ?? 250),\n ...(options?.skip && { skip: asNumber(options?.skip) }),\n ...((options?.sorts && { sort: options?.sorts }) || (options?.sort && { sort: this.coll.sort(...(options?.sort ?? [])) })),\n total: isDefined(options?.skip) || isDefined(options?.take),\n projection: options?.projection ?? { _id: 0 },\n };\n }\n\n protected toIndexSpecification(index: Indexes): IndexSpecification {\n return choose(index)\n .type(isField, f => f.property as IndexSpecification)\n .type(isSortCondition, s => s.toJSON() as IndexSpecification)\n .type(isArray, aa => aa.map(a => this.toIndexSpecification(a)) as IndexSpecification)\n .else(i => i as IndexSpecification);\n }\n\n protected toCreateIndexesOptions(options?: IndexOptions): CreateIndexesOptions {\n return {\n unique: options?.unique ?? true,\n ...(options?.languageOverride && { language_override: options.languageOverride }),\n ...(options?.languageDefault && { default_language: options.languageDefault }),\n ...(options?.filter && { partialFilterExpression: toMongoType(asJson(options.filter)) }),\n };\n }\n\n protected toArray(\n cursor: FindCursor<Document> | AggregationCursor<Document>,\n options?: { take?: number; skip?: number; total?: number }\n ): Promise<PageList<Json>> {\n return cursor.toArray().then(r => toPageList<Json>(r, options));\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBA4BO;AACP,qBAUO;AAEP,mBAA4B;AAE5B,MAAM,SAAS,CAAC,MAAkB,iBAAK,OAAO,GAAG,KAAK;AAgB/C,MAAM,cAAc;AAAA,EAGzB,YAAqB,MAAkB;AAAlB;AAAA,EAAmB;AAAA,EAFxC,OAA0B,UAA0C,CAAC;AAAA,EAIrE,MAAM,UAAgC;AACpC,UAAM,KAAK,KAAK,KAAK;AACrB,UAAM,IAAI,UAAM,kBAAK,GAAG,SAAS,OAAO,EAAE,IAAI,UAAU,OAAO,sBAAU,WAAW,QAAQ,sCAAsC,CAAC;AACnI,WAAO,cAAc,QAAQ,CAAC,MAAM,cAAc,QAAQ,CAAC,IAAI,MAAM,cAAc,QAAQ,GAAG,EAAE;AAAA,EAClG;AAAA,EAEA,aAAyE;AACvE,WAAO,KAAK,QAAQ,EACjB,KAAK,OAAK,EAAE,GAAG,KAAK,KAAK,GAAG,IAAI,CAAC,EACjC,KAAK,QAAM,GAAG,eAAc,sBAAS,KAAK,IAAI,CAAC,CAAC;AAAA,EACrD;AAAA,EAEA,OAAe,QAAQ,GAAW,IAAc;AAC9C,WAAO,2BAAY,QAAQ,GAAG;AAAA,MAC5B,MAAM;AAAA,QACJ,cAAU,sBAAS,GAAG,SAAS,IAAI;AAAA,QACnC,cAAU,sBAAS,GAAG,SAAS,QAAQ;AAAA,MACzC;AAAA,MACA,GAAI,GAAG,SAAS,eAAe,EAAE,aAAa,GAAG,SAAS,YAAY;AAAA,MACtE,GAAI,GAAG,SAAS,eAAe,EAAE,aAAa,GAAG,SAAS,YAAY;AAAA,MACtE,GAAI,GAAG,SAAS,iBAAiB,EAAE,eAAe,GAAG,SAAS,cAAc;AAAA,IAC9E,CAAC,EAAE,KAAK,OAAK;AACX,QAAE,GAAG,SAAS,MAAM,OAAO,cAAc,QAAQ,CAAC,CAAC;AACnD,QAAE,GAAG,SAAS,MAAM,OAAO,cAAc,QAAQ,CAAC,CAAC;AACnD,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA,EAEA,OAAO,aAAa;AAClB,WAAO,OAAO,cAAc,OAAO,EAAE,QAAQ,OAAK,KAAK,EAAE,MAAM,CAAC;AAAA,EAClE;AAAA,EAEA,YAAY,OAAoB;AAC9B,eAAO,8BAAY,oBAAO,KAAK,CAAC;AAAA,EAClC;AAAA,EAEA,KAAK,OAAc,SAAgD;AACjE,eAAO,oBAAO,KAAK,WAAW,GAAG,KAAK,YAAY,KAAK,GAAG,KAAK,cAAc,OAAO,CAAC,EAClF;AAAA,MAAK,CAAC,CAAC,GAAG,GAAG,CAAC,UACb;AAAA,QACE,EAAE,KAAK,GAAG,CAAC;AAAA,YACX,oBAAO,EAAE,OAAO,MAAM,EAAE,eAAe,CAAC,CAAC;AAAA,MAC3C;AAAA,IACF,EACC,KAAK,CAAC,CAAC,KAAK,KAAK,MAAM,KAAK,QAAQ,KAAK,EAAE,GAAG,SAAS,MAAM,CAAC,CAAC;AAAA,EACpE;AAAA,EAEA,IAAI,SAAgD;AAClD,WAAO,KAAK,KAAK,CAAC,GAAG,OAAO;AAAA,EAC9B;AAAA,EAEA,KAAK,IAAQ,SAAsC;AACjD,WAAO,KAAK,WAAW,EAAE,KAAK,OAAK,EAAE,QAAQ,KAAK,YAAY,EAAE,GAAO,CAAC,GAAG,KAAK,cAAc,OAAO,CAAC,CAAkB;AAAA,EAC1H;AAAA,EAEA,GAAG,KAAa,OAAkB,SAAgD;AAChF,WAAO,KAAK,KAAK,EAAE,CAAC,GAAG,GAAG,MAAM,GAAG,OAAO;AAAA,EAC5C;AAAA,EAEA,MAAM,IAA4C;AAChD,WAAO,KAAK,UAAU,EAAE;AAAA,EAC1B;AAAA,EAEA,UAAU,IAA4C;AACpD,WAAO,KAAK,WAAW,EACpB,KAAK,OAAK,EAAE,UAAU,GAAG,IAAI,OAAK,KAAK,YAAY,CAAC,CAAC,CAAC,CAAC,EACvD,KAAK,SAAO,KAAK,QAAQ,GAAG,CAAC;AAAA,EAClC;AAAA,EAEA,IAAI,MAA2B;AAC7B,WAAO,KAAK,WAAW,EACpB,KAAK,OAAK,EAAE,UAAU,OAAO,IAAI,CAAC,CAAC,EACnC,KAAK,MAAM,OAAO,IAAI,CAAC;AAAA,EAC5B;AAAA,EAEA,OAAO,MAA2B;AAChC,WAAO,KAAK,WAAW,EACpB,KAAK,OAAK,EAAE,UAAU,KAAK,YAAY,EAAE,IAAI,KAAK,GAAG,CAAC,GAAG,EAAE,MAAM,OAAO,IAAI,EAAE,CAAC,CAAC,EAChF,KAAK,MAAM,KAAK,KAAK,KAAK,EAAQ,CAAC;AAAA,EACxC;AAAA,EAEA,OAAO,IAA0B;AAC/B,WAAO,KAAK,WAAW,EACpB,KAAK,OAAK,EAAE,UAAU,KAAK,YAAY,EAAE,GAAG,CAAC,CAAC,CAAC,EAC/C,KAAK,OAAK,EAAE,YAAY;AAAA,EAC7B;AAAA,EAEA,MAAM,OAAgC;AACpC,WAAO,KAAK,WAAW,EAAE,KAAK,OAAK,EAAE,eAAe,KAAK,YAAY,SAAS,CAAC,CAAC,CAAC,CAAC;AAAA,EACpF;AAAA,EAEA,YAAY,SAAkB,SAAyC;AACrE,WAAO,KAAK,WAAW,EAAE,KAAK,OAAK,EAAE,YAAY,KAAK,qBAAqB,OAAO,GAAG,KAAK,uBAAuB,OAAO,CAAC,CAAC;AAAA,EAC5H;AAAA,EAEA,mBAAmB,SAAkB,QAAe,SAAyD;AAC3G,WAAO,KAAK,YAAY,SAAS,EAAE,GAAG,SAAS,OAAO,CAAC;AAAA,EACzD;AAAA,EAEA,gBAAgB,SAAoC,SAAyC;AAC3F,UAAM,SAAK,qBAAQ,OAAO,EAAE,OAAO,CAAC,GAAG,OAAO,EAAE,GAAG,GAAG,KAAC,sBAAS,CAAC,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC;AAClF,WAAO,KAAK,YAAY,IAAI,EAAE,QAAQ,OAAO,GAAG,QAAQ,CAAC;AAAA,EAC3D;AAAA,EAEU,cAAc,SAA8D;AACpF,WAAO;AAAA,MACL,WAAO,sBAAS,SAAS,QAAQ,GAAG;AAAA,MACpC,GAAI,SAAS,QAAQ,EAAE,UAAM,sBAAS,SAAS,IAAI,EAAE;AAAA,MACrD,GAAK,SAAS,SAAS,EAAE,MAAM,SAAS,MAAM,KAAO,SAAS,QAAQ,EAAE,MAAM,KAAK,KAAK,KAAK,GAAI,SAAS,QAAQ,CAAC,CAAE,EAAE;AAAA,MACvH,WAAO,uBAAU,SAAS,IAAI,SAAK,uBAAU,SAAS,IAAI;AAAA,MAC1D,YAAY,SAAS,cAAc,EAAE,KAAK,EAAE;AAAA,IAC9C;AAAA,EACF;AAAA,EAEU,qBAAqB,OAAoC;AACjE,eAAO,oBAAO,KAAK,EAChB,KAAK,qBAAS,OAAK,EAAE,QAA8B,EACnD,KAAK,6BAAiB,OAAK,EAAE,OAAO,CAAuB,EAC3D,KAAK,qBAAS,QAAM,GAAG,IAAI,OAAK,KAAK,qBAAqB,CAAC,CAAC,CAAuB,EACnF,KAAK,OAAK,CAAuB;AAAA,EACtC;AAAA,EAEU,uBAAuB,SAA8C;AAC7E,WAAO;AAAA,MACL,QAAQ,SAAS,UAAU;AAAA,MAC3B,GAAI,SAAS,oBAAoB,EAAE,mBAAmB,QAAQ,iBAAiB;AAAA,MAC/E,GAAI,SAAS,mBAAmB,EAAE,kBAAkB,QAAQ,gBAAgB;AAAA,MAC5E,GAAI,SAAS,UAAU,EAAE,6BAAyB,8BAAY,oBAAO,QAAQ,MAAM,CAAC,EAAE;AAAA,IACxF;AAAA,EACF;AAAA,EAEU,QACR,QACA,SACyB;AACzB,WAAO,OAAO,QAAQ,EAAE,KAAK,WAAK,wBAAiB,GAAG,OAAO,CAAC;AAAA,EAChE;AACF;","names":[]}
@@ -10,7 +10,6 @@ import {
10
10
  isField,
11
11
  isSortCondition,
12
12
  json,
13
- reject,
14
13
  toArray,
15
14
  toPageList,
16
15
  tuple2,
@@ -23,30 +22,36 @@ import {
23
22
  import { toMongoType } from "./Utils";
24
23
  const omitId = (j) => json.delete(j, "_id");
25
24
  class MongoProvider {
26
- constructor(coll, client) {
25
+ constructor(coll) {
27
26
  this.coll = coll;
28
- this.client = client;
29
27
  }
30
28
  static clients = {};
31
- static client(db) {
32
- return when(db.options?.cluster).not.isDefined.reject(Exception.IsNotValid.because("Missing cluster in database options.")).then(
33
- (u) => MongoProvider.clients[u] = MongoProvider.clients[u] ?? MongoClient.connect(u, {
34
- auth: {
35
- username: asString(db.options?.user),
36
- password: asString(db.options?.password)
37
- },
38
- ...db.options?.maxPoolSize && { maxPoolSize: db.options?.maxPoolSize },
39
- ...db.options?.minPoolSize && { minPoolSize: db.options?.minPoolSize },
40
- ...db.options?.maxIdleTimeMS && { maxIdleTimeMS: db.options?.maxIdleTimeMS }
41
- })
42
- );
43
- }
44
- cluster() {
45
- return Promise.resolve().then(() => this.client ?? (this.client = MongoProvider.client(this.coll.db))).catch((e) => {
46
- this.client = void 0;
47
- return reject(e);
29
+ async cluster() {
30
+ const db = this.coll.db;
31
+ const c = await when(db.options?.cluster).not.isDefined.reject(Exception.IsNotValid.because("Missing cluster in database options."));
32
+ return MongoProvider.clients[c] ?? (MongoProvider.clients[c] = await MongoProvider.connect(c, db));
33
+ }
34
+ collection() {
35
+ return this.cluster().then((c) => c.db(this.coll.db.name)).then((db) => db.collection(asString(this.coll)));
36
+ }
37
+ static connect(u, db) {
38
+ return MongoClient.connect(u, {
39
+ auth: {
40
+ username: asString(db.options?.user),
41
+ password: asString(db.options?.password)
42
+ },
43
+ ...db.options?.maxPoolSize && { maxPoolSize: db.options?.maxPoolSize },
44
+ ...db.options?.minPoolSize && { minPoolSize: db.options?.minPoolSize },
45
+ ...db.options?.maxIdleTimeMS && { maxIdleTimeMS: db.options?.maxIdleTimeMS }
46
+ }).then((c) => {
47
+ c.on("error", () => delete MongoProvider.clients[u]);
48
+ c.on("close", () => delete MongoProvider.clients[u]);
49
+ return c;
48
50
  });
49
51
  }
52
+ static disconnect() {
53
+ Object.values(MongoProvider.clients).forEach((c) => void c.close());
54
+ }
50
55
  toMongoJson(query) {
51
56
  return toMongoType(asJson(query));
52
57
  }
@@ -95,9 +100,6 @@ class MongoProvider {
95
100
  const ii = toArray(indexes).reduce((i, f) => ({ ...i, [asString(f)]: "text" }), {});
96
101
  return this.createIndex(ii, { unique: false, ...options });
97
102
  }
98
- collection() {
99
- return this.cluster().then((c) => c.db(this.coll.db.name)).then((db) => db.collection(asString(this.coll)));
100
- }
101
103
  toFindOptions(options) {
102
104
  return {
103
105
  limit: asNumber(options?.take ?? 250),
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/MongoProvider.ts"],"sourcesContent":["import {\n asJson,\n asNumber,\n asString,\n choose,\n Condition,\n Database,\n Exception,\n FetchOptions,\n Field,\n Id,\n ifTrue,\n isArray,\n isDefined,\n isField,\n isSortCondition,\n json,\n Json,\n JsonValue,\n LogicalCondition,\n OneOrMore,\n PageList,\n reject,\n Sort,\n toArray,\n toPageList,\n tuple2,\n tuple3,\n when,\n} from '@thisisagile/easy';\nimport {\n AggregationCursor,\n Collection as MongoCollection,\n CreateIndexesOptions,\n Document,\n FindCursor,\n FindOptions as MongoFindOptions,\n IndexSpecification,\n MongoClient,\n StrictFilter as MongoFilter,\n} from 'mongodb';\nimport { Collection } from './Collection';\nimport { toMongoType } from './Utils';\n\nconst omitId = (j: Json): Json => json.delete(j, '_id');\n\nexport type Projection = Record<string, 0 | 1>;\nexport type FindOptions = FetchOptions & { projection?: Projection };\nexport type Filter<T = unknown> = MongoFilter<T>;\nexport type Query = Condition | LogicalCondition | Filter<any>;\n\nexport type IndexOptions = {\n unique?: boolean;\n filter?: Query;\n languageOverride?: string;\n languageDefault?: string;\n};\n\nexport type Indexes = OneOrMore<string | Field | Sort | Record<string, 1 | -1>>;\n\nexport class MongoProvider {\n protected static readonly clients: { [key: string]: Promise<MongoClient> } = {};\n\n constructor(readonly coll: Collection, protected client?: Promise<MongoClient>) {}\n\n static client(db: Database): Promise<MongoClient> {\n return when(db.options?.cluster)\n .not.isDefined.reject(Exception.IsNotValid.because('Missing cluster in database options.'))\n .then(\n u =>\n (MongoProvider.clients[u] =\n MongoProvider.clients[u] ??\n MongoClient.connect(u, {\n auth: {\n username: asString(db.options?.user),\n password: asString(db.options?.password),\n },\n ...(db.options?.maxPoolSize && { maxPoolSize: db.options?.maxPoolSize }),\n ...(db.options?.minPoolSize && { minPoolSize: db.options?.minPoolSize }),\n ...(db.options?.maxIdleTimeMS && { maxIdleTimeMS: db.options?.maxIdleTimeMS }),\n }))\n );\n }\n\n cluster(): Promise<MongoClient> {\n return Promise.resolve()\n .then(() => this.client ?? (this.client = MongoProvider.client(this.coll.db)))\n .catch(e => {\n this.client = undefined;\n return reject(e);\n });\n }\n\n toMongoJson(query: Query): Json {\n return toMongoType(asJson(query));\n }\n\n find(query: Query, options?: FindOptions): Promise<PageList<Json>> {\n return tuple3(this.collection(), this.toMongoJson(query), this.toFindOptions(options))\n .then(([c, q, o]) =>\n tuple2(\n c.find(q, o),\n ifTrue(o.total, () => c.countDocuments(q))\n )\n )\n .then(([res, total]) => this.toArray(res, { ...options, total }));\n }\n\n all(options?: FindOptions): Promise<PageList<Json>> {\n return this.find({}, options);\n }\n\n byId(id: Id, options?: FindOptions): Promise<Json> {\n return this.collection().then(c => c.findOne(this.toMongoJson({ id: id }), this.toFindOptions(options)) as Promise<Json>);\n }\n\n by(key: string, value: JsonValue, options?: FindOptions): Promise<PageList<Json>> {\n return this.find({ [key]: value }, options);\n }\n\n group(qs: Filter<any>[]): Promise<PageList<Json>> {\n return this.aggregate(qs);\n }\n\n aggregate(qs: Filter<any>[]): Promise<PageList<Json>> {\n return this.collection()\n .then(c => c.aggregate(qs.map(q => this.toMongoJson(q))))\n .then(res => this.toArray(res));\n }\n\n add(item: Json): Promise<Json> {\n return this.collection()\n .then(c => c.insertOne(omitId(item)))\n .then(() => omitId(item));\n }\n\n update(item: Json): Promise<Json> {\n return this.collection()\n .then(c => c.updateOne(this.toMongoJson({ id: item.id }), { $set: omitId(item) }))\n .then(() => this.byId(item.id as Id));\n }\n\n remove(id: Id): Promise<boolean> {\n return this.collection()\n .then(c => c.deleteOne(this.toMongoJson({ id })))\n .then(d => d.acknowledged);\n }\n\n count(query?: Query): Promise<number> {\n return this.collection().then(c => c.countDocuments(this.toMongoJson(query ?? {})));\n }\n\n createIndex(indexes: Indexes, options?: IndexOptions): Promise<string> {\n return this.collection().then(c => c.createIndex(this.toIndexSpecification(indexes), this.toCreateIndexesOptions(options)));\n }\n\n createPartialIndex(indexes: Indexes, filter: Query, options?: Omit<IndexOptions, 'filter'>): Promise<string> {\n return this.createIndex(indexes, { ...options, filter });\n }\n\n createTextIndex(indexes: OneOrMore<Field | string>, options?: IndexOptions): Promise<string> {\n const ii = toArray(indexes).reduce((i, f) => ({ ...i, [asString(f)]: 'text' }), {});\n return this.createIndex(ii, { unique: false, ...options });\n }\n\n collection<T extends Document = Document>(): Promise<MongoCollection<T>> {\n return this.cluster()\n .then(c => c.db(this.coll.db.name))\n .then(db => db.collection<T>(asString(this.coll)));\n }\n\n protected toFindOptions(options?: FindOptions): MongoFindOptions & { total: boolean } {\n return {\n limit: asNumber(options?.take ?? 250),\n ...(options?.skip && { skip: asNumber(options?.skip) }),\n ...((options?.sorts && { sort: options?.sorts }) || (options?.sort && { sort: this.coll.sort(...(options?.sort ?? [])) })),\n total: isDefined(options?.skip) || isDefined(options?.take),\n projection: options?.projection ?? { _id: 0 },\n };\n }\n\n protected toIndexSpecification(index: Indexes): IndexSpecification {\n return choose(index)\n .type(isField, f => f.property as IndexSpecification)\n .type(isSortCondition, s => s.toJSON() as IndexSpecification)\n .type(isArray, aa => aa.map(a => this.toIndexSpecification(a)) as IndexSpecification)\n .else(i => i as IndexSpecification);\n }\n\n protected toCreateIndexesOptions(options?: IndexOptions): CreateIndexesOptions {\n return {\n unique: options?.unique ?? true,\n ...(options?.languageOverride && { language_override: options.languageOverride }),\n ...(options?.languageDefault && { default_language: options.languageDefault }),\n ...(options?.filter && { partialFilterExpression: toMongoType(asJson(options.filter)) }),\n };\n }\n\n protected toArray(\n cursor: FindCursor<Document> | AggregationCursor<Document>,\n options?: { take?: number; skip?: number; total?: number }\n ): Promise<PageList<Json>> {\n return cursor.toArray().then(r => toPageList<Json>(r, options));\n }\n}\n"],"mappings":"AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAGA;AAAA,EAIA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAMA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EAQE;AAAA,OAEK;AAEP,SAAS,mBAAmB;AAE5B,MAAM,SAAS,CAAC,MAAkB,KAAK,OAAO,GAAG,KAAK;AAgB/C,MAAM,cAAc;AAAA,EAGzB,YAAqB,MAA4B,QAA+B;AAA3D;AAA4B;AAAA,EAAgC;AAAA,EAFjF,OAA0B,UAAmD,CAAC;AAAA,EAI9E,OAAO,OAAO,IAAoC;AAChD,WAAO,KAAK,GAAG,SAAS,OAAO,EAC5B,IAAI,UAAU,OAAO,UAAU,WAAW,QAAQ,sCAAsC,CAAC,EACzF;AAAA,MACC,OACG,cAAc,QAAQ,CAAC,IACtB,cAAc,QAAQ,CAAC,KACvB,YAAY,QAAQ,GAAG;AAAA,QACrB,MAAM;AAAA,UACJ,UAAU,SAAS,GAAG,SAAS,IAAI;AAAA,UACnC,UAAU,SAAS,GAAG,SAAS,QAAQ;AAAA,QACzC;AAAA,QACA,GAAI,GAAG,SAAS,eAAe,EAAE,aAAa,GAAG,SAAS,YAAY;AAAA,QACtE,GAAI,GAAG,SAAS,eAAe,EAAE,aAAa,GAAG,SAAS,YAAY;AAAA,QACtE,GAAI,GAAG,SAAS,iBAAiB,EAAE,eAAe,GAAG,SAAS,cAAc;AAAA,MAC9E,CAAC;AAAA,IACP;AAAA,EACJ;AAAA,EAEA,UAAgC;AAC9B,WAAO,QAAQ,QAAQ,EACpB,KAAK,MAAM,KAAK,WAAW,KAAK,SAAS,cAAc,OAAO,KAAK,KAAK,EAAE,EAAE,EAC5E,MAAM,OAAK;AACV,WAAK,SAAS;AACd,aAAO,OAAO,CAAC;AAAA,IACjB,CAAC;AAAA,EACL;AAAA,EAEA,YAAY,OAAoB;AAC9B,WAAO,YAAY,OAAO,KAAK,CAAC;AAAA,EAClC;AAAA,EAEA,KAAK,OAAc,SAAgD;AACjE,WAAO,OAAO,KAAK,WAAW,GAAG,KAAK,YAAY,KAAK,GAAG,KAAK,cAAc,OAAO,CAAC,EAClF;AAAA,MAAK,CAAC,CAAC,GAAG,GAAG,CAAC,MACb;AAAA,QACE,EAAE,KAAK,GAAG,CAAC;AAAA,QACX,OAAO,EAAE,OAAO,MAAM,EAAE,eAAe,CAAC,CAAC;AAAA,MAC3C;AAAA,IACF,EACC,KAAK,CAAC,CAAC,KAAK,KAAK,MAAM,KAAK,QAAQ,KAAK,EAAE,GAAG,SAAS,MAAM,CAAC,CAAC;AAAA,EACpE;AAAA,EAEA,IAAI,SAAgD;AAClD,WAAO,KAAK,KAAK,CAAC,GAAG,OAAO;AAAA,EAC9B;AAAA,EAEA,KAAK,IAAQ,SAAsC;AACjD,WAAO,KAAK,WAAW,EAAE,KAAK,OAAK,EAAE,QAAQ,KAAK,YAAY,EAAE,GAAO,CAAC,GAAG,KAAK,cAAc,OAAO,CAAC,CAAkB;AAAA,EAC1H;AAAA,EAEA,GAAG,KAAa,OAAkB,SAAgD;AAChF,WAAO,KAAK,KAAK,EAAE,CAAC,GAAG,GAAG,MAAM,GAAG,OAAO;AAAA,EAC5C;AAAA,EAEA,MAAM,IAA4C;AAChD,WAAO,KAAK,UAAU,EAAE;AAAA,EAC1B;AAAA,EAEA,UAAU,IAA4C;AACpD,WAAO,KAAK,WAAW,EACpB,KAAK,OAAK,EAAE,UAAU,GAAG,IAAI,OAAK,KAAK,YAAY,CAAC,CAAC,CAAC,CAAC,EACvD,KAAK,SAAO,KAAK,QAAQ,GAAG,CAAC;AAAA,EAClC;AAAA,EAEA,IAAI,MAA2B;AAC7B,WAAO,KAAK,WAAW,EACpB,KAAK,OAAK,EAAE,UAAU,OAAO,IAAI,CAAC,CAAC,EACnC,KAAK,MAAM,OAAO,IAAI,CAAC;AAAA,EAC5B;AAAA,EAEA,OAAO,MAA2B;AAChC,WAAO,KAAK,WAAW,EACpB,KAAK,OAAK,EAAE,UAAU,KAAK,YAAY,EAAE,IAAI,KAAK,GAAG,CAAC,GAAG,EAAE,MAAM,OAAO,IAAI,EAAE,CAAC,CAAC,EAChF,KAAK,MAAM,KAAK,KAAK,KAAK,EAAQ,CAAC;AAAA,EACxC;AAAA,EAEA,OAAO,IAA0B;AAC/B,WAAO,KAAK,WAAW,EACpB,KAAK,OAAK,EAAE,UAAU,KAAK,YAAY,EAAE,GAAG,CAAC,CAAC,CAAC,EAC/C,KAAK,OAAK,EAAE,YAAY;AAAA,EAC7B;AAAA,EAEA,MAAM,OAAgC;AACpC,WAAO,KAAK,WAAW,EAAE,KAAK,OAAK,EAAE,eAAe,KAAK,YAAY,SAAS,CAAC,CAAC,CAAC,CAAC;AAAA,EACpF;AAAA,EAEA,YAAY,SAAkB,SAAyC;AACrE,WAAO,KAAK,WAAW,EAAE,KAAK,OAAK,EAAE,YAAY,KAAK,qBAAqB,OAAO,GAAG,KAAK,uBAAuB,OAAO,CAAC,CAAC;AAAA,EAC5H;AAAA,EAEA,mBAAmB,SAAkB,QAAe,SAAyD;AAC3G,WAAO,KAAK,YAAY,SAAS,EAAE,GAAG,SAAS,OAAO,CAAC;AAAA,EACzD;AAAA,EAEA,gBAAgB,SAAoC,SAAyC;AAC3F,UAAM,KAAK,QAAQ,OAAO,EAAE,OAAO,CAAC,GAAG,OAAO,EAAE,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC;AAClF,WAAO,KAAK,YAAY,IAAI,EAAE,QAAQ,OAAO,GAAG,QAAQ,CAAC;AAAA,EAC3D;AAAA,EAEA,aAAyE;AACvE,WAAO,KAAK,QAAQ,EACjB,KAAK,OAAK,EAAE,GAAG,KAAK,KAAK,GAAG,IAAI,CAAC,EACjC,KAAK,QAAM,GAAG,WAAc,SAAS,KAAK,IAAI,CAAC,CAAC;AAAA,EACrD;AAAA,EAEU,cAAc,SAA8D;AACpF,WAAO;AAAA,MACL,OAAO,SAAS,SAAS,QAAQ,GAAG;AAAA,MACpC,GAAI,SAAS,QAAQ,EAAE,MAAM,SAAS,SAAS,IAAI,EAAE;AAAA,MACrD,GAAK,SAAS,SAAS,EAAE,MAAM,SAAS,MAAM,KAAO,SAAS,QAAQ,EAAE,MAAM,KAAK,KAAK,KAAK,GAAI,SAAS,QAAQ,CAAC,CAAE,EAAE;AAAA,MACvH,OAAO,UAAU,SAAS,IAAI,KAAK,UAAU,SAAS,IAAI;AAAA,MAC1D,YAAY,SAAS,cAAc,EAAE,KAAK,EAAE;AAAA,IAC9C;AAAA,EACF;AAAA,EAEU,qBAAqB,OAAoC;AACjE,WAAO,OAAO,KAAK,EAChB,KAAK,SAAS,OAAK,EAAE,QAA8B,EACnD,KAAK,iBAAiB,OAAK,EAAE,OAAO,CAAuB,EAC3D,KAAK,SAAS,QAAM,GAAG,IAAI,OAAK,KAAK,qBAAqB,CAAC,CAAC,CAAuB,EACnF,KAAK,OAAK,CAAuB;AAAA,EACtC;AAAA,EAEU,uBAAuB,SAA8C;AAC7E,WAAO;AAAA,MACL,QAAQ,SAAS,UAAU;AAAA,MAC3B,GAAI,SAAS,oBAAoB,EAAE,mBAAmB,QAAQ,iBAAiB;AAAA,MAC/E,GAAI,SAAS,mBAAmB,EAAE,kBAAkB,QAAQ,gBAAgB;AAAA,MAC5E,GAAI,SAAS,UAAU,EAAE,yBAAyB,YAAY,OAAO,QAAQ,MAAM,CAAC,EAAE;AAAA,IACxF;AAAA,EACF;AAAA,EAEU,QACR,QACA,SACyB;AACzB,WAAO,OAAO,QAAQ,EAAE,KAAK,OAAK,WAAiB,GAAG,OAAO,CAAC;AAAA,EAChE;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/MongoProvider.ts"],"sourcesContent":["import {\n asJson,\n asNumber,\n asString,\n choose,\n Condition,\n Database,\n Exception,\n FetchOptions,\n Field,\n Id,\n ifTrue,\n isArray,\n isDefined,\n isField,\n isSortCondition,\n json,\n Json,\n JsonValue,\n LogicalCondition,\n OneOrMore,\n PageList,\n Sort,\n toArray,\n toPageList,\n tuple2,\n tuple3,\n when,\n} from '@thisisagile/easy';\nimport {\n AggregationCursor,\n Collection as MongoCollection,\n CreateIndexesOptions,\n Document,\n FindCursor,\n FindOptions as MongoFindOptions,\n IndexSpecification,\n MongoClient,\n StrictFilter as MongoFilter,\n} from 'mongodb';\nimport { Collection } from './Collection';\nimport { toMongoType } from './Utils';\n\nconst omitId = (j: Json): Json => json.delete(j, '_id');\n\nexport type Projection = Record<string, 0 | 1>;\nexport type FindOptions = FetchOptions & { projection?: Projection };\nexport type Filter<T = unknown> = MongoFilter<T>;\nexport type Query = Condition | LogicalCondition | Filter<any>;\n\nexport type IndexOptions = {\n unique?: boolean;\n filter?: Query;\n languageOverride?: string;\n languageDefault?: string;\n};\n\nexport type Indexes = OneOrMore<string | Field | Sort | Record<string, 1 | -1>>;\n\nexport class MongoProvider {\n protected static readonly clients: { [key: string]: MongoClient } = {};\n\n constructor(readonly coll: Collection) {}\n\n async cluster(): Promise<MongoClient> {\n const db = this.coll.db;\n const c = await when(db.options?.cluster).not.isDefined.reject(Exception.IsNotValid.because('Missing cluster in database options.'));\n return MongoProvider.clients[c] ?? (MongoProvider.clients[c] = await MongoProvider.connect(c, db));\n }\n\n collection<T extends Document = Document>(): Promise<MongoCollection<T>> {\n return this.cluster()\n .then(c => c.db(this.coll.db.name))\n .then(db => db.collection<T>(asString(this.coll)));\n }\n\n private static connect(u: string, db: Database) {\n return MongoClient.connect(u, {\n auth: {\n username: asString(db.options?.user),\n password: asString(db.options?.password),\n },\n ...(db.options?.maxPoolSize && { maxPoolSize: db.options?.maxPoolSize }),\n ...(db.options?.minPoolSize && { minPoolSize: db.options?.minPoolSize }),\n ...(db.options?.maxIdleTimeMS && { maxIdleTimeMS: db.options?.maxIdleTimeMS }),\n }).then(c => {\n c.on('error', () => delete MongoProvider.clients[u]);\n c.on('close', () => delete MongoProvider.clients[u]);\n return c;\n });\n }\n\n static disconnect() {\n Object.values(MongoProvider.clients).forEach(c => void c.close());\n }\n\n toMongoJson(query: Query): Json {\n return toMongoType(asJson(query));\n }\n\n find(query: Query, options?: FindOptions): Promise<PageList<Json>> {\n return tuple3(this.collection(), this.toMongoJson(query), this.toFindOptions(options))\n .then(([c, q, o]) =>\n tuple2(\n c.find(q, o),\n ifTrue(o.total, () => c.countDocuments(q))\n )\n )\n .then(([res, total]) => this.toArray(res, { ...options, total }));\n }\n\n all(options?: FindOptions): Promise<PageList<Json>> {\n return this.find({}, options);\n }\n\n byId(id: Id, options?: FindOptions): Promise<Json> {\n return this.collection().then(c => c.findOne(this.toMongoJson({ id: id }), this.toFindOptions(options)) as Promise<Json>);\n }\n\n by(key: string, value: JsonValue, options?: FindOptions): Promise<PageList<Json>> {\n return this.find({ [key]: value }, options);\n }\n\n group(qs: Filter<any>[]): Promise<PageList<Json>> {\n return this.aggregate(qs);\n }\n\n aggregate(qs: Filter<any>[]): Promise<PageList<Json>> {\n return this.collection()\n .then(c => c.aggregate(qs.map(q => this.toMongoJson(q))))\n .then(res => this.toArray(res));\n }\n\n add(item: Json): Promise<Json> {\n return this.collection()\n .then(c => c.insertOne(omitId(item)))\n .then(() => omitId(item));\n }\n\n update(item: Json): Promise<Json> {\n return this.collection()\n .then(c => c.updateOne(this.toMongoJson({ id: item.id }), { $set: omitId(item) }))\n .then(() => this.byId(item.id as Id));\n }\n\n remove(id: Id): Promise<boolean> {\n return this.collection()\n .then(c => c.deleteOne(this.toMongoJson({ id })))\n .then(d => d.acknowledged);\n }\n\n count(query?: Query): Promise<number> {\n return this.collection().then(c => c.countDocuments(this.toMongoJson(query ?? {})));\n }\n\n createIndex(indexes: Indexes, options?: IndexOptions): Promise<string> {\n return this.collection().then(c => c.createIndex(this.toIndexSpecification(indexes), this.toCreateIndexesOptions(options)));\n }\n\n createPartialIndex(indexes: Indexes, filter: Query, options?: Omit<IndexOptions, 'filter'>): Promise<string> {\n return this.createIndex(indexes, { ...options, filter });\n }\n\n createTextIndex(indexes: OneOrMore<Field | string>, options?: IndexOptions): Promise<string> {\n const ii = toArray(indexes).reduce((i, f) => ({ ...i, [asString(f)]: 'text' }), {});\n return this.createIndex(ii, { unique: false, ...options });\n }\n\n protected toFindOptions(options?: FindOptions): MongoFindOptions & { total: boolean } {\n return {\n limit: asNumber(options?.take ?? 250),\n ...(options?.skip && { skip: asNumber(options?.skip) }),\n ...((options?.sorts && { sort: options?.sorts }) || (options?.sort && { sort: this.coll.sort(...(options?.sort ?? [])) })),\n total: isDefined(options?.skip) || isDefined(options?.take),\n projection: options?.projection ?? { _id: 0 },\n };\n }\n\n protected toIndexSpecification(index: Indexes): IndexSpecification {\n return choose(index)\n .type(isField, f => f.property as IndexSpecification)\n .type(isSortCondition, s => s.toJSON() as IndexSpecification)\n .type(isArray, aa => aa.map(a => this.toIndexSpecification(a)) as IndexSpecification)\n .else(i => i as IndexSpecification);\n }\n\n protected toCreateIndexesOptions(options?: IndexOptions): CreateIndexesOptions {\n return {\n unique: options?.unique ?? true,\n ...(options?.languageOverride && { language_override: options.languageOverride }),\n ...(options?.languageDefault && { default_language: options.languageDefault }),\n ...(options?.filter && { partialFilterExpression: toMongoType(asJson(options.filter)) }),\n };\n }\n\n protected toArray(\n cursor: FindCursor<Document> | AggregationCursor<Document>,\n options?: { take?: number; skip?: number; total?: number }\n ): Promise<PageList<Json>> {\n return cursor.toArray().then(r => toPageList<Json>(r, options));\n }\n}\n"],"mappings":"AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAGA;AAAA,EAIA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAOA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EAQE;AAAA,OAEK;AAEP,SAAS,mBAAmB;AAE5B,MAAM,SAAS,CAAC,MAAkB,KAAK,OAAO,GAAG,KAAK;AAgB/C,MAAM,cAAc;AAAA,EAGzB,YAAqB,MAAkB;AAAlB;AAAA,EAAmB;AAAA,EAFxC,OAA0B,UAA0C,CAAC;AAAA,EAIrE,MAAM,UAAgC;AACpC,UAAM,KAAK,KAAK,KAAK;AACrB,UAAM,IAAI,MAAM,KAAK,GAAG,SAAS,OAAO,EAAE,IAAI,UAAU,OAAO,UAAU,WAAW,QAAQ,sCAAsC,CAAC;AACnI,WAAO,cAAc,QAAQ,CAAC,MAAM,cAAc,QAAQ,CAAC,IAAI,MAAM,cAAc,QAAQ,GAAG,EAAE;AAAA,EAClG;AAAA,EAEA,aAAyE;AACvE,WAAO,KAAK,QAAQ,EACjB,KAAK,OAAK,EAAE,GAAG,KAAK,KAAK,GAAG,IAAI,CAAC,EACjC,KAAK,QAAM,GAAG,WAAc,SAAS,KAAK,IAAI,CAAC,CAAC;AAAA,EACrD;AAAA,EAEA,OAAe,QAAQ,GAAW,IAAc;AAC9C,WAAO,YAAY,QAAQ,GAAG;AAAA,MAC5B,MAAM;AAAA,QACJ,UAAU,SAAS,GAAG,SAAS,IAAI;AAAA,QACnC,UAAU,SAAS,GAAG,SAAS,QAAQ;AAAA,MACzC;AAAA,MACA,GAAI,GAAG,SAAS,eAAe,EAAE,aAAa,GAAG,SAAS,YAAY;AAAA,MACtE,GAAI,GAAG,SAAS,eAAe,EAAE,aAAa,GAAG,SAAS,YAAY;AAAA,MACtE,GAAI,GAAG,SAAS,iBAAiB,EAAE,eAAe,GAAG,SAAS,cAAc;AAAA,IAC9E,CAAC,EAAE,KAAK,OAAK;AACX,QAAE,GAAG,SAAS,MAAM,OAAO,cAAc,QAAQ,CAAC,CAAC;AACnD,QAAE,GAAG,SAAS,MAAM,OAAO,cAAc,QAAQ,CAAC,CAAC;AACnD,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA,EAEA,OAAO,aAAa;AAClB,WAAO,OAAO,cAAc,OAAO,EAAE,QAAQ,OAAK,KAAK,EAAE,MAAM,CAAC;AAAA,EAClE;AAAA,EAEA,YAAY,OAAoB;AAC9B,WAAO,YAAY,OAAO,KAAK,CAAC;AAAA,EAClC;AAAA,EAEA,KAAK,OAAc,SAAgD;AACjE,WAAO,OAAO,KAAK,WAAW,GAAG,KAAK,YAAY,KAAK,GAAG,KAAK,cAAc,OAAO,CAAC,EAClF;AAAA,MAAK,CAAC,CAAC,GAAG,GAAG,CAAC,MACb;AAAA,QACE,EAAE,KAAK,GAAG,CAAC;AAAA,QACX,OAAO,EAAE,OAAO,MAAM,EAAE,eAAe,CAAC,CAAC;AAAA,MAC3C;AAAA,IACF,EACC,KAAK,CAAC,CAAC,KAAK,KAAK,MAAM,KAAK,QAAQ,KAAK,EAAE,GAAG,SAAS,MAAM,CAAC,CAAC;AAAA,EACpE;AAAA,EAEA,IAAI,SAAgD;AAClD,WAAO,KAAK,KAAK,CAAC,GAAG,OAAO;AAAA,EAC9B;AAAA,EAEA,KAAK,IAAQ,SAAsC;AACjD,WAAO,KAAK,WAAW,EAAE,KAAK,OAAK,EAAE,QAAQ,KAAK,YAAY,EAAE,GAAO,CAAC,GAAG,KAAK,cAAc,OAAO,CAAC,CAAkB;AAAA,EAC1H;AAAA,EAEA,GAAG,KAAa,OAAkB,SAAgD;AAChF,WAAO,KAAK,KAAK,EAAE,CAAC,GAAG,GAAG,MAAM,GAAG,OAAO;AAAA,EAC5C;AAAA,EAEA,MAAM,IAA4C;AAChD,WAAO,KAAK,UAAU,EAAE;AAAA,EAC1B;AAAA,EAEA,UAAU,IAA4C;AACpD,WAAO,KAAK,WAAW,EACpB,KAAK,OAAK,EAAE,UAAU,GAAG,IAAI,OAAK,KAAK,YAAY,CAAC,CAAC,CAAC,CAAC,EACvD,KAAK,SAAO,KAAK,QAAQ,GAAG,CAAC;AAAA,EAClC;AAAA,EAEA,IAAI,MAA2B;AAC7B,WAAO,KAAK,WAAW,EACpB,KAAK,OAAK,EAAE,UAAU,OAAO,IAAI,CAAC,CAAC,EACnC,KAAK,MAAM,OAAO,IAAI,CAAC;AAAA,EAC5B;AAAA,EAEA,OAAO,MAA2B;AAChC,WAAO,KAAK,WAAW,EACpB,KAAK,OAAK,EAAE,UAAU,KAAK,YAAY,EAAE,IAAI,KAAK,GAAG,CAAC,GAAG,EAAE,MAAM,OAAO,IAAI,EAAE,CAAC,CAAC,EAChF,KAAK,MAAM,KAAK,KAAK,KAAK,EAAQ,CAAC;AAAA,EACxC;AAAA,EAEA,OAAO,IAA0B;AAC/B,WAAO,KAAK,WAAW,EACpB,KAAK,OAAK,EAAE,UAAU,KAAK,YAAY,EAAE,GAAG,CAAC,CAAC,CAAC,EAC/C,KAAK,OAAK,EAAE,YAAY;AAAA,EAC7B;AAAA,EAEA,MAAM,OAAgC;AACpC,WAAO,KAAK,WAAW,EAAE,KAAK,OAAK,EAAE,eAAe,KAAK,YAAY,SAAS,CAAC,CAAC,CAAC,CAAC;AAAA,EACpF;AAAA,EAEA,YAAY,SAAkB,SAAyC;AACrE,WAAO,KAAK,WAAW,EAAE,KAAK,OAAK,EAAE,YAAY,KAAK,qBAAqB,OAAO,GAAG,KAAK,uBAAuB,OAAO,CAAC,CAAC;AAAA,EAC5H;AAAA,EAEA,mBAAmB,SAAkB,QAAe,SAAyD;AAC3G,WAAO,KAAK,YAAY,SAAS,EAAE,GAAG,SAAS,OAAO,CAAC;AAAA,EACzD;AAAA,EAEA,gBAAgB,SAAoC,SAAyC;AAC3F,UAAM,KAAK,QAAQ,OAAO,EAAE,OAAO,CAAC,GAAG,OAAO,EAAE,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC;AAClF,WAAO,KAAK,YAAY,IAAI,EAAE,QAAQ,OAAO,GAAG,QAAQ,CAAC;AAAA,EAC3D;AAAA,EAEU,cAAc,SAA8D;AACpF,WAAO;AAAA,MACL,OAAO,SAAS,SAAS,QAAQ,GAAG;AAAA,MACpC,GAAI,SAAS,QAAQ,EAAE,MAAM,SAAS,SAAS,IAAI,EAAE;AAAA,MACrD,GAAK,SAAS,SAAS,EAAE,MAAM,SAAS,MAAM,KAAO,SAAS,QAAQ,EAAE,MAAM,KAAK,KAAK,KAAK,GAAI,SAAS,QAAQ,CAAC,CAAE,EAAE;AAAA,MACvH,OAAO,UAAU,SAAS,IAAI,KAAK,UAAU,SAAS,IAAI;AAAA,MAC1D,YAAY,SAAS,cAAc,EAAE,KAAK,EAAE;AAAA,IAC9C;AAAA,EACF;AAAA,EAEU,qBAAqB,OAAoC;AACjE,WAAO,OAAO,KAAK,EAChB,KAAK,SAAS,OAAK,EAAE,QAA8B,EACnD,KAAK,iBAAiB,OAAK,EAAE,OAAO,CAAuB,EAC3D,KAAK,SAAS,QAAM,GAAG,IAAI,OAAK,KAAK,qBAAqB,CAAC,CAAC,CAAuB,EACnF,KAAK,OAAK,CAAuB;AAAA,EACtC;AAAA,EAEU,uBAAuB,SAA8C;AAC7E,WAAO;AAAA,MACL,QAAQ,SAAS,UAAU;AAAA,MAC3B,GAAI,SAAS,oBAAoB,EAAE,mBAAmB,QAAQ,iBAAiB;AAAA,MAC/E,GAAI,SAAS,mBAAmB,EAAE,kBAAkB,QAAQ,gBAAgB;AAAA,MAC5E,GAAI,SAAS,UAAU,EAAE,yBAAyB,YAAY,OAAO,QAAQ,MAAM,CAAC,EAAE;AAAA,IACxF;AAAA,EACF;AAAA,EAEU,QACR,QACA,SACyB;AACzB,WAAO,OAAO,QAAQ,EAAE,KAAK,OAAK,WAAiB,GAAG,OAAO,CAAC;AAAA,EAChE;AACF;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thisisagile/easy-mongo",
3
- "version": "15.23.6",
3
+ "version": "15.24.0",
4
4
  "description": "Add support for MongoDB",
5
5
  "author": "Sander Hoogendoorn",
6
6
  "license": "MIT",
@@ -33,10 +33,10 @@
33
33
  "access": "public"
34
34
  },
35
35
  "devDependencies": {
36
- "@thisisagile/easy-test": "15.23.6"
36
+ "@thisisagile/easy-test": "15.24.0"
37
37
  },
38
38
  "dependencies": {
39
- "@thisisagile/easy": "^15.23.6",
39
+ "@thisisagile/easy": "^15.24.0",
40
40
  "mongodb": "^5.6.0"
41
41
  }
42
42
  }
@@ -20,7 +20,6 @@ import {
20
20
  LogicalCondition,
21
21
  OneOrMore,
22
22
  PageList,
23
- reject,
24
23
  Sort,
25
24
  toArray,
26
25
  toPageList,
@@ -59,36 +58,40 @@ export type IndexOptions = {
59
58
  export type Indexes = OneOrMore<string | Field | Sort | Record<string, 1 | -1>>;
60
59
 
61
60
  export class MongoProvider {
62
- protected static readonly clients: { [key: string]: Promise<MongoClient> } = {};
63
-
64
- constructor(readonly coll: Collection, protected client?: Promise<MongoClient>) {}
65
-
66
- static client(db: Database): Promise<MongoClient> {
67
- return when(db.options?.cluster)
68
- .not.isDefined.reject(Exception.IsNotValid.because('Missing cluster in database options.'))
69
- .then(
70
- u =>
71
- (MongoProvider.clients[u] =
72
- MongoProvider.clients[u] ??
73
- MongoClient.connect(u, {
74
- auth: {
75
- username: asString(db.options?.user),
76
- password: asString(db.options?.password),
77
- },
78
- ...(db.options?.maxPoolSize && { maxPoolSize: db.options?.maxPoolSize }),
79
- ...(db.options?.minPoolSize && { minPoolSize: db.options?.minPoolSize }),
80
- ...(db.options?.maxIdleTimeMS && { maxIdleTimeMS: db.options?.maxIdleTimeMS }),
81
- }))
82
- );
83
- }
84
-
85
- cluster(): Promise<MongoClient> {
86
- return Promise.resolve()
87
- .then(() => this.client ?? (this.client = MongoProvider.client(this.coll.db)))
88
- .catch(e => {
89
- this.client = undefined;
90
- return reject(e);
91
- });
61
+ protected static readonly clients: { [key: string]: MongoClient } = {};
62
+
63
+ constructor(readonly coll: Collection) {}
64
+
65
+ async cluster(): Promise<MongoClient> {
66
+ const db = this.coll.db;
67
+ const c = await when(db.options?.cluster).not.isDefined.reject(Exception.IsNotValid.because('Missing cluster in database options.'));
68
+ return MongoProvider.clients[c] ?? (MongoProvider.clients[c] = await MongoProvider.connect(c, db));
69
+ }
70
+
71
+ collection<T extends Document = Document>(): Promise<MongoCollection<T>> {
72
+ return this.cluster()
73
+ .then(c => c.db(this.coll.db.name))
74
+ .then(db => db.collection<T>(asString(this.coll)));
75
+ }
76
+
77
+ private static connect(u: string, db: Database) {
78
+ return MongoClient.connect(u, {
79
+ auth: {
80
+ username: asString(db.options?.user),
81
+ password: asString(db.options?.password),
82
+ },
83
+ ...(db.options?.maxPoolSize && { maxPoolSize: db.options?.maxPoolSize }),
84
+ ...(db.options?.minPoolSize && { minPoolSize: db.options?.minPoolSize }),
85
+ ...(db.options?.maxIdleTimeMS && { maxIdleTimeMS: db.options?.maxIdleTimeMS }),
86
+ }).then(c => {
87
+ c.on('error', () => delete MongoProvider.clients[u]);
88
+ c.on('close', () => delete MongoProvider.clients[u]);
89
+ return c;
90
+ });
91
+ }
92
+
93
+ static disconnect() {
94
+ Object.values(MongoProvider.clients).forEach(c => void c.close());
92
95
  }
93
96
 
94
97
  toMongoJson(query: Query): Json {
@@ -163,12 +166,6 @@ export class MongoProvider {
163
166
  return this.createIndex(ii, { unique: false, ...options });
164
167
  }
165
168
 
166
- collection<T extends Document = Document>(): Promise<MongoCollection<T>> {
167
- return this.cluster()
168
- .then(c => c.db(this.coll.db.name))
169
- .then(db => db.collection<T>(asString(this.coll)));
170
- }
171
-
172
169
  protected toFindOptions(options?: FindOptions): MongoFindOptions & { total: boolean } {
173
170
  return {
174
171
  limit: asNumber(options?.take ?? 250),