openfaas / store

Official Function and Template Store for OpenFaaS
MIT License
163 stars 56 forks source link

Submission: bun.sh (JavaScript runtime) #155

Open patlux opened 1 year ago

patlux commented 1 year ago

I would like to suggest adding a bun template to the official store.

https://github.com/patlux/openfaas-bun-template

Proposed templates.json:

  {
        "template": "bun",
        "platform": "x86_64",
        "language": "bun",
        "source": "patlux",
        "description": "bun runtime template based on a debian image",
        "repo": "https://github.com/patlux/openfaas-bun-template",
        "official": "false"
}

What is bun?

Bun is a fast all-in-one JavaScript runtime Run, test, transpile, and bundle JavaScript & TypeScript projects — all in Bun. Bun is a new JavaScript runtime built for speed, with a native bundler, transpiler, test runner, and npm-compatible package manager baked-in.

alexellis commented 1 year ago

Thanks for the submission.

@LucasRoesler can you please make all the necessary suggestions - like:

Example of how to use a package manager within the template, and how to consume a package within a handler.

Making the Dockerfile use a non-root user

And all that kind of stuff?

LucasRoesler commented 1 year ago

Hi @patlux there are a couple of things that I notice in your template

  1. the use of multistage build is good
  2. the final image should use a non-root user. The python template also uses debian, so you can take a look here for an example of creating and setting the non-root user https://github.com/LucasRoesler/python-flask-template/blob/master/template/python3-http-debian/Dockerfile
  3. Another thing that seems to be missing is a clear separation between the function template and the user's handler implementation. Most templates we include into the store standardize the server setup and configuration outside of the handler. Again looking at the python template, you can see an index.py at next to the Dockerfile. This content is hidden from the template users can contains the standard server bootstrap logic. We even do this in compiled languages like Go, see the main.go in this template I would expect your Dockerfile to have multiple COPY statements here one that copies the user's handler implementation and at least one that copies the core template Typescript files, probably and index.ts. This index.ts would mostly look like the one you already have, but it would import the user's handler function and pass it here during configuration.
  4. There seems to be a bit of boiler plate text and code that should be removed. I assume that this comes from the bun init, but things like this log statement should generally be avoided. Relatedly, the handler readme is a great opportunity to provide instructions on how to use the template. The current default text from bun init is likely to cause confusion because it likely doesn't apply very well when the project is templated
patlux commented 1 year ago

@LucasRoesler Thank you for the detailed answer!

  1. Understood. I will update it 👍

I tried, but how does the development cycle works here?

As a user, I want to have a nice DX where I can run my server with live-reload when I update my code.

With the current approach I do the following steps:

faas-cli new my-fancy-bun --lang bun
tree my-fancy-bun
├── my-fancy-bun
│   ├── README.md
│   ├── bun.lockb
│   ├── index.ts
│   ├── package.json
│   └── tsconfig.json

cat index.ts
# export const bunServeOptions: Serve = {
#  port: 3000,
#  fetch: (request: Request) => {
#    return new Response('Hello via Bun!', { status: 200 })
#  },
# }

cd my-fancy-bun
bun run --watch index.ts

Now I can make changes to index.ts and it reloads the updated code automatically and I can code my awesome things like I do with any other project which works with bun.

When I finish I just run

cd ..
faas-cli up -f my-fancy-bun.yml

But how do I this with your suggested approach?

faas-cli new my-fancy-bun --lang bun
tree my-fancy-bun
├── my-fancy-bun
│   ├── README.md
│   ├── bun.lockb
│   ├── handler.ts
│   ├── package.json
│   └── tsconfig.json

cd my-fancy-bun
cat handler.ts
# export const handler = (request: Request) => {
#  return new Response(`Hello from bun via openfaas!`)
# }

Now what? How do I develop now my function without having to rebuild the docker image on each change?

I can't just run bun run handler.ts.

  1. Understood. I will update it 👍
patlux commented 1 year ago
  1. https://github.com/patlux/openfaas-bun-template/commit/e4e11bf73a7c5cc4235209aa4b4617948af8039e
  2. https://github.com/patlux/openfaas-bun-template/commit/9f025579c257219a5856512263b775091d7b0b61
patlux commented 1 year ago
  1. https://github.com/patlux/openfaas-bun-template/commit/9fe42953613c2d552502ea9e1834a4c9310d89ec

Ok I think I found a solution to my problem mentioned in my previous comment.

I hope I could address all your comments :)

LucasRoesler commented 1 year ago

@patlux it is looking pretty good. But I have a question about dependency management. The template has two package.json files in it. When i look at the Dockerfile, it isn't obvious to me when the index.ts or the package.json from the template is copied into the Docker image. I see it only copy and build the handler code. is this expected?

I think it would be interesting to see an example of a project with a non-trivial dependency.

I would be also curious to see an example where the user accidentally sets the port in their handler and then we see the warning message from index.ts in the logs.