Last active
September 5, 2018 03:20
-
-
Save poltak/c3ec3498bc09dd16633025bd1eb78c11 to your computer and use it in GitHub Desktop.
mostly derived from these two modules:https://github.com/WorldBrain/Memex/blob/develop/src/search/storage/dexie-schema.ts and https://github.com/dfahlander/Dexie.js/blob/v2.0.4/samples/open-existing-db/dump-databases.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function getDexieHistory(storageRegistry) { | |
const collections = {} | |
const versions = [] | |
let version = 0 | |
Object.entries(storageRegistry.collectionsByVersion) | |
.sort((left, right) => (left[0] < right[0] ? -1 : 1)) | |
.forEach(([versionTimestamp, defs]) => { | |
defs.forEach(def => (collections[def.name] = def)) | |
versions.push({ | |
...getDexieSchema(collections), | |
version: ++version, | |
}) | |
}) | |
return JSON.stringify(patchDirectLinksSchema(versions), null, 4) | |
} | |
function getDexieSchema(collections) { | |
const schema = {} | |
const migrations = [] | |
Object.entries(collections).forEach(([collectionName, collectionDef]) => { | |
schema[collectionName] = convertIndexToDexieExps(collectionDef) | |
if (collectionDef.migrate && !collectionDef.migrate._seen) { | |
collectionDef.migrate._seen = true // TODO: Clean this up, should have no side-effects | |
migrations.push(collectionDef.migrate) | |
} | |
}) | |
return { schema, migrations } | |
} | |
/** | |
* Handles converting from StorageManager index definitions to Dexie index expressions. | |
*/ | |
function convertIndexToDexieExps({ fields, indices }) { | |
return indices | |
.sort(({ pk }) => (pk ? -1 : 1)) // PK indexes always come first in Dexie | |
.map(indexDef => { | |
// Convert from StorageManager compound index to Dexie compound index | |
// Note that all other `IndexDefinition` opts are ignored for compound indexes | |
if (indexDef.field instanceof Array) { | |
return `[${indexDef.field[0]}+${indexDef.field[1]}]` | |
} | |
// Create Dexie MultiEntry index for indexed text fields: http://dexie.org/docs/MultiEntry-Index | |
// TODO: throw error if text field + PK index | |
if (fields[indexDef.field].type === 'text') { | |
const fullTextField = | |
indexDef.fullTextIndexName || `_${indexDef.field}_terms` | |
return `*${fullTextField}` | |
} | |
// Note that order of these statements matters | |
let listPrefix = indexDef.unique ? '&' : '' | |
listPrefix = indexDef.pk && indexDef.autoInc ? '++' : listPrefix | |
return `${listPrefix}${indexDef.field}` | |
}) | |
.join(', ') | |
} | |
/** | |
* Takes the generated schema versions, based on the registed collections, and finds the | |
* first one in which `directLinks` schema was added, then generates a "patch" schema. | |
* This "patch" schema should contain the incorrect indexes that was accidently rolled out | |
* to users at the release of our Direct Links feature. This should ensure Dexie knows about | |
* both the incorrect indexes and how to drop those to migrate to the correct indexes. | |
*/ | |
function patchDirectLinksSchema(schemaVersions) { | |
const firstAppears = schemaVersions.findIndex( | |
({ schema }) => schema.directLinks != null, | |
) | |
// Return schemas as-is if direct links schema not found (tests) | |
if (firstAppears === -1) { | |
return schemaVersions | |
} | |
const preceding = schemaVersions[firstAppears - 1] | |
const patchedSchema = { | |
schema: { | |
...preceding.schema, | |
directLinks: 'url, *pageTitle, *body, createdWhen', | |
}, | |
migrations: [], | |
version: preceding.version + 1, | |
} | |
return [ | |
...schemaVersions.slice(0, firstAppears), | |
// Shim the schema with the incorrect indexes, so Dexie knows about its existence | |
patchedSchema, | |
// All subsequent schemas need to be 1 version higher to take the incorrect index schema into account | |
...schemaVersions | |
.slice(firstAppears) | |
.map(schema => ({ ...schema, version: schema.version + 1 })), | |
] | |
} | |
function dumpCurrentState() { | |
storage.tables.forEach(function (table, i) { | |
var primKeyAndIndexes = [table.schema.primKey].concat(table.schema.indexes) | |
var schemaSyntax = primKeyAndIndexes.map(index => index.src).join(',') | |
console.log(table.name + ": '" + schemaSyntax + "'" + (i < storage.tables.length - 1 ? "," : "")) | |
}) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment