{"id":18317909,"url":"https://github.com/idiocc/session","last_synced_at":"2025-10-24T13:47:03.111Z","repository":{"id":57113717,"uuid":"194054538","full_name":"idiocc/session","owner":"idiocc","description":"Session Middleware for Goa Apps.","archived":false,"fork":false,"pushed_at":"2020-01-09T14:29:18.000Z","size":247,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-10-24T13:47:02.914Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://www.idio.cc","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/idiocc.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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-06-27T08:25:54.000Z","updated_at":"2020-01-09T14:29:21.000Z","dependencies_parsed_at":"2022-08-22T05:50:35.613Z","dependency_job_id":null,"html_url":"https://github.com/idiocc/session","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/idiocc/session","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idiocc%2Fsession","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idiocc%2Fsession/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idiocc%2Fsession/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idiocc%2Fsession/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/idiocc","download_url":"https://codeload.github.com/idiocc/session/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idiocc%2Fsession/sbom","scorecard":{"id":481429,"data":{"date":"2025-08-11","repo":{"name":"github.com/idiocc/session","commit":"ab8e1f0aa8928a81591a34ccb99b514985d88636"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: GNU Affero General Public License v3.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-19T16:44:38.604Z","repository_id":57113717,"created_at":"2025-08-19T16:44:38.604Z","updated_at":"2025-08-19T16:44:38.604Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":280806799,"owners_count":26394451,"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","status":"online","status_checked_at":"2025-10-24T02:00:06.418Z","response_time":73,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":[],"created_at":"2024-11-05T18:07:50.364Z","updated_at":"2025-10-24T13:47:03.080Z","avatar_url":"https://github.com/idiocc.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @goa/session\n\n[![npm version](https://badge.fury.io/js/%40goa%2Fsession.svg)](https://www.npmjs.com/package/@goa/session)\n\n`@goa/session` is Session Middleware for Goa apps written in ES6 and optimised with [JavaScript Compiler](https://www.compiler.page). It is used in the [Idio web](https://www.idio.cc) server.\n\n```sh\nyarn add @goa/session\n```\n\n## Fork Diff\n\nThis package is a fork of `koa-session` with a number of improvements:\n\n1. The session middleware constructor does not require the app, and will not extend the context with `.session` property, if middleware wasn't explicitly used. Fixes [177](https://github.com/koajs/session/issues/177) to avoid confusion when `.session` is not expected to be present, but is read from cookies anyway.\n1. Remove `crc32` hash checking which was unnecessary. Fixes [161](https://github.com/koajs/session/issues/161) as JSON comparison is enough.\n1. Fix [the bug](https://github.com/koajs/session/pull/175) when initial `maxAge` is not set on the initial session cookie, resulting in a session-only sessions.\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/0.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n## Table Of Contents\n\n- [Fork Diff](#fork-diff)\n- [Table Of Contents](#table-of-contents)\n- [API](#api)\n- [`session(opts=): !_goa.Middleware`](#sessionopts-sessionconfig-_goamiddleware)\n  * [`SessionConfig`](#type-sessionconfig)\n  * [`ExternalStore`](#type-externalstore)\n  * [`Session`](#type-session)\n  * [\u003ccode\u003eKoaSession\u003c/code\u003e](#type-koasession)\n- [Typedefs](#typedefs)\n- [Usage Events](#usage-events)\n- [Copyright \u0026 License](#copyright--license)\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/1.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n\n## API\n\nThe package is available by importing its default function:\n\n```js\nimport session from '@goa/session'\n```\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/2.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n## \u003ccode\u003e\u003cins\u003esession\u003c/ins\u003e(\u003c/code\u003e\u003csub\u003e\u003cbr/\u003e\u0026nbsp;\u0026nbsp;`opts=: !SessionConfig,`\u003cbr/\u003e\u003c/sub\u003e\u003ccode\u003e): \u003ci\u003e!_goa.Middleware\u003c/i\u003e\u003c/code\u003e\nInitialize the session middleware with `opts`.\n\n - \u003ckbd\u003eopts\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003e\u003ca href=\"#type-sessionconfig\" title=\"Configuration for the session middleware.\"\u003e!SessionConfig\u003c/a\u003e\u003c/code\u003e\u003c/em\u003e (optional): The configuration passed to `koa-session`.\n\nThe interface is changed from the original package, so that the app is always passed as the first argument.\n\n__\u003ca name=\"type-sessionconfig\"\u003e`SessionConfig`\u003c/a\u003e__: Configuration for the session middleware.\n\u003ctable\u003e\n \u003cthead\u003e\u003ctr\u003e\n  \u003cth\u003eName\u003c/th\u003e\n  \u003cth\u003eType \u0026amp; Description\u003c/th\u003e\n  \u003cth\u003eDefault\u003c/th\u003e\n \u003c/tr\u003e\u003c/thead\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003ekey\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003estring\u003c/em\u003e\u003c/td\u003e\n  \u003ctd rowSpan=\"3\"\u003e\u003ccode\u003ekoa:sess\u003c/code\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   The cookie key.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003emaxAge\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003e(string | number)\u003c/em\u003e\u003c/td\u003e\n  \u003ctd rowSpan=\"3\"\u003e\u003ccode\u003e86400000\u003c/code\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   \u003ccode\u003emaxAge\u003c/code\u003e in ms with default of 1 day. Either a number or 'session'. \u003ccode\u003esession\u003c/code\u003e will result in a cookie that expires when session/browser is closed. Warning: If a session cookie is stolen, this cookie will never expire.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003eoverwrite\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003eboolean\u003c/em\u003e\u003c/td\u003e\n  \u003ctd rowSpan=\"3\"\u003e\u003ccode\u003etrue\u003c/code\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   Can overwrite or not.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003ehttpOnly\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003eboolean\u003c/em\u003e\u003c/td\u003e\n  \u003ctd rowSpan=\"3\"\u003e\u003ccode\u003etrue\u003c/code\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   httpOnly or not.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003esigned\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003eboolean\u003c/em\u003e\u003c/td\u003e\n  \u003ctd rowSpan=\"3\"\u003e\u003ccode\u003etrue\u003c/code\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   Signed or not.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003eautoCommit\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003eboolean\u003c/em\u003e\u003c/td\u003e\n  \u003ctd rowSpan=\"3\"\u003e\u003ccode\u003etrue\u003c/code\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   Automatically commit headers.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003estore\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003e\u003ca href=\"#type-externalstore\" title=\"By implementing this class, the session can be recorded and retrieved from an external store (e.g., a database), instead of cookies.\"\u003eExternalStore\u003c/a\u003e\u003c/em\u003e\u003c/td\u003e\n  \u003ctd rowSpan=\"3\"\u003e-\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   You can store the session content in external stores (Redis, MongoDB or other DBs) by passing an instance of a store with three methods (these need to be async functions).\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003eexternalKey\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003e{ get: function(\u003ca href=\"https://github.com/idiocc/goa/wiki/Context#type-context\" title=\"The context object for each request.\"\u003e_goa.Context\u003c/a\u003e): string, set: function(\u003ca href=\"https://github.com/idiocc/goa/wiki/Context#type-context\" title=\"The context object for each request.\"\u003e_goa.Context\u003c/a\u003e, string): void }\u003c/em\u003e\u003c/td\u003e\n  \u003ctd rowSpan=\"3\"\u003e-\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   When using a store, the external key is recorded in cookies by default, but you can use \u003ccode\u003eoptions.externalKey\u003c/code\u003e to customize your own external key methods.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003eContextStore\u003c/td\u003e\n  \u003ctd colSpan=\"2\"\u003e\u003cem\u003enew (arg0: \u003ca href=\"https://github.com/idiocc/goa/wiki/Context#type-context\" title=\"The context object for each request.\"\u003e!_goa.Context\u003c/a\u003e) =\u003e \u003ca href=\"#type-externalstore\" title=\"By implementing this class, the session can be recorded and retrieved from an external store (e.g., a database), instead of cookies.\"\u003eExternalStore\u003c/a\u003e\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd colSpan=\"2\"\u003e\n   If your session store requires data or utilities from context, \u003ccode\u003eopts.ContextStore\u003c/code\u003e can be used to set a constructor for the store that implements the \u003cem\u003eExternalStore\u003c/em\u003e interface.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003eprefix\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003estring\u003c/em\u003e\u003c/td\u003e\n  \u003ctd rowSpan=\"3\"\u003e-\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   If you want to add prefix for all external session id. It will not work if \u003ccode\u003eoptions.genid(ctx)\u003c/code\u003e present.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003erolling\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003eboolean\u003c/em\u003e\u003c/td\u003e\n  \u003ctd rowSpan=\"3\"\u003e\u003ccode\u003efalse\u003c/code\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   Force a session identifier cookie to be set on every response. The expiration is reset to the original maxAge, resetting the expiration countdown.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003erenew\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003eboolean\u003c/em\u003e\u003c/td\u003e\n  \u003ctd rowSpan=\"3\"\u003e\u003ccode\u003efalse\u003c/code\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   Renew session when session is nearly expired, so we can always keep user logged in.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003evalid\u003c/td\u003e\n  \u003ctd colSpan=\"2\"\u003e\u003cem\u003e(ctx: \u003ca href=\"https://github.com/idiocc/goa/wiki/Context#type-context\" title=\"The context object for each request.\"\u003e!_goa.Context\u003c/a\u003e, sess: !Object) =\u003e boolean\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd colSpan=\"2\"\u003e\n   The validation hook: valid session value before use it.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003ebeforeSave\u003c/td\u003e\n  \u003ctd colSpan=\"2\"\u003e\u003cem\u003e(ctx: \u003ca href=\"https://github.com/idiocc/goa/wiki/Context#type-context\" title=\"The context object for each request.\"\u003e!_goa.Context\u003c/a\u003e, sess: \u003ca href=\"#type-koasession\" title=\"A private session model.\"\u003e!KoaSession\u003c/a\u003e) =\u003e boolean\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd colSpan=\"2\"\u003e\n   The hook before save session.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003egenid\u003c/td\u003e\n  \u003ctd colSpan=\"2\"\u003e\u003cem\u003e(ctx: \u003ca href=\"https://github.com/idiocc/goa/wiki/Context#type-context\" title=\"The context object for each request.\"\u003e!_goa.Context\u003c/a\u003e) =\u003e string\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd colSpan=\"2\"\u003e\n   The way of generating external session id.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003eencode\u003c/td\u003e\n  \u003ctd colSpan=\"2\"\u003e\u003cem\u003e(sess: !Object) =\u003e string\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd colSpan=\"2\"\u003e\n   Use options.encode and options.decode to customize your own encode/decode methods.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003edecode\u003c/td\u003e\n  \u003ctd colSpan=\"2\"\u003e\u003cem\u003e(sess: string) =\u003e !Object\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd colSpan=\"2\"\u003e\n   Use options.encode and options.decode to customize your own encode/decode methods.\n  \u003c/td\u003e\n \u003c/tr\u003e\n\u003c/table\u003e\n\n**Example**\n\n```js\nimport aqt from '@rqt/aqt'\nimport Goa from '@goa/koa'\nimport session from '@goa/session'\n\nconst app = new Goa()\napp.keys = ['g', 'o', 'a']\napp.use(session({ signed: false })) // normally, signed should be true\n\napp.use((ctx) =\u003e {\n  if (ctx.path == '/set') {\n    ctx.session.message = 'hello'\n    ctx.body = 'You have cookies now:'\n  } else if (ctx.path == '/exit') {\n    ctx.session = null\n    ctx.body = 'Bye'\n  }\n  else ctx.body = `Welcome back: ${ctx.session.message}`\n})\n\napp.listen(async function() {\n  const { port } = this.address()\n  const url = `http://localhost:${port}`\n\n  // 1. Acquire cookies\n  let { body, headers } = await aqt(`${url}/set`)\n  console.log(body, headers, '\\n')\n  const cookie = headers['set-cookie']\n\n  // 2. Exploit cookies\n  ;({ body, headers } = await aqt(url, {\n    headers: {\n      cookie,\n    },\n  }))\n  console.log(body, headers, '\\n')\n\n  // 3. Destroy cookies\n  ;({ body, headers } = await aqt(`${url}/exit`, {\n    headers: {\n      cookie,\n    },\n  }))\n  console.log(body, headers)\n\n  this.close()\n})\n```\n```js\nYou have cookies now: { 'content-type': 'text/plain; charset=utf-8',\n  'content-length': '21',\n  'set-cookie': \n   [ 'koa:sess=eyJtZXNzYWdlIjoiaGVsbG8iLCJfZXhwaXJlIjoxNTc4NjY2NDgzNjc4LCJfbWF4QWdlIjo4NjQwMDAwMH0=; path=/; expires=Fri, 10 Jan 2020 14:28:03 GMT; httponly' ],\n  date: 'Thu, 09 Jan 2020 14:28:03 GMT',\n  connection: 'close' } \n\nWelcome back: hello { 'content-type': 'text/plain; charset=utf-8',\n  'content-length': '19',\n  date: 'Thu, 09 Jan 2020 14:28:03 GMT',\n  connection: 'close' } \n\nBye { 'content-type': 'text/plain; charset=utf-8',\n  'content-length': '3',\n  'set-cookie': \n   [ 'koa:sess=; path=/; expires=Fri, 10 Jan 2020 14:28:03 GMT; httponly' ],\n  date: 'Thu, 09 Jan 2020 14:28:03 GMT',\n  connection: 'close' }\n```\n\nIf your session store requires data or utilities from context, `opts.ContextStore` is also supported. _ContextStore_ must be a class which implements three instance methods demonstrated below. `new ContextStore(ctx)` will be executed on every request.\n\n__\u003ca name=\"type-externalstore\"\u003e`ExternalStore`\u003c/a\u003e__: By implementing this class, the session can be recorded and retrieved from an external store (e.g., a database), instead of cookies.\n\u003ctable\u003e\n \u003cthead\u003e\u003ctr\u003e\n  \u003cth\u003eName\u003c/th\u003e\n  \u003cth\u003eType \u0026amp; Description\u003c/th\u003e\n \u003c/tr\u003e\u003c/thead\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cins\u003econstructor\u003c/ins\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003enew () =\u003e \u003ca href=\"#type-externalstore\" title=\"By implementing this class, the session can be recorded and retrieved from an external store (e.g., a database), instead of cookies.\"\u003eExternalStore\u003c/a\u003e\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   Constructor method.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cins\u003eget\u003c/ins\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003e(key: string, maxAge: (number | string), opts: { rolling: boolean }) =\u003e !Promise\u0026lt;!Object\u0026gt;\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   Get session object by key.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cins\u003eset\u003c/ins\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003e(key: string, sess: !Object, maxAge: (number | string), opts: { rolling: boolean, changed: boolean }) =\u003e !Promise\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   Set session object for key, with a \u003ccode\u003emaxAge\u003c/code\u003e (in ms, or as \u003ccode\u003e'session'\u003c/code\u003e).\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cins\u003edestroy\u003c/ins\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003e(key: string) =\u003e !Promise\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   Destroy session for key.\n  \u003c/td\u003e\n \u003c/tr\u003e\n\u003c/table\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cem\u003eShow an example external store.\u003c/em\u003e\n\u003c/summary\u003e\n\n```js\nconst sessions = {}\n\nexport default {\n  async get(key) {\n    return sessions[key]\n  },\n\n  async set(key, value) {\n    sessions[key] = value\n  },\n\n  async destroy(key) {\n    sessions[key] = undefined\n  },\n}\n```\n\u003c/details\u003e\n\nThe session object itself (`ctx.session`) has the following methods.\n\n__\u003ca name=\"type-session\"\u003e`Session`\u003c/a\u003e__: The session instance accessible via Goa's context.\n\n\n|        Name         |                Type                 |                                       Description                                        |\n| ------------------- | ----------------------------------- | ---------------------------------------------------------------------------------------- |\n| __isNew*__          | \u003cem\u003eboolean\u003c/em\u003e                    | Returns true if the session is new.                                                      |\n| __populated*__      | \u003cem\u003eboolean\u003c/em\u003e                    | Populated flag, which is just a boolean alias of `.length`.                              |\n| __maxAge*__         | \u003cem\u003e(number \\| string)\u003c/em\u003e         | Get/set cookie's maxAge.                                                                 |\n| __save*__           | \u003cem\u003e() =\u003e void\u003c/em\u003e                 | Save this session no matter whether it is populated.                                     |\n| __manuallyCommit*__ | \u003cem\u003e() =\u003e !Promise\u0026lt;void\u0026gt;\u003c/em\u003e | Session headers are auto committed by default. Use this if `autoCommit` is set to false. |\n\n\u003cdetails\u003e\n \u003csummary\u003e\u003cstrong\u003e\u003ca name=\"type-koasession\"\u003e\u003ccode\u003eKoaSession\u003c/code\u003e\u003c/a\u003e extends \u003ca href=\"#type-session\" title=\"The session instance accessible via Goa's context.\"\u003e\u003ccode\u003eSession\u003c/code\u003e\u003c/a\u003e\u003c/strong\u003e: A private session model.\u003c/summary\u003e\n\u003ctable\u003e\n \u003cthead\u003e\u003ctr\u003e\n  \u003cth\u003eName\u003c/th\u003e\n  \u003cth\u003eType \u0026amp; Description\u003c/th\u003e\n \u003c/tr\u003e\u003c/thead\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cins\u003econstructor\u003c/ins\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003enew (sessionContext: KoaContextSession, obj?: { _maxAge: (number | undefined), _session: (boolean | undefined) }) =\u003e \u003ca href=\"#type-koasession\" title=\"A private session model.\"\u003eKoaSession\u003c/a\u003e\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   Private session constructor. It is called one time per request by the session context when middleware accesses \u003ccode\u003e.session\u003c/code\u003e property of the context.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cins\u003e_expire\u003c/ins\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003enumber\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   Private JSON serialisation.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cins\u003e_requireSave\u003c/ins\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003eboolean\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   Private JSON serialisation.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cins\u003e_sessCtx\u003c/ins\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003eKoaContextSession\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   Private JSON serialisation.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cins\u003e_ctx\u003c/ins\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003e\u003ca href=\"https://github.com/idiocc/goa/wiki/Context#type-context\" title=\"The context object for each request.\"\u003e_goa.Context\u003c/a\u003e\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   Private JSON serialisation.\n  \u003c/td\u003e\n \u003c/tr\u003e\n\u003c/table\u003e\n\u003c/details\u003e\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/3.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n## Typedefs\n\nThis package is meant to be used as part of the [Idio web server](https://github.com/idiocc/idio). But it also can be used on its own with _Koa_. To enable auto-completions when configuring the middleware, please install typedefs, and import them in your application entry:\n\n\u003ctable\u003e\n\u003ctr\u003e\u003cth\u003ePackage \u0026 Link\u003c/th\u003e\u003cth\u003eImport\u003c/th\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\n@typedefs/goa\n\n[![npm version](https://badge.fury.io/js/%40typedefs%2Fgoa.svg)](https://www.npmjs.com/package/@typedefs/goa)\n\u003c/td\u003e\n\u003ctd\u003e\n\n```js\nconst sess = session({\n  // you can access ctx as context now\n  valid(ctx, obj) {\n    // force presence of a key in headers too\n    const s = ctx.get('secret-key')\n    return obj['secret-key'] == s\n  }\n})\n// at the bottom of the file\n/**\n * @typedef {import('@typedefs/goa').Context} _goa.Context\n */\n```\n\u003c/td\u003e\n\u003ctr\u003e\n  \u003ctd colspan=\"2\"\u003eThis will add information about required types to \u003cem\u003eVSCode\u003c/em\u003e. This is required because even though session's configuration object is described with \u003cem\u003eJSDoc\u003c/em\u003e in its file, \u003cem\u003eVSCode\u003c/em\u003e has a bug that does not allow propagation of imported types so they need to be imported manually like above.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd colspan=\"2\"\u003e\n  \u003cimg src=\"doc/ts.gif\" alt=\"JSDoc\"\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/4.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n## Usage Events\n\nThis middleware integrates with [_Idio_](https://github.com/idiocc/idio) that collects middleware usage statistics to reward package maintainers. It will emit certain events to bill its usage:\n\n1. `save`: When the session is saved via cookies.\n1. `save-external`: When the session is saved via external storage.\n\nThe usage is recorded via the `ctx.neoluddite` context property set by a server such as _Idio_. In future, more fine-grained usage events might appear.\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/5.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n## Copyright \u0026 License\n\nGNU Affero General Public License v3.0\n\nAffero GPL means that you're not allowed to use this middleware on the web unless you release the source code for your application. This is a restrictive license which has the purpose of defending Open Source work and its creators.\n\nPlease refer to the [Idio license agreement](https://github.com/idiocc/idio#copyright--license) for more info on dual-licensing. You're allowed to use this middleware without disclosing the source code if you sign up on [neoluddite.dev](https://neoluddite.dev) package reward scheme.\n\n[Original Work](https://github.com/koajs/session) by dead-horse and contributors under MIT license.\n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003cth\u003e\n      \u003ca href=\"https://artd.eco\"\u003e\n        \u003cimg width=\"100\" src=\"https://raw.githubusercontent.com/wrote/wrote/master/images/artdeco.png\"\n          alt=\"Art Deco\"\u003e\n      \u003c/a\u003e\n    \u003c/th\u003e\n    \u003cth\u003e© \u003ca href=\"https://artd.eco\"\u003eArt Deco\u003c/a\u003e for \u003ca href=\"https://idio.cc\"\u003eIdio\u003c/a\u003e 2020\u003c/th\u003e\n    \u003cth\u003e\n      \u003ca href=\"https://idio.cc\"\u003e\n        \u003cimg src=\"https://avatars3.githubusercontent.com/u/40834161?s=100\" width=\"100\" alt=\"Idio\"\u003e\n      \u003c/a\u003e\n    \u003c/th\u003e\n    \u003cth\u003e\n      \u003ca href=\"https://www.technation.sucks\" title=\"Tech Nation Visa\"\u003e\n        \u003cimg width=\"100\" src=\"https://raw.githubusercontent.com/idiocc/cookies/master/wiki/arch4.jpg\"\n          alt=\"Tech Nation Visa\"\u003e\n      \u003c/a\u003e\n    \u003c/th\u003e\n    \u003cth\u003e\u003ca href=\"https://www.technation.sucks\"\u003eTech Nation Visa Sucks\u003c/a\u003e\u003c/th\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/-1.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fidiocc%2Fsession","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fidiocc%2Fsession","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fidiocc%2Fsession/lists"}