@atscript/mongo 0.1.34 → 0.1.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,40 +1,6 @@
1
+ import { getKeyProps, BaseDbAdapter, WithRelation, TDbRelation, TDbForeignKey, TTableResolver, FilterExpr, TDbUpdateResult, TSearchIndexInfo, DbQuery, TDbInsertResult, TDbInsertManyResult, TDbDeleteResult, TColumnDiff, TSyncColumnResult, DbSpace } from '@atscript/utils-db';
1
2
  import { TAtscriptAnnotatedType, TValidatorOptions, Validator, TValidatorPlugin, TMetadataMap } from '@atscript/typescript/utils';
2
- import { DbSpace, getKeyProps, BaseDbAdapter, AtscriptDbTable, FilterExpr, TDbUpdateResult, TSearchIndexInfo, DbQuery, TDbInsertResult, TDbInsertManyResult, TDbDeleteResult } from '@atscript/utils-db';
3
- import * as mongodb from 'mongodb';
4
- import { MongoClient, Filter, UpdateFilter, Document, UpdateOptions, Db, Collection, AggregationCursor, ObjectId } from 'mongodb';
5
-
6
- interface TGenericLogger {
7
- error(...messages: any[]): void;
8
- warn(...messages: any[]): void;
9
- log(...messages: any[]): void;
10
- info(...messages: any[]): void;
11
- debug(...messages: any[]): void;
12
- }
13
-
14
- /**
15
- * MongoDB database space — extends {@link DbSpace} with MongoDB-specific
16
- * features (cached collection list, `Db` access, `MongoAdapter` factory).
17
- *
18
- * ```typescript
19
- * const asMongo = new AsMongo('mongodb://localhost:27017/mydb')
20
- * const users = asMongo.getTable(UsersType)
21
- * const posts = asMongo.getTable(PostsType)
22
- * // Relation loading via $with works automatically
23
- * ```
24
- */
25
- declare class AsMongo extends DbSpace {
26
- readonly client: MongoClient;
27
- constructor(client: string | MongoClient, logger?: TGenericLogger);
28
- get db(): mongodb.Db;
29
- protected collectionsList?: Promise<Set<string>>;
30
- protected getCollectionsList(): Promise<Set<string>>;
31
- collectionExists(name: string): Promise<boolean>;
32
- /**
33
- * Returns the MongoAdapter for the given type.
34
- * Convenience accessor for Mongo-specific adapter operations.
35
- */
36
- getAdapter(type: TAtscriptAnnotatedType): MongoAdapter;
37
- }
3
+ import { Filter, UpdateFilter, Document, UpdateOptions, Db, MongoClient, ClientSession, Collection, AggregationCursor, ObjectId } from 'mongodb';
38
4
 
39
5
  /**
40
6
  * Context interface for CollectionPatcher.
@@ -71,16 +37,6 @@ declare class CollectionPatcher {
71
37
  private payload;
72
38
  constructor(collection: TCollectionPatcherContext, payload: any);
73
39
  static getKeyProps: typeof getKeyProps;
74
- /**
75
- * Build a runtime *Validator* that understands the extended patch payload.
76
- *
77
- * * Adds per‑array *patch* wrappers (the `$replace`, `$insert`, … fields).
78
- * * Honors `db.patch.strategy === "merge"` metadata.
79
- *
80
- * @param collection Target collection wrapper
81
- * @returns Atscript Validator
82
- */
83
- static prepareValidator(context: TCollectionPatcherContext): Validator<any, unknown>;
84
40
  /**
85
41
  * Internal accumulator: filter passed to `updateOne()`.
86
42
  * Filled only with the `_id` field right now.
@@ -192,7 +148,7 @@ interface TSearchIndex {
192
148
  type TMongoIndex = TPlainIndex | TSearchIndex;
193
149
  declare class MongoAdapter extends BaseDbAdapter {
194
150
  protected readonly db: Db;
195
- protected readonly asMongo?: AsMongo | undefined;
151
+ protected readonly client?: MongoClient | undefined;
196
152
  private _collection?;
197
153
  /** MongoDB-specific indexes (search, vector) — separate from table.indexes. */
198
154
  protected _mongoIndexes: Map<string, TMongoIndex>;
