<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Safi</title>
    <description>The latest articles on DEV Community by Safi (@saphidev).</description>
    <link>https://dev.to/saphidev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F208470%2F615b5a45-3f94-497b-891a-aefa6c5ab70d.jpeg</url>
      <title>DEV Community: Safi</title>
      <link>https://dev.to/saphidev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/saphidev"/>
    <language>en</language>
    <item>
      <title>build your own FAAS provider</title>
      <dc:creator>Safi</dc:creator>
      <pubDate>Wed, 16 Aug 2023 17:40:17 +0000</pubDate>
      <link>https://dev.to/saphidev/build-your-own-faas-provider-2gca</link>
      <guid>https://dev.to/saphidev/build-your-own-faas-provider-2gca</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7HJHktP8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t9wrcx0ach9pycgf6q9i.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7HJHktP8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t9wrcx0ach9pycgf6q9i.jpg" alt="slsdz faas schema" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is this ?
&lt;/h2&gt;

&lt;p&gt;is a command-line interface (CLI) tool and serverless FAAS for creating serverless applications with random subdomains. It simplifies the process of setting up serverless functions using AWS services.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/apotox"&gt;
        apotox
      &lt;/a&gt; / &lt;a href="https://github.com/apotox/slsdz"&gt;
        slsdz
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      build your own serverless FAAS provider on AWS
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
SLSDZ - build your own FAAS provider&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://badge.fury.io/js/slsdz" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/a92e846983559802d24f3b3dbfa29f57c8cc3a1b4003332d54c95ac6e33099c0/68747470733a2f2f62616467652e667572792e696f2f6a732f736c73647a2e737667" alt="npm version"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/apotox/slsdz-lambda/blob/pub/docs/schema.jpg?raw=true"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fK41R2QO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://github.com/apotox/slsdz-lambda/raw/pub/docs/schema.jpg%3Fraw%3Dtrue" alt="slsdz schema"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
Description&lt;/h2&gt;
&lt;p&gt;slsdz is a command-line interface (CLI) tool and serverless FAAS for creating serverless applications with random subdomains. It simplifies the process of setting up serverless functions using AWS services.&lt;/p&gt;

  
    

    &lt;span class="m-1"&gt;video.mp4&lt;/span&gt;
  
  

  


&lt;h2&gt;
Installation&lt;/h2&gt;
&lt;p&gt;You can try the cli:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;yarn install
yarn bundle
&lt;span class="pl-c1"&gt;cd&lt;/span&gt; demo
./mycli.js --help
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Note: mycli.js is a shortlink to the bundled CLI file cli.js&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
Options&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--help&lt;/code&gt; Show help&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--version&lt;/code&gt; Show version number&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--id&lt;/code&gt; function id&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--secret&lt;/code&gt; function secret&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--init&lt;/code&gt; init new function (id and secret)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-f, --zip&lt;/code&gt; upload a function package (.zip)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-v, --verbose&lt;/code&gt; verbose level 0,1,2&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--log&lt;/code&gt; function log&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--about&lt;/code&gt; about&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note: The &lt;code&gt;--id&lt;/code&gt; and &lt;code&gt;--secret&lt;/code&gt; options are required. you can initialize new function using the &lt;code&gt;--init&lt;/code&gt; option. also you can pass these two options as an env variables &lt;code&gt;SFUNCTION_ID&lt;/code&gt; and &lt;code&gt;SFUNCTION_SECRET&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
Examples&lt;/h2&gt;
&lt;div class="highlight highlight-source-js notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;// simple index.js function&lt;/span&gt;
&lt;span class="pl-smi"&gt;module&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-c1"&gt;exports&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;handler&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-k"&gt;async&lt;/span&gt; &lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s1"&gt;event&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt; &lt;span class="pl-s1"&gt;context&lt;/span&gt;&lt;/pre&gt;…
&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/apotox/slsdz"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;this project is for learning and see how to use Terraform and AWS to build a serverless solution, its not the perfect way to build FAAS specialy for the cost, calling one AWS Lambda function from another Lambda function, often referred to as "double-calling," can indeed impact the cost and performance of your serverless application. When you invoke one Lambda function from another, you incur additional execution time, network latency, and potential resource usage, which can lead to increased costs and slower response times.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;iframe src="https://player.vimeo.com/video/851981171" width="710" height="399"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;You can use slsdz using npx:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn &lt;span class="nb"&gt;install
&lt;/span&gt;yarn bundle
&lt;span class="nb"&gt;cd &lt;/span&gt;demo
./mycli.js &lt;span class="nt"&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Options
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;--help&lt;/code&gt; Show help&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;--version&lt;/code&gt; Show version number&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;--id&lt;/code&gt; function id&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;--secret&lt;/code&gt; function secret&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;--init&lt;/code&gt; init new function (id and secret)&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;-f, --zip&lt;/code&gt; upload a function package (.zip)&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;-v, --verbose&lt;/code&gt; verbose level 0,1,2&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;--log&lt;/code&gt; function log&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;--about&lt;/code&gt; about&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note: The &lt;code&gt;--id&lt;/code&gt; and &lt;code&gt;--secret&lt;/code&gt; options are required. you can initialize new function using the &lt;code&gt;--init&lt;/code&gt; option. also you can pass these two options as an env variables &lt;code&gt;SFUNCTION_ID&lt;/code&gt; and &lt;code&gt;SFUNCTION_SECRET&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Examples
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// simple index.js function&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello World&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# bash&lt;/span&gt;
zip &lt;span class="k"&gt;function&lt;/span&gt;.zip index.js
./mycli.js &lt;span class="nt"&gt;--init&lt;/span&gt;
&lt;span class="c"&gt;# a .slsdz file will be generated which contains the function credentials&lt;/span&gt;
./mycli.js &lt;span class="nt"&gt;--zip&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;.zip


