Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 6 additions & 9 deletions docs/packages/node-mongo/overview.mdx
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that features will be on node-mongo beta right now, could you please rollback it?
When I publish changes, I will add these changes to the doc

Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ interface ServiceOptions {
|`escapeRegExp`|Escape `$regex` values to prevent special characters from being interpreted as patterns. |`false`|
|`collectionOptions`|MongoDB [CollectionOptions](https://mongodb.github.io/node-mongodb-native/4.10/interfaces/CollectionOptions.html)|`{}`|
|`collectionCreateOptions`|MongoDB [CreateCollectionOptions](https://mongodb.github.io/node-mongodb-native/4.10/interfaces/CreateCollectionOptions.html)|`{}`|
|`privateFields`|Fields that should be omitted from the public response.|`[]`|

### `CreateConfig`
Overrides `ServiceOptions` parameters for create operations.
Expand All @@ -222,6 +223,7 @@ Overrides `ServiceOptions` parameters for create operations.
type CreateConfig = {
validateSchema?: boolean,
publishEvents?: boolean,
mode?: 'public' | 'private',
};
```

Expand All @@ -231,6 +233,8 @@ Overrides `ServiceOptions` parameters for read operations.
```typescript
type ReadConfig = {
skipDeletedOnDocs?: boolean,
populate?: PopulateOptions | PopulateOptions[],
mode?: 'public' | 'private',
};
```

Expand All @@ -242,6 +246,7 @@ type UpdateConfig = {
skipDeletedOnDocs?: boolean,
validateSchema?: boolean,
publishEvents?: boolean,
mode?: 'public' | 'private',
};
```

Expand Down Expand Up @@ -281,19 +286,11 @@ Extending API for a single service.
```typescript
const service = db.createService<User>('users', {
schemaValidator: (obj) => schema.parseAsync(obj),
privateFields: ['passwordHash', 'signupToken', 'resetPasswordToken'],
});

const privateFields = [
'passwordHash',
'signupToken',
'resetPasswordToken',
];

const getPublic = (user: User | null) => _.omit(user, privateFields);

export default Object.assign(service, {
updateLastRequest,
getPublic,
});
```

Expand Down
6 changes: 1 addition & 5 deletions packages/node-mongo/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1046,15 +1046,11 @@ Extending API for a single service.
```typescript
const service = db.createService<User>("users", {
schemaValidator: (obj) => schema.parseAsync(obj),
privateFields: ['passwordHash', 'signupToken', 'resetPasswordToken'],
});

const privateFields = ["passwordHash", "signupToken", "resetPasswordToken"];

const getPublic = (user: User | null) => _.omit(user, privateFields);

export default Object.assign(service, {
updateLastRequest,
getPublic,
});
```

Expand Down
91 changes: 61 additions & 30 deletions packages/node-mongo/src/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import {
} from './types';

import logger from './utils/logger';
import { addUpdatedOnField, generateId } from './utils/helpers';
import { addUpdatedOnField, generateId, getPrivateFindOptions, omitPrivateFields } from './utils/helpers';
import PopulateUtil from './utils/populate';

import { inMemoryPublisher } from './events/in-memory';
Expand All @@ -45,6 +45,7 @@ const defaultOptions: ServiceOptions = {
addCreatedOnField: true,
addUpdatedOnField: true,
escapeRegExp: false,
privateFields: [],
};

const isDev = process.env.NODE_ENV === 'development';
Expand Down Expand Up @@ -239,17 +240,21 @@ class Service<T extends IDocument> {
readConfig: ReadConfig = {},
findOptions: FindOptions = {},
): Promise<(U & PopulateTypes) | U | null> {
const { mode = 'private', populate } = readConfig;

const collection = await this.getCollection<U>();

filter = this.handleReadOperations(filter, readConfig);

if (readConfig.populate) {
const docs = await this.populateAggregate<U, PopulateTypes>(collection, filter, readConfig, findOptions);
const privateFindOptions = getPrivateFindOptions({ mode, findOptions, privateFields: this.options.privateFields });

if (populate) {
const docs = await this.populateAggregate<U, PopulateTypes>(collection, filter, readConfig, privateFindOptions);

return docs[0] || null;
}

return collection.findOne<U>(filter, findOptions);
return collection.findOne<U>(filter, privateFindOptions);
}

// Method overloading for find
Expand All @@ -270,16 +275,19 @@ class Service<T extends IDocument> {
readConfig: ReadConfig & { page?: number; perPage?: number } = {},
findOptions: FindOptions = {},
): Promise<FindResult<U & PopulateTypes> | FindResult<U>> {
const { mode = 'private', populate, page, perPage } = readConfig;

const collection = await this.getCollection<U>();
const { page, perPage } = readConfig;
const hasPaging = !!page && !!perPage;

filter = this.handleReadOperations(filter, readConfig);

const privateFindOptions = getPrivateFindOptions({ mode, findOptions, privateFields: this.options.privateFields });

if (!hasPaging) {
const results = readConfig.populate
? await this.populateAggregate<U, PopulateTypes>(collection, filter, readConfig, findOptions)
: await collection.find<U>(filter, findOptions).toArray();
const results = populate
? await this.populateAggregate<U, PopulateTypes>(collection, filter, readConfig, privateFindOptions)
: await collection.find<U>(filter, privateFindOptions).toArray();

return {
pagesCount: 1,
Expand All @@ -288,13 +296,13 @@ class Service<T extends IDocument> {
};
}

findOptions.skip = (page - 1) * perPage;
findOptions.limit = perPage;
privateFindOptions.skip = (page - 1) * perPage;
privateFindOptions.limit = perPage;

const [results, count] = await Promise.all([
readConfig.populate
? this.populateAggregate<U, PopulateTypes>(collection, filter, readConfig, findOptions)
: collection.find<U>(filter, findOptions).toArray(),
populate
? this.populateAggregate<U, PopulateTypes>(collection, filter, readConfig, privateFindOptions)
: collection.find<U>(filter, privateFindOptions).toArray(),
collection.countDocuments(filter),
]);

Expand Down Expand Up @@ -347,12 +355,13 @@ class Service<T extends IDocument> {
createConfig: CreateConfig = {},
insertOneOptions: InsertOneOptions = {},
): Promise<U> => {
const { mode = 'private', publishEvents } = createConfig;
const collection = await this.getCollection<U>();

const validEntity = await this.validateCreateOperation<U>(object, createConfig);

const shouldPublishEvents = typeof createConfig.publishEvents === 'boolean'
? createConfig.publishEvents
const shouldPublishEvents = typeof publishEvents === 'boolean'
? publishEvents
: this.options.publishEvents;

if (shouldPublishEvents) {
Expand All @@ -376,22 +385,28 @@ class Service<T extends IDocument> {
await collection.insertOne(validEntity as OptionalUnlessRequiredId<U>, insertOneOptions);
}

return validEntity;
if (mode === 'public') {
return validEntity;
}

return omitPrivateFields<U>(validEntity, this.options.privateFields);
};

insertMany = async <U extends T = T>(
objects: Partial<U>[],
createConfig: CreateConfig = {},
bulkWriteOptions: BulkWriteOptions = {},
): Promise<U[]> => {
): Promise<Array<U>> => {
const { mode = 'private', publishEvents } = createConfig;

const collection = await this.getCollection<U>();

const validEntities = await Promise.all(objects.map(
(o) => this.validateCreateOperation<U>(o, createConfig),
));

const shouldPublishEvents = typeof createConfig.publishEvents === 'boolean'
? createConfig.publishEvents
const shouldPublishEvents = typeof publishEvents === 'boolean'
? publishEvents
: this.options.publishEvents;

if (shouldPublishEvents) {
Expand All @@ -415,7 +430,11 @@ class Service<T extends IDocument> {
await collection.insertMany(validEntities as OptionalUnlessRequiredId<U>[], bulkWriteOptions);
}

return validEntities;
if (mode === 'public') {
return validEntities;
}

return validEntities.map((doc) => omitPrivateFields<U>(doc, this.options.privateFields));
};

replaceOne = async (
Expand Down Expand Up @@ -455,6 +474,8 @@ class Service<T extends IDocument> {
updateConfig: UpdateConfig = {},
updateOptions: UpdateOptions = {},
): Promise<U | null> {
const { mode = 'private', validateSchema, publishEvents } = updateConfig;

const collection = await this.getCollection<U>();

filter = this.handleReadOperations(filter, updateConfig);
Expand Down Expand Up @@ -515,16 +536,16 @@ class Service<T extends IDocument> {
updateFilter = _.merge(updateFilter, { $set: { updatedOn: updatedOnDate } });
}

const shouldValidateSchema = typeof updateConfig.validateSchema === 'boolean'
? updateConfig.validateSchema
const shouldValidateSchema = typeof validateSchema === 'boolean'
? validateSchema
: Boolean(this.options.schemaValidator);

if (shouldValidateSchema) {
await this.validateSchema(newDoc);
}

const shouldPublishEvents = typeof updateConfig.publishEvents === 'boolean'
? updateConfig.publishEvents
const shouldPublishEvents = typeof publishEvents === 'boolean'
? publishEvents
: this.options.publishEvents;

if (shouldPublishEvents) {
Expand Down Expand Up @@ -556,7 +577,11 @@ class Service<T extends IDocument> {
);
}

return newDoc;
if (mode === 'public') {
return newDoc;
}

return omitPrivateFields<U>(newDoc, this.options.privateFields);
}

updateMany<U extends T = T>(
Expand All @@ -579,6 +604,8 @@ class Service<T extends IDocument> {
updateConfig: UpdateConfig = {},
updateOptions: UpdateOptions = {},
): Promise<U[]> {
const { mode = 'private', validateSchema, publishEvents } = updateConfig;

const collection = await this.getCollection<U>();

filter = this.handleReadOperations(filter, updateConfig);
Expand Down Expand Up @@ -654,8 +681,8 @@ class Service<T extends IDocument> {
});
}

const shouldValidateSchema = typeof updateConfig.validateSchema === 'boolean'
? updateConfig.validateSchema
const shouldValidateSchema = typeof validateSchema === 'boolean'
? validateSchema
: Boolean(this.options.schemaValidator);

if (shouldValidateSchema) {
Expand All @@ -676,8 +703,8 @@ class Service<T extends IDocument> {
},
);

const shouldPublishEvents = typeof updateConfig.publishEvents === 'boolean'
? updateConfig.publishEvents
const shouldPublishEvents = typeof publishEvents === 'boolean'
? publishEvents
: this.options.publishEvents;

if (shouldPublishEvents) {
Expand All @@ -701,7 +728,11 @@ class Service<T extends IDocument> {
await collection.bulkWrite(bulkWriteQuery, updateOptions);
}

return updated.map((u) => u?.doc) as U[];
if (mode === 'public') {
return updated.map((u) => u?.doc) as U[];
}

return updated.map((u) => omitPrivateFields<U>(u?.doc as U, this.options.privateFields)) as U[];
}

deleteOne = async <U extends T = T>(
Expand Down
Loading
Loading