predict-data-types
Advanced tools
+5
-1
@@ -18,3 +18,7 @@ // Type definitions for predict-data-types | ||
| | 'array' | ||
| | 'object'; | ||
| | 'object' | ||
| | 'ip' | ||
| | 'color' | ||
| | 'percentage' | ||
| | 'currency'; | ||
@@ -21,0 +25,0 @@ /** |
+50
-1
@@ -15,3 +15,8 @@ const dayjs = require('dayjs'); | ||
| DATE_CHARS: /^[\d\-/\s:.TZ+-]+$/, | ||
| LEADING_ZERO: /^0\d/ | ||
| LEADING_ZERO: /^0\d/, | ||
| IPV4: /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/, | ||
| IPV6: /^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$|^::(?:[0-9a-fA-F]{1,4}:){0,6}[0-9a-fA-F]{1,4}$|^(?:[0-9a-fA-F]{1,4}:){1,6}:$|^(?:[0-9a-fA-F]{1,4}:)(?::[0-9a-fA-F]{1,4}){1,6}$/, | ||
| HEX_COLOR: /^#(?:[0-9a-fA-F]{3}){1,2}$/, | ||
| PERCENTAGE: /^-?\d+(?:\.\d+)?%$/, | ||
| CURRENCY: /^[$β¬Β£Β₯βΉ][\d,]+(?:\.\d{1,2})?$|^[\d,]+(?:\.\d{1,2})?[$β¬Β£Β₯βΉ]$/ | ||
| }; | ||
@@ -143,2 +148,38 @@ | ||
| /** | ||
| * Checks if a given value is a valid IP address (IPv4 or IPv6) | ||
| * @param {string} value - The value to check | ||
| * @returns {boolean} True if the value is a valid IP address, false otherwise | ||
| */ | ||
| function isIPAddress(value) { | ||
| return PATTERNS.IPV4.test(value) || PATTERNS.IPV6.test(value); | ||
| } | ||
| /** | ||
| * Checks if a given value is a valid hex color code | ||
| * @param {string} value - The value to check | ||
| * @returns {boolean} True if the value is a valid hex color, false otherwise | ||
| */ | ||
| function isHexColor(value) { | ||
| return PATTERNS.HEX_COLOR.test(value); | ||
| } | ||
| /** | ||
| * Checks if a given value is a percentage | ||
| * @param {string} value - The value to check | ||
| * @returns {boolean} True if the value is a percentage, false otherwise | ||
| */ | ||
| function isPercentage(value) { | ||
| return PATTERNS.PERCENTAGE.test(value); | ||
| } | ||
| /** | ||
| * Checks if a given value is a currency amount | ||
| * @param {string} value - The value to check | ||
| * @returns {boolean} True if the value is a currency amount, false otherwise | ||
| */ | ||
| function isCurrency(value) { | ||
| return PATTERNS.CURRENCY.test(value); | ||
| } | ||
| /** | ||
| * Tokenizes a string by splitting on commas while respecting quoted strings and nested objects/arrays | ||
@@ -246,2 +287,6 @@ * Optimized version with improved performance for large inputs | ||
| return 'boolean'; | ||
| } else if (isPercentage(trimmedValue)) { | ||
| return 'percentage'; | ||
| } else if (isCurrency(trimmedValue)) { | ||
| return 'currency'; | ||
| } else if (!isNaN(parseFloat(trimmedValue)) && isFinite(trimmedValue) && !PATTERNS.LEADING_ZERO.test(trimmedValue)) { | ||
@@ -256,2 +301,4 @@ // Numbers, but not those with leading zeros like '01' | ||
| return 'uuid'; | ||
| } else if (isIPAddress(trimmedValue)) { | ||
| return 'ip'; | ||
| } else if (isPhoneNumber(trimmedValue)) { | ||
@@ -261,2 +308,4 @@ return 'phone'; | ||
| return 'email'; | ||
| } else if (isHexColor(trimmedValue)) { | ||
| return 'color'; | ||
| } else if (trimmedValue.startsWith('[') && trimmedValue.endsWith(']')) { | ||
@@ -263,0 +312,0 @@ return 'array'; |
+28
-5
| { | ||
| "name": "predict-data-types", | ||
| "version": "1.2.0", | ||
| "description": "A simple npm package that predicts data types for comma-separated values, including JSON objects, and validates URLs, phone numbers, email addresses, and geolocation data within string values.", | ||
| "version": "1.3.0", | ||
| "description": "A simple npm package that predicts data types for comma-separated values, including JSON objects, and validates URLs, phone numbers, email addresses, IP addresses, colors, percentages, and currency within string values.", | ||
| "main": "index.js", | ||
| "author": "Melih Birim", | ||
| "types": "index.d.ts", | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "git+https://github.com/melihbirim/predict-data-types.git" | ||
| }, | ||
| "bugs": { | ||
| "url": "https://github.com/melihbirim/predict-data-types/issues" | ||
| }, | ||
| "homepage": "https://github.com/melihbirim/predict-data-types#readme", | ||
| "engines": { | ||
| "node": ">=16.0.0" | ||
| }, | ||
| "files": [ | ||
| "index.js", | ||
| "index.d.ts", | ||
| "README.md", | ||
| "LICENSE" | ||
| ], | ||
| "scripts": { | ||
| "test": "mocha test", | ||
| "test:coverage": "npx c8 mocha test", | ||
| "lint": "eslint .", | ||
@@ -20,5 +39,9 @@ "lint:fix": "eslint . --fix" | ||
| "email", | ||
| "geolocation" | ||
| "geolocation", | ||
| "ip", | ||
| "color", | ||
| "percentage", | ||
| "currency", | ||
| "validation" | ||
| ], | ||
| "author": "Your Name", | ||
| "license": "MIT", | ||
@@ -35,2 +58,2 @@ "dependencies": { | ||
| } | ||
| } | ||
| } |
+41
-31
@@ -10,8 +10,8 @@ # Predict Data Types | ||
| - π― **Automatic Type Detection**: Intelligently identifies 9+ data types | ||
| - π **Input Validation**: Robust error handling and input validation | ||
| - π― **Automatic Type Detection**: Intelligently identifies 14 data types | ||
| - π **Input Validation**: Robust error handling and input validation | ||
| - π **CSV Support**: Parse CSV-like data with optional headers | ||
| - π **Lightweight**: Minimal dependencies (only dayjs) | ||
| - π **Well Tested**: Comprehensive test suite with edge cases | ||
| - π§ **TypeScript Ready**: (Coming soon) Type definitions included | ||
| - π§ **TypeScript Ready**: Type definitions included | ||
| - β‘ **Fast**: Optimized tokenization and regex patterns | ||
@@ -27,14 +27,18 @@ | ||
| | Type | Description | Examples | | ||
| |------|-------------|----------| | ||
| | `string` | Plain text values | `'John'`, `'Hello World'` | | ||
| | `number` | Integers and decimals | `42`, `3.14`, `-17`, `1e10` | | ||
| | `boolean` | Boolean representations | `true`, `false`, `yes`, `no` | | ||
| | `email` | Valid email addresses | `user@example.com`, `test+tag@domain.co.uk` | | ||
| | `phone` | Phone numbers | `555-555-5555`, `(555) 555-5555`, `+1 555-555-5555` | | ||
| | `url` | Web URLs | `https://example.com`, `http://subdomain.site.co.uk/path` | | ||
| | `uuid` | UUID v1-v5 | `550e8400-e29b-41d4-a716-446655440000` | | ||
| | `date` | Various date formats | `2023-12-31`, `31/12/2023`, `2023-12-31T23:59:59Z` | | ||
| | `array` | JSON arrays | `[1, 2, 3]`, `["apple", "banana"]` | | ||
| | `object` | JSON objects | `{"name": "John", "age": 30}` | | ||
| | Type | Description | Examples | | ||
| | ------------ | ----------------------- | --------------------------------------------------------- | | ||
| | `string` | Plain text values | `'John'`, `'Hello World'` | | ||
| | `number` | Integers and decimals | `42`, `3.14`, `-17`, `1e10` | | ||
| | `boolean` | Boolean representations | `true`, `false`, `yes`, `no` | | ||
| | `email` | Valid email addresses | `user@example.com`, `test+tag@domain.co.uk` | | ||
| | `phone` | Phone numbers | `555-555-5555`, `(555) 555-5555`, `+1 555-555-5555` | | ||
| | `url` | Web URLs | `https://example.com`, `http://subdomain.site.co.uk/path` | | ||
| | `uuid` | UUID v1-v5 | `550e8400-e29b-41d4-a716-446655440000` | | ||
| | `date` | Various date formats | `2023-12-31`, `31/12/2023`, `2023-12-31T23:59:59Z` | | ||
| | `ip` | IPv4 and IPv6 addresses | `192.168.1.1`, `2001:0db8::1` | | ||
| | `color` | Hex color codes | `#FF0000`, `#fff`, `#00ff00` | | ||
| | `percentage` | Percentage values | `50%`, `0.5%`, `-25%` | | ||
| | `currency` | Currency amounts | `$100`, `β¬50.99`, `Β£25`, `Β₯1000` | | ||
| | `array` | JSON arrays | `[1, 2, 3]`, `["apple", "banana"]` | | ||
| | `object` | JSON objects | `{"name": "John", "age": 30}` | | ||
@@ -46,5 +50,5 @@ ## π Usage | ||
| ```javascript | ||
| const predictDataTypes = require('predict-data-types'); | ||
| const predictDataTypes = require("predict-data-types"); | ||
| const text = 'John, 30, true, john@example.com, 2023-01-01'; | ||
| const text = "John, 30, true, john@example.com, 2023-01-01"; | ||
| const types = predictDataTypes(text); | ||
@@ -56,3 +60,3 @@ | ||
| // 'John': 'string', | ||
| // '30': 'number', | ||
| // '30': 'number', | ||
| // 'true': 'boolean', | ||
@@ -79,3 +83,3 @@ // 'john@example.com': 'email', | ||
| // 'age': 'number', | ||
| // 'active': 'boolean', | ||
| // 'active': 'boolean', | ||
| // 'email': 'email', | ||
@@ -114,3 +118,3 @@ // 'signup_date': 'date' | ||
| ```javascript | ||
| const dates = '2023-12-31, 31/12/2023, 2023-12-31T23:59:59Z, Dec-31-2023'; | ||
| const dates = "2023-12-31, 31/12/2023, 2023-12-31T23:59:59Z, Dec-31-2023"; | ||
| const types = predictDataTypes(dates); | ||
@@ -122,3 +126,3 @@ | ||
| // '2023-12-31': 'date', | ||
| // '31/12/2023': 'date', | ||
| // '31/12/2023': 'date', | ||
| // '2023-12-31T23:59:59Z': 'date', | ||
@@ -134,12 +138,16 @@ // 'Dec-31-2023': 'date' | ||
| **Parameters:** | ||
| - `input` (string): The comma-separated string to analyze | ||
| - `firstRowIsHeader` (boolean, optional): Whether to treat the first row as column headers (default: `false`) | ||
| **Returns:** | ||
| **Returns:** | ||
| - `Object<string, string>`: Mapping of field names/values to their predicted data types | ||
| **Throws:** | ||
| - `Error`: When input is null, undefined, or not a string | ||
| **Supported Date Formats:** | ||
| - ISO 8601: `2023-12-31T23:59:59Z` | ||
@@ -157,5 +165,5 @@ - Standard: `YYYY-MM-DD`, `DD/MM/YYYY`, `MM/DD/YYYY` | ||
| try { | ||
| predictDataTypes(null); // Error: Input cannot be null or undefined | ||
| predictDataTypes(123); // Error: Input must be a string | ||
| predictDataTypes([1,2,3]); // Error: Input must be a string | ||
| predictDataTypes(null); // Error: Input cannot be null or undefined | ||
| predictDataTypes(123); // Error: Input must be a string | ||
| predictDataTypes([1, 2, 3]); // Error: Input must be a string | ||
| } catch (error) { | ||
@@ -166,4 +174,4 @@ console.error(error.message); | ||
| // These will return empty object or appropriate results | ||
| predictDataTypes(''); // Returns: {} | ||
| predictDataTypes(' '); // Returns: { '': 'string' } | ||
| predictDataTypes(""); // Returns: {} | ||
| predictDataTypes(" "); // Returns: { '': 'string' } | ||
| ``` | ||
@@ -184,4 +192,5 @@ | ||
| The package includes comprehensive tests covering: | ||
| - β All supported data types | ||
| - β Edge cases and error conditions | ||
| - β Edge cases and error conditions | ||
| - β Input validation | ||
@@ -195,2 +204,3 @@ - β Complex nested structures | ||
| ### v1.1.0 | ||
| - β Fixed UUID pattern variable name bug | ||
@@ -211,3 +221,3 @@ - β Replaced deprecated moment.js with dayjs | ||
| 2. Create your feature branch (`git checkout -b feature/amazing-feature`) | ||
| 3. Run tests (`npm test`) | ||
| 3. Run tests (`npm test`) | ||
| 4. Commit your changes (`git commit -m 'Add amazing feature'`) | ||
@@ -225,3 +235,3 @@ 5. Push to the branch (`git push origin feature/amazing-feature`) | ||
| - οΏ½οΈ [Roadmap](ROADMAP.md) - Planned features and improvements | ||
| - οΏ½π [Issue Tracker](https://github.com/melihbirim/predict-data-types/issues) | ||
| - οΏ½π [Issue Tracker](https://github.com/melihbirim/predict-data-types/issues) | ||
| - π¬ [Discussions](https://github.com/melihbirim/predict-data-types/discussions) | ||
@@ -231,2 +241,2 @@ | ||
| Made with β€οΈ by [Melih Birim](https://github.com/melihbirim) | ||
| Made with β€οΈ by [Melih Birim](https://github.com/melihbirim) |
| name: CI/CD Pipeline | ||
| on: | ||
| push: | ||
| branches: [ main, develop, upgrades ] | ||
| pull_request: | ||
| branches: [ main, develop ] | ||
| jobs: | ||
| lint: | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 5 | ||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v4 | ||
| - name: Setup Node.js 18.x | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: '18.x' | ||
| cache: 'npm' | ||
| - name: Install dependencies | ||
| run: npm ci --prefer-offline --no-audit | ||
| - name: Run linting | ||
| run: npm run lint | ||
| - name: Check TypeScript definitions | ||
| run: npx tsc --noEmit index.d.ts | ||
| test: | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 10 | ||
| strategy: | ||
| matrix: | ||
| node-version: [16.x, 18.x, 20.x] | ||
| fail-fast: false | ||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v4 | ||
| - name: Setup Node.js ${{ matrix.node-version }} | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: ${{ matrix.node-version }} | ||
| cache: 'npm' | ||
| - name: Install dependencies | ||
| run: npm ci --prefer-offline --no-audit | ||
| - name: Run tests | ||
| run: npm test | ||
| test-cross-platform: | ||
| runs-on: ${{ matrix.os }} | ||
| timeout-minutes: 8 | ||
| strategy: | ||
| matrix: | ||
| os: [windows-latest, macos-latest] | ||
| fail-fast: false | ||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v4 | ||
| - name: Setup Node.js | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: '18.x' | ||
| cache: 'npm' | ||
| - name: Install dependencies | ||
| run: npm ci --prefer-offline --no-audit | ||
| - name: Run tests | ||
| run: npm test | ||
| security-audit: | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 5 | ||
| if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop') | ||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v4 | ||
| - name: Setup Node.js | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: '18.x' | ||
| cache: 'npm' | ||
| - name: Install dependencies | ||
| run: npm ci --prefer-offline --no-audit | ||
| - name: Security audit | ||
| run: npm audit --audit-level moderate | ||
| continue-on-error: true | ||
| - name: Check for high/critical vulnerabilities | ||
| run: npm audit --audit-level high --production | ||
| publish: | ||
| needs: [lint, test, test-cross-platform] | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 5 | ||
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | ||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v4 | ||
| - name: Setup Node.js | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: '18.x' | ||
| registry-url: 'https://registry.npmjs.org' | ||
| cache: 'npm' | ||
| - name: Install dependencies | ||
| run: npm ci --prefer-offline --no-audit | ||
| - name: Check if version changed | ||
| id: version-check | ||
| run: | | ||
| CURRENT_VERSION=$(node -p "require('./package.json').version") | ||
| PUBLISHED_VERSION=$(npm show predict-data-types version 2>/dev/null || echo "0.0.0") | ||
| echo "current=$CURRENT_VERSION" >> $GITHUB_OUTPUT | ||
| echo "published=$PUBLISHED_VERSION" >> $GITHUB_OUTPUT | ||
| if [ "$CURRENT_VERSION" != "$PUBLISHED_VERSION" ]; then | ||
| echo "should_publish=true" >> $GITHUB_OUTPUT | ||
| else | ||
| echo "should_publish=false" >> $GITHUB_OUTPUT | ||
| fi | ||
| - name: Publish to npm | ||
| if: steps.version-check.outputs.should_publish == 'true' | ||
| run: npm publish | ||
| env: | ||
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} |
-278
| # Contributing to Predict Data Types | ||
| Thank you for your interest in contributing to predict-data-types! This document provides guidelines and information for contributors. | ||
| ## π Getting Started | ||
| ### Prerequisites | ||
| - Node.js (v14 or higher) | ||
| - npm (v6 or higher) | ||
| - Git | ||
| ### Setting up the Development Environment | ||
| 1. **Fork and clone the repository:** | ||
| ```bash | ||
| git clone https://github.com/YOUR_USERNAME/predict-data-types.git | ||
| cd predict-data-types | ||
| ``` | ||
| 2. **Install dependencies:** | ||
| ```bash | ||
| npm install | ||
| ``` | ||
| 3. **Run tests to ensure everything works:** | ||
| ```bash | ||
| npm test | ||
| npm run lint | ||
| ``` | ||
| ## π§ͺ Development Workflow | ||
| ### Test-Driven Development (TDD) | ||
| We follow **Test-Driven Development** practices. Before implementing any changes: | ||
| 1. **Write tests first** for the new functionality or bug fix | ||
| 2. **Run tests** to ensure they fail initially | ||
| 3. **Implement** the minimal code to make tests pass | ||
| 4. **Refactor** while keeping tests green | ||
| 5. **Run full test suite** to ensure no regressions | ||
| ### Code Quality Standards | ||
| - **ESLint**: All code must pass ESLint checks (`npm run lint`) | ||
| - **Testing**: All new code must have corresponding tests | ||
| - **JSDoc**: Public functions must have JSDoc documentation | ||
| - **YAGNI Principle**: Don't add features that aren't needed | ||
| - **DRY Principle**: Don't repeat yourself | ||
| ### Making Changes | ||
| 1. **Create a feature branch:** | ||
| ```bash | ||
| git checkout -b feature/your-feature-name | ||
| ``` | ||
| 2. **Write tests first:** | ||
| ```bash | ||
| # Add tests to test/index.spec.js | ||
| npm test # Should fail initially | ||
| ``` | ||
| 3. **Implement your changes:** | ||
| ```bash | ||
| # Make changes to index.js or other files | ||
| npm test # Should pass now | ||
| npm run lint # Should pass | ||
| ``` | ||
| 4. **Commit your changes:** | ||
| ```bash | ||
| git add . | ||
| git commit -m "feat: add awesome new feature" | ||
| ``` | ||
| ## π Commit Message Guidelines | ||
| We follow conventional commit messages: | ||
| - `feat:` new features | ||
| - `fix:` bug fixes | ||
| - `docs:` documentation changes | ||
| - `style:` formatting, missing semi colons, etc | ||
| - `refactor:` code refactoring | ||
| - `test:` adding missing tests | ||
| - `chore:` maintenance tasks | ||
| Examples: | ||
| ``` | ||
| feat: add support for IPv4 address detection | ||
| fix: resolve UUID pattern variable name bug | ||
| docs: update README with better examples | ||
| test: add edge cases for date validation | ||
| ``` | ||
| ## π§ Code Style | ||
| ### ESLint Configuration | ||
| We use ESLint with the following key rules: | ||
| - 4-space indentation | ||
| - Single quotes for strings | ||
| - Semicolons required | ||
| - No console.log in production code | ||
| - Prefer const over let/var | ||
| ### JSDoc Documentation | ||
| All public functions must have JSDoc comments: | ||
| ```javascript | ||
| /** | ||
| * Brief description of what the function does | ||
| * @param {string} value - Description of the parameter | ||
| * @returns {boolean} Description of what is returned | ||
| * @throws {Error} Description of when errors are thrown | ||
| * | ||
| * @example | ||
| * // Usage example | ||
| * functionName('example input'); | ||
| * // Returns: expected output | ||
| */ | ||
| function functionName(value) { | ||
| // Implementation | ||
| } | ||
| ``` | ||
| ## π§ͺ Testing Guidelines | ||
| ### Test Structure | ||
| Tests are organized by functionality: | ||
| ```javascript | ||
| describe('Feature Name', () => { | ||
| it('should handle specific case', () => { | ||
| // Arrange | ||
| const input = 'test data'; | ||
| // Act | ||
| const result = predictDataTypes(input); | ||
| // Assert | ||
| expect(result).to.deep.equal(expectedOutput); | ||
| }); | ||
| }); | ||
| ``` | ||
| ### Test Categories | ||
| 1. **Happy Path**: Normal use cases | ||
| 2. **Edge Cases**: Boundary conditions, empty inputs, etc. | ||
| 3. **Error Cases**: Invalid inputs, error conditions | ||
| 4. **Integration**: Multiple features working together | ||
| ### Running Tests | ||
| ```bash | ||
| npm test # Run all tests | ||
| npm test -- --grep "UUID" # Run specific tests | ||
| npm run lint # Check code style | ||
| npm run lint:fix # Auto-fix style issues | ||
| ``` | ||
| ## π Bug Reports | ||
| When reporting bugs, please include: | ||
| 1. **Description**: Clear description of the issue | ||
| 2. **Steps to Reproduce**: Minimal code example | ||
| 3. **Expected Behavior**: What should happen | ||
| 4. **Actual Behavior**: What actually happens | ||
| 5. **Environment**: Node.js version, OS, etc. | ||
| **Bug Report Template:** | ||
| ```markdown | ||
| ## Bug Description | ||
| Brief description of the bug | ||
| ## Steps to Reproduce | ||
| ```js | ||
| const predictDataTypes = require('predict-data-types'); | ||
| const result = predictDataTypes('your input here'); | ||
| console.log(result); // Shows unexpected output | ||
| ``` | ||
| ## Expected Behavior | ||
| Should return: `{ 'expected': 'result' }` | ||
| ## Actual Behavior | ||
| Actually returns: `{ 'actual': 'result' }` | ||
| ## Environment | ||
| - Node.js version: 18.x | ||
| - Package version: 1.1.0 | ||
| - OS: macOS/Linux/Windows | ||
| ``` | ||
| ## π‘ Feature Requests | ||
| Before submitting feature requests: | ||
| 1. **Check existing issues** to avoid duplicates | ||
| 2. **Consider YAGNI**: Is this feature truly needed? | ||
| 3. **Provide use cases**: Why is this feature valuable? | ||
| 4. **Consider implementation**: How might this work? | ||
| **Feature Request Template:** | ||
| ```markdown | ||
| ## Feature Description | ||
| Clear description of the proposed feature | ||
| ## Use Case | ||
| Why is this feature needed? What problem does it solve? | ||
| ## Proposed Solution | ||
| How should this feature work? | ||
| ## Additional Context | ||
| Any other relevant information | ||
| ``` | ||
| ## π Code Review Process | ||
| 1. **Automated Checks**: All PRs must pass tests and linting | ||
| 2. **Manual Review**: Code will be reviewed for: | ||
| - Correctness and functionality | ||
| - Test coverage and quality | ||
| - Documentation completeness | ||
| - Code style and maintainability | ||
| - Performance implications | ||
| 3. **Feedback**: Address any review comments | ||
| 4. **Approval**: At least one maintainer approval required | ||
| ## π Pull Request Checklist | ||
| Before submitting a PR, ensure: | ||
| - [ ] Tests are written and passing (`npm test`) | ||
| - [ ] Code passes linting (`npm run lint`) | ||
| - [ ] JSDoc documentation is added for new public functions | ||
| - [ ] README is updated if needed | ||
| - [ ] Commit messages follow conventional format | ||
| - [ ] No console.log statements in production code | ||
| - [ ] Changes follow YAGNI and DRY principles | ||
| ## π Performance Considerations | ||
| - **Regex Efficiency**: Avoid ReDoS-vulnerable patterns | ||
| - **Memory Usage**: Be mindful of large string processing | ||
| - **Time Complexity**: Consider algorithmic efficiency | ||
| - **Dependencies**: Minimize new dependencies | ||
| ## π·οΈ Release Process | ||
| Maintainers handle releases following semantic versioning: | ||
| - **PATCH**: Bug fixes | ||
| - **MINOR**: New features (backward compatible) | ||
| - **MAJOR**: Breaking changes | ||
| ## β Questions? | ||
| - **GitHub Issues**: For bugs and feature requests | ||
| - **GitHub Discussions**: For questions and general discussion | ||
| - **Documentation**: Check README.md first | ||
| ## π Recognition | ||
| Contributors will be recognized in: | ||
| - GitHub contributors list | ||
| - Release notes for significant contributions | ||
| - README acknowledgments | ||
| --- | ||
| Thank you for contributing to predict-data-types! Your help makes this project better for everyone. π |
| // eslint.config.js - ESLint v9 flat configuration compatible with Node.js 16+ | ||
| module.exports = [ | ||
| { | ||
| ignores: ['node_modules/**', 'coverage/**', '*.config.js'] | ||
| }, | ||
| { | ||
| files: ['*.js', 'test/**/*.js'], | ||
| languageOptions: { | ||
| ecmaVersion: 2022, | ||
| sourceType: 'commonjs', | ||
| globals: { | ||
| // Node.js globals | ||
| console: 'readonly', | ||
| process: 'readonly', | ||
| require: 'readonly', | ||
| module: 'readonly', | ||
| exports: 'readonly', | ||
| __dirname: 'readonly', | ||
| __filename: 'readonly', | ||
| Buffer: 'readonly', | ||
| global: 'readonly', | ||
| // Test globals | ||
| describe: 'readonly', | ||
| it: 'readonly', | ||
| expect: 'readonly', | ||
| beforeEach: 'readonly', | ||
| afterEach: 'readonly', | ||
| before: 'readonly', | ||
| after: 'readonly' | ||
| } | ||
| }, | ||
| rules: { | ||
| // Core ESLint recommended rules (manual selection for Node 16 compatibility) | ||
| 'no-unused-vars': ['error', { 'argsIgnorePattern': '^_' }], | ||
| 'no-undef': 'error', | ||
| 'no-unreachable': 'error', | ||
| 'no-constant-condition': 'error', | ||
| 'no-dupe-args': 'error', | ||
| 'no-dupe-keys': 'error', | ||
| 'no-duplicate-case': 'error', | ||
| 'no-empty': 'error', | ||
| 'no-ex-assign': 'error', | ||
| 'no-extra-boolean-cast': 'error', | ||
| 'no-extra-semi': 'error', | ||
| 'no-func-assign': 'error', | ||
| 'no-invalid-regexp': 'error', | ||
| 'no-irregular-whitespace': 'error', | ||
| 'no-obj-calls': 'error', | ||
| 'no-regex-spaces': 'error', | ||
| 'no-sparse-arrays': 'error', | ||
| 'use-isnan': 'error', | ||
| 'valid-typeof': 'error', | ||
| // Code style rules | ||
| 'indent': ['error', 4], | ||
| 'quotes': ['error', 'single'], | ||
| 'semi': ['error', 'always'], | ||
| 'no-console': 'off', // Allow console in this project | ||
| 'no-trailing-spaces': 'error', | ||
| 'eol-last': ['error', 'always'], | ||
| 'prefer-const': 'error', | ||
| 'no-var': 'error', | ||
| 'comma-dangle': ['error', 'never'], | ||
| 'object-curly-spacing': ['error', 'always'], | ||
| 'array-bracket-spacing': ['error', 'never'], | ||
| 'space-before-function-paren': ['error', 'never'] | ||
| } | ||
| } | ||
| ]; |
-220
| # πΊοΈ Predict Data Types - Roadmap | ||
| This roadmap outlines the planned features and improvements for the predict-data-types package. Items are organized by priority and implementation complexity. | ||
| ## π― **Current Status (v1.1.0)** | ||
| β **Completed Features:** | ||
| - Automatic type detection for 10+ data types | ||
| - CSV support with optional headers | ||
| - Robust input validation and error handling | ||
| - TypeScript definitions | ||
| - Comprehensive test coverage (31+ tests) | ||
| - Performance optimizations (cached regex patterns) | ||
| - ESLint configuration and code quality | ||
| - JSDoc documentation | ||
| ## π **Roadmap** | ||
| ### **Phase 1: Enhanced Type Detection** (v1.2.0) | ||
| **High Impact, Easy Implementation** | ||
| - [ ] **Geographic Coordinates** | ||
| ```javascript | ||
| '40.7128,-74.0060' -> 'coordinates' | ||
| 'lat:40.7128,lng:-74.0060' -> 'coordinates' | ||
| ``` | ||
| - [ ] **IP Address Detection** | ||
| ```javascript | ||
| '192.168.1.1' -> 'ipv4' | ||
| '2001:db8::1' -> 'ipv6' | ||
| ``` | ||
| - [ ] **Color Code Detection** | ||
| ```javascript | ||
| '#FF5733' -> 'color_hex' | ||
| 'rgb(255, 87, 51)' -> 'color_rgb' | ||
| 'rgba(255, 87, 51, 0.8)' -> 'color_rgba' | ||
| 'hsl(120, 100%, 50%)' -> 'color_hsl' | ||
| ``` | ||
| - [ ] **File & MIME Type Detection** | ||
| ```javascript | ||
| 'document.pdf' -> 'file' | ||
| 'image/jpeg' -> 'mime_type' | ||
| 'application/json' -> 'mime_type' | ||
| ``` | ||
| ### **Phase 2: Configuration & Customization** (v1.3.0) | ||
| **Medium Impact, Medium Implementation** | ||
| - [ ] **Configuration Options** | ||
| ```javascript | ||
| const options = { | ||
| strictMode: true, // More conservative type detection | ||
| customPatterns: { // User-defined regex patterns | ||
| 'product_id': /^PRD-\d{6}$/, | ||
| 'order_code': /^ORD-[A-Z]{3}-\d{4}$/ | ||
| }, | ||
| dateFormats: ['DD/MM/YYYY'], // Limit date formats | ||
| confidence: true, // Return confidence scores | ||
| locale: 'en-US' // Region-specific detection | ||
| } | ||
| ``` | ||
| - [ ] **Confidence Scores** | ||
| ```javascript | ||
| // Returns: { value: 'email', confidence: 0.95, alternates: ['string'] } | ||
| ``` | ||
| - [ ] **Custom Pattern Support** | ||
| - Business-specific type definitions | ||
| - Regex pattern validation | ||
| - Pattern priority management | ||
| ### **Phase 3: Output Format Extensions** (v1.4.0) | ||
| **High Impact, Medium Implementation** | ||
| - [ ] **JSON Schema Generation** | ||
| ```javascript | ||
| predictDataTypes('John,25', { outputFormat: 'jsonSchema' }); | ||
| // Returns: { type: 'object', properties: { John: { type: 'string' } } } | ||
| ``` | ||
| - [ ] **SQL DDL Generation** | ||
| ```javascript | ||
| predictDataTypes('name,age\nJohn,25', { | ||
| header: true, | ||
| outputFormat: 'sql', | ||
| tableName: 'users' | ||
| }); | ||
| // Returns: "CREATE TABLE users (name VARCHAR(255), age INTEGER);" | ||
| ``` | ||
| - [ ] **TypeScript Interface Generation** | ||
| ```javascript | ||
| predictDataTypes('name,age\nJohn,25', { | ||
| header: true, | ||
| outputFormat: 'typescript', | ||
| interfaceName: 'User' | ||
| }); | ||
| // Returns: "interface User { name: string; age: number; }" | ||
| ``` | ||
| - [ ] **Other Format Support** | ||
| - MongoDB schema | ||
| - Prisma schema | ||
| - GraphQL schema | ||
| - Zod validation schema | ||
| ### **Phase 4: Performance & Scalability** (v1.5.0) | ||
| **Medium Impact, High Implementation** | ||
| - [ ] **Batch Processing API** | ||
| ```javascript | ||
| predictDataTypes.batch([ | ||
| 'user1,25,email1@test.com', | ||
| 'user2,30,email2@test.com' | ||
| ], { header: true, parallel: true }); | ||
| ``` | ||
| - [ ] **Streaming API for Large Files** | ||
| ```javascript | ||
| predictDataTypes.stream(fs.createReadStream('large.csv')) | ||
| .on('schema', (schema) => console.log(schema)) | ||
| .on('progress', (percent) => console.log(`${percent}% complete`)); | ||
| ``` | ||
| - [ ] **Performance Optimizations** | ||
| - Web Workers support for browser usage | ||
| - Memory-efficient processing for large datasets | ||
| - Incremental schema building | ||
| - Smart sampling for large files | ||
| ### **Phase 5: Advanced Features** (v2.0.0) | ||
| **High Impact, High Implementation** | ||
| - [ ] **Locale-Specific Detection** | ||
| - Region-specific date formats (EU vs US) | ||
| - Localized phone number validation | ||
| - Currency format detection | ||
| - Address format recognition | ||
| - [ ] **Security-Aware Detection** | ||
| ```javascript | ||
| '****-****-****-1234' -> 'credit_card_masked' | ||
| '***-**-1234' -> 'ssn_masked' | ||
| ``` | ||
| - [ ] **Statistical Analysis** | ||
| - Data quality metrics | ||
| - Null/empty value percentages | ||
| - Value distribution analysis | ||
| - Outlier detection | ||
| - [ ] **Machine Learning Integration** | ||
| - Pattern learning from user feedback | ||
| - Context-aware type detection | ||
| - Adaptive confidence scoring | ||
| ## π― **Target Use Cases** | ||
| ### **Primary Users:** | ||
| 1. **Data Scientists & Analysts** - CSV exploration, pipeline automation | ||
| 2. **Backend Developers** - API validation, form processing | ||
| 3. **ETL Pipeline Developers** - Data transformation and validation | ||
| 4. **Frontend Developers** - File upload processing, data tables | ||
| 5. **No-Code Tool Builders** - Automatic schema inference | ||
| ### **Real-World Applications:** | ||
| - **Database Schema Generation** - Auto-create tables from CSV uploads | ||
| - **API Documentation** - Generate OpenAPI specs from sample data | ||
| - **Form Builder Tools** - Infer form field types from examples | ||
| - **Data Migration** - Type mapping between different systems | ||
| - **Analytics Dashboards** - Smart column type detection | ||
| ## π€ **Considerations & Trade-offs** | ||
| ### **What Might Be Removed:** | ||
| - [ ] **Review complex nested object/array parsing** - might be overkill for CSV use cases | ||
| - [ ] **Evaluate date format complexity** - too many formats can cause false positives | ||
| - [ ] **Assess phone validation scope** - very region-specific, consider simplification | ||
| ### **Architecture Decisions:** | ||
| - **Performance vs Features** - Balance detection accuracy with speed | ||
| - **Bundle Size vs Functionality** - Consider tree-shaking and modular approach | ||
| - **Backward Compatibility** - Maintain API stability across versions | ||
| ## π **Timeline Estimates** | ||
| - **Phase 1 (v1.2.0)**: ~2-3 weeks | ||
| - **Phase 2 (v1.3.0)**: ~3-4 weeks | ||
| - **Phase 3 (v1.4.0)**: ~4-5 weeks | ||
| - **Phase 4 (v1.5.0)**: ~6-8 weeks | ||
| - **Phase 5 (v2.0.0)**: ~10-12 weeks | ||
| ## π€ **Contributing** | ||
| We welcome contributions! Please check our [Contributing Guidelines](CONTRIBUTING.md) for details on: | ||
| - How to propose new features | ||
| - Development setup and testing | ||
| - Code style and quality standards | ||
| - Pull request process | ||
| ## π¬ **Feedback & Discussion** | ||
| Have ideas or suggestions? We'd love to hear from you: | ||
| - π [Issue Tracker](https://github.com/melihbirim/predict-data-types/issues) - Bug reports and feature requests | ||
| - π [Discussions](https://github.com/melihbirim/predict-data-types/discussions) - Ideas and questions | ||
| - π§ Direct feedback via issues or pull requests | ||
| --- | ||
| **Last Updated:** September 12, 2025 | ||
| **Next Review:** October 12, 2025 |
| // TypeScript compilation and usage test | ||
| const predictDataTypes = require('./index'); | ||
| // Test basic usage - should compile without errors | ||
| const basicResult = predictDataTypes('John, 30, true, john@example.com'); | ||
| console.log('Basic types:', basicResult); | ||
| // Test with header mode | ||
| const csvData = 'name,age,active,email\nJohn,30,true,john@example.com'; | ||
| const csvResult = predictDataTypes(csvData, true); | ||
| console.log('CSV with headers:', csvResult); | ||
| // Test TypeScript type checking | ||
| const userName: string = basicResult['John']; // Should be valid | ||
| const userAge: string = basicResult['30']; // Should be valid | ||
| const userActive: string = basicResult['true']; // Should be valid | ||
| const userEmail: string = basicResult['john@example.com']; // Should be valid | ||
| console.log('TypeScript compilation successful!'); | ||
| console.log(`User: ${userName}, Age type: ${userAge}, Active: ${userActive}, Email type: ${userEmail}`); |
| const chai = require('chai'); | ||
| const expect = chai.expect; | ||
| const predictDataTypes = require('../index'); | ||
| describe('predictDataTypes', () => { | ||
| it('should predict data types for string and url', () => { | ||
| const text = 'John, http://asd.com'; | ||
| const types = predictDataTypes(text); | ||
| expect(types).to.deep.equal({ | ||
| 'John': 'string', | ||
| 'http://asd.com': 'url' | ||
| }); | ||
| }); | ||
| it('should predict data types with numbers and date', () => { | ||
| const text = 'John, http://asd.com, 24, 3.4, 2023-01-01'; | ||
| const types = predictDataTypes(text); | ||
| expect(types).to.deep.equal({ | ||
| 'John': 'string', | ||
| 'http://asd.com': 'url', | ||
| '24': 'number', | ||
| '3.4': 'number', | ||
| '2023-01-01': 'date' | ||
| }); | ||
| }); | ||
| it('should predict data types for strings with phone numbers', () => { | ||
| const text = '555-555-5555, (555) 555-5555, +1 555-555-5555, invalid-phone-number'; | ||
| const types = predictDataTypes(text); | ||
| expect(types).to.deep.equal({ | ||
| '555-555-5555': 'phone', | ||
| '(555) 555-5555': 'phone', | ||
| '+1 555-555-5555': 'phone', | ||
| 'invalid-phone-number': 'string' | ||
| }); | ||
| }); | ||
| it('should predict data types for arrays', () => { | ||
| const text = '[["apple"], "banana", "orange"], {"name": "John", "age": 30}'; | ||
| const types = predictDataTypes(text); | ||
| expect(types).to.deep.equal({ | ||
| '[["apple"], "banana", "orange"]': 'array', | ||
| '{"name": "John", "age": 30}': 'object' | ||
| }); | ||
| }); | ||
| it('should predict data types for JSON objects', () => { | ||
| const text = 'name, age, married, dob \n John,30, true, 1991-05-12'; | ||
| const types = predictDataTypes(text, true); | ||
| expect(types).to.deep.equal({ | ||
| 'name': 'string', | ||
| 'age': 'number', | ||
| 'married': 'boolean', | ||
| 'dob': 'date' | ||
| }); | ||
| }); | ||
| // Edge cases and input validation tests | ||
| describe('Input validation and edge cases', () => { | ||
| it('should handle null input', () => { | ||
| expect(() => predictDataTypes(null)).to.throw('Input must be a string'); | ||
| }); | ||
| it('should handle undefined input', () => { | ||
| expect(() => predictDataTypes(undefined)).to.throw('Input must be a string'); | ||
| }); | ||
| it('should handle empty string input', () => { | ||
| const result = predictDataTypes(''); | ||
| expect(result).to.deep.equal({}); | ||
| }); | ||
| it('should handle whitespace-only string input', () => { | ||
| const result = predictDataTypes(' '); | ||
| expect(result).to.deep.equal({}); | ||
| }); | ||
| it('should handle non-string input types', () => { | ||
| expect(() => predictDataTypes(123)).to.throw('Input must be a string'); | ||
| expect(() => predictDataTypes({})).to.throw('Input must be a string'); | ||
| expect(() => predictDataTypes([])).to.throw('Input must be a string'); | ||
| }); | ||
| it('should handle single character input', () => { | ||
| const result = predictDataTypes('a'); | ||
| expect(result).to.deep.equal({ 'a': 'string' }); | ||
| }); | ||
| it('should handle missing header fields gracefully', () => { | ||
| const csvData = 'name,age,active\nJohn,30'; // Missing third column | ||
| const result = predictDataTypes(csvData, true); | ||
| expect(result).to.deep.equal({ | ||
| 'name': 'string', | ||
| 'age': 'number' | ||
| }); | ||
| }); | ||
| it('should handle more data fields than header fields', () => { | ||
| const csvData = 'name,age\nJohn,30,true,extra'; // Extra columns | ||
| const result = predictDataTypes(csvData, true); | ||
| expect(result).to.deep.equal({ | ||
| 'name': 'string', | ||
| 'age': 'number' | ||
| }); | ||
| }); | ||
| }); | ||
| // UUID tests - testing the bug fix | ||
| describe('UUID detection', () => { | ||
| it('should correctly detect valid UUIDs', () => { | ||
| const text = '550e8400-e29b-41d4-a716-446655440000'; | ||
| const types = predictDataTypes(text); | ||
| expect(types).to.deep.equal({ | ||
| '550e8400-e29b-41d4-a716-446655440000': 'uuid' | ||
| }); | ||
| }); | ||
| it('should correctly detect multiple UUIDs', () => { | ||
| const text = '550e8400-e29b-41d4-a716-446655440000, 6ba7b810-9dad-11d1-80b4-00c04fd430c8'; | ||
| const types = predictDataTypes(text); | ||
| expect(types).to.deep.equal({ | ||
| '550e8400-e29b-41d4-a716-446655440000': 'uuid', | ||
| '6ba7b810-9dad-11d1-80b4-00c04fd430c8': 'uuid' | ||
| }); | ||
| }); | ||
| it('should not detect invalid UUIDs', () => { | ||
| const text = '550e8400-e29b-41d4-a716-44665544000, not-a-uuid-at-all'; | ||
| const types = predictDataTypes(text); | ||
| expect(types).to.deep.equal({ | ||
| '550e8400-e29b-41d4-a716-44665544000': 'string', | ||
| 'not-a-uuid-at-all': 'string' | ||
| }); | ||
| }); | ||
| }); | ||
| // Enhanced boolean detection tests | ||
| describe('Boolean detection', () => { | ||
| it('should detect various true/false representations', () => { | ||
| const text = 'true, false, TRUE, FALSE, yes, no, YES, NO, on, off, ON, OFF'; | ||
| const types = predictDataTypes(text); | ||
| expect(types).to.deep.equal({ | ||
| 'true': 'boolean', | ||
| 'false': 'boolean', | ||
| 'TRUE': 'boolean', | ||
| 'FALSE': 'boolean', | ||
| 'yes': 'boolean', | ||
| 'no': 'boolean', | ||
| 'YES': 'boolean', | ||
| 'NO': 'boolean', | ||
| 'on': 'boolean', | ||
| 'off': 'boolean', | ||
| 'ON': 'boolean', | ||
| 'OFF': 'boolean' | ||
| }); | ||
| }); | ||
| it('should detect comprehensive boolean representations', () => { | ||
| const text = 'true, false, yes, no, on, off'; | ||
| const types = predictDataTypes(text); | ||
| expect(types).to.deep.equal({ | ||
| 'true': 'boolean', | ||
| 'false': 'boolean', | ||
| 'yes': 'boolean', | ||
| 'no': 'boolean', | ||
| 'on': 'boolean', | ||
| 'off': 'boolean' | ||
| }); | ||
| }); | ||
| it('should not detect partial boolean words', () => { | ||
| const text = 'truthy, falsy, yesss, nope, online, offline, 10, 01'; | ||
| const types = predictDataTypes(text); | ||
| expect(types).to.deep.equal({ | ||
| 'truthy': 'string', | ||
| 'falsy': 'string', | ||
| 'yesss': 'string', | ||
| 'nope': 'string', | ||
| 'online': 'string', | ||
| 'offline': 'string', | ||
| '10': 'number', | ||
| '01': 'string' // Leading zero makes it a string | ||
| }); | ||
| }); | ||
| }); | ||
| // Email detection tests | ||
| describe('Email detection', () => { | ||
| it('should detect valid email addresses', () => { | ||
| const text = 'user@example.com, test.email+tag@domain.co.uk'; | ||
| const types = predictDataTypes(text); | ||
| expect(types).to.deep.equal({ | ||
| 'user@example.com': 'email', | ||
| 'test.email+tag@domain.co.uk': 'email' | ||
| }); | ||
| }); | ||
| it('should not detect invalid email addresses', () => { | ||
| const text = '@example.com, user@, user@domain, user.domain.com'; | ||
| const types = predictDataTypes(text); | ||
| expect(types).to.deep.equal({ | ||
| '@example.com': 'string', | ||
| 'user@': 'string', | ||
| 'user@domain': 'string', | ||
| 'user.domain.com': 'string' | ||
| }); | ||
| }); | ||
| }); | ||
| // Date format tests | ||
| describe('Date detection', () => { | ||
| it('should detect various date formats', () => { | ||
| const text = '2023-12-31, 31/12/2023, 12/31/2023, 2023-12-31T23:59:59Z'; | ||
| const types = predictDataTypes(text); | ||
| expect(types).to.deep.equal({ | ||
| '2023-12-31': 'date', | ||
| '31/12/2023': 'date', | ||
| '12/31/2023': 'date', | ||
| '2023-12-31T23:59:59Z': 'date' | ||
| }); | ||
| }); | ||
| it('should not detect invalid dates', () => { | ||
| const text = '2023-13-32, 32/13/2023, not-a-date'; | ||
| const types = predictDataTypes(text); | ||
| expect(types).to.deep.equal({ | ||
| '2023-13-32': 'string', | ||
| '32/13/2023': 'string', | ||
| 'not-a-date': 'string' | ||
| }); | ||
| }); | ||
| }); | ||
| // Number detection edge cases | ||
| describe('Number detection', () => { | ||
| it('should detect various number formats', () => { | ||
| const text = '42, -42, 3.14, -3.14, 0, 0.0, 1e10, -1e-10'; | ||
| const types = predictDataTypes(text); | ||
| expect(types).to.deep.equal({ | ||
| '42': 'number', | ||
| '-42': 'number', | ||
| '3.14': 'number', | ||
| '-3.14': 'number', | ||
| '0': 'number', | ||
| '0.0': 'number', | ||
| '1e10': 'number', | ||
| '-1e-10': 'number' | ||
| }); | ||
| }); | ||
| it('should not detect invalid numbers', () => { | ||
| const text = '42abc, 3.14.15, --42, 1e10e5'; | ||
| const types = predictDataTypes(text); | ||
| expect(types).to.deep.equal({ | ||
| '42abc': 'string', | ||
| '3.14.15': 'string', | ||
| '--42': 'string', | ||
| '1e10e5': 'string' | ||
| }); | ||
| }); | ||
| }); | ||
| // Tokenization edge cases | ||
| describe('Tokenization edge cases', () => { | ||
| it('should handle nested objects and arrays', () => { | ||
| const text = '{"nested": {"array": [1, 2, 3]}}, [{"key": "value"}]'; | ||
| const types = predictDataTypes(text); | ||
| expect(types).to.deep.equal({ | ||
| '{"nested": {"array": [1, 2, 3]}}': 'object', | ||
| '[{"key": "value"}]': 'array' | ||
| }); | ||
| }); | ||
| it('should handle quoted strings with commas', () => { | ||
| const text = '"Hello, world", "Another, string"'; | ||
| const types = predictDataTypes(text); | ||
| expect(types).to.deep.equal({ | ||
| '"Hello, world"': 'string', | ||
| '"Another, string"': 'string' | ||
| }); | ||
| }); | ||
| it('should handle strings with escaped quotes', () => { | ||
| const text = '"He said \\"Hello\\"", normal-string'; | ||
| const types = predictDataTypes(text); | ||
| expect(types).to.deep.equal({ | ||
| '"He said \\"Hello\\""': 'string', | ||
| 'normal-string': 'string' | ||
| }); | ||
| }); | ||
| }); | ||
| // Header mode tests | ||
| describe('Header mode functionality', () => { | ||
| it('should handle single line input in header mode', () => { | ||
| const result = predictDataTypes('name, age', true); | ||
| expect(result).to.deep.equal({}); | ||
| }); | ||
| it('should handle multi-line input with headers', () => { | ||
| const text = 'name,age,active\nJohn,30,true'; | ||
| const types = predictDataTypes(text, true); | ||
| expect(types).to.deep.equal({ | ||
| 'name': 'string', | ||
| 'age': 'number', | ||
| 'active': 'boolean' | ||
| }); | ||
| }); | ||
| it('should handle mismatched header and data columns', () => { | ||
| const text = 'name,age,active\nJohn,30'; // Missing third column | ||
| const types = predictDataTypes(text, true); | ||
| expect(types).to.deep.equal({ | ||
| 'name': 'string', | ||
| 'age': 'number' | ||
| }); | ||
| }); | ||
| }); | ||
| }); |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
0
-100%0
-100%228
5.07%0
-100%0
-100%24106
-54.65%5
-54.55%395
-44.99%