@seeka-labs/cli-apps 1.1.24 → 1.1.26
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/LICENSE +19 -19
- package/dist/index.js +10 -10
- package/dist/index.js.map +4 -4
- package/dist/init-templates/aws-lambda/.example.gitignore +48 -48
- package/dist/init-templates/aws-lambda/.gitlab-ci.yml +23 -23
- package/dist/init-templates/aws-lambda/.nvmrc +1 -1
- package/dist/init-templates/aws-lambda/README.md +76 -76
- package/dist/init-templates/aws-lambda/jest.config.js +4 -4
- package/dist/init-templates/aws-lambda/package.json +51 -54
- package/dist/init-templates/aws-lambda/src/index.test.ts +6 -6
- package/dist/init-templates/aws-lambda/src/lib/logging/index.ts +87 -87
- package/dist/init-templates/aws-lambda/src/lib/state/redis/index.ts +64 -64
- package/dist/init-templates/aws-lambda/src/lib/state/seeka/installations.ts +66 -66
- package/dist/init-templates/aws-lambda/src/routes/seekaAppWebhook.ts +193 -193
- package/dist/init-templates/azure-function/.example.gitignore +47 -47
- package/dist/init-templates/azure-function/README.md +107 -107
- package/dist/init-templates/azure-function/jest.config.js +4 -4
- package/dist/init-templates/azure-function/package.json +45 -48
- package/dist/init-templates/azure-function/scripts/dev-queue-setup.js +29 -29
- package/dist/init-templates/azure-function/src/functions/healthCheck.ts +13 -13
- package/dist/init-templates/azure-function/src/functions/pollingExample.ts +39 -39
- package/dist/init-templates/azure-function/src/functions/queueExample.ts +66 -66
- package/dist/init-templates/azure-function/src/functions/seekaAppWebhook.ts +236 -236
- package/dist/init-templates/azure-function/src/index.test.ts +6 -6
- package/dist/init-templates/azure-function/src/lib/browser/index.ts +54 -54
- package/dist/init-templates/azure-function/src/lib/browser/models/index.ts +6 -6
- package/dist/init-templates/azure-function/src/lib/jobs/index.ts +95 -95
- package/dist/init-templates/azure-function/src/lib/logging/index.ts +92 -92
- package/dist/init-templates/azure-function/src/lib/state/redis/index.ts +64 -64
- package/dist/init-templates/azure-function/src/lib/state/seeka/installations.ts +66 -66
- package/dist/init-templates/browser/.editorconfig +14 -14
- package/dist/init-templates/browser/.eslintrc.cjs +1 -1
- package/dist/init-templates/browser/.yarnrc +1 -1
- package/dist/init-templates/browser/jest.config.js +11 -11
- package/dist/init-templates/browser/package.json +3 -3
- package/dist/init-templates/browser/scripts/esbuild/build-browser-plugin.mjs +110 -110
- package/dist/init-templates/browser/scripts/esbuild/plugins/importAsGlobals.mjs +38 -38
- package/dist/init-templates/browser/src/browser.ts +12 -12
- package/dist/init-templates/browser/src/plugin/index.test.ts +6 -6
- package/dist/init-templates/browser/src/plugin/index.ts +49 -49
- package/dist/init-templates/browser/tsconfig.json +34 -34
- package/dist/init-templates/netlify-function/.env.example +17 -17
- package/dist/init-templates/netlify-function/.example.gitignore +36 -36
- package/dist/init-templates/netlify-function/.nvmrc +1 -1
- package/dist/init-templates/netlify-function/.vscode/launch.json +44 -44
- package/dist/init-templates/netlify-function/README.md +61 -61
- package/dist/init-templates/netlify-function/jest.config.js +4 -4
- package/dist/init-templates/netlify-function/netlify.toml +6 -6
- package/dist/init-templates/netlify-function/package.json +11 -14
- package/dist/init-templates/netlify-function/src/api/example-job-background/index.ts +51 -51
- package/dist/init-templates/netlify-function/src/api/polling-example-job-scheduled/index.ts +45 -45
- package/dist/init-templates/netlify-function/src/api/seeka-app-webhook/index.ts +216 -216
- package/dist/init-templates/netlify-function/src/index.test.ts +6 -6
- package/dist/init-templates/netlify-function/src/lib/jobs/index.ts +67 -67
- package/dist/init-templates/netlify-function/src/lib/logging/index.ts +90 -90
- package/dist/init-templates/netlify-function/src/lib/state/redis/index.ts +64 -64
- package/dist/init-templates/netlify-function/src/lib/state/seeka/installations.ts +66 -66
- package/package.json +7 -7
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"allowJs": false,
|
|
4
|
-
"target": "ESNext",
|
|
5
|
-
"module": "ESNext",
|
|
6
|
-
"resolveJsonModule": true,
|
|
7
|
-
"moduleResolution": "node",
|
|
8
|
-
"noEmit": true,
|
|
9
|
-
"strict": true,
|
|
10
|
-
"noImplicitAny": false,
|
|
11
|
-
"strictNullChecks": true,
|
|
12
|
-
"strictFunctionTypes": true,
|
|
13
|
-
"noUnusedLocals": false,
|
|
14
|
-
"noUnusedParameters": false,
|
|
15
|
-
"noImplicitReturns": true,
|
|
16
|
-
"noFallthroughCasesInSwitch": true,
|
|
17
|
-
"importHelpers": true,
|
|
18
|
-
"skipLibCheck": true,
|
|
19
|
-
"esModuleInterop": true,
|
|
20
|
-
"allowSyntheticDefaultImports": true,
|
|
21
|
-
"experimentalDecorators": true,
|
|
22
|
-
"sourceMap": true,
|
|
23
|
-
"types": [
|
|
24
|
-
"node",
|
|
25
|
-
"jest"
|
|
26
|
-
],
|
|
27
|
-
"lib": [
|
|
28
|
-
"ES6",
|
|
29
|
-
"DOM"
|
|
30
|
-
]
|
|
31
|
-
},
|
|
32
|
-
"include": [
|
|
33
|
-
"src/browser.ts",
|
|
34
|
-
]
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"allowJs": false,
|
|
4
|
+
"target": "ESNext",
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"resolveJsonModule": true,
|
|
7
|
+
"moduleResolution": "node",
|
|
8
|
+
"noEmit": true,
|
|
9
|
+
"strict": true,
|
|
10
|
+
"noImplicitAny": false,
|
|
11
|
+
"strictNullChecks": true,
|
|
12
|
+
"strictFunctionTypes": true,
|
|
13
|
+
"noUnusedLocals": false,
|
|
14
|
+
"noUnusedParameters": false,
|
|
15
|
+
"noImplicitReturns": true,
|
|
16
|
+
"noFallthroughCasesInSwitch": true,
|
|
17
|
+
"importHelpers": true,
|
|
18
|
+
"skipLibCheck": true,
|
|
19
|
+
"esModuleInterop": true,
|
|
20
|
+
"allowSyntheticDefaultImports": true,
|
|
21
|
+
"experimentalDecorators": true,
|
|
22
|
+
"sourceMap": true,
|
|
23
|
+
"types": [
|
|
24
|
+
"node",
|
|
25
|
+
"jest"
|
|
26
|
+
],
|
|
27
|
+
"lib": [
|
|
28
|
+
"ES6",
|
|
29
|
+
"DOM"
|
|
30
|
+
]
|
|
31
|
+
},
|
|
32
|
+
"include": [
|
|
33
|
+
"src/browser.ts",
|
|
34
|
+
]
|
|
35
35
|
}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
SEEKA_APP_ID=
|
|
2
|
-
SEEKA_APP_SECRET=
|
|
3
|
-
SEEKA_DEBUG_ENABLED=true
|
|
4
|
-
SEEKA_INGEST_URL=
|
|
5
|
-
SEEKA_ISSUER_URL=
|
|
6
|
-
NODE_TLS_REJECT_UNAUTHORIZED=1
|
|
7
|
-
NETLIFY_ENABLED=false
|
|
8
|
-
NETLIFY_SITE_NAME=
|
|
9
|
-
REDIS_CONNECTION_USER=default
|
|
10
|
-
REDIS_CONNECTION_PASSWORD=
|
|
11
|
-
REDIS_CONNECTION_TLS=true
|
|
12
|
-
REDIS_CONNECTION_HOST=
|
|
13
|
-
REDIS_CONNECTION_PORT=
|
|
14
|
-
LOGGING_SEQ_SERVERURL=
|
|
15
|
-
LOGGING_SEQ_APIKEY=
|
|
16
|
-
LOGGING_LEVEL=silly
|
|
17
|
-
ENCRYPTION_SECRET=
|
|
1
|
+
SEEKA_APP_ID=
|
|
2
|
+
SEEKA_APP_SECRET=
|
|
3
|
+
SEEKA_DEBUG_ENABLED=true
|
|
4
|
+
SEEKA_INGEST_URL=
|
|
5
|
+
SEEKA_ISSUER_URL=
|
|
6
|
+
NODE_TLS_REJECT_UNAUTHORIZED=1
|
|
7
|
+
NETLIFY_ENABLED=false
|
|
8
|
+
NETLIFY_SITE_NAME=
|
|
9
|
+
REDIS_CONNECTION_USER=default
|
|
10
|
+
REDIS_CONNECTION_PASSWORD=
|
|
11
|
+
REDIS_CONNECTION_TLS=true
|
|
12
|
+
REDIS_CONNECTION_HOST=
|
|
13
|
+
REDIS_CONNECTION_PORT=
|
|
14
|
+
LOGGING_SEQ_SERVERURL=
|
|
15
|
+
LOGGING_SEQ_APIKEY=
|
|
16
|
+
LOGGING_LEVEL=silly
|
|
17
|
+
ENCRYPTION_SECRET=
|
|
18
18
|
INBOUND_HTTP_CALL_API_KEY=
|
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
# Local Netlify folder
|
|
2
|
-
.netlify
|
|
3
|
-
.env
|
|
4
|
-
|
|
5
|
-
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
|
6
|
-
|
|
7
|
-
# dependencies
|
|
8
|
-
/node_modules
|
|
9
|
-
/.pnp
|
|
10
|
-
.pnp.js
|
|
11
|
-
.yarn/install-state.gz
|
|
12
|
-
|
|
13
|
-
# testing
|
|
14
|
-
/coverage
|
|
15
|
-
|
|
16
|
-
# production
|
|
17
|
-
/build
|
|
18
|
-
/dist
|
|
19
|
-
|
|
20
|
-
# misc
|
|
21
|
-
.DS_Store
|
|
22
|
-
*.pem
|
|
23
|
-
|
|
24
|
-
# debug
|
|
25
|
-
npm-debug.log*
|
|
26
|
-
yarn-debug.log*
|
|
27
|
-
yarn-error.log*
|
|
28
|
-
|
|
29
|
-
# local env files
|
|
30
|
-
.env*.local
|
|
31
|
-
|
|
32
|
-
# vercel
|
|
33
|
-
.vercel
|
|
34
|
-
|
|
35
|
-
# typescript
|
|
36
|
-
*.tsbuildinfo
|
|
1
|
+
# Local Netlify folder
|
|
2
|
+
.netlify
|
|
3
|
+
.env
|
|
4
|
+
|
|
5
|
+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
|
6
|
+
|
|
7
|
+
# dependencies
|
|
8
|
+
/node_modules
|
|
9
|
+
/.pnp
|
|
10
|
+
.pnp.js
|
|
11
|
+
.yarn/install-state.gz
|
|
12
|
+
|
|
13
|
+
# testing
|
|
14
|
+
/coverage
|
|
15
|
+
|
|
16
|
+
# production
|
|
17
|
+
/build
|
|
18
|
+
/dist
|
|
19
|
+
|
|
20
|
+
# misc
|
|
21
|
+
.DS_Store
|
|
22
|
+
*.pem
|
|
23
|
+
|
|
24
|
+
# debug
|
|
25
|
+
npm-debug.log*
|
|
26
|
+
yarn-debug.log*
|
|
27
|
+
yarn-error.log*
|
|
28
|
+
|
|
29
|
+
# local env files
|
|
30
|
+
.env*.local
|
|
31
|
+
|
|
32
|
+
# vercel
|
|
33
|
+
.vercel
|
|
34
|
+
|
|
35
|
+
# typescript
|
|
36
|
+
*.tsbuildinfo
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
v20
|
|
@@ -1,45 +1,45 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": "0.2.0",
|
|
3
|
-
"configurations": [
|
|
4
|
-
{
|
|
5
|
-
"name": "netlify dev",
|
|
6
|
-
"type": "node",
|
|
7
|
-
"request": "launch",
|
|
8
|
-
"skipFiles": [
|
|
9
|
-
"<node_internals>/**"
|
|
10
|
-
],
|
|
11
|
-
"outFiles": [
|
|
12
|
-
"${workspaceFolder}/.netlify/functions-serve/**/*.js"
|
|
13
|
-
],
|
|
14
|
-
"program": "${workspaceFolder}/node_modules/.bin/netlify",
|
|
15
|
-
"args": [
|
|
16
|
-
"dev"
|
|
17
|
-
],
|
|
18
|
-
"console": "integratedTerminal",
|
|
19
|
-
"env": {
|
|
20
|
-
"BROWSER": "none"
|
|
21
|
-
},
|
|
22
|
-
"serverReadyAction": {
|
|
23
|
-
"pattern": "Server now ready on (https?://[\\w:.-]+)",
|
|
24
|
-
"uriFormat": "%s",
|
|
25
|
-
"action": "debugWithChrome"
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
"name": "netlify functions:serve",
|
|
30
|
-
"type": "node",
|
|
31
|
-
"request": "launch",
|
|
32
|
-
"skipFiles": [
|
|
33
|
-
"<node_internals>/**"
|
|
34
|
-
],
|
|
35
|
-
"outFiles": [
|
|
36
|
-
"${workspaceFolder}/.netlify/functions-serve/**/*.js"
|
|
37
|
-
],
|
|
38
|
-
"program": "${workspaceFolder}/node_modules/.bin/netlify",
|
|
39
|
-
"args": [
|
|
40
|
-
"functions:serve"
|
|
41
|
-
],
|
|
42
|
-
"console": "integratedTerminal"
|
|
43
|
-
}
|
|
44
|
-
]
|
|
1
|
+
{
|
|
2
|
+
"version": "0.2.0",
|
|
3
|
+
"configurations": [
|
|
4
|
+
{
|
|
5
|
+
"name": "netlify dev",
|
|
6
|
+
"type": "node",
|
|
7
|
+
"request": "launch",
|
|
8
|
+
"skipFiles": [
|
|
9
|
+
"<node_internals>/**"
|
|
10
|
+
],
|
|
11
|
+
"outFiles": [
|
|
12
|
+
"${workspaceFolder}/.netlify/functions-serve/**/*.js"
|
|
13
|
+
],
|
|
14
|
+
"program": "${workspaceFolder}/node_modules/.bin/netlify",
|
|
15
|
+
"args": [
|
|
16
|
+
"dev"
|
|
17
|
+
],
|
|
18
|
+
"console": "integratedTerminal",
|
|
19
|
+
"env": {
|
|
20
|
+
"BROWSER": "none"
|
|
21
|
+
},
|
|
22
|
+
"serverReadyAction": {
|
|
23
|
+
"pattern": "Server now ready on (https?://[\\w:.-]+)",
|
|
24
|
+
"uriFormat": "%s",
|
|
25
|
+
"action": "debugWithChrome"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"name": "netlify functions:serve",
|
|
30
|
+
"type": "node",
|
|
31
|
+
"request": "launch",
|
|
32
|
+
"skipFiles": [
|
|
33
|
+
"<node_internals>/**"
|
|
34
|
+
],
|
|
35
|
+
"outFiles": [
|
|
36
|
+
"${workspaceFolder}/.netlify/functions-serve/**/*.js"
|
|
37
|
+
],
|
|
38
|
+
"program": "${workspaceFolder}/node_modules/.bin/netlify",
|
|
39
|
+
"args": [
|
|
40
|
+
"functions:serve"
|
|
41
|
+
],
|
|
42
|
+
"console": "integratedTerminal"
|
|
43
|
+
}
|
|
44
|
+
]
|
|
45
45
|
}
|
|
@@ -1,62 +1,62 @@
|
|
|
1
|
-
# Seeka app - Netlify functions
|
|
2
|
-
|
|
3
|
-
## Development
|
|
4
|
-
|
|
5
|
-
- `yarn install`
|
|
6
|
-
- `yarn dev`
|
|
7
|
-
|
|
8
|
-
### Dependencies
|
|
9
|
-
- Python >=3.6.0 - https://www.python.org/downloads/ or `choco install python`
|
|
10
|
-
|
|
11
|
-
### Invoking functions
|
|
12
|
-
Run `yarn dev:netlify:invoke:polling-example-job-scheduled` to trigger scheduled job which triggers multiple background jobs, 1 for each installation of the app
|
|
13
|
-
|
|
14
|
-
### Debugging / local development before deployment
|
|
15
|
-
- This template uses [Netlify's live url debugging](https://answers.netlify.com/t/netlify-dev-with-support-for-custom-live-urls/101261)
|
|
16
|
-
- Supports VSCode debugging - See `.vscode/launch.json`. This is only supported on Linux. If using Windows then use WSL with an Ubuntu distro for support of attaching the VS code debugger
|
|
17
|
-
|
|
18
|
-
## Logging
|
|
19
|
-
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.
|
|
20
|
-
|
|
21
|
-
[Seq](https://datalust.co/seq) Winston transport is installed in this template (optional).
|
|
22
|
-
|
|
23
|
-
To configure Seq options, see `_SEQ_` environment variables.
|
|
24
|
-
|
|
25
|
-
To install Seq on your development machine
|
|
26
|
-
1. Run `docker run --name seq -d --restart=always -e ACCEPT_EULA=Y -p 5341:80 datalust/seq:2024.2`
|
|
27
|
-
2. Update your `LOGGING_SEQ_SERVERURL` environment variable to `http://localhost:5341` or `http://[YOUR MACHINE NAME].local:5341` if using WSL.
|
|
28
|
-
|
|
29
|
-
If creating an API key for Seq, only permission that is required is `Ingest`.
|
|
30
|
-
|
|
31
|
-
## State management
|
|
32
|
-
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.
|
|
33
|
-
|
|
34
|
-
### Upstash (optional)
|
|
35
|
-
If you dont want to use Upstash for Redis then the connection strings in `.env` can be swapped with your Redis instance.
|
|
36
|
-
|
|
37
|
-
> If using Upstash then create a database before following the below guide to deploying your Netlify function.
|
|
38
|
-
|
|
39
|
-
> When choosing region - use US East (Ohio) - us-east-* as this is the same AWS region that the free Netlify functions run from. If not on the Netlify free plan, select the closest Upstash region that your Netlify function is hosted in to reduce latency between the function and the Redis database.
|
|
40
|
-
|
|
41
|
-
> Considerations - max connection limit (1000) of Upstash connections in relation to concurrent execution count of the Netlify functions
|
|
42
|
-
|
|
43
|
-
## Deployment
|
|
44
|
-
This project comes ready to deploy for free to Netlify with a database and queues backed by Redis hosted by Upstash.
|
|
45
|
-
|
|
46
|
-
At the point of writing, Netlify and Upstash can be used to deploy your app for free.
|
|
47
|
-
- https://upstash.com/pricing
|
|
48
|
-
- https://www.netlify.com/pricing/
|
|
49
|
-
|
|
50
|
-
### Deployment to Netlify
|
|
51
|
-
#### From your local machine
|
|
52
|
-
- `yarn deploy`
|
|
53
|
-
|
|
54
|
-
#### Using Netlify continuous delivery
|
|
55
|
-
See the [Netlify docs](https://docs.netlify.com/functions/deploy/?fn-language=ts)
|
|
56
|
-
|
|
57
|
-
## Considerations when using this template
|
|
58
|
-
Each call to the netlify function will create a new connection to the database/Redis as calls to the Netlify function in quick succession will not share a single "warm" function host which is supported by Azure Functions and AWS Lambda.
|
|
59
|
-
|
|
60
|
-
## References
|
|
61
|
-
- https://docs.netlify.com/cli/get-started/
|
|
1
|
+
# Seeka app - Netlify functions
|
|
2
|
+
|
|
3
|
+
## Development
|
|
4
|
+
|
|
5
|
+
- `yarn install`
|
|
6
|
+
- `yarn dev`
|
|
7
|
+
|
|
8
|
+
### Dependencies
|
|
9
|
+
- Python >=3.6.0 - https://www.python.org/downloads/ or `choco install python`
|
|
10
|
+
|
|
11
|
+
### Invoking functions
|
|
12
|
+
Run `yarn dev:netlify:invoke:polling-example-job-scheduled` to trigger scheduled job which triggers multiple background jobs, 1 for each installation of the app
|
|
13
|
+
|
|
14
|
+
### Debugging / local development before deployment
|
|
15
|
+
- This template uses [Netlify's live url debugging](https://answers.netlify.com/t/netlify-dev-with-support-for-custom-live-urls/101261)
|
|
16
|
+
- Supports VSCode debugging - See `.vscode/launch.json`. This is only supported on Linux. If using Windows then use WSL with an Ubuntu distro for support of attaching the VS code debugger
|
|
17
|
+
|
|
18
|
+
## Logging
|
|
19
|
+
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.
|
|
20
|
+
|
|
21
|
+
[Seq](https://datalust.co/seq) Winston transport is installed in this template (optional).
|
|
22
|
+
|
|
23
|
+
To configure Seq options, see `_SEQ_` environment variables.
|
|
24
|
+
|
|
25
|
+
To install Seq on your development machine
|
|
26
|
+
1. Run `docker run --name seq -d --restart=always -e ACCEPT_EULA=Y -p 5341:80 datalust/seq:2024.2`
|
|
27
|
+
2. Update your `LOGGING_SEQ_SERVERURL` environment variable to `http://localhost:5341` or `http://[YOUR MACHINE NAME].local:5341` if using WSL.
|
|
28
|
+
|
|
29
|
+
If creating an API key for Seq, only permission that is required is `Ingest`.
|
|
30
|
+
|
|
31
|
+
## State management
|
|
32
|
+
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.
|
|
33
|
+
|
|
34
|
+
### Upstash (optional)
|
|
35
|
+
If you dont want to use Upstash for Redis then the connection strings in `.env` can be swapped with your Redis instance.
|
|
36
|
+
|
|
37
|
+
> If using Upstash then create a database before following the below guide to deploying your Netlify function.
|
|
38
|
+
|
|
39
|
+
> When choosing region - use US East (Ohio) - us-east-* as this is the same AWS region that the free Netlify functions run from. If not on the Netlify free plan, select the closest Upstash region that your Netlify function is hosted in to reduce latency between the function and the Redis database.
|
|
40
|
+
|
|
41
|
+
> Considerations - max connection limit (1000) of Upstash connections in relation to concurrent execution count of the Netlify functions
|
|
42
|
+
|
|
43
|
+
## Deployment
|
|
44
|
+
This project comes ready to deploy for free to Netlify with a database and queues backed by Redis hosted by Upstash.
|
|
45
|
+
|
|
46
|
+
At the point of writing, Netlify and Upstash can be used to deploy your app for free.
|
|
47
|
+
- https://upstash.com/pricing
|
|
48
|
+
- https://www.netlify.com/pricing/
|
|
49
|
+
|
|
50
|
+
### Deployment to Netlify
|
|
51
|
+
#### From your local machine
|
|
52
|
+
- `yarn deploy`
|
|
53
|
+
|
|
54
|
+
#### Using Netlify continuous delivery
|
|
55
|
+
See the [Netlify docs](https://docs.netlify.com/functions/deploy/?fn-language=ts)
|
|
56
|
+
|
|
57
|
+
## Considerations when using this template
|
|
58
|
+
Each call to the netlify function will create a new connection to the database/Redis as calls to the Netlify function in quick succession will not share a single "warm" function host which is supported by Azure Functions and AWS Lambda.
|
|
59
|
+
|
|
60
|
+
## References
|
|
61
|
+
- https://docs.netlify.com/cli/get-started/
|
|
62
62
|
- https://docs.netlify.com/functions/get-started/?fn-language=ts
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
/** @type {import('ts-jest').JestConfigWithTsJest} */
|
|
2
|
-
module.exports = {
|
|
3
|
-
preset: 'ts-jest',
|
|
4
|
-
testEnvironment: 'node',
|
|
1
|
+
/** @type {import('ts-jest').JestConfigWithTsJest} */
|
|
2
|
+
module.exports = {
|
|
3
|
+
preset: 'ts-jest',
|
|
4
|
+
testEnvironment: 'node',
|
|
5
5
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
[functions]
|
|
2
|
-
directory = "src/api"
|
|
3
|
-
node_bundler = "esbuild"
|
|
4
|
-
|
|
5
|
-
[dev]
|
|
6
|
-
command = "yarn dev"
|
|
1
|
+
[functions]
|
|
2
|
+
directory = "src/api"
|
|
3
|
+
node_bundler = "esbuild"
|
|
4
|
+
|
|
5
|
+
[dev]
|
|
6
|
+
command = "yarn dev"
|
|
7
7
|
port = 8888
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"type": "module",
|
|
8
8
|
"private": true,
|
|
9
9
|
"engines": {
|
|
10
|
-
"node": ">=
|
|
10
|
+
"node": ">=20"
|
|
11
11
|
},
|
|
12
12
|
"scripts": {
|
|
13
13
|
"dev:invoke:example-scheduled-job": "netlify functions:invoke --name polling-example-job-scheduled --port 8888 --identity",
|
|
@@ -19,24 +19,21 @@
|
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"@datalust/winston-seq": "^2.0.0",
|
|
22
|
-
"@netlify/functions": "^2.
|
|
23
|
-
"@seeka-labs/sdk-apps-server": "^1.1.
|
|
24
|
-
"axios": "^1.6.7",
|
|
22
|
+
"@netlify/functions": "^2.8.2",
|
|
23
|
+
"@seeka-labs/sdk-apps-server": "^1.1.24",
|
|
25
24
|
"lodash-es": "^4.17.21",
|
|
26
|
-
"
|
|
27
|
-
"redis": "^4.6.12",
|
|
28
|
-
"winston": "^3.11.0"
|
|
25
|
+
"redis": "^4.7.0"
|
|
29
26
|
},
|
|
30
27
|
"devDependencies": {
|
|
31
28
|
"@jest/globals": "^29.7.0",
|
|
32
29
|
"@types/lodash-es": "^4.17.12",
|
|
33
|
-
"@types/node": "^
|
|
34
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
35
|
-
"@typescript-eslint/parser": "^
|
|
36
|
-
"eslint": "^
|
|
30
|
+
"@types/node": "^20",
|
|
31
|
+
"@typescript-eslint/eslint-plugin": "^8.17.0",
|
|
32
|
+
"@typescript-eslint/parser": "^8.17.0",
|
|
33
|
+
"eslint": "^9",
|
|
37
34
|
"jest": "^29.7.0",
|
|
38
|
-
"ts-jest": "^29.
|
|
39
|
-
"netlify-cli": "^17.
|
|
40
|
-
"typescript": "^5.
|
|
35
|
+
"ts-jest": "^29.2.5",
|
|
36
|
+
"netlify-cli": "^17.38.0",
|
|
37
|
+
"typescript": "^5.7.2"
|
|
41
38
|
}
|
|
42
39
|
}
|
|
@@ -1,52 +1,52 @@
|
|
|
1
|
-
import winston, { Logger } from 'winston';
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
apiKeyHeaderName, BackgroundJobRequestContext, jobNames, signatureHeaderName, validateApiKey,
|
|
5
|
-
validateSignature
|
|
6
|
-
} from '@/lib/jobs';
|
|
7
|
-
import { backgroundJobLogger } from '@/lib/logging';
|
|
8
|
-
import { startServices, stopServices } from '@/lib/services';
|
|
9
|
-
|
|
10
|
-
import type { Config, Context } from "@netlify/functions"
|
|
11
|
-
export default async (req: Request, context: Context) => {
|
|
12
|
-
if (req.method != "POST") {
|
|
13
|
-
return new Response("Method not allowed", { status: 405 });
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const bodyStr = await req.text();
|
|
17
|
-
const body = JSON.parse(bodyStr) as BackgroundJobRequestContext;
|
|
18
|
-
const logger = backgroundJobLogger(jobNames.exampleBackgroundJob, body, context);
|
|
19
|
-
logger.profile(`job.${jobNames.exampleBackgroundJob}`)
|
|
20
|
-
|
|
21
|
-
await startServices(logger);
|
|
22
|
-
|
|
23
|
-
if (process.env.SEEKA_DEBUG_ENABLED === 'true') {
|
|
24
|
-
logger.debug('Received request to trigger background job', { body, headers: req.headers });
|
|
25
|
-
}
|
|
26
|
-
else {
|
|
27
|
-
logger.verbose('Received request to trigger background job', { body });
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
try {
|
|
31
|
-
// Verify request
|
|
32
|
-
validateApiKey(req.headers.get(apiKeyHeaderName) as string, logger);
|
|
33
|
-
validateSignature(req.headers.get(signatureHeaderName) as string, bodyStr, logger);
|
|
34
|
-
|
|
35
|
-
// Execute
|
|
36
|
-
await doWork(body, logger);
|
|
37
|
-
|
|
38
|
-
// Close db connections
|
|
39
|
-
await stopServices(logger);
|
|
40
|
-
}
|
|
41
|
-
catch (err) {
|
|
42
|
-
logger.error('Error executing background job', { ex: winston.exceptions.getAllInfo(err) })
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
logger.profile(`job.${jobNames.exampleBackgroundJob}`)
|
|
46
|
-
|
|
47
|
-
return new Response(undefined, { status: 202 })
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const doWork = async (context: BackgroundJobRequestContext, logger: Logger) => {
|
|
51
|
-
logger.debug('Ran background job')
|
|
1
|
+
import winston, { Logger } from 'winston';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
apiKeyHeaderName, BackgroundJobRequestContext, jobNames, signatureHeaderName, validateApiKey,
|
|
5
|
+
validateSignature
|
|
6
|
+
} from '@/lib/jobs';
|
|
7
|
+
import { backgroundJobLogger } from '@/lib/logging';
|
|
8
|
+
import { startServices, stopServices } from '@/lib/services';
|
|
9
|
+
|
|
10
|
+
import type { Config, Context } from "@netlify/functions"
|
|
11
|
+
export default async (req: Request, context: Context) => {
|
|
12
|
+
if (req.method != "POST") {
|
|
13
|
+
return new Response("Method not allowed", { status: 405 });
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const bodyStr = await req.text();
|
|
17
|
+
const body = JSON.parse(bodyStr) as BackgroundJobRequestContext;
|
|
18
|
+
const logger = backgroundJobLogger(jobNames.exampleBackgroundJob, body, context);
|
|
19
|
+
logger.profile(`job.${jobNames.exampleBackgroundJob}`)
|
|
20
|
+
|
|
21
|
+
await startServices(logger);
|
|
22
|
+
|
|
23
|
+
if (process.env.SEEKA_DEBUG_ENABLED === 'true') {
|
|
24
|
+
logger.debug('Received request to trigger background job', { body, headers: req.headers });
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
logger.verbose('Received request to trigger background job', { body });
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
// Verify request
|
|
32
|
+
validateApiKey(req.headers.get(apiKeyHeaderName) as string, logger);
|
|
33
|
+
validateSignature(req.headers.get(signatureHeaderName) as string, bodyStr, logger);
|
|
34
|
+
|
|
35
|
+
// Execute
|
|
36
|
+
await doWork(body, logger);
|
|
37
|
+
|
|
38
|
+
// Close db connections
|
|
39
|
+
await stopServices(logger);
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
logger.error('Error executing background job', { ex: winston.exceptions.getAllInfo(err) })
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
logger.profile(`job.${jobNames.exampleBackgroundJob}`)
|
|
46
|
+
|
|
47
|
+
return new Response(undefined, { status: 202 })
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const doWork = async (context: BackgroundJobRequestContext, logger: Logger) => {
|
|
51
|
+
logger.debug('Ran background job')
|
|
52
52
|
}
|