Skip to content

Commit

Permalink
Merge pull request #11 from wSedlacek/typescript
Browse files Browse the repository at this point in the history
refactor(): Rewrite into TypeScript
  • Loading branch information
kleydon authored Sep 9, 2020
2 parents 2cb6fbd + 265bd0c commit e0f20bd
Show file tree
Hide file tree
Showing 44 changed files with 6,555 additions and 1,374 deletions.
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,10 @@ build/Release
.pnp.*
# ---------------------------------------

# TypeScript compiled files
dist
.build-cache

# Testing
coverage
prisma/dev.db
4 changes: 4 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"arrowParens": "always",
"singleQuote": true
}
18 changes: 18 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug Jest Tests",
"type": "node",
"request": "launch",
"runtimeArgs": [
"--inspect-brk",
"${workspaceRoot}/node_modules/.bin/jest",
"--runInBand",
"--coverage"
],
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen"
}
]
}
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"typescript.tsdk": "node_modules/typescript/lib"
}
13 changes: 13 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"version": "2.0.0",
"tasks": [
{
"type": "npm",
"script": "build",
"problemMatcher": ["$tsc"],
"group": "build",
"label": "Build Library",
"detail": "Transpiles TypeScript into JavaScript ouputting in `/dist`"
}
]
}
127 changes: 98 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
# prisma-session-store

