{"id":16427060,"url":"https://github.com/donavon/lambdog-server","last_synced_at":"2025-10-07T11:55:12.801Z","repository":{"id":34735524,"uuid":"182599049","full_name":"donavon/lambdog-server","owner":"donavon","description":"Write Netlify functions without pulling your hair out.","archived":false,"fork":false,"pushed_at":"2023-01-06T01:48:54.000Z","size":2056,"stargazers_count":15,"open_issues_count":15,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-17T20:44:58.623Z","etag":null,"topics":["aws-lambda","netlify","netlify-lambda","serverless","serverless-framework"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/donavon.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}},"created_at":"2019-04-22T00:56:39.000Z","updated_at":"2020-11-06T23:40:14.000Z","dependencies_parsed_at":"2023-01-15T08:51:37.026Z","dependency_job_id":null,"html_url":"https://github.com/donavon/lambdog-server","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/donavon%2Flambdog-server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/donavon%2Flambdog-server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/donavon%2Flambdog-server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/donavon%2Flambdog-server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/donavon","download_url":"https://codeload.github.com/donavon/lambdog-server/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244738172,"owners_count":20501788,"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":["aws-lambda","netlify","netlify-lambda","serverless","serverless-framework"],"created_at":"2024-10-11T08:11:23.791Z","updated_at":"2025-10-07T11:55:12.690Z","avatar_url":"https://github.com/donavon.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\u003cimg\n  height=\"200\"\n  width=\"200\"\n  alt=\"part lamb, part dog\"\n  src=\"https://user-images.githubusercontent.com/887639/56451023-b2ef9280-62f7-11e9-8897-7de261cf0797.png\"\n/\u003e\n\u003cp\u003eIt's part lamb. It's part dog. It's Lambdog.\u003c/p\u003e\n\u003c/div\u003e\n\nOk, so what IS Lambdog? Lambdog is a set of packages (one for the client, and one for the server)\nthat makes it easy to call and write Lambda functions for AWS. You can use either one independently, or use them together.\n\n\u003e ⚡️ New in v0.3.0... ROUTES! ⚡️\n\n## @lambdog/server\n\n@lambdog/server consists of a higher order function that\nyou can use to wrap your plain JavaScript function that will do all of the work to turn it into\nan AWS Lambda function. You concentrate on your code, let Lambdog do the rest.\n\nLet's look at a quick example. Say you have a \"Hello World\" function that you would\nlike to run on the server. It should be as simple as this.\n\n```js\nconst hello = ({ name = 'World' }) =\u003e `Hello, ${name}!`;\n```\n\nI say \"should\" because that's not all you have to do. To make it a Lambda function,\nthere are a few more things you need to do.\n\nFirst, you must create an object with a `statusCode` property set to 200 (OK).\nNext, you take the results from calling `hello` and assign that to the `body` property,\nbut first, you must `JSON.stringify` it. Then you call the callback function with the results.\n\nWhew! That'a a lot of \"plumbing\" for a simple \"Hello World\" function. And you can barely even\nsee your core function.\nWhatever happened to the design principle talking about the\n[separation of concerns](https://en.wikipedia.org/wiki/Separation_of_concerns)?\nAnd exactly what is `queryStringParameters` anyway? ¯\\\\_(ツ)_/¯\n\n```js\nexport function handler(event, context, callback) {\n  callback(null, {\n    statusCode: 200,\n    body: JSON.stringify(\n      `Hello, ${event.queryStringParameters.name || 'World'}!`\n    ),\n  });\n}\n```\n\n### Enter Lambdog\n\nWith Lambdog, we can take our simple `hello` function from above, wrap it and export it.\nThe plumbing is hidden away. You don't have to concern yourself with HTTP, status codes, headers, or caching.\n\n```js\nimport { withJSONHandler } from '@lambdog/server';\n\nconst hello = ({ name = 'World' }) =\u003e `Hello, ${name}!`;\n\nexport const handler = withJSONHandler(hello);\n```\n\nYou would call this from your client by doing a GET to `/hello?name=Joe`.\n\n### Other benefits\n\nOh, and there are a few other benefits that you get out of the box—for free.\n\n- Your return value is automatically `JSON.stringify`'ed and added to `body`.\n\n- Automatic `etag`/`if-none-match` generation/matching to return a 304 status code means fewer bits pass over the wire.\n\n- If your function is \"pure\" (i.e. has no side effects), there is an optional setting that allows you to set \"max-age\" caching.\n\n- Automatic `try`/`catch` to produce 400 server errors.\n\n- Support for `props` based on query parameters, URL pattern matching (i.e. /.netlify/functions/hello/:name), or POST/PUT data.\n\n## Installation\n\n```bash\n$ npm i @lambdog/server\n```\n\nor\n\n```bash\n$ yarn add @lambdog/server\n```\n\n## Usage\n\nHere is a basic setup.\n\n```js\nimport { withJSONHandler } from '@lambdog/server';\n\nexport const handler = withJSONHandler(function, config);\n```\n\n### Parameters\n\nHere are the parameters that you can use.\n\n| Parameter                    | Description                                            |\n| :--------------------------- | :----------------------------------------------------- |\n| `function` or `routes` table | The function to wrap. See below for passed parameters. |\n| `config`                     | An optional configuration object.                      |\n\n### Return\n\n`withJSONHandler` returns a function that can be exported as `handler`.\n\n### Configuration object\n\nThe configuration object has the following options.\n\n| Parameter       | Description                                                                                                                                                                                                                                            |\n| :-------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `pathToProps`   | A string used for URL pattern matching. For example, if you want the URL `/.netlify/functions/hello/World` to call your `hello` function and pass \"World\" as the `name` prop, set `pathToProps` to \":name\". This value ignored if using a route table. |\n| `errorCallback` | A callback function that you can use to format an error.                                                                                                                                                                                               |\n| `maxAge`        | The `max-age` that the client can cache the response. Set to -1 (default) if you don't want the response cached.                                                                                                                                       |\n\n## Your function\n\n### Parameters\n\nYour function will be called with two arguments. The first is a consolidated `props` object. It is built from POST data, URL pattern matching (i.e. :name), and query parameters, in that order.\n\n\u003e Note: POST data will only be decoded if the `Content-Type` header is `application/json` (for JSON encoded) or `application/x-www-form-urlencoded` (for URL encoded).\n\nThe second argument is your \"escape hatch\" in case your function needs to know more about\nhow it was called. For example, you can check for a particular header value,\nor get the entire post data even if the `Content-Encoding` wasn't properly set.\n\nIt contains the following fields.\n\n#### `event`\n\nThe original `event` object passed to the `handler`.\n\n#### `context`\n\nThe `context` object used for Netlify Identity (see the [Netlify docs](https://docs.netlify.com/functions/functions-and-identity/) for details).\n\n#### `query`\n\nA key/value pair containing query parmeters. For example, if the query string on the URL were `?foo=bar`, then `query` would contain the object `{ foo: 'bar' }`.\n\n#### `body`\n\nA decoded representation on the HTTP body. For example, this will be an object if `Content-Type` is `application/json`.\n\n#### `params`\n\nParameters from URL derived from the route or from `pathToProps`.\n\n#### `route`\n\nThe matching route.\n\n### Throwing\n\nIf you throw an error, Lambdog will, by default (unless you set `errorCallback` in config), format a status code of 400\nwith the error message as the body.\n\nIf you throw an object, Lambdog will return that object \"as-is\".\nThis is your response escape hatch.\n\n### Routes\n\nIf the first parameter to `withJSONHandler` is not a function, then it will be considered a route table. A route table is an array of routes.\n\nLambdog will return with the first matching route, so place you most specific routes first and get more general as you go.\n\nA route has the following properties.\n\n#### `method`\n\nThe HTTP method to match. If unspecified, the route will patch all methods.\n\n#### `path`\n\nA path segment used to match against the URL. A value starting with a `:` (colon) will interpret the current path segment as a parameter (i.e. will be added to the `params` object).\n\nIf `path` is `*` (i.e. an asterisk) it will match all segments and any remaining segments.\n\nIf `path` is `.` (i.e. an period) it will match the current segment only.\n\n#### `handler`\n\nIf the route mathes, this handler will be called.\n\n#### `children`\n\nAn array of child routes.\n\n### Sample routes table\n\nHere is an example of a typical CRUD routes table.\n\n```js\n[\n  {\n    method: 'get',\n    path: 'orders',\n    handler: getAllOrders,\n  },\n  {\n    method: 'post',\n    path: 'orders',\n    handler: createOrder,\n  },\n  {\n    path: 'orders',\n    children: [\n      { method: 'get', path: ':orderId', handler: getOrder },\n      { method: 'put', path: ':orderId', handler: updateOrder },\n      { method: 'delete', path: ':orderId', handler: deleteOrder },\n    ],\n  },\n  { path: '*', handler: notFound },\n];\n```\n\nGiven the route above, a URL of `/orders/123` will call `getOrder` passing a `params` of `{ orderId: '123' }`.\n\nA `get` from `/orders` would call `getAllOrders` with `params` of `{}`.\n\nA `post` to `/orders` would call `createOrder`.\n\nA `put` to `/orders/123` would call `updateOrder`.\n\nBecasue the last route does not specify a method, and has a path of `*`, any non-matching URL, with any method, will result in calling `notFound`. This is your \"catch-all\" handler. If you do not specify a catch-all handler, Lambdog will return a `404 Not Found`.\n\n### Return value\n\nYour function can return a value directly, or it can be an `async` function\nwhat resolves to a value (i.e. return a Promise).\n\nThe results from your function will be JSON stringified and\nplaced in the body.\nAn `etag` hash of the body will also be included in the header.\n\nA `status` of 200 will be used, unless your function returns `undefined`, in which case a 204 will be used.\n\nLambdog will also set the content type to `application/json`.\n\n## License\n\n**[MIT](LICENSE)** Licensed\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdonavon%2Flambdog-server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdonavon%2Flambdog-server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdonavon%2Flambdog-server/lists"}