Skip to content

Commit

Permalink
Merge branch 'release/3.4.2'
Browse files Browse the repository at this point in the history
  • Loading branch information
electerious committed Dec 17, 2022
2 parents 7d0196e + c3fb91f commit 32025ae
Show file tree
Hide file tree
Showing 16 changed files with 3,147 additions and 2,570 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Expand Up @@ -28,7 +28,7 @@ jobs:

strategy:
matrix:
node-version: [14.x, 16.x, 17.x]
node-version: [14.x, 16.x, 18.x]
os: [ubuntu-latest, windows-latest, macOS-latest]

steps:
Expand Down
10 changes: 10 additions & 0 deletions CHANGELOG.md
Expand Up @@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [3.4.2] - 2022-12-17

## Changed

- Adjust Docker to run as non-root user (thanks @rjhancock, #309, #337)

## Fixed

- Rendering issue in Safari

## [3.4.1] - 2022-05-21

## Fixed
Expand Down
11 changes: 11 additions & 0 deletions Dockerfile
@@ -1,6 +1,12 @@
# Start with first build stage

FROM node:14-alpine AS build

# Add and set non-root user. Disable the password and do not create a home folder.

RUN adduser -D ackee ackee
USER ackee

WORKDIR /srv/app/

# Add dependencies first so that Docker can use the cache as long as the dependencies stay unchanged
Expand All @@ -24,6 +30,11 @@ WORKDIR /srv/app/

COPY --from=build /srv/app/ /srv/app/

# Create user/group to run as, change ownership of files and set user

RUN adduser -D ackee ackee && chown -R ackee:ackee /srv/app
USER ackee

# Run healthcheck against MongoDB, server and API.
# Wait a bit before start to ensure the `yarn build` is done.

Expand Down
2 changes: 1 addition & 1 deletion dist/index.css

Large diffs are not rendered by default.

256 changes: 106 additions & 150 deletions dist/index.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docker-compose.yml
Expand Up @@ -18,4 +18,4 @@ services:
container_name: mongo
restart: always
volumes:
- ./data:/data/db
- ./data:/data/db
26 changes: 13 additions & 13 deletions package.json
@@ -1,7 +1,7 @@
{
"name": "ackee",
"private": true,
"version": "3.4.1",
"version": "3.4.2",
"authors": [
"Tobias Reich <tobias@electerious.com>"
],
Expand Down Expand Up @@ -33,18 +33,18 @@
"lint": "eslint \"{functions,src,test}/**/*.js\""
},
"dependencies": {
"@graphql-tools/merge": "^8.2.10",
"@graphql-tools/merge": "^8.3.14",
"ackee-tracker": "^5.1.0",
"apollo-server-core": "^3.6.7",
"apollo-server-lambda": "^3.6.7",
"apollo-server-micro": "^3.6.7",
"apollo-server-core": "^3.11.1",
"apollo-server-lambda": "^3.11.1",
"apollo-server-micro": "^3.11.1",
"apollo-server-plugin-http-headers": "^0.1.4",
"date-fns": "^2.28.0",
"date-fns-tz": "^1.3.4",
"debounce-promise": "^3.1.2",
"dotenv": "^16.0.0",
"graphql": "^16.4.0",
"graphql-scalars": "^1.17.0",
"graphql": "^16.6.0",
"graphql-scalars": "^1.20.1",
"is-url": "^1.2.4",
"is-valid-domain": "^0.1.6",
"micro": "^9.3.4",
Expand All @@ -56,17 +56,17 @@
"request-ip": "^2.1.3",
"sanitize-filename": "^1.6.3",
"signale": "^1.4.0",
"uuid": "^8.3.2"
"uuid": "^9.0.0"
},
"devDependencies": {
"@apollo/client": "^3.6.1",
"@electerious/eslint-config": "^3.1.0",
"ava": "4.2.0",
"@apollo/client": "^3.7.2",
"@electerious/eslint-config": "^3.5.0",
"ava": "5.1.0",
"classnames": "^2.3.1",
"coveralls": "^3.1.1",
"formbase": "^12.0.2",
"history": "^5.3.0",
"human-number": "^1.0.10",
"human-number": "^2.0.1",
"mocked-env": "^1.3.5",
"mongodb-memory-server": "^8.5.2",
"nodemon": "^2.0.16",
Expand Down Expand Up @@ -107,4 +107,4 @@
"engines": {
"node": ">= 14"
}
}
}
12 changes: 6 additions & 6 deletions src/healthcheck.js
Expand Up @@ -14,18 +14,18 @@ if (config.dbUrl == null) {
}

