UNPKG

@thisisagile/easy-mongo

Version:
1 lines 12.3 kB
{"version":3,"sources":["../src/MongoProvider.ts"],"sourcesContent":["import {\n asJson,\n asNumber,\n asString,\n choose,\n Condition,\n Database,\n entries,\n Exception,\n FetchOptions,\n Field,\n Id,\n ifDefined,\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 use,\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 type Options = { maxTimeMS?: number };\n\nexport class MongoProvider {\n protected static readonly clients: { [key: string]: Promise<MongoClient> } = {};\n\n constructor(readonly coll: Collection) {}\n\n static destroyAll(): Promise<void> {\n return Promise.all(entries(MongoProvider.clients).map(([u, c]) => c.then(c => c.close()).then(() => delete MongoProvider.clients[u]))).then(\n () => undefined\n );\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 })\n .then(c => {\n c.on('error', () => delete MongoProvider.clients[u]);\n c.on('close', () => delete MongoProvider.clients[u]);\n return c;\n })\n .catch(err => {\n delete MongoProvider.clients[u];\n return Promise.reject(err);\n });\n }\n\n cluster(): Promise<MongoClient> {\n return use(this.coll.db, db =>\n when(db.options?.cluster)\n .not.isDefined.reject(Exception.IsNotValid.because('Missing cluster in database options.'))\n .then(c => MongoProvider.clients[c] ?? (MongoProvider.clients[c] = MongoProvider.connect(c, db)))\n );\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 toMongoJson(query: Query): Json {\n return toMongoType(asJson(query));\n }\n\n find(query: Query, options?: FindOptions & Options): Promise<PageList<Json>> {\n const { maxTimeMS, ...opts } = options ?? {};\n return tuple3(this.collection(), this.toMongoJson(query), this.toFindOptions(opts))\n .then(([c, q, o]) =>\n tuple2(\n c.find(q, { ...o, ...ifDefined(maxTimeMS, { maxTimeMS }, {}) }),\n ifTrue(o.total, () =>\n ifDefined(\n maxTimeMS,\n maxTimeMS => c.countDocuments(q, { maxTimeMS }),\n () => c.countDocuments(q)\n )\n )\n )\n )\n .then(([res, total]) => this.toArray(res, { ...opts, 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>[], options?: Options): Promise<PageList<Json>> {\n return this.aggregate(qs, options);\n }\n\n aggregate(qs: Filter<any>[], options?: Options): Promise<PageList<Json>> {\n return this.collection()\n .then(c =>\n c.aggregate(\n qs.map(q => this.toMongoJson(q)),\n options\n )\n )\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, options?: Options): Promise<number> {\n return this.collection().then(c => c.countDocuments(this.toMongoJson(query ?? {}), options));\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":"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","names":["c","maxTimeMS"]}