Ctrl + k

or run

tessl search
Log in

evernote-upgrade-migration

tessl install github:jeremylongshore/claude-code-plugins-plus-skills --skill evernote-upgrade-migration
github.com/jeremylongshore/claude-code-plugins-plus-skills

Upgrade Evernote SDK versions and migrate between API versions. Use when upgrading SDK, handling breaking changes, or migrating to newer API patterns. Trigger with phrases like "upgrade evernote sdk", "evernote migration", "update evernote", "evernote breaking changes".

Review Score

84%

Validation Score

12/16

Implementation Score

77%

Activation Score

90%

Evernote Upgrade & Migration

Overview

Guide for upgrading Evernote SDK versions, handling breaking changes, and migrating legacy integrations to current API patterns.

Prerequisites

  • Existing Evernote integration
  • Test environment for validation
  • Understanding of current implementation

SDK Version History

VersionNode.jsKey Changes
2.0.x10+Promise-based API, ES6 modules
1.25.x8+Legacy callback pattern
1.x6+Original SDK

Instructions

Step 1: Check Current Version

# Check installed version
npm list evernote

# Check available versions
npm view evernote versions

# Check for outdated packages
npm outdated evernote

Step 2: Review Breaking Changes

// SDK 1.x -> 2.x Breaking Changes

// 1. Client initialization changed
// OLD (1.x):
var Evernote = require('evernote').Evernote;
var client = new Evernote.Client({
  consumerKey: 'key',
  consumerSecret: 'secret',
  sandbox: true
});

// NEW (2.x):
const Evernote = require('evernote');
const client = new Evernote.Client({
  consumerKey: 'key',
  consumerSecret: 'secret',
  sandbox: true
});

// 2. API calls return Promises (not callbacks)
// OLD (1.x):
noteStore.listNotebooks(function(err, notebooks) {
  if (err) console.error(err);
  else console.log(notebooks);
});

// NEW (2.x):
noteStore.listNotebooks()
  .then(notebooks => console.log(notebooks))
  .catch(err => console.error(err));

// Or with async/await:
const notebooks = await noteStore.listNotebooks();

// 3. Type constructors
// OLD (1.x):
var note = new Evernote.Note();

// NEW (2.x):
const note = new Evernote.Types.Note();

Step 3: Migration Script

// scripts/migrate-to-v2.js
const fs = require('fs');
const path = require('path');
const glob = require('glob');

