| name | evernote-migration-deep-dive |
| description | Deep dive into Evernote data migration strategies.
Use when migrating to/from Evernote, bulk data transfers,
or complex migration scenarios.
Trigger with phrases like "migrate to evernote", "migrate from evernote",
"evernote data transfer", "bulk evernote migration".
|
| allowed-tools | Read, Write, Edit, Bash(npm:*), Grep |
| version | 1.0.0 |
| license | MIT |
| author | Jeremy Longshore <jeremy@intentsolutions.io> |
Evernote Migration Deep Dive
Overview
Comprehensive guide for migrating data to and from Evernote, including bulk operations, format conversions, and maintaining data integrity.
Prerequisites
- Understanding of Evernote data model
- Source/target system access
- Sufficient API quota for migration
- Backup strategy in place
Migration Scenarios
| Scenario | Source | Target | Complexity |
|---|
| Import to Evernote | External | Evernote | Medium |
| Export from Evernote | Evernote | External | Medium |
| Evernote to Evernote | Account A | Account B | High |
| Bulk archive | Evernote | Archive storage | Low |
Instructions
Step 1: Migration Planning
class MigrationPlanner {
constructor(sourceClient, targetConfig) {
this.source = sourceClient;
this.target = targetConfig;
this.plan = null;
}
async analyzeSource() {
const noteStore = this.source.getNoteStore();
const notebooks = await noteStore.listNotebooks();
const tags = await noteStore.listTags();
const noteCounts = {};
for (const notebook of notebooks) {
const filter = new Evernote.NoteStore.NoteFilter({
notebookGuid: notebook.guid
});
const result = await noteStore.findNotesMetadata(
filter, 0, 1,
new Evernote.NoteStore.({})
);
noteCounts[notebook.] = result.;
}
analysis = {
: notebooks.,
: tags.,
: .(noteCounts).( a + b, ),
: notebooks.( ({
: nb.,
: nb.,
: noteCounts[nb.]
})),
: .(.(noteCounts).( a + b, )),
: []
};
(analysis. > ) {
analysis..();
}
(analysis. > ) {
analysis..();
}
analysis;
}
() {
seconds = noteCount;
hours = .(seconds / );
;
}
() {
analysis = .();
. = {
: ,
: ().(),
: {
: ,
analysis
},
: .,
: {
: options. ?? ,
: options. ?? ,
: options. ?? ,
: options. || {},
: options. || [],
: options. || ,
: options. ||
},
: ,
: {
: analysis.,
: ,
:
}
};
.;
}
}
. = ;
Step 2: Export from Evernote
const fs = require('fs').promises;
const path = require('path');
class EvernoteExporter {
constructor(noteStore, options = {}) {
this.noteStore = noteStore;
this.outputDir = options.outputDir || './export';
this.format = options.format || 'enex';
}
async exportAll(progressCallback) {
await fs.mkdir(this.outputDir, { recursive: true });
const notebooks = await this.noteStore.listNotebooks();
const tags = await this.noteStore.listTags();
await this.exportMetadata(notebooks, tags);
let total = ;
exported = ;
( notebook notebooks) {
noteCount = .(notebook, {
progressCallback?.({
: ,
: notebook.,
...progress
});
});
total += noteCount;
exported += noteCount;
}
{
: notebooks.,
: tags.,
: total,
: .
};
}
() {
metadata = {
: ().(),
: notebooks.( ({
: nb.,
: nb.,
: nb.,
: nb.
})),
: tags.( ({
: t.,
: t.,
: t.
}))
};
fs.(
path.(., ),
.(metadata, , )
);
}
() {
notebookDir = path.(., .(notebook.));
fs.(notebookDir, { : });
filter = ..({
: notebook.
});
spec = ..({
: ,
:
});
result = ..(filter, , , spec);
total = result..;
exported = ;
( noteMeta result.) {
{
note = ..(
noteMeta.,
,
,
,
);
.(note, notebookDir);
exported++;
progressCallback?.({
: exported,
total,
: note.
});
.();
} (error) {
.(, error.);
}
}
exported;
}
() {
noteDir = path.(outputDir, .(note.) + + note..(, ));
fs.(noteDir, { : });
(.) {
:
.(note, noteDir);
;
:
.(note, noteDir);
;
:
:
.(note, noteDir);
}
(note.) {
resourcesDir = path.(noteDir, );
fs.(resourcesDir, { : });
( resource note.) {
.(resource, resourcesDir);
}
}
}
() {
data = {
: note.,
: note.,
: note.,
: note.,
: note.,
: note.,
: note.?.( ({
: r.,
: r.,
: r.?.,
: .(r..).()
}))
};
fs.(
path.(outputDir, ),
.(data, , )
);
}
() {
markdown = ;
markdown += ;
markdown += ;
markdown += ;
markdown += .(note.);
fs.(
path.(outputDir, ),
markdown
);
}
() {
md = enml
.(, )
.(, )
.(, )
.(, )
.(, )
.(, )
.(, )
.(, )
.(, )
.(, )
.(, )
.(, )
.(, )
.(, )
.(, )
.(, )
.(, )
.(, )
.(, )
.(, )
.(, )
.(, )
.(, )
.(, )
.(, )
.(, )
.(, )
.(, )
.(, )
.();
md;
}
() {
hash = .(resource..).();
ext = .(resource.);
fileName = resource.?. || ;
fs.(
path.(outputDir, fileName),
resource..
);
}
() {
name
.(, )
.(, )
.(, );
}
() {
map = {
: ,
: ,
: ,
:
};
map[mimeType] || ;
}
() {
( (resolve, ms));
}
}
. = ;
Step 3: Import to Evernote
const fs = require('fs').promises;
const path = require('path');
const crypto = require('crypto');
class EvernoteImporter {
constructor(noteStore, options = {}) {
this.noteStore = noteStore;
this.batchSize = options.batchSize || 10;
this.notebookMapping = new Map();
this.tagMapping = new Map();
}
async importFromDirectory(sourceDir, progressCallback) {
const metadataPath = path.join(sourceDir, 'metadata.json');
const metadata = JSON.parse(await fs.readFile(metadataPath, 'utf8'));
await this.createNotebooks(metadata.notebooks);
.(metadata.);
notebooks = fs.(sourceDir, { : });
totalImported = ;
( entry notebooks) {
(entry.() && entry. !== ) {
notebookDir = path.(sourceDir, entry.);
imported = .(notebookDir, entry., progressCallback);
totalImported += imported;
}
}
{ : totalImported };
}
() {
existing = ..();
existingMap = (existing.( [nb..(), nb]));
( nb notebooks) {
existingNb = existingMap.(nb..());
(existingNb) {
..(nb., existingNb.);
} {
newNb = ..();
newNb. = nb.;
(nb.) newNb. = nb.;
created = ..(newNb);
..(nb., created.);
}
}
}
() {
existing = ..();
existingMap = (existing.( [t..(), t]));
( tag tags) {
existingTag = existingMap.(tag..());
(existingTag) {
..(tag., existingTag.);
} {
newTag = ..();
newTag. = tag.;
created = ..(newTag);
..(tag., created.);
}
}
}
() {
notes = fs.(notebookDir, { : });
noteDirs = notes.( e.());
imported = ;
( noteEntry noteDirs) {
{
noteDir = path.(notebookDir, noteEntry.);
.(noteDir);
imported++;
progressCallback?.({
: notebookName,
: imported,
: noteDirs.
});
.();
} (error) {
.(, error.);
}
}
imported;
}
() {
jsonPath = path.(noteDir, );
data = .( fs.(jsonPath, ));
note = ..();
note. = data.;
note. = data.;
(data. && ..(data.)) {
note. = ..(data.);
}
(data.) {
note. = data.
.( ..(guid))
.();
}
(data.) {
note. = [];
resourcesDir = path.(noteDir, );
( resMeta data.) {
{
resource = .(resourcesDir, resMeta);
(resource) {
note..(resource);
}
} (error) {
.(, error.);
}
}
}
..(note);
}
() {
files = fs.(resourcesDir);
matchingFile = files.(
f.(metadata.) || f === metadata.
);
(!matchingFile) {
.();
;
}
filePath = path.(resourcesDir, matchingFile);
fileData = fs.(filePath);
hash = crypto.().(fileData).();
resource = ..();
resource. = metadata.;
resource. = ..();
resource.. = fileData;
resource.. = fileData.;
resource.. = hash;
(metadata.) {
resource. = ..();
resource.. = metadata.;
}
resource;
}
() {
( (resolve, ms));
}
}
. = ;
Step 4: Migration Runner
class MigrationRunner {
constructor(plan, exporter, importer) {
this.plan = plan;
this.exporter = exporter;
this.importer = importer;
this.status = 'pending';
this.startTime = null;
this.endTime = null;
this.errors = [];
}
async run(progressCallback) {
this.status = 'running';
this.startTime = Date.now();
try {
progressCallback?.({ phase: 'export', status: 'starting' });
const exportResult = await this.exporter.exportAll((progress) => {
progressCallback?.({ phase: 'export', ...progress });
});
progressCallback?.({ phase: , : , : exportResult });
progressCallback?.({ : , : });
importResult = ..(
..,
{
progressCallback?.({ : , ...progress });
}
);
progressCallback?.({ : , : , : importResult });
progressCallback?.({ : , : });
verifyResult = .();
progressCallback?.({ : , : , : verifyResult });
. = ;
} (error) {
. = ;
..(error.);
error;
} {
. = .();
}
.();
}
() {
{ : };
}
() {
{
: ..,
: .,
: (.).(),
: . ? (.).() : ,
: . ? : ,
: .
};
}
}
. = ;
Output
- Migration planning tools
- Evernote data exporter (JSON, Markdown, ENEX)
- Evernote data importer
- Migration runner with progress tracking
- Verification and reporting
Migration Checklist
## Pre-Migration
- [ ] Analyze source data
- [ ] Create migration plan
- [ ] Backup source data
- [ ] Test with small dataset
- [ ] Verify API quota
## During Migration
- [ ] Monitor progress
- [ ] Check for errors
- [ ] Handle rate limits
- [ ] Log all operations
## Post-Migration
- [ ] Verify data integrity
- [ ] Compare counts
- [ ] Test functionality
- [ ] Document results
- [ ] Clean up temporary files
Resources
Support
For complex migrations, consider contacting Evernote Business support or professional services.