From 3ddd3092a104844ebd36af256ecfd9b28da4be65 Mon Sep 17 00:00:00 2001 From: "harshitha.d" Date: Thu, 17 Apr 2025 16:04:06 +0530 Subject: [PATCH 1/6] Add pre-commit hook for Snyk and Talisman scans; update .gitignore and package.json --- .gitignore | 4 +++ .husky/pre-commit | 69 +++++++++++++++++++++++++++++++++++++++++++++++ .talismanrc | 7 +++-- package-lock.json | 35 +++++++++++++++++------- package.json | 5 ++-- 5 files changed, 107 insertions(+), 13 deletions(-) create mode 100755 .husky/pre-commit diff --git a/.gitignore b/.gitignore index 1dcac4f..7907888 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,7 @@ playground newQueryBuilder.ts query-builder.ts dist + +# pre-commit scans +talisman_output.log +snyk_output.log \ No newline at end of file diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 0000000..4f1fbbc --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,69 @@ +#!/usr/bin/env sh +# Pre-commit hook to run Snyk and Talisman scans, completing both before deciding to commit + +# Function to check if a command exists +command_exists() { + command -v "$1" >/dev/null 2>&1 +} + +# Check if Snyk is installed +if ! command_exists snyk; then + echo "Error: Snyk is not installed. Please install it and try again." + exit 1 +fi + +# Check if Talisman is installed +if ! command_exists talisman; then + echo "Error: Talisman is not installed. Please install it and try again." + exit 1 +fi + +# Allow bypassing the hook with an environment variable +if [ "$SKIP_HOOK" = "1" ]; then + echo "Skipping Snyk and Talisman scans (SKIP_HOOK=1)." + exit 0 +fi + +# Initialize variables to track scan results +snyk_failed=false +talisman_failed=false + +# Run Snyk vulnerability scan +echo "Running Snyk vulnerability scan..." +snyk test --all-projects > snyk_output.log 2>&1 +snyk_exit_code=$? + +if [ $snyk_exit_code -eq 0 ]; then + echo "Snyk scan passed: No vulnerabilities found." +elif [ $snyk_exit_code -eq 1 ]; then + echo "Snyk found vulnerabilities. See snyk_output.log for details." + snyk_failed=true +else + echo "Snyk scan failed with error (exit code $snyk_exit_code). See snyk_output.log for details." + snyk_failed=true +fi + +# Run Talisman secret scan (continues even if Snyk failed) +echo "Running Talisman secret scan..." +talisman --githook pre-commit > talisman_output.log 2>&1 +talisman_exit_code=$? + +if [ $talisman_exit_code -eq 0 ]; then + echo "Talisman scan passed: No secrets found." +else + echo "Talisman scan failed (exit code $talisman_exit_code). See talisman_output.log for details." + talisman_failed=true +fi + +# Evaluate results after both scans +if [ "$snyk_failed" = true ] || [ "$talisman_failed" = true ]; then + echo "Commit aborted due to issues found in one or both scans." + [ "$snyk_failed" = true ] && echo "- Snyk issues: Check snyk_output.log" + [ "$talisman_failed" = true ] && echo "- Talisman issues: Check talisman_output.log" + exit 1 +fi + +# If both scans pass, allow the commit +echo "All scans passed. Proceeding with commit.cd ." +rm -f snyk_output.log talisman_output.log +exit 0 \ No newline at end of file diff --git a/.talismanrc b/.talismanrc index 2cd9815..f60a646 100644 --- a/.talismanrc +++ b/.talismanrc @@ -1,4 +1,7 @@ fileignoreconfig: - filename: package-lock.json - checksum: a618ae6c113021eef425f224f1dfd7066b15af1a45249ea063a193517ce5a92f -version: "" \ No newline at end of file + checksum: 37742c5c56859fdfed906c14e97881c4a10e0a52464fda489e4eb8154298fde4 +- filename: .husky/pre-commit + checksum: 5baabd7d2c391648163f9371f0e5e9484f8fb90fa2284cfc378732ec3192c193 +version: "" +base64_entropy: false \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 9d40848..353e2a4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "@types/node": "10.17.60", "@types/rimraf": "4.0.5", "debug": "^4.4.0", + "husky": "^9.1.7", "jest": "^29.7.0", "jsdoc": "^4.0.4", "node-notifier": "^10.0.1", @@ -1567,9 +1568,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001713", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001713.tgz", - "integrity": "sha512-wCIWIg+A4Xr7NfhTuHdX+/FKh3+Op3LBbSp2N5Pfx6T/LhdQy3GTyoTg48BReaW/MyMNZAkTadsBtai3ldWK0Q==", + "version": "1.0.30001714", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001714.tgz", + "integrity": "sha512-mtgapdwDLSSBnCI3JokHM7oEQBLxiJKVRtg10AxM1AyeiKcM96f0Mkbqeq+1AbiCtvMcHRulAAEMu693JrSWqg==", "dev": true, "funding": [ { @@ -2259,6 +2260,22 @@ "node": ">=10.17.0" } }, + "node_modules/husky": { + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", + "dev": true, + "license": "MIT", + "bin": { + "husky": "bin.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, "node_modules/import-local": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", @@ -4352,9 +4369,9 @@ } }, "node_modules/tr46": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.0.tgz", - "integrity": "sha512-IUWnUK7ADYR5Sl1fZlO1INDUhVhatWl7BtJWsIhwJ0UAK7ilzzIa8uIqOO/aYVWHZPJkKbEL+362wrzoeRF7bw==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", + "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", "license": "MIT", "dependencies": { "punycode": "^2.3.1" @@ -4427,9 +4444,9 @@ } }, "node_modules/ts-jest/node_modules/type-fest": { - "version": "4.39.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.39.1.tgz", - "integrity": "sha512-uW9qzd66uyHYxwyVBYiwS4Oi0qZyUqwjU+Oevr6ZogYiXt99EOYtwvzMSLw1c3lYo2HzJsep/NB23iEVEgjG/w==", + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.40.0.tgz", + "integrity": "sha512-ABHZ2/tS2JkvH1PEjxFDTUWC8dB5OsIGZP4IFLhR293GqT5Y5qB1WwL2kMPYhQW9DVgVD8Hd7I8gjwPIf5GFkw==", "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { diff --git a/package.json b/package.json index 34e3dce..79e383c 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "main": "dist/index.js", "scripts": { "clean": "rimraf dist typings coverage", - "build-ts": "npm run clean && tsc", + "build-ts": "npm run clean && tsc && husky && chmod +x .husky/pre-commit", "build-doc": "npm run build-ts && ./node_modules/.bin/jsdoc dist/ -r -R README.md -d docs", "watch-ts": "npm run clean && tsc -w", "compile": "tsc", @@ -19,7 +19,7 @@ "dependencies": { "lodash": "^4.17.21", "mongodb": "^6.12.0", - "sift": "^17.1.3" + "sift": "^17.1.3" }, "devDependencies": { "@types/jest": "29.5.14", @@ -27,6 +27,7 @@ "@types/node": "10.17.60", "@types/rimraf": "4.0.5", "debug": "^4.4.0", + "husky": "^9.1.7", "jest": "^29.7.0", "jsdoc": "^4.0.4", "node-notifier": "^10.0.1", From b6062fb105be7a210167c61c4791020ff815f0bd Mon Sep 17 00:00:00 2001 From: "harshitha.d" Date: Thu, 17 Apr 2025 16:10:48 +0530 Subject: [PATCH 2/6] Update build-ts script to include husky install for pre-commit hook setup --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 79e383c..a938293 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "main": "dist/index.js", "scripts": { "clean": "rimraf dist typings coverage", - "build-ts": "npm run clean && tsc && husky && chmod +x .husky/pre-commit", + "build-ts": "npm run clean && tsc && husky install && husky && chmod +x .husky/pre-commit", "build-doc": "npm run build-ts && ./node_modules/.bin/jsdoc dist/ -r -R README.md -d docs", "watch-ts": "npm run clean && tsc -w", "compile": "tsc", From 146fdb67d4c19ede0c94cc63f43bcac55dc8aefe Mon Sep 17 00:00:00 2001 From: "harshitha.d" Date: Mon, 21 Apr 2025 16:33:59 +0530 Subject: [PATCH 3/6] Refactor build-ts script to separate husky installation from TypeScript build process --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index a938293..fa2d582 100644 --- a/package.json +++ b/package.json @@ -6,11 +6,12 @@ "main": "dist/index.js", "scripts": { "clean": "rimraf dist typings coverage", - "build-ts": "npm run clean && tsc && husky install && husky && chmod +x .husky/pre-commit", + "build-ts": "npm run clean && tsc", "build-doc": "npm run build-ts && ./node_modules/.bin/jsdoc dist/ -r -R README.md -d docs", "watch-ts": "npm run clean && tsc -w", "compile": "tsc", "prepare": "npm run compile", + "pre-commit": "husky install && husky && chmod +x .husky/pre-commit", "start": "dist/index.js", "tslint": "npx tslint -c tslint.json 'src/**/*.ts' --fix", "test": "jest" From d863a7822b21af594d750b6156988234bcaf1660 Mon Sep 17 00:00:00 2001 From: reeshika-h Date: Tue, 28 Oct 2025 13:27:02 +0530 Subject: [PATCH 4/6] updated error messages --- src/messages.ts | 62 +++++++++++++++++++++++++++++++++++++++++++ src/stack.ts | 62 +++++++++++++++++++++++-------------------- src/util.ts | 5 ++-- typings/messages.d.ts | 41 ++++++++++++++++++++++++++++ 4 files changed, 139 insertions(+), 31 deletions(-) create mode 100644 src/messages.ts create mode 100644 typings/messages.d.ts 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; +}; + From e882be7a85d8d487951dee03782f886ad143530b Mon Sep 17 00:00:00 2001 From: "harshitha.d" Date: Fri, 7 Nov 2025 18:06:55 +0530 Subject: [PATCH 5/6] version bump --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 353e2a4..059797e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@contentstack/datasync-mongodb-sdk", - "version": "1.0.11", + "version": "1.0.12", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@contentstack/datasync-mongodb-sdk", - "version": "1.0.11", + "version": "1.0.12", "license": "MIT", "dependencies": { "lodash": "^4.17.21", diff --git a/package.json b/package.json index fa2d582..75020dd 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "author": "Contentstack Ecosystem ", "name": "@contentstack/datasync-mongodb-sdk", - "version": "1.0.11", + "version": "1.0.12", "description": "Mongodb query wrapper around contents synced via @contentstack/content-store-mongodb", "main": "dist/index.js", "scripts": { From 690eb77afb006d3fefca868b31e5926a66974dcf Mon Sep 17 00:00:00 2001 From: "harshitha.d" Date: Fri, 7 Nov 2025 18:07:53 +0530 Subject: [PATCH 6/6] Merge branch 'development' into fix/version-bump --- typings/messages.d.ts | 68 +++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 35 deletions(-) diff --git a/typings/messages.d.ts b/typings/messages.d.ts index 879a86e..0e1ed2a 100644 --- a/typings/messages.d.ts +++ b/typings/messages.d.ts @@ -1,41 +1,39 @@ /** - * Type definitions for centralized error messages and warnings + * Centralized error messages and warnings for the DataSync MongoDB SDK + * This file contains all user-facing messages for consistency and maintainability */ - 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; + readonly INVALID_MONGODB_URI: (uri: any) => string; + readonly INVALID_DBNAME: "Content store dbName should be of type string and not empty"; + readonly INVALID_ASCENDING_PARAMS: "Invalid parameters for .ascending(). Expected a valid string field name"; + readonly INVALID_DESCENDING_PARAMS: "Invalid parameters for .descending(). Expected a valid string field name"; + readonly INVALID_LANGUAGE_PARAMS: "Invalid parameters for .language(). Expected a valid language code string"; + readonly INVALID_AND_PARAMS: "Invalid parameters for .and(). Expected an array of query objects"; + readonly INVALID_OR_PARAMS: "Invalid parameters for .or(). Expected an array of query objects"; + readonly INVALID_LESSTHAN_PARAMS: "Invalid key or value parameters for .lessThan(). Expected a string key and a value"; + readonly INVALID_LESSTHAN_OR_EQUAL_PARAMS: "Invalid key or value parameters for .lessThanOrEqualTo(). Expected a string key and a value"; + readonly INVALID_GREATERTHAN_PARAMS: "Invalid key or value parameters for .greaterThan(). Expected a string key and a value"; + readonly INVALID_GREATERTHAN_OR_EQUAL_PARAMS: "Invalid key or value parameters for .greaterThanOrEqualTo(). Expected a string key and a value"; + readonly INVALID_NOTEQUAL_PARAMS: "Invalid key or value parameters for .notEqualTo(). Expected a string key and a value"; + readonly INVALID_CONTAINED_IN_PARAMS: "Invalid key or value parameters for .containedIn(). Expected a string key and an array value"; + readonly INVALID_NOT_CONTAINED_IN_PARAMS: "Invalid key or value parameters for .notContainedIn(). Expected a string key and an array value"; + readonly INVALID_EXISTS_PARAMS: "Invalid key parameter for .exists(). Expected a valid string field name"; + readonly INVALID_NOT_EXISTS_PARAMS: "Invalid key parameter for .notExists(). Expected a valid string field name"; + readonly MISSING_CONTENT_TYPE_UID: "Content type UID is required. Please provide a valid content type UID"; + readonly MISSING_CONTENT_TYPE_FOR_ENTRY: "Please call .contentType() before .entry()"; + readonly MISSING_CONTENT_TYPE_FOR_ENTRIES: "Please call .contentType() before .entries()"; + readonly INVALID_LIMIT_VALUE: "Invalid value for .limit(). Expected a positive numeric value"; + readonly INVALID_SKIP_VALUE: "Invalid value for .skip(). Expected a non-negative numeric value"; + readonly INVALID_ONLY_PARAMS: "Invalid field values for .only(). Expected a non-empty array of field names"; + readonly INVALID_EXCEPT_PARAMS: "Invalid field values for .except(). Expected a non-empty array of field names"; + readonly INVALID_REGEX_PARAMS: "Invalid field or pattern parameters for .regex(). Expected string values for both field and pattern"; + readonly INVALID_TAGS_PARAMS: "Invalid field values for .tags(). Expected an array of tag values"; + readonly INVALID_WHERE_PARAMS: "Invalid expression for .where(). Expected a valid expression or function"; + readonly INVALID_QUERY_REFERENCES_PARAMS: "Invalid query object for .queryReferences(). Expected a valid query object"; + readonly INVALID_INCLUDE_PARAMS: "Invalid reference field path for .include(). Expected a valid string or array of strings"; + readonly INVALID_QUERY: "Invalid query provided. Please ensure your query is properly formatted"; + readonly INVALID_QUERIES: "Invalid queries provided. Please ensure all queries are properly formatted"; }; - export declare const WarningMessages: { - readonly SLOW_INCLUDE_REFERENCES: string; + readonly SLOW_INCLUDE_REFERENCES: ".includeReferences(...) is a relatively slow query. Consider limiting the depth or using .include() for specific references"; }; -