const migrations = [
  // Client import
  {
    pattern: /require\(['"]evernote['"]\)\.Evernote/g,
    replacement: "require('evernote')"
  },

  // Type constructors
  {
    pattern: /new Evernote\.Note\(\)/g,
    replacement: 'new Evernote.Types.Note()'
  },
  {
    pattern: /new Evernote\.Notebook\(\)/g,
    replacement: 'new Evernote.Types.Notebook()'
  },
  {
    pattern: /new Evernote\.Tag\(\)/g,
    replacement: 'new Evernote.Types.Tag()'
  },
  {
    pattern: /new Evernote\.Resource\(\)/g,
    replacement: 'new Evernote.Types.Resource()'
  },

  // NoteFilter
  {
    pattern: /new Evernote\.NoteFilter\(\)/g,
    replacement: 'new Evernote.NoteStore.NoteFilter()'
  },

  // NotesMetadataResultSpec
  {
    pattern: /new Evernote\.NotesMetadataResultSpec\(\)/g,
    replacement: 'new Evernote.NoteStore.NotesMetadataResultSpec()'
  }
];

function migrateFile(filePath) {
  let content = fs.readFileSync(filePath, 'utf8');
  let modified = false;

  for (const { pattern, replacement } of migrations) {
    if (pattern.test(content)) {
      content = content.replace(pattern, replacement);
      modified = true;
    }
  }

  if (modified) {
    // Create backup
    fs.writeFileSync(`${filePath}.bak`, fs.readFileSync(filePath));
    // Write migrated file
    fs.writeFileSync(filePath, content);
    console.log(`Migrated: ${filePath}`);
    return true;
  }

  return false;
}

// Run migration
const files = glob.sync('src/**/*.js');
let migratedCount = 0;

for (const file of files) {
  if (migrateFile(file)) {
    migratedCount++;
  }
}

console.log(`\nMigration complete. ${migratedCount} files modified.`);
console.log('Backup files created with .bak extension');

Step 4: Convert Callbacks to Promises

// utils/promisify-legacy.js

/**
 * Wrapper for legacy callback-based code
 */
function promisifyNoteStore(noteStore) {
  const promisified = {};

  // List of methods that need promisification
  const methods = [
    'listNotebooks',
    'getNotebook',
    'createNotebook',
    'updateNotebook',
    'listTags',
    'getTag',
    'createTag',
    'getNote',
    'createNote',
    'updateNote',
    'deleteNote',
    'findNotesMetadata',
    'getNoteContent',
    'getResource'
  ];

  for (const method of methods) {
    promisified[method] = (...args) => {
      return new Promise((resolve, reject) => {
        noteStore[method](...args, (err, result) => {
          if (err) reject(err);
          else resolve(result);
        });
      });
    };
  }

  return promisified;
}

module.exports = { promisifyNoteStore };

Step 5: Upgrade Dependencies

# Update to latest version
npm install evernote@latest

# If using TypeScript, update types
npm install @types/evernote@latest --save-dev

# Update related dependencies
npm update

Step 6: Test Suite Updates

// tests/migration-tests.js
const assert = require('assert');
const Evernote = require('evernote');

describe('SDK v2 Migration Tests', () => {
  let client;
  let noteStore;

  before(() => {
    client = new Evernote.Client({
      token: process.env.EVERNOTE_ACCESS_TOKEN,
      sandbox: true
    });
    noteStore = client.getNoteStore();
  });

  describe('Type Constructors', () => {
    it('should create Note using Types namespace', () => {
      const note = new Evernote.Types.Note();
      assert(note);
      note.title = 'Test';
      assert.equal(note.title, 'Test');
    });

    it('should create NoteFilter using NoteStore namespace', () => {
      const filter = new Evernote.NoteStore.NoteFilter({
        words: 'test'
      });
      assert(filter);
      assert.equal(filter.words, 'test');
    });
  });

  describe('Promise-based API', () => {
    it('should return Promise from listNotebooks', async () => {
      const result = noteStore.listNotebooks();
      assert(result instanceof Promise);
    });

    it('should resolve notebooks array', async () => {
      const notebooks = await noteStore.listNotebooks();
      assert(Array.isArray(notebooks));
    });
  });

  describe('Error Handling', () => {
    it('should reject with EDAMUserException for invalid data', async () => {
      const note = new Evernote.Types.Note();
      // Missing required fields

      try {
        await noteStore.createNote(note);
        assert.fail('Should have thrown');
      } catch (error) {
        assert(error.errorCode !== undefined);
      }
    });
  });
});

Step 7: Compatibility Layer

// utils/compatibility.js

/**
 * Compatibility layer for gradual migration
 * Supports both callback and Promise patterns
 */
class CompatibleNoteStore {
  constructor(noteStore) {
    this.store = noteStore;
  }

  listNotebooks(callback) {
    const promise = this.store.listNotebooks();

    if (callback) {
      // Legacy callback support
      promise
        .then(result => callback(null, result))
        .catch(error => callback(error, null));
      return;
    }

    return promise;
  }

  getNote(guid, withContent, withResources, withRecognition, withAlternate, callback) {
    const promise = this.store.getNote(
      guid,
      withContent,
      withResources,
      withRecognition,
      withAlternate
    );

    if (callback) {
      promise
        .then(result => callback(null, result))
        .catch(error => callback(error, null));
      return;
    }

    return promise;
  }

  createNote(note, callback) {
    const promise = this.store.createNote(note);

    if (callback) {
      promise
        .then(result => callback(null, result))
        .catch(error => callback(error, null));
      return;
    }

    return promise;
  }

  // Add more methods as needed
}

module.exports = CompatibleNoteStore;

Step 8: Deprecation Warnings

// utils/deprecation-warnings.js

const deprecations = new Set();

function warnOnce(message) {
  if (!deprecations.has(message)) {
    deprecations.add(message);
    console.warn(`[DEPRECATION WARNING] ${message}`);
  }
}

// Proxy to add deprecation warnings
function wrapWithDeprecationWarnings(noteStore) {
  return new Proxy(noteStore, {
    get(target, prop) {
      // Warn about deprecated patterns
      if (prop === 'getNote') {
        return (...args) => {
          if (args.length === 6 && typeof args[5] === 'function') {
            warnOnce(
              'Callback pattern is deprecated. ' +
              'Use Promise: noteStore.getNote(...).then(note => ...)'
            );
          }
          return target[prop](...args);
        };
      }

      return target[prop];
    }
  });
}

module.exports = { wrapWithDeprecationWarnings };

Migration Checklist

## SDK v2 Migration Checklist

### Pre-Migration
- [ ] Backup current codebase
- [ ] Document current SDK version
- [ ] Review breaking changes
- [ ] Set up test environment

### Code Changes
- [ ] Update import statements
- [ ] Update type constructors (Types namespace)
- [ ] Update filter constructors (NoteStore namespace)
- [ ] Convert callbacks to Promises/async-await
- [ ] Update error handling for Promise rejections

### Testing
- [ ] Run migration script on test branch
- [ ] Execute full test suite
- [ ] Test OAuth flow end-to-end
- [ ] Test note CRUD operations
- [ ] Test search functionality
- [ ] Verify error handling

### Deployment
- [ ] Deploy to staging
- [ ] Run integration tests
- [ ] Monitor for errors
- [ ] Deploy to production
- [ ] Monitor metrics

### Cleanup
- [ ] Remove compatibility layers (after validation period)
- [ ] Remove backup files
- [ ] Update documentation
- [ ] Archive migration scripts

Output

  • SDK version comparison
  • Automated migration script
  • Callback to Promise conversion
  • Compatibility layer for gradual migration
  • Migration test suite
  • Deprecation warning system

Error Handling

IssueCauseSolution
Evernote.Note is not a constructorOld import styleUse Evernote.Types.Note
callback is not a functionMixed patternsUse Promise or callback, not both
Cannot read property 'then'Using old callback-only methodUpdate to Promise-based method

Resources

  • Evernote SDK JS
  • SDK Changelog
  • API Reference

Next Steps

For CI/CD integration, see evernote-ci-integration.