From e06d8e30991e23f9301fdef1e4684669593dcf96 Mon Sep 17 00:00:00 2001 From: Ryan Block Date: Mon, 29 Apr 2024 10:45:56 -0700 Subject: [PATCH 1/4] Update deps, upgrade to ESLint v9 --- .eslintignore | 2 -- eslint.config.js | 11 +++++++++++ package.json | 10 +++++----- 3 files changed, 16 insertions(+), 7 deletions(-) delete mode 100644 .eslintignore create mode 100644 eslint.config.js diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index ccd4fd0..0000000 --- a/.eslintignore +++ /dev/null @@ -1,2 +0,0 @@ -.nyc_output/ -dist/index.js diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..b97fe6e --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,11 @@ +const arc = require('@architect/eslint-config') + +module.exports = [ + ...arc, + { + ignores: [ + '.nyc_output/', + 'dist/index.js', + ], + }, +] diff --git a/package.json b/package.json index a2b99d2..ffa928b 100644 --- a/package.json +++ b/package.json @@ -25,16 +25,16 @@ "src/*" ], "dependencies": { - "@aws-lite/client": "~0.20.0", - "@aws-lite/s3": "^0.1.20" + "@aws-lite/client": "~0.21.1", + "@aws-lite/s3": "^0.1.21" }, "devDependencies": { - "@architect/eslint-config": "~2.1.2", + "@architect/eslint-config": "~3.0.0", "@architect/req-res-fixtures": "git+https://github.com/architect/req-res-fixtures.git", "cross-env": "7.0.3", - "eslint": "~8.57.0", + "eslint": "~9.1.1", "mime-types": "~2.1.35", - "mock-tmp": "~0.0.3", + "mock-tmp": "~0.0.4", "nyc": "~15.1.0", "proxyquire": "~2.1.3", "tap-arc": "~1.2.2", From 6da07e41e2e5939b7e03fc4186c2897a5d073b63 Mon Sep 17 00:00:00 2001 From: Ryan Block Date: Mon, 29 Apr 2024 10:46:39 -0700 Subject: [PATCH 2/4] Update PR template --- .github/pull_request_template.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index f10341d..57d2a41 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -4,7 +4,7 @@ To maintain a high standard of quality in our releases, before merging every pull request we ask that you've completed the following: -- [ ] Forked the repo and created your branch from `master` +- [ ] Forked the repo and created your branch from `main` - [ ] Made sure tests pass (run `npm it` from the repo root) - [ ] Expanded test coverage related to your changes: - [ ] Added and/or updated unit tests (if appropriate) From cc2953b2068c48e24f04b3246066424a370d63bc Mon Sep 17 00:00:00 2001 From: Ryan Block Date: Mon, 29 Apr 2024 10:48:25 -0700 Subject: [PATCH 3/4] Lint --- src/format/compress.js | 4 ++-- src/lib/error.js | 6 +++--- src/lib/get-s3.js | 2 -- src/read/_pretty.js | 6 +++--- src/read/_s3.js | 6 +++--- test/unit/src/_methods-test.js | 1 - test/unit/src/format/response-test.js | 6 +++--- test/unit/src/format/templatize-test.js | 6 +++--- test/unit/src/index-test.js | 14 ++++++------- test/unit/src/read/_local-test.js | 23 +++++++++++----------- test/unit/src/read/_pretty-test.js | 26 ++++++++++++------------- test/unit/src/read/_s3-test.js | 6 +++--- 12 files changed, 51 insertions(+), 55 deletions(-) diff --git a/src/format/compress.js b/src/format/compress.js index e14297f..0f4736a 100644 --- a/src/format/compress.js +++ b/src/format/compress.js @@ -12,7 +12,7 @@ function compressor (direction, type, data) { let exec = { gzip: compress ? gzipSync : gunzipSync, br: compress ? brotliCompressSync : brotliDecompressSync, - deflate: compress ? deflateSync : inflateSync + deflate: compress ? deflateSync : inflateSync, } if (!exec[type]) throw ReferenceError('Invalid compression type specified, must be gzip, br, or deflate') @@ -21,5 +21,5 @@ function compressor (direction, type, data) { module.exports = { compress: compressor.bind({}, 'compress'), - decompress: compressor.bind({}, 'decompress') + decompress: compressor.bind({}, 'decompress'), } diff --git a/src/lib/error.js b/src/lib/error.js index 44cf800..c9dab0a 100644 --- a/src/lib/error.js +++ b/src/lib/error.js @@ -3,7 +3,7 @@ */ module.exports = { httpError, - proxyConfig: proxyConfig() + proxyConfig: proxyConfig(), } function proxyConfig () { @@ -27,7 +27,7 @@ function httpError ({ statusCode = 502, title = 'Unknown error', message = '' }) statusCode, headers: { 'content-type': 'text/html; charset=utf8;', - 'cache-control': 'no-cache, no-store, must-revalidate, max-age=0, s-maxage=0' + 'cache-control': 'no-cache, no-store, must-revalidate, max-age=0, s-maxage=0', }, body: ` @@ -96,6 +96,6 @@ function httpError ({ statusCode = 502, title = 'Unknown error', message = '' }) -` +`, } } diff --git a/src/lib/get-s3.js b/src/lib/get-s3.js index cc10a11..c0394e5 100644 --- a/src/lib/get-s3.js +++ b/src/lib/get-s3.js @@ -2,11 +2,9 @@ let _s3 module.exports = async function getS3 () { if (_s3) return _s3 - // eslint-disable-next-line let awsLite = require('@aws-lite/client') let { s3 } = await awsLite({ region: process.env.AWS_REGION || 'us-west-2', - // eslint-disable-next-line plugins: [ import('@aws-lite/s3') ], }) _s3 = s3.GetObject diff --git a/src/read/_pretty.js b/src/read/_pretty.js index ce7f4a2..cb776f2 100644 --- a/src/read/_pretty.js +++ b/src/read/_pretty.js @@ -41,7 +41,7 @@ module.exports = async function pretty (params) { throw err } else return { - Body: readFileSync(file) + Body: readFileSync(file), } } @@ -86,10 +86,10 @@ module.exports = async function pretty (params) { return { headers: { 'content-type': 'text/html; charset=utf8;', - 'cache-control': 'no-cache, no-store, must-revalidate, max-age=0, s-maxage=0' + 'cache-control': 'no-cache, no-store, must-revalidate, max-age=0, s-maxage=0', }, statusCode: 404, - body + body, } } else { diff --git a/src/read/_s3.js b/src/read/_s3.js index e552ae0..e27971c 100644 --- a/src/read/_s3.js +++ b/src/read/_s3.js @@ -57,8 +57,8 @@ module.exports = async function readS3 (params) { statusCode: 302, headers: { location, - 'cache-control': 'no-cache, no-store, must-revalidate, max-age=0, s-maxage=0' - } + 'cache-control': 'no-cache, no-store, must-revalidate, max-age=0, s-maxage=0', + }, } } @@ -87,7 +87,7 @@ module.exports = async function readS3 (params) { headers.etag = IfNoneMatch response = { statusCode: 304, - headers + headers, } } else { diff --git a/test/unit/src/_methods-test.js b/test/unit/src/_methods-test.js index 569c6e4..b68d81a 100644 --- a/test/unit/src/_methods-test.js +++ b/test/unit/src/_methods-test.js @@ -6,7 +6,6 @@ let asap function setup () { delete require.cache[require.resolve(mod)] delete require.cache[require.resolve(join(mod, 'src', 'read'))] - // eslint-disable-next-line asap = require(mod) } diff --git a/test/unit/src/format/response-test.js b/test/unit/src/format/response-test.js index 4dada20..de8d2d8 100644 --- a/test/unit/src/format/response-test.js +++ b/test/unit/src/format/response-test.js @@ -17,16 +17,16 @@ function basicResponse () { 'cache-control': 'max-age=86400', etag: ETag, }, - body + body, }, // S3 result object result: { ContentType, ETag, - Body: body + Body: body, }, Key: 'this-is-fine.gif', - config: { spa: true } + config: { spa: true }, } } let htmlKey = 'index.html' diff --git a/test/unit/src/format/templatize-test.js b/test/unit/src/format/templatize-test.js index a1acb44..e7185db 100644 --- a/test/unit/src/format/templatize-test.js +++ b/test/unit/src/format/templatize-test.js @@ -16,7 +16,7 @@ test('Templatizer ignores binary responses', t => { let response = { body: buf(content) } let result = filePath({ isBinary: true, - response + response, }) t.equal(content, result.body.toString(), 'Templatizer exited early') }) @@ -43,7 +43,7 @@ test('Templatizer replaces fingerprinted assets', t => { t.plan(6) let fingerprinted = 'this-is-fine-abc123.gif' let assets = { - 'this-is-fine.gif': fingerprinted + 'this-is-fine.gif': fingerprinted, } let response = { body: buf('here is an asset: ${STATIC(\'this-is-fine.gif\')}') } let result = filePath({ response, assets }).body.toString() @@ -66,7 +66,7 @@ test('Templatizer replaces fingerprinted assets', t => { test('Templatizer does not replace fingerprinted assets locally', t => { t.plan(6) let assets = { - 'this-is-fine.gif': 'this-is-fine-abc123.gif' + 'this-is-fine.gif': 'this-is-fine-abc123.gif', } let isLocal = true let response = { body: buf('here is an asset: ${STATIC(\'this-is-fine.gif\')}') } diff --git a/test/unit/src/index-test.js b/test/unit/src/index-test.js index 45c00fe..9967486 100644 --- a/test/unit/src/index-test.js +++ b/test/unit/src/index-test.js @@ -5,7 +5,7 @@ let reader = params => params let readStub = () => reader let sut = join(process.cwd()) let asap = proxyquire(sut, { - './read': readStub + './read': readStub, }) let { http } = require('@architect/req-res-fixtures') let reqs = http.req @@ -17,7 +17,7 @@ let productionBucket = 'my-production-bucket' let basicBucketConfig = { bucket: { staging: stagingBucket, - } + }, } test('Set up env', t => { @@ -42,8 +42,8 @@ test('Config: bucket', async t => { // Test ARC_STATIC_BUCKET vs config proxy = asap({ bucket: { - production: stagingBucket - } + production: stagingBucket, + }, }) result = await proxy(req) t.equal(result.Bucket, productionBucket, 'ARC_STATIC_BUCKET overrides config') @@ -52,8 +52,8 @@ test('Config: bucket', async t => { // Test config.bucket proxy = asap({ bucket: { - staging: stagingBucket - } + staging: stagingBucket, + }, }) result = await proxy(req) t.equal(result.Bucket, stagingBucket, 'config.bucket sets bucket') @@ -150,7 +150,7 @@ test('rootPath param', async t => { let params = proxyReq params.requestContext = { - path: '/staging/nature/hiking' + path: '/staging/nature/hiking', } result = await proxy(proxyReq) t.equal(result.rootPath, 'staging', 'rootPath param correctly set: staging') diff --git a/test/unit/src/read/_local-test.js b/test/unit/src/read/_local-test.js index 9ed6d25..c219d56 100644 --- a/test/unit/src/read/_local-test.js +++ b/test/unit/src/read/_local-test.js @@ -19,9 +19,8 @@ let setSandboxPath = tmp => sandboxPath = join(tmp, public) // static.json let staticStub = { 'images/this-is-fine.gif': 'images/this-is-fine-a1c3e5.gif', - 'publicfile.md': 'publicfile-b2d4f6.md' + 'publicfile.md': 'publicfile-b2d4f6.md', } -// eslint-disable-next-line let prettyStub = async () => 'pretty' // Generates proxy read requests @@ -30,7 +29,7 @@ function read (params = {}) { return { Key: Key || 'images/this-is-fine.gif', IfNoneMatch: IfNoneMatch || 'abc123', - config: config || { spa: true, sandboxPath } + config: config || { spa: true, sandboxPath }, } } @@ -52,10 +51,10 @@ let imgETag = hash(imgContents) let binary = [ 137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 1, 0, 0, 0, 1, - 8, 4, 0, 0, 0, 181, 28, 12, 2, 0, 0, 0, + 8, 4, 0, 0, 0, 181, 28, 12, 2, 0, 0, 0, 11, 73, 68, 65, 84, 120, 218, 99, 100, 96, 0, 0, - 0, 6, 0, 2, 48, 129, 208, 47, 0, 0, 0, 0, - 73, 69, 78, 68, 174, 66, 96, 130 + 0, 6, 0, 2, 48, 129, 208, 47, 0, 0, 0, 0, + 73, 69, 78, 68, 174, 66, 96, 130, ] let mdName = 'some-file.md' @@ -66,7 +65,7 @@ let defaultCacheControl = 'public, max-age=0, must-revalidate' // Ok, we're good to go let sut = join(process.cwd(), 'src', 'read', '_local') let readLocal = proxyquire(sut, { - './_pretty': prettyStub + './_pretty': prettyStub, }) test('Set up env', t => { @@ -77,7 +76,7 @@ test('Set up env', t => { test('Local proxy reader returns formatted response from text payload (200)', async t => { t.plan(6) let tmp = mockTmp({ - [join(public, imgName)]: imgContents + [join(public, imgName)]: imgContents, }) setSandboxPath(tmp) let result = await readLocal(read()) @@ -93,7 +92,7 @@ test('Local proxy reader returns formatted response from text payload (200)', as test('Local proxy reader returns formatted response from binary payload (200)', async t => { t.plan(2) let tmp = mockTmp({ - [join(public, imgName)]: Buffer.from(binary) + [join(public, imgName)]: Buffer.from(binary), }) setSandboxPath(tmp) let result = await readLocal(read()) @@ -109,7 +108,7 @@ test('Local proxy reader unsets ARC_STATIC_PREFIX and returns formatted response t.ok(process.env.ARC_STATIC_PREFIX, 'ARC_STATIC_PREFIX set') let tmp = mockTmp({ - [join(public, imgName)]: imgContents + [join(public, imgName)]: imgContents, }) setSandboxPath(tmp) let params = read({ Key: `${process.env.ARC_STATIC_PREFIX}/${imgName}` }) @@ -127,7 +126,7 @@ test('Local proxy reader unsets ARC_STATIC_PREFIX and returns formatted response test('Local proxy reader returns 304 (aka S3 NotModified)', async t => { t.plan(2) let tmp = mockTmp({ - [join(public, imgName)]: imgContents + [join(public, imgName)]: imgContents, }) setSandboxPath(tmp) let params = read({ IfNoneMatch: hash(imgContents) }) @@ -143,7 +142,7 @@ test('Local proxy reader templatizes with local paths when fingerprinting is ena process.env.ARC_ENV = 'staging' let tmp = mockTmp({ [join(public, mdName)]: mdContents, - [join(public, imgName)]: imgContents + [join(public, imgName)]: imgContents, }) setSandboxPath(tmp) let params = read({ Key: mdName, config: { assets: staticStub, sandboxPath } }) diff --git a/test/unit/src/read/_pretty-test.js b/test/unit/src/read/_pretty-test.js index 8ca229a..ded2da4 100644 --- a/test/unit/src/read/_pretty-test.js +++ b/test/unit/src/read/_pretty-test.js @@ -45,7 +45,7 @@ test('Set up env', t => { t.plan(1) process.env.__TESTING__ = true pretty = proxyquire(sut, { - '../lib/get-s3': getS3 + '../lib/get-s3': getS3, }) t.ok(pretty, 'Loaded pretty') }) @@ -60,20 +60,20 @@ test('Peek and find nested index.html', async t => { Bucket, Key, headers, - isFolder + isFolder, }) t.equal(result.body, 'got ok/hi/index.html', 'Successfully peeked into an S3 folder without a trailing slash') // Fingerprinting enabled let assets = { - 'ok/hi/index.html': 'ok/hi/index-abc12.html' + 'ok/hi/index.html': 'ok/hi/index-abc12.html', } result = await pretty({ Bucket, Key, assets, headers, - isFolder + isFolder, }) t.equal(result.body, 'got ok/hi/index-abc12.html', 'Successfully peeked into an S3 folder with fingerprinting enabled') @@ -85,7 +85,7 @@ test('Peek and find nested index.html', async t => { assets, headers, isFolder, - prefix + prefix, }) t.equal(result.body, 'got a-prefix/ok/hi/index-abc12.html', 'Successfully peeked into an S3 folder with fingerprinting and prefix enabled') @@ -93,7 +93,7 @@ test('Peek and find nested index.html', async t => { process.env.ARC_ENV = 'testing' let msg = 'got ok/hi/index.html from local!' tmp = mockTmp({ - 'ok/hi/index.html': buf(msg) + 'ok/hi/index.html': buf(msg), }) result = await pretty({ Bucket, @@ -117,7 +117,7 @@ test('Peek and do not find nested index.html', async t => { Bucket, Key, headers, - isFolder + isFolder, }) t.equal(result.statusCode, 404, 'Returns statusCode of 404 if S3 file is not found') t.match(result.body, /NoSuchKey/, 'Error message included in response from S3') @@ -145,21 +145,21 @@ test('Return a custom 404', async t => { Bucket, Key, headers, - isFolder + isFolder, }) t.equal(result.statusCode, 404, 'Returns statusCode of 404 with custom 404 error from S3') t.equal(result.body, 'got 404.html', 'Output is custom 404 page from S3 at: 404.html') // Fingerprinting enabled let assets = { - '404.html': '404-abc12.html' + '404.html': '404-abc12.html', } result = await pretty({ Bucket, Key, assets, headers, - isFolder + isFolder, }) t.equal(result.statusCode, 404, 'Returns statusCode of 404 with custom 404 error from S3') t.equal(result.body, 'got 404-abc12.html', 'Output is custom 404 page from S3 at: 404-abc12.html') @@ -172,7 +172,7 @@ test('Return a custom 404', async t => { assets, headers, isFolder, - prefix + prefix, }) t.equal(result.statusCode, 404, 'Returns statusCode of 404 with custom 404 error from S3') t.equal(result.body, 'got a-prefix/404-abc12.html', 'Output is custom 404 page from S3 at: a-prefix/404-abc12.html') @@ -205,7 +205,7 @@ test('Return the default 404', async t => { Bucket, Key, headers, - isFolder + isFolder, }) t.equal(result.statusCode, 404, 'Returns statusCode of 404 if S3 file is not found') t.match(result.body, /NoSuchKey/, 'Error message included in response from S3') @@ -226,7 +226,7 @@ test('Return the default 404', async t => { // Check casing tmp = mockTmp({ - '404.HTML': 'yo' + '404.HTML': 'yo', }) errorState = 'NoSuchKey' result = await pretty({ diff --git a/test/unit/src/read/_s3-test.js b/test/unit/src/read/_s3-test.js index d4cc562..d53170d 100644 --- a/test/unit/src/read/_s3-test.js +++ b/test/unit/src/read/_s3-test.js @@ -51,7 +51,7 @@ function read (params = {}) { Key: Key || imgName, IfNoneMatch: IfNoneMatch || imgETag, config: config || { spa: true }, - rootPath: rootPath || undefined + rootPath: rootPath || undefined, } } @@ -88,7 +88,7 @@ let imgETag = 'abc123' let sut = join(process.cwd(), 'src', 'read', '_s3') let readS3 = proxyquire(sut, { '../lib/get-s3': getS3, - './_pretty': prettyStub + './_pretty': prettyStub, }) test('Set up env', t => { @@ -152,7 +152,7 @@ test('S3 proxy reader passes through ContentEncoding to response headers', async let Body = gzipSync(Buffer.from(imgContents)) createResponse(null, null, { ContentEncoding, - Body + Body, }) let result = await readS3(read()) t.equal(result.statusCode, 200, 'Returns statusCode: 200') From c8f63c1638b2d7c2a1284f7b7eb710acb5e46299 Mon Sep 17 00:00:00 2001 From: Ryan Block Date: Mon, 29 Apr 2024 10:49:49 -0700 Subject: [PATCH 4/4] Update CI --- .github/workflows/build.yml | 15 +++++++++++---- package.json | 1 + 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6a8c934..3856750 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,10 +21,10 @@ jobs: # Go steps: - name: Check out repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} @@ -40,7 +40,14 @@ jobs: - name: Install run: npm i + - name: Test (Node.js <= 16.x) + if: matrix.node-version <= '16.x' + run: npm run test:nolint + env: + CI: true + - name: Test + if: matrix.node-version > '16.x' run: npm test env: CI: true @@ -67,10 +74,10 @@ jobs: # Go steps: - name: Check out repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: lts/* registry-url: https://registry.npmjs.org/ diff --git a/package.json b/package.json index ffa928b..0313e92 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "scripts": { "lint": "eslint . --fix", "rc": "npm version prerelease --preid RC", + "test:nolint": "npm run coverage", "test": "npm run lint && npm run coverage", "test:unit": "cross-env tape 'test/unit/**/*-test.js' | tap-arc", "coverage": "nyc --reporter=lcov --reporter=text npm run test:unit",