From e94f84283d3fcae8340a508016e2596cd4dd3795 Mon Sep 17 00:00:00 2001 From: Roman Hotsiy Date: Tue, 6 Mar 2018 13:10:08 +0200 Subject: [PATCH] feat: serialize search-index --- demo/playground/hmr-playground.tsx | 4 ++-- package.json | 2 +- src/services/AppStore.ts | 19 ++++++++++++++----- src/services/SearchStore.ts | 29 +++++++++++++++++++---------- src/services/SearchWorker.worker.ts | 16 +++++++++++++++- 5 files changed, 51 insertions(+), 19 deletions(-) diff --git a/demo/playground/hmr-playground.tsx b/demo/playground/hmr-playground.tsx index c90cfa4ae0..e1f3688e97 100644 --- a/demo/playground/hmr-playground.tsx +++ b/demo/playground/hmr-playground.tsx @@ -35,12 +35,12 @@ async function init() { init(); if (module.hot) { - const reload = (reloadStore = false) => () => { + const reload = (reloadStore = false) => async () => { if (reloadStore) { // create a new Store store.dispose(); - const state = store.toJS(); + const state = await store.toJS(); store = AppStore.fromJS(state); } diff --git a/package.json b/package.json index 604373aafb..732bc2ce06 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,7 @@ "webpack": "^3.10.0", "webpack-dev-server": "^2.9.5", "webpack-node-externals": "^1.6.0", - "workerize-loader": "^1.0.1", + "workerize-loader": "^1.0.2", "yaml-js": "^0.2.3" }, "peerDependencies": { diff --git a/src/services/AppStore.ts b/src/services/AppStore.ts index 51eece3e7b..81031cc06c 100644 --- a/src/services/AppStore.ts +++ b/src/services/AppStore.ts @@ -17,6 +17,7 @@ interface StoreData { url: string; data: any; }; + searchIndex: any; options: RedocRawOptions; } @@ -36,9 +37,10 @@ export class AppStore { */ // TODO: static fromJS(state: StoreData): AppStore { - const inst = new AppStore(state.spec.data, state.spec.url, state.options); + const inst = new AppStore(state.spec.data, state.spec.url, state.options, false); inst.menu.activeItemIdx = state.menu.activeItemIdx || 0; inst.menu.activate(inst.menu.flatItems[inst.menu.activeItemIdx]); + inst.search.load(state.searchIndex); return inst; } @@ -52,7 +54,12 @@ export class AppStore { private scroll: ScrollService; private disposer; - constructor(spec: OpenAPISpec, specUrl?: string, options: RedocRawOptions = {}) { + constructor( + spec: OpenAPISpec, + specUrl?: string, + options: RedocRawOptions = {}, + createSearchIndex: boolean = true, + ) { this.rawOptions = options; this.options = new RedocNormalizedOptions(options); this.scroll = new ScrollService(this.options); @@ -60,8 +67,9 @@ export class AppStore { this.menu = new MenuStore(this.spec, this.scroll); this.search = new SearchStore(); - this.search.indexItems(this.menu.items); - this.search.done(); + if (createSearchIndex) { + this.search.indexItems(this.menu.items); + } this.disposer = observe(this.menu, 'activeItemIdx', change => { this.updateMarkOnMenu(change.newValue as number); @@ -106,7 +114,7 @@ export class AppStore { * **SUPER HACKY AND NOT OPTIMAL IMPLEMENTATION** */ // TODO: - toJS(): StoreData { + async toJS(): Promise { return { menu: { activeItemIdx: this.menu.activeItemIdx, @@ -115,6 +123,7 @@ export class AppStore { url: this.spec.parser.specUrl, data: this.spec.parser.spec, }, + searchIndex: await this.search.toJS(), options: this.rawOptions, }; } diff --git a/src/services/SearchStore.ts b/src/services/SearchStore.ts index e85a511623..9f537f0452 100644 --- a/src/services/SearchStore.ts +++ b/src/services/SearchStore.ts @@ -6,23 +6,32 @@ export class SearchStore { searchWorker = new worker(); indexItems(groups: Array) { - groups.forEach(group => { - if (group.type !== 'group') { - this.add(group.name, group.description || '', group.id); - } - this.indexItems(group.items); - }); + const recurse = groups => { + groups.forEach(group => { + if (group.type !== 'group') { + this.add(group.name, group.description || '', group.id); + } + recurse(group.items); + }); + }; + + recurse(groups); + this.searchWorker.done(); } add(title: string, body: string, ref: string) { this.searchWorker.add(title, body, ref); } - done() { - this.searchWorker.done(); - } - search(q: string) { return this.searchWorker.search(q); } + + async toJS() { + return this.searchWorker.toJS(); + } + + load(state: any) { + this.searchWorker.load(state); + } } diff --git a/src/services/SearchWorker.worker.ts b/src/services/SearchWorker.worker.ts index 170850ec53..d0efd21cb4 100644 --- a/src/services/SearchWorker.worker.ts +++ b/src/services/SearchWorker.worker.ts @@ -5,6 +5,8 @@ export default class Worker { add = add; done = done; search = search; + toJS = toJS; + load = load; } export interface SearchDocument { @@ -17,7 +19,7 @@ export interface SearchResult extends SearchDocument { score: number; } -const store: { [id: string]: SearchDocument } = {}; +let store: { [id: string]: SearchDocument } = {}; let resolveIndex: (v: lunr.Index) => void; const index: Promise = new Promise(resolve => { @@ -43,6 +45,18 @@ export async function done() { resolveIndex(builder.build()); } +export async function toJS() { + return { + store: store, + index: (await index).toJSON(), + }; +} + +export async function load(state: any) { + store = state.store; + resolveIndex(lunr.Index.load(state.index)); +} + export async function search(q: string): Promise { if (q.trim().length === 0) { return [];