3:27:27 PM - API_URL:  your &lt;span class="k"&gt;function &lt;/span&gt;URL https://ABCDEF.safidev.de

ℹ file size: 283 bytes
3:27:29 PM - UPLOAD_STATUS:  200

✔ uploading &lt;span class="o"&gt;[&lt;/span&gt;/Users/mac/test/function.zip]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;h4&gt;
  
  
  AWS services:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Lambda (functions)&lt;/li&gt;
&lt;li&gt;ApiGateway (handle http requests)&lt;/li&gt;
&lt;li&gt;S3 (store functions codes)&lt;/li&gt;
&lt;li&gt;CloudFormation (create users functions)&lt;/li&gt;
&lt;li&gt;CloudWatch (logs)&lt;/li&gt;
&lt;li&gt;EventBridge (trigger function to create CNAME records)&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  external services:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Cloudflare&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;to interact with the service, developers use a CLI tool called slsdz without the need for any AWS-related authentication.&lt;/p&gt;

&lt;p&gt;Each user can initialize a function and receive an ID and a secret. The secret acts as an ID signature, which is used for uploading or updating a function. These data are saved in a local file called &lt;code&gt;.slsdz&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The slsdz CLI communicates with the serverless backend, where functions can be created, updated, and their logs can be retrieved. This backend utilizes API Gateway with Lambda integrations to manage the interactions.&lt;/p&gt;




&lt;p&gt;When a user uploads function code, a Lambda function called &lt;code&gt;Signer&lt;/code&gt; comes into play. The &lt;code&gt;Signer&lt;/code&gt; generates a signed URL &lt;code&gt;https://abc.users-functions.aws.../function-id.zip&lt;/code&gt; that allows users to upload the function code to an S3 bucket.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I intentionally included "function-id.zip" in the URL so that I can utilize it for the subsequent task of managing the S3 ObjectPut event.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The S3 bucket is configured to trigger another function called &lt;code&gt;Deployer&lt;/code&gt; when an ObjectPut event occurs. The &lt;code&gt;Deployer&lt;/code&gt; function reads the uploaded zip file, and it expects the zip file to be named like &lt;code&gt;function-id.zip&lt;/code&gt; , where "function-id" represents the unique ID of the function. This naming convention allows the &lt;code&gt;Deployer&lt;/code&gt; lambda function to determine which function should be updated/created.&lt;/p&gt;

