Skip to content

Commit

Permalink
Updated to support S3 and automatic cache purge
Browse files Browse the repository at this point in the history
  • Loading branch information
emcifuntik committed Apr 7, 2023
1 parent 77d459c commit 7ce4f41
Show file tree
Hide file tree
Showing 7 changed files with 2,459 additions and 17 deletions.
132 changes: 131 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,132 @@

.DS_Store

# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage
*.lcov

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# Snowpack dependency directory (https://snowpack.dev/)
web_modules/

# TypeScript cache
*.tsbuildinfo

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional stylelint cache
.stylelintcache

# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local

# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache

# Next.js build output
.next
out

# Nuxt.js build / generate output
.nuxt
dist

# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public

# vuepress build output
.vuepress/dist

# vuepress v2.x temp and cache directory
.temp
.cache

# Docusaurus cache and generated files
.docusaurus

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

# TernJS port file
.tern-port

# Stores VSCode versions used for testing VSCode extensions
.vscode-test

# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
57 changes: 57 additions & 0 deletions cfCacheCleaner.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import Cloudflare from 'cloudflare';

const TOKEN = process.env['CF_CACHE_PURGE_TOKEN'];
const ZONE_ID = process.env['CF_CACHE_ZONE_ID'];
const PURGE_URL = process.env['CF_CACHE_PURGE_URL']; // Should be with "/" in the end

const CFClient = new Cloudflare({
token: TOKEN
});


function purgeFile(cdnPath) {
return PURGE_URL + cdnPath;
}

async function purgeDir(dirPath, cdnPath, version) {
const filesToPurge = [];
dirPath = path.resolve(dirPath);
const files = await walk(dirPath);

for (let i = 0; i < files.length; ++i) {
const file = files[i];
const stats = fs.statSync(file);
if (!stats.isDirectory()) {
const filePath = file.replace(dirPath, '').substring(1).replace(/\\/g, '/');
const key = cdnPath + '/' + filePath;
filesToPurge.push(purgeFile(key));
}
}

if (version) {
filesToPurge.push(purgeFile(cdnPath + '/update.json'));
}

return filesToPurge;
}

async function clearCache(files) {
return CFClient.zones.purgeCache(ZONE_ID, {
files
})
}

export async function purgeCache(filePath, cdnPath, version) {
if (fs.existsSync(filePath)) {
if (fs.lstatSync(filePath).isDirectory()) {
const filesToPurge = purgeDir(filePath, cdnPath, version);
return clearCache(filesToPurge);
} else {
const toPurge = [ purgeFile(filePath, cdnPath, version) ];
return clearCache(toPurge);
}
} else {
console.error('File not found');
return false;
}
}
21 changes: 18 additions & 3 deletions cli.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#!/usr/bin/env node

const path = require('path');
const { upload } = require('.');
import path from 'path';
import { upload as legacyUpload } from './index.js';
import { upload as s3upload } from './s3upload.js';
import { purgeCache } from './cfCacheCleaner.js';

async function start() {
if (process.argv.length < 4) {
Expand All @@ -13,7 +15,20 @@ async function start() {
const cdnPath = process.argv[3];
const version = process.argv.length >= 5 ? process.argv[4] : null;

upload(filePath, cdnPath, version)
// Legacy way to upload files
if (process.env['CI_UPLOAD_URL']) {
await legacyUpload(filePath, cdnPath, version);
}

// Upload to our R2 bucket
if (process.env['AWS_KEY_ID']) {
await s3upload(filePath, cdnPath, version);
}

// Automatically clear update.json cache
if (process.env['CF_CACHE_PURGE_TOKEN'] && version) {
await purgeCache(filePath, cdnPath, version);
}
}

start();
18 changes: 6 additions & 12 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
const request = require('request');
const klaw = require('klaw');
const path = require('path');
const fs = require('fs');
const crypto = require('crypto');
import request from 'request';
import klaw from 'klaw';
import path from 'path';
import fs from 'fs';
import crypto from 'crypto';

function walk(dir, options) {
return new Promise((resolve, reject) => {
Expand Down Expand Up @@ -101,7 +101,7 @@ async function uploadDir(dirPath, cdnPath, version) {
return result;
}

async function upload(filePath, cdnPath, version) {
export async function upload(filePath, cdnPath, version) {
if (fs.existsSync(filePath)) {
if (fs.lstatSync(filePath).isDirectory()) {
return uploadDir(filePath, cdnPath, version);
Expand All @@ -113,9 +113,3 @@ async function upload(filePath, cdnPath, version) {
return false;
}
}

module.exports = {
uploadDir,
uploadFile,
upload
}
Loading

0 comments on commit 7ce4f41

Please sign in to comment.