forked from algolia/gatsby-plugin-algolia
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgatsby-node.js
134 lines (118 loc) · 3.48 KB
/
gatsby-node.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
const algoliasearch = require('algoliasearch');
const chunk = require('lodash.chunk');
const report = require('gatsby-cli/lib/reporter');
/**
* give back the same thing as this was called with.
*
* @param {any} obj what to keep the same
*/
const identity = obj => obj;
exports.onPostBuild = async function(
{ graphql },
{ appId, apiKey, queries, indexName: mainIndexName, chunkSize = 1000 }
) {
const activity = report.activityTimer(`index to Algolia`);
activity.start();
const client = algoliasearch(appId, apiKey);
setStatus(activity, `${queries.length} queries to index`);
const jobs = queries.map(async function doQuery(
{ indexName = mainIndexName, query, transformer = identity, settings },
i
) {
if (!query) {
report.panic(
`failed to index to Algolia. You did not give "query" to this query`
);
}
const index = client.initIndex(indexName);
const mainIndexExists = await indexExists(index);
const tmpIndex = client.initIndex(`${indexName}_tmp`);
const indexToUse = mainIndexExists ? tmpIndex : index;
if (mainIndexExists) {
setStatus(activity, `query ${i}: copying existing index`);
await scopedCopyIndex(client, index, tmpIndex);
}
setStatus(activity, `query ${i}: executing query`);
const result = await graphql(query);
if (result.errors) {
report.panic(`failed to index to Algolia`, result.errors);
}
const objects = await transformer(result);
const chunks = chunk(objects, chunkSize);
setStatus(activity, `query ${i}: splitting in ${chunks.length} jobs`);
const chunkJobs = chunks.map(async function(chunked) {
const { taskID } = await indexToUse.addObjects(chunked);
return indexToUse.waitTask(taskID);
});
await Promise.all(chunkJobs);
if (settings) {
const { taskID } = await indexToUse.setSettings(settings);
await indexToUse.waitTask(taskID);
}
if (mainIndexExists) {
setStatus(activity, `query ${i}: moving copied index to main index`);
return moveIndex(client, tmpIndex, index);
}
});
try {
await Promise.all(jobs);
} catch (err) {
report.panic(`failed to index to Algolia`, err);
}
activity.end();
};
/**
* Copy the settings, synonyms, and rules of the source index to the target index
* @param client
* @param sourceIndex
* @param targetIndex
* @return {Promise}
*/
async function scopedCopyIndex(client, sourceIndex, targetIndex) {
const { taskID } = await client.copyIndex(
sourceIndex.indexName,
targetIndex.indexName,
['settings', 'synonyms', 'rules']
);
return targetIndex.waitTask(taskID);
}
/**
* moves the source index to the target index
* @param client
* @param sourceIndex
* @param targetIndex
* @return {Promise}
*/
async function moveIndex(client, sourceIndex, targetIndex) {
const { taskID } = await client.moveIndex(
sourceIndex.indexName,
targetIndex.indexName
);
return targetIndex.waitTask(taskID);
}
/**
* Does an Algolia index exist already
*
* @param index
*/
async function indexExists(index) {
try {
const { nbHits } = await index.search();
return nbHits > 0;
} catch (e) {
return false;
}
}
/**
* Hotfix the Gatsby reporter to allow setting status (not supported everywhere)
*
* @param {Object} activity reporter
* @param {String} status status to report
*/
function setStatus(activity, status) {
if (activity && activity.setStatus) {
activity.setStatus(status);
} else {
console.log('Algolia:', status);
}
}