&lt;p&gt;if the function is new (doesnt exists) the &lt;code&gt;Deployer&lt;/code&gt; function will build a cloudformation template that has all the required parameters to create:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;add new api mapping&lt;/li&gt;
&lt;li&gt;add new custom domain to apigateway custom domains&lt;/li&gt;
&lt;li&gt;a new lambda function with basic AMI role.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;resource "aws_iam_role" "user_lambda_role" {&lt;/span&gt;
  &lt;span class="s"&gt;name               = "basic-lambda-role-${local.stage_name}"&lt;/span&gt;
  &lt;span class="s"&gt;assume_role_policy = &amp;lt;&amp;lt;EOF&lt;/span&gt;
&lt;span class="pi"&gt;{&lt;/span&gt;
   &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Version"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2012-10-17"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
   &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Statement"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;
       &lt;span class="pi"&gt;{&lt;/span&gt;
           &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Action"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sts:AssumeRole"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
           &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Principal"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt;
               &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Service"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;lambda.amazonaws.com"&lt;/span&gt;
           &lt;span class="pi"&gt;},&lt;/span&gt;
           &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Effect"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Allow"&lt;/span&gt;
       &lt;span class="pi"&gt;}&lt;/span&gt;
   &lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="pi"&gt;}&lt;/span&gt;
 &lt;span class="s"&gt;EOF&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;stack name has function-id , so we can extract it easly when handling the creation event in &lt;code&gt;cname&lt;/code&gt; lambda function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stackName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`sls-stack-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;functionId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;in AWS console it will looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IFezmUXd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qeonhhmosyebr3we9e9f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IFezmUXd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qeonhhmosyebr3we9e9f.png" alt="stack creation" width="800" height="62"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When the CloudFormation stack successfully creates the resources, it publishes a "Stack Creation Event" to Amazon EventBridge.&lt;/p&gt;

&lt;p&gt;Where there is a Lambda function called &lt;code&gt;cname&lt;/code&gt; that is subscribed to the "Stack Creation Event" in EventBridge.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;cname&lt;/code&gt; Lambda function represent an integration with the Cloudflare API. It uses the "functionId" from the received EventBridge event to create a new CNAME record on Cloudflare.&lt;/p&gt;

&lt;p&gt;After the Lambda function is triggered and successfully creates the CNAME record through the Cloudflare API, you will see a new record added to your Cloudflare dashboard with the same "functionId" that was used in the Lambda function.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Jyr460GH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wamrdw4tcsvwrq5dlb9u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Jyr460GH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wamrdw4tcsvwrq5dlb9u.png" alt="cloudflare records" width="800" height="188"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Logs
&lt;/h1&gt;

&lt;p&gt;user can find a function's logs using the CLI by passing &lt;code&gt;--log&lt;/code&gt; option, i have chosen to use AWS CloudWatch as the primary logging service.&lt;/p&gt;

&lt;p&gt;AWS CloudWatch is a centralized monitoring and logging service provided by Amazon Web Services, It allows us to collect, store, and analyze logs from various AWS resources and applications in one place.&lt;/p&gt;

&lt;p&gt;The logging process involves a lambda function named &lt;code&gt;logger&lt;/code&gt; which facilitates secure access to AWS CloudWatch logs associated with each function by its unique Id.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;logGroupName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`/aws/lambda/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;buildFunctionName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;getCwClient&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;describeLogStreams&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="nx"&gt;logGroupName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;orderBy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;LastEventTime&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;descending&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;getCwClient&lt;/code&gt; is a CloudWatchLogs instance&lt;/p&gt;




&lt;h1&gt;
  
  
  Project Structure
&lt;/h1&gt;

&lt;p&gt;The project structure consists of three main components: sls-lambda, sls-cli, and infra. all of which have been implemented using TypeScript and Terraform for Infrastructure as Code (IaC).&lt;/p&gt;

&lt;p&gt;Yarn workspaces are utilized to facilitate the sharing of common dependencies between projects and enable running the test and bundle commands from a unified location.&lt;/p&gt;

