@atscript/mongo 0.1.35 → 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,15 +1,6 @@
1
- import * as mongodb from 'mongodb';
2
- import { Filter, UpdateFilter, Document, UpdateOptions, Db, ClientSession, Collection, AggregationCursor, ObjectId, MongoClient } from 'mongodb';
1
+ import { getKeyProps, BaseDbAdapter, WithRelation, TDbRelation, TDbForeignKey, TTableResolver, FilterExpr, TDbUpdateResult, TSearchIndexInfo, DbQuery, TDbInsertResult, TDbInsertManyResult, TDbDeleteResult, TColumnDiff, TSyncColumnResult, DbSpace } from '@atscript/utils-db';
3
2
  import { TAtscriptAnnotatedType, TValidatorOptions, Validator, TValidatorPlugin, TMetadataMap } from '@atscript/typescript/utils';
4
- import { getKeyProps, BaseDbAdapter, AtscriptDbTable, FilterExpr, TDbUpdateResult, TSearchIndexInfo, DbQuery, TDbInsertResult, TDbInsertManyResult, TDbDeleteResult, DbSpace } from '@atscript/utils-db';
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
- }
3
+ import { Filter, UpdateFilter, Document, UpdateOptions, Db, MongoClient, ClientSession, Collection, AggregationCursor, ObjectId } from 'mongodb';
13
4
 
14
5
  /**
15
6
  * Context interface for CollectionPatcher.
@@ -46,16 +37,6 @@ declare class CollectionPatcher {
46
37
  private payload;
47
38
  constructor(collection: TCollectionPatcherContext, payload: any);
48
39
  static getKeyProps: typeof getKeyProps;
49
- /**
50
- * Build a runtime *Validator* that understands the extended patch payload.
51
- *
52
- * * Adds per‑array *patch* wrappers (the `$replace`, `$insert`, … fields).
53
- * * Honors `db.patch.strategy === "merge"` metadata.
54
- *
55
- * @param collection Target collection wrapper
56
- * @returns Atscript Validator
57
- */
58
- static prepareValidator(context: TCollectionPatcherContext): Validator<any, unknown>;
59
40
  /**
60
41
  * Internal accumulator: filter passed to `updateOne()`.
61
42
  * Filled only with the `_id` field right now.
@@ -167,7 +148,7 @@ interface TSearchIndex {
167
148
  type TMongoIndex = TPlainIndex | TSearchIndex;
168
149
  declare class MongoAdapter extends BaseDbAdapter {
169
150
  protected readonly db: Db;
170
- protected readonly asMongo?: AsMongo | undefined;
151
+ protected readonly client?: MongoClient | undefined;
171
152
  private _collection?;
172
153
  /** MongoDB-specific indexes (search, vector) — separate from table.indexes. */
173
154
  protected _mongoIndexes: Map<string, TMongoIndex>;
@@ -182,7 +163,9 @@ declare class MongoAdapter extends BaseDbAdapter {
182
163
  size: number;
183
164
  max?: number;
184
165
  };
185
- constructor(db: Db, asMongo?: AsMongo | undefined);
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);
186
169
  private get _client();
187
170
  /** Whether transaction support has been detected as unavailable (standalone MongoDB). */
188
171
  private _txDisabled;
