Skip to content

Commit e94f842

Browse files
committed
feat: serialize search-index
1 parent 8e4184b commit e94f842

File tree

5 files changed

+51
-19
lines changed

5 files changed

+51
-19
lines changed

demo/playground/hmr-playground.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@ async function init() {
3535
init();
3636

3737
if (module.hot) {
38-
const reload = (reloadStore = false) => () => {
38+
const reload = (reloadStore = false) => async () => {
3939
if (reloadStore) {
4040
// create a new Store
4141
store.dispose();
4242

43-
const state = store.toJS();
43+
const state = await store.toJS();
4444
store = AppStore.fromJS(state);
4545
}
4646

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@
7272
"webpack": "^3.10.0",
7373
"webpack-dev-server": "^2.9.5",
7474
"webpack-node-externals": "^1.6.0",
75-
"workerize-loader": "^1.0.1",
75+
"workerize-loader": "^1.0.2",
7676
"yaml-js": "^0.2.3"
7777
},
7878
"peerDependencies": {

src/services/AppStore.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ interface StoreData {
1717
url: string;
1818
data: any;
1919
};
20+
searchIndex: any;
2021
options: RedocRawOptions;
2122
}
2223

@@ -36,9 +37,10 @@ export class AppStore {
3637
*/
3738
// TODO:
3839
static fromJS(state: StoreData): AppStore {
39-
const inst = new AppStore(state.spec.data, state.spec.url, state.options);
40+
const inst = new AppStore(state.spec.data, state.spec.url, state.options, false);
4041
inst.menu.activeItemIdx = state.menu.activeItemIdx || 0;
4142
inst.menu.activate(inst.menu.flatItems[inst.menu.activeItemIdx]);
43+
inst.search.load(state.searchIndex);
4244
return inst;
4345
}
4446

@@ -52,16 +54,22 @@ export class AppStore {
5254
private scroll: ScrollService;
5355
private disposer;
5456

55-
constructor(spec: OpenAPISpec, specUrl?: string, options: RedocRawOptions = {}) {
57+
constructor(
58+
spec: OpenAPISpec,
59+
specUrl?: string,
60+
options: RedocRawOptions = {},
61+
createSearchIndex: boolean = true,
62+
) {
5663
this.rawOptions = options;
5764
this.options = new RedocNormalizedOptions(options);
5865
this.scroll = new ScrollService(this.options);
5966
this.spec = new SpecStore(spec, specUrl, this.options);
6067
this.menu = new MenuStore(this.spec, this.scroll);
6168

6269
this.search = new SearchStore();
63-
this.search.indexItems(this.menu.items);
64-
this.search.done();
70+
if (createSearchIndex) {
71+
this.search.indexItems(this.menu.items);
72+
}
6573

6674
this.disposer = observe(this.menu, 'activeItemIdx', change => {
6775
this.updateMarkOnMenu(change.newValue as number);
@@ -106,7 +114,7 @@ export class AppStore {
106114
* **SUPER HACKY AND NOT OPTIMAL IMPLEMENTATION**
107115
*/
108116
// TODO:
109-
toJS(): StoreData {
117+
async toJS(): Promise<StoreData> {
110118
return {
111119
menu: {
112120
activeItemIdx: this.menu.activeItemIdx,
@@ -115,6 +123,7 @@ export class AppStore {
115123
url: this.spec.parser.specUrl,
116124
data: this.spec.parser.spec,
117125
},
126+
searchIndex: await this.search.toJS(),
118127
options: this.rawOptions,
119128
};
120129
}

src/services/SearchStore.ts

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,32 @@ export class SearchStore {
66
searchWorker = new worker();
77

88
indexItems(groups: Array<IMenuItem | OperationModel>) {
9-
groups.forEach(group => {
10-
if (group.type !== 'group') {
11-
this.add(group.name, group.description || '', group.id);
12-
}
13-
this.indexItems(group.items);
14-
});
9+
const recurse = groups => {
10+
groups.forEach(group => {
11+
if (group.type !== 'group') {
12+
this.add(group.name, group.description || '', group.id);
13+
}
14+
recurse(group.items);
15+
});
16+
};
17+
18+
recurse(groups);
19+
this.searchWorker.done();
1520
}
1621

1722
add(title: string, body: string, ref: string) {
1823
this.searchWorker.add(title, body, ref);
1924
}
2025

21-
done() {
22-
this.searchWorker.done();
23-
}
24-
2526
search(q: string) {
2627
return this.searchWorker.search(q);
2728
}
29+
30+
async toJS() {
31+
return this.searchWorker.toJS();
32+
}
33+
34+
load(state: any) {
35+
this.searchWorker.load(state);
36+
}
2837
}

src/services/SearchWorker.worker.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ export default class Worker {
55
add = add;
66
done = done;
77
search = search;
8+
toJS = toJS;
9+
load = load;
810
}
911

1012
export interface SearchDocument {
@@ -17,7 +19,7 @@ export interface SearchResult extends SearchDocument {
1719
score: number;
1820
}
1921

20-
const store: { [id: string]: SearchDocument } = {};
22+
let store: { [id: string]: SearchDocument } = {};
2123

2224
let resolveIndex: (v: lunr.Index) => void;
2325
const index: Promise<lunr.Index> = new Promise(resolve => {
@@ -43,6 +45,18 @@ export async function done() {
4345
resolveIndex(builder.build());
4446
}
4547

48+
export async function toJS() {
49+
return {
50+
store: store,
51+
index: (await index).toJSON(),
52+
};
53+
}
54+
55+
export async function load(state: any) {
56+
store = state.store;
57+
resolveIndex(lunr.Index.load(state.index));
58+
}
59+
4660
export async function search(q: string): Promise<SearchResult[]> {
4761
if (q.trim().length === 0) {
4862
return [];

0 commit comments

Comments
 (0)