Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

validator: string #650

Merged
merged 15 commits into from
Oct 9, 2024
24 changes: 22 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions validate/phone/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module.exports = {
testEnvironment: 'node',

transform: {
'^.+\\.tsx?$': 'ts-jest',
},
setupFiles: ['../../test/dotenv-config.js'],
setupFilesAfterEnv: [
'../../test/betterConsoleLog.js',
'../../test/unit.cleanup.js',
],
testTimeout: 60_000,
globalSetup: '../../test/setup-global.js',
forceExit: true,
passWithNoTests: true,
}
4 changes: 3 additions & 1 deletion validate/phone/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@
"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"
"test": "jest src/*.spec.ts --detectOpenHandles",
"test:unit": "jest src/*.spec.ts --testPathIgnorePatterns=.*\\.e2e\\.spec\\.ts$ --detectOpenHandles",
"test:e2e": "jest src/*.e2e.spec.ts --detectOpenHandles"
},
"keywords": [
"flatfile-plugins",
Expand Down
16 changes: 8 additions & 8 deletions validate/phone/src/validate.phone.utils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,50 +3,50 @@ import { NumberFormat } from 'libphonenumber-js';

describe('formatPhoneNumber', () => {
it('should format a valid US phone number', () => {
const result = formatPhoneNumber('2125551234', 'US', NumberFormat.NATIONAL);
const result = formatPhoneNumber('2125551234', 'US', 'NATIONAL');
expect(result).toEqual({
formattedPhone: '(212) 555-1234',
error: null,
});
});

it('should format a valid UK phone number', () => {
const result = formatPhoneNumber('2071234567', 'GB', NumberFormat.INTERNATIONAL);
const result = formatPhoneNumber('2071234567', 'GB', 'INTERNATIONAL');
expect(result).toEqual({
formattedPhone: '+44 20 7123 4567',
error: null,
});
});

it('should return an error for an invalid phone number', () => {
const result = formatPhoneNumber('1234', 'US', NumberFormat.NATIONAL);
const result = formatPhoneNumber('1234', 'US', 'NATIONAL');
expect(result).toEqual({
formattedPhone: '1234',
error: 'Invalid phone number format for US',
});
});

it('should handle different number formats', () => {
const result = formatPhoneNumber('2125551234', 'US', NumberFormat.E164);
const result = formatPhoneNumber('2125551234', 'US', 'E.164');
expect(result).toEqual({
formattedPhone: '+12125551234',
error: null,
});
});

it('should handle format options', () => {
const result = formatPhoneNumber('2125551234', 'US', NumberFormat.INTERNATIONAL, { formatExtension: 'national' });
it('should handle format options with a valid fromCountry', () => {
const result = formatPhoneNumber('2125551234', 'US', 'INTERNATIONAL', { fromCountry: 'GB' });
expect(result).toEqual({
formattedPhone: '+1 212 555 1234',
error: null,
});
});

it('should return an error for an invalid country code', () => {
const result = formatPhoneNumber('2125551234', 'XX', NumberFormat.NATIONAL);
const result = formatPhoneNumber('2125551234', 'XX', 'NATIONAL');
expect(result).toEqual({
formattedPhone: '2125551234',
error: 'Error processing phone number',
error: 'Invalid phone number format for XX',
});
});
});
87 changes: 87 additions & 0 deletions validate/string/README.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<!-- START_INFOCARD -->

The `@flatfile/plugin-validate-string` plugin for string configuration and validation. This plugin combines multiple string validations in a single configuration, including regex pattern matching, length validation, case sensitivity, trimming options, and custom transformations.

**Event Type:**
`listener.on('commit:created')`

<!-- END_INFOCARD -->
## Features
Comment on lines +8 to +9
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
<!-- END_INFOCARD -->
## Features
<!-- END_INFOCARD -->
## Features


- Regular expression pattern matching
- Length validation (min, max, exact)
- Case type enforcement (lowercase, uppercase, titlecase)
- Whitespace trimming (leading, trailing)
- Custom transformation functions
- Configurable error messages
- Common regex patterns for email, phone, and URL validation
- Empty string handling

## Installation

To install the plugin, use npm:

```bash
npm install @flatfile/plugin-validate-string
```

## Example Usage

```typescript
import { FlatfileListener } from '@flatfile/listener';
import { validateString } from '@flatfile/plugin-validate-string';

const listener = new FlatfileListener();

const stringConfig = {
fields: ['name'],
minLength: 2,
maxLength: 50,
caseType: 'titlecase',
errorMessages: {
length: 'Name must be between 2 and 50 characters',
case: 'Name must be in Title Case',
},

};

listener.use(validateString(stringConfig));
```

**Pattern usage:**
```typescript
const config = {
fields: ['email'],
pattern: 'email' // Uses predefined email pattern
};

// Or with a custom pattern:
const customConfig = {
fields: ['customField'],
pattern: /^[A-Z]{3}-\d{2}$/ // Custom pattern for format like 'ABC-12'
};
```
bangarang marked this conversation as resolved.
Show resolved Hide resolved

## Configuration

The `validateString` accepts a `StringValidationConfig` object with the following properties:
- `fields`: string[] - Fields to validate
- `sheetSlug`: string - Sheet slug to validate (defaults to '**' all sheets)
- `pattern`: RegExp - A regular expression pattern to match against
- `pattern`: keyof typeof commonRegexPatterns | RegExp - A regular expression pattern to match against. You can use one of the predefined patterns ('email', 'phone', 'url') or provide a custom RegExp. The predefined patterns are:
bangarang marked this conversation as resolved.
Show resolved Hide resolved
- `email`: Validates email addresses
- `phone`: Validates phone numbers (10-14 digits, optional '+' prefix)
- `url`: Validates URLs (with or without protocol)
- `minLength`: number - Minimum length of the string
- `maxLength`: number - Maximum length of the string
- `exactLength`: number - Exact required length of the string
- `caseType`: 'lowercase' | 'uppercase' | 'titlecase' - Enforces specific case type
- `trim`: { leading?: boolean, trailing?: boolean } - Trims whitespace
- `emptyStringAllowed`: boolean - Whether empty strings are allowed
- `errorMessages`: Object with custom error messages for different validations

## Behavior

The plugin processes each record in the Flatfile import, applying the configured validations to the specified fields. If a validation fails, an error is added to the record for that field. If a custom transformation is specified and all validations pass, the transformed value is set for the field.

The plugin uses the `recordHook` to process individual records, allowing for efficient and flexible validation and transformation of string fields during the import process.
16 changes: 16 additions & 0 deletions validate/string/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module.exports = {
testEnvironment: 'node',

transform: {
'^.+\\.tsx?$': 'ts-jest',
},
setupFiles: ['../../test/dotenv-config.js'],
setupFilesAfterEnv: [
'../../test/betterConsoleLog.js',
'../../test/unit.cleanup.js',
],
testTimeout: 60_000,
globalSetup: '../../test/setup-global.js',
forceExit: true,
passWithNoTests: true,
}
63 changes: 63 additions & 0 deletions validate/string/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{
"name": "@flatfile/plugin-validate-string",
"version": "0.0.0",
"description": "A Flatfile plugin for string configuration and validation",
"url": "https://github.com/FlatFilers/flatfile-plugins/tree/main/validate/string",
"main": "./dist/index.cjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"browser": {
"./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.cjs"
},
"browser": {
"require": "./dist/index.browser.cjs",
"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 src/*.spec.ts --detectOpenHandles",
"test:unit": "jest src/*.spec.ts --testPathIgnorePatterns=.*\\.e2e\\.spec\\.ts$ --detectOpenHandles",
"test:e2e": "jest src/*.e2e.spec.ts --detectOpenHandles"
},
"keywords": [
"flatfile-plugins",
"category-transform"
],
"author": "Flatfile, Inc",
"license": "ISC",
"dependencies": {
"@flatfile/plugin-record-hook": "^1.7.0"
},
"peerDependencies": {
"@flatfile/listener": "^1.0.5"
},
"devDependencies": {
"@flatfile/rollup-config": "^0.1.1"
},
"repository": {
"type": "git",
"url": "https://github.com/FlatFilers/flatfile-plugins.git",
"directory": "validate/string"
},
"browserslist": [
"> 0.5%",
"last 2 versions",
"not dead"
]
}
5 changes: 5 additions & 0 deletions validate/string/rollup.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { buildConfig } from '@flatfile/rollup-config'

const config = buildConfig({})

export default config
2 changes: 2 additions & 0 deletions validate/string/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './validate.string.plugin'
export * from './validate.string.utils'
Loading
Loading