diff --git a/.gitignore b/.gitignore index e3aaaf1..c3215c2 100644 --- a/.gitignore +++ b/.gitignore @@ -93,3 +93,5 @@ dist /static/tailwind.css /_cache +/test/_temp* +/temp diff --git a/helpers/incremental/caching.js b/helpers/incremental/caching.js index f9e8e07..36073a4 100644 --- a/helpers/incremental/caching.js +++ b/helpers/incremental/caching.js @@ -25,11 +25,20 @@ export async function getNetlifyConfig () { return TOML.parse( netlifyTomlContents ) } +export async function readFromJSON ( path ) { + // Read back the JSON we just wrote to ensure it exists + const savedJSON = await fs.readFile( path , 'utf-8' ) + + // console.log('savedListJSON', savedListJSON) + + return JSON.parse( savedJSON ) +} + export class IncrementalCache { constructor( options = {} ) { - this.cachePath = options.cachePath || CACHE_PATH + this.cachePath = options.cachePath || path.join( CACHE_PATH, 'prod_publish' ) this.publishDirectoryName = options.publishDirectoryName || null this.publishDirectoryPath = options.publishDirectoryPath || null @@ -44,6 +53,13 @@ export class IncrementalCache { return await fs.pathExists( homePageFile ) } + async hasPublishFolder () { + const homePageFile = `${ this.publishDirectoryPath }/index.html` + + // https://github.com/jprichardson/node-fs-extra/blob/master/docs/pathExists.md + return await fs.pathExists( homePageFile ) + } + async getPublishDirectoryName () { const netlifyConfig = await getNetlifyConfig() @@ -51,8 +67,6 @@ export class IncrementalCache { } async getPublishDirectoryPath () { - // const publishDirectoryPath = await this.getPublishDirectoryName() - return path.resolve( rootDir, this.publishDirectoryName ) } @@ -70,11 +84,77 @@ export class IncrementalCache { } async emptyPublishDirectory () { - // const publishDirectoryPath = await this.getPublishDirectoryName() - return await fs.emptyDir( this.publishDirectoryPath, 'utf-8' ) } + async restoreCachedEndpoints ( options = {} ) { + + const { + endpoints, + shouldOverwrite = false + } = options + + if ( !shouldOverwrite && (await this.hasPublishFolder()) === true ) { + throw new Error('Publish folder already exists!') + } + + // Copy concurrently for speed + await Promise.all( endpoints.map( endpoint => { + const cachedPagePath = path.join( this.cachePath, endpoint.route ) + const publishPagePath = path.join( this.publishDirectoryPath, endpoint.route ) + + return fs.copy( cachedPagePath, publishPagePath ) + })) + } + + async restoreCachedNuxtFiles ( options = {} ) { + + const cachedNuxtAssetsPath = path.resolve( this.cachePath, '_nuxt') + const publishNuxtAssetsPath = path.resolve( this.publishDirectoryPath, '_nuxt') + + await fs.copy( cachedNuxtAssetsPath, publishNuxtAssetsPath ) + + const nuxtEndpointsPath = path.resolve( rootDir, 'static/nuxt-endpoints.json') + const nuxtEndpoints = await readFromJSON( nuxtEndpointsPath ) + + await this.restoreCachedEndpoints({ + endpoints: nuxtEndpoints, + ...options + }) + } + + async syncInCachedPublishFolder () { + + if ( (await this.hasPublishFolder()) !== true ) { + throw new Error('Publish folder not found') + } + + // const publishDirectoryPath = await this.getPublishDirectoryPath() + + // console.log('publishDirectoryPath', publishDirectoryPath) + + // Make sure cache folder exists + // await fs.ensureDir( this.cachePath ) + + // await fs.copy( this.publishDirectoryPath, this.cachePath ) + + } + + async findMissingEndpoints () { + const sitemapEndpointsPath = path.resolve( rootDir, 'static/sitemap-endpoints.json') + const sitemapEndpoints = await readFromJSON( sitemapEndpointsPath ) + + const missingEndpoints = [] + + for ( const endpoint of sitemapEndpoints ) { + const publishPageFile = `${ this.publishDirectoryPath }/index.html` + const exists = await fs.pathExists( publishPageFile ) + + if (!exists) missingEndpoints.push( endpoint ) + } + + return missingEndpoints + } async init () { diff --git a/helpers/incremental/caching.test.js b/helpers/incremental/caching.test.js index 4df4eb6..d11b944 100644 --- a/helpers/incremental/caching.test.js +++ b/helpers/incremental/caching.test.js @@ -3,25 +3,32 @@ import path from 'path' import test from 'ava' import { isObject, isString } from '../type-checks.js' +import { rootDir } from '../environment.js' import { getNetlifyConfig, - CACHE_PATH, + readFromJSON, + // CACHE_PATH, IncrementalCache } from './caching.js' // Keeps tests from messing up production publish folder and files -const testingCachePath = path.join( CACHE_PATH, 'test' ) +const testingCachePath = path.join( 'temp', '_test_cache' ) +const testingPublishPath = path.join( 'temp', '_test_publish' ) test.before(async t => { + // Clone publish + // testingPublishPath + t.context.cache = new IncrementalCache({ - cachePath: testingCachePath + cachePath: testingCachePath, + publishDirectoryPath: testingPublishPath }) - // Set up cache + // Let cache pull in environment context await t.context.cache.init() }) @@ -41,9 +48,18 @@ test.serial('Can read netlify.toml', async (t) => { test.serial('Can cache publish folder', async (t) => { - const { - cache - } = t.context + // Special caching instance that pulls from live publish directory + // but stores to testing cache directory + // so that we can copy the live data into an empty testing directory + // and not the live directory. + // This means we won't wipe out the build we just did with cached data + const cache = new IncrementalCache({ + cachePath: testingCachePath + }) + + // Let cache pull in environment context + await cache.init() + // So that we don't overwrite the cached files // we check if a cached file already exists @@ -80,11 +96,10 @@ test.serial('Can restore publish folder from cache', async (t) => { cache } = t.context - if ( (await cache.hasCachedPublishFolder( testingCachePath )) === false ) { - t.log(`Could not find publish folder at ${ testingCachePath }`) - t.fail() - return - } + // Set up nuxt endpoints + // so that the publish directory looks like it + // would during a build + await cache.restoreCachedNuxtFiles() // await cache.emptyPublishDirectory() @@ -94,12 +109,14 @@ test.serial('Can restore publish folder from cache', async (t) => { // // If there's no files there already // // then we can write to the directory with - await cache.cachePublishFolder() - + // await cache.cachePublishFolder() + // List missing endpoints + // so we can compare + const missingEndpoints = await cache.findMissingEndpoints() // t.log(`Cached publish folder at ${ testingCachePath }`) - t.pass() + t.is( missingEndpoints.length, 0 ) })