You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

8.4 KiB

ESLint Rules for PlatformServiceMixin Migration

Overview

Custom ESLint rules to enforce PlatformServiceMixin patterns and prevent regression to legacy patterns.

Rules Configuration

Add to .eslintrc.js:

module.exports = {
  // ... existing config
  rules: {
    // ... existing rules
    
    // Custom rules for PlatformServiceMixin migration
    'timesafari/no-direct-database-util': 'error',
    'timesafari/no-legacy-logging': 'error',
    'timesafari/require-mixin-for-database': 'error',
    'timesafari/no-direct-platform-service': 'warn',
    'timesafari/prefer-mixin-methods': 'warn',
  },
  
  // Custom rules plugin
  plugins: ['timesafari'],
}

Custom Rules Implementation

Create eslint-plugin-timesafari/index.js:

module.exports = {
  rules: {
    'no-direct-database-util': {
      meta: {
        type: 'problem',
        docs: {
          description: 'Disallow direct imports from databaseUtil',
          category: 'Migration',
          recommended: true,
        },
        schema: [],
      },
      create(context) {
        return {
          ImportDeclaration(node) {
            if (node.source.value.includes('databaseUtil')) {
              context.report({
                node,
                message: 'Direct databaseUtil imports are deprecated. Use PlatformServiceMixin instead.',
              });
            }
          },
        };
      },
    },
    
    'no-legacy-logging': {
      meta: {
        type: 'problem',
        docs: {
          description: 'Disallow legacy logging methods',
          category: 'Migration',
          recommended: true,
        },
        schema: [],
      },
      create(context) {
        return {
          ImportDeclaration(node) {
            if (node.specifiers.some(spec => spec.imported?.name === 'logConsoleAndDb')) {
              context.report({
                node,
                message: 'logConsoleAndDb is deprecated. Use PlatformServiceMixin $log methods instead.',
              });
            }
          },
          CallExpression(node) {
            if (node.callee.name === 'logConsoleAndDb') {
              context.report({
                node,
                message: 'logConsoleAndDb is deprecated. Use this.$logAndConsole() instead.',
              });
            }
          },
        };
      },
    },
    
    'require-mixin-for-database': {
      meta: {
        type: 'suggestion',
        docs: {
          description: 'Require PlatformServiceMixin for components using database operations',
          category: 'Migration',
          recommended: true,
        },
        schema: [],
      },
      create(context) {
        let hasDbOperations = false;
        let hasMixin = false;
        
        return {
          CallExpression(node) {
            // Check for database operations
            if (node.callee.property && 
                ['dbQuery', 'dbExec', 'dbGetOneRow'].includes(node.callee.property.name)) {
              hasDbOperations = true;
            }
          },
          Property(node) {
            // Check for mixin usage
            if (node.key.name === 'mixins' && 
                node.value.elements?.some(el => el.name === 'PlatformServiceMixin')) {
              hasMixin = true;
            }
          },
          'Program:exit'() {
            if (hasDbOperations && !hasMixin) {
              context.report({
                node: context.getSourceCode().ast,
                message: 'Components using database operations should include PlatformServiceMixin.',
              });
            }
          },
        };
      },
    },
    
    'no-direct-platform-service': {
      meta: {
        type: 'suggestion',
        docs: {
          description: 'Discourage direct PlatformServiceFactory usage',
          category: 'Migration',
          recommended: false,
        },
        schema: [],
      },
      create(context) {
        return {
          CallExpression(node) {
            if (node.callee.object?.name === 'PlatformServiceFactory' &&
                node.callee.property?.name === 'getInstance') {
              context.report({
                node,
                message: 'Consider using PlatformServiceMixin methods instead of direct PlatformServiceFactory.',
              });
            }
          },
        };
      },
    },
    
    'prefer-mixin-methods': {
      meta: {
        type: 'suggestion',
        docs: {
          description: 'Prefer mixin convenience methods over direct database calls',
          category: 'Migration',
          recommended: false,
        },
        schema: [],
      },
      create(context) {
        return {
          CallExpression(node) {
            // Check for patterns that could use mixin methods
            if (node.callee.property?.name === 'dbQuery') {
              const arg = node.arguments[0];
              if (arg && arg.type === 'Literal') {
                const sql = arg.value.toLowerCase();
                if (sql.includes('select * from contacts')) {
                  context.report({
                    node,
                    message: 'Consider using this.$getAllContacts() instead of direct SQL.',
                  });
                }
                if (sql.includes('select * from settings')) {
                  context.report({
                    node,
                    message: 'Consider using this.$settings() instead of direct SQL.',
                  });
                }
              }
            }
          },
        };
      },
    },
  },
};

