diff --git a/src/messages.ts b/src/messages.ts new file mode 100644 index 0000000..dfe909f --- /dev/null +++ b/src/messages.ts @@ -0,0 +1,62 @@ +/** + * Centralized error messages and warnings for the DataSync MongoDB SDK + * This file contains all user-facing messages for consistency and maintainability + */ + +export const ErrorMessages = { + // Configuration errors + INVALID_MONGODB_URI: (uri: any) => `MongoDB connection URL: ${uri} must be of type string`, + INVALID_DBNAME: 'Content store dbName should be of type string and not empty', + + // Sorting errors + INVALID_ASCENDING_PARAMS: 'Invalid parameters for .ascending(). Expected a valid string field name', + INVALID_DESCENDING_PARAMS: 'Invalid parameters for .descending(). Expected a valid string field name', + + // Language errors + INVALID_LANGUAGE_PARAMS: 'Invalid parameters for .language(). Expected a valid language code string', + + // Logical operator errors + INVALID_AND_PARAMS: 'Invalid parameters for .and(). Expected an array of query objects', + INVALID_OR_PARAMS: 'Invalid parameters for .or(). Expected an array of query objects', + + // Comparison operator errors + INVALID_LESSTHAN_PARAMS: 'Invalid key or value parameters for .lessThan(). Expected a string key and a value', + INVALID_LESSTHAN_OR_EQUAL_PARAMS: 'Invalid key or value parameters for .lessThanOrEqualTo(). Expected a string key and a value', + INVALID_GREATERTHAN_PARAMS: 'Invalid key or value parameters for .greaterThan(). Expected a string key and a value', + INVALID_GREATERTHAN_OR_EQUAL_PARAMS: 'Invalid key or value parameters for .greaterThanOrEqualTo(). Expected a string key and a value', + INVALID_NOTEQUAL_PARAMS: 'Invalid key or value parameters for .notEqualTo(). Expected a string key and a value', + INVALID_CONTAINED_IN_PARAMS: 'Invalid key or value parameters for .containedIn(). Expected a string key and an array value', + INVALID_NOT_CONTAINED_IN_PARAMS: 'Invalid key or value parameters for .notContainedIn(). Expected a string key and an array value', + INVALID_EXISTS_PARAMS: 'Invalid key parameter for .exists(). Expected a valid string field name', + INVALID_NOT_EXISTS_PARAMS: 'Invalid key parameter for .notExists(). Expected a valid string field name', + + // Content type errors + MISSING_CONTENT_TYPE_UID: 'Content type UID is required. Please provide a valid content type UID', + MISSING_CONTENT_TYPE_FOR_ENTRY: 'Please call .contentType() before .entry()', + MISSING_CONTENT_TYPE_FOR_ENTRIES: 'Please call .contentType() before .entries()', + + // Pagination errors + INVALID_LIMIT_VALUE: 'Invalid value for .limit(). Expected a positive numeric value', + INVALID_SKIP_VALUE: 'Invalid value for .skip(). Expected a non-negative numeric value', + + // Projection errors + INVALID_ONLY_PARAMS: 'Invalid field values for .only(). Expected a non-empty array of field names', + INVALID_EXCEPT_PARAMS: 'Invalid field values for .except(). Expected a non-empty array of field names', + + // Query errors + INVALID_REGEX_PARAMS: 'Invalid field or pattern parameters for .regex(). Expected string values for both field and pattern', + INVALID_TAGS_PARAMS: 'Invalid field values for .tags(). Expected an array of tag values', + INVALID_WHERE_PARAMS: 'Invalid expression for .where(). Expected a valid expression or function', + INVALID_QUERY_REFERENCES_PARAMS: 'Invalid query object for .queryReferences(). Expected a valid query object', + INVALID_INCLUDE_PARAMS: 'Invalid reference field path for .include(). Expected a valid string or array of strings', + + // Query validation errors + INVALID_QUERY: 'Invalid query provided. Please ensure your query is properly formatted', + INVALID_QUERIES: 'Invalid queries provided. Please ensure all queries are properly formatted', +} as const + +export const WarningMessages = { + // Performance warnings + SLOW_INCLUDE_REFERENCES: '.includeReferences(...) is a relatively slow query. Consider limiting the depth or using .include() for specific references', +} as const + diff --git a/src/stack.ts b/src/stack.ts index 814ccf8..5a0488b 100644 --- a/src/stack.ts +++ b/src/stack.ts @@ -23,6 +23,10 @@ import { validateConfig, validateURI, } from './util' +import { + ErrorMessages, + WarningMessages, +} from './messages' interface IShelf { path: string, @@ -102,7 +106,7 @@ export class Stack { */ public ascending(field) { if (typeof this.q.content_type_uid !== 'string' || typeof field !== 'string' || field.length === 0) { - throw new Error('Kindly provide valid parameters for .ascending!') + throw new Error(ErrorMessages.INVALID_ASCENDING_PARAMS) } else if (this.internal.sort && typeof this.internal.sort === 'object') { this.internal.sort[field] = 1 } else { @@ -140,7 +144,7 @@ export class Stack { */ public descending(field) { if (typeof this.q.content_type_uid !== 'string' || typeof field !== 'string' || field.length === 0) { - throw new Error('Kindly provide valid parameters for .descending()!') + throw new Error(ErrorMessages.INVALID_DESCENDING_PARAMS) } else if (this.internal.sort && typeof this.internal.sort === 'object') { this.internal.sort[field] = -1 } else { @@ -220,7 +224,7 @@ export class Stack { */ public language(code) { if (typeof code !== 'string' || code.length === 0) { - throw new Error('Kindly pass valid parameters for .language()!') + throw new Error(ErrorMessages.INVALID_LANGUAGE_PARAMS) } this.q.locale = code @@ -257,7 +261,7 @@ export class Stack { */ public and(queries) { if (typeof queries !== 'object' || !Array.isArray(queries)) { - throw new Error('Kindly provide valid parameters for .and()!') + throw new Error(ErrorMessages.INVALID_AND_PARAMS) } else if (this.q.query && typeof this.q.query === 'object') { this.q.query = merge(this.q.query, { $and: queries, @@ -301,7 +305,7 @@ export class Stack { */ public or(queries) { if (typeof queries !== 'object' || !Array.isArray(queries)) { - throw new Error('Kindly provide valid parameters for .or()!') + throw new Error(ErrorMessages.INVALID_OR_PARAMS) } else if (this.q.query && typeof this.q.query === 'object') { this.q.query = merge(this.q.query, { $or: queries, @@ -343,7 +347,7 @@ export class Stack { */ public lessThan(key, value) { if (typeof key !== 'string' || typeof value === 'undefined') { - throw new Error('Kindly pass valid key and value parameters for \'.lessThan()\'') + throw new Error(ErrorMessages.INVALID_LESSTHAN_PARAMS) } else if (this.q.query && typeof this.q.query === 'object') { this.q.query[key] = { $lt: value, @@ -387,7 +391,7 @@ export class Stack { */ public lessThanOrEqualTo(key, value) { if (typeof key !== 'string' || typeof value === 'undefined') { - throw new Error('Kindly pass valid key and value parameters for \'.lessThanOrEqualTo()\'') + throw new Error(ErrorMessages.INVALID_LESSTHAN_OR_EQUAL_PARAMS) } else if (this.q.query && typeof this.q.query === 'object') { this.q.query[key] = { $lte: value, @@ -431,7 +435,7 @@ export class Stack { */ public greaterThan(key, value) { if (typeof key !== 'string' || typeof value === 'undefined') { - throw new Error('Kindly pass valid key and value parameters for \'.greaterThan()\'') + throw new Error(ErrorMessages.INVALID_GREATERTHAN_PARAMS) } else if (this.q.query && typeof this.q.query === 'object') { this.q.query[key] = { $gt: value, @@ -475,7 +479,7 @@ export class Stack { */ public greaterThanOrEqualTo(key, value) { if (typeof key !== 'string' || typeof value === 'undefined') { - throw new Error('Kindly pass valid key and value parameters for \'.greaterThanOrEqualTo()\'') + throw new Error(ErrorMessages.INVALID_GREATERTHAN_OR_EQUAL_PARAMS) } else if (this.q.query && typeof this.q.query === 'object') { this.q.query[key] = { $gte: value, @@ -524,7 +528,7 @@ export class Stack { */ public notEqualTo(key, value) { if (typeof key !== 'string' || typeof value === 'undefined') { - throw new Error('Kindly pass valid key and value parameters for \'.notEqualTo()\'') + throw new Error(ErrorMessages.INVALID_NOTEQUAL_PARAMS) } else if (this.q.query && typeof this.q.query === 'object') { this.q.query[key] = { $ne: value, @@ -574,7 +578,7 @@ export class Stack { */ public containedIn(key, value) { if (typeof key !== 'string' || typeof value !== 'object' || !(value instanceof Array)) { - throw new Error('Kindly pass valid key and value parameters for \'.containedIn()\'') + throw new Error(ErrorMessages.INVALID_CONTAINED_IN_PARAMS) } else if (this.q.query && typeof this.q.query === 'object') { this.q.query[key] = { $in: value, @@ -624,7 +628,7 @@ export class Stack { */ public notContainedIn(key, value) { if (typeof key !== 'string' || typeof value !== 'object' || !(value instanceof Array)) { - throw new Error('Kindly pass valid key and value parameters for \'.notContainedIn()\'') + throw new Error(ErrorMessages.INVALID_NOT_CONTAINED_IN_PARAMS) } else if (this.q.query && typeof this.q.query === 'object') { this.q.query[key] = { $nin: value, @@ -674,7 +678,7 @@ export class Stack { */ public exists(key) { if (typeof key !== 'string') { - throw new Error('Kindly pass valid key for \'.exists()\'') + throw new Error(ErrorMessages.INVALID_EXISTS_PARAMS) } else if (this.q.query && typeof this.q.query === 'object') { this.q.query[key] = { $exists: true, @@ -723,7 +727,7 @@ export class Stack { */ public notExists(key) { if (typeof key !== 'string') { - throw new Error('Kindly pass valid key for \'.notExists()\'') + throw new Error(ErrorMessages.INVALID_NOT_EXISTS_PARAMS) } else if (this.q.query && typeof this.q.query === 'object') { this.q.query[key] = { $exists: false, @@ -766,7 +770,7 @@ export class Stack { return stack } - throw new Error('Kindly pass the content type\'s uid') + throw new Error(ErrorMessages.MISSING_CONTENT_TYPE_UID) } /** @@ -793,7 +797,7 @@ export class Stack { */ public entry(uid ? ) { if (!(this.q.content_type_uid)) { - throw new Error('Kindly call \'contentType()\' before \'entry()\'!') + throw new Error(ErrorMessages.MISSING_CONTENT_TYPE_FOR_ENTRY) } if (uid && typeof uid === 'string') { this.q.query = this.q.query || {} @@ -830,7 +834,7 @@ export class Stack { return this } - throw new Error('Kindly call \'contentType()\' before \'entries()\'!') + throw new Error(ErrorMessages.MISSING_CONTENT_TYPE_FOR_ENTRIES) } /** @@ -1013,7 +1017,7 @@ export class Stack { return this } - throw new Error('Kindly provide a valid \'numeric\' value for \'limit()\'') + throw new Error(ErrorMessages.INVALID_LIMIT_VALUE) } /** @@ -1046,7 +1050,7 @@ export class Stack { return this } - throw new Error('Kindly provide a valid \'numeric\' value for \'skip()\'') + throw new Error(ErrorMessages.INVALID_SKIP_VALUE) } /** @@ -1106,7 +1110,7 @@ export class Stack { */ public only(fields) { if (!fields || typeof fields !== 'object' || !(fields instanceof Array) || fields.length === 0) { - throw new Error('Kindly provide valid \'field\' values for \'only()\'') + throw new Error(ErrorMessages.INVALID_ONLY_PARAMS) } this.internal.only = this.internal.only || {} this.internal.only._id = 0 @@ -1144,7 +1148,7 @@ export class Stack { */ public except(fields) { if (!fields || typeof fields !== 'object' || !(fields instanceof Array) || fields.length === 0) { - throw new Error('Kindly provide valid \'field\' values for \'except()\'') + throw new Error(ErrorMessages.INVALID_EXCEPT_PARAMS) } this.internal.except = this.internal.except || {} fields.forEach((field) => { @@ -1184,7 +1188,7 @@ export class Stack { */ public regex(field, pattern, options = 'i') { if (!(field) || !(pattern) || typeof field !== 'string' || typeof pattern !== 'string') { - throw new Error('Kindly provide a valid field and pattern value for \'.regex()\'') + throw new Error(ErrorMessages.INVALID_REGEX_PARAMS) } else if (this.q.query && typeof this.q.query === 'object') { this.q.query = merge(this.q.query, { [field]: { @@ -1227,7 +1231,7 @@ export class Stack { */ public tags(values) { if (!values || typeof values !== 'object' || !(values instanceof Array)) { - throw new Error('Kindly provide valid \'field\' values for \'tags()\'') + throw new Error(ErrorMessages.INVALID_TAGS_PARAMS) } // filter non-string keys remove(values, (value) => { @@ -1282,7 +1286,7 @@ export class Stack { */ public where(expr) { if (!(expr)) { - throw new Error('Kindly provide a valid field and expr/fn value for \'.where()\'') + throw new Error(ErrorMessages.INVALID_WHERE_PARAMS) } else if (this.q.query && typeof this.q.query === 'object') { if (typeof expr === 'function') { expr = expr.toString() @@ -1440,7 +1444,7 @@ export class Stack { return this } - throw new Error('Kindly pass a query object for \'.queryReferences()\'') + throw new Error(ErrorMessages.INVALID_QUERY_REFERENCES_PARAMS) } /** @@ -1477,7 +1481,7 @@ export class Stack { * @returns {Stack} Returns 'this' instance (of Stack) */ public includeReferences(depth?: number) { - console.warn('.includeReferences() is a relatively slow query..!') + console.warn(WarningMessages.SLOW_INCLUDE_REFERENCES) if (typeof depth === 'number') { this.q.referenceDepth = depth } @@ -1501,7 +1505,7 @@ export class Stack { */ public include(fields) { if (fields.length === 0) { - throw new Error('Kindly pass a valid reference field path to \'.include()\' ') + throw new Error(ErrorMessages.INVALID_INCLUDE_PARAMS) } else if (typeof fields === 'string') { this.internal.includeSpecificReferences = [fields] } else { @@ -2099,7 +2103,7 @@ export class Stack { private async getReferencePath(query, locale, currentInclude) { if (!this.sanityQueryAny(query)) { - throw new Error('Invalid query provided'); + throw new Error(ErrorMessages.INVALID_QUERY) } const querySanitize = this.sanitizeQueryBucket(query) const schemas = await this.db.collection(getCollectionName({ @@ -2195,7 +2199,7 @@ export class Stack { private async fetchEntries(query: IQuery, locale: string, paths: string[], include: string[], includeAll: boolean = false) { if (!this.sanitizeIQuery(query)) { - throw new Error('Invalid queries provided'); + throw new Error(ErrorMessages.INVALID_QUERIES) } const sanitizeQuery = this.sanitizeQueryBucket(query) const result = await this.db.collection(getCollectionName({ diff --git a/src/util.ts b/src/util.ts index a421cf0..de740a5 100644 --- a/src/util.ts +++ b/src/util.ts @@ -5,6 +5,7 @@ */ import { uniq } from 'lodash' +import { ErrorMessages } from './messages' /** * @private @@ -16,7 +17,7 @@ import { uniq } from 'lodash' */ export const validateURI = (uri) => { if (typeof uri !== 'string' || uri.length === 0) { - throw new Error(`Mongodb connection url: ${uri} must be of type string`) + throw new Error(ErrorMessages.INVALID_MONGODB_URI(uri)) } return uri @@ -59,7 +60,7 @@ const getParents = (child, mapping) => { const validateContentStore = (contentStore) => { if (typeof contentStore.dbName !== 'string' || contentStore.dbName.length === 0) { - throw new Error('Contentstore dbName should be of type string and not empty!') + throw new Error(ErrorMessages.INVALID_DBNAME) } if (typeof contentStore.collectionName === 'string') { diff --git a/typings/messages.d.ts b/typings/messages.d.ts new file mode 100644 index 0000000..879a86e --- /dev/null +++ b/typings/messages.d.ts @@ -0,0 +1,41 @@ +/** + * Type definitions for centralized error messages and warnings + */ + +export declare const ErrorMessages: { + readonly INVALID_MONGODB_URI: (uri: any) => string; + readonly INVALID_DBNAME: string; + readonly INVALID_ASCENDING_PARAMS: string; + readonly INVALID_DESCENDING_PARAMS: string; + readonly INVALID_LANGUAGE_PARAMS: string; + readonly INVALID_AND_PARAMS: string; + readonly INVALID_OR_PARAMS: string; + readonly INVALID_LESSTHAN_PARAMS: string; + readonly INVALID_LESSTHAN_OR_EQUAL_PARAMS: string; + readonly INVALID_GREATERTHAN_PARAMS: string; + readonly INVALID_GREATERTHAN_OR_EQUAL_PARAMS: string; + readonly INVALID_NOTEQUAL_PARAMS: string; + readonly INVALID_CONTAINED_IN_PARAMS: string; + readonly INVALID_NOT_CONTAINED_IN_PARAMS: string; + readonly INVALID_EXISTS_PARAMS: string; + readonly INVALID_NOT_EXISTS_PARAMS: string; + readonly MISSING_CONTENT_TYPE_UID: string; + readonly MISSING_CONTENT_TYPE_FOR_ENTRY: string; + readonly MISSING_CONTENT_TYPE_FOR_ENTRIES: string; + readonly INVALID_LIMIT_VALUE: string; + readonly INVALID_SKIP_VALUE: string; + readonly INVALID_ONLY_PARAMS: string; + readonly INVALID_EXCEPT_PARAMS: string; + readonly INVALID_REGEX_PARAMS: string; + readonly INVALID_TAGS_PARAMS: string; + readonly INVALID_WHERE_PARAMS: string; + readonly INVALID_QUERY_REFERENCES_PARAMS: string; + readonly INVALID_INCLUDE_PARAMS: string; + readonly INVALID_QUERY: string; + readonly INVALID_QUERIES: string; +}; + +export declare const WarningMessages: { + readonly SLOW_INCLUDE_REFERENCES: string; +}; +