@@ -206,10 +189,35 @@ declare class MongoAdapter extends BaseDbAdapter {
206
189
  supportsNestedObjects(): boolean;
207
190
  supportsNativePatch(): boolean;
208
191
  getValidatorPlugins(): TValidatorPlugin[];
209
- getTopLevelArrayTag(): string;
210
192
  getAdapterTableName(type: TAtscriptAnnotatedType): string | undefined;
211
- buildInsertValidator(table: AtscriptDbTable): any;
212
- 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;
213
221
  /** Returns the context object used by CollectionPatcher. */
214
222
  getPatcherContext(): TCollectionPatcherContext;
215
223
  nativePatch(filter: FilterExpr, patch: unknown): Promise<TDbUpdateResult>;
@@ -226,12 +234,12 @@ declare class MongoAdapter extends BaseDbAdapter {
226
234
  * Builds a MongoDB `$search` pipeline stage.
227
235
  * Override `buildVectorSearchStage` in subclasses to provide embeddings.
228
236
  */
229
- protected buildSearchStage(text: string, indexName?: string): Document | undefined;
237
+ protected buildSearchStage(text: string, indexName?: string): Promise<Document | undefined>;
230
238
  /**
231
239
  * Builds a vector search stage. Override in subclasses to generate embeddings.
232
240
  * Returns `undefined` by default (vector search requires custom implementation).
233
241
  */
234
- protected buildVectorSearchStage(text: string, index: TMongoIndex): Document | undefined;
242
+ protected buildVectorSearchStage(text: string, index: TMongoIndex): Promise<Document | undefined>;
235
243
  search(text: string, query: DbQuery, indexName?: string): Promise<Array<Record<string, unknown>>>;
236
244
  searchWithCount(text: string, query: DbQuery, indexName?: string): Promise<{
237
245
  data: Array<Record<string, unknown>>;
@@ -243,6 +251,11 @@ declare class MongoAdapter extends BaseDbAdapter {
243
251
  }>;
244
252
  collectionExists(): Promise<boolean>;
245
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;
246
259
  insertOne(data: Record<string, unknown>): Promise<TDbInsertResult>;
247
260
  insertMany(data: Array<Record<string, unknown>>): Promise<TDbInsertManyResult>;
248
261
  findOne(query: DbQuery): Promise<Record<string, unknown> | null>;
@@ -254,13 +267,64 @@ declare class MongoAdapter extends BaseDbAdapter {
254
267
  updateMany(filter: FilterExpr, data: Record<string, unknown>): Promise<TDbUpdateResult>;
255
268
  replaceMany(filter: FilterExpr, data: Record<string, unknown>): Promise<TDbUpdateResult>;
256
269
  deleteMany(filter: FilterExpr): Promise<TDbDeleteResult>;
270
+ tableExists(): Promise<boolean>;
271
+ detectTableOptionDrift(): Promise<boolean>;
257
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;
258
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;
259
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
+ }>;
260
317
  /** Returns physical field names of increment fields that are undefined in the data. */
261
318
  private _fieldsNeedingIncrement;
262
- /** Reads current max value for each field via $group aggregation. */
263
- 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;
264
328
  private _buildFindOptions;
265
329
  protected _addMongoIndexField(type: TPlainIndex['type'], name: string, field: string, weight?: number): void;
266
330
  protected _setSearchIndex(type: TSearchIndex['type'], name: string | undefined, definition: TMongoSearchIndexDefinition): void;
@@ -289,31 +353,6 @@ interface TMongoSearchIndexDefinition {
289
353
  };
290
354
  }
291
355
 
292
- /**
293
- * MongoDB database space — extends {@link DbSpace} with MongoDB-specific
294
- * features (cached collection list, `Db` access, `MongoAdapter` factory).
295
- *
296
- * ```typescript
297
- * const asMongo = new AsMongo('mongodb://localhost:27017/mydb')
298
- * const users = asMongo.getTable(UsersType)
299
- * const posts = asMongo.getTable(PostsType)
300
- * // Relation loading via $with works automatically
301
- * ```
302
- */
303
- declare class AsMongo extends DbSpace {
304
- readonly client: MongoClient;
305
- constructor(client: string | MongoClient, logger?: TGenericLogger);
306
- get db(): mongodb.Db;
307
- protected collectionsList?: Promise<Set<string>>;
308
- protected getCollectionsList(): Promise<Set<string>>;
309
- collectionExists(name: string): Promise<boolean>;
310
- /**
311
- * Returns the MongoAdapter for the given type.
312
- * Convenience accessor for Mongo-specific adapter operations.
313
- */
314
- getAdapter(type: TAtscriptAnnotatedType): MongoAdapter;
315
- }
316
-
317
356
  /**
318
357
  * Translates a generic {@link FilterExpr} into a MongoDB-compatible
319
358
  * {@link Filter} document.
@@ -325,7 +364,7 @@ declare function buildMongoFilter(filter: FilterExpr): Filter<any>;
325
364
 
326
365
  declare const validateMongoIdPlugin: TValidatorPlugin;
327
366
 
328
- declare function createAdapter(connection: string, _options?: Record<string, unknown>): AsMongo;
367
+ declare function createAdapter(connection: string, _options?: Record<string, unknown>): DbSpace;
329
368
 
330
- export { AsMongo, CollectionPatcher, MongoAdapter, buildMongoFilter, createAdapter, validateMongoIdPlugin };
369
+ export { CollectionPatcher, MongoAdapter, buildMongoFilter, createAdapter, validateMongoIdPlugin };
331
370
  export type { TCollectionPatcherContext, TMongoIndex, TMongoSearchIndexDefinition, TPlainIndex, TSearchIndex };