From 239d9d7f825b501a083d3cfae0e231fe91a7b899 Mon Sep 17 00:00:00 2001 From: Luca Iaconelli Date: Tue, 6 Oct 2020 18:40:49 +0200 Subject: [PATCH] feat: pagination with recursive api --- README.md | 14 +- example/nuxt.config.js | 154 +++++++++++++- example/pages/index.css | 30 +++ example/pages/index.vue | 55 ++++- example/static/.htaccess | 121 +++++++++++ example/static/favicon.ico | Bin 0 -> 34494 bytes example/static/humans.txt | 10 + example/static/icon.png | Bin 0 -> 64948 bytes example/static/robots.txt | 2 + example/store/build-data.js | 62 ++++-- example/store/comments.js | 9 + example/store/locations.js | 9 + example/store/posts.js | 9 + lib/module.js | 396 ++++++++++++++++++++++++++++-------- lib/plugin.js | 1 - test/module.test.js | 170 +++++++++++----- 16 files changed, 884 insertions(+), 158 deletions(-) create mode 100644 example/pages/index.css create mode 100644 example/static/.htaccess create mode 100644 example/static/favicon.ico create mode 100644 example/static/humans.txt create mode 100644 example/static/icon.png create mode 100644 example/static/robots.txt delete mode 100644 lib/plugin.js diff --git a/README.md b/README.md index 45d18eb..79b99c6 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,7 @@ ___ requests: [ // Every request is passed to an `axios.create` instance { + skip: false, // skip a request endpoint: 'https://awesome-api.com/give-me-my-blazing-fast-data', // default = `axios.url` method: 'get', // default = `axios.method || 'get'` // The params of the request, you can pass a graph-ql query too, check it in the example folder @@ -102,11 +103,21 @@ ___ // Use this to map the response in a custom `key` field: 'categories', // default = `the actual index in this array of requests` // Usually, your data is always nested in one or more objects - pathToData: 'data.categories.listCategories', + pathToData: 'data.categories.listCategories.items', // Check `dot-object` to know more // In case of no-response, what value do you prefer for your empty data? emptyValue: [], // Like headers, authentication or everything is required by this request config: {}, + // New, available after with version >= 1.2 + id: -1, // useful for debugging purpose, default = `the actual index in this array of requests + 1` + // For recursive api calls with lists or nested data + pagination: { + pathBodyToPaginationParamValue: 'variables.nextToken', // [REQUIRED] + pathResponseToTheNextPaginationValue: 'data.categories.listCategories.nextToken', // useful with Graphql, default = null + step: 1, // It always start with the `pathBodyToPaginationParamValue` param if specified, so this is used to increase this numeric value + maxIterations: 15, // Max deep of iterations + lastPaginationValue: null // stop the recursion if 'pathResponseToTheNextPaginationValue' or 'pathBodyToPaginationParamValue' is this value, and is useful to stop the Iteration if the next value is matched + }, }, ], }, @@ -223,6 +234,7 @@ ___ - Nuxt [staticDir](https://nuxtjs.org/api/configuration-dir/); - Nuxt [buildModules](https://nuxtjs.org/guide/modules/#build-only-modules); - [fs-extra.outputJson](https://github.com/jprichardson/node-fs-extra/blob/master/docs/outputJson.md); +- `pathTo` data handled with [dot-notation](https://github.com/rhalff/dot-object); - [Axios.create](https://github.com/axios/axios#creating-an-instance); - [@nuxtjs/axios](https://axios.nuxtjs.org/). diff --git a/example/nuxt.config.js b/example/nuxt.config.js index f40256f..ec35449 100644 --- a/example/nuxt.config.js +++ b/example/nuxt.config.js @@ -3,7 +3,10 @@ import { resolve } from 'path'; import * as PACKAGE from '../package.json'; // GraphQL RAW Queries -import { GRAPHQL, LOCATIONS } from './graphql'; +import { + GRAPHQL, + LOCATIONS, +} from './graphql'; // Configuration const apisToFile = { @@ -11,13 +14,56 @@ const apisToFile = { baseURL: 'https://jsonplaceholder.typicode.com', }, requests: [ + // Rest API { endpoint: '/posts', field: 'posts', + body: { + params: { + '_page': 1, + '_limit': 10, + }, + }, + }, + { + endpoint: '/posts', + field: 'postsPaginated', + body: { + params: { + '_page': 1, + '_limit': 10, + }, + }, + // New settings + pagination: { + pathBodyToPaginationParamValue: 'params._page', + maxIterations: 3, + }, }, { endpoint: '/comments', field: 'comments', + body: { + params: { + '_limit': 10, + }, + }, + }, + { + endpoint: '/comments', + field: 'commentsPaginated', + body: { + params: { + '_page': 1, + '_limit': 15, + }, + }, + // New settings + pagination: { + pathBodyToPaginationParamValue: 'params._page', + step: 2, + lastPaginationValue: 7, + }, }, // GraphQL { @@ -31,7 +77,7 @@ const apisToFile = { { endpoint: 'https://kdonz3bavvbbhmocoletnw4w2q.appsync-api.eu-west-1.amazonaws.com/graphql', method: 'post', - field: 'locations', + field: 'graphqlLocations', pathToData: 'data.listLocations', config: { headers: { @@ -42,7 +88,25 @@ const apisToFile = { }, emptyValue: {}, body: LOCATIONS, + }, + { + endpoint: 'https://kdonz3bavvbbhmocoletnw4w2q.appsync-api.eu-west-1.amazonaws.com/graphql', + method: 'post', + field: 'graphqlLocationsPaginated', + pathToData: 'data.listLocations.items', + config: { + headers: { + 'Content-Type': 'application/json', + 'x-api-key': 'da2-jy2nym3ybbgubehdqhf5rjgbxq', + 'x-region': 'eu-west-1', + }, + }, + body: LOCATIONS, // New settings + pagination: { + pathResponseToTheNextPaginationValue: 'data.listLocations.nextToken', + pathBodyToPaginationParamValue: 'variables.nextToken', + }, }, ], }; @@ -51,7 +115,7 @@ const apisToFile = { export default { // Plugin options apisToFile, - // Other options + // Options modern: true, srcDir: __dirname, rootDir: resolve( @@ -68,11 +132,34 @@ export default { '../lib/module' ), ], + watch: [ + resolve( + __dirname, + '../lib/module' + ), + ], + // Meta head: { htmlAttrs: { lang: 'en', }, title: PACKAGE.name, + link: [ + { + once: true, + hid: 'favicon', + rel: 'shortcut icon', + type: 'image/x-icon', + href: '/favicon.ico', + }, + { + once: true, + hid: 'humans', + rel: 'author', + type: 'text/plain', + href: '/humans.txt', + }, + ], meta: [ { once: true, @@ -101,6 +188,67 @@ export default { '../docs' ), }, + /* + * Build + */ + build: { + loaders: { + vue: { + compilerOptions: { + preserveWhitespace: false, + whitespace: 'condense', + }, + }, + }, + /* + ** Minifier + */ + html: { + minify: { + collapseBooleanAttributes: true, + decodeEntities: true, + minifyCSS: true, + minifyJS: true, + processConditionalComments: true, + collapseInlineTagWhitespace: true, + removeOptionalTags: true, + removeAttributeQuotes: true, + removeEmptyAttributes: true, + removeRedundantAttributes: true, + trimCustomFragments: true, + useShortDoctype: true, + collapseWhitespace: true, + removeScriptTypeAttributes: true, + removeStyleLinkTypeAttributes: true, + removeComments: true, + continueOnParseError: true, + }, + }, + /* + ** Run lint on save + */ + extend( + config, + { + isDev, + isClient, + }, + ) { + + /* + ** ESLint loaded + */ + isDev && isClient && config.module.rules.push( + { + enforce: 'pre', + test: /\.(js|vue)$/, + loader: 'eslint-loader', + exclude: /(node_modules)/, + }, + ); + + }, + }, /* * Server */ diff --git a/example/pages/index.css b/example/pages/index.css new file mode 100644 index 0000000..6465800 --- /dev/null +++ b/example/pages/index.css @@ -0,0 +1,30 @@ +.page h3, +.page p { + + display: block; + width: 100%; + max-width: 500px; + margin: 0; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + +} + +.page h3 { + + margin-top: 16px; + +} + +.page em { + + display: block; + +} + +.page button { + + margin: 32px; + +} diff --git a/example/pages/index.vue b/example/pages/index.vue index c96fbff..f1b204a 100644 --- a/example/pages/index.vue +++ b/example/pages/index.vue @@ -1,8 +1,31 @@ @@ -80,3 +116,8 @@ }, }; + + diff --git a/example/static/.htaccess b/example/static/.htaccess new file mode 100644 index 0000000..16008cc --- /dev/null +++ b/example/static/.htaccess @@ -0,0 +1,121 @@ +# SP BEGIN php handler + + AddHandler fcgid-script .php .php5 .php7 .phtml + FcgidWrapper /usr/local/cpanel/cgi-sys/sp-ea-php74 .php + FcgidWrapper /usr/local/cpanel/cgi-sys/sp-ea-php74 .php5 + FcgidWrapper /usr/local/cpanel/cgi-sys/sp-ea-php74 .php7 + FcgidWrapper /usr/local/cpanel/cgi-sys/sp-ea-php74 .phtml + +# SP END php handler + +# Validation + force https + + + RewriteEngine On + + # Force HTTPS + RewriteCond %{HTTPS} !on + RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} + + # Rules to correctly serve gzip compressed CSS and JS files. + # Requires both mod_rewrite and mod_headers to be enabled. + + + # Serve brotli compressed CSS files if they exist and the client accepts gzip. + RewriteCond %{HTTP:Accept-encoding} br + RewriteCond %{REQUEST_FILENAME}\.br -s + RewriteRule ^(.*)\.css $1\.css\.br [QSA] + + # Serve gzip compressed CSS files if they exist and the client accepts gzip. + RewriteCond %{HTTP:Accept-encoding} gzip + RewriteCond %{REQUEST_FILENAME}\.gz -s + RewriteRule ^(.*)\.css $1\.css\.gz [QSA] + + # Serve brotli compressed JS files if they exist and the client accepts gzip. + RewriteCond %{HTTP:Accept-encoding} br + RewriteCond %{REQUEST_FILENAME}\.br -s + RewriteRule ^(.*)\.js$ $1\.js\.br [QSA] + + # Serve gzip compressed JS files if they exist and the client accepts gzip. + RewriteCond %{HTTP:Accept-encoding} gzip + RewriteCond %{REQUEST_FILENAME}\.gz -s + RewriteRule ^(.*)\.js$ $1\.js\.gz [QSA] + + # Serve correct content types, and prevent mod_deflate double gzip. + RewriteRule \.css\.gz$ - [T=text/css,E=no-gzip:1] + RewriteRule \.js\.gz$ - [T=text/javascript,E=no-gzip:1] + RewriteRule \.css\.br$ - [T=text/css,E=no-gzip:1] + RewriteRule \.js\.br$ - [T=text/javascript,E=no-gzip:1] + + + # Serve correct encoding type. + Header set Content-Encoding gzip + # Force proxies to cache gzipped & non-gzipped css/js files separately. + Header append Vary Accept-Encoding + + + + # Serve correct encoding type. + Header set Content-Encoding br + # Force proxies to cache gzipped & non-gzipped css/js files separately. + Header append Vary Accept-Encoding + + + + + + +# Compression BEGIN + + + AddOutputFilterByType DEFLATE application/json + AddOutputFilterByType DEFLATE application/javascript + AddOutputFilterByType DEFLATE application/rss+xml + AddOutputFilterByType DEFLATE application/vnd.ms-fontobject + AddOutputFilterByType DEFLATE application/x-font + AddOutputFilterByType DEFLATE application/x-font-opentype + AddOutputFilterByType DEFLATE application/x-font-otf + AddOutputFilterByType DEFLATE application/x-font-truetype + AddOutputFilterByType DEFLATE application/x-font-ttf + AddOutputFilterByType DEFLATE application/x-javascript + AddOutputFilterByType DEFLATE application/xhtml+xml + AddOutputFilterByType DEFLATE application/xml + AddOutputFilterByType DEFLATE font/opentype + AddOutputFilterByType DEFLATE font/otf + AddOutputFilterByType DEFLATE font/ttf + AddOutputFilterByType DEFLATE image/svg+xml + AddOutputFilterByType DEFLATE image/x-icon + AddOutputFilterByType DEFLATE text/css + AddOutputFilterByType DEFLATE text/html + AddOutputFilterByType DEFLATE text/javascript + AddOutputFilterByType DEFLATE text/plain + AddOutputFilterByType DEFLATE text/xml + + +# Compression END + +# Service worker BEGIN + + + # YEAR + + Header set Cache-Control "max-age=29030400" + + + # WEEK + + Header set Cache-Control "max-age=604800" + + + # 60 MIN + + Header set Cache-Control "max-age=3000" + + + # Service worker + + Header set Cache-Control "max-age=0, no-cache" + + + +# Service worker END diff --git a/example/static/favicon.ico b/example/static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..9e2bb999e1bff8ec0cbe1eb27000c983e992c797 GIT binary patch literal 34494 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 literal 0 HcmV?d00001 diff --git a/example/static/humans.txt b/example/static/humans.txt new file mode 100644 index 0000000..8da229d --- /dev/null +++ b/example/static/humans.txt @@ -0,0 +1,10 @@ +/* TEAM */ +Full stack developer: Luca Iaconelli +Twitter: @luxdamore +Instagram: @luxdamore +From: Faenza, Italia + +/* SITE */ +Language: Italian +Doctype: HTML5 +IDE: Visual Studio Code diff --git a/example/static/icon.png b/example/static/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..2b5660de2f2bc367f9e10b8464158c9f2427149f GIT binary patch literal 64948 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

~R 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 literal 0 HcmV?d00001 diff --git a/example/static/robots.txt b/example/static/robots.txt new file mode 100644 index 0000000..c2a49f4 --- /dev/null +++ b/example/static/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Allow: / diff --git a/example/store/build-data.js b/example/store/build-data.js index 57084c1..fc79ca9 100644 --- a/example/store/build-data.js +++ b/example/store/build-data.js @@ -11,29 +11,42 @@ export const actions = { { commit } ) { - let preloadedComments = [] - , preloadedPosts = [] + let preloadedPosts = [] + , preloadedCommentsPaginated = [] + , preloadedComments = [] + , preloadedPostsPaginated = [] , preloadedGraphQl = {} , preloadedLocations = {} + , preloadedLocationsPaginated = [] ; try { const { - comments, posts, + postsPaginated, + comments, + commentsPaginated, graphql, - locations, + graphqlLocations, + graphqlLocationsPaginated, } = await getFile(); - if( comments ) - preloadedComments = comments; if( posts ) preloadedPosts = posts; + if( postsPaginated ) + preloadedPostsPaginated = postsPaginated; + if( comments ) + preloadedComments = comments; + if( commentsPaginated ) + preloadedCommentsPaginated = commentsPaginated; + if( graphql ) preloadedGraphQl = graphql; - if( preloadedLocations ) - preloadedLocations = locations; + if( graphqlLocations ) + preloadedLocations = graphqlLocations; + if( graphqlLocationsPaginated ) + preloadedLocationsPaginated = graphqlLocationsPaginated; } catch( e ) { @@ -45,6 +58,23 @@ export const actions = { } + + commit( + 'posts/SET_ITEMS', + preloadedPosts, + { + root: true, + } + ); + + commit( + 'posts/SET_ITEMS_PAGINATED', + preloadedPostsPaginated, + { + root: true, + } + ); + commit( 'comments/SET_ITEMS', preloadedComments, @@ -54,8 +84,16 @@ export const actions = { ); commit( - 'posts/SET_ITEMS', - preloadedPosts, + 'comments/SET_ITEMS_PAGINATED', + preloadedCommentsPaginated, + { + root: true, + } + ); + + commit( + 'graphql/SET_ITEMS', + preloadedGraphQl, { root: true, } @@ -70,8 +108,8 @@ export const actions = { ); commit( - 'graphql/SET_ITEMS', - preloadedGraphQl, + 'locations/SET_ITEMS_PAGINATED', + preloadedLocationsPaginated, { root: true, } diff --git a/example/store/comments.js b/example/store/comments.js index 8815ed5..524e498 100644 --- a/example/store/comments.js +++ b/example/store/comments.js @@ -1,6 +1,7 @@ export const state = () => ( { items: [], + paginated: [], } ); @@ -13,4 +14,12 @@ export const mutations = { state.items = items; }, + SET_ITEMS_PAGINATED( + state, + items, + ) { + + state.paginated = items; + + }, }; diff --git a/example/store/locations.js b/example/store/locations.js index 375b52e..2759c75 100644 --- a/example/store/locations.js +++ b/example/store/locations.js @@ -1,6 +1,7 @@ export const state = () => ( { data: {}, + paginated: [], } ); @@ -13,4 +14,12 @@ export const mutations = { state.data = value; }, + SET_ITEMS_PAGINATED( + state, + items, + ) { + + state.paginated = items; + + }, }; diff --git a/example/store/posts.js b/example/store/posts.js index 8815ed5..524e498 100644 --- a/example/store/posts.js +++ b/example/store/posts.js @@ -1,6 +1,7 @@ export const state = () => ( { items: [], + paginated: [], } ); @@ -13,4 +14,12 @@ export const mutations = { state.items = items; }, + SET_ITEMS_PAGINATED( + state, + items, + ) { + + state.paginated = items; + + }, }; diff --git a/lib/module.js b/lib/module.js index 141f323..f420354 100644 --- a/lib/module.js +++ b/lib/module.js @@ -3,6 +3,7 @@ import { resolve } from 'path'; // External import { create, all } from 'axios'; +import { str, pick } from 'dot-object'; import { outputJson } from 'fs-extra'; // Log @@ -27,24 +28,58 @@ const moduleName = 'apis-to-file' dir: null, requests: [], axios: {}, + // New + genericErrorMessage: 'Generic error', + pagination: null, } - , checkIfUndefinedAndReturnDifferentData = ( - check, - value, - ) => { +; + +// Find the data +function findValue( + pathway, + data = {}, + emptyValue = [], +) { + + if( ! pathway ) { - return typeof check === 'undefined' - ? value - : check - ; + if( typeof data !== 'undefined' && data !== null ) + return data; + + return emptyValue; } -; + + try { + + const value = pick( + pathway, + data + ); + + if( typeof value !== 'undefined' && value !== null ) + return value; + + } catch( e ) { + + logger.error( + '\x1B[31m%s\x1B[0m', + moduleName, + '[dot-object] error', + e + ); + + } + + return emptyValue; + +} export default async function( moduleOptions, ) { + // Default options const options = { ... defaultConfig, hideGenericMessagesInConsole: ! this.options.dev, @@ -54,59 +89,101 @@ export default async function( ... this.options.apisToFile || {}, }; + // Check for requests if( ! options.requests || ! options.requests.length ) { - ! options.hideErrorsInConsole && logger.info( + logger.info( '\x1B[32m%s\x1B[0m', moduleName, - 'skipping, no requests found in the configuration', + 'skipping, no requests found in the configuration object', ); return; } - // Promise generator + // Promises generator const axiosWithConfig = create( options.axios, ) - , requests = options.requests.filter( + // Requests filtering + , validRequests = options.requests.filter( obj => ! obj.skip, ) - , promises = [] + , { + requestsInParallel, + requestsWithPagination, + } = validRequests.reduce( + ( + accumulator, + item, + index + ) => { + + if( ! item.id ) + item.id = index + 1; + + if( item.pagination && item.pagination.pathBodyToPaginationParamValue ) { + + accumulator.requestsWithPagination.push( + item + ); + + } else { + + accumulator.requestsInParallel.push( + item + ); + + } + + return accumulator; + + }, + { + requestsInParallel: [], + requestsWithPagination: [], + } + ) + , errors = [] ; - for( let index = 0; index < requests.length; index ++ ) { - - const request = requests[ index ] - , { - method = options.axios.method || 'get', - endpoint = options.axios.url, - body = {}, - config = {}, - } = request - ; - - promises.push( - axiosWithConfig[ method ]( - endpoint, - body, - config, - ), - ); + let fileContent = {}; - } + // Parallel requests + if( requestsInParallel.length ) { - let fileContent = null; + // Handle results + const promises = []; - try { + // Parallel promises generation + for( let index = 0; index < requestsInParallel.length; index ++ ) { + const request = requestsInParallel[ index ] + , { + method = options.axios.method || 'get', + endpoint = options.axios.url, + body = {}, + config = {}, + } = request + ; + + promises.push( + axiosWithConfig[ method ]( + endpoint, + body, + config, + ), + ); + + } + + // API const responses = await all( - promises, - ) - , errors = [] - ; + promises, + ); + // Start the file creation fileContent = responses.reduce( ( accumulator, @@ -114,48 +191,31 @@ export default async function( index, ) => { + const { + id, + field: key = index, + emptyValue, + pathToData, + } = requestsInParallel[ index ] + , value = findValue( + pathToData, + data, + emptyValue + ) + ; + + // Keep errors for later data.error && errors.push( - data.error + `[${ id }] ${ data.error }` ); data.errors && data.errors.length && errors.push( ... data.errors.map( - error => error.message || 'Generic error', + error => `[${ id }] ${ error.message }` ), ); - const { - field: key = index, - emptyValue = [], - pathToData, - } = requests[ index ] - , value = ( - pathToData - ? pathToData - .split( - '.', - ) - .reduce( - ( - acc, - key, - ) => ( - typeof acc !== 'undefined' && acc !== null - ? checkIfUndefinedAndReturnDifferentData( - acc[ key ], - emptyValue - ) - : acc || {} - ), - data || {}, - ) - : checkIfUndefinedAndReturnDifferentData( - data, - emptyValue - ) - ) - ; - + // Return data return { ... accumulator, [ key ]: value, @@ -165,38 +225,201 @@ export default async function( {}, ); - // Console - errors.length && ! options.hideErrorsInConsole && logger.error( - '\x1B[31m%s\x1B[0m', + } + + // Recursive requests + if( requestsWithPagination.length ) { + + // Pagination + for( let index = 0; index < requestsWithPagination.length; index ++ ) { + + const request = requestsWithPagination[ index ] + , { + method = options.axios.method || 'get', + endpoint = options.axios.url, + body = {}, + config = {}, + // Paths + id, + field: key = index, + emptyValue = [], + pathToData, + // Pagination + pagination: { + pathBodyToPaginationParamValue, + pathResponseToTheNextPaginationValue = null, + step = 1, + maxIterations = 15, + lastPaginationValue = null, + }, + } = request + // Recursive data + , recursion = async() => { + + // Value and limit control + let value = emptyValue + , count = 1 + // Params + , params = body + ; + + async function next( + token + ) { + + if( token ) { + + params = str( + pathBodyToPaginationParamValue, + token, + params + ); + + } + + const { data = {} } = await axiosWithConfig[ method ]( + endpoint, + params, + config, + ) + , newValue = findValue( + pathToData, + data, + emptyValue, + ) + ; + + if( value && newValue ) { + + if( + Array.isArray( + value + ) + ) { + + value.push( + ... newValue + ); + + } else { + + value = { + ... value, + ... newValue, + }; + + } + + } + + // Keep errors for later + data.error && errors.push( + `[${ id }] ${ data.error }` + ); + + data.errors && data.errors.length && errors.push( + ... data.errors.map( + error => `[${ id }] ${ error.message }` + ), + ); + + const nextToken = ( + pathResponseToTheNextPaginationValue + ? findValue( + pathResponseToTheNextPaginationValue, + data, + null + ) + : ( + parseInt( + findValue( + pathBodyToPaginationParamValue, + params, + step + ), + 10 + ) + step + ) + ) + ; + + if( ! nextToken || nextToken === lastPaginationValue || maxIterations <= count ) + return value; + + count ++; + + await next( + nextToken + ); + + } + + await next(); + + return value; + + } + // Do it + , data = await recursion() + ; + + fileContent[ key ] = data; + + } + + } + + // Console + if( ! options.hideGenericMessagesInConsole ) { + + logger.info( + '\x1B[32m%s\x1B[0m', moduleName, - 'error during request', - errors + 'total number of Parallel APIs requests', + requestsInParallel.length, ); - ! options.hideGenericMessagesInConsole && logger.info( + logger.info( '\x1B[32m%s\x1B[0m', moduleName, - 'total number of APIs calls', - responses.length, + 'total number of Parallel APIs requests', + requestsWithPagination.length, ); - } catch( e ) { + logger.info( + '\x1B[32m%s\x1B[0m', + moduleName, + 'total number of APIs requests', + validRequests.length, + ); - ! options.hideErrorsInConsole && logger.error( + } + + if( ! options.hideErrorsInConsole && errors.length ) { + + logger.error( '\x1B[31m%s\x1B[0m', moduleName, - 'there was a problem calling some APIs', - e, + 'total number of errors', + errors.length + ); + + logger.error( + '\x1B[31m%s\x1B[0m', + moduleName, + 'recorded errors', + errors ); } - // File generator + // File data const completeFilePath = resolve( __dirname, `${ options.file.startFromStaticDir ? this.options.dir.static : this.options.srcDir }/${ options.file.path || '' }/${ options.dir || '' }/${ options.file.name || moduleName }.${ options.file.ext || 'json' }`, ); + // File generation try { await outputJson( @@ -225,6 +448,7 @@ export default async function( } +// Exports const meta = PACKAGE; export { meta }; diff --git a/lib/plugin.js b/lib/plugin.js deleted file mode 100644 index 2d1ec23..0000000 --- a/lib/plugin.js +++ /dev/null @@ -1 +0,0 @@ -export default () => {}; diff --git a/test/module.test.js b/test/module.test.js index f226193..ea756d1 100644 --- a/test/module.test.js +++ b/test/module.test.js @@ -62,51 +62,66 @@ describe( } ); + // Utils + const getElement = async( + selector, + value + ) => { + + const html = await get( + BASE_URL + ) + , { window } = new JSDOM( + html + ) + , element = window.document.querySelector( + selector + ) + , number = element.querySelector( + '.number' + ) + , numberValue = number.textContent + ; + + expect( + element + ).toBeDefined(); + + expect( + number + ).toBeDefined(); + + expect( + numberValue + ).toBeDefined(); + + expect( + parseInt( + numberValue + ) + ).toEqual( + value + ); + + }; + + // Rest API describe( - 'data', + 'rest-api', () => { - const getElement = async( - selector, - value - ) => { - - const html = await get( - BASE_URL - ) - , { window } = new JSDOM( - html - ) - , element = window.document.querySelector( - selector - ) - , number = element.querySelector( - '.number' - ) - , numberValue = number.textContent - ; - - expect( - element - ).toBeDefined(); - - expect( - number - ).toBeDefined(); - - expect( - numberValue - ).toBeDefined(); + // Posts and comments + test( + 'posts', + async() => { - expect( - parseInt( - numberValue - ) - ).toEqual( - value - ); + await getElement( + '.posts', + 10, + ); - }; + } + ); test( 'comments', @@ -114,26 +129,54 @@ describe( await getElement( '.comments', - 500, + 10, ); } ); - test( - 'posts', - async() => { + // paginated + describe( + 'paginated', + () => { - await getElement( - '.posts', - 100, + test( + 'posts', + async() => { + + await getElement( + '.posts-paginated', + 30, + ); + + } + ); + + test( + 'comments', + async() => { + + await getElement( + '.comments-paginated', + 45, + ); + + } ); } ); + } + ); + + // GraphQL + describe( + 'graphql', + () => { + test( - 'graphql', + 'render', async() => { const html = await get( @@ -149,6 +192,37 @@ describe( } ); + test( + 'locations', + async() => { + + await getElement( + '.locations', + 11, + ); + + } + ); + + describe( + 'paginated', + () => { + + test( + 'locations', + async() => { + + await getElement( + '.locations-paginated', + 20, + ); + + } + ); + + } + ); + } );