Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
28 changes: 28 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,18 @@ JSON_STDOUT="false"
# Sets up logging level: critical, normal, verbose
LOG_LEVELS="critical,normal,verbose"

# Constant reference in code: ENV_LOG_HISTORY_BUFFER_SIZE | Default value: 255
# Sets up logging history buffer size. It is a max length of the history buffer, every record is the call of log function, that can contain multi-line text. (Default: 255)
LOG_HISTORY_BUFFER_SIZE="255"

# Constant reference in code: ENV_EXPRESS_REQUEST_LOG_HISTORY_BUFFER_SIZE | Default value: 255
# Sets up logging history buffer size. It is a max length of the history buffer, every record is the record of the request. (Default: 255)
EXPRESS_REQUEST_LOG_HISTORY_BUFFER_SIZE="255"

# Constant reference in code: ENV_ENABLE_REQUEST_HISTORY | Default value: false
# Enables request history, useful if you want to log the last n requests and be able to replay the request. (Default: false)
ENABLE_REQUEST_HISTORY="false"

# Constant reference in code: ENV_SERVER_PORT | Default value: 1331
# Server port on which express app will be hosted
SERVER_PORT="1331"
Expand All @@ -34,6 +46,10 @@ PRIVATE_KEY_CONFIGURATION="__INSERT_YOUR_PRIVATE_KEY_CONFIGURATION__"
# Server max allowed body size from client that express app will support. (Main usecase is Apple Subscription Notifications)
SERVER_BODY_SIZE="2mb"

# Constant reference in code: ENV_SERVER_BODY_SIZE_ADMIN_CONSOLE | Default value: 50mb
# Server max allowed body size from client that express app will support for admin console.
SERVER_BODY_SIZE_ADMIN_CONSOLE="50mb"

# Constant reference in code: ENV_DISABLE_EXPRESS_BODY_PARSER | Default value: false
# The Express body parser will be disabled for all routes except the ones required for Console.
DISABLE_EXPRESS_BODY_PARSER="false"
Expand Down Expand Up @@ -82,6 +98,10 @@ HLAMBDA_CONSOLE_ASSETS_DIR="public"
# Debounce ms time to wait before closing the server and reloading metadata.
HLAMBDA_METADATA_RELOAD_DEBOUNCE_MS="1331"

# Constant reference in code: ENV_HLAMBDA_GRACEFUL_SHUTDOWN_DELAY_MS | Default value: 0
# Graceful shutdown delay in ms, time to wait before closing the server (Used to give some time to the app to finish all processes after SIGINT).
HLAMBDA_GRACEFUL_SHUTDOWN_DELAY_MS="0"

# Constant reference in code: ENV_HLAMBDA_LOADED_APPS_PREFIX | Default value:
# Prefix used for all the loaded router apps.
HLAMBDA_LOADED_APPS_PREFIX=""
Expand All @@ -94,6 +114,14 @@ HLAMBDA_ENABLE_PUBLIC_SWAGGER="false"
# Flag to map swagger route, default `/docs`.
HLAMBDA_PUBLIC_SWAGGER_ROUTE="/docs"

# Constant reference in code: ENV_HLAMBDA_SWAGGER_UI_TOKEN_EXPIRES_IN_SECONDS | Default value: 86400
# Expires in value in seconds, time before JWT token expires and cookie is deleted on the client.
HLAMBDA_SWAGGER_UI_TOKEN_EXPIRES_IN_SECONDS="86400"

# Constant reference in code: ENV_HLAMBDA_VSCODE_UI_TOKEN_EXPIRES_IN_SECONDS | Default value: 86400
# Expires in value in seconds, time before JWT token expires and cookie is deleted on the client.
HLAMBDA_VSCODE_UI_TOKEN_EXPIRES_IN_SECONDS="86400"

# Constant reference in code: ENV_HLAMBDA_CONFIGURATION_LOADER_PREFIX | Default value: hlambda-config.yaml
# Sets the value for the name of the configuration file that will be loaded.
HLAMBDA_CONFIGURATION_LOADER_PREFIX="hlambda-config.yaml"
Expand Down
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
# Release 0.3.0

- Added zero downtime reload.
- Added fully featured vscode for editing metadata in Console UI
- Added pre-installed Hlambda extension to custom vscode build.
- Added pre-installed Hasura extension to custom vscode build.
- Added pre-installed Color-Vision extension to custom vscode build.
- Updated Console UI. Home page now shows both logs and Swagger UI.
- Added support for saving request history, added replay option for the requests saved in request history.
- Replaced terminal with vscode pseudo terminal.
- Updated to new Hlambda logo.
- Updated favicon.

# Release 0.2.0

- Updated Console UI (Logs: Auto scroll snap, Metadata: Action history dates)
Expand Down
12 changes: 11 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ RUN apk -U upgrade \
git \
openssh

## Install Nginx (used for zero downtime)
#RUN apk add nginx

#COPY ./nginx/nginx.conf /etc/nginx/nginx.conf

