liwi-mongo 13.3.3 → 13.4.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.
@@ -6,14 +6,20 @@ export interface MongoConfig {
6
6
  database: string;
7
7
  user?: string;
8
8
  password?: string;
9
+ authSource?: string;
9
10
  }
11
+ interface BuildMongoConnectionStringParams extends MongoConfig {
12
+ redactCredentials: boolean;
13
+ }
14
+ export declare const buildMongoConnectionString: ({ host, port, database, user, password, authSource, redactCredentials, }: BuildMongoConnectionStringParams) => string;
10
15
  export default class MongoConnection extends AbstractConnection {
11
16
  _connection?: mongodb.MongoClient;
12
17
  _connecting?: Promise<mongodb.MongoClient>;
13
18
  connectionFailed?: boolean;
14
- constructor({ host, port, database, user, password, }: MongoConfig);
19
+ constructor(config: MongoConfig);
15
20
  connect(connectionString: string, connectionStringRedacted: string): void;
16
21
  getConnection(): Promise<mongodb.MongoClient>;
17
22
  close(): Promise<void>;
18
23
  }
24
+ export {};
19
25
  //# sourceMappingURL=MongoConnection.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"MongoConnection.d.ts","sourceRoot":"","sources":["../../src/MongoConnection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,OAAO,MAAM,SAAS,CAAC;AAK9B,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,CAAC,OAAO,OAAO,eAAgB,SAAQ,kBAAkB;IAC7D,WAAW,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC;IAElC,WAAW,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAE3C,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAG3B,YAAY,EACV,IAAkB,EAClB,IAAc,EACd,QAAQ,EACR,IAAI,EACJ,QAAQ,GACT,EAAE,WAAW,EA0Bb;IAED,OAAO,CAAC,gBAAgB,EAAE,MAAM,EAAE,wBAAwB,EAAE,MAAM,GAAG,IAAI,CAgDxE;IAED,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAE5C;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAS3B;CACF"}
