From c26e1cf1a1532b862e982ebc373a9332de994471 Mon Sep 17 00:00:00 2001 From: "Alex Rock (Koala)" Date: Fri, 27 Sep 2024 12:04:47 -0600 Subject: [PATCH 1/8] koala: initial commit --- validators/BooleanValidator/README.MD | 79 ++++++++ validators/BooleanValidator/metadata.json | 84 ++++++++ validators/BooleanValidator/package.json | 71 +++++++ validators/BooleanValidator/rollup.config.mjs | 5 + validators/BooleanValidator/src/index.ts | 186 ++++++++++++++++++ 5 files changed, 425 insertions(+) create mode 100644 validators/BooleanValidator/README.MD create mode 100644 validators/BooleanValidator/metadata.json create mode 100644 validators/BooleanValidator/package.json create mode 100644 validators/BooleanValidator/rollup.config.mjs create mode 100644 validators/BooleanValidator/src/index.ts diff --git a/validators/BooleanValidator/README.MD b/validators/BooleanValidator/README.MD new file mode 100644 index 000000000..75cef38b7 --- /dev/null +++ b/validators/BooleanValidator/README.MD @@ -0,0 +1,79 @@ +# Boolean Validator Plugin for Flatfile + +This plugin implements a Boolean Validator for Flatfile Listener that validates and converts boolean values in Flatfile records. It supports various options for validation, including multi-language representations, custom truthy/falsy values, and batch processing for large datasets. + +## Features + +- Strict or lenient boolean validation +- Custom truthy and falsy value support +- Multi-language representations +- Case-sensitive or case-insensitive validation +- Null value handling +- Conversion of non-boolean values +- Customizable error messages +- Default value option +- Batch processing for large datasets + +## Installation + +To install the plugin, run the following command: + +```bash +npm install @flatfile/plugin-boolean-validator +``` + +## Example Usage + +```javascript +import { FlatfileListener } from "@flatfile/listener"; +import booleanValidatorPlugin from "@flatfile/plugin-boolean-validator"; + +const listener = new FlatfileListener(); + +listener.use( + booleanValidatorPlugin(listener, { + strict: false, + allowTruthyFalsy: true, + caseSensitive: false, + allowNull: true, + convertNonBoolean: true, + languageRepresentations: { + en: { true: ["true", "yes"], false: ["false", "no"] }, + es: { true: ["verdadero", "sí"], false: ["falso", "no"] }, + }, + errorMessages: { + invalidBoolean: "Invalid boolean value", + }, + defaultValue: null, + batchSize: 1000, + }) +); +``` + +## Configuration + +The plugin accepts a `ValidationOptions` object with the following properties: + +- `strict`: Boolean, if true, only allows "true" and "false" values +- `allowTruthyFalsy`: Boolean, allows custom truthy/falsy values +- `customTruthyValues`: Array of strings, custom truthy values +- `customFalsyValues`: Array of strings, custom falsy values +- `caseSensitive`: Boolean, enables case-sensitive validation +- `allowNull`: Boolean, allows null values +- `convertNonBoolean`: Boolean, converts non-boolean values to boolean +- `languageRepresentations`: Object, multi-language representations for true/false +- `errorMessages`: Object, custom error messages +- `defaultValue`: Boolean or null, default value for invalid inputs +- `batchSize`: Number, batch size for processing large datasets + +## Behavior + +1. The plugin processes all fields ending with "_bool". +2. It validates the input based on the provided configuration. +3. If the input is valid, it converts it to a boolean value. +4. If the input is invalid: + - It assigns the default value if provided. + - It adds an error message to the record if no default value is set. +5. The plugin processes records in batches for better performance with large datasets. + +For detailed behavior on specific input types and validation rules, please refer to the source code and comments. \ No newline at end of file diff --git a/validators/BooleanValidator/metadata.json b/validators/BooleanValidator/metadata.json new file mode 100644 index 000000000..b37f9d39b --- /dev/null +++ b/validators/BooleanValidator/metadata.json @@ -0,0 +1,84 @@ +{ + "timestamp": "2024-09-27T16-52-25-463Z", + "task": "Create a Boolean Validator Flatfile Listener plugin:\n - Implement strict boolean validation (true/false only)\n - Add support for truthy/falsy value validation\n - Allow custom truthy/falsy value mapping (e.g., 'yes'/'no', '1'/'0')\n - Implement case-insensitive boolean string matching\n - Add options for handling null/undefined values\n - Implement conversion of non-boolean types to boolean\n - Add support for multi-language boolean representations\n - Implement custom error messages for invalid boolean values\n - Add options for default values when conversion fails\n - Implement batch processing for efficient boolean validation of large datasets", + "summary": "This code implements a Boolean Validator Flatfile Listener plugin that validates and converts boolean values in Flatfile records. It supports various options for validation, including multi-language representations, custom truthy/falsy values, and batch processing for large datasets.", + "steps": [ + [ + "Retrieve information about Flatfile Listeners and the Record Hook plugin to understand the structure and implementation details.\n", + "#E1", + "PineconeAssistant", + "Provide information about Flatfile Listeners and the Record Hook plugin, including their structure and implementation details", + "Plan: Retrieve information about Flatfile Listeners and the Record Hook plugin to understand the structure and implementation details.\n#E1 = PineconeAssistant[Provide information about Flatfile Listeners and the Record Hook plugin, including their structure and implementation details]" + ], + [ + "Based on the retrieved information, create the basic structure of the Boolean Validator Listener plugin.\n", + "#E2", + "LLM", + "Using the information from #E1, create the basic structure of a Flatfile Listener plugin for boolean validation", + "Plan: Based on the retrieved information, create the basic structure of the Boolean Validator Listener plugin.\n#E2 = LLM[Using the information from #E1, create the basic structure of a Flatfile Listener plugin for boolean validation]" + ], + [ + "Implement strict boolean validation (true/false only) and add support for truthy/falsy value validation.\n", + "#E3", + "LLM", + "Extend the code from #E2 to implement strict boolean validation and support for truthy/falsy value validation", + "Plan: Implement strict boolean validation (true/false only) and add support for truthy/falsy value validation.\n#E3 = LLM[Extend the code from #E2 to implement strict boolean validation and support for truthy/falsy value validation]" + ], + [ + "Add support for custom truthy/falsy value mapping and case-insensitive boolean string matching.\n", + "#E4", + "LLM", + "Extend the code from #E3 to add support for custom truthy/falsy value mapping and case-insensitive boolean string matching", + "Plan: Add support for custom truthy/falsy value mapping and case-insensitive boolean string matching.\n#E4 = LLM[Extend the code from #E3 to add support for custom truthy/falsy value mapping and case-insensitive boolean string matching]" + ], + [ + "Implement handling for null/undefined values and conversion of non-boolean types to boolean.\n", + "#E5", + "LLM", + "Extend the code from #E4 to handle null/undefined values and implement conversion of non-boolean types to boolean", + "Plan: Implement handling for null/undefined values and conversion of non-boolean types to boolean.\n#E5 = LLM[Extend the code from #E4 to handle null/undefined values and implement conversion of non-boolean types to boolean]" + ], + [ + "Add support for multi-language boolean representations and custom error messages for invalid boolean values.\n", + "#E6", + "LLM", + "Extend the code from #E5 to add support for multi-language boolean representations and custom error messages for invalid boolean values", + "Plan: Add support for multi-language boolean representations and custom error messages for invalid boolean values.\n#E6 = LLM[Extend the code from #E5 to add support for multi-language boolean representations and custom error messages for invalid boolean values]" + ], + [ + "Implement options for default values when conversion fails and batch processing for efficient boolean validation of large datasets.\n", + "#E7", + "LLM", + "Extend the code from #E6 to implement options for default values when conversion fails and batch processing for efficient boolean validation of large datasets", + "Plan: Implement options for default values when conversion fails and batch processing for efficient boolean validation of large datasets.\n#E7 = LLM[Extend the code from #E6 to implement options for default values when conversion fails and batch processing for efficient boolean validation of large datasets]" + ], + [ + "Verify that the implemented Listener is subscribed to valid Event Topics and uses appropriate Flatfile plugins or common utils.\n", + "#E8", + "PineconeAssistant", + "Verify that the Listener in #E7 is subscribed to valid Event Topics and uses appropriate Flatfile plugins or common utils. Provide any necessary corrections or suggestions.", + "Plan: Verify that the implemented Listener is subscribed to valid Event Topics and uses appropriate Flatfile plugins or common utils.\n#E8 = PineconeAssistant[Verify that the Listener in #E7 is subscribed to valid Event Topics and uses appropriate Flatfile plugins or common utils. Provide any necessary corrections or suggestions.]" + ], + [ + "Finalize the Boolean Validator Flatfile Listener plugin by incorporating any corrections or suggestions from the previous step.\n", + "#E9", + "LLM", + "Incorporate the corrections and suggestions from #E8 into the code from #E7 to finalize the Boolean Validator Flatfile Listener plugin", + "Plan: Finalize the Boolean Validator Flatfile Listener plugin by incorporating any corrections or suggestions from the previous step.\n#E9 = LLM[Incorporate the corrections and suggestions from #E8 into the code from #E7 to finalize the Boolean Validator Flatfile Listener plugin]" + ], + [ + "Perform a final check to ensure all requirements are met, remove any unused imports, and validate the plugin's code and parameters.\n", + "#E10", + "LLM", + "Review the final code from #E9, ensure all requirements are met, remove any unused imports, and validate the plugin's code and parameters", + "Plan: Perform a final check to ensure all requirements are met, remove any unused imports, and validate the plugin's code and parameters.\n#E10 = LLM[Review the final code from #E9, ensure all requirements are met, remove any unused imports, and validate the plugin's code and parameters]" + ] + ], + "metrics": { + "tokens": { + "plan": 6011, + "state": 6623, + "total": 12634 + } + } +} \ No newline at end of file diff --git a/validators/BooleanValidator/package.json b/validators/BooleanValidator/package.json new file mode 100644 index 000000000..b83a788e9 --- /dev/null +++ b/validators/BooleanValidator/package.json @@ -0,0 +1,71 @@ +{ + "name": "@flatfile/plugin-validate-boolean", + "version": "1.0.0", + "description": "A Flatfile plugin for boolean validation and conversion", + "main": "./dist/index.js", + "module": "./dist/index.mjs", + "types": "./dist/index.d.ts", + "browser": { + "./dist/index.js": "./dist/index.browser.js", + "./dist/index.mjs": "./dist/index.browser.mjs" + }, + "exports": { + "types": "./dist/index.d.ts", + "node": { + "import": "./dist/index.mjs", + "require": "./dist/index.js" + }, + "browser": { + "require": "./dist/index.browser.js", + "import": "./dist/index.browser.mjs" + }, + "default": "./dist/index.mjs" + }, + "source": "./src/index.ts", + "files": [ + "dist/**" + ], + "scripts": { + "build": "rollup -c", + "build:watch": "rollup -c --watch", + "build:prod": "NODE_ENV=production rollup -c", + "check": "tsc ./**/*.ts --noEmit --esModuleInterop", + "test": "jest ./**/*.spec.ts --config=../../jest.config.js --runInBand" + }, + "keywords": [ + "flatfile", + "plugin", + "boolean", + "validator", + "flatfile-plugins", + "category-transform" + ], + "author": "Your Name", + "license": "MIT", + "dependencies": { + "@flatfile/plugin-record-hook": "^1.7.0", + "@flatfile/util-common": "^1.4.0" + }, + "peerDependencies": { + "@flatfile/listener": "^1.0.5" + }, + "devDependencies": { + "@flatfile/hooks": "^1.5.0", + "@flatfile/rollup-config": "^0.1.1", + "typescript": "^5.6.2", + "@types/node": "^22.7.4", + "rollup": "^4.22.5", + "jest": "^29.7.0", + "@types/jest": "^29.5.13" + }, + "repository": { + "type": "git", + "url": "https://github.com/FlatFilers/flatfile-plugins.git", + "directory": "plugins/boolean-validator" + }, + "browserslist": [ + "> 0.5%", + "last 2 versions", + "not dead" + ] +} diff --git a/validators/BooleanValidator/rollup.config.mjs b/validators/BooleanValidator/rollup.config.mjs new file mode 100644 index 000000000..fafa813c6 --- /dev/null +++ b/validators/BooleanValidator/rollup.config.mjs @@ -0,0 +1,5 @@ +import { buildConfig } from '@flatfile/rollup-config' + +const config = buildConfig({}) + +export default config diff --git a/validators/BooleanValidator/src/index.ts b/validators/BooleanValidator/src/index.ts new file mode 100644 index 000000000..25d275961 --- /dev/null +++ b/validators/BooleanValidator/src/index.ts @@ -0,0 +1,186 @@ +import { recordHook } from '@flatfile/plugin-record-hook' +import { FlatfileListener } from '@flatfile/listener' +import { asyncBatch } from '@flatfile/util-common' + +interface ValidationOptions { + strict: boolean + allowTruthyFalsy: boolean + customTruthyValues?: string[] + customFalsyValues?: string[] + caseSensitive?: boolean + allowNull?: boolean + convertNonBoolean?: boolean + languageRepresentations?: Record + errorMessages?: { + invalidBoolean?: string + nullNotAllowed?: string + strictModeViolation?: string + } + defaultValue?: boolean | null + batchSize?: number +} + +export default function booleanValidatorPlugin( + listener: FlatfileListener, + options: ValidationOptions = { + strict: false, + allowTruthyFalsy: true, + caseSensitive: false, + allowNull: true, + convertNonBoolean: true, + languageRepresentations: { + en: { true: ['true', 'yes'], false: ['false', 'no'] }, + es: { true: ['verdadero', 'sí'], false: ['falso', 'no'] }, + fr: { true: ['vrai', 'oui'], false: ['faux', 'non'] }, + }, + errorMessages: { + invalidBoolean: 'Invalid boolean value', + nullNotAllowed: 'Null or undefined values are not allowed', + strictModeViolation: 'Only true or false are allowed in strict mode', + }, + defaultValue: null, + batchSize: 1000, + } +) { + listener.use( + recordHook( + '**', + async (records, event) => { + try { + await asyncBatch({ + items: records, + batchSize: options.batchSize || 1000, + asyncFn: async (batch) => { + await Promise.all( + batch.map(async (record) => { + for (const [fieldName, value] of Object.entries( + record.values + )) { + if (isBooleanField(fieldName)) { + validateBoolean(record, fieldName, value, options) + } + } + }) + ) + }, + }) + return records + } catch (error) { + console.error('Error in booleanValidatorPlugin:', error) + throw error + } + }, + { + concurrency: 10, + debug: false, + } + ) + ) +} + +function isBooleanField(fieldName: string): boolean { + return fieldName.endsWith('_bool') +} + +function validateBoolean( + record: any, + fieldName: string, + value: any, + options: ValidationOptions +): void { + if (value === null || value === undefined) { + if (options.allowNull) { + return + } else { + record.addError( + fieldName, + options.errorMessages?.nullNotAllowed || + 'Null or undefined values are not allowed' + ) + return + } + } + + if (typeof value === 'boolean') { + return + } + + if (options.strict) { + record.addError( + fieldName, + options.errorMessages?.strictModeViolation || + 'Only true or false are allowed in strict mode' + ) + return + } + + if (typeof value === 'string') { + const stringValue = options.caseSensitive ? value : value.toLowerCase() + const trimmedValue = stringValue.trim() + + if (['true', 'false'].includes(trimmedValue)) { + const boolValue = trimmedValue === 'true' + record.set(fieldName, boolValue) + return + } + + if (options.allowTruthyFalsy) { + const defaultTruthyValues = ['yes', '1', 'on'] + const defaultFalsyValues = ['no', '0', 'off'] + + const truthyValues = options.customTruthyValues || defaultTruthyValues + const falsyValues = options.customFalsyValues || defaultFalsyValues + + if (truthyValues.includes(trimmedValue)) { + record.set(fieldName, true) + return + } + if (falsyValues.includes(trimmedValue)) { + record.set(fieldName, false) + return + } + } + + if (options.languageRepresentations) { + for (const langRepresentations of Object.values( + options.languageRepresentations + )) { + if (langRepresentations.true.includes(trimmedValue)) { + record.set(fieldName, true) + return + } + if (langRepresentations.false.includes(trimmedValue)) { + record.set(fieldName, false) + return + } + } + } + } + + if (options.allowTruthyFalsy && typeof value === 'number') { + if (value === 1) { + record.set(fieldName, true) + return + } + if (value === 0) { + record.set(fieldName, false) + return + } + } + + if (options.convertNonBoolean) { + const boolValue = Boolean(value) + record.set(fieldName, boolValue) + return + } + + if (options.defaultValue !== undefined) { + record.set(fieldName, options.defaultValue) + return + } + + record.addError( + fieldName, + options.errorMessages?.invalidBoolean || 'Invalid boolean value' + ) +} From b122ede4da63350c62f3607fa1ffce1aa5196984 Mon Sep 17 00:00:00 2001 From: "Alex Rock (Koala)" Date: Mon, 30 Sep 2024 23:34:09 -0600 Subject: [PATCH 2/8] koala: initial commit --- validate/boolean/README.MD | 63 ++++++ validate/boolean/metadata.json | 98 +++++++++ .../boolean}/package.json | 13 +- .../boolean}/rollup.config.mjs | 0 validate/boolean/src/index.ts | 146 ++++++++++++++ validators/BooleanValidator/README.MD | 79 -------- validators/BooleanValidator/metadata.json | 84 -------- validators/BooleanValidator/src/index.ts | 186 ------------------ 8 files changed, 310 insertions(+), 359 deletions(-) create mode 100644 validate/boolean/README.MD create mode 100644 validate/boolean/metadata.json rename {validators/BooleanValidator => validate/boolean}/package.json (79%) rename {validators/BooleanValidator => validate/boolean}/rollup.config.mjs (100%) create mode 100644 validate/boolean/src/index.ts delete mode 100644 validators/BooleanValidator/README.MD delete mode 100644 validators/BooleanValidator/metadata.json delete mode 100644 validators/BooleanValidator/src/index.ts diff --git a/validate/boolean/README.MD b/validate/boolean/README.MD new file mode 100644 index 000000000..f5d283a19 --- /dev/null +++ b/validate/boolean/README.MD @@ -0,0 +1,63 @@ +# Flatfile Boolean Validator Plugin + +This plugin provides a robust Boolean validation solution for Flatfile, offering flexible configuration options to handle various boolean representations across different languages and use cases. + +## Features + +- Supports both strict and truthy boolean validation +- Multi-language support (English, Spanish, French, German) +- Custom mapping for boolean values +- Case-sensitive and case-insensitive options +- Configurable null value handling +- Option to convert non-boolean values +- Custom error messages +- Default value setting + +## Installation + +To install the plugin, run the following command: + +```bash +npm install @flatfile/plugin-boolean-validator +``` + +## Example Usage + +```javascript +import { validateBoolean } from '@flatfile/plugin-boolean-validator'; + +const booleanValidator = validateBoolean({ + fields: ['isActive', 'hasSubscription'], + validationType: 'truthy', + language: 'en', + handleNull: 'false', + convertNonBoolean: true +}); + +listener.use(booleanValidator); +``` + +## Configuration + +The `BooleanValidator` function accepts a configuration object with the following properties: + +- `fields`: An array of field names to validate +- `validationType`: 'strict' or 'truthy' +- `customMapping`: A custom mapping of string values to boolean +- `caseSensitive`: Whether the validation should be case-sensitive +- `handleNull`: How to handle null values ('error', 'false', 'true', or 'skip') +- `convertNonBoolean`: Whether to convert non-boolean values to boolean +- `language`: The language for predefined mappings ('en', 'es', 'fr', 'de') +- `customErrorMessages`: Custom error messages for different scenarios +- `defaultValue`: A default value to use for invalid inputs + +## Behavior + +1. **Strict Validation**: Only accepts 'true', 'false', true, or false as valid inputs. +2. **Truthy Validation**: Accepts various representations of true/false, including language-specific terms. +3. **Null Handling**: Configurable behavior for null or undefined values. +4. **Non-Boolean Conversion**: Option to convert non-boolean values to boolean. +5. **Error Handling**: Adds errors or info messages to the record for invalid inputs. +6. **Default Value**: Option to set a default value for invalid inputs instead of raising an error. + +The plugin can be used either as a RecordHook or as an external constraint, providing flexibility in integration with your Flatfile setup. diff --git a/validate/boolean/metadata.json b/validate/boolean/metadata.json new file mode 100644 index 000000000..f9c4a3a3d --- /dev/null +++ b/validate/boolean/metadata.json @@ -0,0 +1,98 @@ +{ + "timestamp": "2024-10-01T04-33-41-969Z", + "task": "Create a Boolean Validator Flatfile Listener plugin:\n - Add configuration for what fields are booleans\n - Implement strict boolean validation (true/false only)\n - Add support for truthy/falsy value validation\n - Allow custom truthy/falsy value mapping (e.g., 'yes'/'no', '1'/'0')\n - Implement case-insensitive boolean string matching\n - Add options for handling null/undefined values\n - Implement conversion of non-boolean types to boolean\n - Add support for multi-language boolean representations\n - Implement custom error messages for invalid boolean values\n - Add options for default values when conversion fails\n - Export recordHook and external constraint versions", + "summary": "This code implements a Boolean Validator plugin for Flatfile, providing both recordHook and external constraint versions. The plugin validates boolean fields in records, supporting strict and truthy validation types, custom mappings, and multi-language support.", + "steps": [ + [ + "Retrieve information about Flatfile Listeners and the Record Hook plugin to understand the structure and best practices.\n", + "#E1", + "PineconeAssistant", + "Provide information about Flatfile Listeners and the Record Hook plugin, including their structure and best practices", + "Plan: Retrieve information about Flatfile Listeners and the Record Hook plugin to understand the structure and best practices.\n#E1 = PineconeAssistant[Provide information about Flatfile Listeners and the Record Hook plugin, including their structure and best practices]" + ], + [ + "Create the basic structure of the Boolean Validator plugin, including configuration options for boolean fields and validation types.\n", + "#E2", + "LLM", + "Create a basic structure for a Flatfile Listener plugin named BooleanValidator with configuration options for boolean fields and validation types (strict, truthy/falsy) based on the information in #E1", + "Plan: Create the basic structure of the Boolean Validator plugin, including configuration options for boolean fields and validation types.\n#E2 = LLM[Create a basic structure for a Flatfile Listener plugin named BooleanValidator with configuration options for boolean fields and validation types (strict, truthy/falsy) based on the information in #E1]" + ], + [ + "Implement strict boolean validation and truthy/falsy value validation.\n", + "#E3", + "LLM", + "Extend the BooleanValidator plugin from #E2 to include implementations for strict boolean validation (true/false only) and truthy/falsy value validation", + "Plan: Implement strict boolean validation and truthy/falsy value validation.\n#E3 = LLM[Extend the BooleanValidator plugin from #E2 to include implementations for strict boolean validation (true/false only) and truthy/falsy value validation]" + ], + [ + "Add support for custom truthy/falsy value mapping and case-insensitive boolean string matching.\n", + "#E4", + "LLM", + "Enhance the BooleanValidator plugin from #E3 to support custom truthy/falsy value mapping (e.g., 'yes'/'no', '1'/'0') and implement case-insensitive boolean string matching", + "Plan: Add support for custom truthy/falsy value mapping and case-insensitive boolean string matching.\n#E4 = LLM[Enhance the BooleanValidator plugin from #E3 to support custom truthy/falsy value mapping (e.g., 'yes'/'no', '1'/'0') and implement case-insensitive boolean string matching]" + ], + [ + "Implement options for handling null/undefined values and conversion of non-boolean types to boolean.\n", + "#E5", + "LLM", + "Add functionality to the BooleanValidator plugin from #E4 to handle null/undefined values and implement conversion of non-boolean types to boolean", + "Plan: Implement options for handling null/undefined values and conversion of non-boolean types to boolean.\n#E5 = LLM[Add functionality to the BooleanValidator plugin from #E4 to handle null/undefined values and implement conversion of non-boolean types to boolean]" + ], + [ + "Add support for multi-language boolean representations and custom error messages for invalid boolean values.\n", + "#E6", + "LLM", + "Extend the BooleanValidator plugin from #E5 to support multi-language boolean representations and implement custom error messages for invalid boolean values", + "Plan: Add support for multi-language boolean representations and custom error messages for invalid boolean values.\n#E6 = LLM[Extend the BooleanValidator plugin from #E5 to support multi-language boolean representations and implement custom error messages for invalid boolean values]" + ], + [ + "Implement options for default values when conversion fails.\n", + "#E7", + "LLM", + "Add functionality to the BooleanValidator plugin from #E6 to include options for default values when conversion fails", + "Plan: Implement options for default values when conversion fails.\n#E7 = LLM[Add functionality to the BooleanValidator plugin from #E6 to include options for default values when conversion fails]" + ], + [ + "Create the recordHook version of the Boolean Validator plugin.\n", + "#E8", + "LLM", + "Convert the BooleanValidator plugin from #E7 into a recordHook version, ensuring it adheres to the recordHook structure and requirements based on the information in #E1", + "Plan: Create the recordHook version of the Boolean Validator plugin.\n#E8 = LLM[Convert the BooleanValidator plugin from #E7 into a recordHook version, ensuring it adheres to the recordHook structure and requirements based on the information in #E1]" + ], + [ + "Create the external constraint version of the Boolean Validator plugin.\n", + "#E9", + "LLM", + "Convert the BooleanValidator plugin from #E7 into an external constraint version, ensuring it adheres to the external constraint structure and requirements based on the information in #E1", + "Plan: Create the external constraint version of the Boolean Validator plugin.\n#E9 = LLM[Convert the BooleanValidator plugin from #E7 into an external constraint version, ensuring it adheres to the external constraint structure and requirements based on the information in #E1]" + ], + [ + "Combine all components and create the final Boolean Validator Flatfile Listener plugin with both recordHook and external constraint versions.\n", + "#E10", + "LLM", + "Combine the BooleanValidator plugin implementations from #E7, #E8, and #E9 into a single file, exporting both recordHook and external constraint versions. Ensure all required functionality is included and the code is properly structured and commented", + "Plan: Combine all components and create the final Boolean Validator Flatfile Listener plugin with both recordHook and external constraint versions.\n#E10 = LLM[Combine the BooleanValidator plugin implementations from #E7, #E8, and #E9 into a single file, exporting both recordHook and external constraint versions. Ensure all required functionality is included and the code is properly structured and commented]" + ], + [ + "Validate the final Boolean Validator plugin code, check for unused imports, and ensure correct Event Topic usage.\n", + "#E11", + "PineconeAssistant", + "Validate the Boolean Validator plugin code from #E10, check for unused imports, ensure correct Event Topic usage, and verify that all required functionality is implemented correctly", + "Plan: Validate the final Boolean Validator plugin code, check for unused imports, and ensure correct Event Topic usage.\n#E11 = PineconeAssistant[Validate the Boolean Validator plugin code from #E10, check for unused imports, ensure correct Event Topic usage, and verify that all required functionality is implemented correctly]" + ], + [ + "Make any necessary corrections or improvements based on the validation results.\n", + "#E12", + "LLM", + "Review the validation results from #E11 and make any necessary corrections or improvements to the Boolean Validator plugin code", + "Plan: Make any necessary corrections or improvements based on the validation results.\n#E12 = LLM[Review the validation results from #E11 and make any necessary corrections or improvements to the Boolean Validator plugin code]" + ] + ], + "metrics": { + "tokens": { + "plan": 8662, + "state": 8209, + "total": 16871 + } + } +} \ No newline at end of file diff --git a/validators/BooleanValidator/package.json b/validate/boolean/package.json similarity index 79% rename from validators/BooleanValidator/package.json rename to validate/boolean/package.json index b83a788e9..eaa2e3762 100644 --- a/validators/BooleanValidator/package.json +++ b/validate/boolean/package.json @@ -1,7 +1,7 @@ { "name": "@flatfile/plugin-validate-boolean", "version": "1.0.0", - "description": "A Flatfile plugin for boolean validation and conversion", + "description": "A Flatfile plugin for boolean validation with multi-language support", "main": "./dist/index.js", "module": "./dist/index.mjs", "types": "./dist/index.d.ts", @@ -43,20 +43,13 @@ "author": "Your Name", "license": "MIT", "dependencies": { - "@flatfile/plugin-record-hook": "^1.7.0", - "@flatfile/util-common": "^1.4.0" + "@flatfile/plugin-record-hook": "^1.7.0" }, "peerDependencies": { "@flatfile/listener": "^1.0.5" }, "devDependencies": { - "@flatfile/hooks": "^1.5.0", - "@flatfile/rollup-config": "^0.1.1", - "typescript": "^5.6.2", - "@types/node": "^22.7.4", - "rollup": "^4.22.5", - "jest": "^29.7.0", - "@types/jest": "^29.5.13" + "@flatfile/rollup-config": "^0.1.1" }, "repository": { "type": "git", diff --git a/validators/BooleanValidator/rollup.config.mjs b/validate/boolean/rollup.config.mjs similarity index 100% rename from validators/BooleanValidator/rollup.config.mjs rename to validate/boolean/rollup.config.mjs diff --git a/validate/boolean/src/index.ts b/validate/boolean/src/index.ts new file mode 100644 index 000000000..904edd6f2 --- /dev/null +++ b/validate/boolean/src/index.ts @@ -0,0 +1,146 @@ +import { FlatfileListener } from '@flatfile/listener' +import { FlatfileRecord, recordHook } from '@flatfile/plugin-record-hook' + +interface BooleanValidatorConfig { + fields: string[] + validationType: 'strict' | 'truthy' + customMapping?: Record + caseSensitive?: boolean + handleNull?: 'error' | 'false' | 'true' | 'skip' + convertNonBoolean?: boolean + language?: string + customErrorMessages?: { + invalidBoolean?: string + invalidTruthy?: string + nullValue?: string + } + defaultValue?: boolean | 'skip' + sheetSlug?: string // New field to specify the sheet slug +} + +const languageMappings: Record> = { + en: { yes: true, no: false, y: true, n: false }, + es: { sí: true, si: true, no: false, s: true, n: false }, + fr: { oui: true, non: false, o: true, n: false }, + de: { ja: true, nein: false, j: true, n: false }, +} + +function handleNullValue( + record: FlatfileRecord, + field: string, + config: BooleanValidatorConfig +) { + switch (config.handleNull) { + case 'error': + record.addError( + field, + config.customErrorMessages?.nullValue || + 'Value cannot be null or undefined' + ) + break + case 'false': + record.set(field, false) + break + case 'true': + record.set(field, true) + break + case 'skip': + default: + // Do nothing, leave the field as is + break + } +} + +function validateStrictBoolean( + record: FlatfileRecord, + field: string, + value: any, + config: BooleanValidatorConfig +) { + const trueValues = config.caseSensitive ? ['true'] : ['true', 'True', 'TRUE'] + const falseValues = config.caseSensitive + ? ['false'] + : ['false', 'False', 'FALSE'] + + if (value === true || trueValues.includes(value)) { + record.set(field, true) + } else if (value === false || falseValues.includes(value)) { + record.set(field, false) + } else if (config.convertNonBoolean) { + record.set(field, Boolean(value)) + } else { + handleInvalidValue(record, field, config) + } +} + +function validateTruthyBoolean( + record: FlatfileRecord, + field: string, + value: any, + config: BooleanValidatorConfig +) { + const defaultMapping = config.language + ? languageMappings[config.language] + : languageMappings.en + const mapping = config.customMapping || defaultMapping + + let normalizedValue = value + if (typeof value === 'string' && !config.caseSensitive) { + normalizedValue = value.toLowerCase() + } + + if (normalizedValue === true || normalizedValue === false) { + record.set(field, normalizedValue) + } else if (mapping.hasOwnProperty(normalizedValue)) { + record.set(field, mapping[normalizedValue]) + } else if (config.convertNonBoolean) { + record.set(field, Boolean(value)) + } else { + handleInvalidValue(record, field, config) + } +} + +function handleInvalidValue( + record: FlatfileRecord, + field: string, + config: BooleanValidatorConfig +) { + if (config.defaultValue === undefined || config.defaultValue === 'skip') { + record.addError( + field, + config.customErrorMessages?.invalidBoolean || + 'Must be a valid boolean value' + ) + } else { + record.set(field, config.defaultValue) + record.addInfo( + field, + `Invalid value converted to default: ${config.defaultValue}` + ) + } +} + +// Updated RecordHook version +export const validateBoolean = (config: BooleanValidatorConfig) => { + return (listener: FlatfileListener) => { + listener.use( + recordHook(config.sheetSlug || '**', async (record: FlatfileRecord) => { + config.fields.forEach((field) => { + const value = record.get(field) + + if (value === null || value === undefined) { + handleNullValue(record, field, config) + } else if (config.validationType === 'strict') { + validateStrictBoolean(record, field, value, config) + } else { + validateTruthyBoolean(record, field, value, config) + } + }) + + return record + }) + ) + } +} + +export default validateBoolean diff --git a/validators/BooleanValidator/README.MD b/validators/BooleanValidator/README.MD deleted file mode 100644 index 75cef38b7..000000000 --- a/validators/BooleanValidator/README.MD +++ /dev/null @@ -1,79 +0,0 @@ -# Boolean Validator Plugin for Flatfile - -This plugin implements a Boolean Validator for Flatfile Listener that validates and converts boolean values in Flatfile records. It supports various options for validation, including multi-language representations, custom truthy/falsy values, and batch processing for large datasets. - -## Features - -- Strict or lenient boolean validation -- Custom truthy and falsy value support -- Multi-language representations -- Case-sensitive or case-insensitive validation -- Null value handling -- Conversion of non-boolean values -- Customizable error messages -- Default value option -- Batch processing for large datasets - -## Installation - -To install the plugin, run the following command: - -```bash -npm install @flatfile/plugin-boolean-validator -``` - -## Example Usage - -```javascript -import { FlatfileListener } from "@flatfile/listener"; -import booleanValidatorPlugin from "@flatfile/plugin-boolean-validator"; - -const listener = new FlatfileListener(); - -listener.use( - booleanValidatorPlugin(listener, { - strict: false, - allowTruthyFalsy: true, - caseSensitive: false, - allowNull: true, - convertNonBoolean: true, - languageRepresentations: { - en: { true: ["true", "yes"], false: ["false", "no"] }, - es: { true: ["verdadero", "sí"], false: ["falso", "no"] }, - }, - errorMessages: { - invalidBoolean: "Invalid boolean value", - }, - defaultValue: null, - batchSize: 1000, - }) -); -``` - -## Configuration - -The plugin accepts a `ValidationOptions` object with the following properties: - -- `strict`: Boolean, if true, only allows "true" and "false" values -- `allowTruthyFalsy`: Boolean, allows custom truthy/falsy values -- `customTruthyValues`: Array of strings, custom truthy values -- `customFalsyValues`: Array of strings, custom falsy values -- `caseSensitive`: Boolean, enables case-sensitive validation -- `allowNull`: Boolean, allows null values -- `convertNonBoolean`: Boolean, converts non-boolean values to boolean -- `languageRepresentations`: Object, multi-language representations for true/false -- `errorMessages`: Object, custom error messages -- `defaultValue`: Boolean or null, default value for invalid inputs -- `batchSize`: Number, batch size for processing large datasets - -## Behavior - -1. The plugin processes all fields ending with "_bool". -2. It validates the input based on the provided configuration. -3. If the input is valid, it converts it to a boolean value. -4. If the input is invalid: - - It assigns the default value if provided. - - It adds an error message to the record if no default value is set. -5. The plugin processes records in batches for better performance with large datasets. - -For detailed behavior on specific input types and validation rules, please refer to the source code and comments. \ No newline at end of file diff --git a/validators/BooleanValidator/metadata.json b/validators/BooleanValidator/metadata.json deleted file mode 100644 index b37f9d39b..000000000 --- a/validators/BooleanValidator/metadata.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "timestamp": "2024-09-27T16-52-25-463Z", - "task": "Create a Boolean Validator Flatfile Listener plugin:\n - Implement strict boolean validation (true/false only)\n - Add support for truthy/falsy value validation\n - Allow custom truthy/falsy value mapping (e.g., 'yes'/'no', '1'/'0')\n - Implement case-insensitive boolean string matching\n - Add options for handling null/undefined values\n - Implement conversion of non-boolean types to boolean\n - Add support for multi-language boolean representations\n - Implement custom error messages for invalid boolean values\n - Add options for default values when conversion fails\n - Implement batch processing for efficient boolean validation of large datasets", - "summary": "This code implements a Boolean Validator Flatfile Listener plugin that validates and converts boolean values in Flatfile records. It supports various options for validation, including multi-language representations, custom truthy/falsy values, and batch processing for large datasets.", - "steps": [ - [ - "Retrieve information about Flatfile Listeners and the Record Hook plugin to understand the structure and implementation details.\n", - "#E1", - "PineconeAssistant", - "Provide information about Flatfile Listeners and the Record Hook plugin, including their structure and implementation details", - "Plan: Retrieve information about Flatfile Listeners and the Record Hook plugin to understand the structure and implementation details.\n#E1 = PineconeAssistant[Provide information about Flatfile Listeners and the Record Hook plugin, including their structure and implementation details]" - ], - [ - "Based on the retrieved information, create the basic structure of the Boolean Validator Listener plugin.\n", - "#E2", - "LLM", - "Using the information from #E1, create the basic structure of a Flatfile Listener plugin for boolean validation", - "Plan: Based on the retrieved information, create the basic structure of the Boolean Validator Listener plugin.\n#E2 = LLM[Using the information from #E1, create the basic structure of a Flatfile Listener plugin for boolean validation]" - ], - [ - "Implement strict boolean validation (true/false only) and add support for truthy/falsy value validation.\n", - "#E3", - "LLM", - "Extend the code from #E2 to implement strict boolean validation and support for truthy/falsy value validation", - "Plan: Implement strict boolean validation (true/false only) and add support for truthy/falsy value validation.\n#E3 = LLM[Extend the code from #E2 to implement strict boolean validation and support for truthy/falsy value validation]" - ], - [ - "Add support for custom truthy/falsy value mapping and case-insensitive boolean string matching.\n", - "#E4", - "LLM", - "Extend the code from #E3 to add support for custom truthy/falsy value mapping and case-insensitive boolean string matching", - "Plan: Add support for custom truthy/falsy value mapping and case-insensitive boolean string matching.\n#E4 = LLM[Extend the code from #E3 to add support for custom truthy/falsy value mapping and case-insensitive boolean string matching]" - ], - [ - "Implement handling for null/undefined values and conversion of non-boolean types to boolean.\n", - "#E5", - "LLM", - "Extend the code from #E4 to handle null/undefined values and implement conversion of non-boolean types to boolean", - "Plan: Implement handling for null/undefined values and conversion of non-boolean types to boolean.\n#E5 = LLM[Extend the code from #E4 to handle null/undefined values and implement conversion of non-boolean types to boolean]" - ], - [ - "Add support for multi-language boolean representations and custom error messages for invalid boolean values.\n", - "#E6", - "LLM", - "Extend the code from #E5 to add support for multi-language boolean representations and custom error messages for invalid boolean values", - "Plan: Add support for multi-language boolean representations and custom error messages for invalid boolean values.\n#E6 = LLM[Extend the code from #E5 to add support for multi-language boolean representations and custom error messages for invalid boolean values]" - ], - [ - "Implement options for default values when conversion fails and batch processing for efficient boolean validation of large datasets.\n", - "#E7", - "LLM", - "Extend the code from #E6 to implement options for default values when conversion fails and batch processing for efficient boolean validation of large datasets", - "Plan: Implement options for default values when conversion fails and batch processing for efficient boolean validation of large datasets.\n#E7 = LLM[Extend the code from #E6 to implement options for default values when conversion fails and batch processing for efficient boolean validation of large datasets]" - ], - [ - "Verify that the implemented Listener is subscribed to valid Event Topics and uses appropriate Flatfile plugins or common utils.\n", - "#E8", - "PineconeAssistant", - "Verify that the Listener in #E7 is subscribed to valid Event Topics and uses appropriate Flatfile plugins or common utils. Provide any necessary corrections or suggestions.", - "Plan: Verify that the implemented Listener is subscribed to valid Event Topics and uses appropriate Flatfile plugins or common utils.\n#E8 = PineconeAssistant[Verify that the Listener in #E7 is subscribed to valid Event Topics and uses appropriate Flatfile plugins or common utils. Provide any necessary corrections or suggestions.]" - ], - [ - "Finalize the Boolean Validator Flatfile Listener plugin by incorporating any corrections or suggestions from the previous step.\n", - "#E9", - "LLM", - "Incorporate the corrections and suggestions from #E8 into the code from #E7 to finalize the Boolean Validator Flatfile Listener plugin", - "Plan: Finalize the Boolean Validator Flatfile Listener plugin by incorporating any corrections or suggestions from the previous step.\n#E9 = LLM[Incorporate the corrections and suggestions from #E8 into the code from #E7 to finalize the Boolean Validator Flatfile Listener plugin]" - ], - [ - "Perform a final check to ensure all requirements are met, remove any unused imports, and validate the plugin's code and parameters.\n", - "#E10", - "LLM", - "Review the final code from #E9, ensure all requirements are met, remove any unused imports, and validate the plugin's code and parameters", - "Plan: Perform a final check to ensure all requirements are met, remove any unused imports, and validate the plugin's code and parameters.\n#E10 = LLM[Review the final code from #E9, ensure all requirements are met, remove any unused imports, and validate the plugin's code and parameters]" - ] - ], - "metrics": { - "tokens": { - "plan": 6011, - "state": 6623, - "total": 12634 - } - } -} \ No newline at end of file diff --git a/validators/BooleanValidator/src/index.ts b/validators/BooleanValidator/src/index.ts deleted file mode 100644 index 25d275961..000000000 --- a/validators/BooleanValidator/src/index.ts +++ /dev/null @@ -1,186 +0,0 @@ -import { recordHook } from '@flatfile/plugin-record-hook' -import { FlatfileListener } from '@flatfile/listener' -import { asyncBatch } from '@flatfile/util-common' - -interface ValidationOptions { - strict: boolean - allowTruthyFalsy: boolean - customTruthyValues?: string[] - customFalsyValues?: string[] - caseSensitive?: boolean - allowNull?: boolean - convertNonBoolean?: boolean - languageRepresentations?: Record - errorMessages?: { - invalidBoolean?: string - nullNotAllowed?: string - strictModeViolation?: string - } - defaultValue?: boolean | null - batchSize?: number -} - -export default function booleanValidatorPlugin( - listener: FlatfileListener, - options: ValidationOptions = { - strict: false, - allowTruthyFalsy: true, - caseSensitive: false, - allowNull: true, - convertNonBoolean: true, - languageRepresentations: { - en: { true: ['true', 'yes'], false: ['false', 'no'] }, - es: { true: ['verdadero', 'sí'], false: ['falso', 'no'] }, - fr: { true: ['vrai', 'oui'], false: ['faux', 'non'] }, - }, - errorMessages: { - invalidBoolean: 'Invalid boolean value', - nullNotAllowed: 'Null or undefined values are not allowed', - strictModeViolation: 'Only true or false are allowed in strict mode', - }, - defaultValue: null, - batchSize: 1000, - } -) { - listener.use( - recordHook( - '**', - async (records, event) => { - try { - await asyncBatch({ - items: records, - batchSize: options.batchSize || 1000, - asyncFn: async (batch) => { - await Promise.all( - batch.map(async (record) => { - for (const [fieldName, value] of Object.entries( - record.values - )) { - if (isBooleanField(fieldName)) { - validateBoolean(record, fieldName, value, options) - } - } - }) - ) - }, - }) - return records - } catch (error) { - console.error('Error in booleanValidatorPlugin:', error) - throw error - } - }, - { - concurrency: 10, - debug: false, - } - ) - ) -} - -function isBooleanField(fieldName: string): boolean { - return fieldName.endsWith('_bool') -} - -function validateBoolean( - record: any, - fieldName: string, - value: any, - options: ValidationOptions -): void { - if (value === null || value === undefined) { - if (options.allowNull) { - return - } else { - record.addError( - fieldName, - options.errorMessages?.nullNotAllowed || - 'Null or undefined values are not allowed' - ) - return - } - } - - if (typeof value === 'boolean') { - return - } - - if (options.strict) { - record.addError( - fieldName, - options.errorMessages?.strictModeViolation || - 'Only true or false are allowed in strict mode' - ) - return - } - - if (typeof value === 'string') { - const stringValue = options.caseSensitive ? value : value.toLowerCase() - const trimmedValue = stringValue.trim() - - if (['true', 'false'].includes(trimmedValue)) { - const boolValue = trimmedValue === 'true' - record.set(fieldName, boolValue) - return - } - - if (options.allowTruthyFalsy) { - const defaultTruthyValues = ['yes', '1', 'on'] - const defaultFalsyValues = ['no', '0', 'off'] - - const truthyValues = options.customTruthyValues || defaultTruthyValues - const falsyValues = options.customFalsyValues || defaultFalsyValues - - if (truthyValues.includes(trimmedValue)) { - record.set(fieldName, true) - return - } - if (falsyValues.includes(trimmedValue)) { - record.set(fieldName, false) - return - } - } - - if (options.languageRepresentations) { - for (const langRepresentations of Object.values( - options.languageRepresentations - )) { - if (langRepresentations.true.includes(trimmedValue)) { - record.set(fieldName, true) - return - } - if (langRepresentations.false.includes(trimmedValue)) { - record.set(fieldName, false) - return - } - } - } - } - - if (options.allowTruthyFalsy && typeof value === 'number') { - if (value === 1) { - record.set(fieldName, true) - return - } - if (value === 0) { - record.set(fieldName, false) - return - } - } - - if (options.convertNonBoolean) { - const boolValue = Boolean(value) - record.set(fieldName, boolValue) - return - } - - if (options.defaultValue !== undefined) { - record.set(fieldName, options.defaultValue) - return - } - - record.addError( - fieldName, - options.errorMessages?.invalidBoolean || 'Invalid boolean value' - ) -} From 63144c9d431e0402901708eb0b5e480fa6a5278a Mon Sep 17 00:00:00 2001 From: Alex Rock Date: Tue, 1 Oct 2024 00:35:05 -0600 Subject: [PATCH 3/8] feat: add tests --- validate/boolean/src/index.ts | 17 +- .../boolean/src/validateBoolean.e2e.spec.ts | 176 ++++++++++++++++++ 2 files changed, 182 insertions(+), 11 deletions(-) create mode 100644 validate/boolean/src/validateBoolean.e2e.spec.ts diff --git a/validate/boolean/src/index.ts b/validate/boolean/src/index.ts index 904edd6f2..3ee691ef7 100644 --- a/validate/boolean/src/index.ts +++ b/validate/boolean/src/index.ts @@ -51,21 +51,15 @@ function handleNullValue( } } + function validateStrictBoolean( record: FlatfileRecord, field: string, value: any, config: BooleanValidatorConfig ) { - const trueValues = config.caseSensitive ? ['true'] : ['true', 'True', 'TRUE'] - const falseValues = config.caseSensitive - ? ['false'] - : ['false', 'False', 'FALSE'] - - if (value === true || trueValues.includes(value)) { - record.set(field, true) - } else if (value === false || falseValues.includes(value)) { - record.set(field, false) + if ( value === true || value === false) { + record.set(field, value) } else if (config.convertNonBoolean) { record.set(field, Boolean(value)) } else { @@ -93,13 +87,14 @@ function validateTruthyBoolean( record.set(field, normalizedValue) } else if (mapping.hasOwnProperty(normalizedValue)) { record.set(field, mapping[normalizedValue]) + } else if (typeof normalizedValue === 'number') { + record.set(field, Boolean(normalizedValue)) } else if (config.convertNonBoolean) { record.set(field, Boolean(value)) } else { handleInvalidValue(record, field, config) } } - function handleInvalidValue( record: FlatfileRecord, field: string, @@ -109,7 +104,7 @@ function handleInvalidValue( record.addError( field, config.customErrorMessages?.invalidBoolean || - 'Must be a valid boolean value' + 'Invalid boolean value' ) } else { record.set(field, config.defaultValue) diff --git a/validate/boolean/src/validateBoolean.e2e.spec.ts b/validate/boolean/src/validateBoolean.e2e.spec.ts new file mode 100644 index 000000000..4f22de174 --- /dev/null +++ b/validate/boolean/src/validateBoolean.e2e.spec.ts @@ -0,0 +1,176 @@ +import { FlatfileClient } from '@flatfile/api' +import { + createRecords, + deleteSpace, + getRecords, + setupListener, + setupSimpleWorkbook, + setupSpace, +} from '@flatfile/utils-testing' +import { validateBoolean } from './index' + +const api = new FlatfileClient() + +describe('validateBoolean e2e', () => { + const listener = setupListener() + + // Console spies + const logSpy = jest.spyOn(global.console, 'log') + const logErrorSpy = jest.spyOn(global.console, 'error') + + let spaceId: string + let sheetId: string + + beforeAll(async () => { + const space = await setupSpace() + spaceId = space.id + const workbook = await setupSimpleWorkbook(space.id, [ + { key: 'isActive', type: 'boolean' }, + { key: 'hasSubscription', type: 'boolean' }, + { key: 'agreeToTerms', type: 'boolean' }, + { key: 'optIn', type: 'boolean' }, + ]) + sheetId = workbook.sheets![0].id + }) + + afterAll(async () => { + await deleteSpace(spaceId) + }) + + afterEach(async () => { + listener.reset() + logSpy.mockReset() + logErrorSpy.mockReset() + const records = await getRecords(sheetId) + if (records.length > 0) { + const ids = records.map((record) => record.id) + await api.records.delete(sheetId, { ids }) + } + }) + + describe('validateBoolean()', () => { + it('validates strict boolean values', async () => { + listener.use( + validateBoolean({ + fields: ['isActive'], + validationType: 'strict' + }) + ) + + await createRecords(sheetId, [ + { isActive: true }, + { isActive: false }, + { isActive: 'true' }, + { isActive: 'false' }, + { isActive: 1 }, + { isActive: 0 }, + ]) + await listener.waitFor('commit:created') + + const records = await getRecords(sheetId) + + expect(records[0].values['isActive'].value).toBe(true) + expect(records[1].values['isActive'].value).toBe(false) + expect(records[2].values['isActive'].value).toBe(true) + expect(records[3].values['isActive'].value).toBe(false) + expect(records[4].values['isActive'].messages[0].message).toContain('Invalid boolean value') + expect(records[5].values['isActive'].messages[0].message).toContain('Invalid boolean value') + + }) + + it('validates truthy boolean values', async () => { + listener.use( + validateBoolean({ + fields: ['hasSubscription'], + validationType: 'truthy', + }) + ) + + await createRecords(sheetId, [ + { hasSubscription: true }, + { hasSubscription: false }, + { hasSubscription: 'true' }, + { hasSubscription: 'false' }, + { hasSubscription: 1 }, + { hasSubscription: 0 }, + { hasSubscription: 'yes' }, + { hasSubscription: 'no' }, + ]) + await listener.waitFor('commit:created') + + const records = await getRecords(sheetId) + + expect(records[0].values['hasSubscription'].value).toBeTruthy() + expect(records[1].values['hasSubscription'].value).toBeFalsy() + expect(records[2].values['hasSubscription'].value).toBeTruthy() + expect(records[3].values['hasSubscription'].value).toBeFalsy() + expect(records[4].values['hasSubscription'].value).toBeTruthy() + expect(records[5].values['hasSubscription'].value).toBeFalsy() + expect(records[6].values['hasSubscription'].value).toBeTruthy() + expect(records[7].values['hasSubscription'].value).toBeFalsy() + }) + + it('handles custom mapping', async () => { + listener.use( + validateBoolean({ + fields: ['agreeToTerms'], + validationType: 'truthy', + customMapping: { 'agreed': true, 'disagreed': false }, + }) + ) + + await createRecords(sheetId, [ + { agreeToTerms: 'agreed' }, + { agreeToTerms: 'disagreed' }, + { agreeToTerms: 'yes' }, + ]) + await listener.waitFor('commit:created') + + const records = await getRecords(sheetId) + + expect(records[0].values['agreeToTerms'].value).toBeTruthy() + expect(records[1].values['agreeToTerms'].value).toBeFalsy() + expect(records[2].values['agreeToTerms'].value).toBeTruthy() + }) + + it('handles null values', async () => { + listener.use( + validateBoolean({ + fields: ['optIn'], + validationType: 'truthy', + handleNull: 'false', + }) + ) + + await createRecords(sheetId, [ + { optIn: null }, + { optIn: undefined }, + { optIn: '' }, + ]) + await listener.waitFor('commit:created') + + const records = await getRecords(sheetId) + + expect(records[0].values['optIn'].value).toBe(false) + expect(records[1].values['optIn'].value).toBe(false) + expect(records[2].values['optIn'].value).toBe(false) + }) + + it('handles errors', async () => { + listener.use( + validateBoolean({ + fields: ['isActive'], + validationType: 'truthy', + }) + ) + + await createRecords(sheetId, [{ isActive: 'invalid' }]) + await listener.waitFor('commit:created') + + const records = await getRecords(sheetId) + + expect(records[0].values['isActive'].value).toBe('invalid') + expect(records[0].values['isActive'].messages[0].message).toContain('Invalid boolean value') + }) + }) +}) From 1cbd69564d8ef5302105b9e0c9646c7ec140a9b8 Mon Sep 17 00:00:00 2001 From: Alex Rock Date: Thu, 3 Oct 2024 14:27:51 -0600 Subject: [PATCH 4/8] Apply suggestions from code review Co-authored-by: Carl Brugger --- validate/boolean/package.json | 18 +++++++----------- validate/boolean/src/index.ts | 4 ++-- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/validate/boolean/package.json b/validate/boolean/package.json index eaa2e3762..dae56d524 100644 --- a/validate/boolean/package.json +++ b/validate/boolean/package.json @@ -6,17 +6,17 @@ "module": "./dist/index.mjs", "types": "./dist/index.d.ts", "browser": { - "./dist/index.js": "./dist/index.browser.js", + "./dist/index.cjs": "./dist/index.browser.cjs", "./dist/index.mjs": "./dist/index.browser.mjs" }, "exports": { "types": "./dist/index.d.ts", "node": { "import": "./dist/index.mjs", - "require": "./dist/index.js" + "require": "./dist/index.cjs" }, "browser": { - "require": "./dist/index.browser.js", + "require": "./dist/index.browser.cjs", "import": "./dist/index.browser.mjs" }, "default": "./dist/index.mjs" @@ -33,15 +33,11 @@ "test": "jest ./**/*.spec.ts --config=../../jest.config.js --runInBand" }, "keywords": [ - "flatfile", - "plugin", - "boolean", - "validator", "flatfile-plugins", - "category-transform" + "category-validate" ], - "author": "Your Name", - "license": "MIT", + "author": "Flatfile, Inc.", + "license": "ISC", "dependencies": { "@flatfile/plugin-record-hook": "^1.7.0" }, @@ -54,7 +50,7 @@ "repository": { "type": "git", "url": "https://github.com/FlatFilers/flatfile-plugins.git", - "directory": "plugins/boolean-validator" + "directory": "validate/boolean" }, "browserslist": [ "> 0.5%", diff --git a/validate/boolean/src/index.ts b/validate/boolean/src/index.ts index 3ee691ef7..f6d73fb17 100644 --- a/validate/boolean/src/index.ts +++ b/validate/boolean/src/index.ts @@ -1,5 +1,5 @@ -import { FlatfileListener } from '@flatfile/listener' -import { FlatfileRecord, recordHook } from '@flatfile/plugin-record-hook' +import { type FlatfileListener } from '@flatfile/listener' +import { type FlatfileRecord, recordHook } from '@flatfile/plugin-record-hook' interface BooleanValidatorConfig { fields: string[] From 8250fcc85545c3c19bb934fa2b11b3c93b26468e Mon Sep 17 00:00:00 2001 From: Alex Rock Date: Fri, 4 Oct 2024 13:22:25 -0600 Subject: [PATCH 5/8] feat: rename structure --- validate/boolean/src/index.ts | 142 +----------------- ...ts => validate.boolean.plugin.e2e.spec.ts} | 2 +- .../boolean/src/validate.boolean.plugin.ts | 139 +++++++++++++++++ 3 files changed, 141 insertions(+), 142 deletions(-) rename validate/boolean/src/{validateBoolean.e2e.spec.ts => validate.boolean.plugin.e2e.spec.ts} (98%) create mode 100644 validate/boolean/src/validate.boolean.plugin.ts diff --git a/validate/boolean/src/index.ts b/validate/boolean/src/index.ts index f6d73fb17..98c6b6d69 100644 --- a/validate/boolean/src/index.ts +++ b/validate/boolean/src/index.ts @@ -1,141 +1 @@ -import { type FlatfileListener } from '@flatfile/listener' -import { type FlatfileRecord, recordHook } from '@flatfile/plugin-record-hook' - -interface BooleanValidatorConfig { - fields: string[] - validationType: 'strict' | 'truthy' - customMapping?: Record - caseSensitive?: boolean - handleNull?: 'error' | 'false' | 'true' | 'skip' - convertNonBoolean?: boolean - language?: string - customErrorMessages?: { - invalidBoolean?: string - invalidTruthy?: string - nullValue?: string - } - defaultValue?: boolean | 'skip' - sheetSlug?: string // New field to specify the sheet slug -} - -const languageMappings: Record> = { - en: { yes: true, no: false, y: true, n: false }, - es: { sí: true, si: true, no: false, s: true, n: false }, - fr: { oui: true, non: false, o: true, n: false }, - de: { ja: true, nein: false, j: true, n: false }, -} - -function handleNullValue( - record: FlatfileRecord, - field: string, - config: BooleanValidatorConfig -) { - switch (config.handleNull) { - case 'error': - record.addError( - field, - config.customErrorMessages?.nullValue || - 'Value cannot be null or undefined' - ) - break - case 'false': - record.set(field, false) - break - case 'true': - record.set(field, true) - break - case 'skip': - default: - // Do nothing, leave the field as is - break - } -} - - -function validateStrictBoolean( - record: FlatfileRecord, - field: string, - value: any, - config: BooleanValidatorConfig -) { - if ( value === true || value === false) { - record.set(field, value) - } else if (config.convertNonBoolean) { - record.set(field, Boolean(value)) - } else { - handleInvalidValue(record, field, config) - } -} - -function validateTruthyBoolean( - record: FlatfileRecord, - field: string, - value: any, - config: BooleanValidatorConfig -) { - const defaultMapping = config.language - ? languageMappings[config.language] - : languageMappings.en - const mapping = config.customMapping || defaultMapping - - let normalizedValue = value - if (typeof value === 'string' && !config.caseSensitive) { - normalizedValue = value.toLowerCase() - } - - if (normalizedValue === true || normalizedValue === false) { - record.set(field, normalizedValue) - } else if (mapping.hasOwnProperty(normalizedValue)) { - record.set(field, mapping[normalizedValue]) - } else if (typeof normalizedValue === 'number') { - record.set(field, Boolean(normalizedValue)) - } else if (config.convertNonBoolean) { - record.set(field, Boolean(value)) - } else { - handleInvalidValue(record, field, config) - } -} -function handleInvalidValue( - record: FlatfileRecord, - field: string, - config: BooleanValidatorConfig -) { - if (config.defaultValue === undefined || config.defaultValue === 'skip') { - record.addError( - field, - config.customErrorMessages?.invalidBoolean || - 'Invalid boolean value' - ) - } else { - record.set(field, config.defaultValue) - record.addInfo( - field, - `Invalid value converted to default: ${config.defaultValue}` - ) - } -} - -// Updated RecordHook version -export const validateBoolean = (config: BooleanValidatorConfig) => { - return (listener: FlatfileListener) => { - listener.use( - recordHook(config.sheetSlug || '**', async (record: FlatfileRecord) => { - config.fields.forEach((field) => { - const value = record.get(field) - - if (value === null || value === undefined) { - handleNullValue(record, field, config) - } else if (config.validationType === 'strict') { - validateStrictBoolean(record, field, value, config) - } else { - validateTruthyBoolean(record, field, value, config) - } - }) - - return record - }) - ) - } -} - -export default validateBoolean +export * from './validate.boolean.plugin' diff --git a/validate/boolean/src/validateBoolean.e2e.spec.ts b/validate/boolean/src/validate.boolean.plugin.e2e.spec.ts similarity index 98% rename from validate/boolean/src/validateBoolean.e2e.spec.ts rename to validate/boolean/src/validate.boolean.plugin.e2e.spec.ts index 4f22de174..65ed9a71c 100644 --- a/validate/boolean/src/validateBoolean.e2e.spec.ts +++ b/validate/boolean/src/validate.boolean.plugin.e2e.spec.ts @@ -7,7 +7,7 @@ import { setupSimpleWorkbook, setupSpace, } from '@flatfile/utils-testing' -import { validateBoolean } from './index' +import { validateBoolean } from './validate.boolean.plugin' const api = new FlatfileClient() diff --git a/validate/boolean/src/validate.boolean.plugin.ts b/validate/boolean/src/validate.boolean.plugin.ts new file mode 100644 index 000000000..a3a179ba4 --- /dev/null +++ b/validate/boolean/src/validate.boolean.plugin.ts @@ -0,0 +1,139 @@ +import { type FlatfileListener } from '@flatfile/listener' +import { type FlatfileRecord, recordHook } from '@flatfile/plugin-record-hook' + +export interface BooleanValidatorConfig { + fields: string[] + validationType: 'strict' | 'truthy' + customMapping?: Record + caseSensitive?: boolean + handleNull?: 'error' | 'false' | 'true' | 'skip' + convertNonBoolean?: boolean + language?: string + customErrorMessages?: { + invalidBoolean?: string + invalidTruthy?: string + nullValue?: string + } + defaultValue?: boolean | 'skip' + sheetSlug?: string // New field to specify the sheet slug +} + +export const languageMappings: Record> = { + en: { yes: true, no: false, y: true, n: false }, + es: { sí: true, si: true, no: false, s: true, n: false }, + fr: { oui: true, non: false, o: true, n: false }, + de: { ja: true, nein: false, j: true, n: false }, +} + +export function handleNullValue( + record: FlatfileRecord, + field: string, + config: BooleanValidatorConfig +) { + switch (config.handleNull) { + case 'error': + record.addError( + field, + config.customErrorMessages?.nullValue || + 'Value cannot be null or undefined' + ) + break + case 'false': + record.set(field, false) + break + case 'true': + record.set(field, true) + break + case 'skip': + default: + // Do nothing, leave the field as is + break + } +} + +export function validateStrictBoolean( + record: FlatfileRecord, + field: string, + value: any, + config: BooleanValidatorConfig +) { + if (value === true || value === false) { + record.set(field, value) + } else if (config.convertNonBoolean) { + record.set(field, Boolean(value)) + } else { + handleInvalidValue(record, field, config) + } +} + +export function validateTruthyBoolean( + record: FlatfileRecord, + field: string, + value: any, + config: BooleanValidatorConfig +) { + const defaultMapping = config.language + ? languageMappings[config.language] + : languageMappings.en + const mapping = config.customMapping || defaultMapping + + let normalizedValue = value + if (typeof value === 'string' && !config.caseSensitive) { + normalizedValue = value.toLowerCase() + } + + if (normalizedValue === true || normalizedValue === false) { + record.set(field, normalizedValue) + } else if (mapping.hasOwnProperty(normalizedValue)) { + record.set(field, mapping[normalizedValue]) + } else if (typeof normalizedValue === 'number') { + record.set(field, Boolean(normalizedValue)) + } else if (config.convertNonBoolean) { + record.set(field, Boolean(value)) + } else { + handleInvalidValue(record, field, config) + } +} +export function handleInvalidValue( + record: FlatfileRecord, + field: string, + config: BooleanValidatorConfig +) { + if (config.defaultValue === undefined || config.defaultValue === 'skip') { + record.addError( + field, + config.customErrorMessages?.invalidBoolean || 'Invalid boolean value' + ) + } else { + record.set(field, config.defaultValue) + record.addInfo( + field, + `Invalid value converted to default: ${config.defaultValue}` + ) + } +} + +// Updated RecordHook version +export const validateBoolean = (config: BooleanValidatorConfig) => { + return (listener: FlatfileListener) => { + listener.use( + recordHook(config.sheetSlug || '**', async (record: FlatfileRecord) => { + config.fields.forEach((field) => { + const value = record.get(field) + + if (value === null || value === undefined) { + handleNullValue(record, field, config) + } else if (config.validationType === 'strict') { + validateStrictBoolean(record, field, value, config) + } else { + validateTruthyBoolean(record, field, value, config) + } + }) + + return record + }) + ) + } +} + +export default validateBoolean From 9af220e94e3f2b0712f0135298ccc6f85cfe77cf Mon Sep 17 00:00:00 2001 From: Alex Rock Date: Fri, 4 Oct 2024 13:26:08 -0600 Subject: [PATCH 6/8] feat: fix readme --- validate/boolean/README.MD | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/validate/boolean/README.MD b/validate/boolean/README.MD index f5d283a19..a1eab871f 100644 --- a/validate/boolean/README.MD +++ b/validate/boolean/README.MD @@ -1,6 +1,12 @@ -# Flatfile Boolean Validator Plugin + +# @flatfile/plugin-validate-boolean -This plugin provides a robust Boolean validation solution for Flatfile, offering flexible configuration options to handle various boolean representations across different languages and use cases. +The `@flatfile/plugin-validate-boolean` plugin provides comprehensive boolean validation capabilities, offering flexible configuration options to handle various boolean representations across different languages and use cases. + +**Event Type:** +`listener.on('commit:created')` + + ## Features @@ -18,13 +24,13 @@ This plugin provides a robust Boolean validation solution for Flatfile, offering To install the plugin, run the following command: ```bash -npm install @flatfile/plugin-boolean-validator +npm install @flatfile/plugin-validate-boolean ``` ## Example Usage ```javascript -import { validateBoolean } from '@flatfile/plugin-boolean-validator'; +import { validateBoolean } from '@flatfile/plugin-validate-boolean'; const booleanValidator = validateBoolean({ fields: ['isActive', 'hasSubscription'], From 6c4fd7794e83d1beadceb09310e09623f74e8c61 Mon Sep 17 00:00:00 2001 From: Alex Rock Date: Fri, 4 Oct 2024 16:04:09 -0600 Subject: [PATCH 7/8] feat: fix package-lock.json --- package-lock.json | 180 +++++++++++++++++++++++++--------------------- 1 file changed, 99 insertions(+), 81 deletions(-) diff --git a/package-lock.json b/package-lock.json index a5abc975a..18530b0eb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -81,6 +81,7 @@ "flatfilers/playground": { "name": "@private/playground", "version": "0.0.0", + "extraneous": true, "license": "ISC", "dependencies": { "@flatfile/api": "^1.9.19", @@ -3188,6 +3189,10 @@ "resolved": "plugins/tsv-extractor", "link": true }, + "node_modules/@flatfile/plugin-validate-boolean": { + "resolved": "validate/boolean", + "link": true + }, "node_modules/@flatfile/plugin-validate-isbn": { "resolved": "validate/isbn", "link": true @@ -20206,14 +20211,14 @@ }, "plugins/autocast": { "name": "@flatfile/plugin-autocast", - "version": "2.0.0", + "version": "2.0.1", "license": "ISC", "dependencies": { "@flatfile/hooks": "^1.4.1", - "@flatfile/util-common": "^1.4.0" + "@flatfile/util-common": "^1.4.1" }, "devDependencies": { - "@flatfile/plugin-record-hook": "^1.7.0", + "@flatfile/plugin-record-hook": "^1.7.1", "@flatfile/rollup-config": "0.1.1" }, "engines": { @@ -20222,19 +20227,19 @@ "peerDependencies": { "@flatfile/api": "^1.9.19", "@flatfile/listener": "^1.1.0", - "@flatfile/plugin-record-hook": "^1.7.0" + "@flatfile/plugin-record-hook": "^1.7.1" } }, "plugins/automap": { "name": "@flatfile/plugin-automap", - "version": "0.5.0", + "version": "0.5.1", "license": "ISC", "dependencies": { "@flatfile/common-plugin-utils": "^1.0.2", "remeda": "^1.23.0" }, "devDependencies": { - "@flatfile/utils-testing": "^0.3.0" + "@flatfile/utils-testing": "^0.3.1" }, "engines": { "node": ">= 16" @@ -20246,10 +20251,10 @@ }, "plugins/constraints": { "name": "@flatfile/plugin-constraints", - "version": "3.0.0", + "version": "3.0.1", "license": "ISC", "devDependencies": { - "@flatfile/plugin-record-hook": "^1.7.0", + "@flatfile/plugin-record-hook": "^1.7.1", "@flatfile/rollup-config": "0.1.1" }, "engines": { @@ -20258,16 +20263,16 @@ "peerDependencies": { "@flatfile/api": "^1.9.19", "@flatfile/listener": "^1.1.0", - "@flatfile/plugin-record-hook": "^1.7.0" + "@flatfile/plugin-record-hook": "^1.7.1" } }, "plugins/dedupe": { "name": "@flatfile/plugin-dedupe", - "version": "1.2.0", + "version": "1.2.1", "license": "ISC", "dependencies": { - "@flatfile/plugin-job-handler": "^0.6.0", - "@flatfile/util-common": "^1.4.0" + "@flatfile/plugin-job-handler": "^0.6.1", + "@flatfile/util-common": "^1.4.1" }, "devDependencies": { "@faker-js/faker": "^7.6.0", @@ -20283,10 +20288,10 @@ }, "plugins/delimiter-extractor": { "name": "@flatfile/plugin-delimiter-extractor", - "version": "2.2.1", + "version": "2.2.2", "license": "ISC", "dependencies": { - "@flatfile/util-extractor": "^2.1.2", + "@flatfile/util-extractor": "^2.1.7", "papaparse": "^5.4.1", "remeda": "^1.14.0" }, @@ -20303,7 +20308,7 @@ }, "plugins/dxp-configure": { "name": "@flatfile/plugin-dxp-configure", - "version": "1.2.0", + "version": "1.2.1", "license": "ISC", "devDependencies": { "@flatfile/configure": "^1.0.1", @@ -20319,11 +20324,11 @@ }, "plugins/export-workbook": { "name": "@flatfile/plugin-export-workbook", - "version": "1.0.0", + "version": "1.0.1", "license": "ISC", "devDependencies": { - "@flatfile/plugin-job-handler": "^0.6.0", - "@flatfile/util-common": "^1.4.0" + "@flatfile/plugin-job-handler": "^0.6.1", + "@flatfile/util-common": "^1.4.1" }, "engines": { "node": ">= 16" @@ -20331,15 +20336,15 @@ "peerDependencies": { "@flatfile/api": "^1.9.19", "@flatfile/listener": "^1.1.0", - "@flatfile/plugin-job-handler": "^0.6.0", - "@flatfile/util-common": "^1.4.0", + "@flatfile/plugin-job-handler": "^0.6.1", + "@flatfile/util-common": "^1.4.1", "remeda": "^1.14.0", "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz" } }, "plugins/foreign-db-extractor": { "name": "@flatfile/plugin-foreign-db-extractor", - "version": "0.2.0", + "version": "0.2.1", "license": "ISC", "dependencies": { "cross-fetch": "^4.0.0", @@ -20358,10 +20363,10 @@ }, "plugins/graphql-schema": { "name": "@flatfile/plugin-graphql-schema", - "version": "1.3.0", + "version": "1.3.1", "license": "ISC", "dependencies": { - "@flatfile/plugin-space-configure": "^0.6.0", + "@flatfile/plugin-space-configure": "^0.6.1", "change-case": "^5.4.3", "cross-fetch": "^4.0.0", "graphql": "^16.8.1" @@ -20375,14 +20380,14 @@ }, "plugins/job-handler": { "name": "@flatfile/plugin-job-handler", - "version": "0.6.0", + "version": "0.6.1", "license": "ISC", "dependencies": { - "@flatfile/util-common": "^1.4.0" + "@flatfile/util-common": "^1.4.1" }, "devDependencies": { "@flatfile/rollup-config": "0.1.1", - "@flatfile/utils-testing": "^0.3.0" + "@flatfile/utils-testing": "^0.3.1" }, "engines": { "node": ">= 16" @@ -20408,10 +20413,10 @@ }, "plugins/json-schema": { "name": "@flatfile/plugin-convert-json-schema", - "version": "0.4.0", + "version": "0.4.1", "license": "ISC", "dependencies": { - "@flatfile/plugin-space-configure": "^0.6.0", + "@flatfile/plugin-space-configure": "^0.6.1", "cross-fetch": "^4.0.0" }, "engines": { @@ -20424,11 +20429,11 @@ }, "plugins/merge-connection": { "name": "@flatfile/plugin-connect-via-merge", - "version": "0.4.0", + "version": "0.4.1", "license": "ISC", "dependencies": { - "@flatfile/plugin-convert-openapi-schema": "^0.3.0", - "@flatfile/plugin-job-handler": "^0.6.0", + "@flatfile/plugin-convert-openapi-schema": "^0.3.1", + "@flatfile/plugin-job-handler": "^0.6.1", "@mergeapi/merge-node-client": "^1.0.4" }, "engines": { @@ -20441,10 +20446,10 @@ }, "plugins/openapi-schema": { "name": "@flatfile/plugin-convert-openapi-schema", - "version": "0.3.0", + "version": "0.3.1", "license": "ISC", "dependencies": { - "@flatfile/plugin-space-configure": "^0.6.0", + "@flatfile/plugin-space-configure": "^0.6.1", "cross-fetch": "^4.0.0" }, "devDependencies": { @@ -20460,11 +20465,11 @@ }, "plugins/pdf-extractor": { "name": "@flatfile/plugin-pdf-extractor", - "version": "0.3.0", + "version": "0.3.1", "license": "ISC", "dependencies": { - "@flatfile/util-common": "^1.4.0", - "@flatfile/util-file-buffer": "^0.4.0", + "@flatfile/util-common": "^1.4.1", + "@flatfile/util-file-buffer": "^0.4.1", "cross-fetch": "^4.0.0", "form-data": "^4.0.0", "fs-extra": "^11.1.1", @@ -20512,7 +20517,7 @@ }, "plugins/psv-extractor": { "name": "@flatfile/plugin-psv-extractor", - "version": "1.9.0", + "version": "1.9.1", "license": "ISC", "engines": { "node": ">= 16" @@ -20524,10 +20529,10 @@ }, "plugins/record-hook": { "name": "@flatfile/plugin-record-hook", - "version": "1.7.0", + "version": "1.7.1", "license": "ISC", "dependencies": { - "@flatfile/util-common": "^1.4.0" + "@flatfile/util-common": "^1.4.1" }, "devDependencies": { "@flatfile/rollup-config": "0.1.1" @@ -20543,11 +20548,11 @@ }, "plugins/rollout": { "name": "@flatfile/plugin-rollout", - "version": "1.1.0", + "version": "1.1.1", "license": "ISC", "dependencies": { - "@flatfile/plugin-job-handler": "^0.6.0", - "@flatfile/util-common": "^1.4.0", + "@flatfile/plugin-job-handler": "^0.6.1", + "@flatfile/util-common": "^1.4.1", "async": "^3.2.5", "modern-async": "^2.0.0" }, @@ -20564,15 +20569,15 @@ }, "plugins/space-configure": { "name": "@flatfile/plugin-space-configure", - "version": "0.6.0", + "version": "0.6.1", "license": "ISC", "dependencies": { - "@flatfile/plugin-job-handler": "^0.6.0" + "@flatfile/plugin-job-handler": "^0.6.1" }, "devDependencies": { "@flatfile/api": "^1.9.19", "@flatfile/rollup-config": "0.1.1", - "@flatfile/utils-testing": "^0.3.0" + "@flatfile/utils-testing": "^0.3.1" }, "engines": { "node": ">= 16" @@ -20584,11 +20589,11 @@ }, "plugins/sql-ddl-converter": { "name": "@flatfile/plugin-convert-sql-ddl", - "version": "0.2.0", + "version": "0.2.1", "license": "ISC", "dependencies": { - "@flatfile/plugin-convert-json-schema": "^0.4.0", - "@flatfile/plugin-space-configure": "^0.6.0", + "@flatfile/plugin-convert-json-schema": "^0.4.1", + "@flatfile/plugin-space-configure": "^0.6.1", "sql-ddl-to-json-schema": "^4.1.0" }, "engines": { @@ -20601,7 +20606,7 @@ }, "plugins/tsv-extractor": { "name": "@flatfile/plugin-tsv-extractor", - "version": "1.8.0", + "version": "1.8.1", "license": "ISC", "engines": { "node": ">= 16" @@ -20613,7 +20618,7 @@ }, "plugins/view-mapped": { "name": "@flatfile/plugin-view-mapped", - "version": "1.0.2", + "version": "1.0.3", "license": "ISC", "dependencies": { "@flatfile/api": "^1.9.19", @@ -20621,7 +20626,7 @@ }, "devDependencies": { "@flatfile/rollup-config": "0.1.1", - "@flatfile/utils-testing": "^0.3.0" + "@flatfile/utils-testing": "^0.3.1" }, "engines": { "node": ">= 16" @@ -20629,17 +20634,17 @@ }, "plugins/webhook-egress": { "name": "@flatfile/plugin-webhook-egress", - "version": "1.4.0", + "version": "1.4.1", "license": "ISC", "dependencies": { - "@flatfile/plugin-job-handler": "^0.6.0", - "@flatfile/util-common": "^1.4.0", - "@flatfile/util-response-rejection": "^1.4.0", + "@flatfile/plugin-job-handler": "^0.6.1", + "@flatfile/util-common": "^1.4.1", + "@flatfile/util-response-rejection": "^1.4.1", "cross-fetch": "^4.0.0" }, "devDependencies": { "@flatfile/rollup-config": "0.1.1", - "@flatfile/utils-testing": "^0.3.0", + "@flatfile/utils-testing": "^0.3.1", "jest-fetch-mock": "^3.0.3" }, "engines": { @@ -20652,7 +20657,7 @@ }, "plugins/webhook-event-forwarder": { "name": "@flatfile/plugin-webhook-event-forwarder", - "version": "0.4.0", + "version": "0.4.1", "license": "ISC", "dependencies": { "cross-fetch": "^4.0.0" @@ -20671,10 +20676,10 @@ }, "plugins/xlsx-extractor": { "name": "@flatfile/plugin-xlsx-extractor", - "version": "3.2.1", + "version": "3.2.2", "license": "ISC", "dependencies": { - "@flatfile/util-extractor": "^2.1.5", + "@flatfile/util-extractor": "^2.1.7", "remeda": "^1.14.0", "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz" }, @@ -20687,10 +20692,10 @@ }, "plugins/xml-extractor": { "name": "@flatfile/plugin-xml-extractor", - "version": "0.7.0", + "version": "0.7.1", "license": "ISC", "dependencies": { - "@flatfile/util-extractor": "^2.1.6", + "@flatfile/util-extractor": "^2.1.7", "remeda": "^1.24.0", "xml-json-format": "^1.0.8" }, @@ -20703,16 +20708,16 @@ }, "plugins/yaml-schema": { "name": "@flatfile/plugin-convert-yaml-schema", - "version": "0.3.0", + "version": "0.3.1", "license": "ISC", "dependencies": { - "@flatfile/plugin-convert-json-schema": "^0.4.0", - "@flatfile/plugin-space-configure": "^0.6.0", + "@flatfile/plugin-convert-json-schema": "^0.4.1", + "@flatfile/plugin-space-configure": "^0.6.1", "cross-fetch": "^4.0.0", "js-yaml": "^4.1.0" }, "devDependencies": { - "@flatfile/utils-testing": "^0.3.0", + "@flatfile/utils-testing": "^0.3.1", "express": "^4.18.2", "jest-fetch-mock": "^3.0.3" }, @@ -20740,17 +20745,17 @@ }, "plugins/zip-extractor": { "name": "@flatfile/plugin-zip-extractor", - "version": "0.6.0", + "version": "0.6.1", "license": "ISC", "dependencies": { - "@flatfile/plugin-job-handler": "^0.6.0", - "@flatfile/util-common": "^1.4.0", - "@flatfile/util-file-buffer": "^0.4.0", + "@flatfile/plugin-job-handler": "^0.6.1", + "@flatfile/util-common": "^1.4.1", + "@flatfile/util-file-buffer": "^0.4.1", "adm-zip": "^0.5.10", "modern-async": "^2.0.0" }, "devDependencies": { - "@flatfile/utils-testing": "^0.3.0", + "@flatfile/utils-testing": "^0.3.1", "@types/adm-zip": "^0.4.3" }, "engines": { @@ -20771,7 +20776,7 @@ }, "utils/common": { "name": "@flatfile/util-common", - "version": "1.4.0", + "version": "1.4.1", "license": "ISC", "dependencies": { "@flatfile/cross-env-config": "^0.0.6", @@ -20795,11 +20800,11 @@ }, "utils/extractor": { "name": "@flatfile/util-extractor", - "version": "2.1.6", + "version": "2.1.7", "license": "ISC", "dependencies": { - "@flatfile/util-common": "^1.4.0", - "@flatfile/util-file-buffer": "^0.4.0" + "@flatfile/util-common": "^1.4.1", + "@flatfile/util-file-buffer": "^0.4.1" }, "engines": { "node": ">= 16" @@ -20811,7 +20816,7 @@ }, "utils/fetch-schema": { "name": "@flatfile/util-fetch-schema", - "version": "0.2.3", + "version": "0.2.4", "license": "ISC", "dependencies": { "cross-fetch": "^4.0.0" @@ -20825,7 +20830,7 @@ }, "utils/file-buffer": { "name": "@flatfile/util-file-buffer", - "version": "0.4.0", + "version": "0.4.1", "license": "ISC", "engines": { "node": ">= 16" @@ -20837,10 +20842,10 @@ }, "utils/response-rejection": { "name": "@flatfile/util-response-rejection", - "version": "1.4.0", + "version": "1.4.1", "license": "ISC", "dependencies": { - "@flatfile/util-common": "^1.4.0" + "@flatfile/util-common": "^1.4.1" }, "devDependencies": { "@flatfile/rollup-config": "0.1.1" @@ -20854,7 +20859,7 @@ }, "utils/testing": { "name": "@flatfile/utils-testing", - "version": "0.3.0", + "version": "0.3.1", "license": "ISC", "dependencies": { "@flatfile/api": "^1.9.19", @@ -20867,10 +20872,23 @@ "node": ">= 16" } }, + "validate/boolean": { + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@flatfile/plugin-record-hook": "^1.7.0" + }, + "devDependencies": { + "@flatfile/rollup-config": "^0.1.1" + }, + "peerDependencies": { + "@flatfile/listener": "^1.0.5" + } + }, "validate/isbn": { "name": "@flatfile/plugin-validate-isbn", - "version": "1.0.0", - "license": "MIT", + "version": "0.0.0", + "license": "ISC", "dependencies": { "@flatfile/plugin-record-hook": "^1.7.0", "isbn3": "^1.2.0" From 67f2474199d977ffa02fb7555033f5a201cadc30 Mon Sep 17 00:00:00 2001 From: Carl Brugger Date: Fri, 4 Oct 2024 18:24:40 -0500 Subject: [PATCH 8/8] Apply suggestions from code review --- validate/boolean/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/validate/boolean/package.json b/validate/boolean/package.json index dae56d524..30a87182f 100644 --- a/validate/boolean/package.json +++ b/validate/boolean/package.json @@ -1,8 +1,8 @@ { "name": "@flatfile/plugin-validate-boolean", - "version": "1.0.0", + "version": "0.0.0", "description": "A Flatfile plugin for boolean validation with multi-language support", - "main": "./dist/index.js", + "main": "./dist/index.cjs", "module": "./dist/index.mjs", "types": "./dist/index.d.ts", "browser": {