@seeka-labs/cli-apps 1.1.39 → 2.0.7-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +31 -36
- package/dist/index.js.map +4 -4
- package/dist/init-template/.gitlab-ci.yml +47 -0
- package/dist/init-template/.yarnrc.yml +8 -0
- package/dist/init-template/README.md +7 -0
- package/dist/{init-templates → init-template/app}/browser/jest.config.js +11 -11
- package/dist/{init-templates → init-template/app}/browser/package.json +16 -12
- package/dist/{init-templates → init-template/app}/browser/scripts/esbuild/build-browser-plugin.mjs +110 -110
- package/dist/{init-templates → init-template/app}/browser/scripts/esbuild/plugins/importAsGlobals.mjs +38 -38
- package/dist/{init-templates → init-template/app}/browser/src/browser.ts +12 -12
- package/dist/{init-templates → init-template/app}/browser/src/plugin/index.test.ts +6 -6
- package/dist/{init-templates → init-template/app}/browser/src/plugin/index.ts +47 -49
- package/dist/{init-templates → init-template/app}/browser/tsconfig.json +34 -34
- package/dist/{init-templates/netlify-function → init-template/app/server-azure-function}/.eslintrc.cjs +2 -10
- package/dist/{init-templates/azure-function → init-template/app/server-azure-function}/.funcignore +12 -7
- package/dist/init-template/app/server-azure-function/.nvmrc +1 -0
- package/dist/{init-templates/azure-function → init-template/app/server-azure-function}/README.md +104 -107
- package/dist/{init-templates/azure-function → init-template/app/server-azure-function}/host.json +1 -10
- package/dist/init-template/app/server-azure-function/package.json +52 -0
- package/dist/{init-templates/azure-function → init-template/app/server-azure-function}/src/functions/seekaAppWebhook.ts +235 -236
- package/dist/{init-templates/azure-function → init-template/app/server-azure-function}/src/lib/browser/index.ts +54 -54
- package/dist/{init-templates/azure-function → init-template/app/server-azure-function}/src/lib/jobs/index.ts +1 -1
- package/dist/{init-templates/azure-function → init-template/app/server-azure-function}/src/lib/logging/index.ts +92 -92
- package/dist/{init-templates/azure-function/src/lib/browser → init-template/app/server-azure-function/src/lib}/models/index.ts +6 -6
- package/dist/{init-templates/azure-function → init-template/app/server-azure-function}/src/lib/state/redis/index.ts +96 -65
- package/dist/{init-templates/azure-function → init-template/app/server-azure-function}/src/lib/state/seeka/installations.ts +64 -66
- package/dist/{init-templates/azure-function → init-template/app/server-azure-function}/tsconfig.json +1 -1
- package/dist/init-template/package.json +28 -0
- package/dist/init-template/tsconfig.json +25 -0
- package/package.json +5 -4
- package/dist/init-templates/aws-lambda/.env.example +0 -15
- package/dist/init-templates/aws-lambda/.eslintrc.cjs +0 -19
- package/dist/init-templates/aws-lambda/.example.gitignore +0 -49
- package/dist/init-templates/aws-lambda/.gitlab-ci.yml +0 -39
- package/dist/init-templates/aws-lambda/.nvmrc +0 -1
- package/dist/init-templates/aws-lambda/.vscode/extensions.json +0 -5
- package/dist/init-templates/aws-lambda/.vscode/launch.json +0 -20
- package/dist/init-templates/aws-lambda/.vscode/settings.json +0 -3
- package/dist/init-templates/aws-lambda/.vscode/tasks.json +0 -12
- package/dist/init-templates/aws-lambda/README.md +0 -77
- package/dist/init-templates/aws-lambda/jest.config.js +0 -5
- package/dist/init-templates/aws-lambda/package.json +0 -53
- package/dist/init-templates/aws-lambda/scripts/ngrok.js +0 -28
- package/dist/init-templates/aws-lambda/src/index.test.ts +0 -7
- package/dist/init-templates/aws-lambda/src/index.ts +0 -33
- package/dist/init-templates/aws-lambda/src/lib/logging/index.ts +0 -88
- package/dist/init-templates/aws-lambda/src/lib/services/index.ts +0 -41
- package/dist/init-templates/aws-lambda/src/lib/state/redis/index.ts +0 -65
- package/dist/init-templates/aws-lambda/src/lib/state/seeka/installations.ts +0 -67
- package/dist/init-templates/aws-lambda/src/routes/seekaAppWebhook.ts +0 -194
- package/dist/init-templates/aws-lambda/tsconfig.json +0 -31
- package/dist/init-templates/aws-lambda/yarn.lock +0 -4392
- package/dist/init-templates/azure-function/.eslintrc.cjs +0 -19
- package/dist/init-templates/azure-function/.example.gitignore +0 -48
- package/dist/init-templates/azure-function/.gitlab-ci.yml +0 -48
- package/dist/init-templates/azure-function/.nvmrc +0 -1
- package/dist/init-templates/azure-function/.vscode/extensions.json +0 -7
- package/dist/init-templates/azure-function/.vscode/launch.json +0 -13
- package/dist/init-templates/azure-function/.vscode/settings.json +0 -9
- package/dist/init-templates/azure-function/.vscode/tasks.json +0 -39
- package/dist/init-templates/azure-function/jest.config.js +0 -5
- package/dist/init-templates/azure-function/package.json +0 -47
- package/dist/init-templates/azure-function/scripts/dev-queue-setup.js +0 -30
- package/dist/init-templates/azure-function/src/index.test.ts +0 -7
- package/dist/init-templates/azure-function/yarn.lock +0 -3772
- package/dist/init-templates/browser/.editorconfig +0 -14
- package/dist/init-templates/browser/.eslintrc.cjs +0 -1
- package/dist/init-templates/browser/.yarnrc +0 -1
- package/dist/init-templates/browser/yarn.lock +0 -3045
- package/dist/init-templates/netlify-function/.env.example +0 -18
- package/dist/init-templates/netlify-function/.example.gitignore +0 -36
- package/dist/init-templates/netlify-function/.nvmrc +0 -1
- package/dist/init-templates/netlify-function/.vscode/launch.json +0 -45
- package/dist/init-templates/netlify-function/README.md +0 -62
- package/dist/init-templates/netlify-function/jest.config.js +0 -5
- package/dist/init-templates/netlify-function/netlify.toml +0 -7
- package/dist/init-templates/netlify-function/package.json +0 -39
- package/dist/init-templates/netlify-function/src/api/example-job-background/index.ts +0 -52
- package/dist/init-templates/netlify-function/src/api/polling-example-job-scheduled/index.ts +0 -46
- package/dist/init-templates/netlify-function/src/api/seeka-app-webhook/index.ts +0 -217
- package/dist/init-templates/netlify-function/src/index.test.ts +0 -7
- package/dist/init-templates/netlify-function/src/lib/jobs/index.ts +0 -68
- package/dist/init-templates/netlify-function/src/lib/logging/index.ts +0 -91
- package/dist/init-templates/netlify-function/src/lib/services/index.ts +0 -41
- package/dist/init-templates/netlify-function/src/lib/state/redis/index.ts +0 -65
- package/dist/init-templates/netlify-function/src/lib/state/seeka/installations.ts +0 -67
- package/dist/init-templates/netlify-function/tsconfig.json +0 -25
- package/dist/init-templates/netlify-function/yarn.lock +0 -9337
- /package/dist/{init-templates → init-template/app}/browser/README.md +0 -0
- /package/dist/{init-templates/azure-function → init-template/app/server-azure-function}/local.settings.example.json +0 -0
- /package/dist/{init-templates/azure-function → init-template/app/server-azure-function}/scripts/ngrok.js +0 -0
- /package/dist/{init-templates/azure-function → init-template/app/server-azure-function}/src/functions/healthCheck.ts +0 -0
- /package/dist/{init-templates/azure-function → init-template/app/server-azure-function}/src/functions/pollingExample.ts +0 -0
- /package/dist/{init-templates/azure-function → init-template/app/server-azure-function}/src/functions/queueExample.ts +0 -0
- /package/dist/{init-templates/azure-function → init-template/app/server-azure-function}/src/lib/services/index.ts +0 -0
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
bin
|
|
2
|
-
obj
|
|
3
|
-
csx
|
|
4
|
-
.vs
|
|
5
|
-
edge
|
|
6
|
-
Publish
|
|
7
|
-
deploy.zip
|
|
8
|
-
|
|
9
|
-
*.user
|
|
10
|
-
*.suo
|
|
11
|
-
*.cscfg
|
|
12
|
-
*.Cache
|
|
13
|
-
project.lock.json
|
|
14
|
-
|
|
15
|
-
/packages
|
|
16
|
-
/TestResults
|
|
17
|
-
|
|
18
|
-
/tools/NuGet.exe
|
|
19
|
-
/App_Data
|
|
20
|
-
/secrets
|
|
21
|
-
/data
|
|
22
|
-
.secrets
|
|
23
|
-
appsettings.json
|
|
24
|
-
local.settings.json
|
|
25
|
-
|
|
26
|
-
node_modules
|
|
27
|
-
dist
|
|
28
|
-
|
|
29
|
-
# Local python packages
|
|
30
|
-
.python_packages/
|
|
31
|
-
|
|
32
|
-
# Python Environments
|
|
33
|
-
.env
|
|
34
|
-
.venv
|
|
35
|
-
env/
|
|
36
|
-
venv/
|
|
37
|
-
ENV/
|
|
38
|
-
env.bak/
|
|
39
|
-
venv.bak/
|
|
40
|
-
|
|
41
|
-
# Byte-compiled / optimized / DLL files
|
|
42
|
-
__pycache__/
|
|
43
|
-
*.py[cod]
|
|
44
|
-
*$py.class
|
|
45
|
-
|
|
46
|
-
# Azurite artifacts
|
|
47
|
-
__blobstorage__
|
|
48
|
-
__queuestorage__
|
|
49
|
-
__azurite_db*__.json
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
stages:
|
|
2
|
-
- deploy
|
|
3
|
-
|
|
4
|
-
variables:
|
|
5
|
-
LAMBDA_FUNC_RESOURCE_NAME: seeka-app-example-name
|
|
6
|
-
CI_DEBUG_TRACE: "true"
|
|
7
|
-
|
|
8
|
-
workflow:
|
|
9
|
-
rules:
|
|
10
|
-
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
|
11
|
-
when: never
|
|
12
|
-
- if: '$CI_COMMIT_BRANCH == "main" && ($CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "web")'
|
|
13
|
-
when: always
|
|
14
|
-
- if: '$CI_COMMIT_BRANCH == "staging" && ($CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "web")'
|
|
15
|
-
when: always
|
|
16
|
-
|
|
17
|
-
deploy:
|
|
18
|
-
stage: deploy
|
|
19
|
-
image: node:20
|
|
20
|
-
environment:
|
|
21
|
-
name: $HOSTING_REGION_NAME/$HOSTING_ENV_NAME/apps
|
|
22
|
-
before_script:
|
|
23
|
-
- echo "installing aws cli"
|
|
24
|
-
- curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
|
|
25
|
-
- unzip awscliv2.zip
|
|
26
|
-
- ./aws/install --bin-dir /usr/local/bin --install-dir /usr/local/aws-cli --update
|
|
27
|
-
- ls -l /usr/local/bin/aws
|
|
28
|
-
- aws --version
|
|
29
|
-
- echo "using environment variables AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_DEFAULT_REGION for accessing the AWS CLI"
|
|
30
|
-
- echo "installing zip"
|
|
31
|
-
- apt-get update
|
|
32
|
-
- apt-get install zip
|
|
33
|
-
script:
|
|
34
|
-
- echo "deploying AWS lambda func $LAMBDA_FUNC_RESOURCE_NAME from branch $CI_COMMIT_BRANCH"
|
|
35
|
-
- yarn install --production=false
|
|
36
|
-
- yarn deploy
|
|
37
|
-
only:
|
|
38
|
-
- main
|
|
39
|
-
- staging
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
v20
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": "0.2.0",
|
|
3
|
-
"configurations": [
|
|
4
|
-
{
|
|
5
|
-
"name": "Debug Seeka app",
|
|
6
|
-
"type": "node",
|
|
7
|
-
"request": "attach",
|
|
8
|
-
"restart": true,
|
|
9
|
-
"port": 5858,
|
|
10
|
-
"outFiles": [],
|
|
11
|
-
"sourceMaps": true,
|
|
12
|
-
"resolveSourceMapLocations": [
|
|
13
|
-
"${workspaceFolder}/**",
|
|
14
|
-
"!**/node_modules/**",
|
|
15
|
-
"node_modules/@seeka-labs/**/*.js",
|
|
16
|
-
],
|
|
17
|
-
"preLaunchTask": "yarn watch and debug",
|
|
18
|
-
},
|
|
19
|
-
]
|
|
20
|
-
}
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
# Seeka app - AWS lambda
|
|
2
|
-
|
|
3
|
-
## Development
|
|
4
|
-
- `yarn install`
|
|
5
|
-
- `yarn watch:debug` or use VsCode debugging for "Debug Seeka App" configuration
|
|
6
|
-
|
|
7
|
-
### Debugging
|
|
8
|
-
Supports VSCode debugging via the debugger and utilisation of breakpoints.
|
|
9
|
-
Use "Debug Seeka App" configuration to compile, watch and start app.
|
|
10
|
-
This is only tested on Linux but may work on Windows.
|
|
11
|
-
If using Windows, WSL coupled with an Ubuntu distro will provide support for attaching the VS code debugger.
|
|
12
|
-
|
|
13
|
-
### Live urls
|
|
14
|
-
You can expose your app locally to the internet via Ngrok to test your app before deploying.
|
|
15
|
-
|
|
16
|
-
#### Setup
|
|
17
|
-
1. Sign up for a Ngrok account
|
|
18
|
-
2. Get your auth token
|
|
19
|
-
3. `yarn ngrok config add-authtoken [auth token here]` replacing `[auth token]` with the auth token retrieved from your Ngrok dashboard
|
|
20
|
-
|
|
21
|
-
#### Running
|
|
22
|
-
1. `yarn start` OR start debugging in VSCode
|
|
23
|
-
2. In separate terminal window run `yarn tunnel` and observe the log entry that starts with `Live url exposed`.
|
|
24
|
-
3. Input the URL into your Seeka app configuration as the "Webook URL" via the Seeka UI.
|
|
25
|
-
|
|
26
|
-
## Logging
|
|
27
|
-
Centralised logging handled by [Winston](https://www.npmjs.com/package/winston). Winston is installed in this template and is also used in the Seeka SDK NPM packages.
|
|
28
|
-
|
|
29
|
-
[Seq](https://datalust.co/seq) Winston transport is installed in this template (optional).
|
|
30
|
-
|
|
31
|
-
To configure Seq options, see `_SEQ_` environment variables.
|
|
32
|
-
|
|
33
|
-
To install Seq on your development machine
|
|
34
|
-
1. Run `docker run --name seq -d --restart=always -e ACCEPT_EULA=Y -p 5341:80 datalust/seq:2024.2`
|
|
35
|
-
2. Update your `LOGGING_SEQ_SERVERURL` environment variable to `http://localhost:5341` or `http://[YOUR MACHINE NAME].local:5341` if using WSL.
|
|
36
|
-
|
|
37
|
-
If creating an API key for Seq, only permission that is required is `Ingest`.
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
## State management
|
|
41
|
-
Installations of your app and other state required for your app to function is stored in Redis. Another state provider can be swapped out for Redis, see `src/lib/state/seeka/installations.ts` for the file that manages the state of the installations.
|
|
42
|
-
|
|
43
|
-
### Upstash (optional)
|
|
44
|
-
If you dont want to use Upstash for Redis then you can swap out the connection strings with your Redis instance.
|
|
45
|
-
|
|
46
|
-
> If using Upstash then create a database before following the below guide to deploying your AWS lambda function.
|
|
47
|
-
|
|
48
|
-
> When choosing a region, consider the AWS region that the lambda function is running from to reduce latency between the function and the Redis database.
|
|
49
|
-
|
|
50
|
-
## Deployment
|
|
51
|
-
1. [Install the aws lambda CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html#getting-started-install-instructions)
|
|
52
|
-
1. Create a function via the AWS console with following settings
|
|
53
|
-
- Mode: Author from scratch
|
|
54
|
-
- function name: `seeka-app-example-name`
|
|
55
|
-
- runtime: `Node.js 18.x`
|
|
56
|
-
- architecture: `arm64`
|
|
57
|
-
- Advanced settings:
|
|
58
|
-
- Enable code signing: unchecked
|
|
59
|
-
- Enable function URL: checked
|
|
60
|
-
- Auth type: `NONE` - Calls to your function from Seeka will be verified by SHA256 signatures
|
|
61
|
-
- Invoke mode: Buffered
|
|
62
|
-
- Configure cross-origin resource sharing: unchecked
|
|
63
|
-
- Enable VPC: unchecked
|
|
64
|
-
- All other settings leave as defaults
|
|
65
|
-
3. Add environment variables to the function in AWS by clicking 'Configuration' and then 'Environment varables'. Use the `.env` file in this project as a reference to what variables are required by to be set in the AWS Lambda.
|
|
66
|
-
4. [Authenticate the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-authentication-short-term.html)
|
|
67
|
-
2. `yarn deploy`
|
|
68
|
-
|
|
69
|
-
> At this point you may wish to [configure concurrency](https://docs.aws.amazon.com/lambda/latest/dg/scaling-behavior.html) of the AWS lambda function depending on the amount of concurrent requests you forecast your function handling.
|
|
70
|
-
|
|
71
|
-
6. Update your `Webhook URL` in you Seeka app configuration to point to the AWS Lambda function URL. This URL can be found in your viewing your Lambda via the AWS console and copying the "Function URL". It should look something like `https://prragnghaaupodlqte6hkvo446acc.lambda-url.ap-southeast-2.on.aws/`. Ensure to append `api/webhook/seeka/app` onto this URL so the complete example to update your Seeka app configuration with will look like `https://prragnghaaupodlqte6hkvo446acc.lambda-url.ap-southeast-2.on.aws/api/webhook/seeka/app`
|
|
72
|
-
|
|
73
|
-
### Continuous delivery
|
|
74
|
-
This template includes a GitLab CD pipeline that can be used to trigger deployments of your app when changes are pushed to your Git repository.
|
|
75
|
-
|
|
76
|
-
## References
|
|
77
|
-
- https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/index.html#available-commands
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "seeka-app-example-name",
|
|
3
|
-
"version": "0.0.1",
|
|
4
|
-
"description": "Seeka example app for hosting on AWS lambda functions",
|
|
5
|
-
"author": "Seeka <platform@seeka.co>",
|
|
6
|
-
"license": "MIT",
|
|
7
|
-
"main": "./index.js",
|
|
8
|
-
"private": true,
|
|
9
|
-
"engines": {
|
|
10
|
-
"node": ">=20"
|
|
11
|
-
},
|
|
12
|
-
"scripts": {
|
|
13
|
-
"lint": "eslint",
|
|
14
|
-
"build": "esbuild src/index.ts --bundle --minify --sourcemap --platform=node --target=node18 --outfile=dist/index.js",
|
|
15
|
-
"watch": "tsc -w",
|
|
16
|
-
"test": "yarn jest",
|
|
17
|
-
"clean": "<packageManagerRunPrefix> rimraf dist && <packageManagerRunPrefix> rimraf deploy.zip",
|
|
18
|
-
"start": "node --require dotenv/config dist/index.js",
|
|
19
|
-
"dev": "<packageManagerRunPrefix> clean && <packageManagerRunPrefix> build && node --require dotenv/config dist/index.js",
|
|
20
|
-
"tunnel": "node scripts/ngrok.js seeka-app-example-name-localdev",
|
|
21
|
-
"build:aws": "<packageManagerRunPrefix> clean && <packageManagerRunPrefix> build && cd dist && zip -r ../deploy.zip . && cd ..",
|
|
22
|
-
"deploy": "<packageManagerRunPrefix> build:aws && aws lambda update-function-code --function-name seeka-app-example-name --zip-file fileb://deploy.zip && rm deploy.zip",
|
|
23
|
-
"watch:debug": "nodemon --inspect=5858 -e ts --exec node -r ts-node/register --require dotenv/config ./src/index.ts"
|
|
24
|
-
},
|
|
25
|
-
"dependencies": {
|
|
26
|
-
"@datalust/winston-seq": "^2.0.0",
|
|
27
|
-
"@seeka-labs/sdk-apps-server": "^1.1.26",
|
|
28
|
-
"express": "^4.21.2",
|
|
29
|
-
"lodash-es": "^4.17.21",
|
|
30
|
-
"redis": "^4.7.0",
|
|
31
|
-
"serverless-http": "^3.2.0",
|
|
32
|
-
"winston": "^3.17.0"
|
|
33
|
-
},
|
|
34
|
-
"devDependencies": {
|
|
35
|
-
"@jest/globals": "^29.7.0",
|
|
36
|
-
"@types/aws-lambda": "^8.10.147",
|
|
37
|
-
"@types/express": "^5.0.0",
|
|
38
|
-
"@types/lodash-es": "^4.17.12",
|
|
39
|
-
"@types/node": "^20",
|
|
40
|
-
"@typescript-eslint/eslint-plugin": "^8.22.0",
|
|
41
|
-
"@typescript-eslint/parser": "^8.22.0",
|
|
42
|
-
"dotenv": "^16.4.7",
|
|
43
|
-
"esbuild": "^0.24.2",
|
|
44
|
-
"eslint": "^9",
|
|
45
|
-
"jest": "^29.7.0",
|
|
46
|
-
"ngrok": "^5.0.0-beta.2",
|
|
47
|
-
"nodemon": "^3.1.9",
|
|
48
|
-
"rimraf": "^6.0.1",
|
|
49
|
-
"ts-jest": "^29.2.5",
|
|
50
|
-
"ts-node": "^10.9.2",
|
|
51
|
-
"typescript": "^5.7.3"
|
|
52
|
-
}
|
|
53
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-undef */
|
|
2
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
3
|
-
const ngrok = require('ngrok');
|
|
4
|
-
(async function () {
|
|
5
|
-
const url = await ngrok.connect({
|
|
6
|
-
proto: 'http',
|
|
7
|
-
web_addr: 'localhost:4041',
|
|
8
|
-
addr: 4041,
|
|
9
|
-
subdomain: process.argv[2],
|
|
10
|
-
onLogEvent: (event) => {
|
|
11
|
-
console.log('Ngrok - ', event);
|
|
12
|
-
}
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
console.log('')
|
|
16
|
-
console.log('')
|
|
17
|
-
console.log('------------------------------------------')
|
|
18
|
-
console.log('')
|
|
19
|
-
console.info(`Public URL for Seeka app is exposed by Ngrok`)
|
|
20
|
-
console.log('')
|
|
21
|
-
console.info(`${url}/api/webhook/seeka/app`)
|
|
22
|
-
console.log('')
|
|
23
|
-
console.info(`Use this URL in your Seeka app configuration for testing`)
|
|
24
|
-
console.log('')
|
|
25
|
-
console.log('------------------------------------------')
|
|
26
|
-
console.log('')
|
|
27
|
-
console.log('')
|
|
28
|
-
})();
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { Context, Handler } from 'aws-lambda';
|
|
2
|
-
import bodyParser from 'body-parser';
|
|
3
|
-
import express from 'express';
|
|
4
|
-
import serverless from 'serverless-http';
|
|
5
|
-
|
|
6
|
-
import { seekaAppWebhook } from './routes/seekaAppWebhook';
|
|
7
|
-
|
|
8
|
-
const app = express();
|
|
9
|
-
|
|
10
|
-
app.post('/api/webhook/seeka/app', bodyParser.text({ type: '*/*' }), async (req, res) => {
|
|
11
|
-
await seekaAppWebhook(req, res, {} as Context);
|
|
12
|
-
})
|
|
13
|
-
|
|
14
|
-
app.get('/api/webhook/seeka/app', async (req, res) => {
|
|
15
|
-
res.status(404).json({ error: "Must use POST" }).send();
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
const serverlessHandler = serverless(app, {
|
|
19
|
-
provider: 'aws'
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
const startServer = async () => {
|
|
23
|
-
app.listen(4041, () => {
|
|
24
|
-
console.log("listening on port 4041!");
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
startServer();
|
|
29
|
-
|
|
30
|
-
export const handler: Handler = async (event, context) => {
|
|
31
|
-
const response = serverlessHandler(event, context);
|
|
32
|
-
return response;
|
|
33
|
-
};
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import { Context } from 'aws-lambda';
|
|
2
|
-
import * as winston from 'winston';
|
|
3
|
-
|
|
4
|
-
import { SeqTransport } from '@datalust/winston-seq';
|
|
5
|
-
|
|
6
|
-
import * as packageJson from '../../../package.json';
|
|
7
|
-
|
|
8
|
-
import type {
|
|
9
|
-
SeekaWebhookPayload, SeekaWebhookPayloadOfSeekaAppWebhookContext
|
|
10
|
-
} from '@seeka-labs/sdk-apps-server';
|
|
11
|
-
|
|
12
|
-
const loggerTransports: winston.transport[] = [
|
|
13
|
-
new winston.transports.Console({
|
|
14
|
-
level: process.env.LOGGING_LEVEL,
|
|
15
|
-
format: winston.format.combine(
|
|
16
|
-
winston.format.errors({ stack: true }),
|
|
17
|
-
winston.format.cli(),
|
|
18
|
-
winston.format.splat(),
|
|
19
|
-
),
|
|
20
|
-
handleExceptions: true,
|
|
21
|
-
handleRejections: true,
|
|
22
|
-
}),
|
|
23
|
-
]
|
|
24
|
-
if (process.env.LOGGING_SEQ_SERVERURL) {
|
|
25
|
-
loggerTransports.push(
|
|
26
|
-
new SeqTransport({
|
|
27
|
-
level: process.env.LOGGING_LEVEL,
|
|
28
|
-
serverUrl: process.env.LOGGING_SEQ_SERVERURL,
|
|
29
|
-
apiKey: process.env.LOGGING_SEQ_APIKEY,
|
|
30
|
-
onError: ((e: any) => { console.error('Failed to configure Seq logging transport', e) }),
|
|
31
|
-
format: winston.format.combine(
|
|
32
|
-
winston.format.errors({ stack: true }),
|
|
33
|
-
winston.format.json(),
|
|
34
|
-
),
|
|
35
|
-
handleExceptions: true,
|
|
36
|
-
handleRejections: true,
|
|
37
|
-
})
|
|
38
|
-
)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
let logger: winston.Logger | null = null;
|
|
42
|
-
|
|
43
|
-
const createLogger = () => winston.createLogger({
|
|
44
|
-
level: process.env.LOGGING_LEVEL,
|
|
45
|
-
defaultMeta: {
|
|
46
|
-
seekaAppId: process.env.SEEKA_APP_ID,
|
|
47
|
-
Hosting_Provider: 'aws',
|
|
48
|
-
Release_Version: `v${packageJson.version}`,
|
|
49
|
-
Hosting_Region: process.env.AWS_REGION,
|
|
50
|
-
Aws_Xray_TraceId: process.env._X_AMZN_TRACE_ID,
|
|
51
|
-
Aws_Lambda_FunctionName: process.env.AWS_LAMBDA_FUNCTION_NAME,
|
|
52
|
-
Service: `app/${packageJson.name}`,
|
|
53
|
-
},
|
|
54
|
-
transports: loggerTransports,
|
|
55
|
-
exitOnError: false,
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
export const getLogger = () => {
|
|
59
|
-
if (!logger || logger.closed) {
|
|
60
|
-
// If the AWS lambda host is reused then the logger will be closed and we need to recreate it
|
|
61
|
-
logger = createLogger();
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return logger;
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
export const childLogger = (meta: object) => getLogger().child(meta);
|
|
68
|
-
|
|
69
|
-
export const webhookLogger = (payload: SeekaWebhookPayload, functionContext: Context) => {
|
|
70
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
71
|
-
const meta: any = {
|
|
72
|
-
seekaWebhookType: payload.type,
|
|
73
|
-
seekaWebhookIsTest: payload.isTest,
|
|
74
|
-
RequestId: payload.requestId,
|
|
75
|
-
AwsLambda_RequestId: functionContext.awsRequestId,
|
|
76
|
-
CausationId: payload.causationId,
|
|
77
|
-
CorrelationId: payload.causationId,
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const context = (payload as SeekaWebhookPayloadOfSeekaAppWebhookContext).context;
|
|
81
|
-
if (context) {
|
|
82
|
-
meta.seekaAppInstallId = context.applicationInstallId;
|
|
83
|
-
meta.seekaAppInstallOrganisationBrandId = context.organisationBrandId;
|
|
84
|
-
meta.seekaAppInstallOrganisationId = context.organisationId;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return childLogger(meta)
|
|
88
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import winston, { Logger } from 'winston';
|
|
2
|
-
|
|
3
|
-
import { connect, disconnect, isConnected } from '../state/redis';
|
|
4
|
-
|
|
5
|
-
export const startServices = async (logger: Logger) => {
|
|
6
|
-
logger.debug(`Trying to connect to Redis - ${process.env.REDIS_CONNECTION_HOST}`)
|
|
7
|
-
try {
|
|
8
|
-
if (isConnected()) {
|
|
9
|
-
logger.verbose(`Redis already connected - ${process.env.REDIS_CONNECTION_HOST}`)
|
|
10
|
-
}
|
|
11
|
-
else {
|
|
12
|
-
logger.profile('service.redis.connect')
|
|
13
|
-
await connect();
|
|
14
|
-
logger.profile('service.redis.connect')
|
|
15
|
-
logger.debug(`Redis connected - ${process.env.REDIS_CONNECTION_HOST}`)
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
catch (err) {
|
|
19
|
-
logger.error(`Failed to connect to Redis - ${process.env.REDIS_CONNECTION_HOST}`, { ex: winston.exceptions.getAllInfo(err as any) })
|
|
20
|
-
throw err;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export const stopServices = async (logger: Logger) => {
|
|
25
|
-
logger.debug(`Trying to disconnect from Redis - ${process.env.REDIS_CONNECTION_HOST}`)
|
|
26
|
-
try {
|
|
27
|
-
if (isConnected() === false) {
|
|
28
|
-
logger.verbose(`Redis already disconnected - ${process.env.REDIS_CONNECTION_HOST}`)
|
|
29
|
-
}
|
|
30
|
-
else {
|
|
31
|
-
logger.profile('service.redis.disconnect')
|
|
32
|
-
await disconnect();
|
|
33
|
-
logger.profile('service.redis.disconnect')
|
|
34
|
-
logger.debug(`Redis disconnected - ${process.env.REDIS_CONNECTION_HOST}`)
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
catch (err) {
|
|
38
|
-
logger.error(`Failed to disconnect from Redis - ${process.env.REDIS_CONNECTION_HOST}`, { ex: winston.exceptions.getAllInfo(err as any) })
|
|
39
|
-
throw err;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { createClient } from 'redis';
|
|
2
|
-
|
|
3
|
-
import { getLogger } from '../../logging';
|
|
4
|
-
import winston from 'winston';
|
|
5
|
-
|
|
6
|
-
const redisProtocol = process.env.REDIS_CONNECTION_TLS === 'true' ? 'rediss://' : 'redis://';
|
|
7
|
-
const redisConn = `${redisProtocol}${process.env.REDIS_CONNECTION_USER}:${process.env.REDIS_CONNECTION_PASSWORD}@${process.env.REDIS_CONNECTION_HOST}:${process.env.REDIS_CONNECTION_PORT}`;
|
|
8
|
-
|
|
9
|
-
const redisClient = createClient({
|
|
10
|
-
url: redisConn
|
|
11
|
-
})
|
|
12
|
-
.on('error', (err: any) => getLogger().error('Redis Client ', { ex: winston.exceptions.getAllInfo(err) }));
|
|
13
|
-
|
|
14
|
-
export const connect = async () => {
|
|
15
|
-
await redisClient.connect();
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export const isConnected = () => {
|
|
19
|
-
return redisClient.isOpen;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export const disconnect = async () => {
|
|
23
|
-
await redisClient.disconnect();
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const getKeyPrefix = (stateType: string) => `seeka:app:${process.env.SEEKA_APP_ID}:${stateType}`
|
|
27
|
-
const getKey = (stateType: string, key: string) => `${getKeyPrefix(stateType)}:${key}`
|
|
28
|
-
|
|
29
|
-
export async function getOrCreate<TState>(stateType: string, key: string, toCreate: TState): Promise<TState> {
|
|
30
|
-
const fullKey = getKey(stateType, key);
|
|
31
|
-
const existingStr = await redisClient.get(fullKey);
|
|
32
|
-
if (existingStr) return JSON.parse(existingStr);
|
|
33
|
-
|
|
34
|
-
await redisClient.set(fullKey, JSON.stringify(toCreate));
|
|
35
|
-
|
|
36
|
-
return toCreate;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export async function tryGet<TState>(stateType: string, key: string): Promise<TState | null> {
|
|
40
|
-
const fullKey = getKey(stateType, key);
|
|
41
|
-
const existingStr = await redisClient.get(fullKey);
|
|
42
|
-
if (existingStr) return JSON.parse(existingStr);
|
|
43
|
-
|
|
44
|
-
return null;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export async function getList<TState>(stateType: string): Promise<TState[]> {
|
|
48
|
-
const prefix = getKeyPrefix(stateType);
|
|
49
|
-
const allKeys = await redisClient.keys(`${prefix}:*`);
|
|
50
|
-
const listStr = await redisClient.mGet(allKeys);
|
|
51
|
-
|
|
52
|
-
if (listStr) return listStr.filter(e => Boolean(e)).map(e => JSON.parse(e as string));
|
|
53
|
-
|
|
54
|
-
return [];
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export async function set<TState>(stateType: string, key: string, toCreate: TState): Promise<void> {
|
|
58
|
-
const fullKey = getKey(stateType, key);
|
|
59
|
-
await redisClient.set(fullKey, JSON.stringify(toCreate));
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export async function remove(stateType: string, key: string): Promise<void> {
|
|
63
|
-
const fullKey = getKey(stateType, key);
|
|
64
|
-
await redisClient.del(fullKey);
|
|
65
|
-
}
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import type { Logger } from 'winston';
|
|
2
|
-
|
|
3
|
-
import { getList, remove, set, tryGet } from '../../state/redis';
|
|
4
|
-
|
|
5
|
-
export interface SeekaAppInstallState {
|
|
6
|
-
/** ID of the organisation that installed the app */
|
|
7
|
-
organisationId: string;
|
|
8
|
-
/** ID of the brand that installed the app */
|
|
9
|
-
organisationBrandId: string;
|
|
10
|
-
/** ID of the installation of the app */
|
|
11
|
-
applicationInstallId: string;
|
|
12
|
-
// Installation settings provided by the user installing the app
|
|
13
|
-
installationSettings: SampleAppInstallSettings;
|
|
14
|
-
// State relating to the app and installation of the app
|
|
15
|
-
installationState: SampleAppInstallState;
|
|
16
|
-
|
|
17
|
-
// When the app was installed
|
|
18
|
-
installedAt: string; // new Date().toISOString()
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export interface SampleAppInstallState {
|
|
22
|
-
stateItem1?: string
|
|
23
|
-
stateItem2?: string
|
|
24
|
-
grantedPermissions?: string[]
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export type SampleAppInstallSettings = { [key: string]: any; } | {
|
|
28
|
-
myAppInstallSetting1: string | number | undefined;
|
|
29
|
-
myAppInstallSetting2: string | number | undefined;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const stateType = 'install'
|
|
33
|
-
|
|
34
|
-
export const tryGetInstallation = async (applicationInstallId: string, throwWhenNotFound: boolean, logger: Logger): Promise<SeekaAppInstallState | null> => {
|
|
35
|
-
const installation = await tryGet<SeekaAppInstallState>(stateType, applicationInstallId);
|
|
36
|
-
if (installation == null && throwWhenNotFound) {
|
|
37
|
-
throw new Error(`Seeka installation ${applicationInstallId} not found`);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return installation;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export const listInstallations = async (logger: Logger): Promise<SeekaAppInstallState[]> => {
|
|
44
|
-
const installations = await getList<SeekaAppInstallState>(stateType);
|
|
45
|
-
|
|
46
|
-
return installations;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
export const createOrUpdateInstallation = async (state: SeekaAppInstallState, logger: Logger): Promise<SeekaAppInstallState> => {
|
|
51
|
-
if (!state.installationState) state.installationState = {};
|
|
52
|
-
if (!state.installedAt) state.installedAt = new Date().toISOString();
|
|
53
|
-
|
|
54
|
-
const creating = (await tryGetInstallation(state.applicationInstallId, false, logger)) === null;
|
|
55
|
-
|
|
56
|
-
await set(stateType, state.applicationInstallId, state);
|
|
57
|
-
|
|
58
|
-
logger.info(creating ? 'Created installation state' : 'Updated installation state', { applicationInstallId: state.applicationInstallId, organisationId: state.organisationId, organisationBrandId: state.organisationBrandId });
|
|
59
|
-
|
|
60
|
-
return state;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export const deleteInstallation = async (applicationInstallId: string, logger: Logger): Promise<void> => {
|
|
64
|
-
await remove(stateType, applicationInstallId);
|
|
65
|
-
|
|
66
|
-
logger.info('Deleted installation state', { applicationInstallId });
|
|
67
|
-
}
|