{"id":28003150,"url":"https://github.com/fnproject/fdk-node","last_synced_at":"2025-05-09T01:59:11.183Z","repository":{"id":41971781,"uuid":"117882818","full_name":"fnproject/fdk-node","owner":"fnproject","description":"Experimental FDK for Node.js","archived":false,"fork":false,"pushed_at":"2025-04-24T09:17:50.000Z","size":564,"stargazers_count":23,"open_issues_count":14,"forks_count":12,"subscribers_count":29,"default_branch":"master","last_synced_at":"2025-05-09T01:59:06.567Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fnproject.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-01-17T19:29:33.000Z","updated_at":"2025-04-24T09:17:47.000Z","dependencies_parsed_at":"2023-12-12T12:27:27.439Z","dependency_job_id":"1c828094-c737-4490-ad29-7a1aa4ff0a24","html_url":"https://github.com/fnproject/fdk-node","commit_stats":{"total_commits":129,"total_committers":15,"mean_commits":8.6,"dds":0.5193798449612403,"last_synced_commit":"a09ac9611983968c150a5213e0a8e29ad0280158"},"previous_names":[],"tags_count":73,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fnproject%2Ffdk-node","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fnproject%2Ffdk-node/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fnproject%2Ffdk-node/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fnproject%2Ffdk-node/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fnproject","download_url":"https://codeload.github.com/fnproject/fdk-node/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253176436,"owners_count":21866142,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-05-09T01:59:10.748Z","updated_at":"2025-05-09T01:59:11.160Z","avatar_url":"https://github.com/fnproject.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Fn Function Developer Kit for Node.js\n\nThis Function Developer Kit makes it easy to deploy Node.js functions to Fn.\nIt currently supports default (cold) and hot functions using the JSON format.\n\n## Creating a Node Function\n\nWriting a Node.js function is simply a matter of writing a handler function\nthat you pass to the FDK to invoke each time your function is called.\n\nStart by creating a node function with `fn init` and installing the FDK:\n\n```sh\nfn init --runtime node nodefunc\ncd nodefunc\n```\n\nThis creates a simple hello world function in `func.js`:\n\n```javascript\nconst fdk=require('@fnproject/fdk');\n\nfdk.handle(function(input){\n  let name = 'World';\n  if (input.name) {\n    name = input.name;\n  }\n  return {'message': 'Hello ' + name}\n})\n```\n\nThe handler function takes the string input that is sent to the function\nand returns a response string.  Using the FDK you don't have to worry about reading\ninput from standard input and writing to standard output to return your response.\nThe FDK let's you focus on your function logic and not the mechanics.\n\nNow run it!\n\n```sh\nfn deploy --local --app fdkdemo \nfn invoke fdkdemo nodefunc \n```\n\nNow you have a basic running Node function that you can modify and add what you want.\n\n\n```sh\necho -n '{\"name\": \"Tom\"}' | fn invoke fdkdemo nodefunc\n```\n\n\nYou should see the result\n\n```sh\n{\"message\": \"Hello Tom\"}\n```\n\n## Function Context\n\nFunction invocation context details are available through an optional function argument.\nTo receive a context object, simply add a second argument to your handler function.\nin the following example the `callID` is obtained from the context and included in \nthe response message:\n\n```javascript\nconst fdk=require('@fnproject/fdk');\n\nfdk.handle(function(input, ctx){\n  let name = 'World';\n  if (input) {\n    name = input;\n  }\n  return 'Hello ' + name + ' from Node call ' + ctx.callID + '!';\n})\n```\n\n\nThe context contains other context information about the request such as: \n\n* `ctx.config` : An Object containing function config variables (from the environment ) (read only)\n* `ctx.headers` : an object containing input headers for the event as lists of strings (read only)\n* `ctx.deadline` : a `Date` object indicating when the function call must be processed by \n* `ctx.callID` : The call ID of the current call \n* `ctx.fnID` : The Function ID of the current function \n* `ctx.memory` : Amount of ram in MB allocated to this function \n* `ctx.contentType` : The incoming request content type (if set, otherwise null)\n* `ctx.setResponseHeader(key,values...)` : Sets a response header to one or more values \n* `ctx.addResponseHeader(key,values...)` : Appends values to an existing response header\n* `ctx.responseContentType` set/read the response content type of the function (read/write)\n* `ctx.httpGateway`  The HTTP Gateway context for this function (if set) see `HTTPGatewayContext` below  \n\n \n\n## Asynchronous function responses\n\nYou return an asynchronous response from a function by returning a Javascript `Promise` from the function body: \n\n```javascript\nconst fdk=require('@fnproject/fdk');\n\nfdk.handle(function(input, ctx){\n  return new Promise((resolve,reject)=\u003e{\n     setTimeout(()=\u003eresolve(\"Hello\"),1000);\n  });\n})\n```\n\nYou can also  use `async`/`await` calling conventions in functions. \n \n## Handling non-json input and output\n\nBy default the FDK will try and convert input into a JSON object, or fall back to its string format otherwise. \n\nLikewise by default the output of a function will be treated as a JSON object and converted using JSON.stringify. \n\n\nTo change the handling of the input you can add an additional `options` parameter to `fdk.handle` that specifies the input handling strategy: \n\n```javascript\nfunction myfunction(input,ctx){}\n\nfdk.handle(myfunction, {inputMode: 'string'})\n```\n\nvalid input modes are: \n*  `json` (the default) attempts to parse the input as json or falls back to raw (possibly binary) string value otherwise\n* `string` always treats input as a string \n* `buffer` reads input into a `Buffer` object and passes this to your function \n\nTo change the output handling of your function from the default you should wrap the result value using a response decorator: \n\n```javascript\nfunction myfunction(input,ctx){\n   return fdk.rawResult(\"Some string\")\n}\n\nfdk.handle(myfunction)\n```\n\nthe available decorators are: \n* `rawResult({string|Buffer})` passes the result directly to the response - the value can be a string or a buffer - this will not encode quotes on string objects \n* `streamResult({ReadableStream})` pipes the contents of a `ReadableStream` into the output - this allows processing of data from files or HTTP responses \n\n\n## Using HTTP headers and setting HTTP status codes\nYou can read http headers passed into a function invocation using `ctx.protocol.header(key)`, this returns the first header value of the header matching `key` (after canonicalization)  and `ctx.protocol.headers` which returns an object containing all headers.  \n\n```javascript\nconst fdk=require('@fnproject/fdk');\n\nfdk.handle(function(input, ctx){\n  \n  let hctx = ctx.httpGateway\n  console.log(\"Request URL\" , hctx.requestURL)\n  \n  console.log(\"Authorization header:\" , hctx.getHeader(\"Authorization\"))\n  console.log( hctx.headers) // prints e.g. { \"Content-Type\": [\"application/json\"],\"Accept\":[\"application/json\",\"text/plain\"] } \n})\n```\n\nOutbound headers and the HTTP status code can be modified in a similar way:  \n\n```javascript\nconst fdk=require('@fnproject/fdk');\n\nfdk.handle(function(input, ctx){\n    let hctx = ctx.httpGateway\n\n   hctx.setResponseHeader(\"Location\",\"http://example.com\")\n   hctx.statusCode = 302\n})\n```\n\nThe `HTTPGatewayContext` object has a similar interface to `Context` but accesses only the HTTP headers of the function: \n\n* `hctx.requestURL` : Get the http request URL of the function as received by the gateway (null if not set)\n* `hctx.method` : Get the HTTP request method used to invoke the gateway \n* `hctx.headers` : Get the HTTP headers of the incoming request (read-only)\n* `hctx.statusCode` : Set the the HTTP status code of the HTTP resposne \n\u0026 `hctx.setResponseHeader(key,values..)`, `hctx.addResponseHeader(key,values)` Set/add response headers \n\n## Fn and Node.js Dependencies\nFn handles Node.js dependencies in the following way:\n* If a `package.json` is present without a `node_modules` directory, an Fn build runs an `npm install` within the build process and installs your dependencies.\n* If the `node_modules` is present, Fn assumes you have provided the dependencies yourself and no installation is performed.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffnproject%2Ffdk-node","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffnproject%2Ffdk-node","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffnproject%2Ffdk-node/lists"}