1
+ {"version":3,"file":"MongoConnection.d.ts","sourceRoot":"","sources":["../../src/MongoConnection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,OAAO,MAAM,SAAS,CAAC;AAK9B,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,UAAU,gCAAiC,SAAQ,WAAW;IAC5D,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAED,eAAO,MAAM,0BAA0B,6EAQpC,gCAAgC,KAAG,MAalC,CAAC;AAEL,MAAM,CAAC,OAAO,OAAO,eAAgB,SAAQ,kBAAkB;IAC7D,WAAW,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC;IAElC,WAAW,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAE3C,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAG3B,YAAY,MAAM,EAAE,WAAW,EAiB9B;IAED,OAAO,CAAC,gBAAgB,EAAE,MAAM,EAAE,wBAAwB,EAAE,MAAM,GAAG,IAAI,CAgDxE;IAED,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAE5C;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAS3B;CACF"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=MongoConnection.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MongoConnection.test.d.ts","sourceRoot":"","sources":["../../src/MongoConnection.test.ts"],"names":[],"mappings":""}
@@ -1,7 +1,7 @@
1
1
  import mongodb from 'mongodb';
2
2
  import { AbstractStoreCursor, AbstractConnection } from 'liwi-store';
3
3
  import { AbstractSubscribableStoreQuery, SubscribeStore } from 'liwi-subscribe-store';
4
- import mingo from 'mingo';
4
+ import { Query } from 'mingo';
5
5
  import { Logger } from 'nightingale-logger';
6
6
 
7
7
  class MongoCursor extends AbstractStoreCursor {
@@ -66,7 +66,7 @@ class MongoQueryCollection extends AbstractSubscribableStoreQuery {
66
66
  if ("$text" in this.options.criteria) {
67
67
  return () => false;
68
68
  }
69
- const mingoQuery = new mingo.Query(this.options.criteria);
69
+ const mingoQuery = new Query(this.options.criteria);
70
70
  this.testCriteria = mingoQuery.test.bind(mingoQuery);
71
71
  }
72
72
  return this.testCriteria;
@@ -195,7 +195,7 @@ class MongoQuerySingleItem extends AbstractSubscribableStoreQuery {
195
195
  if (!this.options.criteria) {
196
196
  return () => true;
197
197
  }
198
- const mingoQuery = new mingo.Query(this.options.criteria);
198
+ const mingoQuery = new Query(this.options.criteria);
199
199
  this.testCriteria = mingoQuery.test.bind(mingoQuery);
200
200
  }
201
201
  return this.testCriteria;
@@ -920,25 +920,33 @@ class MongoStore {
920
920
  }
921
921
 
922
922
  const logger$1 = new Logger("liwi:mongo:MongoConnection");
923
+ const buildMongoConnectionString = ({
924
+ host = "localhost",
925
+ port = "27017",
926
+ database,
927
+ user,
928
+ password,
929
+ authSource,
930
+ redactCredentials
931
+ }) => `mongodb://${user ? `${redactCredentials ? `${user.slice(0, 2)}[redacted]` : encodeURIComponent(user)}:${redactCredentials ? "[redacted]" : encodeURIComponent(password ?? "")}@` : ""}${host}:${port}/${encodeURIComponent(database)}${authSource ? `?authSource=${encodeURIComponent(authSource)}` : ""}`;
923
932
  class MongoConnection extends AbstractConnection {
924
933
  _connection;
925
934
  _connecting;
926
935
  connectionFailed;
927
936
  // TODO interface
928
- constructor({
929
- host = "localhost",
930
- port = "27017",
931
- database,
932
- user,
933
- password
934
- }) {
937
+ constructor(config) {
935
938
  super();
936
- if (!database) {
939
+ if (!config.database) {
937
940
  throw new Error("Missing config database");
938
941
  }
939
- const buildConnectionString = (redactCredentials) => `mongodb://${user ? `${redactCredentials ? `${user.slice(0, 2)}[redacted]` : encodeURIComponent(user)}:${redactCredentials ? "[redacted]" : encodeURIComponent(password ?? "")}@` : ""}${host}:${port}/${encodeURIComponent(database)}`;
940
- const connectionString = buildConnectionString(false);
941
- const connectionStringRedacted = buildConnectionString(true);
942
+ const connectionString = buildMongoConnectionString({
943
+ ...config,
944
+ redactCredentials: false
945
+ });
946
+ const connectionStringRedacted = buildMongoConnectionString({
947
+ ...config,
948
+ redactCredentials: true
949
+ });
942
950
  this.connect(connectionString, connectionStringRedacted);
943
951
  }
944
952
  connect(connectionString, connectionStringRedacted) {
@@ -1 +1 @@
1
- {"version":3,"file":"index-node.mjs","sources":["../src/MongoCursor.ts","../src/MongoQueryCollection.ts","../src/MongoQuerySingleItem.ts","../src/indexes/isIndexConflictError.ts","../src/indexes/applyIndexPlan.ts","../src/indexes/deepEqualUnordered.ts","../src/indexes/buildIndexName.ts","../src/indexes/normalizeIndex.ts","../src/indexes/diffIndexes.ts","../src/MongoStore.ts","../src/MongoConnection.ts","../src/createMongoSubscribeStore.ts","../src/MongoRegistry.ts","../src/indexes/formatIndexPlan.ts","../src/indexes/runIndexesCli.ts"],"sourcesContent":["import { AbstractStoreCursor } from \"liwi-store\";\nimport type { AllowedKeyValue } from \"liwi-store\";\nimport type { FindCursor } from \"mongodb\";\nimport type { MongoBaseModel } from \"./MongoBaseModel\";\nimport type MongoStore from \"./MongoStore\";\n\nexport default class MongoCursor<\n Model extends MongoBaseModel<KeyValue>,\n Result extends Partial<Model> = Model,\n KeyValue extends AllowedKeyValue = Model[\"_id\"],\n> extends AbstractStoreCursor<\n MongoStore<Model, KeyValue>,\n KeyValue,\n Model,\n Result\n> {\n // key in AbstractCursor\n\n private readonly cursor: FindCursor<Result>;\n\n private _result?: Result | null;\n\n constructor(store: MongoStore<Model, KeyValue>, cursor: FindCursor<Result>) {\n super(store);\n this.cursor = cursor;\n }\n\n advance(count: number): void {\n this.cursor.skip(count);\n }\n\n next(): Promise<KeyValue | undefined> {\n return this.cursor.next().then((value) => {\n this._result = value;\n this.key = value?._id;\n return this.key;\n });\n }\n\n override async forEach(\n callback: (result: Result) => Promise<void> | void,\n ): Promise<void> {\n for await (const result of this.cursor) {\n await callback(result);\n }\n }\n\n limit(newLimit: number): Promise<this> {\n this.cursor.limit(newLimit);\n return Promise.resolve(this);\n }\n\n override result(): Promise<Result> {\n if (!this._result) throw new Error(\"Cannot call result() before next()\");\n return Promise.resolve(this._result);\n }\n\n close(): Promise<void> {\n if (this.cursor) {\n this.cursor.close();\n }\n\n return Promise.resolve();\n }\n\n toArray(): Promise<Result[]> {\n return this.cursor.toArray();\n }\n}\n","/* eslint-disable complexity */\nimport type {\n AllowedKeyValue,\n Changes,\n QueryOptions,\n QueryParams,\n QueryResult,\n QuerySubscription,\n SubscribeCallback,\n Transformer,\n} from \"liwi-store\";\nimport type { Actions } from \"liwi-subscribe-store\";\nimport { AbstractSubscribableStoreQuery } from \"liwi-subscribe-store\";\nimport mingo from \"mingo\";\nimport type {\n MongoBaseModel,\n MongoInsertType,\n MongoKeyPath,\n} from \"./MongoBaseModel\";\nimport type MongoCursor from \"./MongoCursor\";\nimport type MongoStore from \"./MongoStore\";\n\nconst identityTransformer = <\n Model extends MongoBaseModel<any>,\n Transformed = Model,\n>(\n model: Model,\n): Transformed => model as unknown as Transformed;\n\ntype TestCriteria = (obj: any) => boolean;\n\nexport default class MongoQueryCollection<\n Model extends MongoBaseModel<KeyValue>,\n Params extends QueryParams<Params> = never,\n KeyValue extends AllowedKeyValue = Model[\"_id\"],\n Item extends Record<MongoKeyPath, KeyValue> = Model,\n> extends AbstractSubscribableStoreQuery<\n MongoKeyPath,\n KeyValue,\n Model,\n MongoInsertType<Model, KeyValue>,\n Params,\n Item[]\n> {\n private readonly store: MongoStore<Model, KeyValue>;\n\n private readonly options: QueryOptions<Model>;\n\n private testCriteria?: TestCriteria;\n\n private readonly transformer: Transformer<Model, Item>;\n\n constructor(\n store: MongoStore<Model, KeyValue>,\n options: QueryOptions<Model>,\n transformer: Transformer<Model, Item> = identityTransformer,\n ) {\n super();\n this.store = store;\n this.options = options;\n this.transformer = transformer;\n }\n\n createTestCriteria(): TestCriteria {\n if (!this.testCriteria) {\n if (!this.options.criteria) {\n return () => true;\n }\n\n // criteria not supported by mingo: updates will not work\n if (\"$text\" in this.options.criteria) {\n return () => false;\n }\n\n const mingoQuery = new mingo.Query(this.options.criteria);\n this.testCriteria = mingoQuery.test.bind(mingoQuery);\n }\n return this.testCriteria;\n }\n\n async fetch<T>(onFulfilled: (result: QueryResult<Item[]>) => T): Promise<T> {\n const [result, count] = await Promise.all([\n this.createMongoCursor().then((cursor) => cursor.toArray()),\n this.store.count(this.options.criteria),\n ]);\n\n return onFulfilled({\n result: result.map(this.transformer),\n meta: { total: count },\n info: {\n sort: this.options.sort,\n limit: this.options.limit,\n keyPath: this.store.keyPath,\n },\n });\n }\n\n _subscribe(\n callback: SubscribeCallback<KeyValue, Item[]>,\n _includeInitial: boolean,\n ): QuerySubscription {\n const store = super.getSubscribeStore();\n const testCriteria: TestCriteria = this.createTestCriteria();\n\n const promise: Promise<void> = _includeInitial\n ? this.fetch(({ result, meta, info }: QueryResult<Item[]>) => {\n callback(null, [\n {\n type: \"initial\",\n initial: result,\n queryInfo: info,\n meta,\n },\n ]);\n })\n : Promise.resolve();\n\n const unsubscribe = store.subscribe((action: Actions<Model>) => {\n const changes: Changes<KeyValue, Item[]> = [];\n switch (action.type) {\n case \"inserted\": {\n const filtered = action.next.filter(testCriteria);\n if (filtered.length > 0) {\n changes.push({\n type: \"inserted\",\n result: filtered.map(this.transformer),\n });\n }\n break;\n }\n case \"deleted\": {\n const filtered = action.prev.filter(testCriteria);\n if (filtered.length > 0) {\n changes.push({\n type: \"deleted\",\n keys: filtered.map((object) => object[this.store.keyPath]),\n });\n }\n break;\n }\n case \"updated\": {\n const {\n deleted,\n updated,\n inserted,\n }: {\n deleted: KeyValue[];\n updated: Item[];\n inserted: Item[];\n } = { deleted: [], updated: [], inserted: [] };\n\n action.changes.forEach(([prevObject, nextObject]: [Model, Model]) => {\n if (testCriteria(prevObject)) {\n if (!testCriteria(nextObject)) {\n deleted.push(prevObject[this.store.keyPath]);\n } else {\n updated.push(this.transformer(nextObject));\n }\n } else if (testCriteria(nextObject)) {\n inserted.push(this.transformer(nextObject));\n }\n });\n\n if (deleted.length > 0) {\n changes.push({ type: \"deleted\", keys: deleted });\n }\n if (updated.length > 0) {\n changes.push({ type: \"updated\", result: updated });\n }\n if (inserted.length > 0) {\n changes.push({ type: \"inserted\", result: inserted });\n }\n\n break;\n }\n default:\n throw new Error(\"Unsupported type\");\n }\n\n if (changes.length === 0) return;\n\n callback(null, changes);\n });\n // let _feed;\n // const promise = this.queryCallback(this.store.query(), this.store.r)\n // .changes({\n // includeInitial: _includeInitial,\n // includeStates: true,\n // includeTypes: true,\n // includeOffsets: true,\n // })\n // .then((feed) => {\n // if (args.length === 0) {\n // _feed = feed;\n // delete this._promise;\n // }\n //\n // feed.each(callback);\n // return feed;\n // });\n //\n // if (args.length === 0) this._promise = promise;\n\n return {\n stop: unsubscribe,\n cancel: unsubscribe,\n then: <T, U>(\n onFulfilled: () => Promise<T> | T,\n onRejected?: (error: any) => Promise<U> | U,\n ): Promise<T | U> => promise.then(onFulfilled, onRejected),\n };\n }\n\n private async createMongoCursor(): Promise<\n MongoCursor<Model, Model, KeyValue>\n > {\n const cursor = await this.store.cursor(\n this.options.criteria,\n this.options.sort,\n this.options.fields,\n );\n\n if (this.options.skip) {\n cursor.advance(this.options.skip);\n }\n\n if (this.options.limit) {\n await cursor.limit(this.options.limit);\n }\n\n return cursor;\n }\n}\n","import type {\n AllowedKeyValue,\n Changes,\n QueryOptions,\n QueryParams,\n QueryResult,\n QuerySubscription,\n SubscribeCallback,\n Transformer,\n} from \"liwi-store\";\nimport type { Actions } from \"liwi-subscribe-store\";\nimport { AbstractSubscribableStoreQuery } from \"liwi-subscribe-store\";\nimport mingo from \"mingo\";\nimport type {\n MongoBaseModel,\n MongoInsertType,\n MongoKeyPath,\n} from \"./MongoBaseModel\";\nimport type MongoCursor from \"./MongoCursor\";\nimport type MongoStore from \"./MongoStore\";\n\nconst identityTransformer = <\n Model extends MongoBaseModel<any>,\n Transformed = Model,\n>(\n model: Model,\n): Transformed => model as unknown as Transformed;\n\ntype TestCriteria = (obj: any) => boolean;\n\nexport default class MongoQuerySingleItem<\n Model extends MongoBaseModel<KeyValue>,\n Params extends QueryParams<Params> = never,\n Result extends Record<MongoKeyPath, KeyValue> | null = Model | null,\n KeyValue extends AllowedKeyValue = Model[\"_id\"],\n> extends AbstractSubscribableStoreQuery<\n MongoKeyPath,\n KeyValue,\n Model,\n MongoInsertType<Model, KeyValue>,\n Params,\n Result\n> {\n private readonly store: MongoStore<Model, KeyValue>;\n\n private readonly options: QueryOptions<Model>;\n\n private testCriteria?: TestCriteria;\n\n private readonly transformer: Transformer<Model, Result>;\n\n constructor(\n store: MongoStore<Model, KeyValue>,\n options: QueryOptions<Model>,\n transformer: Transformer<Model, Result> = identityTransformer,\n ) {\n super();\n this.store = store;\n this.options = options;\n this.transformer = transformer;\n }\n\n createMingoTestCriteria(): TestCriteria {\n if (!this.testCriteria) {\n if (!this.options.criteria) {\n return () => true;\n }\n\n const mingoQuery = new mingo.Query(this.options.criteria);\n this.testCriteria = mingoQuery.test.bind(mingoQuery);\n }\n\n return this.testCriteria;\n }\n\n async fetch<T>(onFulfilled: (result: QueryResult<Result>) => T): Promise<T> {\n const cursor = await this.createMongoCursor();\n await cursor.limit(1);\n return cursor.toArray().then((result: Model[]) => {\n const item: Result =\n result.length === 0 ? (null as Result) : this.transformer(result[0]!);\n return onFulfilled({\n result: item,\n meta: { total: result === null ? 0 : 1 },\n info: {\n limit: 1,\n keyPath: this.store.keyPath,\n },\n });\n });\n }\n\n _subscribe(\n callback: SubscribeCallback<KeyValue, Result>,\n _includeInitial: boolean,\n ): QuerySubscription {\n const store = super.getSubscribeStore();\n const testCriteria: TestCriteria = this.createMingoTestCriteria();\n\n const promise: Promise<void> = _includeInitial\n ? this.fetch(({ result, meta, info }: QueryResult<Result>) => {\n callback(null, [\n {\n type: \"initial\",\n initial: result,\n queryInfo: info,\n meta,\n },\n ]);\n })\n : Promise.resolve();\n\n const unsubscribe = store.subscribe(async (action: Actions<Model>) => {\n const changes: Changes<KeyValue, Result> = [];\n switch (action.type) {\n case \"inserted\": {\n const filtered = action.next.filter(testCriteria);\n if (filtered.length > 0) {\n changes.push({\n type: \"updated\",\n result: this.transformer(filtered[0]!),\n });\n }\n break;\n }\n case \"deleted\": {\n const filtered = action.prev.filter(testCriteria);\n if (filtered.length > 0) {\n changes.push({\n type: \"deleted\",\n keys: filtered.map((object) => object[this.store.keyPath]),\n });\n }\n break;\n }\n case \"updated\": {\n const filtered = action.changes.filter(([prev, next]) =>\n testCriteria(prev),\n );\n if (filtered.length > 0) {\n if (this.options.sort) {\n const { result } = await this.fetch((res) => res);\n changes.push({\n type: \"updated\",\n result,\n });\n } else if (filtered.length !== 1) {\n throw new Error(\n \"should not match more than 1, use sort if you can have multiple match\",\n );\n } else {\n const [, next] = filtered[0]!;\n changes.push({\n type: \"updated\",\n result: testCriteria(next) ? this.transformer(next) : null!,\n });\n }\n } else if (filtered.length === 0) {\n }\n break;\n }\n default:\n throw new Error(\"Unsupported type\");\n }\n\n if (changes.length === 0) return;\n\n callback(null, changes);\n });\n\n return {\n stop: unsubscribe,\n cancel: unsubscribe,\n then: <T, U>(\n onFulfilled: () => Promise<T> | T,\n onRejected?: (error: any) => Promise<U> | U,\n ): Promise<T | U> => promise.then(onFulfilled, onRejected),\n };\n }\n\n private async createMongoCursor(): Promise<\n MongoCursor<Model, Model, KeyValue>\n > {\n const cursor = await this.store.cursor(\n this.options.criteria,\n this.options.sort,\n this.options.fields,\n );\n\n if (this.options.limit) {\n await cursor.limit(this.options.limit);\n }\n\n return cursor;\n }\n}\n","const indexOptionsConflict = 85;\nconst indexKeySpecsConflict = 86;\nconst indexNotFound = 27;\nconst namespaceNotFound = 26;\n\nconst getErrorCode = (error: unknown): unknown =>\n typeof error === \"object\" && error !== null\n ? (error as { code?: unknown }).code\n : undefined;\n\nexport const isIndexConflictError = (error: unknown): boolean => {\n const code = getErrorCode(error);\n return code === indexOptionsConflict || code === indexKeySpecsConflict;\n};\n\nexport const isIndexNotFoundError = (error: unknown): boolean =>\n getErrorCode(error) === indexNotFound;\n\nexport const isNamespaceNotFoundError = (error: unknown): boolean =>\n getErrorCode(error) === namespaceNotFound;\n","import type {\n Collection,\n Db,\n IndexDescription,\n IndexDescriptionInfo,\n} from \"mongodb\";\nimport { Logger } from \"nightingale-logger\";\nimport {\n isIndexConflictError,\n isIndexNotFoundError,\n} from \"./isIndexConflictError.ts\";\nimport type { MongoIndexPlan, MongoIndexSyncResult } from \"./types.ts\";\n\nconst logger = new Logger(\"liwi:mongo:indexes\");\n\nconst idIndexName = \"_id_\";\n\nconst serializeKey = (key: IndexDescription[\"key\"]): string =>\n JSON.stringify(key instanceof Map ? [...key.entries()] : Object.entries(key));\n\nconst findConflictingIndex = (\n existingIndexes: readonly IndexDescriptionInfo[],\n description: IndexDescription,\n): IndexDescriptionInfo | undefined => {\n const byName = existingIndexes.find(({ name }) => name === description.name);\n if (byName) return byName;\n\n const serializedKey = serializeKey(description.key);\n return existingIndexes.find(\n ({ key, name }) =>\n name !== idIndexName && serializeKey(key) === serializedKey,\n );\n};\n\ninterface CreateIndexParams {\n collection: Collection<any>;\n collectionName: string;\n description: IndexDescription;\n}\n\nconst createIndexWithConflictRecovery = async ({\n collection,\n collectionName,\n description,\n}: CreateIndexParams): Promise<void> => {\n try {\n await collection.createIndexes([description]);\n return;\n } catch (error: unknown) {\n if (!isIndexConflictError(error)) throw error;\n\n logger.warn(\"index conflict, recovering\", {\n collectionName,\n name: description.name,\n error,\n });\n\n const existingIndexes = await collection.listIndexes().toArray();\n const conflicting = findConflictingIndex(existingIndexes, description);\n if (!conflicting?.name) throw error;\n\n await collection.dropIndex(conflicting.name);\n }\n\n await collection.createIndexes([description]);\n};\n\ninterface ApplyIndexPlanParams {\n plan: MongoIndexPlan;\n collection: Collection<any>;\n db: Db;\n dryRun: boolean;\n}\n\nexport const applyIndexPlan = async ({\n plan,\n collection,\n db,\n dryRun,\n}: ApplyIndexPlanParams): Promise<MongoIndexSyncResult> => {\n const { collectionName } = plan;\n const result: MongoIndexSyncResult = {\n collectionName,\n plan,\n dryRun,\n created: [],\n dropped: [],\n modified: [],\n };\n\n if (dryRun) return result;\n\n const namesToDrop = [...plan.toDrop, ...plan.toRecreate]\n .map(({ name }) => name)\n .filter((name) => name !== idIndexName);\n\n for (const name of namesToDrop) {\n try {\n await collection.dropIndex(name);\n logger.info(\"dropIndex\", { collectionName, name });\n result.dropped.push(name);\n } catch (error: unknown) {\n if (!isIndexNotFoundError(error)) throw error;\n logger.warn(\"index already dropped\", { collectionName, name });\n }\n }\n\n for (const { name, changes } of plan.toCollMod) {\n await db.command({\n collMod: collectionName,\n index: { name, ...changes },\n });\n logger.info(\"collMod\", { collectionName, name, changes });\n result.modified.push(name);\n }\n\n const descriptions = [...plan.toCreate, ...plan.toRecreate].map(\n ({ index }) => index,\n );\n\n if (descriptions.length > 0) {\n try {\n await collection.createIndexes(descriptions);\n } catch (error: unknown) {\n logger.warn(\"createIndexes failed, retrying one by one\", {\n collectionName,\n error,\n });\n for (const description of descriptions) {\n await createIndexWithConflictRecovery({\n collection,\n collectionName,\n description,\n });\n }\n }\n result.created.push(...descriptions.map(({ name }) => name!));\n logger.info(\"createIndexes\", { collectionName, names: result.created });\n }\n\n logger.info(\"syncIndexes done\", {\n collectionName,\n created: result.created,\n dropped: result.dropped,\n modified: result.modified,\n });\n\n return result;\n};\n","const isPlainRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" &&\n value !== null &&\n !Array.isArray(value) &&\n !(value instanceof Date) &&\n !(value instanceof RegExp);\n\nexport const deepEqualUnordered = (a: unknown, b: unknown): boolean => {\n if (a === b) return true;\n\n if (a instanceof Date && b instanceof Date) {\n return a.getTime() === b.getTime();\n }\n\n if (a instanceof RegExp && b instanceof RegExp) {\n return a.source === b.source && a.flags === b.flags;\n }\n\n if (Array.isArray(a) || Array.isArray(b)) {\n if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) {\n return false;\n }\n return a.every((item, index) => deepEqualUnordered(item, b[index]));\n }\n\n if (!isPlainRecord(a) || !isPlainRecord(b)) return false;\n\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n if (keysA.length !== keysB.length) return false;\n\n return keysA.every(\n (key) =>\n Object.hasOwn(b, key) && deepEqualUnordered(a[key], (b as any)[key]),\n );\n};\n","import type { MongoIndexDirection } from \"./types.ts\";\n\nexport const buildIndexName = (\n key: Record<string, MongoIndexDirection>,\n): string =>\n Object.entries(key)\n .map(([field, direction]) => `${field}_${direction}`)\n .join(\"_\");\n","import type {\n CollationOptions,\n Document,\n IndexDescription,\n IndexDescriptionInfo,\n} from \"mongodb\";\nimport type { MongoBaseModel } from \"../MongoBaseModel.ts\";\nimport { buildIndexName } from \"./buildIndexName.ts\";\nimport type { MongoIndex, MongoIndexDirection } from \"./types.ts\";\n\nconst textDefaultLanguage = \"english\";\nconst textLanguageOverride = \"language\";\n\nexport interface NormalizedIndexOptions {\n unique: boolean;\n sparse: boolean;\n hidden: boolean;\n expireAfterSeconds?: number;\n partialFilterExpression?: Document;\n collation?: CollationOptions;\n weights?: Record<string, number>;\n defaultLanguage?: string;\n languageOverride?: string;\n wildcardProjection?: Document;\n}\n\nexport interface NormalizedIndex {\n name: string;\n key: Record<string, MongoIndexDirection>;\n keyEntries: [string, MongoIndexDirection][];\n isText: boolean;\n options: NormalizedIndexOptions;\n}\n\nexport interface NormalizedDeclaredIndex extends NormalizedIndex {\n description: IndexDescription;\n}\n\nconst buildDescription = (\n index: MongoIndex<any>,\n name: string,\n): IndexDescription => {\n const description: IndexDescription = {\n key: index.key as Record<string, MongoIndexDirection>,\n name,\n };\n\n if (index.unique !== undefined) description.unique = index.unique;\n if (index.sparse !== undefined) description.sparse = index.sparse;\n if (index.hidden !== undefined) description.hidden = index.hidden;\n if (index.expireAfterSeconds !== undefined) {\n description.expireAfterSeconds = index.expireAfterSeconds;\n }\n if (index.partialFilterExpression) {\n description.partialFilterExpression = index.partialFilterExpression;\n }\n if (index.collation) description.collation = index.collation;\n if (index.weights) description.weights = index.weights;\n if (index.default_language) {\n // eslint-disable-next-line camelcase -- mongo option name\n description.default_language = index.default_language;\n }\n if (index.language_override) {\n // eslint-disable-next-line camelcase -- mongo option name\n description.language_override = index.language_override;\n }\n if (index.wildcardProjection) {\n description.wildcardProjection = index.wildcardProjection;\n }\n\n return description;\n};\n\nexport const normalizeDeclaredIndex = <Model extends MongoBaseModel<any>>(\n index: MongoIndex<Model>,\n): NormalizedDeclaredIndex => {\n const key = index.key as Record<string, MongoIndexDirection>;\n const entries = Object.entries(key);\n\n if (entries.length === 0) {\n throw new Error(\"Invalid index: key must have at least one field\");\n }\n\n const textFields = entries\n .filter(([, direction]) => direction === \"text\")\n .map(([field]) => field);\n const isText = textFields.length > 0;\n\n const name = index.name ?? buildIndexName(key);\n const isIdOnly = entries.length === 1 && entries[0]![0] === \"_id\";\n if (name === \"_id_\" || isIdOnly) {\n throw new Error(\n \"Invalid index: _id is always indexed by mongo and cannot be declared\",\n );\n }\n\n const weights = isText\n ? {\n ...Object.fromEntries(textFields.map((field) => [field, 1])),\n ...index.weights,\n }\n : undefined;\n\n return {\n name,\n key,\n keyEntries: entries.filter(([, direction]) => direction !== \"text\"),\n isText,\n options: {\n unique: index.unique ?? false,\n sparse: index.sparse ?? false,\n hidden: index.hidden ?? false,\n expireAfterSeconds: index.expireAfterSeconds,\n partialFilterExpression: index.partialFilterExpression,\n collation: index.collation,\n weights,\n defaultLanguage: isText\n ? (index.default_language ?? textDefaultLanguage)\n : undefined,\n languageOverride: isText\n ? (index.language_override ?? textLanguageOverride)\n : undefined,\n wildcardProjection: index.wildcardProjection,\n },\n description: buildDescription(index, name),\n };\n};\n\nexport const normalizeExistingIndex = (\n existing: IndexDescriptionInfo,\n): NormalizedIndex => {\n const key = existing.key as Record<string, MongoIndexDirection>;\n const entries = Object.entries(key);\n const isText = entries.some(([field]) => field === \"_fts\");\n\n return {\n name: existing.name ?? buildIndexName(key),\n key,\n keyEntries: entries.filter(\n ([field]) => field !== \"_fts\" && field !== \"_ftsx\",\n ),\n isText,\n options: {\n unique: existing.unique ?? false,\n sparse: existing.sparse ?? false,\n hidden: existing.hidden ?? false,\n expireAfterSeconds: existing.expireAfterSeconds,\n partialFilterExpression: existing.partialFilterExpression,\n collation: existing.collation,\n weights: isText ? existing.weights : undefined,\n defaultLanguage: isText\n ? (existing.default_language ?? textDefaultLanguage)\n : undefined,\n languageOverride: isText\n ? (existing.language_override ?? textLanguageOverride)\n : undefined,\n wildcardProjection: existing.wildcardProjection,\n },\n };\n};\n\ninterface NormalizeDeclaredIndexesParams<Model extends MongoBaseModel<any>> {\n collectionName: string;\n indexes: readonly MongoIndex<Model>[];\n}\n\nexport const normalizeDeclaredIndexes = <Model extends MongoBaseModel<any>>({\n collectionName,\n indexes,\n}: NormalizeDeclaredIndexesParams<Model>): NormalizedDeclaredIndex[] => {\n const normalized = indexes.map((index) => normalizeDeclaredIndex(index));\n\n const names = new Set<string>();\n normalized.forEach(({ name }) => {\n if (names.has(name)) {\n throw new Error(\n `Duplicate index name \"${name}\" declared on collection \"${collectionName}\"`,\n );\n }\n names.add(name);\n });\n\n const textIndexes = normalized.filter(({ isText }) => isText);\n if (textIndexes.length > 1) {\n throw new Error(\n `Only one text index is allowed per collection, \"${collectionName}\" declares ${textIndexes.length}`,\n );\n }\n\n return normalized;\n};\n","import type { IndexDescriptionInfo } from \"mongodb\";\nimport type { MongoBaseModel } from \"../MongoBaseModel.ts\";\nimport { deepEqualUnordered } from \"./deepEqualUnordered.ts\";\nimport type { NormalizedIndex } from \"./normalizeIndex.ts\";\nimport {\n normalizeDeclaredIndexes,\n normalizeExistingIndex,\n} from \"./normalizeIndex.ts\";\nimport type {\n MongoIndex,\n MongoIndexCollModChanges,\n MongoIndexDifference,\n MongoIndexPlan,\n} from \"./types.ts\";\n\nconst idIndexName = \"_id_\";\n\nconst isSameKey = (\n declared: NormalizedIndex,\n existing: NormalizedIndex,\n): boolean =>\n declared.isText === existing.isText &&\n declared.keyEntries.length === existing.keyEntries.length &&\n declared.keyEntries.every(\n ([field, direction], index) =>\n existing.keyEntries[index]![0] === field &&\n existing.keyEntries[index]![1] === direction,\n );\n\nconst isSameCollation = (\n declared: NormalizedIndex[\"options\"][\"collation\"],\n existing: NormalizedIndex[\"options\"][\"collation\"],\n): boolean => {\n if (!declared) return !existing;\n if (!existing) return false;\n\n return Object.entries(declared).every(([key, value]) =>\n deepEqualUnordered(value, (existing as any)[key]),\n );\n};\n\nconst diffOptions = (\n declared: NormalizedIndex,\n existing: NormalizedIndex,\n): MongoIndexDifference[] => {\n const differences: MongoIndexDifference[] = [];\n\n const compare = (\n field: MongoIndexDifference[\"field\"],\n declaredValue: unknown,\n existingValue: unknown,\n equals: (a: unknown, b: unknown) => boolean = deepEqualUnordered,\n ): void => {\n if (!equals(declaredValue, existingValue)) {\n differences.push({\n field,\n declared: declaredValue,\n existing: existingValue,\n });\n }\n };\n\n compare(\"unique\", declared.options.unique, existing.options.unique);\n compare(\"sparse\", declared.options.sparse, existing.options.sparse);\n compare(\"hidden\", declared.options.hidden, existing.options.hidden);\n compare(\n \"expireAfterSeconds\",\n declared.options.expireAfterSeconds,\n existing.options.expireAfterSeconds,\n );\n compare(\n \"partialFilterExpression\",\n declared.options.partialFilterExpression,\n existing.options.partialFilterExpression,\n );\n compare(\n \"collation\",\n declared.options.collation,\n existing.options.collation,\n (a, b) =>\n isSameCollation(\n a as NormalizedIndex[\"options\"][\"collation\"],\n b as NormalizedIndex[\"options\"][\"collation\"],\n ),\n );\n compare(\"weights\", declared.options.weights, existing.options.weights);\n compare(\n \"default_language\",\n declared.options.defaultLanguage,\n existing.options.defaultLanguage,\n );\n compare(\n \"language_override\",\n declared.options.languageOverride,\n existing.options.languageOverride,\n );\n compare(\n \"wildcardProjection\",\n declared.options.wildcardProjection,\n existing.options.wildcardProjection,\n );\n\n return differences;\n};\n\nconst isCollModApplicable = (\n differences: readonly MongoIndexDifference[],\n): boolean =>\n differences.length > 0 &&\n differences.every(\n (difference) =>\n difference.field === \"hidden\" ||\n (difference.field === \"expireAfterSeconds\" &&\n difference.declared !== undefined &&\n difference.existing !== undefined),\n );\n\nconst buildCollModChanges = (\n differences: readonly MongoIndexDifference[],\n): MongoIndexCollModChanges => {\n const changes: MongoIndexCollModChanges = {};\n differences.forEach((difference) => {\n if (difference.field === \"hidden\") {\n changes.hidden = difference.declared as boolean;\n } else if (difference.field === \"expireAfterSeconds\") {\n changes.expireAfterSeconds = difference.declared as number;\n }\n });\n return changes;\n};\n\ninterface DiffIndexesParams<Model extends MongoBaseModel<any>> {\n collectionName: string;\n declaredIndexes: readonly MongoIndex<Model>[];\n existingIndexes: readonly IndexDescriptionInfo[];\n dropUndeclaredIndexes: boolean;\n}\n\nexport const diffIndexes = <Model extends MongoBaseModel<any>>({\n collectionName,\n declaredIndexes,\n existingIndexes,\n dropUndeclaredIndexes,\n}: DiffIndexesParams<Model>): MongoIndexPlan => {\n const declared = normalizeDeclaredIndexes({\n collectionName,\n indexes: declaredIndexes,\n });\n\n const remainingExisting = new Map<\n string,\n { normalized: NormalizedIndex; raw: IndexDescriptionInfo }\n >();\n existingIndexes.forEach((raw) => {\n const normalized = normalizeExistingIndex(raw);\n if (normalized.name === idIndexName) return;\n remainingExisting.set(normalized.name, { normalized, raw });\n });\n\n const plan: MongoIndexPlan = {\n collectionName,\n toCreate: [],\n toRecreate: [],\n toCollMod: [],\n toDrop: [],\n unchanged: [],\n undeclaredKept: [],\n };\n\n declared.forEach((declaredIndex) => {\n const existing = remainingExisting.get(declaredIndex.name);\n\n if (!existing) {\n plan.toCreate.push({\n name: declaredIndex.name,\n index: declaredIndex.description,\n });\n return;\n }\n\n remainingExisting.delete(declaredIndex.name);\n\n if (!isSameKey(declaredIndex, existing.normalized)) {\n plan.toRecreate.push({\n name: declaredIndex.name,\n index: declaredIndex.description,\n existing: existing.raw,\n differences: [\n {\n field: \"key\",\n declared: declaredIndex.key,\n existing: existing.normalized.key,\n },\n ],\n });\n return;\n }\n\n const differences = diffOptions(declaredIndex, existing.normalized);\n\n if (differences.length === 0) {\n plan.unchanged.push(declaredIndex.name);\n } else if (isCollModApplicable(differences)) {\n plan.toCollMod.push({\n name: declaredIndex.name,\n changes: buildCollModChanges(differences),\n differences,\n });\n } else {\n plan.toRecreate.push({\n name: declaredIndex.name,\n index: declaredIndex.description,\n existing: existing.raw,\n differences,\n });\n }\n });\n\n remainingExisting.forEach(({ raw }, name) => {\n if (dropUndeclaredIndexes) {\n plan.toDrop.push({ name, existing: raw });\n } else {\n plan.undeclaredKept.push(name);\n }\n });\n\n return plan;\n};\n\nexport const isMongoIndexPlanEmpty = (plan: MongoIndexPlan): boolean =>\n plan.toCreate.length === 0 &&\n plan.toRecreate.length === 0 &&\n plan.toCollMod.length === 0 &&\n plan.toDrop.length === 0;\n","import type {\n AllowedKeyValue,\n CreateQueryOptions,\n Criteria,\n Fields,\n OptionalBaseModelKeysForInsert,\n QueryParams,\n Sort,\n SubscribableStore,\n Update,\n UpsertPartialObject,\n UpsertResult,\n} from \"liwi-store\";\nimport type {\n Collection,\n Filter,\n FindCursor,\n MongoClient,\n UpdateFilter,\n} from \"mongodb\";\nimport mongodb from \"mongodb\";\nimport type {\n MongoBaseModel,\n MongoInsertType,\n MongoKeyPath,\n} from \"./MongoBaseModel.ts\";\nimport type MongoConnection from \"./MongoConnection.ts\";\nimport MongoCursor from \"./MongoCursor.ts\";\nimport MongoQueryCollection from \"./MongoQueryCollection.ts\";\nimport MongoQuerySingleItem from \"./MongoQuerySingleItem.ts\";\nimport { applyIndexPlan } from \"./indexes/applyIndexPlan.ts\";\nimport { diffIndexes } from \"./indexes/diffIndexes.ts\";\nimport { isNamespaceNotFoundError } from \"./indexes/isIndexConflictError.ts\";\nimport { normalizeDeclaredIndexes } from \"./indexes/normalizeIndex.ts\";\nimport type {\n MongoIndex,\n MongoIndexPlan,\n MongoIndexSyncResult,\n SyncIndexesOptions,\n} from \"./indexes/types.ts\";\n\nexport type MongoUpsertResult<\n KeyValue extends AllowedKeyValue,\n Model extends MongoBaseModel<KeyValue>,\n> = UpsertResult<Model>;\n\nexport interface MongoStoreOptions<Model extends MongoBaseModel<any>> {\n indexes?: readonly MongoIndex<Model>[];\n}\n\nexport default class MongoStore<\n Model extends MongoBaseModel<KeyValue>,\n KeyValue extends AllowedKeyValue = Model[MongoKeyPath],\n> implements SubscribableStore<\n MongoKeyPath,\n KeyValue,\n Model,\n MongoInsertType<Model>,\n MongoConnection\n> {\n readonly keyPath: MongoKeyPath = \"_id\";\n\n readonly connection: MongoConnection;\n\n readonly collectionName: string;\n\n private readonly declaredIndexes: readonly MongoIndex<Model>[];\n\n private _collection: Collection<Model> | Promise<Collection<Model>>;\n\n constructor(\n connection: MongoConnection,\n collectionName: string,\n { indexes = [] }: MongoStoreOptions<Model> = {},\n ) {\n this.connection = connection;\n\n if (!collectionName) {\n throw new Error(`Invalid collectionName: \"${collectionName}\"`);\n }\n\n this.collectionName = collectionName;\n this.declaredIndexes = indexes;\n normalizeDeclaredIndexes({ collectionName, indexes });\n\n this._collection = connection.getConnection().then(\n (client: MongoClient) => {\n this._collection = client.db().collection(collectionName);\n return this._collection;\n },\n (error: Error) => {\n this._collection = Promise.reject(error);\n return this._collection;\n },\n );\n }\n\n get collection(): Promise<Collection<Model>> {\n if (this.connection.connectionFailed) {\n return Promise.reject(new Error(\"MongoDB connection failed\"));\n }\n\n return Promise.resolve(this._collection);\n }\n\n async planIndexes({\n dropUndeclaredIndexes = true,\n }: SyncIndexesOptions = {}): Promise<MongoIndexPlan> {\n const collection = await this.collection;\n\n const existingIndexes = await collection\n .listIndexes()\n .toArray()\n .catch((error: unknown) => {\n if (isNamespaceNotFoundError(error)) return [];\n throw error;\n });\n\n return diffIndexes<Model>({\n collectionName: this.collectionName,\n declaredIndexes: this.declaredIndexes,\n existingIndexes,\n dropUndeclaredIndexes,\n });\n }\n\n async syncIndexes(\n options: SyncIndexesOptions = {},\n ): Promise<MongoIndexSyncResult> {\n const plan = await this.planIndexes(options);\n const collection = await this.collection;\n const client = await this.connection.getConnection();\n\n return applyIndexPlan({\n plan,\n collection: collection as Collection<any>,\n db: client.db(),\n dryRun: options.dryRun ?? false,\n });\n }\n\n createQuerySingleItem<\n Result extends Record<MongoKeyPath, KeyValue> = Model,\n Params extends QueryParams<Params> = never,\n >({\n transformer,\n ...options\n }: CreateQueryOptions<Model, Result>): MongoQuerySingleItem<\n Model,\n Params,\n Result,\n KeyValue\n > {\n return new MongoQuerySingleItem<Model, Params, Result, KeyValue>(\n this,\n options,\n transformer,\n );\n }\n\n createQueryCollection<\n Item extends Record<MongoKeyPath, KeyValue> = Model,\n Params extends QueryParams<Params> = never,\n >({\n transformer,\n ...options\n }: CreateQueryOptions<Model, Item>): MongoQueryCollection<\n Model,\n Params,\n Model[\"_id\"],\n Item\n > {\n return new MongoQueryCollection<Model, Params, KeyValue, Item>(\n this,\n options,\n transformer,\n );\n }\n\n async insertOne(object: MongoInsertType<Model>): Promise<Model> {\n if (!object._id) {\n object._id = new mongodb.ObjectId().toString() as Model[\"_id\"];\n }\n\n if (!object.created) object.created = new Date();\n if (!object.updated) object.updated = new Date();\n\n const collection = await this.collection;\n const { acknowledged: isAcknowledged } = await collection.insertOne(\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n object as any,\n );\n if (!isAcknowledged) {\n throw new Error(\"Fail to insert\");\n }\n\n return object as Model;\n }\n\n async replaceOne(object: Model): Promise<Model> {\n if (!object.updated) object.updated = new Date();\n\n const collection = await this.collection;\n await collection.replaceOne({ _id: object._id } as Filter<Model>, object);\n return object;\n }\n\n async upsertOne<\n K extends Exclude<\n keyof Model,\n MongoKeyPath | OptionalBaseModelKeysForInsert\n >,\n >(\n object: UpsertPartialObject<MongoKeyPath, KeyValue, Model, K>,\n setOnInsertPartialObject?: Update<Model>[\"$setOnInsert\"],\n ): Promise<Model> {\n const result = await this.upsertOneWithInfo(\n object,\n setOnInsertPartialObject,\n );\n return result.object;\n }\n\n async upsertOneWithInfo<\n K extends Exclude<\n keyof Model,\n MongoKeyPath | OptionalBaseModelKeysForInsert\n >,\n >(\n object: UpsertPartialObject<MongoKeyPath, KeyValue, Model, K>,\n setOnInsertPartialObject?: Update<Model>[\"$setOnInsert\"],\n ): Promise<MongoUpsertResult<KeyValue, Model>> {\n const $setOnInsert: Update<Model>[\"$setOnInsert\"] = {\n // @ts-expect-error -- created is Date as set in BaseModel\n created: object.created || new Date(),\n ...setOnInsertPartialObject,\n };\n\n if (!object.updated) {\n (object as MongoBaseModel).updated = new Date();\n }\n\n const $set: Partial<typeof object> = { ...object };\n delete $set.created;\n\n const collection = await this.collection;\n\n const prev = await collection.findOneAndUpdate(\n { _id: object._id } as Filter<Model>,\n { $set, $setOnInsert } as UpdateFilter<Model>,\n { upsert: true, returnDocument: \"before\" },\n );\n\n if (!prev) {\n Object.assign(object, $setOnInsert);\n return {\n resolvedAs: \"inserted\",\n inserted: true,\n object: object as unknown as Model,\n };\n }\n\n const next = { ...prev, ...$set };\n\n return {\n resolvedAs: \"updated\",\n inserted: false,\n object: next as Model,\n prev: prev as Model,\n };\n }\n\n replaceSeveral(objects: Model[]): Promise<Model[]> {\n return Promise.all(objects.map((object: Model) => this.replaceOne(object)));\n }\n\n async partialUpdateByKey(\n key: KeyValue,\n partialUpdate: Update<Model>,\n criteria?: Criteria<Model>,\n ): Promise<Model> {\n const collection = await this.collection;\n const commandResult = await collection.updateOne(\n { _id: key, ...criteria } as Filter<Model>,\n partialUpdate as UpdateFilter<Model>,\n );\n if (!commandResult.acknowledged) {\n console.error(commandResult);\n throw new Error(\"Update failed\");\n }\n const object = await this.findByKey(key);\n return object!;\n }\n\n partialUpdateOne(\n object: Model,\n partialUpdate: Update<Model>,\n ): Promise<Model> {\n return this.partialUpdateByKey(object._id, partialUpdate);\n }\n\n partialUpdateMany(\n criteria: Criteria<Model>,\n partialUpdate: Update<Model>,\n ): Promise<void> {\n return this.collection\n .then((collection) =>\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n collection.updateMany(criteria as Filter<Model>, partialUpdate as any),\n )\n .then((res) => undefined); // TODO return updated object\n }\n\n deleteByKey(key: KeyValue, criteria?: Criteria<Model>): Promise<void> {\n return this.collection\n .then((collection) =>\n collection.deleteOne({ _id: key, ...criteria } as Filter<Model>),\n )\n .then(() => undefined);\n }\n\n deleteOne(object: Model): Promise<void> {\n return this.deleteByKey(object._id);\n }\n\n deleteMany(selector: Criteria<Model>): Promise<void> {\n return this.collection\n .then((collection) => collection.deleteMany(selector as Filter<Model>))\n .then(() => undefined);\n }\n\n async count(filter?: Criteria<Model>): Promise<number> {\n const collection = await this.collection;\n return filter\n ? collection.countDocuments(filter as Filter<Model>)\n : collection.countDocuments();\n }\n\n async cursor<Result extends Partial<Model> = Model>(\n filter?: Criteria<Model>,\n sort?: Sort<Model>,\n fields?: Fields<Model>,\n ): Promise<MongoCursor<Model, Result, KeyValue>> {\n const collection = await this.collection;\n const findCursor = filter\n ? collection.find<Result>(filter as Filter<Model>)\n : (collection.find() as unknown as FindCursor<Result>);\n if (sort) findCursor.sort(sort);\n if (fields) findCursor.project(fields);\n return new MongoCursor<Model, Result, KeyValue>(this, findCursor);\n }\n\n async findByKey(\n key: KeyValue,\n criteria?: Criteria<Model>,\n ): Promise<Model | undefined> {\n const collection = await this.collection;\n const result = await collection.findOne<Model>({\n _id: key,\n ...criteria,\n } as Filter<Model>);\n return result || undefined;\n }\n\n findAll(criteria?: Criteria<Model>, sort?: Sort<Model>): Promise<Model[]> {\n return this.cursor<Model>(criteria, sort).then((cursor) =>\n cursor.toArray(),\n );\n }\n\n async findOne(\n filter: Criteria<Model>,\n sort?: Sort<Model>,\n ): Promise<Model | undefined> {\n const collection = await this.collection;\n const result = await collection.findOne<Model>(filter as Filter<Model>, {\n sort,\n });\n return result || undefined;\n }\n}\n","import { AbstractConnection } from \"liwi-store\";\nimport mongodb from \"mongodb\";\nimport { Logger } from \"nightingale-logger\";\n\nconst logger = new Logger(\"liwi:mongo:MongoConnection\");\n\nexport interface MongoConfig {\n host?: string;\n port?: number | string;\n database: string;\n user?: string;\n password?: string;\n}\n\nexport default class MongoConnection extends AbstractConnection {\n _connection?: mongodb.MongoClient;\n\n _connecting?: Promise<mongodb.MongoClient>;\n\n connectionFailed?: boolean;\n\n // TODO interface\n constructor({\n host = \"localhost\",\n port = \"27017\",\n database,\n user,\n password,\n }: MongoConfig) {\n super();\n\n if (!database) {\n throw new Error(\"Missing config database\");\n }\n\n const buildConnectionString = (redactCredentials: boolean): string =>\n `mongodb://${\n user\n ? `${\n redactCredentials\n ? `${user.slice(0, 2)}[redacted]`\n : encodeURIComponent(user)\n }:${\n redactCredentials\n ? \"[redacted]\"\n : encodeURIComponent(password ?? \"\")\n }@`\n : \"\"\n }${host}:${port}/${encodeURIComponent(database)}`;\n\n const connectionString = buildConnectionString(false);\n const connectionStringRedacted = buildConnectionString(true);\n\n this.connect(connectionString, connectionStringRedacted);\n }\n\n connect(connectionString: string, connectionStringRedacted: string): void {\n logger.info(\"connecting\", { connectionStringRedacted });\n\n const connectPromise = mongodb.MongoClient.connect(connectionString)\n .then((connection) => {\n logger.info(\"connected\", { connectionStringRedacted });\n connection.on(\"close\", () => {\n logger.warn(\"close\", { connectionStringRedacted });\n this.connectionFailed = true;\n this.getConnection = () => {\n throw new Error(\"MongoDB connection closed\");\n };\n });\n connection.on(\"timeout\", () => {\n logger.warn(\"timeout\", { connectionStringRedacted });\n this.connectionFailed = true;\n this.getConnection = () => {\n throw new Error(\"MongoDB connection timeout\");\n };\n });\n connection.on(\"reconnect\", () => {\n logger.warn(\"reconnect\", { connectionStringRedacted });\n this.connectionFailed = false;\n this.getConnection = () => Promise.resolve(this._connection!);\n });\n connection.on(\"error\", (err) => {\n logger.warn(\"error\", { connectionStringRedacted, err });\n });\n\n this._connection = connection;\n this._connecting = undefined;\n this.getConnection = () => Promise.resolve(this._connection!);\n return connection;\n })\n .catch((error: unknown) => {\n logger.info(\"not connected\", { connectionStringRedacted });\n console.error((error as Error).message || error);\n // throw err;\n process.nextTick(() => {\n // eslint-disable-next-line unicorn/no-process-exit\n process.exit(1);\n });\n\n throw error;\n });\n\n this.getConnection = () => Promise.resolve(connectPromise);\n this._connecting = this.getConnection();\n }\n\n getConnection(): Promise<mongodb.MongoClient> {\n throw new Error(\"call connect()\");\n }\n\n async close(): Promise<void> {\n this.getConnection = () => Promise.reject(new Error(\"Connection closed\"));\n if (this._connection) {\n await this._connection.close();\n this._connection = undefined;\n } else if (this._connecting) {\n await this._connecting;\n await this.close();\n }\n }\n}\n","import type { AllowedKeyValue } from \"liwi-store\";\nimport { SubscribeStore } from \"liwi-subscribe-store\";\nimport type {\n MongoBaseModel,\n MongoInsertType,\n MongoKeyPath,\n} from \"./MongoBaseModel\";\nimport type MongoConnection from \"./MongoConnection\";\nimport type MongoStore from \"./MongoStore\";\n\nexport default function createMongoSubscribeStore<\n Model extends MongoBaseModel<KeyValue>,\n KeyValue extends AllowedKeyValue = Model[MongoKeyPath],\n>(\n mongoStore: MongoStore<Model, KeyValue>,\n): SubscribeStore<\n MongoKeyPath,\n KeyValue,\n Model,\n MongoInsertType<Model, KeyValue>,\n MongoConnection,\n MongoStore<Model, KeyValue>\n> {\n return new SubscribeStore(mongoStore);\n}\n\nexport { type SubscribeStore } from \"liwi-subscribe-store\";\n","import { Logger } from \"nightingale-logger\";\nimport type { MongoRegistryStore } from \"./MongoRegistryStore.ts\";\nimport type {\n MongoIndexPlan,\n MongoIndexSyncResult,\n SyncIndexesOptions,\n} from \"./indexes/types.ts\";\n\nconst logger = new Logger(\"liwi:mongo:MongoRegistry\");\n\nexport interface MongoRegistryOptions {\n dropUndeclaredIndexes?: boolean;\n}\n\nexport default class MongoRegistry {\n private readonly _stores: MongoRegistryStore[];\n\n private readonly dropUndeclaredIndexes: boolean;\n\n constructor(\n stores: readonly MongoRegistryStore[] = [],\n { dropUndeclaredIndexes = true }: MongoRegistryOptions = {},\n ) {\n this._stores = [];\n this.dropUndeclaredIndexes = dropUndeclaredIndexes;\n stores.forEach((store) => this.add(store));\n }\n\n get stores(): readonly MongoRegistryStore[] {\n return this._stores;\n }\n\n add(store: MongoRegistryStore): this {\n if (this.getStore(store.collectionName)) {\n logger.warn(\"collection already registered\", {\n collectionName: store.collectionName,\n });\n }\n this._stores.push(store);\n return this;\n }\n\n remove(store: MongoRegistryStore): this {\n const index = this._stores.indexOf(store);\n if (index !== -1) this._stores.splice(index, 1);\n return this;\n }\n\n getStore(collectionName: string): MongoRegistryStore | undefined {\n return this._stores.find(\n (store) => store.collectionName === collectionName,\n );\n }\n\n private resolveOptions(options: SyncIndexesOptions = {}): SyncIndexesOptions {\n return {\n ...options,\n dropUndeclaredIndexes:\n options.dropUndeclaredIndexes ?? this.dropUndeclaredIndexes,\n };\n }\n\n private sortedStores(): MongoRegistryStore[] {\n return this._stores.toSorted((storeA, storeB) =>\n storeA.collectionName.localeCompare(storeB.collectionName),\n );\n }\n\n private async runSequentially<Result>(\n operation: string,\n run: (store: MongoRegistryStore) => Promise<Result>,\n ): Promise<Result[]> {\n const results: Result[] = [];\n const errors: unknown[] = [];\n\n for (const store of this.sortedStores()) {\n try {\n results.push(await run(store));\n } catch (error: unknown) {\n logger.error(operation, {\n collectionName: store.collectionName,\n error,\n });\n errors.push(error);\n }\n }\n\n if (errors.length > 0) {\n throw new AggregateError(errors, `${operation} failed`);\n }\n\n return results;\n }\n\n planIndexes(options?: SyncIndexesOptions): Promise<MongoIndexPlan[]> {\n const resolvedOptions = this.resolveOptions(options);\n return this.runSequentially(\"planIndexes\", (store) =>\n store.planIndexes(resolvedOptions),\n );\n }\n\n syncIndexes(options?: SyncIndexesOptions): Promise<MongoIndexSyncResult[]> {\n const resolvedOptions = this.resolveOptions(options);\n return this.runSequentially(\"syncIndexes\", (store) =>\n store.syncIndexes(resolvedOptions),\n );\n }\n}\n","import type { MongoIndexDifference, MongoIndexPlan } from \"./types.ts\";\n\nconst formatDifference = ({\n field,\n declared,\n existing,\n}: MongoIndexDifference): string =>\n `${field}: ${JSON.stringify(existing) ?? \"undefined\"} -> ${JSON.stringify(declared) ?? \"undefined\"}`;\n\nconst formatDifferences = (\n differences: readonly MongoIndexDifference[],\n): string =>\n differences.map((difference) => formatDifference(difference)).join(\", \");\n\ninterface PlanLine {\n action: string;\n name: string;\n detail: string;\n}\n\nconst buildLines = (plan: MongoIndexPlan): PlanLine[] => [\n ...plan.toCreate.map(({ name, index }) => ({\n action: \"+ create\",\n name,\n detail: JSON.stringify(index.key),\n })),\n ...plan.toRecreate.map(({ name, differences }) => ({\n action: \"~ recreate\",\n name,\n detail: formatDifferences(differences),\n })),\n ...plan.toCollMod.map(({ name, differences }) => ({\n action: \"! modify\",\n name,\n detail: formatDifferences(differences),\n })),\n ...plan.toDrop.map(({ name }) => ({ action: \"- drop\", name, detail: \"\" })),\n ...plan.undeclaredKept.map((name) => ({\n action: \"? kept\",\n name,\n detail: \"undeclared, not dropped\",\n })),\n];\n\nexport const formatIndexPlan = (plan: MongoIndexPlan): string => {\n const lines = buildLines(plan);\n const unchangedCount = plan.unchanged.length;\n\n if (lines.length === 0) {\n return `${plan.collectionName}\\n = ${unchangedCount} unchanged, nothing to do`;\n }\n\n const actionWidth = Math.max(...lines.map(({ action }) => action.length));\n const nameWidth = Math.max(...lines.map(({ name }) => name.length));\n\n const formattedLines = lines.map(\n ({ action, name, detail }) =>\n ` ${action.padEnd(actionWidth)} ${detail ? name.padEnd(nameWidth) : name}${detail ? ` ${detail}` : \"\"}`,\n );\n\n if (unchangedCount > 0) {\n formattedLines.push(` = ${unchangedCount} unchanged`);\n }\n\n return [plan.collectionName, ...formattedLines].join(\"\\n\");\n};\n\nexport const formatIndexPlans = (plans: readonly MongoIndexPlan[]): string =>\n plans.map((plan) => formatIndexPlan(plan)).join(\"\\n\");\n\nexport { isMongoIndexPlanEmpty } from \"./diffIndexes.ts\";\n","import type MongoConnection from \"../MongoConnection.ts\";\nimport type MongoRegistry from \"../MongoRegistry.ts\";\nimport { isMongoIndexPlanEmpty } from \"./diffIndexes.ts\";\nimport { formatIndexPlans } from \"./formatIndexPlan.ts\";\nimport type { MongoIndexSyncResult, SyncIndexesOptions } from \"./types.ts\";\n\nconst usage = `Usage: [plan|sync] [options]\n\n plan print the plan, changes nothing (default)\n sync apply the plan\n\n --check with plan, exit 1 when the plan is not empty\n --dry-run with sync, compute everything but apply nothing\n --keep-undeclared do not drop indexes that are not declared`;\n\nconst formatSyncResult = ({\n collectionName,\n created,\n modified,\n dropped,\n}: MongoIndexSyncResult): string =>\n `${collectionName}: ${created.length} created, ${modified.length} modified, ${dropped.length} dropped`;\n\nexport interface RunIndexesCliParams {\n registry: MongoRegistry;\n argv?: readonly string[];\n connection?: MongoConnection;\n log?: (message: string) => void;\n logError?: (message: string) => void;\n}\n\nexport const runIndexesCli = async ({\n registry,\n argv = process.argv.slice(2),\n connection,\n log = console.log,\n logError = console.error,\n}: RunIndexesCliParams): Promise<number> => {\n const command = argv.find((arg) => !arg.startsWith(\"--\")) ?? \"plan\";\n const options: SyncIndexesOptions = {\n ...(argv.includes(\"--keep-undeclared\")\n ? { dropUndeclaredIndexes: false }\n : {}),\n dryRun: argv.includes(\"--dry-run\"),\n };\n\n try {\n if (command === \"plan\") {\n const plans = await registry.planIndexes(options);\n log(formatIndexPlans(plans));\n const hasChanges = !plans.every((plan) => isMongoIndexPlanEmpty(plan));\n return argv.includes(\"--check\") && hasChanges ? 1 : 0;\n }\n\n if (command === \"sync\") {\n const results = await registry.syncIndexes(options);\n log(formatIndexPlans(results.map(({ plan }) => plan)));\n log(\n results\n .map(\n (result) =>\n `${formatSyncResult(result)}${result.dryRun ? \" (dry run, nothing applied)\" : \"\"}`,\n )\n .join(\"\\n\"),\n );\n return 0;\n }\n\n logError(`Unknown command \"${command}\".\\n\\n${usage}`);\n return 2;\n } finally {\n await connection?.close();\n }\n};\n"],"names":["identityTransformer","logger","idIndexName"],"mappings":"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"}
1
+ {"version":3,"file":"index-node.mjs","sources":["../src/MongoCursor.ts","../src/MongoQueryCollection.ts","../src/MongoQuerySingleItem.ts","../src/indexes/isIndexConflictError.ts","../src/indexes/applyIndexPlan.ts","../src/indexes/deepEqualUnordered.ts","../src/indexes/buildIndexName.ts","../src/indexes/normalizeIndex.ts","../src/indexes/diffIndexes.ts","../src/MongoStore.ts","../src/MongoConnection.ts","../src/createMongoSubscribeStore.ts","../src/MongoRegistry.ts","../src/indexes/formatIndexPlan.ts","../src/indexes/runIndexesCli.ts"],"sourcesContent":["import { AbstractStoreCursor } from \"liwi-store\";\nimport type { AllowedKeyValue } from \"liwi-store\";\nimport type { FindCursor } from \"mongodb\";\nimport type { MongoBaseModel } from \"./MongoBaseModel\";\nimport type MongoStore from \"./MongoStore\";\n\nexport default class MongoCursor<\n Model extends MongoBaseModel<KeyValue>,\n Result extends Partial<Model> = Model,\n KeyValue extends AllowedKeyValue = Model[\"_id\"],\n> extends AbstractStoreCursor<\n MongoStore<Model, KeyValue>,\n KeyValue,\n Model,\n Result\n> {\n // key in AbstractCursor\n\n private readonly cursor: FindCursor<Result>;\n\n private _result?: Result | null;\n\n constructor(store: MongoStore<Model, KeyValue>, cursor: FindCursor<Result>) {\n super(store);\n this.cursor = cursor;\n }\n\n advance(count: number): void {\n this.cursor.skip(count);\n }\n\n next(): Promise<KeyValue | undefined> {\n return this.cursor.next().then((value) => {\n this._result = value;\n this.key = value?._id;\n return this.key;\n });\n }\n\n override async forEach(\n callback: (result: Result) => Promise<void> | void,\n ): Promise<void> {\n for await (const result of this.cursor) {\n await callback(result);\n }\n }\n\n limit(newLimit: number): Promise<this> {\n this.cursor.limit(newLimit);\n return Promise.resolve(this);\n }\n\n override result(): Promise<Result> {\n if (!this._result) throw new Error(\"Cannot call result() before next()\");\n return Promise.resolve(this._result);\n }\n\n close(): Promise<void> {\n if (this.cursor) {\n this.cursor.close();\n }\n\n return Promise.resolve();\n }\n\n toArray(): Promise<Result[]> {\n return this.cursor.toArray();\n }\n}\n","/* eslint-disable complexity */\nimport type {\n AllowedKeyValue,\n Changes,\n QueryOptions,\n QueryParams,\n QueryResult,\n QuerySubscription,\n SubscribeCallback,\n Transformer,\n} from \"liwi-store\";\nimport type { Actions } from \"liwi-subscribe-store\";\nimport { AbstractSubscribableStoreQuery } from \"liwi-subscribe-store\";\nimport { Query as MingoQuery } from \"mingo\";\nimport type {\n MongoBaseModel,\n MongoInsertType,\n MongoKeyPath,\n} from \"./MongoBaseModel\";\nimport type MongoCursor from \"./MongoCursor\";\nimport type MongoStore from \"./MongoStore\";\n\nconst identityTransformer = <\n Model extends MongoBaseModel<any>,\n Transformed = Model,\n>(\n model: Model,\n): Transformed => model as unknown as Transformed;\n\ntype TestCriteria = (obj: any) => boolean;\n\nexport default class MongoQueryCollection<\n Model extends MongoBaseModel<KeyValue>,\n Params extends QueryParams<Params> = never,\n KeyValue extends AllowedKeyValue = Model[\"_id\"],\n Item extends Record<MongoKeyPath, KeyValue> = Model,\n> extends AbstractSubscribableStoreQuery<\n MongoKeyPath,\n KeyValue,\n Model,\n MongoInsertType<Model, KeyValue>,\n Params,\n Item[]\n> {\n private readonly store: MongoStore<Model, KeyValue>;\n\n private readonly options: QueryOptions<Model>;\n\n private testCriteria?: TestCriteria;\n\n private readonly transformer: Transformer<Model, Item>;\n\n constructor(\n store: MongoStore<Model, KeyValue>,\n options: QueryOptions<Model>,\n transformer: Transformer<Model, Item> = identityTransformer,\n ) {\n super();\n this.store = store;\n this.options = options;\n this.transformer = transformer;\n }\n\n createTestCriteria(): TestCriteria {\n if (!this.testCriteria) {\n if (!this.options.criteria) {\n return () => true;\n }\n\n // criteria not supported by mingo: updates will not work\n if (\"$text\" in this.options.criteria) {\n return () => false;\n }\n\n const mingoQuery = new MingoQuery(this.options.criteria);\n this.testCriteria = mingoQuery.test.bind(mingoQuery);\n }\n return this.testCriteria;\n }\n\n async fetch<T>(onFulfilled: (result: QueryResult<Item[]>) => T): Promise<T> {\n const [result, count] = await Promise.all([\n this.createMongoCursor().then((cursor) => cursor.toArray()),\n this.store.count(this.options.criteria),\n ]);\n\n return onFulfilled({\n result: result.map(this.transformer),\n meta: { total: count },\n info: {\n sort: this.options.sort,\n limit: this.options.limit,\n keyPath: this.store.keyPath,\n },\n });\n }\n\n _subscribe(\n callback: SubscribeCallback<KeyValue, Item[]>,\n _includeInitial: boolean,\n ): QuerySubscription {\n const store = super.getSubscribeStore();\n const testCriteria: TestCriteria = this.createTestCriteria();\n\n const promise: Promise<void> = _includeInitial\n ? this.fetch(({ result, meta, info }: QueryResult<Item[]>) => {\n callback(null, [\n {\n type: \"initial\",\n initial: result,\n queryInfo: info,\n meta,\n },\n ]);\n })\n : Promise.resolve();\n\n const unsubscribe = store.subscribe((action: Actions<Model>) => {\n const changes: Changes<KeyValue, Item[]> = [];\n switch (action.type) {\n case \"inserted\": {\n const filtered = action.next.filter(testCriteria);\n if (filtered.length > 0) {\n changes.push({\n type: \"inserted\",\n result: filtered.map(this.transformer),\n });\n }\n break;\n }\n case \"deleted\": {\n const filtered = action.prev.filter(testCriteria);\n if (filtered.length > 0) {\n changes.push({\n type: \"deleted\",\n keys: filtered.map((object) => object[this.store.keyPath]),\n });\n }\n break;\n }\n case \"updated\": {\n const {\n deleted,\n updated,\n inserted,\n }: {\n deleted: KeyValue[];\n updated: Item[];\n inserted: Item[];\n } = { deleted: [], updated: [], inserted: [] };\n\n action.changes.forEach(([prevObject, nextObject]: [Model, Model]) => {\n if (testCriteria(prevObject)) {\n if (!testCriteria(nextObject)) {\n deleted.push(prevObject[this.store.keyPath]);\n } else {\n updated.push(this.transformer(nextObject));\n }\n } else if (testCriteria(nextObject)) {\n inserted.push(this.transformer(nextObject));\n }\n });\n\n if (deleted.length > 0) {\n changes.push({ type: \"deleted\", keys: deleted });\n }\n if (updated.length > 0) {\n changes.push({ type: \"updated\", result: updated });\n }\n if (inserted.length > 0) {\n changes.push({ type: \"inserted\", result: inserted });\n }\n\n break;\n }\n default:\n throw new Error(\"Unsupported type\");\n }\n\n if (changes.length === 0) return;\n\n callback(null, changes);\n });\n // let _feed;\n // const promise = this.queryCallback(this.store.query(), this.store.r)\n // .changes({\n // includeInitial: _includeInitial,\n // includeStates: true,\n // includeTypes: true,\n // includeOffsets: true,\n // })\n // .then((feed) => {\n // if (args.length === 0) {\n // _feed = feed;\n // delete this._promise;\n // }\n //\n // feed.each(callback);\n // return feed;\n // });\n //\n // if (args.length === 0) this._promise = promise;\n\n return {\n stop: unsubscribe,\n cancel: unsubscribe,\n then: <T, U>(\n onFulfilled: () => Promise<T> | T,\n onRejected?: (error: any) => Promise<U> | U,\n ): Promise<T | U> => promise.then(onFulfilled, onRejected),\n };\n }\n\n private async createMongoCursor(): Promise<\n MongoCursor<Model, Model, KeyValue>\n > {\n const cursor = await this.store.cursor(\n this.options.criteria,\n this.options.sort,\n this.options.fields,\n );\n\n if (this.options.skip) {\n cursor.advance(this.options.skip);\n }\n\n if (this.options.limit) {\n await cursor.limit(this.options.limit);\n }\n\n return cursor;\n }\n}\n","import type {\n AllowedKeyValue,\n Changes,\n QueryOptions,\n QueryParams,\n QueryResult,\n QuerySubscription,\n SubscribeCallback,\n Transformer,\n} from \"liwi-store\";\nimport type { Actions } from \"liwi-subscribe-store\";\nimport { AbstractSubscribableStoreQuery } from \"liwi-subscribe-store\";\nimport { Query as MingoQuery } from \"mingo\";\nimport type {\n MongoBaseModel,\n MongoInsertType,\n MongoKeyPath,\n} from \"./MongoBaseModel\";\nimport type MongoCursor from \"./MongoCursor\";\nimport type MongoStore from \"./MongoStore\";\n\nconst identityTransformer = <\n Model extends MongoBaseModel<any>,\n Transformed = Model,\n>(\n model: Model,\n): Transformed => model as unknown as Transformed;\n\ntype TestCriteria = (obj: any) => boolean;\n\nexport default class MongoQuerySingleItem<\n Model extends MongoBaseModel<KeyValue>,\n Params extends QueryParams<Params> = never,\n Result extends Record<MongoKeyPath, KeyValue> | null = Model | null,\n KeyValue extends AllowedKeyValue = Model[\"_id\"],\n> extends AbstractSubscribableStoreQuery<\n MongoKeyPath,\n KeyValue,\n Model,\n MongoInsertType<Model, KeyValue>,\n Params,\n Result\n> {\n private readonly store: MongoStore<Model, KeyValue>;\n\n private readonly options: QueryOptions<Model>;\n\n private testCriteria?: TestCriteria;\n\n private readonly transformer: Transformer<Model, Result>;\n\n constructor(\n store: MongoStore<Model, KeyValue>,\n options: QueryOptions<Model>,\n transformer: Transformer<Model, Result> = identityTransformer,\n ) {\n super();\n this.store = store;\n this.options = options;\n this.transformer = transformer;\n }\n\n createMingoTestCriteria(): TestCriteria {\n if (!this.testCriteria) {\n if (!this.options.criteria) {\n return () => true;\n }\n\n const mingoQuery = new MingoQuery(this.options.criteria);\n this.testCriteria = mingoQuery.test.bind(mingoQuery);\n }\n\n return this.testCriteria;\n }\n\n async fetch<T>(onFulfilled: (result: QueryResult<Result>) => T): Promise<T> {\n const cursor = await this.createMongoCursor();\n await cursor.limit(1);\n return cursor.toArray().then((result: Model[]) => {\n const item: Result =\n result.length === 0 ? (null as Result) : this.transformer(result[0]!);\n return onFulfilled({\n result: item,\n meta: { total: result === null ? 0 : 1 },\n info: {\n limit: 1,\n keyPath: this.store.keyPath,\n },\n });\n });\n }\n\n _subscribe(\n callback: SubscribeCallback<KeyValue, Result>,\n _includeInitial: boolean,\n ): QuerySubscription {\n const store = super.getSubscribeStore();\n const testCriteria: TestCriteria = this.createMingoTestCriteria();\n\n const promise: Promise<void> = _includeInitial\n ? this.fetch(({ result, meta, info }: QueryResult<Result>) => {\n callback(null, [\n {\n type: \"initial\",\n initial: result,\n queryInfo: info,\n meta,\n },\n ]);\n })\n : Promise.resolve();\n\n const unsubscribe = store.subscribe(async (action: Actions<Model>) => {\n const changes: Changes<KeyValue, Result> = [];\n switch (action.type) {\n case \"inserted\": {\n const filtered = action.next.filter(testCriteria);\n if (filtered.length > 0) {\n changes.push({\n type: \"updated\",\n result: this.transformer(filtered[0]!),\n });\n }\n break;\n }\n case \"deleted\": {\n const filtered = action.prev.filter(testCriteria);\n if (filtered.length > 0) {\n changes.push({\n type: \"deleted\",\n keys: filtered.map((object) => object[this.store.keyPath]),\n });\n }\n break;\n }\n case \"updated\": {\n const filtered = action.changes.filter(([prev, next]) =>\n testCriteria(prev),\n );\n if (filtered.length > 0) {\n if (this.options.sort) {\n const { result } = await this.fetch((res) => res);\n changes.push({\n type: \"updated\",\n result,\n });\n } else if (filtered.length !== 1) {\n throw new Error(\n \"should not match more than 1, use sort if you can have multiple match\",\n );\n } else {\n const [, next] = filtered[0]!;\n changes.push({\n type: \"updated\",\n result: testCriteria(next) ? this.transformer(next) : null!,\n });\n }\n } else if (filtered.length === 0) {\n }\n break;\n }\n default:\n throw new Error(\"Unsupported type\");\n }\n\n if (changes.length === 0) return;\n\n callback(null, changes);\n });\n\n return {\n stop: unsubscribe,\n cancel: unsubscribe,\n then: <T, U>(\n onFulfilled: () => Promise<T> | T,\n onRejected?: (error: any) => Promise<U> | U,\n ): Promise<T | U> => promise.then(onFulfilled, onRejected),\n };\n }\n\n private async createMongoCursor(): Promise<\n MongoCursor<Model, Model, KeyValue>\n > {\n const cursor = await this.store.cursor(\n this.options.criteria,\n this.options.sort,\n this.options.fields,\n );\n\n if (this.options.limit) {\n await cursor.limit(this.options.limit);\n }\n\n return cursor;\n }\n}\n","const indexOptionsConflict = 85;\nconst indexKeySpecsConflict = 86;\nconst indexNotFound = 27;\nconst namespaceNotFound = 26;\n\nconst getErrorCode = (error: unknown): unknown =>\n typeof error === \"object\" && error !== null\n ? (error as { code?: unknown }).code\n : undefined;\n\nexport const isIndexConflictError = (error: unknown): boolean => {\n const code = getErrorCode(error);\n return code === indexOptionsConflict || code === indexKeySpecsConflict;\n};\n\nexport const isIndexNotFoundError = (error: unknown): boolean =>\n getErrorCode(error) === indexNotFound;\n\nexport const isNamespaceNotFoundError = (error: unknown): boolean =>\n getErrorCode(error) === namespaceNotFound;\n","import type {\n Collection,\n Db,\n IndexDescription,\n IndexDescriptionInfo,\n} from \"mongodb\";\nimport { Logger } from \"nightingale-logger\";\nimport {\n isIndexConflictError,\n isIndexNotFoundError,\n} from \"./isIndexConflictError.ts\";\nimport type { MongoIndexPlan, MongoIndexSyncResult } from \"./types.ts\";\n\nconst logger = new Logger(\"liwi:mongo:indexes\");\n\nconst idIndexName = \"_id_\";\n\nconst serializeKey = (key: IndexDescription[\"key\"]): string =>\n JSON.stringify(key instanceof Map ? [...key.entries()] : Object.entries(key));\n\nconst findConflictingIndex = (\n existingIndexes: readonly IndexDescriptionInfo[],\n description: IndexDescription,\n): IndexDescriptionInfo | undefined => {\n const byName = existingIndexes.find(({ name }) => name === description.name);\n if (byName) return byName;\n\n const serializedKey = serializeKey(description.key);\n return existingIndexes.find(\n ({ key, name }) =>\n name !== idIndexName && serializeKey(key) === serializedKey,\n );\n};\n\ninterface CreateIndexParams {\n collection: Collection<any>;\n collectionName: string;\n description: IndexDescription;\n}\n\nconst createIndexWithConflictRecovery = async ({\n collection,\n collectionName,\n description,\n}: CreateIndexParams): Promise<void> => {\n try {\n await collection.createIndexes([description]);\n return;\n } catch (error: unknown) {\n if (!isIndexConflictError(error)) throw error;\n\n logger.warn(\"index conflict, recovering\", {\n collectionName,\n name: description.name,\n error,\n });\n\n const existingIndexes = await collection.listIndexes().toArray();\n const conflicting = findConflictingIndex(existingIndexes, description);\n if (!conflicting?.name) throw error;\n\n await collection.dropIndex(conflicting.name);\n }\n\n await collection.createIndexes([description]);\n};\n\ninterface ApplyIndexPlanParams {\n plan: MongoIndexPlan;\n collection: Collection<any>;\n db: Db;\n dryRun: boolean;\n}\n\nexport const applyIndexPlan = async ({\n plan,\n collection,\n db,\n dryRun,\n}: ApplyIndexPlanParams): Promise<MongoIndexSyncResult> => {\n const { collectionName } = plan;\n const result: MongoIndexSyncResult = {\n collectionName,\n plan,\n dryRun,\n created: [],\n dropped: [],\n modified: [],\n };\n\n if (dryRun) return result;\n\n const namesToDrop = [...plan.toDrop, ...plan.toRecreate]\n .map(({ name }) => name)\n .filter((name) => name !== idIndexName);\n\n for (const name of namesToDrop) {\n try {\n await collection.dropIndex(name);\n logger.info(\"dropIndex\", { collectionName, name });\n result.dropped.push(name);\n } catch (error: unknown) {\n if (!isIndexNotFoundError(error)) throw error;\n logger.warn(\"index already dropped\", { collectionName, name });\n }\n }\n\n for (const { name, changes } of plan.toCollMod) {\n await db.command({\n collMod: collectionName,\n index: { name, ...changes },\n });\n logger.info(\"collMod\", { collectionName, name, changes });\n result.modified.push(name);\n }\n\n const descriptions = [...plan.toCreate, ...plan.toRecreate].map(\n ({ index }) => index,\n );\n\n if (descriptions.length > 0) {\n try {\n await collection.createIndexes(descriptions);\n } catch (error: unknown) {\n logger.warn(\"createIndexes failed, retrying one by one\", {\n collectionName,\n error,\n });\n for (const description of descriptions) {\n await createIndexWithConflictRecovery({\n collection,\n collectionName,\n description,\n });\n }\n }\n result.created.push(...descriptions.map(({ name }) => name!));\n logger.info(\"createIndexes\", { collectionName, names: result.created });\n }\n\n logger.info(\"syncIndexes done\", {\n collectionName,\n created: result.created,\n dropped: result.dropped,\n modified: result.modified,\n });\n\n return result;\n};\n","const isPlainRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" &&\n value !== null &&\n !Array.isArray(value) &&\n !(value instanceof Date) &&\n !(value instanceof RegExp);\n\nexport const deepEqualUnordered = (a: unknown, b: unknown): boolean => {\n if (a === b) return true;\n\n if (a instanceof Date && b instanceof Date) {\n return a.getTime() === b.getTime();\n }\n\n if (a instanceof RegExp && b instanceof RegExp) {\n return a.source === b.source && a.flags === b.flags;\n }\n\n if (Array.isArray(a) || Array.isArray(b)) {\n if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) {\n return false;\n }\n return a.every((item, index) => deepEqualUnordered(item, b[index]));\n }\n\n if (!isPlainRecord(a) || !isPlainRecord(b)) return false;\n\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n if (keysA.length !== keysB.length) return false;\n\n return keysA.every(\n (key) =>\n Object.hasOwn(b, key) && deepEqualUnordered(a[key], (b as any)[key]),\n );\n};\n","import type { MongoIndexDirection } from \"./types.ts\";\n\nexport const buildIndexName = (\n key: Record<string, MongoIndexDirection>,\n): string =>\n Object.entries(key)\n .map(([field, direction]) => `${field}_${direction}`)\n .join(\"_\");\n","import type {\n CollationOptions,\n Document,\n IndexDescription,\n IndexDescriptionInfo,\n} from \"mongodb\";\nimport type { MongoBaseModel } from \"../MongoBaseModel.ts\";\nimport { buildIndexName } from \"./buildIndexName.ts\";\nimport type { MongoIndex, MongoIndexDirection } from \"./types.ts\";\n\nconst textDefaultLanguage = \"english\";\nconst textLanguageOverride = \"language\";\n\nexport interface NormalizedIndexOptions {\n unique: boolean;\n sparse: boolean;\n hidden: boolean;\n expireAfterSeconds?: number;\n partialFilterExpression?: Document;\n collation?: CollationOptions;\n weights?: Record<string, number>;\n defaultLanguage?: string;\n languageOverride?: string;\n wildcardProjection?: Document;\n}\n\nexport interface NormalizedIndex {\n name: string;\n key: Record<string, MongoIndexDirection>;\n keyEntries: [string, MongoIndexDirection][];\n isText: boolean;\n options: NormalizedIndexOptions;\n}\n\nexport interface NormalizedDeclaredIndex extends NormalizedIndex {\n description: IndexDescription;\n}\n\nconst buildDescription = (\n index: MongoIndex<any>,\n name: string,\n): IndexDescription => {\n const description: IndexDescription = {\n key: index.key as Record<string, MongoIndexDirection>,\n name,\n };\n\n if (index.unique !== undefined) description.unique = index.unique;\n if (index.sparse !== undefined) description.sparse = index.sparse;\n if (index.hidden !== undefined) description.hidden = index.hidden;\n if (index.expireAfterSeconds !== undefined) {\n description.expireAfterSeconds = index.expireAfterSeconds;\n }\n if (index.partialFilterExpression) {\n description.partialFilterExpression = index.partialFilterExpression;\n }\n if (index.collation) description.collation = index.collation;\n if (index.weights) description.weights = index.weights;\n if (index.default_language) {\n // eslint-disable-next-line camelcase -- mongo option name\n description.default_language = index.default_language;\n }\n if (index.language_override) {\n // eslint-disable-next-line camelcase -- mongo option name\n description.language_override = index.language_override;\n }\n if (index.wildcardProjection) {\n description.wildcardProjection = index.wildcardProjection;\n }\n\n return description;\n};\n\nexport const normalizeDeclaredIndex = <Model extends MongoBaseModel<any>>(\n index: MongoIndex<Model>,\n): NormalizedDeclaredIndex => {\n const key = index.key as Record<string, MongoIndexDirection>;\n const entries = Object.entries(key);\n\n if (entries.length === 0) {\n throw new Error(\"Invalid index: key must have at least one field\");\n }\n\n const textFields = entries\n .filter(([, direction]) => direction === \"text\")\n .map(([field]) => field);\n const isText = textFields.length > 0;\n\n const name = index.name ?? buildIndexName(key);\n const isIdOnly = entries.length === 1 && entries[0]![0] === \"_id\";\n if (name === \"_id_\" || isIdOnly) {\n throw new Error(\n \"Invalid index: _id is always indexed by mongo and cannot be declared\",\n );\n }\n\n const weights = isText\n ? {\n ...Object.fromEntries(textFields.map((field) => [field, 1])),\n ...index.weights,\n }\n : undefined;\n\n return {\n name,\n key,\n keyEntries: entries.filter(([, direction]) => direction !== \"text\"),\n isText,\n options: {\n unique: index.unique ?? false,\n sparse: index.sparse ?? false,\n hidden: index.hidden ?? false,\n expireAfterSeconds: index.expireAfterSeconds,\n partialFilterExpression: index.partialFilterExpression,\n collation: index.collation,\n weights,\n defaultLanguage: isText\n ? (index.default_language ?? textDefaultLanguage)\n : undefined,\n languageOverride: isText\n ? (index.language_override ?? textLanguageOverride)\n : undefined,\n wildcardProjection: index.wildcardProjection,\n },\n description: buildDescription(index, name),\n };\n};\n\nexport const normalizeExistingIndex = (\n existing: IndexDescriptionInfo,\n): NormalizedIndex => {\n const key = existing.key as Record<string, MongoIndexDirection>;\n const entries = Object.entries(key);\n const isText = entries.some(([field]) => field === \"_fts\");\n\n return {\n name: existing.name ?? buildIndexName(key),\n key,\n keyEntries: entries.filter(\n ([field]) => field !== \"_fts\" && field !== \"_ftsx\",\n ),\n isText,\n options: {\n unique: existing.unique ?? false,\n sparse: existing.sparse ?? false,\n hidden: existing.hidden ?? false,\n expireAfterSeconds: existing.expireAfterSeconds,\n partialFilterExpression: existing.partialFilterExpression,\n collation: existing.collation,\n weights: isText ? existing.weights : undefined,\n defaultLanguage: isText\n ? (existing.default_language ?? textDefaultLanguage)\n : undefined,\n languageOverride: isText\n ? (existing.language_override ?? textLanguageOverride)\n : undefined,\n wildcardProjection: existing.wildcardProjection,\n },\n };\n};\n\ninterface NormalizeDeclaredIndexesParams<Model extends MongoBaseModel<any>> {\n collectionName: string;\n indexes: readonly MongoIndex<Model>[];\n}\n\nexport const normalizeDeclaredIndexes = <Model extends MongoBaseModel<any>>({\n collectionName,\n indexes,\n}: NormalizeDeclaredIndexesParams<Model>): NormalizedDeclaredIndex[] => {\n const normalized = indexes.map((index) => normalizeDeclaredIndex(index));\n\n const names = new Set<string>();\n normalized.forEach(({ name }) => {\n if (names.has(name)) {\n throw new Error(\n `Duplicate index name \"${name}\" declared on collection \"${collectionName}\"`,\n );\n }\n names.add(name);\n });\n\n const textIndexes = normalized.filter(({ isText }) => isText);\n if (textIndexes.length > 1) {\n throw new Error(\n `Only one text index is allowed per collection, \"${collectionName}\" declares ${textIndexes.length}`,\n );\n }\n\n return normalized;\n};\n","import type { IndexDescriptionInfo } from \"mongodb\";\nimport type { MongoBaseModel } from \"../MongoBaseModel.ts\";\nimport { deepEqualUnordered } from \"./deepEqualUnordered.ts\";\nimport type { NormalizedIndex } from \"./normalizeIndex.ts\";\nimport {\n normalizeDeclaredIndexes,\n normalizeExistingIndex,\n} from \"./normalizeIndex.ts\";\nimport type {\n MongoIndex,\n MongoIndexCollModChanges,\n MongoIndexDifference,\n MongoIndexPlan,\n} from \"./types.ts\";\n\nconst idIndexName = \"_id_\";\n\nconst isSameKey = (\n declared: NormalizedIndex,\n existing: NormalizedIndex,\n): boolean =>\n declared.isText === existing.isText &&\n declared.keyEntries.length === existing.keyEntries.length &&\n declared.keyEntries.every(\n ([field, direction], index) =>\n existing.keyEntries[index]![0] === field &&\n existing.keyEntries[index]![1] === direction,\n );\n\nconst isSameCollation = (\n declared: NormalizedIndex[\"options\"][\"collation\"],\n existing: NormalizedIndex[\"options\"][\"collation\"],\n): boolean => {\n if (!declared) return !existing;\n if (!existing) return false;\n\n return Object.entries(declared).every(([key, value]) =>\n deepEqualUnordered(value, (existing as any)[key]),\n );\n};\n\nconst diffOptions = (\n declared: NormalizedIndex,\n existing: NormalizedIndex,\n): MongoIndexDifference[] => {\n const differences: MongoIndexDifference[] = [];\n\n const compare = (\n field: MongoIndexDifference[\"field\"],\n declaredValue: unknown,\n existingValue: unknown,\n equals: (a: unknown, b: unknown) => boolean = deepEqualUnordered,\n ): void => {\n if (!equals(declaredValue, existingValue)) {\n differences.push({\n field,\n declared: declaredValue,\n existing: existingValue,\n });\n }\n };\n\n compare(\"unique\", declared.options.unique, existing.options.unique);\n compare(\"sparse\", declared.options.sparse, existing.options.sparse);\n compare(\"hidden\", declared.options.hidden, existing.options.hidden);\n compare(\n \"expireAfterSeconds\",\n declared.options.expireAfterSeconds,\n existing.options.expireAfterSeconds,\n );\n compare(\n \"partialFilterExpression\",\n declared.options.partialFilterExpression,\n existing.options.partialFilterExpression,\n );\n compare(\n \"collation\",\n declared.options.collation,\n existing.options.collation,\n (a, b) =>\n isSameCollation(\n a as NormalizedIndex[\"options\"][\"collation\"],\n b as NormalizedIndex[\"options\"][\"collation\"],\n ),\n );\n compare(\"weights\", declared.options.weights, existing.options.weights);\n compare(\n \"default_language\",\n declared.options.defaultLanguage,\n existing.options.defaultLanguage,\n );\n compare(\n \"language_override\",\n declared.options.languageOverride,\n existing.options.languageOverride,\n );\n compare(\n \"wildcardProjection\",\n declared.options.wildcardProjection,\n existing.options.wildcardProjection,\n );\n\n return differences;\n};\n\nconst isCollModApplicable = (\n differences: readonly MongoIndexDifference[],\n): boolean =>\n differences.length > 0 &&\n differences.every(\n (difference) =>\n difference.field === \"hidden\" ||\n (difference.field === \"expireAfterSeconds\" &&\n difference.declared !== undefined &&\n difference.existing !== undefined),\n );\n\nconst buildCollModChanges = (\n differences: readonly MongoIndexDifference[],\n): MongoIndexCollModChanges => {\n const changes: MongoIndexCollModChanges = {};\n differences.forEach((difference) => {\n if (difference.field === \"hidden\") {\n changes.hidden = difference.declared as boolean;\n } else if (difference.field === \"expireAfterSeconds\") {\n changes.expireAfterSeconds = difference.declared as number;\n }\n });\n return changes;\n};\n\ninterface DiffIndexesParams<Model extends MongoBaseModel<any>> {\n collectionName: string;\n declaredIndexes: readonly MongoIndex<Model>[];\n existingIndexes: readonly IndexDescriptionInfo[];\n dropUndeclaredIndexes: boolean;\n}\n\nexport const diffIndexes = <Model extends MongoBaseModel<any>>({\n collectionName,\n declaredIndexes,\n existingIndexes,\n dropUndeclaredIndexes,\n}: DiffIndexesParams<Model>): MongoIndexPlan => {\n const declared = normalizeDeclaredIndexes({\n collectionName,\n indexes: declaredIndexes,\n });\n\n const remainingExisting = new Map<\n string,\n { normalized: NormalizedIndex; raw: IndexDescriptionInfo }\n >();\n existingIndexes.forEach((raw) => {\n const normalized = normalizeExistingIndex(raw);\n if (normalized.name === idIndexName) return;\n remainingExisting.set(normalized.name, { normalized, raw });\n });\n\n const plan: MongoIndexPlan = {\n collectionName,\n toCreate: [],\n toRecreate: [],\n toCollMod: [],\n toDrop: [],\n unchanged: [],\n undeclaredKept: [],\n };\n\n declared.forEach((declaredIndex) => {\n const existing = remainingExisting.get(declaredIndex.name);\n\n if (!existing) {\n plan.toCreate.push({\n name: declaredIndex.name,\n index: declaredIndex.description,\n });\n return;\n }\n\n remainingExisting.delete(declaredIndex.name);\n\n if (!isSameKey(declaredIndex, existing.normalized)) {\n plan.toRecreate.push({\n name: declaredIndex.name,\n index: declaredIndex.description,\n existing: existing.raw,\n differences: [\n {\n field: \"key\",\n declared: declaredIndex.key,\n existing: existing.normalized.key,\n },\n ],\n });\n return;\n }\n\n const differences = diffOptions(declaredIndex, existing.normalized);\n\n if (differences.length === 0) {\n plan.unchanged.push(declaredIndex.name);\n } else if (isCollModApplicable(differences)) {\n plan.toCollMod.push({\n name: declaredIndex.name,\n changes: buildCollModChanges(differences),\n differences,\n });\n } else {\n plan.toRecreate.push({\n name: declaredIndex.name,\n index: declaredIndex.description,\n existing: existing.raw,\n differences,\n });\n }\n });\n\n remainingExisting.forEach(({ raw }, name) => {\n if (dropUndeclaredIndexes) {\n plan.toDrop.push({ name, existing: raw });\n } else {\n plan.undeclaredKept.push(name);\n }\n });\n\n return plan;\n};\n\nexport const isMongoIndexPlanEmpty = (plan: MongoIndexPlan): boolean =>\n plan.toCreate.length === 0 &&\n plan.toRecreate.length === 0 &&\n plan.toCollMod.length === 0 &&\n plan.toDrop.length === 0;\n","import type {\n AllowedKeyValue,\n CreateQueryOptions,\n Criteria,\n Fields,\n OptionalBaseModelKeysForInsert,\n QueryParams,\n Sort,\n SubscribableStore,\n Update,\n UpsertPartialObject,\n UpsertResult,\n} from \"liwi-store\";\nimport type {\n Collection,\n Filter,\n FindCursor,\n MongoClient,\n UpdateFilter,\n} from \"mongodb\";\nimport mongodb from \"mongodb\";\nimport type {\n MongoBaseModel,\n MongoInsertType,\n MongoKeyPath,\n} from \"./MongoBaseModel.ts\";\nimport type MongoConnection from \"./MongoConnection.ts\";\nimport MongoCursor from \"./MongoCursor.ts\";\nimport MongoQueryCollection from \"./MongoQueryCollection.ts\";\nimport MongoQuerySingleItem from \"./MongoQuerySingleItem.ts\";\nimport { applyIndexPlan } from \"./indexes/applyIndexPlan.ts\";\nimport { diffIndexes } from \"./indexes/diffIndexes.ts\";\nimport { isNamespaceNotFoundError } from \"./indexes/isIndexConflictError.ts\";\nimport { normalizeDeclaredIndexes } from \"./indexes/normalizeIndex.ts\";\nimport type {\n MongoIndex,\n MongoIndexPlan,\n MongoIndexSyncResult,\n SyncIndexesOptions,\n} from \"./indexes/types.ts\";\n\nexport type MongoUpsertResult<\n KeyValue extends AllowedKeyValue,\n Model extends MongoBaseModel<KeyValue>,\n> = UpsertResult<Model>;\n\nexport interface MongoStoreOptions<Model extends MongoBaseModel<any>> {\n indexes?: readonly MongoIndex<Model>[];\n}\n\nexport default class MongoStore<\n Model extends MongoBaseModel<KeyValue>,\n KeyValue extends AllowedKeyValue = Model[MongoKeyPath],\n> implements SubscribableStore<\n MongoKeyPath,\n KeyValue,\n Model,\n MongoInsertType<Model>,\n MongoConnection\n> {\n readonly keyPath: MongoKeyPath = \"_id\";\n\n readonly connection: MongoConnection;\n\n readonly collectionName: string;\n\n private readonly declaredIndexes: readonly MongoIndex<Model>[];\n\n private _collection: Collection<Model> | Promise<Collection<Model>>;\n\n constructor(\n connection: MongoConnection,\n collectionName: string,\n { indexes = [] }: MongoStoreOptions<Model> = {},\n ) {\n this.connection = connection;\n\n if (!collectionName) {\n throw new Error(`Invalid collectionName: \"${collectionName}\"`);\n }\n\n this.collectionName = collectionName;\n this.declaredIndexes = indexes;\n normalizeDeclaredIndexes({ collectionName, indexes });\n\n this._collection = connection.getConnection().then(\n (client: MongoClient) => {\n this._collection = client.db().collection(collectionName);\n return this._collection;\n },\n (error: Error) => {\n this._collection = Promise.reject(error);\n return this._collection;\n },\n );\n }\n\n get collection(): Promise<Collection<Model>> {\n if (this.connection.connectionFailed) {\n return Promise.reject(new Error(\"MongoDB connection failed\"));\n }\n\n return Promise.resolve(this._collection);\n }\n\n async planIndexes({\n dropUndeclaredIndexes = true,\n }: SyncIndexesOptions = {}): Promise<MongoIndexPlan> {\n const collection = await this.collection;\n\n const existingIndexes = await collection\n .listIndexes()\n .toArray()\n .catch((error: unknown) => {\n if (isNamespaceNotFoundError(error)) return [];\n throw error;\n });\n\n return diffIndexes<Model>({\n collectionName: this.collectionName,\n declaredIndexes: this.declaredIndexes,\n existingIndexes,\n dropUndeclaredIndexes,\n });\n }\n\n async syncIndexes(\n options: SyncIndexesOptions = {},\n ): Promise<MongoIndexSyncResult> {\n const plan = await this.planIndexes(options);\n const collection = await this.collection;\n const client = await this.connection.getConnection();\n\n return applyIndexPlan({\n plan,\n collection: collection as Collection<any>,\n db: client.db(),\n dryRun: options.dryRun ?? false,\n });\n }\n\n createQuerySingleItem<\n Result extends Record<MongoKeyPath, KeyValue> = Model,\n Params extends QueryParams<Params> = never,\n >({\n transformer,\n ...options\n }: CreateQueryOptions<Model, Result>): MongoQuerySingleItem<\n Model,\n Params,\n Result,\n KeyValue\n > {\n return new MongoQuerySingleItem<Model, Params, Result, KeyValue>(\n this,\n options,\n transformer,\n );\n }\n\n createQueryCollection<\n Item extends Record<MongoKeyPath, KeyValue> = Model,\n Params extends QueryParams<Params> = never,\n >({\n transformer,\n ...options\n }: CreateQueryOptions<Model, Item>): MongoQueryCollection<\n Model,\n Params,\n Model[\"_id\"],\n Item\n > {\n return new MongoQueryCollection<Model, Params, KeyValue, Item>(\n this,\n options,\n transformer,\n );\n }\n\n async insertOne(object: MongoInsertType<Model>): Promise<Model> {\n if (!object._id) {\n object._id = new mongodb.ObjectId().toString() as Model[\"_id\"];\n }\n\n if (!object.created) object.created = new Date();\n if (!object.updated) object.updated = new Date();\n\n const collection = await this.collection;\n const { acknowledged: isAcknowledged } = await collection.insertOne(\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n object as any,\n );\n if (!isAcknowledged) {\n throw new Error(\"Fail to insert\");\n }\n\n return object as Model;\n }\n\n async replaceOne(object: Model): Promise<Model> {\n if (!object.updated) object.updated = new Date();\n\n const collection = await this.collection;\n await collection.replaceOne({ _id: object._id } as Filter<Model>, object);\n return object;\n }\n\n async upsertOne<\n K extends Exclude<\n keyof Model,\n MongoKeyPath | OptionalBaseModelKeysForInsert\n >,\n >(\n object: UpsertPartialObject<MongoKeyPath, KeyValue, Model, K>,\n setOnInsertPartialObject?: Update<Model>[\"$setOnInsert\"],\n ): Promise<Model> {\n const result = await this.upsertOneWithInfo(\n object,\n setOnInsertPartialObject,\n );\n return result.object;\n }\n\n async upsertOneWithInfo<\n K extends Exclude<\n keyof Model,\n MongoKeyPath | OptionalBaseModelKeysForInsert\n >,\n >(\n object: UpsertPartialObject<MongoKeyPath, KeyValue, Model, K>,\n setOnInsertPartialObject?: Update<Model>[\"$setOnInsert\"],\n ): Promise<MongoUpsertResult<KeyValue, Model>> {\n const $setOnInsert: Update<Model>[\"$setOnInsert\"] = {\n // @ts-expect-error -- created is Date as set in BaseModel\n created: object.created || new Date(),\n ...setOnInsertPartialObject,\n };\n\n if (!object.updated) {\n (object as MongoBaseModel).updated = new Date();\n }\n\n const $set: Partial<typeof object> = { ...object };\n delete $set.created;\n\n const collection = await this.collection;\n\n const prev = await collection.findOneAndUpdate(\n { _id: object._id } as Filter<Model>,\n { $set, $setOnInsert } as UpdateFilter<Model>,\n { upsert: true, returnDocument: \"before\" },\n );\n\n if (!prev) {\n Object.assign(object, $setOnInsert);\n return {\n resolvedAs: \"inserted\",\n inserted: true,\n object: object as unknown as Model,\n };\n }\n\n const next = { ...prev, ...$set };\n\n return {\n resolvedAs: \"updated\",\n inserted: false,\n object: next as Model,\n prev: prev as Model,\n };\n }\n\n replaceSeveral(objects: Model[]): Promise<Model[]> {\n return Promise.all(objects.map((object: Model) => this.replaceOne(object)));\n }\n\n async partialUpdateByKey(\n key: KeyValue,\n partialUpdate: Update<Model>,\n criteria?: Criteria<Model>,\n ): Promise<Model> {\n const collection = await this.collection;\n const commandResult = await collection.updateOne(\n { _id: key, ...criteria } as Filter<Model>,\n partialUpdate as UpdateFilter<Model>,\n );\n if (!commandResult.acknowledged) {\n console.error(commandResult);\n throw new Error(\"Update failed\");\n }\n const object = await this.findByKey(key);\n return object!;\n }\n\n partialUpdateOne(\n object: Model,\n partialUpdate: Update<Model>,\n ): Promise<Model> {\n return this.partialUpdateByKey(object._id, partialUpdate);\n }\n\n partialUpdateMany(\n criteria: Criteria<Model>,\n partialUpdate: Update<Model>,\n ): Promise<void> {\n return this.collection\n .then((collection) =>\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n collection.updateMany(criteria as Filter<Model>, partialUpdate as any),\n )\n .then((res) => undefined); // TODO return updated object\n }\n\n deleteByKey(key: KeyValue, criteria?: Criteria<Model>): Promise<void> {\n return this.collection\n .then((collection) =>\n collection.deleteOne({ _id: key, ...criteria } as Filter<Model>),\n )\n .then(() => undefined);\n }\n\n deleteOne(object: Model): Promise<void> {\n return this.deleteByKey(object._id);\n }\n\n deleteMany(selector: Criteria<Model>): Promise<void> {\n return this.collection\n .then((collection) => collection.deleteMany(selector as Filter<Model>))\n .then(() => undefined);\n }\n\n async count(filter?: Criteria<Model>): Promise<number> {\n const collection = await this.collection;\n return filter\n ? collection.countDocuments(filter as Filter<Model>)\n : collection.countDocuments();\n }\n\n async cursor<Result extends Partial<Model> = Model>(\n filter?: Criteria<Model>,\n sort?: Sort<Model>,\n fields?: Fields<Model>,\n ): Promise<MongoCursor<Model, Result, KeyValue>> {\n const collection = await this.collection;\n const findCursor = filter\n ? collection.find<Result>(filter as Filter<Model>)\n : (collection.find() as unknown as FindCursor<Result>);\n if (sort) findCursor.sort(sort);\n if (fields) findCursor.project(fields);\n return new MongoCursor<Model, Result, KeyValue>(this, findCursor);\n }\n\n async findByKey(\n key: KeyValue,\n criteria?: Criteria<Model>,\n ): Promise<Model | undefined> {\n const collection = await this.collection;\n const result = await collection.findOne<Model>({\n _id: key,\n ...criteria,\n } as Filter<Model>);\n return result || undefined;\n }\n\n findAll(criteria?: Criteria<Model>, sort?: Sort<Model>): Promise<Model[]> {\n return this.cursor<Model>(criteria, sort).then((cursor) =>\n cursor.toArray(),\n );\n }\n\n async findOne(\n filter: Criteria<Model>,\n sort?: Sort<Model>,\n ): Promise<Model | undefined> {\n const collection = await this.collection;\n const result = await collection.findOne<Model>(filter as Filter<Model>, {\n sort,\n });\n return result || undefined;\n }\n}\n","import { AbstractConnection } from \"liwi-store\";\nimport mongodb from \"mongodb\";\nimport { Logger } from \"nightingale-logger\";\n\nconst logger = new Logger(\"liwi:mongo:MongoConnection\");\n\nexport interface MongoConfig {\n host?: string;\n port?: number | string;\n database: string;\n user?: string;\n password?: string;\n authSource?: string;\n}\n\ninterface BuildMongoConnectionStringParams extends MongoConfig {\n redactCredentials: boolean;\n}\n\nexport const buildMongoConnectionString = ({\n host = \"localhost\",\n port = \"27017\",\n database,\n user,\n password,\n authSource,\n redactCredentials,\n}: BuildMongoConnectionStringParams): string =>\n `mongodb://${\n user\n ? `${\n redactCredentials\n ? `${user.slice(0, 2)}[redacted]`\n : encodeURIComponent(user)\n }:${\n redactCredentials ? \"[redacted]\" : encodeURIComponent(password ?? \"\")\n }@`\n : \"\"\n }${host}:${port}/${encodeURIComponent(database)}${\n authSource ? `?authSource=${encodeURIComponent(authSource)}` : \"\"\n }`;\n\nexport default class MongoConnection extends AbstractConnection {\n _connection?: mongodb.MongoClient;\n\n _connecting?: Promise<mongodb.MongoClient>;\n\n connectionFailed?: boolean;\n\n // TODO interface\n constructor(config: MongoConfig) {\n super();\n\n if (!config.database) {\n throw new Error(\"Missing config database\");\n }\n\n const connectionString = buildMongoConnectionString({\n ...config,\n redactCredentials: false,\n });\n const connectionStringRedacted = buildMongoConnectionString({\n ...config,\n redactCredentials: true,\n });\n\n this.connect(connectionString, connectionStringRedacted);\n }\n\n connect(connectionString: string, connectionStringRedacted: string): void {\n logger.info(\"connecting\", { connectionStringRedacted });\n\n const connectPromise = mongodb.MongoClient.connect(connectionString)\n .then((connection) => {\n logger.info(\"connected\", { connectionStringRedacted });\n connection.on(\"close\", () => {\n logger.warn(\"close\", { connectionStringRedacted });\n this.connectionFailed = true;\n this.getConnection = () => {\n throw new Error(\"MongoDB connection closed\");\n };\n });\n connection.on(\"timeout\", () => {\n logger.warn(\"timeout\", { connectionStringRedacted });\n this.connectionFailed = true;\n this.getConnection = () => {\n throw new Error(\"MongoDB connection timeout\");\n };\n });\n connection.on(\"reconnect\", () => {\n logger.warn(\"reconnect\", { connectionStringRedacted });\n this.connectionFailed = false;\n this.getConnection = () => Promise.resolve(this._connection!);\n });\n connection.on(\"error\", (err) => {\n logger.warn(\"error\", { connectionStringRedacted, err });\n });\n\n this._connection = connection;\n this._connecting = undefined;\n this.getConnection = () => Promise.resolve(this._connection!);\n return connection;\n })\n .catch((error: unknown) => {\n logger.info(\"not connected\", { connectionStringRedacted });\n console.error((error as Error).message || error);\n // throw err;\n process.nextTick(() => {\n // eslint-disable-next-line unicorn/no-process-exit\n process.exit(1);\n });\n\n throw error;\n });\n\n this.getConnection = () => Promise.resolve(connectPromise);\n this._connecting = this.getConnection();\n }\n\n getConnection(): Promise<mongodb.MongoClient> {\n throw new Error(\"call connect()\");\n }\n\n async close(): Promise<void> {\n this.getConnection = () => Promise.reject(new Error(\"Connection closed\"));\n if (this._connection) {\n await this._connection.close();\n this._connection = undefined;\n } else if (this._connecting) {\n await this._connecting;\n await this.close();\n }\n }\n}\n","import type { AllowedKeyValue } from \"liwi-store\";\nimport { SubscribeStore } from \"liwi-subscribe-store\";\nimport type {\n MongoBaseModel,\n MongoInsertType,\n MongoKeyPath,\n} from \"./MongoBaseModel\";\nimport type MongoConnection from \"./MongoConnection\";\nimport type MongoStore from \"./MongoStore\";\n\nexport default function createMongoSubscribeStore<\n Model extends MongoBaseModel<KeyValue>,\n KeyValue extends AllowedKeyValue = Model[MongoKeyPath],\n>(\n mongoStore: MongoStore<Model, KeyValue>,\n): SubscribeStore<\n MongoKeyPath,\n KeyValue,\n Model,\n MongoInsertType<Model, KeyValue>,\n MongoConnection,\n MongoStore<Model, KeyValue>\n> {\n return new SubscribeStore(mongoStore);\n}\n\nexport { type SubscribeStore } from \"liwi-subscribe-store\";\n","import { Logger } from \"nightingale-logger\";\nimport type { MongoRegistryStore } from \"./MongoRegistryStore.ts\";\nimport type {\n MongoIndexPlan,\n MongoIndexSyncResult,\n SyncIndexesOptions,\n} from \"./indexes/types.ts\";\n\nconst logger = new Logger(\"liwi:mongo:MongoRegistry\");\n\nexport interface MongoRegistryOptions {\n dropUndeclaredIndexes?: boolean;\n}\n\nexport default class MongoRegistry {\n private readonly _stores: MongoRegistryStore[];\n\n private readonly dropUndeclaredIndexes: boolean;\n\n constructor(\n stores: readonly MongoRegistryStore[] = [],\n { dropUndeclaredIndexes = true }: MongoRegistryOptions = {},\n ) {\n this._stores = [];\n this.dropUndeclaredIndexes = dropUndeclaredIndexes;\n stores.forEach((store) => this.add(store));\n }\n\n get stores(): readonly MongoRegistryStore[] {\n return this._stores;\n }\n\n add(store: MongoRegistryStore): this {\n if (this.getStore(store.collectionName)) {\n logger.warn(\"collection already registered\", {\n collectionName: store.collectionName,\n });\n }\n this._stores.push(store);\n return this;\n }\n\n remove(store: MongoRegistryStore): this {\n const index = this._stores.indexOf(store);\n if (index !== -1) this._stores.splice(index, 1);\n return this;\n }\n\n getStore(collectionName: string): MongoRegistryStore | undefined {\n return this._stores.find(\n (store) => store.collectionName === collectionName,\n );\n }\n\n private resolveOptions(options: SyncIndexesOptions = {}): SyncIndexesOptions {\n return {\n ...options,\n dropUndeclaredIndexes:\n options.dropUndeclaredIndexes ?? this.dropUndeclaredIndexes,\n };\n }\n\n private sortedStores(): MongoRegistryStore[] {\n return this._stores.toSorted((storeA, storeB) =>\n storeA.collectionName.localeCompare(storeB.collectionName),\n );\n }\n\n private async runSequentially<Result>(\n operation: string,\n run: (store: MongoRegistryStore) => Promise<Result>,\n ): Promise<Result[]> {\n const results: Result[] = [];\n const errors: unknown[] = [];\n\n for (const store of this.sortedStores()) {\n try {\n results.push(await run(store));\n } catch (error: unknown) {\n logger.error(operation, {\n collectionName: store.collectionName,\n error,\n });\n errors.push(error);\n }\n }\n\n if (errors.length > 0) {\n throw new AggregateError(errors, `${operation} failed`);\n }\n\n return results;\n }\n\n planIndexes(options?: SyncIndexesOptions): Promise<MongoIndexPlan[]> {\n const resolvedOptions = this.resolveOptions(options);\n return this.runSequentially(\"planIndexes\", (store) =>\n store.planIndexes(resolvedOptions),\n );\n }\n\n syncIndexes(options?: SyncIndexesOptions): Promise<MongoIndexSyncResult[]> {\n const resolvedOptions = this.resolveOptions(options);\n return this.runSequentially(\"syncIndexes\", (store) =>\n store.syncIndexes(resolvedOptions),\n );\n }\n}\n","import type { MongoIndexDifference, MongoIndexPlan } from \"./types.ts\";\n\nconst formatDifference = ({\n field,\n declared,\n existing,\n}: MongoIndexDifference): string =>\n `${field}: ${JSON.stringify(existing) ?? \"undefined\"} -> ${JSON.stringify(declared) ?? \"undefined\"}`;\n\nconst formatDifferences = (\n differences: readonly MongoIndexDifference[],\n): string =>\n differences.map((difference) => formatDifference(difference)).join(\", \");\n\ninterface PlanLine {\n action: string;\n name: string;\n detail: string;\n}\n\nconst buildLines = (plan: MongoIndexPlan): PlanLine[] => [\n ...plan.toCreate.map(({ name, index }) => ({\n action: \"+ create\",\n name,\n detail: JSON.stringify(index.key),\n })),\n ...plan.toRecreate.map(({ name, differences }) => ({\n action: \"~ recreate\",\n name,\n detail: formatDifferences(differences),\n })),\n ...plan.toCollMod.map(({ name, differences }) => ({\n action: \"! modify\",\n name,\n detail: formatDifferences(differences),\n })),\n ...plan.toDrop.map(({ name }) => ({ action: \"- drop\", name, detail: \"\" })),\n ...plan.undeclaredKept.map((name) => ({\n action: \"? kept\",\n name,\n detail: \"undeclared, not dropped\",\n })),\n];\n\nexport const formatIndexPlan = (plan: MongoIndexPlan): string => {\n const lines = buildLines(plan);\n const unchangedCount = plan.unchanged.length;\n\n if (lines.length === 0) {\n return `${plan.collectionName}\\n = ${unchangedCount} unchanged, nothing to do`;\n }\n\n const actionWidth = Math.max(...lines.map(({ action }) => action.length));\n const nameWidth = Math.max(...lines.map(({ name }) => name.length));\n\n const formattedLines = lines.map(\n ({ action, name, detail }) =>\n ` ${action.padEnd(actionWidth)} ${detail ? name.padEnd(nameWidth) : name}${detail ? ` ${detail}` : \"\"}`,\n );\n\n if (unchangedCount > 0) {\n formattedLines.push(` = ${unchangedCount} unchanged`);\n }\n\n return [plan.collectionName, ...formattedLines].join(\"\\n\");\n};\n\nexport const formatIndexPlans = (plans: readonly MongoIndexPlan[]): string =>\n plans.map((plan) => formatIndexPlan(plan)).join(\"\\n\");\n\nexport { isMongoIndexPlanEmpty } from \"./diffIndexes.ts\";\n","import type MongoConnection from \"../MongoConnection.ts\";\nimport type MongoRegistry from \"../MongoRegistry.ts\";\nimport { isMongoIndexPlanEmpty } from \"./diffIndexes.ts\";\nimport { formatIndexPlans } from \"./formatIndexPlan.ts\";\nimport type { MongoIndexSyncResult, SyncIndexesOptions } from \"./types.ts\";\n\nconst usage = `Usage: [plan|sync] [options]\n\n plan print the plan, changes nothing (default)\n sync apply the plan\n\n --check with plan, exit 1 when the plan is not empty\n --dry-run with sync, compute everything but apply nothing\n --keep-undeclared do not drop indexes that are not declared`;\n\nconst formatSyncResult = ({\n collectionName,\n created,\n modified,\n dropped,\n}: MongoIndexSyncResult): string =>\n `${collectionName}: ${created.length} created, ${modified.length} modified, ${dropped.length} dropped`;\n\nexport interface RunIndexesCliParams {\n registry: MongoRegistry;\n argv?: readonly string[];\n connection?: MongoConnection;\n log?: (message: string) => void;\n logError?: (message: string) => void;\n}\n\nexport const runIndexesCli = async ({\n registry,\n argv = process.argv.slice(2),\n connection,\n log = console.log,\n logError = console.error,\n}: RunIndexesCliParams): Promise<number> => {\n const command = argv.find((arg) => !arg.startsWith(\"--\")) ?? \"plan\";\n const options: SyncIndexesOptions = {\n ...(argv.includes(\"--keep-undeclared\")\n ? { dropUndeclaredIndexes: false }\n : {}),\n dryRun: argv.includes(\"--dry-run\"),\n };\n\n try {\n if (command === \"plan\") {\n const plans = await registry.planIndexes(options);\n log(formatIndexPlans(plans));\n const hasChanges = !plans.every((plan) => isMongoIndexPlanEmpty(plan));\n return argv.includes(\"--check\") && hasChanges ? 1 : 0;\n }\n\n if (command === \"sync\") {\n const results = await registry.syncIndexes(options);\n log(formatIndexPlans(results.map(({ plan }) => plan)));\n log(\n results\n .map(\n (result) =>\n `${formatSyncResult(result)}${result.dryRun ? \" (dry run, nothing applied)\" : \"\"}`,\n )\n .join(\"\\n\"),\n );\n return 0;\n }\n\n logError(`Unknown command \"${command}\".\\n\\n${usage}`);\n return 2;\n } finally {\n await connection?.close();\n }\n};\n"],"names":["identityTransformer","MingoQuery","logger","idIndexName"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "liwi-mongo",
3
- "version": "13.3.3",
3
+ "version": "13.4.0",
4
4
  "description": "mongo implementation for liwi",
5
5
  "keywords": [],
6
6
  "homepage": "https://github.com/christophehurpeau/liwi",
@@ -32,14 +32,14 @@
32
32
  }
33
33
  },
34
34
  "dependencies": {
35
- "liwi-store": "13.3.3",
36
- "liwi-subscribe-store": "13.3.3",
35
+ "liwi-store": "13.4.0",
36
+ "liwi-subscribe-store": "13.4.0",
37
37
  "mingo": "~6.2.7",
38
- "mongodb": "^7.6.0",
38
+ "mongodb": "^7.7.0",
39
39
  "nightingale-logger": "^18.2.0"
40
40
  },
41
41
  "devDependencies": {
42
- "@pob/rollup-esbuild": "10.0.0",
42
+ "@pob/rollup-esbuild": "10.1.0",
43
43
  "@typescript/native": "npm:typescript@7.0.2",
44
44
  "mongodb-memory-server-core": "11.2.0",
45
45
  "typescript": "npm:@typescript/typescript6@6.0.2"
@@ -66,8 +66,9 @@
66
66
  "build:definitions": "tsc -p tsconfig.json",
67
67
  "clean": "yarn clean:build",
68
68
  "clean:build": "pob-esbuild-clean-out dist",
69
- "lint": "pnpm run lint:eslint",
70
- "lint:eslint": "pnpm run --dir '../..' eslint --quiet 'packages/liwi-mongo'",
69
+ "lint": "pnpm run lint:oxlint && pnpm run lint:eslint",
70
+ "lint:eslint": "pnpm --dir '../..' exec eslint --quiet 'packages/liwi-mongo'",
71
+ "lint:oxlint": "pnpm --dir '../..' exec oxlint --quiet 'packages/liwi-mongo'",
71
72
  "test:integration": "LIWI_MONGO_INTEGRATION=1 TZ=UTC node --test 'src/**/*.integration.test.ts'",
72
73
  "tsc": "tsc",
73
74
  "watch": "yarn clean:build && rollup --config rollup.config.mjs --watch"
@@ -0,0 +1,75 @@
1
+ import assert from "node:assert/strict";
2
+ import { describe, it } from "node:test";
3
+ import { buildMongoConnectionString } from "./MongoConnection.ts";
4
+
5
+ describe("buildMongoConnectionString", () => {
6
+ it("uses default host and port", () => {
7
+ assert.equal(
8
+ buildMongoConnectionString({ database: "db", redactCredentials: false }),
9
+ "mongodb://localhost:27017/db",
10
+ );
11
+ });
12
+
13
+ it("includes encoded credentials", () => {
14
+ assert.equal(
15
+ buildMongoConnectionString({
16
+ host: "mongo",
17
+ port: 1234,
18
+ database: "db",
19
+ user: "user@x",
20
+ password: "p:ss",
21
+ redactCredentials: false,
22
+ }),
23
+ "mongodb://user%40x:p%3Ass@mongo:1234/db",
24
+ );
25
+ });
26
+
27
+ it("redacts credentials", () => {
28
+ assert.equal(
29
+ buildMongoConnectionString({
30
+ database: "db",
31
+ user: "username",
32
+ password: "secret",
33
+ redactCredentials: true,
34
+ }),
35
+ "mongodb://us[redacted]:[redacted]@localhost:27017/db",
36
+ );
37
+ });
38
+
39
+ it("appends authSource when provided", () => {
40
+ assert.equal(
41
+ buildMongoConnectionString({
42
+ database: "db",
43
+ user: "user",
44
+ password: "pass",
45
+ authSource: "admin",
46
+ redactCredentials: false,
47
+ }),
48
+ "mongodb://user:pass@localhost:27017/db?authSource=admin",
49
+ );
50
+ });
51
+
52
+ it("keeps authSource in redacted connection string", () => {
53
+ assert.equal(
54
+ buildMongoConnectionString({
55
+ database: "db",
56
+ user: "user",
57
+ password: "pass",
58
+ authSource: "admin",
59
+ redactCredentials: true,
60
+ }),
61
+ "mongodb://us[redacted]:[redacted]@localhost:27017/db?authSource=admin",
62
+ );
63
+ });
64
+
65
+ it("omits authSource when empty", () => {
66
+ assert.equal(
67
+ buildMongoConnectionString({
68
+ database: "db",
69
+ authSource: "",
70
+ redactCredentials: false,
71
+ }),
72
+ "mongodb://localhost:27017/db",
73
+ );
74
+ });
75
+ });
@@ -10,8 +10,36 @@ export interface MongoConfig {
10
10
  database: string;
11
11
  user?: string;
12
12
  password?: string;
13
+ authSource?: string;
13
14
  }
14
15
 
16
+ interface BuildMongoConnectionStringParams extends MongoConfig {
17
+ redactCredentials: boolean;
18
+ }
19
+
20
+ export const buildMongoConnectionString = ({
21
+ host = "localhost",
22
+ port = "27017",
23
+ database,
24
+ user,
25
+ password,
26
+ authSource,
27
+ redactCredentials,
28
+ }: BuildMongoConnectionStringParams): string =>
29
+ `mongodb://${
30
+ user
31
+ ? `${
32
+ redactCredentials
33
+ ? `${user.slice(0, 2)}[redacted]`
34
+ : encodeURIComponent(user)
35
+ }:${
36
+ redactCredentials ? "[redacted]" : encodeURIComponent(password ?? "")
37
+ }@`
38
+ : ""
39
+ }${host}:${port}/${encodeURIComponent(database)}${
40
+ authSource ? `?authSource=${encodeURIComponent(authSource)}` : ""
41
+ }`;
42
+
15
43
  export default class MongoConnection extends AbstractConnection {
16
44
  _connection?: mongodb.MongoClient;
17
45
 
@@ -20,36 +48,21 @@ export default class MongoConnection extends AbstractConnection {
20
48
  connectionFailed?: boolean;
21
49
 
22
50
  // TODO interface
23
- constructor({
24
- host = "localhost",
25
- port = "27017",
26
- database,
27
- user,
28
- password,
29
- }: MongoConfig) {
51
+ constructor(config: MongoConfig) {
30
52
  super();
31
53
 
32
- if (!database) {
54
+ if (!config.database) {
33
55
  throw new Error("Missing config database");
34
56
  }
35
57
 
36
- const buildConnectionString = (redactCredentials: boolean): string =>
37
- `mongodb://${
38
- user
39
- ? `${
40
- redactCredentials
41
- ? `${user.slice(0, 2)}[redacted]`
42
- : encodeURIComponent(user)
43
- }:${
44
- redactCredentials
45
- ? "[redacted]"
46
- : encodeURIComponent(password ?? "")
47
- }@`
48
- : ""
49
- }${host}:${port}/${encodeURIComponent(database)}`;
50
-
51
- const connectionString = buildConnectionString(false);
52
- const connectionStringRedacted = buildConnectionString(true);
58
+ const connectionString = buildMongoConnectionString({
59
+ ...config,
60
+ redactCredentials: false,
61
+ });
62
+ const connectionStringRedacted = buildMongoConnectionString({
63
+ ...config,
64
+ redactCredentials: true,
65
+ });
53
66
 
54
67
  this.connect(connectionString, connectionStringRedacted);
55
68
  }
@@ -1,6 +1,9 @@
1
1
  import assert from "node:assert/strict";
2
2
  import { beforeEach, describe, it, mock } from "node:test";
3
+ import mongodb from "mongodb";
3
4
  import type { MongoBaseModel } from "./MongoBaseModel.ts";
5
+ import MongoConnection from "./MongoConnection.ts";
6
+ import MongoStore from "./MongoStore.ts";
4
7
 
5
8
  interface TestModel extends MongoBaseModel {
6
9
  name: string;
@@ -50,29 +53,12 @@ const collection = {
50
53
  countDocuments: () => Promise.resolve(documents.length),
51
54
  };
52
55
 
53
- // eslint-disable-next-line n/no-unsupported-features/node-builtins
54
- mock.module("mongodb", {
55
- // @ts-expect-error: not yet typed
56
- exports: {
57
- default: {
58
- MongoClient: {
59
- connect: () =>
60
- Promise.resolve({
61
- on: () => undefined,
62
- db: () => ({ collection: () => collection }),
63
- }),
64
- },
65
- ObjectId: class {
66
- toString(): string {
67
- return "generated-id";
68
- }
69
- },
70
- },
71
- },
72
- });
73
-
74
- const { default: MongoConnection } = await import("./MongoConnection.ts");
75
- const { default: MongoStore } = await import("./MongoStore.ts");
56
+ mock.method(mongodb.MongoClient, "connect", () =>
57
+ Promise.resolve({
58
+ on: () => undefined,
59
+ db: () => ({ collection: () => collection }),
60
+ } as unknown as mongodb.MongoClient),
61
+ );
76
62
 
77
63
  const createStore = (): InstanceType<typeof MongoStore<TestModel>> => {
78
64
  const connection = new MongoConnection({ database: "test" });
@@ -11,7 +11,7 @@ import type {
11
11
  } from "liwi-store";
12
12
  import type { Actions } from "liwi-subscribe-store";
13
13
  import { AbstractSubscribableStoreQuery } from "liwi-subscribe-store";
14
- import mingo from "mingo";
14
+ import { Query as MingoQuery } from "mingo";
15
15
  import type {
16
16
  MongoBaseModel,
17
17
  MongoInsertType,
@@ -72,7 +72,7 @@ export default class MongoQueryCollection<
72
72
  return () => false;
73
73
  }
74
74
 
75
- const mingoQuery = new mingo.Query(this.options.criteria);
75
+ const mingoQuery = new MingoQuery(this.options.criteria);
76
76
  this.testCriteria = mingoQuery.test.bind(mingoQuery);
77
77
  }
78
78
  return this.testCriteria;
@@ -10,7 +10,7 @@ import type {
10
10
  } from "liwi-store";
11
11
  import type { Actions } from "liwi-subscribe-store";
12
12
  import { AbstractSubscribableStoreQuery } from "liwi-subscribe-store";
13
- import mingo from "mingo";
13
+ import { Query as MingoQuery } from "mingo";
14
14
  import type {
15
15
  MongoBaseModel,
16
16
  MongoInsertType,
@@ -66,7 +66,7 @@ export default class MongoQuerySingleItem<
66
66
  return () => true;
67
67
  }
68
68
 
69
- const mingoQuery = new mingo.Query(this.options.criteria);
69
+ const mingoQuery = new MingoQuery(this.options.criteria);
70
70
  this.testCriteria = mingoQuery.test.bind(mingoQuery);
71
71
  }
72
72
 
@@ -1,6 +1,9 @@
1
1
  import assert from "node:assert/strict";
2
2
  import { beforeEach, describe, it, mock } from "node:test";
3
+ import mongodb from "mongodb";
3
4
  import type { MongoBaseModel } from "./MongoBaseModel.ts";
5
+ import MongoConnection from "./MongoConnection.ts";
6
+ import MongoStore from "./MongoStore.ts";
4
7
 
5
8
  interface TestModel extends MongoBaseModel {
6
9
  label: string;
@@ -17,24 +20,12 @@ const collection = {
17
20
  },
18
21
  };
19
22
 
20
- // eslint-disable-next-line n/no-unsupported-features/node-builtins
21
- mock.module("mongodb", {
22
- // @ts-expect-error: not yet typed
23
- exports: {
24
- default: {
25
- MongoClient: {
26
- connect: () =>
27
- Promise.resolve({
28
- on: () => undefined,
29
- db: () => ({ collection: () => collection }),
30
- }),
31
- },
32
- },
33
- },
34
- });
35
-
36
- const { default: MongoConnection } = await import("./MongoConnection.ts");
37
- const { default: MongoStore } = await import("./MongoStore.ts");
23
+ mock.method(mongodb.MongoClient, "connect", () =>
24
+ Promise.resolve({
25
+ on: () => undefined,
26
+ db: () => ({ collection: () => collection }),
27
+ } as unknown as mongodb.MongoClient),
28
+ );
38
29
 
39
30
  const createStore = (): InstanceType<typeof MongoStore<TestModel>> =>
40
31
  new MongoStore<TestModel>(new MongoConnection({ database: "test" }), "tasks");
@@ -1,8 +1,12 @@
1
1
  import assert from "node:assert/strict";
2
2
  import { beforeEach, describe, it, mock } from "node:test";
3
+ import mongodb from "mongodb";
3
4
  import type { IndexDescription, IndexDescriptionInfo } from "mongodb";
4
5
  import type { MongoBaseModel } from "./MongoBaseModel.ts";
6
+ import MongoConnection from "./MongoConnection.ts";
7
+ import MongoRegistry from "./MongoRegistry.ts";
5
8
  import type { MongoStoreOptions } from "./MongoStore.ts";
9
+ import MongoStore from "./MongoStore.ts";
6
10
 
7
11
  interface TestModel extends MongoBaseModel {
8
12
  completed: boolean;
@@ -47,30 +51,12 @@ const db = {
47
51
  },
48
52
  };
49
53
 
50
- // eslint-disable-next-line n/no-unsupported-features/node-builtins
51
- mock.module("mongodb", {
52
- // @ts-expect-error: not yet typed
53
- exports: {
54
- default: {
55
- MongoClient: {
56
- connect: () =>
57
- Promise.resolve({
58
- on: () => undefined,
59
- db: () => db,
60
- }),
61
- },
62
- ObjectId: class {
63
- toString(): string {
64
- return "generated-id";
65
- }
66
- },
67
- },
68
- },
69
- });
70
-
71
- const { default: MongoConnection } = await import("./MongoConnection.ts");
72
- const { default: MongoStore } = await import("./MongoStore.ts");
73
- const { default: MongoRegistry } = await import("./MongoRegistry.ts");
54
+ mock.method(mongodb.MongoClient, "connect", () =>
55
+ Promise.resolve({
56
+ on: () => undefined,
57
+ db: () => db,
58
+ } as unknown as mongodb.MongoClient),
59
+ );
74
60
 
75
61
  const createStore = (
76
62
  options?: MongoStoreOptions<TestModel>,