Skip to content

Commit a6d1295

Browse files
committed
add readAll option
1 parent 4095db5 commit a6d1295

File tree

5 files changed

+230
-5
lines changed

5 files changed

+230
-5
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,14 @@ module.exports = {
124124
**/
125125
format: 'object',
126126

127+
/**
128+
* if format is 'list' and readAll is true then read all contents with fetchs which divided into multiple times. (Optional)
129+
*
130+
* Type: boolean.
131+
* Default: false.
132+
**/
133+
readAll: true,
134+
127135
/**
128136
* API request query options. (Optional)
129137
*

src/__tests__/pluginOptions.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,32 @@ describe('validateOptions', () => {
105105
expect(reporter.panic.mock.calls.length).toBe(1);
106106
});
107107

108+
test('valid readAll option should be success.', () => {
109+
const options = {
110+
apiKey: 'key',
111+
serviceId: 'id',
112+
endpoint: 'endpoint',
113+
format: 'list',
114+
readAll: true,
115+
};
116+
117+
validateOptions({ reporter }, options);
118+
expect(reporter.panic.mock.calls.length).toBe(0);
119+
});
120+
121+
test('invalid readAll option should be fail.', () => {
122+
const options = {
123+
apiKey: 'key',
124+
serviceId: 'id',
125+
endpoint: 'endpoint',
126+
format: 'list',
127+
readAll: 'true',
128+
};
129+
130+
validateOptions({ reporter }, options);
131+
expect(reporter.panic.mock.calls.length).toBe(0);
132+
});
133+
108134
test('draftKey option should be success.', () => {
109135
const options = {
110136
apiKey: 'key',

src/__tests__/sourceNodes.js

Lines changed: 149 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,15 @@ const pluginOptions = {
2525
serviceId: 'id',
2626
endpoint: 'point',
2727
format: 'list',
28+
readAll: false,
2829
version: 'v1',
2930
};
3031

3132
describe('sourceNodes', () => {
3233
test('sourceNodes with list, success response', async () => {
3334
mockResponse = {
3435
statusCode: 200,
35-
body: { contents: [{ id: '1' }, { id: '2' }] },
36+
body: { contents: [{ id: '1' }, { id: '2' }], totalCount: 2 },
3637
};
3738
await sourceNodes({ actions, createNodeId, reporter }, pluginOptions);
3839
expect(actions.createNode.mock.calls.length).toBe(2);
@@ -75,4 +76,151 @@ describe('sourceNodes', () => {
7576
expect(createNodeId).not.toBeCalled();
7677
expect(reporter.panic.mock.calls.length).toBe(1);
7778
});
79+
80+
test('sourceNodes with list and readAll, success response', async () => {
81+
const options = {
82+
apiKey: 'key',
83+
serviceId: 'id',
84+
endpoint: 'point',
85+
format: 'list',
86+
readAll: true,
87+
version: 'v1',
88+
};
89+
mockResponse = {
90+
statusCode: 200,
91+
body: { contents: [{ id: '1' }, { id: '2' }], totalCount: 2 },
92+
};
93+
await sourceNodes({ actions, createNodeId, reporter }, options);
94+
expect(actions.createNode.mock.calls.length).toBe(2);
95+
expect(createNodeId.mock.calls.length).toBe(2);
96+
expect(reporter.panic).not.toBeCalled();
97+
});
98+
99+
test('sourceNodes with list and readAll, success response', async () => {
100+
const options = {
101+
apiKey: 'key',
102+
serviceId: 'id',
103+
endpoint: 'point',
104+
format: 'list',
105+
readAll: true,
106+
version: 'v1',
107+
query: {
108+
limit: 2,
109+
},
110+
};
111+
mockResponse = {
112+
statusCode: 200,
113+
body: {
114+
contents: [{ id: '1' }, { id: '2' }, { id: '3' }],
115+
totalCount: 2,
116+
},
117+
};
118+
await sourceNodes({ actions, createNodeId, reporter }, options);
119+
expect(actions.createNode.mock.calls.length).toBe(3);
120+
expect(createNodeId.mock.calls.length).toBe(3);
121+
expect(reporter.panic).not.toBeCalled();
122+
});
123+
test('sourceNodes with list, error response', async () => {
124+
const options = {
125+
apiKey: 'key',
126+
serviceId: 'id',
127+
endpoint: 'point',
128+
format: 'list',
129+
readAll: true,
130+
version: 'v1',
131+
};
132+
mockResponse = {
133+
statusCode: 400,
134+
body: { message: 'error' },
135+
};
136+
await sourceNodes({ actions, createNodeId, reporter }, options);
137+
expect(actions.createNode).not.toBeCalled();
138+
expect(createNodeId).not.toBeCalled();
139+
expect(reporter.panic.mock.calls.length).toBe(1);
140+
});
141+
142+
test('sourceNodes with list, error response', async () => {
143+
const options = {
144+
apiKey: 'key',
145+
serviceId: 'id',
146+
endpoint: 'point',
147+
format: 'list',
148+
readAll: true,
149+
version: 'v1',
150+
};
151+
mockResponse = {
152+
statusCode: 200,
153+
body: { content: { id: '1' }, totalCount: 1 },
154+
};
155+
await sourceNodes({ actions, createNodeId, reporter }, options);
156+
expect(actions.createNode).not.toBeCalled();
157+
expect(createNodeId).not.toBeCalled();
158+
expect(reporter.panic.mock.calls.length).toBe(1);
159+
});
160+
test('sourceNodes with list and readAll, success response', async () => {
161+
const options = {
162+
apiKey: 'key',
163+
serviceId: 'id',
164+
endpoint: 'point',
165+
format: 'list',
166+
readAll: true,
167+
version: 'v1',
168+
query: {
169+
limit: 0,
170+
},
171+
};
172+
mockResponse = {
173+
statusCode: 200,
174+
body: {
175+
contents: [{ id: '1' }, { id: '2' }, { id: '3' }],
176+
totalCount: 3,
177+
},
178+
};
179+
await sourceNodes({ actions, createNodeId, reporter }, options);
180+
expect(actions.createNode.mock.calls.length).toBe(3);
181+
expect(createNodeId.mock.calls.length).toBe(3);
182+
expect(reporter.panic).not.toBeCalled();
183+
});
184+
test('sourceNodes with list and readAll, success response', async () => {
185+
const options = {
186+
apiKey: 'key',
187+
serviceId: 'id',
188+
endpoint: 'point',
189+
format: 'list',
190+
readAll: true,
191+
version: 'v1',
192+
query: {
193+
limit: 20,
194+
},
195+
};
196+
mockResponse = {
197+
statusCode: 200,
198+
body: { contents: [{ id: '1' }, { id: '2' }, { id: '3' }] },
199+
};
200+
await sourceNodes({ actions, createNodeId, reporter }, options);
201+
expect(actions.createNode.mock.calls.length).toBe(3);
202+
expect(createNodeId.mock.calls.length).toBe(3);
203+
expect(reporter.panic).not.toBeCalled();
204+
});
205+
test('sourceNodes with list and readAll, success response', async () => {
206+
const options = {
207+
apiKey: 'key',
208+
serviceId: 'id',
209+
endpoint: 'point',
210+
format: 'list',
211+
readAll: true,
212+
version: 'v1',
213+
query: {
214+
limit: 1,
215+
},
216+
};
217+
mockResponse = {
218+
statusCode: 200,
219+
body: { contents: [{ id: '1' }], totalCount: 3 },
220+
};
221+
await sourceNodes({ actions, createNodeId, reporter }, options);
222+
expect(actions.createNode.mock.calls.length).toBe(3);
223+
expect(createNodeId.mock.calls.length).toBe(3);
224+
expect(reporter.panic).not.toBeCalled();
225+
});
78226
});

src/pluginOptions.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const Joi = require('@hapi/joi');
33
const defaultOptions = {
44
format: 'list',
55
version: 'v1',
6+
readAll: false,
67
fields: [],
78
query: {},
89
};
@@ -28,6 +29,7 @@ const optionsSchema = Joi.object().keys({
2829
.empty(),
2930
type: Joi.string(),
3031
format: Joi.string().pattern(/^(list|object)$/),
32+
readAll: Joi.boolean(),
3133
query: Joi.object({
3234
draftKey: Joi.string(),
3335
fields: Joi.string(),

src/sourceNodes.js

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,56 @@ const sourceNodes = async (
1313
const { createNode } = actions;
1414

1515
const pluginConfig = createPluginConfig(pluginOptions);
16-
1716
const apiUrl = `https://${pluginConfig.get(
1817
'serviceId'
1918
)}.microcms.io/api/${pluginConfig.get('version')}/${pluginConfig.get(
2019
'endpoint'
2120
)}`;
21+
// type option. default is endpoint value.
22+
const type = pluginConfig.get('type') || pluginConfig.get('endpoint');
23+
24+
if (pluginConfig.get('readAll') && pluginConfig.get('format') === 'list') {
25+
let offset = 0;
26+
while (true) {
27+
const query = { ...pluginConfig.get('query'), offset };
28+
const { statusCode, body } = await fetchData(apiUrl, {
29+
apiKey: pluginConfig.get('apiKey'),
30+
query,
31+
});
32+
if (statusCode !== 200) {
33+
reporter.panic(`microCMS API ERROR:
34+
statusCode: ${statusCode}
35+
message: ${body.message}`);
36+
return;
37+
}
38+
39+
if (!Array.isArray(body.contents)) {
40+
reporter.panic(`format set to 'list' but got ${typeof body.contents}`);
41+
return;
42+
}
43+
body.contents.forEach(content => {
44+
createContentNode({
45+
createNode,
46+
createNodeId,
47+
content: content,
48+
type: type,
49+
});
50+
});
51+
52+
const limit = query.limit || 10;
53+
54+
// totalCount not found
55+
if (!body.totalCount) {
56+
break;
57+
}
58+
59+
offset += limit;
60+
if (offset >= body.totalCount) {
61+
break;
62+
}
63+
}
64+
return;
65+
}
2266

2367
const { statusCode, body } = await fetchData(apiUrl, {
2468
apiKey: pluginConfig.get('apiKey'),
@@ -31,9 +75,6 @@ statusCode: ${statusCode}
3175
message: ${body.message}`);
3276
}
3377

34-
// type option. default is endpoint value.
35-
const type = pluginConfig.get('type') || pluginConfig.get('endpoint');
36-
3778
// list content
3879
if (
3980
isListContent({

0 commit comments

Comments
 (0)