&lt;p&gt;Project:&lt;br&gt;
-- sls-lambda&lt;br&gt;
-- sls-cli&lt;br&gt;
-- infra&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;sls-lambda&lt;/strong&gt;:&lt;br&gt;
This part of the project comprises separate folders, each representing a lambda function. Each folder contains an index.ts file that serves as the entrypoint or function handler for that specific lambda function.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;sls-cli&lt;/strong&gt;:&lt;br&gt;
The sls-cli component is implemented using Yargs, a popular command-line argument parser. This module provides the Command-Line Interface (CLI) for the project, allowing users to interact with the serverless FaaS provider and deploy their functions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;infra&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--v0k5uEXI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8gy8vf0g58jp2h530akg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--v0k5uEXI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8gy8vf0g58jp2h530akg.png" alt="infra folder" width="588" height="656"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The infra directory holds the Terraform code for managing the Infrastructure as Code (IaC). Specifically, the dev subdirectory contains all the required resources for the development environment. Each lambda function has its dedicated tf file, which begins with the prefix &lt;code&gt;fn-&lt;/code&gt;, making it easy to locate and manage individual functions' infrastructure.&lt;/p&gt;



&lt;p&gt;inside this infra directory you can see also the &lt;code&gt;data.tf&lt;/code&gt; which contain the part of zipping function bundles and generate release.zip files, and also this tf file define all the required Policies (aws_iam_policy resources).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;locals&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;functions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s2"&gt;"cname"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"deployer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"signer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"logger"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"sls_proxy"&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;locals&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;lambda_files&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;fn&lt;/span&gt; &lt;span class="nx"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;local&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;functions&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fn&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;source_file&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"${path.module}/../../dist/${fn}/bundle.js"&lt;/span&gt;
      &lt;span class="nx"&gt;output_path&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"${path.module}/../../release/${fn}.zip"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"archive_file"&lt;/span&gt; &lt;span class="s2"&gt;"zipped"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;for_each&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;local&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lambda_files&lt;/span&gt;
  &lt;span class="nx"&gt;depends_on&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;null_resource&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bundle&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"zip"&lt;/span&gt;
  &lt;span class="nx"&gt;source_file&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;each&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;source_file&lt;/span&gt;
  &lt;span class="nx"&gt;output_path&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;each&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;output_path&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;each policy resource definition is declared in a json template inside &lt;code&gt;/templates&lt;/code&gt;. by using &lt;code&gt;templatefile&lt;/code&gt; function it can populate the policy attributes from json content.&lt;/p&gt;




&lt;p&gt;for example in the &lt;code&gt;fs-cname.tf&lt;/code&gt; file, you found the usage of a data source called &lt;code&gt;zipped&lt;/code&gt; in the &lt;code&gt;aws_lambda_function&lt;/code&gt; resource.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_lambda_function"&lt;/span&gt; &lt;span class="s2"&gt;"cname"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;depends_on&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;null_resource&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bundle&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nx"&gt;function_name&lt;/span&gt;                  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"${var.project_name}-${var.stage_name}-cname"&lt;/span&gt;
  &lt;span class="nx"&gt;filename&lt;/span&gt;                       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;archive_file&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;zipped&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"cname"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;output_path&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Deploy on your own aws account
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone it
yarn &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# before deploying you need to set up some variables,&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;AWS_ACCESS_KEY_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;AWS_SECRET_ACCESS_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;TF_VAR_custom_api_domain_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;api.example.com
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;TF_VAR_signing_secret&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="c"&gt;# used to sign the function id&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;TF_VAR_cloudflare_zone_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;TF_VAR_cloudflare_email&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;TF_VAR_cloudflare_api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;TF_VAR_certificate_arn&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="c"&gt;#https://docs.aws.amazon.com/acm/latest/userguide/gs-acm-request-public.html&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and you need to add your own domain name to cloudflare example "api.example.de" and create new CNAME record point to your apigateway.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IZe_oIHO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dl5qlgbiftpbvmhdizo6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IZe_oIHO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dl5qlgbiftpbvmhdizo6.png" alt="cname record" width="800" height="39"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# edit `infra/globals/s3/main.tf` and comment the S3 backend, we need to do this onetime because the s3 bucket doesnt exists yet. it will be created in the next step.&lt;/span&gt;