Pre-commit Hook

Create .pre-commit-config.yaml:

repos:
  - repo: local
    hooks:
      - id: eslint-migration-check
        name: ESLint Migration Check
        entry: npx eslint --ext .vue --rule 'timesafari/no-direct-database-util: error'
        language: system
        files: \.vue$
        
      - id: no-legacy-logging
        name: No Legacy Logging
        entry: bash -c 'if grep -r "logConsoleAndDb" src/ --include="*.vue" --include="*.ts"; then echo "Found legacy logging imports"; exit 1; fi'
        language: system
        pass_filenames: false

Migration Validation Script

Create scripts/validate-migration.sh:

#!/bin/bash

echo "🔍 Validating PlatformServiceMixin migration..."

# Check for legacy patterns
echo "Checking for legacy databaseUtil imports..."
LEGACY_DB_IMPORTS=$(grep -r "import.*databaseUtil" src/ --include="*.vue" --include="*.ts" | wc -l)
echo "Found $LEGACY_DB_IMPORTS legacy databaseUtil imports"

echo "Checking for legacy logging imports..."
LEGACY_LOG_IMPORTS=$(grep -r "logConsoleAndDb" src/ --include="*.vue" --include="*.ts" | wc -l)
echo "Found $LEGACY_LOG_IMPORTS legacy logging imports"

# Check for mixin usage
echo "Checking for PlatformServiceMixin usage..."
MIXIN_USAGE=$(grep -r "PlatformServiceMixin" src/ --include="*.vue" | wc -l)
echo "Found $MIXIN_USAGE files using PlatformServiceMixin"

# Check for direct PlatformService usage
echo "Checking for direct PlatformService usage..."
DIRECT_PLATFORM=$(grep -r "PlatformServiceFactory.getInstance" src/ --include="*.vue" --include="*.ts" | wc -l)
echo "Found $DIRECT_PLATFORM direct PlatformService usages"

# Summary
echo ""
echo "📊 Migration Status Summary:"
echo "- Legacy databaseUtil imports: $LEGACY_DB_IMPORTS (should be 0)"
echo "- Legacy logging imports: $LEGACY_LOG_IMPORTS (should be 0)"
echo "- Mixin usage: $MIXIN_USAGE (should be high)"
echo "- Direct PlatformService usage: $DIRECT_PLATFORM (should be low)"

# Set exit code based on legacy usage
if [ $LEGACY_DB_IMPORTS -gt 0 ] || [ $LEGACY_LOG_IMPORTS -gt 0 ]; then
    echo "❌ Migration validation failed - legacy patterns found"
    exit 1
else
    echo "✅ Migration validation passed - no legacy patterns found"
    exit 0
fi

Usage

  1. Install ESLint rules:

    npm install --save-dev eslint-plugin-timesafari
    
  2. Run validation:

    npm run lint
    ./scripts/validate-migration.sh
    
  3. Fix issues automatically:

    npm run lint -- --fix
    

IDE Integration

VS Code Settings

Add to .vscode/settings.json:

{
  "eslint.validate": [
    "javascript",
    "typescript",
    "vue"
  ],
  "eslint.options": {
    "extensions": [".js", ".ts", ".vue"]
  }
}

WebStorm Settings

  1. Go to Settings → Languages & Frameworks → JavaScript → Code Quality Tools → ESLint
  2. Enable ESLint
  3. Set configuration file to .eslintrc.js
  4. Add .vue to file extensions