RUN mkdir -p /usr/src/app

# Create app directory
Expand All @@ -31,7 +36,12 @@ RUN cd ./metadata && npm install --only=production
# At the point of building image we also want to move metadata folder with npm modules to data/metadata-examples
RUN cp -r ./metadata/* ./data/metadata-examples

CMD ["npm", "run", "start"]
# Install PM2 globally
RUN npm install pm2 -g

# CMD ["npm", "run", "start"]

CMD [ "pm2-runtime", "start", "ecosystem.config.cjs" ]

# This is not ready, there are known bugs with cluster mode (state management between nodes, like path in remote shell etc...)
#CMD ["npm", "run", "cluster-runtime"]
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,19 @@

## What is Hlambda (/hlæmdə/) [Hyper Lambda]

Hlambda is ECMAScript meta API service. That means that it offers simple ways to deploy ECMAScript code to local or remote servers.
Hlambda is ECMAScript meta API service. It offers simple ways to deploy ECMAScript code to local or remote servers.

<a href="https://hub.docker.com/r/hlambda/hlambda-core" title="Docker Image">

<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://www.hlambda.io/assets/hlambda-logo-light.png">
<source media="(prefers-color-scheme: light)" srcset="https://www.hlambda.io/assets/hlambda-logo-dark.png">
<img alt="Hlambda Banner" src="https://www.hlambda.io/assets/hlambda-logo-dark.png">
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/hlambda/hlambda-core/master/public/static/images/hlambda-logo-banner-light-blue.png">
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/hlambda/hlambda-core/master/public/static/images/hlambda-logo-banner-blue.png">
<img alt="Hlambda Banner" src="https://raw.githubusercontent.com/hlambda/hlambda-core/master/public/static/images/hlambda-logo-banner-blue.png">
</picture>

</a>

It is the implementation of the idea to load your ECMAScript code as configuration (metadata). With Hlambda you can easily create a microservice that can load arbitrary code configuration.
It is the implementation of the idea to load your ECMAScript code as configuration (metadata). With Hlambda you can easily create a microservice that can load arbitrary code configurations.

The main use case was to implement a stateless REST microservice that will run Hasura custom actions in a separate container, containing any custom business logic.

Expand Down
2 changes: 1 addition & 1 deletion docker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Hlambda is easy to manage, meta ECMAScript API server, with console UI and CLI t

Your ECMAScript metadata payload is the configuration of the (Hyper Lambda) Hlambda Server.

![Hlambda Banner](https://www.hlambda.io/assets/hlambda-logo-dark.png)
![Hlambda Banner](https://raw.githubusercontent.com/hlambda/hlambda-core/master/public/static/images/hlambda-logo-banner-blue.png)

# How to use this image

Expand Down
38 changes: 38 additions & 0 deletions ecosystem.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
module.exports = {
apps: [
{
name: 'Backend Microservice',
script: 'src/index.js',
// script: 'npm', // Do not use this, express port binding will be problematic with npm start
// args: 'run start', // Look abowe

exec_mode: 'cluster',

instances: 1, // Important!!! (Hlambda is stateless but shell, logs and other routes are not shared)
autorestart: true, // Set autorestart if there is unexpected error.
max_memory_restart: '2G',

// Watch is problematic, it will issue pm2 restart instead of pm2 reload
// watch: false,
// watch: 'watcher_trigger/', // This only works if dot files / folders are not used, due to chokidar and pm2 :(

// Delay between restart
// watch_delay: 1000,
listen_timeout: 15000,
wait_ready: true,
kill_timeout: 60000, // Amount of time waiting after SIGINT to execute SIGKILL

out_file: '/dev/null',
error_file: '/dev/null',

vizion: false,
pmx: false,

// output: '/dev/null', // This will disable stdout logs even for windows :)
// error: '/dev/null', // This will disable stderr logs even for windows :)
// log: true, // This will enable combined stdout and stderr logs, without giving a path
// log_type: 'json', // This will transform output to JSON
// merge_logs: true, // This will combine stdout and stderr logs, without giving a path
},
],
};
29 changes: 0 additions & 29 deletions ecosystem.config.js

This file was deleted.

17 changes: 2 additions & 15 deletions metadata/apps/auth/routes/router.auth.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,17 @@
import express from 'express';
import asyncHandler from 'express-async-handler';

import { DateTime } from 'luxon';

import hasuraRequestLogger from './../hasura-request-logger.js';

import errors from './../errors.demo.js';

// Create express router
const router = express.Router();

router.use('/hook/auth*', hasuraRequestLogger);

router.get(
'/hook/auth',
asyncHandler((req, res) => {
res.send(`Demo app works: ${DateTime.now()} ${process.env.SPECIAL_PASSWORD}`);
})
);

router.get(
'/hook/auth-error',
asyncHandler((req, res) => {
// res.send(`Demo app works: ${DateTime.now()} ${process.env.SPECIAL_PASSWORD}`);
throw new Error(errors.SOMETHING_WENT_TERRIBLY_WRONG);
// res.send(`Demo app works: ${DateTime.now()} ${process.env.SPECIAL_PASSWORD}`);
asyncHandler(async (req, res) => {
res.send(`Demo auth hook works: ${DateTime.now()} ${process.env.SPECIAL_PASSWORD}`);
})
);

Expand Down
6 changes: 2 additions & 4 deletions metadata/apps/auth/routes/router.cookies.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import express from 'express';
import asyncHandler from 'express-async-handler';

import cookieParser from 'cookie-parser';

import errors from './../errors.demo.js';

// Create express router
Expand All @@ -12,15 +10,15 @@ const router = express.Router();

router.get(
'/cookie/set',
asyncHandler((req, res) => {
asyncHandler(async (req, res) => {
res.cookie('demo-jwt-token', 'token ey...', { maxAge: 10800 });
res.send(`Demo token set!`);
})
);

router.get(
'/cookie/get',
asyncHandler((req, res) => {
asyncHandler(async (req, res) => {
console.log('Cookies: ', req.cookies);
res.send(JSON.stringify(req.cookies, null, 2));
})
Expand Down
24 changes: 24 additions & 0 deletions metadata/apps/bad-app/router.async-issue.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
// Uncomment this file to test how Hlambda handles bad code with errors.

import express from 'express';
import asyncHandler from 'express-async-handler';

// Create express router
const router = express.Router();

// This app is intentionally wrong, fix it your self to see that even broken scripts won't kill hlambda container

router.get(
'/await-but-not-async',
asyncHandler(
// async
(req, res) => {
await (async () => {})()
res.send(`Be careful that your resolver really is async when you use await. There will be no stacktrace`);
})
);

export default router;

*/
2 changes: 1 addition & 1 deletion metadata/apps/bad-app/router.auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ zzzzz;

