diff --git a/.github/workflows/triggers-functions-offline-testing.yml b/.github/workflows/triggers-functions-offline-testing.yml
new file mode 100644
index 0000000..7ea3471
--- /dev/null
+++ b/.github/workflows/triggers-functions-offline-testing.yml
@@ -0,0 +1,96 @@
+---
+name: triggers-offline-testing
+
+on:
+ push:
+ branches: [main]
+ pull_request:
+ branches: [main]
+
+env:
+ TRIGGERS_GETTING_STARTED_FOLDER: functions/triggers-getting-started
+ OFFLINE_SERVER_URL: http://localhost:8080
+
+jobs:
+ trigger-node:
+ runs-on: ubuntu-22.04
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+
+ - name: Install node
+ uses: actions/setup-node@v3
+ with:
+ node-version: 20
+
+ - name: Install node dev requirements
+ run: |
+ cd ${{ env.TRIGGERS_GETTING_STARTED_FOLDER }}/node
+ npm install
+
+ - name: Install python
+ uses: actions/setup-python@v4
+ with:
+ python-version: "3.11"
+
+ - name: Install testing requirements
+ run: pip install -r ${{ env.TRIGGERS_GETTING_STARTED_FOLDER }}/tests/requirements.txt
+
+ - name: Run node offline testing
+ uses: BerniWittmann/background-server-action@v1
+ with:
+ # The wait-on directive doesn't work with 405 on / with GETs
+ command: python ${{ env.TRIGGERS_GETTING_STARTED_FOLDER }}/tests/test_handler.py
+ start: npm start --prefix ${{ env.TRIGGERS_GETTING_STARTED_FOLDER }}/node
+
+ trigger-go:
+ runs-on: ubuntu-22.04
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+
+ - name: Install go
+ uses: actions/setup-go@v4
+ with:
+ go-version: "1.20"
+
+ - name: Install python
+ uses: actions/setup-python@v4
+ with:
+ python-version: "3.11"
+
+ - name: Install testing requirements
+ run: pip install -r ${{ env.TRIGGERS_GETTING_STARTED_FOLDER }}/tests/requirements.txt
+
+ - name: Run go offline testing
+ uses: BerniWittmann/background-server-action@v1
+ with:
+ # The wait-on directive doesn't work with 405 on / with GETs
+ command: python ${{ env.TRIGGERS_GETTING_STARTED_FOLDER }}/tests/test_handler.py
+ start: >
+ cd ${{ env.TRIGGERS_GETTING_STARTED_FOLDER }}/go &&
+ go run ./cmd
+
+ trigger-python:
+ runs-on: ubuntu-22.04
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+
+ - name: Install python
+ uses: actions/setup-python@v4
+ with:
+ python-version: "3.11"
+
+ - name: Install python dev requirements
+ run: pip install -r ${{ env.TRIGGERS_GETTING_STARTED_FOLDER }}/python/requirements-dev.txt
+
+ - name: Install testing requirements
+ run: pip install -r ${{ env.TRIGGERS_GETTING_STARTED_FOLDER }}/tests/requirements.txt
+
+ - name: Run python offline testing
+ uses: BerniWittmann/background-server-action@v1
+ with:
+ # The wait-on directive doesn't work with 405 on / with GETs
+ command: python ${{ env.TRIGGERS_GETTING_STARTED_FOLDER }}/tests/test_handler.py
+ start: python ${{ env.TRIGGERS_GETTING_STARTED_FOLDER }}/python/handler.py
diff --git a/README.md b/README.md
index 09413d7..b5bb9b7 100644
--- a/README.md
+++ b/README.md
@@ -43,22 +43,23 @@ Table of Contents:
| **[Python ChatBot](functions/python-dependencies/README.md)**
A chatbot example with ChatterBot. | python310 | [Serverless Framework] |
| **[Python Dependencies](functions/python-chatbot/README.md)**
Example showing how to use Python requirements with Serverless Framework. | python310 | [Serverless Framework] |
| **[Python MultiPart Upload to S3](functions/python-upload-file-s3-multipart/README.md)**
A function to upload file from form-data to S3. | python311 | [Python API Framework] |
-| **[Python SQS Trigger Hello World](functions/python-sqs-trigger-hello-world/README.md)**
Trigger a function by sending a message to a SQS queue. | python311 | [Terraform] |
-| **[Python SQS Trigger Async Worker](functions/python-sqs-trigger-async-worker/README.md)**
Use SQS queues and function triggers to scheule an async task from another function. | python311 | [Terraform] |
+| **[Python SQS Trigger Hello World](functions/python-sqs-trigger-hello-world/README.md)**
Trigger a function by sending a message to a SQS queue. | python311 | [Terraform] |
+| **[Python SQS Trigger Async Worker](functions/python-sqs-trigger-async-worker/README.md)**
Use SQS queues and function triggers to scheule an async task from another function. | python311 | [Terraform] |
| **[Redis TLS](functions/redis-tls/README.md)**
How to connect a function to a Scaleway Redis cluster with TLS enabled. | python310 | [Terraform] |
| **[Rust MNIST](functions/rust-mnist/README.md)**
A Rust function to recognize hand-written digits with a simple neural network. | rust165 | [Serverless Framework] |
| **[PostgreSQL Python](functions/postgre-sql-python/README.md)**
A Python function to perform a query on a PostgreSQL managed database. | python310 | [Serverless Framework] |
| **[Terraform Python](functions/terraform-python-example/README.md)**
A Python function deployed with Terraform. | python310 | [Terraform] |
+| **[Triggers Getting Started](functions/triggers-getting-started/README.md)**
Simple SQS trigger example for all runtimes. | all | [Terraform] |
| **[Typescript with Node runtime](functions/typescript-with-node/README.md)**
A Typescript function using Node runtime. | node18 | [Serverless Framework] |
-| **[Serverless Gateway Python Example](functions/serverless-gateway-python/README.md)**
A Python serverless API using Serverless Gateway. | python310 | [Python API Framework] |
+| **[Serverless Gateway Python Example](functions/serverless-gateway-python/README.md)**
A Python serverless API using Serverless Gateway. | python310 | [Python API Framework] |
### 📦 Containers
| Example | Language | Deployment |
|----------------------------------------------------------------------------------------------------------------------------------------------|--------------|------------------------|
| **[Container Bash Script](containers/bash-scheduled-job/README.md)**
A Bash script runnning on a schedule using serverless containers. | Bash | [Serverless Framework] |
-| **[Function Handler Java](containers/function-handler-java/README.md)**
A Java function handler deployed on CaaS. | Java | [Serverless Framework] |
-| **[Nginx CORS Private](containers/nginx-cors-private-python/README.md)**
A Nginx proxy to allow CORS requests to a private container. | Python Flask | [Terraform] |
+| **[Function Handler Java](containers/function-handler-java/README.md)**
A Java function handler deployed on CaaS. | Java | [Serverless Framework] |
+| **[Nginx CORS Private](containers/nginx-cors-private-python/README.md)**
A Nginx proxy to allow CORS requests to a private container. | Python Flask | [Terraform] |
### 💜 Projects
diff --git a/functions/redis-tls/README.md b/functions/redis-tls/README.md
index 67b4d9f..ae86bbd 100644
--- a/functions/redis-tls/README.md
+++ b/functions/redis-tls/README.md
@@ -16,7 +16,7 @@ Everything is managed with Terraform. The terraform config files will also creat
```sh
terraform init
-terraform deploy
+terraform apply
```
You should be able to see your function in the Scaleway console.
diff --git a/functions/triggers-getting-started/.gitignore b/functions/triggers-getting-started/.gitignore
new file mode 100644
index 0000000..1d6ac01
--- /dev/null
+++ b/functions/triggers-getting-started/.gitignore
@@ -0,0 +1,13 @@
+# Local .terraform directories
+**/.terraform/*
+
+# Generated files
+*.zip
+
+# .tfstate files
+*.tfstate
+*.tfstate.*
+
+# Crash log files
+crash.log
+crash.*.log
diff --git a/functions/triggers-getting-started/.terraform.lock.hcl b/functions/triggers-getting-started/.terraform.lock.hcl
new file mode 100644
index 0000000..04c2a1d
--- /dev/null
+++ b/functions/triggers-getting-started/.terraform.lock.hcl
@@ -0,0 +1,44 @@
+# This file is maintained automatically by "terraform init".
+# Manual edits may be lost in future updates.
+
+provider "registry.terraform.io/hashicorp/archive" {
+ version = "2.4.0"
+ constraints = ">= 2.4.0"
+ hashes = [
+ "h1:EtN1lnoHoov3rASpgGmh6zZ/W6aRCTgKC7iMwvFY1yc=",
+ "zh:18e408596dd53048f7fc8229098d0e3ad940b92036a24287eff63e2caec72594",
+ "zh:392d4216ecd1a1fd933d23f4486b642a8480f934c13e2cae3c13b6b6a7e34a7b",
+ "zh:655dd1fa5ca753a4ace21d0de3792d96fff429445717f2ce31c125d19c38f3ff",
+ "zh:70dae36c176aa2b258331ad366a471176417a94dd3b4985a911b8be9ff842b00",
+ "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
+ "zh:7d8c8e3925f1e21daf73f85983894fbe8868e326910e6df3720265bc657b9c9c",
+ "zh:a032ec0f0aee27a789726e348e8ad20778c3a1c9190ef25e7cff602c8d175f44",
+ "zh:b8e50de62ba185745b0fe9713755079ad0e9f7ac8638d204de6762cc36870410",
+ "zh:c8ad0c7697a3d444df21ff97f3473a8604c8639be64afe3f31b8ec7ad7571e18",
+ "zh:df736c5a2a7c3a82c5493665f659437a22f0baf8c2d157e45f4dd7ca40e739fc",
+ "zh:e8ffbf578a0977074f6d08aa8734e36c726e53dc79894cfc4f25fadc4f45f1df",
+ "zh:efea57ff23b141551f92b2699024d356c7ffd1a4ad62931da7ed7a386aef7f1f",
+ ]
+}
+
+provider "registry.terraform.io/scaleway/scaleway" {
+ version = "2.27.0"
+ constraints = ">= 2.12.0"
+ hashes = [
+ "h1:Og47Om5NlmVBxIowPf2eqTtnCB+eHmcdocIugrBxoAI=",
+ "zh:69703b786535ac43a47145e48875f7dd5da2de9b2868e35cb3053374f912cf5f",
+ "zh:75a62a02971545c216732b369d78cf277d4065e23d8ff453bd3ddc37ff87a2eb",
+ "zh:8bd985631980f60e96f197be254bee6ef7b431169025d615703d12eee74f8119",
+ "zh:910012fcded93f99768a5b66aba7bcd94a3fd94ffe95fdb2cc96b11b9cc3643c",
+ "zh:917b46a52647767afaa169abb6c2ddab4274b3fbcfa47ae66670335bd26c5a5c",
+ "zh:91a1ffc2c219a2db0226dc43a6279c85708d1d62ab4f2dbd4b59c6f43d7d38ab",
+ "zh:ab08103d5fff1817e295754ad8684883eb0652be89116a260f64db166a6b430b",
+ "zh:b972c3940f4fd0ae45b5ff6dee15fcd0f2065db3f51d8fe9b6b03825ff812ae3",
+ "zh:bac194f28d24a72499b2e92e3126475de1f6bd57709f972b5f2120e6bfc7ef3b",
+ "zh:bea0c0a52d2e6fdd2bb259c5bbfedd481a3117cbc480dcf832abb8dd169fd4d6",
+ "zh:e617974d3af9ac1d0eb9d9cbc9595342474e9ddf374e27d3e39554489cd0d10e",
+ "zh:eeca97061dbf09c887347467cd3ea2f41839550f8a47695f571ba721b6d18079",
+ "zh:fc521229e8a83b6e0bf4d65452484e242cf7eef073e4c63abe793934bebe4f7c",
+ "zh:fdc15b5e46fafb82acd5e3b0f1dda1743686b98d5c6ba40e34e91bae67f00c91",
+ ]
+}
diff --git a/functions/triggers-getting-started/README.md b/functions/triggers-getting-started/README.md
new file mode 100644
index 0000000..9cd63ac
--- /dev/null
+++ b/functions/triggers-getting-started/README.md
@@ -0,0 +1,58 @@
+# Triggers Getting Started
+
+Simple starter examples that showcase using SQS triggers in all Scaleway Functions supported languages.
+
+In each example, a function is triggered by a SQS queue with a message containing a number. The function will then print the factorial of this number to the logs.
+
+## Requirements
+
+This example requires [Terraform](https://www.scaleway.com/en/docs/tutorials/terraform-quickstart/).
+
+## Setup
+
+The Terraform configuration will deploy a function for each language, showing how to use triggers with each language.
+
+It will also create a SQS queue per function to trigger it.
+
+```console
+terraform init
+terraform apply
+```
+
+You should be able to see your functions in the Scaleway console.
+
+## Running
+
+You can use the `tests/send_messages.py` script to send a message to the SQS queue of each function.
+
+```console
+export AWS_ACCESS_KEY_ID=$(terraform output -raw sqs_access_key)
+export AWS_SECRET_ACCESS_KEY=$(terraform output -raw sqs_secret_key)
+python tests/send_messages.py
+```
+
+In Cockpit, you should see the functions being triggered and the result of the factorial being printed in the logs.
+
+```console
+...
+DEBUG - php: factorial of 17 is 355687428096000 source=user stream=stdout
+2023-09-11 10:36:19.994 DEBUG - Function Triggered: / source=core
+2023-09-11 10:36:19.993 DEBUG - php: factorial of 13 is 6227020800 source=user stream=stdout
+2023-09-11 10:36:19.991 DEBUG - Function Triggered: / source=core
+2023-09-11 10:36:19.977 DEBUG - php: factorial of 12 is 479001600 source=user stream=stdout
+2023-09-11 10:36:19.976 DEBUG - php: factorial of 11 is 39916800 source=user stream=stdout
+2023-09-11 10:36:19.975 DEBUG - php: factorial of 10 is 3628800 source=user stream=stdout
+2023-09-11 10:36:19.964 DEBUG - Function Triggered: / source=core
+2023-09-11 10:36:19.954 DEBUG - php: factorial of 3 is 6 source=user stream=stdout
+2023-09-11 10:36:19.954 DEBUG - php: factorial of 4 is 24 source=user stream=stdout
+2023-09-11 10:36:19.948 DEBUG - php: factorial of 0 is 1 source=user stream=stdout
+... (truncated)
+```
+
+Configuring and managing triggers is free, you only pay for the execution of your functions. For more information, please consult the [Scaleway Serverless pricing](https://www.scaleway.com/en/pricing/?tags=serverless). You will also be billed for the SQS queue usage when sending messages to it.
+
+## Cleanup
+
+```console
+terraform destroy
+```
diff --git a/functions/triggers-getting-started/go/cmd/main.go b/functions/triggers-getting-started/go/cmd/main.go
new file mode 100644
index 0000000..2f73b45
--- /dev/null
+++ b/functions/triggers-getting-started/go/cmd/main.go
@@ -0,0 +1,11 @@
+package main
+
+import (
+ "triggers-getting-started/go"
+ "github.com/scaleway/serverless-functions-go/local"
+)
+
+func main() {
+ // Replace "Handle" with your function handler name if necessary
+ local.ServeHandler(handler.Handle, local.WithPort(8080))
+}
diff --git a/functions/triggers-getting-started/go/go.mod b/functions/triggers-getting-started/go/go.mod
new file mode 100644
index 0000000..4016da5
--- /dev/null
+++ b/functions/triggers-getting-started/go/go.mod
@@ -0,0 +1,7 @@
+module triggers-getting-started/go
+
+go 1.19
+
+require github.com/scaleway/serverless-functions-go v0.1.2
+
+require github.com/google/uuid v1.3.0 // indirect
diff --git a/functions/triggers-getting-started/go/go.sum b/functions/triggers-getting-started/go/go.sum
new file mode 100644
index 0000000..cc000e7
--- /dev/null
+++ b/functions/triggers-getting-started/go/go.sum
@@ -0,0 +1,8 @@
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
+github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/scaleway/serverless-functions-go v0.1.2 h1:UUToB+XXpLDG9l6c9c0ALhAs1jvb6rV2Lkyj2kZEYCo=
+github.com/scaleway/serverless-functions-go v0.1.2/go.mod h1:23Hj74DYzTsVY3QgvsM0MGnx0+0OAAabTC06BOMJE58=
+github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
diff --git a/functions/triggers-getting-started/go/handler.go b/functions/triggers-getting-started/go/handler.go
new file mode 100644
index 0000000..c586df6
--- /dev/null
+++ b/functions/triggers-getting-started/go/handler.go
@@ -0,0 +1,53 @@
+package handler
+
+import (
+ "fmt"
+ "io"
+ "math/big"
+ "net/http"
+ "strconv"
+)
+
+func factorial(n int) *big.Int {
+ var f big.Int
+ f.MulRange(1, int64(n))
+ return &f
+}
+
+func Handle(w http.ResponseWriter, r *http.Request) {
+ if r.Method != http.MethodPost {
+ // SQS triggers are sent as POST requests.
+ http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
+ return
+ }
+
+ // The SQS trigger sends the message content in the body.
+ body, err := io.ReadAll(r.Body)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ n, err := strconv.Atoi(string(body))
+ if err != nil {
+ // Setting the status code to 200 will mark the message as processed.
+ http.Error(w, err.Error(), http.StatusOK)
+ return
+ }
+
+ result := factorial(n)
+ fmt.Printf("go: factorial of %d is %s\n", n, result.String())
+
+ // Because triggers are asynchronous, the response body is ignored.
+ // It's kept here when testing locally.
+ _, err = io.WriteString(w, result.String())
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ // If the status code is not in the 2XX range, the message is considered
+ // failed and is retried. In total, there are 3 retries.
+ w.WriteHeader(http.StatusOK)
+ w.Header().Set("Content-Type", "text/plain")
+}
diff --git a/functions/triggers-getting-started/main.tf b/functions/triggers-getting-started/main.tf
new file mode 100644
index 0000000..35eabaa
--- /dev/null
+++ b/functions/triggers-getting-started/main.tf
@@ -0,0 +1,84 @@
+locals {
+ functions = {
+ "go" = {
+ path = "go"
+ runtime = "go120"
+ handler = "Handle"
+ }
+ "node" = {
+ path = "node"
+ runtime = "node20"
+ handler = "handler.handle"
+ }
+ "php" = {
+ path = "php"
+ runtime = "php82"
+ handler = "handler.handle"
+ }
+ "python" = {
+ path = "python"
+ runtime = "python311"
+ handler = "handler.handler"
+ }
+ "rust" = {
+ path = "rust"
+ runtime = "rust165"
+ handler = "handler"
+ }
+ }
+}
+
+resource "scaleway_function_namespace" "main" {
+ name = "triggers-getting-started"
+}
+
+data "archive_file" "function" {
+ for_each = local.functions
+
+ type = "zip"
+ source_dir = "${path.module}/${each.value.path}"
+ output_path = "${path.module}/${each.value.path}.zip"
+}
+
+resource "scaleway_function" "main" {
+ for_each = local.functions
+
+ namespace_id = scaleway_function_namespace.main.id
+ name = each.key
+ runtime = each.value.runtime
+ handler = each.value.handler
+
+ // As of 2023/09/04, only public functions can be triggered by a message queue
+ privacy = "public"
+
+ zip_file = data.archive_file.function[each.key].output_path
+ zip_hash = data.archive_file.function[each.key].output_sha256
+ deploy = true
+
+ memory_limit = 512 # MB / 280 mVCPU
+
+ min_scale = 0
+}
+
+resource "scaleway_mnq_queue" "main" {
+ for_each = local.functions
+
+ namespace_id = scaleway_mnq_namespace.main.id
+ name = "factorial-requests-${each.key}"
+
+ sqs {
+ access_key = scaleway_mnq_credential.main.sqs_sns_credentials.0.access_key
+ secret_key = scaleway_mnq_credential.main.sqs_sns_credentials.0.secret_key
+ }
+}
+
+resource "scaleway_function_trigger" "main" {
+ for_each = local.functions
+
+ function_id = scaleway_function.main[each.key].id
+ name = "on-factorial-request"
+ sqs {
+ namespace_id = scaleway_mnq_namespace.main.id
+ queue = scaleway_mnq_queue.main[each.key].name
+ }
+}
diff --git a/functions/triggers-getting-started/messaging.tf b/functions/triggers-getting-started/messaging.tf
new file mode 100644
index 0000000..6d52853
--- /dev/null
+++ b/functions/triggers-getting-started/messaging.tf
@@ -0,0 +1,16 @@
+resource "scaleway_mnq_namespace" "main" {
+ name = "triggers-getting-started"
+ protocol = "sqs_sns"
+}
+
+resource "scaleway_mnq_credential" "main" {
+ name = "triggers-getting-started"
+ namespace_id = scaleway_mnq_namespace.main.id
+ sqs_sns_credentials {
+ permissions {
+ can_publish = true
+ can_receive = true
+ can_manage = true
+ }
+ }
+}
diff --git a/functions/triggers-getting-started/node/.gitignore b/functions/triggers-getting-started/node/.gitignore
new file mode 100644
index 0000000..c2658d7
--- /dev/null
+++ b/functions/triggers-getting-started/node/.gitignore
@@ -0,0 +1 @@
+node_modules/
diff --git a/functions/triggers-getting-started/node/handler.js b/functions/triggers-getting-started/node/handler.js
new file mode 100644
index 0000000..dbef5e6
--- /dev/null
+++ b/functions/triggers-getting-started/node/handler.js
@@ -0,0 +1,55 @@
+"use strict";
+
+import { pathToFileURL } from "url";
+
+/**
+ * Compute the factorial of a number
+ * @param {number} n
+ * @returns {number} The factorial of n
+ */
+function factorial(n) {
+ let result = 1;
+ for (let i = 2; i <= n; i++) {
+ result *= i;
+ }
+ return result;
+}
+
+export function handle(event, context, callback) {
+ if (event["httpMethod"] !== "POST") {
+ return {
+ statusCode: 405,
+ body: "Method Not Allowed",
+ headers: {
+ "Content-Type": "text/plain",
+ },
+ };
+ }
+
+ // The SQS trigger sends the message content in the body.
+ const n = parseInt(event["body"]);
+ console.log(`node: received ${n}`);
+ const result = factorial(n);
+
+ console.log(`node: factorial of ${n} is ${result}`);
+
+ return {
+ // If the status code is not in the 2XX range, the message is considered
+ // failed and is retried. In total, there are 3 retries.
+ statusCode: 200,
+ // Because triggers are asynchronous, the response body is ignored.
+ // It's kept here when testing locally.
+ body: result.toString(),
+ headers: {
+ "Content-Type": "text/plain",
+ },
+ };
+}
+
+/* Module was not imported but called directly, so we can test locally.
+This will not be executed on Scaleway Functions */
+if (import.meta.url === pathToFileURL(process.argv[1]).href) {
+ import("@scaleway/serverless-functions").then(scw_fnc_node => {
+ scw_fnc_node.serveHandler(handle, 8080);
+ });
+}
diff --git a/functions/triggers-getting-started/node/package-lock.json b/functions/triggers-getting-started/node/package-lock.json
new file mode 100644
index 0000000..07c6315
--- /dev/null
+++ b/functions/triggers-getting-started/node/package-lock.json
@@ -0,0 +1,693 @@
+{
+ "name": "examples",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "examples",
+ "version": "1.0.0",
+ "license": "ISC",
+ "devDependencies": {
+ "@scaleway/serverless-functions": "^1.0.0"
+ }
+ },
+ "node_modules/@fastify/ajv-compiler": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/@fastify/ajv-compiler/-/ajv-compiler-3.5.0.tgz",
+ "integrity": "sha512-ebbEtlI7dxXF5ziNdr05mOY8NnDiPB1XvAlLHctRt/Rc+C3LCOVW5imUVX+mhvUhnNzmPBHewUkOFgGlCxgdAA==",
+ "dev": true,
+ "dependencies": {
+ "ajv": "^8.11.0",
+ "ajv-formats": "^2.1.1",
+ "fast-uri": "^2.0.0"
+ }
+ },
+ "node_modules/@fastify/deepmerge": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@fastify/deepmerge/-/deepmerge-1.3.0.tgz",
+ "integrity": "sha512-J8TOSBq3SoZbDhM9+R/u77hP93gz/rajSA+K2kGyijPpORPWUXHUpTaleoj+92As0S9uPRP7Oi8IqMf0u+ro6A==",
+ "dev": true
+ },
+ "node_modules/@fastify/error": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/@fastify/error/-/error-3.3.0.tgz",
+ "integrity": "sha512-dj7vjIn1Ar8sVXj2yAXiMNCJDmS9MQ9XMlIecX2dIzzhjSHCyKo4DdXjXMs7wKW2kj6yvVRSpuQjOZ3YLrh56w==",
+ "dev": true
+ },
+ "node_modules/@fastify/fast-json-stringify-compiler": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/@fastify/fast-json-stringify-compiler/-/fast-json-stringify-compiler-4.3.0.tgz",
+ "integrity": "sha512-aZAXGYo6m22Fk1zZzEUKBvut/CIIQe/BapEORnxiD5Qr0kPHqqI69NtEMCme74h+at72sPhbkb4ZrLd1W3KRLA==",
+ "dev": true,
+ "dependencies": {
+ "fast-json-stringify": "^5.7.0"
+ }
+ },
+ "node_modules/@fastify/url-data": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/@fastify/url-data/-/url-data-5.3.1.tgz",
+ "integrity": "sha512-DbXNlGyxyKQZijNn+GE5qrlTyy8Hl77K+DZrp2MFcdaa0CuxpOQTTVzfV3Inx0otCVVtcjVAS7KrhAwQ2UHvSA==",
+ "dev": true,
+ "dependencies": {
+ "fast-uri": "^2.2.0",
+ "fastify-plugin": "^4.0.0"
+ }
+ },
+ "node_modules/@scaleway/serverless-functions": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@scaleway/serverless-functions/-/serverless-functions-1.0.2.tgz",
+ "integrity": "sha512-rTfOTvGrVfi00JWckjP+JsJtBjvquQC6+RN3RCfEqYG9od38sLW++5uu9hcuOS+ZjxqkcF/+nPB2uUzmrxR6Rw==",
+ "dev": true,
+ "dependencies": {
+ "@fastify/url-data": "^5.3.1",
+ "@types/node": "^18.15.11",
+ "fastify": "^4.15.0"
+ }
+ },
+ "node_modules/@types/node": {
+ "version": "18.17.14",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.14.tgz",
+ "integrity": "sha512-ZE/5aB73CyGqgQULkLG87N9GnyGe5TcQjv34pwS8tfBs1IkCh0ASM69mydb2znqd6v0eX+9Ytvk6oQRqu8T1Vw==",
+ "dev": true
+ },
+ "node_modules/abort-controller": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
+ "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
+ "dev": true,
+ "dependencies": {
+ "event-target-shim": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=6.5"
+ }
+ },
+ "node_modules/abstract-logging": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/abstract-logging/-/abstract-logging-2.0.1.tgz",
+ "integrity": "sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==",
+ "dev": true
+ },
+ "node_modules/ajv": {
+ "version": "8.12.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
+ "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ajv-formats": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
+ "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
+ "dev": true,
+ "dependencies": {
+ "ajv": "^8.0.0"
+ },
+ "peerDependencies": {
+ "ajv": "^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "ajv": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/archy": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz",
+ "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==",
+ "dev": true
+ },
+ "node_modules/atomic-sleep": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz",
+ "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/avvio": {
+ "version": "8.2.1",
+ "resolved": "https://registry.npmjs.org/avvio/-/avvio-8.2.1.tgz",
+ "integrity": "sha512-TAlMYvOuwGyLK3PfBb5WKBXZmXz2fVCgv23d6zZFdle/q3gPjmxBaeuC0pY0Dzs5PWMSgfqqEZkrye19GlDTgw==",
+ "dev": true,
+ "dependencies": {
+ "archy": "^1.0.0",
+ "debug": "^4.0.0",
+ "fastq": "^1.6.1"
+ }
+ },
+ "node_modules/base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/buffer": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
+ "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.2.1"
+ }
+ },
+ "node_modules/cookie": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
+ "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/event-target-shim": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
+ "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/events": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
+ "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.x"
+ }
+ },
+ "node_modules/fast-content-type-parse": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-1.0.0.tgz",
+ "integrity": "sha512-Xbc4XcysUXcsP5aHUU7Nq3OwvHq97C+WnbkeIefpeYLX+ryzFJlU6OStFJhs6Ol0LkUGpcK+wL0JwfM+FCU5IA==",
+ "dev": true
+ },
+ "node_modules/fast-decode-uri-component": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz",
+ "integrity": "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==",
+ "dev": true
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true
+ },
+ "node_modules/fast-json-stringify": {
+ "version": "5.8.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-5.8.0.tgz",
+ "integrity": "sha512-VVwK8CFMSALIvt14U8AvrSzQAwN/0vaVRiFFUVlpnXSnDGrSkOAO5MtzyN8oQNjLd5AqTW5OZRgyjoNuAuR3jQ==",
+ "dev": true,
+ "dependencies": {
+ "@fastify/deepmerge": "^1.0.0",
+ "ajv": "^8.10.0",
+ "ajv-formats": "^2.1.1",
+ "fast-deep-equal": "^3.1.3",
+ "fast-uri": "^2.1.0",
+ "rfdc": "^1.2.0"
+ }
+ },
+ "node_modules/fast-querystring": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/fast-querystring/-/fast-querystring-1.1.2.tgz",
+ "integrity": "sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==",
+ "dev": true,
+ "dependencies": {
+ "fast-decode-uri-component": "^1.0.1"
+ }
+ },
+ "node_modules/fast-redact": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.3.0.tgz",
+ "integrity": "sha512-6T5V1QK1u4oF+ATxs1lWUmlEk6P2T9HqJG3e2DnHOdVgZy2rFJBoEnrIedcTXlkAHU/zKC+7KETJ+KGGKwxgMQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/fast-uri": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-2.2.0.tgz",
+ "integrity": "sha512-cIusKBIt/R/oI6z/1nyfe2FvGKVTohVRfvkOhvx0nCEW+xf5NoCXjAHcWp93uOUBchzYcsvPlrapAdX1uW+YGg==",
+ "dev": true
+ },
+ "node_modules/fastify": {
+ "version": "4.22.2",
+ "resolved": "https://registry.npmjs.org/fastify/-/fastify-4.22.2.tgz",
+ "integrity": "sha512-rK8mF/1mZJHH6H/L22OhmilTgrp5XMkk3RHcSy03LC+TJ6+wLhbq+4U62bjns15VzIbBNgxTqAForBqtGAa0NQ==",
+ "dev": true,
+ "dependencies": {
+ "@fastify/ajv-compiler": "^3.5.0",
+ "@fastify/error": "^3.2.0",
+ "@fastify/fast-json-stringify-compiler": "^4.3.0",
+ "abstract-logging": "^2.0.1",
+ "avvio": "^8.2.1",
+ "fast-content-type-parse": "^1.0.0",
+ "fast-json-stringify": "^5.7.0",
+ "find-my-way": "^7.6.0",
+ "light-my-request": "^5.9.1",
+ "pino": "^8.12.0",
+ "process-warning": "^2.2.0",
+ "proxy-addr": "^2.0.7",
+ "rfdc": "^1.3.0",
+ "secure-json-parse": "^2.5.0",
+ "semver": "^7.5.0",
+ "tiny-lru": "^11.0.1"
+ }
+ },
+ "node_modules/fastify-plugin": {
+ "version": "4.5.1",
+ "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-4.5.1.tgz",
+ "integrity": "sha512-stRHYGeuqpEZTL1Ef0Ovr2ltazUT9g844X5z/zEBFLG8RYlpDiOCIG+ATvYEp+/zmc7sN29mcIMp8gvYplYPIQ==",
+ "dev": true
+ },
+ "node_modules/fastq": {
+ "version": "1.15.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
+ "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
+ "dev": true,
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/find-my-way": {
+ "version": "7.6.2",
+ "resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-7.6.2.tgz",
+ "integrity": "sha512-0OjHn1b1nCX3eVbm9ByeEHiscPYiHLfhei1wOUU9qffQkk98wE0Lo8VrVYfSGMgnSnDh86DxedduAnBf4nwUEw==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3",
+ "fast-querystring": "^1.0.0",
+ "safe-regex2": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/forwarded": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
+ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/ipaddr.js": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
+ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+ "dev": true
+ },
+ "node_modules/light-my-request": {
+ "version": "5.10.0",
+ "resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-5.10.0.tgz",
+ "integrity": "sha512-ZU2D9GmAcOUculTTdH9/zryej6n8TzT+fNGdNtm6SDp5MMMpHrJJkvAdE3c6d8d2chE9i+a//dS9CWZtisknqA==",
+ "dev": true,
+ "dependencies": {
+ "cookie": "^0.5.0",
+ "process-warning": "^2.0.0",
+ "set-cookie-parser": "^2.4.1"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/on-exit-leak-free": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.0.tgz",
+ "integrity": "sha512-VuCaZZAjReZ3vUwgOB8LxAosIurDiAW0s13rI1YwmaP++jvcxP77AWoQvenZebpCA2m8WC1/EosPYPMjnRAp/w==",
+ "dev": true
+ },
+ "node_modules/pino": {
+ "version": "8.15.0",
+ "resolved": "https://registry.npmjs.org/pino/-/pino-8.15.0.tgz",
+ "integrity": "sha512-olUADJByk4twxccmAxb1RiGKOSvddHugCV3wkqjyv+3Sooa2KLrmXrKEWOKi0XPCLasRR5jBXxioE1jxUa4KzQ==",
+ "dev": true,
+ "dependencies": {
+ "atomic-sleep": "^1.0.0",
+ "fast-redact": "^3.1.1",
+ "on-exit-leak-free": "^2.1.0",
+ "pino-abstract-transport": "v1.0.0",
+ "pino-std-serializers": "^6.0.0",
+ "process-warning": "^2.0.0",
+ "quick-format-unescaped": "^4.0.3",
+ "real-require": "^0.2.0",
+ "safe-stable-stringify": "^2.3.1",
+ "sonic-boom": "^3.1.0",
+ "thread-stream": "^2.0.0"
+ },
+ "bin": {
+ "pino": "bin.js"
+ }
+ },
+ "node_modules/pino-abstract-transport": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.0.0.tgz",
+ "integrity": "sha512-c7vo5OpW4wIS42hUVcT5REsL8ZljsUfBjqV/e2sFxmFEFZiq1XLUp5EYLtuDH6PEHq9W1egWqRbnLUP5FuZmOA==",
+ "dev": true,
+ "dependencies": {
+ "readable-stream": "^4.0.0",
+ "split2": "^4.0.0"
+ }
+ },
+ "node_modules/pino-std-serializers": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz",
+ "integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==",
+ "dev": true
+ },
+ "node_modules/process": {
+ "version": "0.11.10",
+ "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
+ "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6.0"
+ }
+ },
+ "node_modules/process-warning": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-2.2.0.tgz",
+ "integrity": "sha512-/1WZ8+VQjR6avWOgHeEPd7SDQmFQ1B5mC1eRXsCm5TarlNmx/wCsa5GEaxGm05BORRtyG/Ex/3xq3TuRvq57qg==",
+ "dev": true
+ },
+ "node_modules/proxy-addr": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
+ "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
+ "dev": true,
+ "dependencies": {
+ "forwarded": "0.2.0",
+ "ipaddr.js": "1.9.1"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/punycode": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
+ "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/quick-format-unescaped": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz",
+ "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==",
+ "dev": true
+ },
+ "node_modules/readable-stream": {
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.2.tgz",
+ "integrity": "sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==",
+ "dev": true,
+ "dependencies": {
+ "abort-controller": "^3.0.0",
+ "buffer": "^6.0.3",
+ "events": "^3.3.0",
+ "process": "^0.11.10",
+ "string_decoder": "^1.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/real-require": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz",
+ "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 12.13.0"
+ }
+ },
+ "node_modules/require-from-string": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ret": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/ret/-/ret-0.2.2.tgz",
+ "integrity": "sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true,
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rfdc": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz",
+ "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==",
+ "dev": true
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/safe-regex2": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/safe-regex2/-/safe-regex2-2.0.0.tgz",
+ "integrity": "sha512-PaUSFsUaNNuKwkBijoAPHAK6/eM6VirvyPWlZ7BAQy4D+hCvh4B6lIG+nPdhbFfIbP+gTGBcrdsOaUs0F+ZBOQ==",
+ "dev": true,
+ "dependencies": {
+ "ret": "~0.2.0"
+ }
+ },
+ "node_modules/safe-stable-stringify": {
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz",
+ "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/secure-json-parse": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz",
+ "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==",
+ "dev": true
+ },
+ "node_modules/semver": {
+ "version": "7.5.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
+ "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/set-cookie-parser": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz",
+ "integrity": "sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==",
+ "dev": true
+ },
+ "node_modules/sonic-boom": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.3.0.tgz",
+ "integrity": "sha512-LYxp34KlZ1a2Jb8ZQgFCK3niIHzibdwtwNUWKg0qQRzsDoJ3Gfgkf8KdBTFU3SkejDEIlWwnSnpVdOZIhFMl/g==",
+ "dev": true,
+ "dependencies": {
+ "atomic-sleep": "^1.0.0"
+ }
+ },
+ "node_modules/split2": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
+ "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 10.x"
+ }
+ },
+ "node_modules/string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "node_modules/thread-stream": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.4.0.tgz",
+ "integrity": "sha512-xZYtOtmnA63zj04Q+F9bdEay5r47bvpo1CaNqsKi7TpoJHcotUez8Fkfo2RJWpW91lnnaApdpRbVwCWsy+ifcw==",
+ "dev": true,
+ "dependencies": {
+ "real-require": "^0.2.0"
+ }
+ },
+ "node_modules/tiny-lru": {
+ "version": "11.0.1",
+ "resolved": "https://registry.npmjs.org/tiny-lru/-/tiny-lru-11.0.1.tgz",
+ "integrity": "sha512-iNgFugVuQgBKrqeO/mpiTTgmBsTP0WL6yeuLfLs/Ctf0pI/ixGqIRm8sDCwMcXGe9WWvt2sGXI5mNqZbValmJg==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ }
+ }
+}
diff --git a/functions/triggers-getting-started/node/package.json b/functions/triggers-getting-started/node/package.json
new file mode 100644
index 0000000..96b216e
--- /dev/null
+++ b/functions/triggers-getting-started/node/package.json
@@ -0,0 +1,15 @@
+{
+ "name": "triggers-getting-started",
+ "version": "1.0.0",
+ "description": "",
+ "main": "handler.js",
+ "scripts": {
+ "start": "node handler.js"
+ },
+ "type": "module",
+ "author": "",
+ "license": "ISC",
+ "devDependencies": {
+ "@scaleway/serverless-functions": "^1.0.0"
+ }
+}
diff --git a/functions/triggers-getting-started/outputs.tf b/functions/triggers-getting-started/outputs.tf
new file mode 100644
index 0000000..7d6ec78
--- /dev/null
+++ b/functions/triggers-getting-started/outputs.tf
@@ -0,0 +1,8 @@
+output "sqs_access_key" {
+ value = scaleway_mnq_credential.main.sqs_sns_credentials.0.access_key
+}
+
+output "sqs_secret_key" {
+ value = scaleway_mnq_credential.main.sqs_sns_credentials.0.secret_key
+ sensitive = true
+}
diff --git a/functions/triggers-getting-started/php/handler.php b/functions/triggers-getting-started/php/handler.php
new file mode 100644
index 0000000..e2698bf
--- /dev/null
+++ b/functions/triggers-getting-started/php/handler.php
@@ -0,0 +1,38 @@
+ 405,
+ "headers" => ["Content-Type" => "text/plain"],
+ "body" => "Method Not Allowed",
+ ];
+ }
+
+ # The content of the SQS message is passed in the body.
+ $n = intval($event["body"]);
+ $result = factorial($n);
+
+ echo "php: factorial of $n is $result\n";
+
+ return [
+ // If the status code is not in the 2XX range, the message is considered
+ // failed and is retried. In total, there are 3 retries.
+ "statusCode" => 200,
+ "headers" => ["Content-Type" => "text/plain"],
+ // Because triggers are asynchronous, the response body is ignored.
+ // It's kept here when testing locally.
+ "body" => $result,
+ ];
+}
diff --git a/functions/triggers-getting-started/provider.tf b/functions/triggers-getting-started/provider.tf
new file mode 100644
index 0000000..14ef505
--- /dev/null
+++ b/functions/triggers-getting-started/provider.tf
@@ -0,0 +1,13 @@
+terraform {
+ required_providers {
+ scaleway = {
+ source = "scaleway/scaleway"
+ version = ">= 2.12"
+ }
+ archive = {
+ source = "hashicorp/archive"
+ version = ">= 2.4"
+ }
+ }
+ required_version = ">= 0.13"
+}
diff --git a/functions/triggers-getting-started/python/handler.py b/functions/triggers-getting-started/python/handler.py
new file mode 100644
index 0000000..27577d7
--- /dev/null
+++ b/functions/triggers-getting-started/python/handler.py
@@ -0,0 +1,49 @@
+from typing import TYPE_CHECKING
+import functools
+import operator
+import http
+
+if TYPE_CHECKING:
+ from scaleway_functions_python.framework.v1.hints import Context, Event, Response
+
+
+def factorial(n: int) -> int: # pylint: disable=invalid-name
+ """Return the factorial of n >= 0."""
+ return functools.reduce(operator.mul, range(1, n + 1), 1)
+
+
+def handler(event: "Event", _context: "Context") -> "Response":
+ """Compute factorial of the number passed in the trigger message."""
+
+ if event["httpMethod"] != "POST":
+ # SQS triggers are sent as POST requests.
+ status = http.HTTPStatus.METHOD_NOT_ALLOWED
+ return {
+ "headers": {"Content-Type": "text/plain"},
+ "statusCode": status.value,
+ "body": status.description,
+ }
+
+ # The content of the SQS message is passed in the body.
+ n = int(event["body"]) # pylint: disable=invalid-name
+ result = factorial(n)
+
+ print(f"python: factorial of {n} is {result}")
+
+ return {
+ "headers": {"Content-Type": "text/plain"},
+ # If the status code is not in the 2XX range, the message is considered
+ # failed and is retried. In total, there are 3 retries.
+ "statusCode": http.HTTPStatus.OK.value,
+ # Because triggers are asynchronous, the response body is ignored.
+ # It's kept here when testing locally.
+ "body": str(result),
+ }
+
+
+if __name__ == "__main__":
+ from scaleway_functions_python import local
+
+ # Example usage:
+ # curl -X POST -d 5 http://localhost:8080
+ local.serve_handler(handler)
diff --git a/functions/triggers-getting-started/python/requirements-dev.txt b/functions/triggers-getting-started/python/requirements-dev.txt
new file mode 100644
index 0000000..0c07318
--- /dev/null
+++ b/functions/triggers-getting-started/python/requirements-dev.txt
@@ -0,0 +1,3 @@
+scaleway_functions_python==0.2.0
+requests==2.28.2
+pytest==7.2.2
\ No newline at end of file
diff --git a/functions/triggers-getting-started/rust/.gitignore b/functions/triggers-getting-started/rust/.gitignore
new file mode 100644
index 0000000..2f7896d
--- /dev/null
+++ b/functions/triggers-getting-started/rust/.gitignore
@@ -0,0 +1 @@
+target/
diff --git a/functions/triggers-getting-started/rust/Cargo.lock b/functions/triggers-getting-started/rust/Cargo.lock
new file mode 100644
index 0000000..a066719
--- /dev/null
+++ b/functions/triggers-getting-started/rust/Cargo.lock
@@ -0,0 +1,273 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "addr2line"
+version = "0.21.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
+dependencies = [
+ "gimli",
+]
+
+[[package]]
+name = "adler"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+
+[[package]]
+name = "backtrace"
+version = "0.3.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
+dependencies = [
+ "addr2line",
+ "cc",
+ "cfg-if",
+ "libc",
+ "miniz_oxide",
+ "object",
+ "rustc-demangle",
+]
+
+[[package]]
+name = "bytes"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
+
+[[package]]
+name = "cc"
+version = "1.0.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "fnv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+
+[[package]]
+name = "futures-channel"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2"
+dependencies = [
+ "futures-core",
+]
+
+[[package]]
+name = "futures-core"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c"
+
+[[package]]
+name = "futures-task"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65"
+
+[[package]]
+name = "futures-util"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533"
+dependencies = [
+ "futures-core",
+ "futures-task",
+ "pin-project-lite",
+ "pin-utils",
+]
+
+[[package]]
+name = "gimli"
+version = "0.28.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0"
+
+[[package]]
+name = "http"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482"
+dependencies = [
+ "bytes",
+ "fnv",
+ "itoa",
+]
+
+[[package]]
+name = "http-body"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
+dependencies = [
+ "bytes",
+ "http",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "httparse"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
+
+[[package]]
+name = "httpdate"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
+
+[[package]]
+name = "hyper"
+version = "0.14.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468"
+dependencies = [
+ "bytes",
+ "futures-channel",
+ "futures-core",
+ "futures-util",
+ "http",
+ "http-body",
+ "httparse",
+ "httpdate",
+ "itoa",
+ "pin-project-lite",
+ "tokio",
+ "tower-service",
+ "tracing",
+ "want",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
+
+[[package]]
+name = "libc"
+version = "0.2.147"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
+
+[[package]]
+name = "memchr"
+version = "2.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c"
+
+[[package]]
+name = "miniz_oxide"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
+dependencies = [
+ "adler",
+]
+
+[[package]]
+name = "object"
+version = "0.32.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
+
+[[package]]
+name = "pin-utils"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+
+[[package]]
+name = "rustc-demangle"
+version = "0.1.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
+
+[[package]]
+name = "tokio"
+version = "1.32.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9"
+dependencies = [
+ "backtrace",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "tower-service"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
+
+[[package]]
+name = "tracing"
+version = "0.1.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
+dependencies = [
+ "cfg-if",
+ "pin-project-lite",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-core"
+version = "0.1.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a"
+dependencies = [
+ "once_cell",
+]
+
+[[package]]
+name = "triggers-getting-started"
+version = "0.1.0"
+dependencies = [
+ "hyper",
+]
+
+[[package]]
+name = "try-lock"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
+
+[[package]]
+name = "want"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
+dependencies = [
+ "try-lock",
+]
diff --git a/functions/triggers-getting-started/rust/Cargo.toml b/functions/triggers-getting-started/rust/Cargo.toml
new file mode 100644
index 0000000..50aa3a6
--- /dev/null
+++ b/functions/triggers-getting-started/rust/Cargo.toml
@@ -0,0 +1,9 @@
+[package]
+name = "triggers-getting-started"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+hyper = { version = "0.14", features = ["http1"] }
diff --git a/functions/triggers-getting-started/rust/src/lib.rs b/functions/triggers-getting-started/rust/src/lib.rs
new file mode 100644
index 0000000..5c00454
--- /dev/null
+++ b/functions/triggers-getting-started/rust/src/lib.rs
@@ -0,0 +1,43 @@
+use hyper::{Body, Request, Response, StatusCode};
+
+// Reference: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.product
+fn factorial(n: u64) -> u64 {
+ (1..=n).product()
+}
+
+pub async fn handler(req: Request