@@ -202,7 +158,25 @@ declare class MongoAdapter extends BaseDbAdapter {
202
158
  protected _searchIndexesMap?: Map<string, TMongoIndex>;
203
159
  /** Physical field names with @db.default.fn "increment". */
204
160
  protected _incrementFields: Set<string>;
205
- constructor(db: Db, asMongo?: AsMongo | undefined);
161
+ /** Capped collection options from @db.mongo.capped. */
162
+ protected _cappedOptions?: {
163
+ size: number;
164
+ max?: number;
165
+ };
166
+ /** Whether the schema explicitly defines _id (via @db.mongo.collection or manual _id field). */
167
+ protected _hasExplicitId: boolean;
168
+ constructor(db: Db, client?: MongoClient | undefined);
169
+ private get _client();
170
+ /** Whether transaction support has been detected as unavailable (standalone MongoDB). */
171
+ private _txDisabled;
172
+ protected _beginTransaction(): Promise<unknown>;
173
+ protected _commitTransaction(state: unknown): Promise<void>;
174
+ protected _rollbackTransaction(state: unknown): Promise<void>;
175
+ private static readonly _noSession;
176
+ /** Returns `{ session }` opts if inside a transaction, empty object otherwise. */
177
+ protected _getSessionOpts(): {
178
+ session: ClientSession;
179
+ } | Record<string, never>;
206
180
  get collection(): Collection<any>;
207
181
  aggregate(pipeline: Document[]): AggregationCursor;
208
182
  get idType(): 'string' | 'number' | 'objectId';
@@ -215,10 +189,35 @@ declare class MongoAdapter extends BaseDbAdapter {
215
189
  supportsNestedObjects(): boolean;
216
190
  supportsNativePatch(): boolean;
217
191
  getValidatorPlugins(): TValidatorPlugin[];
218
- getTopLevelArrayTag(): string;
219
192
  getAdapterTableName(type: TAtscriptAnnotatedType): string | undefined;
220
- buildInsertValidator(table: AtscriptDbTable): any;
221
- buildPatchValidator(table: AtscriptDbTable): any;
193
+ supportsNativeRelations(): boolean;
194
+ loadRelations(rows: Array<Record<string, unknown>>, withRelations: WithRelation[], relations: ReadonlyMap<string, TDbRelation>, foreignKeys: ReadonlyMap<string, TDbForeignKey>, tableResolver?: TTableResolver): Promise<void>;
195
+ /** Builds a $match filter to re-select source rows by PK. */
196
+ private _buildPKMatchFilter;
197
+ /** Dispatches to the correct $lookup builder based on relation direction. */
198
+ private _buildRelationLookup;
199
+ /** Builds `let` variable bindings and the corresponding `$expr` match for `$lookup`. */
200
+ private _buildLookupJoin;
201
+ /** $lookup for TO relations (FK is on this table → target). Always single-valued. */
202
+ private _buildToLookup;
203
+ /** $lookup for FROM relations (FK is on target → this table). */
204
+ private _buildFromLookup;
205
+ /** $lookup for VIA relations (M:N through junction table). Always array. */
206
+ private _buildViaLookup;
207
+ /** Builds inner pipeline stages for relation controls ($sort, $limit, $skip, $select, filter). */
208
+ private _buildLookupInnerPipeline;
209
+ /** Extracts nested $with from a WithRelation's controls. */
210
+ private _extractNestedWith;
211
+ /** Post-processes nested $with by delegating to the target table's own relation loading. */
212
+ private _loadNestedRelations;
213
+ /** Merges aggregation results back onto the original rows by PK. */
214
+ private _mergeRelationResults;
215
+ /** Finds FK entry for a TO relation from this table's foreignKeys map. */
216
+ private _findFKForRelationLookup;
217
+ /** Finds a FK on a remote table that points back to the given table name. */
218
+ private _findRemoteFKFromMeta;
219
+ /** Resolves the target table/collection name from a relation's target type. */
220
+ private _resolveRelTargetTableName;
222
221
  /** Returns the context object used by CollectionPatcher. */
223
222
  getPatcherContext(): TCollectionPatcherContext;
224
223
  nativePatch(filter: FilterExpr, patch: unknown): Promise<TDbUpdateResult>;
@@ -235,12 +234,12 @@ declare class MongoAdapter extends BaseDbAdapter {
235
234
  * Builds a MongoDB `$search` pipeline stage.
236
235
  * Override `buildVectorSearchStage` in subclasses to provide embeddings.
237
236
  */
238
- protected buildSearchStage(text: string, indexName?: string): Document | undefined;
237
+ protected buildSearchStage(text: string, indexName?: string): Promise<Document | undefined>;
239
238
  /**
240
239
  * Builds a vector search stage. Override in subclasses to generate embeddings.
241
240
  * Returns `undefined` by default (vector search requires custom implementation).
242
241
  */
243
- protected buildVectorSearchStage(text: string, index: TMongoIndex): Document | undefined;
242
+ protected buildVectorSearchStage(text: string, index: TMongoIndex): Promise<Document | undefined>;
244
243
  search(text: string, query: DbQuery, indexName?: string): Promise<Array<Record<string, unknown>>>;
245
244
  searchWithCount(text: string, query: DbQuery, indexName?: string): Promise<{
246
245
  data: Array<Record<string, unknown>>;
@@ -252,6 +251,11 @@ declare class MongoAdapter extends BaseDbAdapter {
252
251
  }>;
253
252
  collectionExists(): Promise<boolean>;
254
253
  ensureCollectionExists(): Promise<void>;
254
+ /**
255
+ * Wraps an async operation to catch MongoDB duplicate key errors
256
+ * (code 11000) and rethrow as structured `DbError`.
257
+ */
258
+ private _wrapDuplicateKeyError;
255
259
  insertOne(data: Record<string, unknown>): Promise<TDbInsertResult>;
256
260
  insertMany(data: Array<Record<string, unknown>>): Promise<TDbInsertManyResult>;
257
261
  findOne(query: DbQuery): Promise<Record<string, unknown> | null>;
@@ -263,12 +267,64 @@ declare class MongoAdapter extends BaseDbAdapter {
263
267
  updateMany(filter: FilterExpr, data: Record<string, unknown>): Promise<TDbUpdateResult>;
264
268
  replaceMany(filter: FilterExpr, data: Record<string, unknown>): Promise<TDbUpdateResult>;
265
269
  deleteMany(filter: FilterExpr): Promise<TDbDeleteResult>;
270
+ tableExists(): Promise<boolean>;
271
+ detectTableOptionDrift(): Promise<boolean>;
266
272
  ensureTable(): Promise<void>;
273
+ /**
274
+ * Creates a MongoDB view from the AtscriptDbView's view plan.
275
+ * Translates joins → $lookup/$unwind, filter → $match, columns → $project.
276
+ */
277
+ private _ensureView;
278
+ /**
279
+ * Extracts localField/foreignField from a join condition like `User.id = Task.assigneeId`.
280
+ * The condition is a comparison node with two field refs.
281
+ */
282
+ private _resolveJoinFields;
283
+ /**
284
+ * Translates an AtscriptQueryNode to a MongoDB $match expression.
285
+ * Field refs are resolved to dot-path references (joined fields use JOINED_PREFIX).
286
+ */
287
+ private _queryNodeToMatch;
288
+ /**
289
+ * Resolves a field ref to a MongoDB dot path for view pipeline expressions.
290
+ */
291
+ private _resolveViewFieldPath;
292
+ dropTable(): Promise<void>;
293
+ dropViewByName(viewName: string): Promise<void>;
294
+ dropTableByName(tableName: string): Promise<void>;
295
+ recreateTable(): Promise<void>;
296
+ syncColumns(diff: TColumnDiff): Promise<TSyncColumnResult>;
297
+ dropColumns(columns: string[]): Promise<void>;
298
+ renameTable(oldName: string): Promise<void>;
299
+ /**
300
+ * Resolves a field's default value for bulk $set during column sync.
301
+ * Returns `undefined` if no concrete default can be determined.
302
+ */
303
+ private _resolveSyncDefault;
267
304
  syncIndexes(): Promise<void>;
305
+ /** Cached physical name of the single @meta.id field, or null if none/composite. */
306
+ private _metaIdPhysical;
307
+ /**
308
+ * Returns the physical column name of the single @meta.id field (if any).
309
+ * Used to return the user's logical ID instead of MongoDB's _id on insert.
310
+ */
311
+ private _getMetaIdPhysical;
312
+ /** Returns the counters collection used for atomic auto-increment. */
313
+ protected get _countersCollection(): Collection<{
314
+ _id: string;
315
+ seq: number;
316
+ }>;
268
317
  /** Returns physical field names of increment fields that are undefined in the data. */
269
318
  private _fieldsNeedingIncrement;
270
- /** Reads current max value for each field via $group aggregation. */
271
- private _getMaxValues;
319
+ /**
320
+ * Atomically allocates `count` sequential values for each increment field
321
+ * using a counter collection. Returns a map of field → first allocated value.
322
+ */
323
+ private _allocateIncrementValues;
324
+ /** Reads current max value for a single field via $group aggregation. */
325
+ private _getCurrentFieldMax;
326
+ /** Allocates increment values for a batch of items, assigning in order. */
327
+ private _assignBatchIncrements;
272
328
  private _buildFindOptions;
273
329
  protected _addMongoIndexField(type: TPlainIndex['type'], name: string, field: string, weight?: number): void;
274
330
  protected _setSearchIndex(type: TSearchIndex['type'], name: string | undefined, definition: TMongoSearchIndexDefinition): void;
@@ -308,5 +364,7 @@ declare function buildMongoFilter(filter: FilterExpr): Filter<any>;
308
364
 
309
365
  declare const validateMongoIdPlugin: TValidatorPlugin;
310
366
 
311
- export { AsMongo, CollectionPatcher, MongoAdapter, buildMongoFilter, validateMongoIdPlugin };
367
+ declare function createAdapter(connection: string, _options?: Record<string, unknown>): DbSpace;
368
+
369
+ export { CollectionPatcher, MongoAdapter, buildMongoFilter, createAdapter, validateMongoIdPlugin };
312
370
  export type { TCollectionPatcherContext, TMongoIndex, TMongoSearchIndexDefinition, TPlainIndex, TSearchIndex };