Skip to content

Instantly share code, notes, and snippets.

@alxhub
Created March 29, 2016 18:05
Show Gist options
  • Save alxhub/70963c69d47948fda71b9fce2b997239 to your computer and use it in GitHub Desktop.
Save alxhub/70963c69d47948fda71b9fce2b997239 to your computer and use it in GitHub Desktop.
import {Observable} from 'rxjs/Rx';
import {Manifest, ManifestParser, ManifestDelta, GroupDelta, ManifestGroup} from './manifest';
let EMPTY_GROUP = new ManifestGroup();
function _keys(...objs: Object[]): string[] {
let keys = {};
objs.forEach(obj => Object
.keys(obj)
.forEach(key => keys[key] = true));
return Object.keys(keys);
}
function _groupOrEmpty(manifest: Manifest, name: string): ManifestGroup {
if (!manifest.group.hasOwnProperty(name)) {
return EMPTY_GROUP
}
return manifest.group[name];
}
interface DiffArrayResult {
added: string[];
removed: string[];
}
function _diffArray(prev: string[], curr: string[]): DiffArrayResult {
return <DiffArrayResult>{
added: curr.filter(value => prev.indexOf(value) == -1),
removed: prev.filter(value => curr.indexOf(value) == -1)
};
}
function _diffGroups(prev: ManifestGroup, curr: ManifestGroup): GroupDelta {
let cacheDiff = _diffArray(_keys(prev.cache), _keys(curr.cache));
let networkDiff = _diffArray(_keys(prev.network), _keys(curr.network));
let fallbackDiff = _diffArray(_keys(prev.fallback), _keys(curr.fallback));
return <GroupDelta> {
cacheAdded: cacheDiff.added,
cacheRemoved: cacheDiff.removed,
networkAdded: networkDiff.added,
networkRemoved: networkDiff.removed,
fallbackAdded: fallbackDiff.added,
fallbackRemoved: fallbackDiff.removed
};
}
export function diffManifests(obs: Observable<string[]>): Observable<any> {
let parser = new ManifestParser();
return obs.map(manifests => {
let [cachedManifestData, liveManifestData] = manifests;
let delta = new ManifestDelta();
let current = parser.parse(liveManifestData);
delta.current = current;
// Fast path for identical manifests.
if (cachedManifestData && cachedManifestData == liveManifestData) {
delta.changed = false;
return delta;
}
delta.changed = true;
let previous = parser.parse(cachedManifestData);
delta.previous = previous;
let groups = _keys(current.group, previous.group);
groups.forEach(name => {
let prevGroup = _groupOrEmpty(previous, name);
let currGroup = _groupOrEmpty(current, name);
delta.delta[name] = _diffGroups(prevGroup, currGroup);
});
return delta;
});
}
export interface ManifestEntry {
url: string;
metadata: Object;
groupMetadata: Object;
}
export interface ManifestEntryMap {
[url: string]: ManifestEntry;
}
export interface FallbackManifestEntry extends ManifestEntry {
fallbackTo: string;
}
export interface FallbackEntryMap {
[url: string]: FallbackManifestEntry;
}
export class ManifestGroup {
cache: ManifestEntryMap = {};
network: ManifestEntryMap = {};
fallback: FallbackEntryMap = {};
}
export interface ManifestGroupMap {
[name: string]: ManifestGroup;
}
export interface GroupDelta {
cacheAdded: string[];
cacheRemoved: string[];
networkAdded: string[];
networkRemoved: string[];
fallbackAdded: string[];
fallbackRemoved: string[];
}
export interface GroupDeltaMap {
[name: string]: GroupDelta;
}
export class Manifest {
metadata: Object;
group: ManifestGroupMap = {}
}
export class ManifestDelta {
changed: boolean;
current: Manifest;
previous: Manifest;
delta: GroupDeltaMap = {};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment