{"id":33751904,"url":"https://github.com/pxseu/fami","last_synced_at":"2026-04-02T13:43:18.028Z","repository":{"id":325918181,"uuid":"1103579260","full_name":"pxseu/fami","owner":"pxseu","description":"Working with cookies shouldn't be complicated or scary.","archived":false,"fork":false,"pushed_at":"2026-03-26T00:47:02.000Z","size":404,"stargazers_count":9,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"senpai","last_synced_at":"2026-03-26T19:49:23.749Z","etag":null,"topics":["cookies","http","rfc6265","rfc6265bis"],"latest_commit_sha":null,"homepage":"https://npm.im/fami","language":"TypeScript","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/pxseu.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["pxseu"]}},"created_at":"2025-11-25T04:00:04.000Z","updated_at":"2026-03-17T09:34:13.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/pxseu/fami","commit_stats":null,"previous_names":["pxseu/fami"],"tags_count":25,"template":false,"template_full_name":null,"purl":"pkg:github/pxseu/fami","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pxseu%2Ffami","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pxseu%2Ffami/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pxseu%2Ffami/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pxseu%2Ffami/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pxseu","download_url":"https://codeload.github.com/pxseu/fami/tar.gz/refs/heads/senpai","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pxseu%2Ffami/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31120886,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-28T17:50:59.904Z","status":"ssl_error","status_checked_at":"2026-03-28T17:50:59.435Z","response_time":79,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["cookies","http","rfc6265","rfc6265bis"],"created_at":"2025-12-05T06:04:20.931Z","updated_at":"2026-04-02T13:43:18.015Z","avatar_url":"https://github.com/pxseu.png","language":"TypeScript","readme":"# fami\n\n![NPM Version](https://img.shields.io/npm/v/fami) ![License](https://img.shields.io/npm/l/fami) ![npm package minimized gzipped size](https://img.shields.io/bundlejs/size/fami) [![Publishing](https://github.com/pxseu/fami/actions/workflows/publish.yml/badge.svg)](https://github.com/pxseu/fami/actions/workflows/publish.yml) [![Tests](https://github.com/pxseu/fami/actions/workflows/test.yml/badge.svg)](https://github.com/pxseu/fami/actions/workflows/test.yml)\n\nWorking with cookies shouldn't be complicated or scary. **fami** makes HTTP cookie management simple, safe, and of course type-safe.\n\n**fami** is a lightweight library focused on correctness and developer experience, following modern RFC 6265bis standards with an intuitive API designed for today's web.\n\n## Table of Contents\n\n- [Features](#features)\n- [Why fami?](#why-fami)\n- [Compatibility](#compatibility)\n- [Installation](#installation)\n- [Quick Start](#quick-start)\n  - [High-level API (recommended)](#highlevel-api-recommended)\n  - [Low-level API](#lowlevel-api)\n- [Framework Integration](#framework-integration)\n  - [Kaito](#kaito)\n  - [Express](#express)\n- [RFC Compliance](#rfc-compliance)\n- [Inspirations](#inspirations)\n- [Development](#development)\n- [License](#license)\n\n## Features\n\n- Schema-based abstraction for cookie definitions and serializing/parsing cookies with type safety\n- Flexible cookie parsing/serialization\n- First‑class integration with [**Express**](https://expressjs.com/) and [**Kaito**](https://github.com/kaito-http/kaito)\n- Safe, predictable behavior following the latest HTTP State Management draft ([RFC 6265bis](https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis-21))\n- Strong TypeScript support with extensive JSDoc\n- Zero dependencies, tiny footprint\n\n## Why fami?\n\nIf you're already using a cookie library, you might wonder why you should switch. Here's what sets **fami** apart:\n\n**vs. [`cookie`](https://github.com/jshttp/cookie)** (the most popular choice)\n\n\u003e **Note:** `cookie` is a perfectly valid choice and is very well maintained. It has been around for a long time and is a well-established library with battle-tested code and a large community.\n\n- fami provides a high-level schema-based API that prevents cookie configuration drift across your codebase\n- Full RFC 6265bis compliance with modern parsing rules\n- Better TypeScript support with extensive JSDoc comments\n\n**vs. rolling your own**\n\n- Cookie parsing/serialization has many edge cases (whitespace, special characters, encoding, attribute ordering)\n- RFC 6265bis compliance requires careful handling of modern attributes\n- Manual cookie handling is error-prone (typos, missing attributes, type mismatches) and hard to maintain across a codebase\n\n**Perfect for:**\n\n- New projects that want modern cookie handling out of the box\n- Teams migrating to edge runtimes or modern frameworks\n- Developers who want type-safe cookie management with minimal boilerplate\n\n## Compatibility\n\n**fami** is runtime-agnostic and works in all of your favorite runtimes. Such as but not limited to: Bun, Node.js, Deno, Cloudflare Workers, Vercel, Netlify, and more.\n\n## Installation\n\n```bash\nbun add fami\n# or\nnpm install fami\n# or\nyarn add fami\n# or\npnpm add fami\n```\n\n## Quick Start\n\n### High‑level API (recommended)\n\nThe High-level API provides a simple and intuitive abstraction for managing your cookie attributes and names. Define your cookie names once and use them throughout your application with full type safety. Set sane defaults for your cookies and serialize/parse them worry free of edge cases.\n\n```ts\nimport { Fami } from \"fami\";\n\nconst fami = new Fami({\n\ttheme: {},\n\tsession: {\n\t\thttpOnly: true,\n\t\tsecure: true,\n\t\tmaxAge: 3600,\n\t},\n});\n\nconst cookies = fami.parse(\"theme=light; session=value\");\n\nconsole.log(cookies);\n// { theme: \"light\", session: \"value\" }\n\nconst theme = fami.serialize(\"theme\", \"light\");\nconsole.log(theme);\n// \"theme=light\"\n\n// You can also override the default attributes with your own\nconst session = fami.serialize(\"session\", \"value\", {\n\tmaxAge: 7200,\n});\nconsole.log(session);\n// \"session=value; Max-Age=7200; Secure; HttpOnly\"\n\nconst deleteSession = fami.delete(\"session\");\nconsole.log(deleteSession);\n// \"session=; Max-Age=0; Expires=Thu, 01 Jan 1970 00:00:00 GMT\"\n```\n\n### Low‑level API\n\nUseful when you want more control or are moving away from other libraries. You can easily check if Fami is compatible with your existing code. If it is, you _should_ migrate over to the High-level API.\n\n```ts\nimport { parse } from \"fami\";\n\nconst cookies = parse(\"foo=bar; baz=qux\");\n\nconsole.log(cookies);\n// { foo: \"bar\", baz: \"qux\" }\n```\n\n```ts\nimport { serialize } from \"fami\";\n\nconst cookie = serialize(\"session\", \"value\", {\n\thttpOnly: true,\n\tsecure: true,\n\tmaxAge: 3600,\n});\n\nconsole.log(cookie);\n// \"session=value; Max-Age=3600; Secure; HttpOnly\"\n```\n\n## Framework Integration\n\n### Kaito\n\n**[Kaito](https://github.com/kaito-http/kaito)** is a modern, type-safe functional HTTP framework.\n\nfami provides first‑class [**Kaito**](https://github.com/kaito-http/kaito) support through a tiny utility that extends the Kaito context with fami's methods. The utility adds functions like `ctx.setCookie(\"session\", \"value\")` and `ctx.deleteCookie(\"session\")` to the Kaito context which make it a great experience to work with.\n\n```ts\nimport { create } from \"@kaito-http/core\";\nimport { fami } from \"fami/kaito\";\n\nconst kaito = create().pipe(\n  fami({\n    session: {},\n  }),\n});\n\nconst app = kaito.get(\"/\", ({ ctx }) =\u003e {\n  const session = ctx.cookies.session;\n\n  if (session) {\n    return {\n      message: \"You are logged in!\",\n    };\n  }\n\n  throw new KaitoError(401, \"Unauthorized\");\n});\n\nBun.serve({\n  fetch: app.serve(),\n});\n```\n\nFor more details, you can take a look at the [examples](./examples/kaito/index.ts).\n\n### Express\n\n**[Express](https://expressjs.com/)** is the most popular web framework for Node.js.\n\nfami provides a dedicated Express adapter through `fami/express` that gives you type-safe cookie management with full Express autocomplete. The adapter provides a middleware that augments `req` and `res` with fami's methods, and a `handler()` wrapper that narrows the types so `req.cookies`, `res.setCookie()`, `res.deleteCookie()` and `res.json()` all have full autocomplete and type safety.\n\n\u003e [!IMPORTANT]\n\u003e You MUST install the `@types/express` package manually, for the best experience.\n\n```ts\nimport express from \"express\";\nimport { fami } from \"fami/express\";\n\nconst app = express();\nconst f = fami({ session: {} });\n\napp.use(f.middleware());\n\napp.get(\n\t\"/\",\n\tf.handler((req, res) =\u003e {\n\t\tconst session = req.cookies.session; // typed as string | undefined\n\n\t\tres.setCookie(\"session\", \"value\"); // autocomplete for cookie names\n\t\tres.json({ session }); // full Express autocomplete\n\t}),\n);\n\napp.listen(3000);\n```\n\nFor more details, you can take a look at the [examples](./examples/express/index.ts).\n\n## RFC Compliance\n\nfami targets the latest HTTP State Management draft (**RFC 6265bis**, draft‑21 as of 2025), and future drafts onwards.\n\nHighlights:\n\n- **Modern Attributes:** Full support for [`Partitioned` (CHIPS)](https://developer.mozilla.org/en-US/docs/Web/Privacy/Guides/Privacy_sandbox/Partitioned_cookies), `Priority`, and `SameSite` configuration.\n- Follows modern parsing rules\n- Is backwards compatible with the legacy RFC 6265 syntax\n- Strict attribute handling\n- Serialization consistent with draft syntax expectations\n\n## Inspirations\n\nfami was inspired by the following libraries:\n\n- [cookie](https://github.com/jshttp/cookie) - The most popular cookie library, it is a well-established library with battle-tested code and a large community.\n- [pika](https://github.com/Phineas/pika/tree/main/impl/js) - Fully typed, 0 dependencies JS implementation of the full Pika specification.\n\n## Development\n\n### Prerequisites\n\nAlthough **fami** is runtime-agnostic, it is developed and tested using Bun. It is advised to use Bun when developing.\n\n```bash\n# install deps\nbun install\n\n# dry run the publish command to see what would be published,\n# this also runs the test suite and builds the package\nbun run publish --dry-run\n```\n\n### Testing\n\n```bash\nbun t\n```\n\nThe above command is a shortcut for `bun run test` that executes the test suite and generates a coverage report via Bun's built-in coverage tool.\n\nThe test suite covers:\n\n- Attribute correctness\n- Legacy separators\n- Serialization stability\n- Path/domain/expiration handling\n- Edge cases around whitespace, casing, and malformed input\n\n### Publishing\n\nReleases are published automatically via GitHub Actions. Existing versions on npm are never overwritten and each release is immutable, and new versions are always published with a new semver tag.\n\n## License\n\nMIT License, see [LICENSE](./LICENSE) for details.\n","funding_links":["https://github.com/sponsors/pxseu"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpxseu%2Ffami","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpxseu%2Ffami","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpxseu%2Ffami/lists"}