object-migrations
Version:
Linear, in-memory migrations for versioned objects
2 lines (1 loc) • 2.66 kB
JavaScript
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).ObjectMigrations={})}(this,(function(t){"use strict";class e extends Error{constructor(t,e){super(e),this.name=t}}class r extends e{constructor(t,e,r){super("MigrationError",`Error "${String(r)}" thrown while migrating an object from version ${s(t)} to ${s(e)}`),this.from=t,this.to=e,this.cause=r}}class o extends e{constructor(t,e){super("NoMigrationStepsError",`No migration steps from version ${s(t)} to ${s(e)}`),this.from=t,this.to=e}}function s(t){return"function"==typeof t&&""!==t.name?t.name:String(t)}t.MigrationError=r,t.Migrator=class{constructor(){this.forwardStep=new Map,this.backwardStep=new Map,this.cache=new Map}register(t,e,r,o){this.forwardStep.set(t,{to:e,migration:r}),void 0!==o&&this.backwardStep.set(e,{to:t,migration:o})}forward(t,e,r){if(void 0!==r){const o=e;return this.migrate(t,o,r,this.forwardStep)}{const r=t.constructor,o=e;return this.migrate(t,r,o,this.forwardStep)}}async forwardAsync(t,e,r){if(void 0!==r){const o=e;return await this.migrateAsync(t,o,r,this.forwardStep)}{const r=t.constructor,o=e;return await this.migrateAsync(t,r,o,this.forwardStep)}}backward(t,e,r){const o=this.resolveOverloadVersions(t,e,r);return this.migrate(t,o.from,o.to,this.backwardStep)}async backwardAsync(t,e,r){const o=this.resolveOverloadVersions(t,e,r);return await this.migrateAsync(t,o.from,o.to,this.backwardStep)}resolveOverloadVersions(t,e,r){return void 0!==r?{from:e,to:r}:{from:t.constructor,to:e}}migrate(t,e,o,s){if(e===o)return{value:t,changed:!1};let i=this.tryGetCachedSteps(e,o);void 0===i&&(i=this.computeSteps(e,o,s),this.cacheSteps(e,o,i));let n=t;for(const t of i)try{n=(0,t.migration)(n)}catch(t){throw new r(e,o,t)}return{value:n,changed:!0}}async migrateAsync(t,e,o,s){if(e===o)return{value:t,changed:!1};let i=this.tryGetCachedSteps(e,o);void 0===i&&(i=this.computeSteps(e,o,s),this.cacheSteps(e,o,i));let n=t;for(const t of i)try{const e=t.migration;n=await Promise.resolve(e(n))}catch(t){throw new r(e,o,t)}return{value:n,changed:!0}}computeSteps(t,e,r){const s=[];let i=r.get(t);if(void 0===i)throw new o(t,e);for(;void 0!==i&&(s.push(i),i.to!==e);)i=r.get(i.to);if(0===s.length||s[s.length-1].to!==e)throw new o(t,e);return s}tryGetCachedSteps(t,e){return this.cache.get(t)?.get(e)}cacheSteps(t,e,r){if(0===r.length)throw new RangeError("There must be at least 1 step to be cached.");let o=this.cache.get(t);void 0===o&&(o=new Map,this.cache.set(t,o)),o.set(e,r)}},t.MigratorError=e,t.NoMigrationStepsError=o}));