const checkServer = async (url) => {
const res = await fetch(url)
const response = await fetch(url)

if (res.ok === false) {
throw new Error(`Server is unhealthy and returned with the status '${ res.status }'`)
if (response.ok === false) {
throw new Error(`Server is unhealthy and returned with the status '${ response.status }'`)
}
}

const checkApi = async (url) => {
const res = await fetch(url)
const response = await fetch(url)

if (res.ok === false) {
throw new Error(`API is unhealthy and returned with the status '${ res.status }'`)
if (response.ok === false) {
throw new Error(`API is unhealthy and returned with the status '${ response.status }'`)
}
}

Expand Down
78 changes: 39 additions & 39 deletions src/server.js
Expand Up @@ -21,7 +21,7 @@ const styles = readFile(resolve(__dirname, '../dist/index.css')).catch(signale.f
const scripts = readFile(resolve(__dirname, '../dist/index.js')).catch(signale.fatal)
const tracker = readFile(resolve(__dirname, '../dist/tracker.js')).catch(signale.fatal)

const handleMicroError = (error, res) => {
const handleMicroError = (error, response) => {
// This part is for micro errors and errors outside of GraphQL.
// Most errors won't be caught here, but some error can still
// happen outside of GraphQL. In this case we distinguish
Expand All @@ -35,11 +35,11 @@ const handleMicroError = (error, res) => {
// Only log the full error stack when the error isn't a known response
if (isUnknownError === true) {
signale.fatal(error)
return send(res, 500, error.message)
return send(response, 500, error.message)
}

signale.warn(hasOriginalError === true ? error.originalError.message : error.message)
send(res, error.statusCode, error.message)
send(response, error.statusCode, error.message)
}

const handleGraphError = (error) => {
Expand All @@ -61,34 +61,34 @@ const handleGraphError = (error) => {
return error
}

const catchError = (fn) => async (req, res) => {
const catchError = (fn) => async (request, response) => {
try {
return await fn(req, res)
return await fn(request, response)
} catch (error) {
handleMicroError(error, res)
handleMicroError(error, response)
}
}

const attachCorsHeaders = (fn) => async (req, res) => {
const matchingOrigin = await findMatchingOrigin(req, config.allowOrigin, config.autoOrigin)
const attachCorsHeaders = (fn) => async (request, response) => {
const matchingOrigin = await findMatchingOrigin(request, config.allowOrigin, config.autoOrigin)

if (matchingOrigin != null) {
res.setHeader('Access-Control-Allow-Origin', matchingOrigin)
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PATCH, OPTIONS')
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, Time-Zone')
res.setHeader('Access-Control-Allow-Credentials', 'true')
res.setHeader('Access-Control-Max-Age', '3600')
response.setHeader('Access-Control-Allow-Origin', matchingOrigin)
response.setHeader('Access-Control-Allow-Methods', 'GET, POST, PATCH, OPTIONS')
response.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, Time-Zone')
response.setHeader('Access-Control-Allow-Credentials', 'true')
response.setHeader('Access-Control-Max-Age', '3600')
}

return fn(req, res)
return fn(request, response)
}

const awaitedHandler = (fn) => async (req, res) => {
return (await fn)(req, res)
const awaitedHandler = (fn) => async (request, response) => {
return (await fn)(request, response)
}

const notFound = (req) => {
const error = new Error(`\`${ req.url }\` not found`)
const notFound = (request) => {
const error = new Error(`\`${ request.url }\` not found`)

throw createError(404, 'Not found', error)
}
Expand All @@ -105,33 +105,33 @@ const apolloHandler = apolloServer

const routes = [

get('/', async (req, res) => {
res.setHeader('Content-Type', 'text/html; charset=utf-8')
res.end(await index)
get('/', async (request, response) => {
response.setHeader('Content-Type', 'text/html; charset=utf-8')
response.end(await index)
}),
get('/index.html', async (req, res) => {
res.setHeader('Content-Type', 'text/html; charset=utf-8')
res.end(await index)
get('/index.html', async (request, response) => {
response.setHeader('Content-Type', 'text/html; charset=utf-8')
response.end(await index)
}),
get('/favicon.ico', async (req, res) => {
res.setHeader('Content-Type', 'image/vnd.microsoft.icon')
res.end(await favicon)
get('/favicon.ico', async (request, response) => {
response.setHeader('Content-Type', 'image/vnd.microsoft.icon')
response.end(await favicon)
}),
get('/index.css', async (req, res) => {
res.setHeader('Content-Type', 'text/css; charset=utf-8')
res.end(await styles)
get('/index.css', async (request, response) => {
response.setHeader('Content-Type', 'text/css; charset=utf-8')
response.end(await styles)
}),
get('/index.js', async (req, res) => {
res.setHeader('Content-Type', 'text/javascript; charset=utf-8')
res.end(await scripts)
get('/index.js', async (request, response) => {
response.setHeader('Content-Type', 'text/javascript; charset=utf-8')
response.end(await scripts)
}),
get('/tracker.js', async (req, res) => {
res.setHeader('Content-Type', 'text/javascript; charset=utf-8')
res.end(await tracker)
get('/tracker.js', async (request, response) => {
response.setHeader('Content-Type', 'text/javascript; charset=utf-8')
response.end(await tracker)
}),
customTracker.exists === true ? get(customTracker.url, async (req, res) => {
res.setHeader('Content-Type', 'text/javascript; charset=utf-8')
res.end(await tracker)
customTracker.exists === true ? get(customTracker.url, async (request, response) => {
response.setHeader('Content-Type', 'text/javascript; charset=utf-8')
response.end(await tracker)
}) : undefined,

post(graphqlPath, awaitedHandler(apolloHandler)),
Expand Down
7 changes: 5 additions & 2 deletions src/ui/scripts/index.js
@@ -1,5 +1,5 @@
import { createElement as h, useState, useCallback } from 'react'
import { render } from 'react-dom'
import { createRoot } from 'react-dom/client'
import { ApolloProvider } from '@apollo/client/react'

import createStatusLink from './api/links/createStatusLink'
Expand Down Expand Up @@ -81,4 +81,7 @@ const App = () => {
)
}

render(h(App), document.querySelector('#main'))
const container = document.querySelector('#main')
const root = createRoot(container)

root.render(h(App))
3 changes: 1 addition & 2 deletions src/ui/styles/_status.scss
@@ -1,8 +1,7 @@
.status {

display: grid;
display: flex;
gap: math.div($gutter, 2);
grid-auto-flow: column;
justify-content: start;
align-items: center;

Expand Down
10 changes: 5 additions & 5 deletions src/utils/findMatchingOrigin.js
Expand Up @@ -2,20 +2,20 @@

const fullyQualifiedDomainNames = require('./fullyQualifiedDomainNames')

const findOrigin = (req, origins) => {
return origins.find((origin) => origin.includes(req.headers.origin) || origin.includes(req.headers.host))
const findOrigin = (request, origins) => {
return origins.find((origin) => origin.includes(request.headers.origin) || origin.includes(request.headers.host))
}

module.exports = async (req, allowedOrigins, autoOrigin) => {
module.exports = async (request, allowedOrigins, autoOrigin) => {
if (autoOrigin === true) {
const origins = await fullyQualifiedDomainNames()
return findOrigin(req, origins)
return findOrigin(request, origins)
}

if (allowedOrigins === '*') return '*'

if (allowedOrigins != null) {
const origins = allowedOrigins.split(',')
return findOrigin(req, origins)
return findOrigin(request, origins)
}
}
6 changes: 3 additions & 3 deletions src/utils/pipe.js
Expand Up @@ -2,9 +2,9 @@

module.exports = (...args) => {
return Array.prototype.slice.call(args, 1).reduce((a, b) => {
return (...args) => Promise.resolve(a(...args)).then((res) => {
if (res == null) return b(...args)
return res
return (...args) => Promise.resolve(a(...args)).then((result) => {
if (result == null) return b(...args)
return result
})
}, args[0])
}
6 changes: 3 additions & 3 deletions test/resolvers/_utils.js
Expand Up @@ -86,7 +86,7 @@ const api = async (base, body, token, headers = {}) => {
defaultHeaders['Content-Type'] = 'application/json'
defaultHeaders['Authorization'] = token == null ? undefined : `Bearer ${ token }`

const res = await fetch(url.href, {
const result = await fetch(url.href, {
method: 'post',
body: JSON.stringify(body),
headers: {
Expand All @@ -96,8 +96,8 @@ const api = async (base, body, token, headers = {}) => {
})

return {
headers: res.headers,
json: await res.json(),
headers: result.headers,
json: await result.json(),
}
}

Expand Down

1 comment on commit 32025ae

@vercel
Copy link

@vercel vercel bot commented on 32025ae Dec 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

ackee – ./

ackee-mocha.vercel.app
ackee-electerious.vercel.app
ackee-git-master-electerious.vercel.app

Please sign in to comment.