&lt;span class="c1"&gt;# terraform {&lt;/span&gt;
&lt;span class="c1"&gt;#   backend "s3" {&lt;/span&gt;
&lt;span class="c1"&gt;#     bucket         = "sls-lambda-terraform-state"&lt;/span&gt;
&lt;span class="c1"&gt;#     key            = "global/s3/terraform.tfstate"&lt;/span&gt;
&lt;span class="c1"&gt;#     region         = "us-east-1"&lt;/span&gt;
&lt;span class="c1"&gt;#     dynamodb_table = "sls-lambda-terraform-locks"&lt;/span&gt;
&lt;span class="c1"&gt;#     encrypt        = true&lt;/span&gt;
&lt;span class="c1"&gt;#   }&lt;/span&gt;
&lt;span class="c1"&gt;# }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# now run&lt;/span&gt;
terraform &lt;span class="nt"&gt;--chdir&lt;/span&gt; infra/globals/s3 init
terraform &lt;span class="nt"&gt;--chdir&lt;/span&gt; infra/globals/s3 apply &lt;span class="nt"&gt;--auto-approve&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# edit `infra/globals/s3/main.tf` and uncomment the S3 backend section&lt;/span&gt;

&lt;span class="s"&gt;terraform {&lt;/span&gt;
&lt;span class="s"&gt;backend "s3" {&lt;/span&gt;
&lt;span class="s"&gt;bucket         = "sls-lambda-terraform-state"&lt;/span&gt;
&lt;span class="s"&gt;key            = "global/s3/terraform.tfstate"&lt;/span&gt;
&lt;span class="s"&gt;region         = "us-east-1"&lt;/span&gt;
&lt;span class="s"&gt;dynamodb_table = "sls-lambda-terraform-locks"&lt;/span&gt;
&lt;span class="s"&gt;encrypt        = &lt;/span&gt;&lt;span class="no"&gt;true&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# now we can enable remote backend by running again init and apply&lt;/span&gt;
terraform &lt;span class="nt"&gt;--chdir&lt;/span&gt; infra/globals/s3 init
terraform &lt;span class="nt"&gt;--chdir&lt;/span&gt; infra/globals/s3 apply &lt;span class="nt"&gt;--auto-approve&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;in &lt;code&gt;infra/dev&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# infra/dev contains all files required to setup an envirenmnt. in infra/dev/main.tf you can see backend section has a diffrent key = "dev/terraform.tfstate". to deploy diffrent env stage for example 'prod' you can copy the dev folder and name it prod and set the key to "prod/terraform.tfstate".&lt;/span&gt;

terraform &lt;span class="o"&gt;{&lt;/span&gt;
   backend &lt;span class="s2"&gt;"s3"&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
     bucket         &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"sls-lambda-terraform-state"&lt;/span&gt;
     key            &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"dev/terraform.tfstate"&lt;/span&gt;  &amp;lt;&lt;span class="nt"&gt;--&lt;/span&gt; this should be unique &lt;span class="k"&gt;for &lt;/span&gt;each dev envirenmnt
     region         &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"us-east-1"&lt;/span&gt;
     dynamodb_table &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"sls-lambda-terraform-locks"&lt;/span&gt;
     encrypt        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;
   &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

terraform &lt;span class="nt"&gt;--chdir&lt;/span&gt; infra/dev init
terraform &lt;span class="nt"&gt;--chdir&lt;/span&gt; infra/dev apply &lt;span class="nt"&gt;--auto-approve&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Update CLI consts
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;slsdz&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;cli&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;consts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SLSDZ_CONFIG_FILENAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.slsdz&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SLSDZ_DOMAIN_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;example.de&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SLSDZ_API_BASE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SLSDZ_API_BASE_URL&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.example.de&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;slsdz&lt;/code&gt; means serverless and dz is a country abbreviation that most of Algerian developers love to add to their project so i did ✨&lt;/p&gt;

&lt;p&gt;this small project is a developer-friendly, serverless FaaS provider that simplifies the deployment of functions to AWS accounts using a CLI tool and a secure signature-based authentication method.&lt;/p&gt;

&lt;p&gt;The deployment process involves utilizing a signer function to generate a signed URL for S3 uploads, which then triggers a deployer function to read and update the respective function based on the provided ID in the zip file name.&lt;/p&gt;

&lt;p&gt;project still needs lot of work (ex: Monitoring,Logging) to be a prod ready but i think its not that hard specially with AWS services and integrations. if you have any additional ideas or question just ping me.&lt;/p&gt;

</description>
      <category>serverless</category>
      <category>aws</category>
      <category>faas</category>
      <category>cli</category>
    </item>
  </channel>
</rss>