router.get(
'/share-dependency',
asyncHandler((req, res) => {
asyncHandler(async (req, res) => {
res.send(`Prototype login works: ${DateTime.now()}`);
})
);
Expand Down
46 changes: 31 additions & 15 deletions metadata/apps/example-demo-app/hlambda-config.yaml
Original file line number Diff line number Diff line change
@@ -1,24 +1,40 @@
# Defines if the app is enabled or not, disabled apps are skipped from importing
enabled: true
# # Defines if we want to use namespace or not
# use_namespace: true # NOT IN USE!
# # Define the namespace name
# namespace_name: 'demo_app' # NOT IN USE!
# Custom environment variables override for our app
env:
HASURA_GRAPHQL_API_ENDPOINT: "http://graphql-engine:8099/v1/graphql"
HASURA_GRAPHQL_ADMIN_SECRET: "hlambda-test"
HLAMBDA_DISABLE_CONSOLE: "false"

HASURA_GRAPHQL_API_ENDPOINT: 'http://graphql-engine:8099/v1/graphql'
HASURA_GRAPHQL_ADMIN_SECRET: 'hlambda-test'
HLAMBDA_DISABLE_CONSOLE: 'false'
ENABLE_REQUEST_HISTORY: 'true'

#HLAMBDA_ENABLE_ENVIRONMENT_BANNER: "true"
#HLAMBDA_ENVIRONMENT_BANNER_NAME: "Local Hlambda Demo Development"
#HLAMBDA_ENVIRONMENT_BANNER_MESSAGE: "Hello Hlambda Env Banner!"
#HLAMBDA_ENABLE_ENVIRONMENT_BANNER_COLOR: "#eeFF22"

#JSON_STDOUT: true

# Custom environment variables override for our app
envForce:
HASURA_GRAPHQL_API_ENDPOINT: "http://graphql-engine:8099/v1/graphql"
HASURA_GRAPHQL_ADMIN_SECRET: "real-password"
SPECIAL_PASSWORD: "value-from-env"
HLAMBDA_DISABLE_CONSOLE: "false"
HASURA_GRAPHQL_API_ENDPOINT: 'http://graphql-engine:8099/v1/graphql'
HASURA_GRAPHQL_ADMIN_SECRET: 'real-password'
SPECIAL_PASSWORD: 'value-from-env'
HLAMBDA_DISABLE_CONSOLE: 'false'

# Consider that cwd for the script is ./metadata/ , also we suggest that you do not deploy ts as metadata, only js and do transpilation before metadata apply.
# But if you want you can slow down the reload time and await for scripts to run after every reload.
#postReloadScripts:
# - npm install --only=production
# - npx tsc --module ES2020 ./apps/example-demo-app/router.demo-ts.ts

# If used routers and entrypoints are skipped from importing
#ignoreRouters: './*' # use `true` for all
#ignoreEntrypoints: './*' # use `true` for all

# Defines if the app is enabled or not, disabled apps are not applied (configuration is ignored)
#enabled: false # default true

# --- Proposals ---

# # Defines if we want to use namespace or not
# use_namespace: true # NOT IN USE!

# # Define the namespace name
# namespace_name: 'demo_app' # NOT IN USE!
Loading