An [express](https://github.com/expressjs) session store implementation, for the [Prisma (2) Framework](https://github.com/prisma).
An [express](https://github.com/expressjs) session store implementation, for the [Prisma (2) Framework](https://github.com/prisma).

Want the flexibility and scalability of a Prisma GraphQL data layer, along with the optionality and maturity of the Express ecosystem - but concerned about [JWT](https://jwt.io) or [Paseto](https://paseto.io) tokens for session management (see cautions posted [here](https://paragonie.com/blog/2017/03/jwt-json-web-tokens-is-bad-standard-that-everyone-should-avoid), [here](http://cryto.net/%7Ejoepie91/blog/2016/06/19/stop-using-jwt-for-sessions-part-2-why-your-solution-doesnt-work/), [here](https://techblog.bozho.net/using-jwt-sessions/), [here](https://news.ycombinator.com/item?id=17877332), and [here](https://developer.okta.com/blog/2017/08/17/why-jwts-suck-as-session-tokens))?

`prisma-session-store` simplifies access to tried-and-true express session management via Prisma's database client.
`prisma-session-store` simplifies access to tried-and-true express session management via Prisma's database client.

Based on: [memorystore](https://github.com/roccomuso/memorystore), by [roccomuso](https://github.com/roccomuso)

## Usage

```javascript
### JavaScript (CommonJS)

var expressSession = require('express-session')
var PrismaSessionStore = require('prisma-session-store')(expressSession)
```js

const expressSession = require('express-session')
const PrismaSessionStore = require('@quixo3/prisma-session-store')(expressSession)

...

app.use(
session({
cookie: {
maxAge: 7 * 24 * 60 * 60 * 1000 // ms
cookie: {
maxAge: 7 * 24 * 60 * 60 * 1000 // ms
},
secret: 'a santa at nasa',
store: new PrismaSessionStore(
prisma,
prisma,
{
checkPeriod: 2 * 60 * 1000, //ms
dbRecordIdIsSessionId: true,
Expand All @@ -38,21 +40,72 @@ app.use(

```

## Setup
### TypeScript

```ts
import expressSession from 'express-session';
import prismaSessionStore from '@quixo3/prisma-session-store';

const PrismaSessionStore = prismaSessionStore(expressSession);

...

1. Install `prisma-session-store` (and `express-session`, if not already installed):
`$ npm install prisma-session-store express-session`
2. From your **prisma.schema** file, include a session model:
app.use(
session({
cookie: {
maxAge: 7 * 24 * 60 * 60 * 1000 // ms
},
secret: 'a santa at nasa',
store: new PrismaSessionStore(
prisma,
{
checkPeriod: 2 * 60 * 1000, //ms
dbRecordIdIsSessionId: true,
dbRecordIdFunction: null,
}
)
})
)

...
```

## Setup

### Install

Install `@quixo3/prisma-session-store` (and `express-session`, if not already installed):

#### NPM

`$ npm install @quixo3/prisma-session-store express-session`

#### yarn

`$ yarn add @quixo3/prisma-session-store express-session`

### Prisma

#### Model

From your **prisma.schema** file, include a session model:

```prisma
model Session {
id String @id
sid String @unique
sid String @unique
data String
expires DateTime
}
```
3. Where types are defined, add a corresponding session type:
```

Don't forget to run `prisma generate` to generate your PrismaClient.

#### GraphQL Nexus

If you are using [@nexus/schema](https://www.npmjs.com/package/@nexus/schema) you can define your Session type:

```js
...

{
Expand All @@ -68,34 +121,50 @@ model Session {

```

#### Database

If you are using Prisma's migrations you can simply run `prisma migrate save` and `prisma migrate up` to migrate your database.
If you are using something other then `prisma` then you will need to manage the migrations yourself and you check the [Prisma Documentation](https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch-sql-typescript-postgres#create-database-tables-with-sql) on the subject if you need help.

## Options

* `checkPeriod` Interval, in ms, at which PrismaSessionStore will automatically remove expired sessions. Disabled by default; set to something reasonable.
- `dbRecordIdIsSessionId` A flag indicating to use the session ID as the Prisma Record ID

- `dbRecordIdFunction` A function to generate the Prisma Record ID for a given session ID

Note: If both dbRecordIdFunction and dbRecordIdIsSessionId are undefined then a random
CUID will be used instead.

- `checkPeriod` Interval, in ms, at which PrismaSessionStore will automatically remove expired sessions. Disabled by default; set to something reasonable.

- `ttl` "Time to live", in ms; defines session expiration time. Defaults to session.maxAge (if set), or one day (if not set). May alternatively be set to a function, of the form `(options, session, sessionID) => number`.

- `dispose` Called on sessions when they are dropped. Handy if you want to close file descriptors or do other cleanup tasks when sessions are no longer accessible. Called with `key, value`. It's called _before_ actually removing the item from the internal cache, so if you want to immediately put it back in, you'll have to do that in a `nextTick` or `setTimeout` callback or it won't do anything.

- `stale` By default, if you set a `maxAge`, it'll only actually pull stale items out of the cache when you `get(key)`. (That is, it's not pre-emptively doing a `setTimeout` or anything.) If you set `stale:true`, it'll return the stale value before deleting it. If you don't set this, then it'll return `undefined` when you try to get a stale entry, as if it had already been deleted.

* `ttl` "Time to live", in ms; defines session expiration time. Defaults to session.maxAge (if set), or one day (if not set). May alternatively be set to a function, of the form `(options, sess, sessionID) => number`.
- `noDisposeOnSet` By default, if you set a `dispose()` method, then it'll be called whenever a `set()` operation overwrites an existing key. If you set this option, `dispose()` will only be called when a key falls out of the cache, not when it is overwritten.

* `dispose` Called on sessions when they are dropped. Handy if you want to close file descriptors or do other cleanup tasks when sessions are no longer accessible. Called with `key, value`. It's called *before* actually removing the item from the internal cache, so if you want to immediately put it back in, you'll have to do that in a `nextTick` or `setTimeout` callback or it won't do anything.
- `serializer` An object containing `stringify` and `parse` methods compatible with Javascript's `JSON` to override the serializer used.

* `stale` By default, if you set a `maxAge`, it'll only actually pull stale items out of the cache when you `get(key)`. (That is, it's not pre-emptively doing a `setTimeout` or anything.) If you set `stale:true`, it'll return the stale value before deleting it. If you don't set this, then it'll return `undefined` when you try to get a stale entry, as if it had already been deleted.
Two new options were added apart from the work that was already done by [memorystore](https://github.com/roccomuso/memorystore), they both relate to logging and allow you to inject your own logger object giving you flexibility to log outputs to something like NestJS or where ever you would like even saving them to disk if that's what you want.

* `noDisposeOnSet` By default, if you set a `dispose()` method, then it'll be called whenever a `set()` operation overwrites an existing key. If you set this option, `dispose()` will only be called when a key falls out of the cache, not when it is overwritten.
- `logger` Where logs should be outputted to, by default `console`. If set to `false` then logging will be disabled

* `serializer` An object containing `stringify` and `parse` methods compatible with Javascript's `JSON` to override the serializer used.

- `loggerLevel` Determines which logging methods to enable, by default `error` only

## Methods

`prisma-session-store` implements all the **required**, **recommended** and **optional** methods of the [express-session](https://github.com/expressjs/session#session-store-implementation) store, plus a few more:

* `startInterval()` and `stopInterval()` methods to start/clear the automatic check for expired.
* `prune()` that you can use to manually remove only the expired entries from the store.
- `startInterval()` and `stopInterval()` methods to start/clear the automatic check for expired.
- `prune()` that you can use to manually remove only the expired entries from the store.
- `shutdown()` that can be used to stop any intervals and disconnect from prisma.


# Author
## Author

Krispin Leydon ([kleydon](https://github.com/kleydon)), based heavily on [memorystore](https://github.com/roccomuso/memorystore), by [roccomuso](https://github.com/roccomuso)

Krispin Leydon ([kleydon](https://github.com/kleydon)), based heavily on [memorystore](https://github.com/roccomuso/memorystore), by [roccomuso](https://github.com/roccomuso), refactored to TypeScript by [wSedlacek](https://github.com/wSedlacek)

# License
## License

MIT
1 change: 0 additions & 1 deletion index.js

This file was deleted.

4 changes: 4 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
};
Loading

0 comments on commit e0f20bd

Please sign in to comment.