Giter Site home page Giter Site logo

nookies's Introduction

nookies 🍪

Working npm version

A collection of cookie helpers for Next.js

Features

  • ✨ SSR support, for setter, parser and destroy
  • ⚙️ Custom Express server support
  • 🪶 super light
  • 🛡 perfect for authentication

Setting and destroying cookies also works on server-side.

Quick start

yarn add nookies

You can play with the example code here.

ServerSide cookies

import nookies from 'nookies'

export default function Me() {
  return <div>My profile</div>
}

export async function getServerSideProps(ctx) {
  // Parse
  const cookies = nookies.get(ctx)

  // Set
  nookies.set(ctx, 'fromGetInitialProps', 'value', {
    maxAge: 30 * 24 * 60 * 60,
    path: '/',
  })

  // Destroy
  // nookies.destroy(ctx, 'cookieName')

  return { cookies }
}

Client-only Cookies

import { parseCookies, setCookie, destroyCookie } from 'nookies'

function handleClick() {
  // Simply omit context parameter.
  // Parse
  const cookies = parseCookies()
  console.log({ cookies })

  // Set
  setCookie(null, 'fromClient', 'value', {
    maxAge: 30 * 24 * 60 * 60,
    path: '/',
  })

  // Destroy
  // destroyCookie(null, 'cookieName')
}

export default function Me() {
  return <button onClick={handleClick}>Set Cookie</button>
}

Custom Express server cookies

const express = require('express');
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();
const { parseCookies, setCookie, destroyCookie } = require('nookies');

app.prepare()
    .then(() => {
        const server = express();

        server.get('/page', (req, res) => {

          // Notice how the request object is passed
          const parsedCookies = parseCookies({ req });

          // Notice how the response object is passed
          setCookie({ res }, 'fromServer', 'value', {
            maxAge: 30 * 24 * 60 * 60,
            path: '/page',
          });

          // destroyCookie({ res }, 'fromServer');

          return handle(req, res);
        });

    );

Reference

For client side usage, omit the ctx parameter. You can do so by setting it to an empty object ({}), null or undefined.

parseCookies(ctx, options) or nookies.get(ctx, options)

  • ctx: Next.js context || (Express request object)
  • options:
    • decode: a custom resolver function (default: decodeURIComponent)

setCookie(ctx, name, value, options) or nookies.set(ctx, name, value, options)

Don't forget to end your response on the server with res.send().

  • ctx: (Next.js context) || (Express request object)
  • name: cookie name
  • value: cookie value
  • options:
    • domain
    • encode
    • expires
    • httpOnly
    • maxAge
    • path
    • sameSite
    • secure

destroyCookie(ctx, name, options) or nookies.destroy(ctx, 'token', options)

Don't forget to end your response on the server with res.send(). This might be the reason your cookie isn't removed.

  • ctx: (Next.js context) || (Express response object)
  • name: cookie name
  • options:
    • domain
    • path

License

MIT

nookies's People

Contributors

alirezamirsepassi avatar aminkhademian avatar aykutkardas avatar bukinoshita avatar dependabot[bot] avatar fabioruolo avatar gabsii avatar garth avatar hasparus avatar jforsaken avatar jvorcak avatar karlhorky avatar koprivajakub avatar lmachens avatar maticzav avatar mattisa avatar mkteh95 avatar omar-dulaimi avatar pesekviktor avatar renovate-bot avatar renovate[bot] avatar rexxars avatar szczepanbarszczowski avatar tomas2387 avatar vassbence avatar wootsbot avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nookies's Issues

express is not includes as one of the dependencies

There is an error saying express is not defined when I included this package as one of my dependencies for some open source project...
I realized there is only @types/express is defined in devDependencies but express is not included in dependencies

Add typehinting

I really like this small little package. Would be great if get, set, and destroy were typehinted!

Dependency `jsmin` uses a custom license

My project requires licences to be audited - we only accept certain types - and the jsmin dependency of this project doesn't have a valid license field: https://github.com/pkrumins/node-jsmin/blob/master/package.json

I know this isn't exactly a problem with nookies but because of this invalid license I cannot use this - rather nice and simple - lib.

Is there any chance that the jsmin dependency can be updated to something which has a valid OS licence?

Cheers and thanks in advance.

Update cookie

Hi,

Is it possible to update a currently set cookie?
Obviously we can just run createCookie with the same name to update the values, but what if I don't want to change the maxAge?

parseCookies() doesn't seem to give me that information.

Is there a way forward with this?

What is maxAge

Hi, What is expected time measure unit in maxAge argument? I am trying to set cookie to expire in 5 minutes, having some hard time with this. Can you provide any inside please? It could be helpful to add it to the docs probably

Thanks!

Deliver ES5 version

I would very much like to be able to use nookies on IE11.

Currently to do that I need to jump through hoops of loading it through babel-loader since there's no es5 version in dist

Prevent setting headers on a finished response

Currently, nookies does not check if the response is already finished in the setCookie method, which may create unwanted, and hard to debug errors. Could we make a simple check on res.finished in the setCookie logic?

I could propose a PR for this.

Only last cookie gets set when trying to set 2 cookies

I use two cookies for user authentication and authorization in my app. I want to refresh both of them when the user loads a page. I noticed that my cookie_one does not get set on page load. Only the second one gets set. Is this a nookies bug (or possibly a bug of the cookie library that nookies uses internally) or am I missing something obvious?

static async getInitialProps(ctx: { req; res }) {
      if (parseCookies(ctx).cookie_one && parseCookies(ctx).cookie_two) {
        setCookie(ctx, 'cookie_one', parseCookies(ctx).cookie_one, {
          maxAge: 36000 * 24 * 14,
        });
        setCookie(ctx, 'cookie_two', parseCookies(ctx).cookie_two, {
          maxAge: 36000 * 24 * 14,
        });
      }

      return {};
    }

Issue with destroyCookie in 1.2.0

I'm having problems with the destroyCookie method not removing the cookie in v1.2.0. It looks like it's because of the domain and path options not being passed through correctly as I am setting these explicitly when I create the cookie.

I noticed you had added an options parameter for destroyCookie recently but I can't see this in the npm module import. If I copy and paste the destroyCookie method directly into my codebase and use it that way it seems to work as expected.

cookie destory fails on the client side

This is a weird behaviour I observed with next.js 9.5.1.
Destroying the cookie on the client side(with destroyCookie(null, 'cookieName')) fails(nothing happens) when using a custom express server.

But as in your #133 (comment) , using getInitialProps doesn't work either.

Create a logout route and use getInitialProps to carry out cookie removal.

LogoutPage.getInitialProps = async (appContext) => {
  destroyCookie(appContext.ctx, 'token');

  // https://err.sh/vercel/next.js/empty-object-getInitialProps
  return {logout: true};
};

Also, thanks for this awesome library, made my day 💯

destroyCookie

destroyCookie does not work in this situation, while nookies.set does the work
nookies on 2.06 version

import nookies, { destroyCookie } from 'nookies'

export const logout = async ({ res }) => {
    console.log('LOGOUTING')
    console.log('destroying cookie')
    // destroyCookie({ res }, 'sbsToken')
    nookies.set({ res }, 'sbsToken', '', {
        maxAge: -1,
        path: '/',
        httpOnly: true,
        secure: process.env.NODE_ENV === 'production',
    })
    return { ok: true }
}

Action Required: Fix Renovate Configuration

There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop PRs until it is resolved.

Error type: undefined. Note: this is a nested preset so please contact the preset author if you are unable to fix it yourself.

The automated release is failing 🚨

🚨 The automated release from the master branch failed. 🚨

I recommend you give this issue a high priority, so other packages depending on you could benefit from your bug fixes and new features.

You can find below the list of errors reported by semantic-release. Each one of them has to be resolved in order to automatically publish your package. I’m sure you can resolve this 💪.

Errors are usually caused by a misconfiguration or an authentication problem. With each error reported below you will find explanation and guidance to help you to resolve it.

Once all the errors are resolved, semantic-release will release your package the next time you push a commit to the master branch. You can also manually restart the failed CI job that runs semantic-release.

If you are not sure how to resolve this, here is some links that can help you:

If those don’t help, or if this issue is reporting something you think isn’t right, you can always ask the humans behind semantic-release.


Invalid npm token.

The npm token configured in the NPM_TOKEN environment variable must be a valid token allowing to publish to the registry https://registry.npmjs.org/.

If you are using Two-Factor Authentication, make configure the auth-only level is supported. semantic-release cannot publish with the default auth-and-writes level.

Please make sure to set the NPM_TOKEN environment variable in your CI with the exact value of the npm token.


Good luck with your project ✨

Your semantic-release bot 📦🚀

Set a cookie upon an animation is complete on server side?

Hi,

I have an animation which plays upon first visit to my site, and upon animation completion I want to set a cookie so it doesn't replay each time a user refreshes or switches pages etc. I solved that with using the client side setCookie without setting ctx.

But when I do the check to see if the cookie is present before rendering the animation component theres obviously a mis-match in the server code and client code, but I;m not sure how to set the cookie with context?

Can you help?

Thanks

Does it support a custom server?

Hello, thanks for the awesome library.
Since we use a custom server for our routes, I wanted to use the same library to handle cookies everywhere on the stack/project.
So does this library support this use case? A custom Express server?

Any future plans?

support for older browsers

Hi.
Seems that typescript compilation target is set to "es6".
This causes dist code to contain arrow function that will break IE11.

(https://caniuse.com/#feat=arrow-functions)

If compilation target would be "es5":

  • IE11 would work and there would be
  • uncompressed dist size would raise from 3611B to 4013B

Should i fork this for my own use or are there any plans to support older browsers while IE11 dies away?

How to populate cookies infos from SignupPage to the Navbar component ?

Hello, everyone
i'm struggling since 2 days to implement authentication.
I use Strapi as a headless CMS/backend. I use [email protected] for the frontend.
I found out this package on this morning from a tutorial.
I have a signup page where I've implemented nookies but since I want to show the username and a link to let the user to logout out, I've decided to put everything within React context (don't know if it's a good idea).
Everything works fine until i refresh the page. The cookie is still there but the Username and the link dissapear

Here is the signup page

import cogoToast from 'cogo-toast';
import Router from 'next/router';
import { parseCookies } from 'nookies';
import styled from 'styled-components';
import FormStyles from '../components/styles/FormStyles';
import Title from '../components/Title';
import { signupUser } from '../lib/api';
import useForm from '../lib/useForm';
import { useInfos } from './context/LocalState';
// import { useState, useEffect } from 'react';

const Column = styled.div`
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
  gap: 20px;
`;

const SignUpPage = () => {
  //   const [authenticated, setAuthenticated] = useState(initialState)
  // useEffect(() => {
  //   effect
  //   return () => {
  //     cleanup
  //   }
  // }, [input])

  const { inputs, handleChange, clearForm } = useForm({
    username: 'machin',
    email: '[email protected]',
    password: 'azerty123',
  });

  const { userLogin } = useInfos();
  const isEmpty = !inputs.username || !inputs.email || !inputs.password;

  const handleSubmit = async e => {
    e.preventDefault();
    const res = await signupUser(
      inputs.username,
      inputs.email,
      inputs.password
    );
    userLogin(res);
    clearForm();
  };
  return (
    <Column>
      <FormStyles method="post" onSubmit={handleSubmit}>
        <fieldset>
          <Title title="Se creer un Compte" center />

          {isEmpty && (
            <p className="form-empty">Pense a remplir tous les champs</p>
          )}
          <label htmlFor="username">
            Username
            <input
              type="text"
              name="username"
              value={inputs.username}
              onChange={handleChange}
              autoComplete="name"
            />
          </label>
          <label htmlFor="email">
            Email
            <input
              type="email"
              name="email"
              value={inputs.email}
              onChange={handleChange}
              autoComplete="email"
            />
          </label>
          <label htmlFor="password">
            Password
            <input
              type="password"
              name="password"
              value={inputs.password}
              onChange={handleChange}
              autoComplete="new-password"
            />
          </label>
          {!isEmpty && <button type="submit">S'inscrire!</button>}
        </fieldset>
      </FormStyles>
    </Column>
  );
};

SignUpPage.getInitialProps = ctx => {
  const isAuthenticated = parseCookies(ctx).fromClientSide;
  console.log({ isAuthenticated });

  // When the user is authenticated, don't let the user visit the
  // sign-in and sign-up routes
  if (isAuthenticated && ['/signup', '/signin'].indexOf(ctx.asPath) > -1) {
    if (typeof window !== 'undefined') {
      Router.push('/');
      cogoToast.info('Tu es déjà loguee papi');
    } else if (ctx.res) {
      ctx.res.writeHead(301, {
        Location: '/',
      });
      ctx.res.end();
    }
  }
  return {};
};

export default SignUpPage;


**My 2 functions from React Context** 

const userLogin = info => (
setCookie(null, 'fromClientSide', info.jwt, {
maxAge: 30 * 24 * 60 * 60,
path: '/',
}),
setUser(info),
info.jwt
? cogoToast.success(


great {info.user.username}!
TYou are logged in


)
: cogoToast.error("Something went wrong"),
Router.push('/')
);

const userLogout = () => (
destroyCookie(null, 'fromClientSide'),
Router.push('/'),
setUser([]),
cogoToast.success('See you soon')
);

Overwrite cookie with the same options and name

I am facing an issue, where I call the setCookie multiple times in a row on server with same cookie name and options but different values. This might not be a problem because the browser should take the latest which is valid but to be sure I would like to send a cookie only once.

Options error with http only

i'm trying to set options for httpOnly. Can anyone explain if possible? How it work? Cookie http only can work in next js with nookies?

Cookie not available in getServerSideProps

Hello, I am setting my httpOnly cookie in /api/auth/login.

setCookie({ res }, 'token', token, {
      httpOnly: true,
      sameSite: 'strict',
      secure: process.env.NODE_ENV === 'production',
      path: '/',
    })

However when I reach any route like /api/auth/refreshToken I am not able to get the cookies, they are missing, they are not available if I fetch them from getInitialProps or getServerSideProps on mount.

How to make it available in some api endpoints in the /api folder?

how to save cookies on a login

When you're login a user, you're doing it client-side. How do I save the token for example without the context?

class Login extends Component {
  constructor() {
    super()

    this.onSubmit = this.onSubmit.bind(this)

    this.state = { email: '', password: '' }
  }

  async onSubmit(e) {
    e.preventDefault()

    const { email, password } = this.state
    const { data } = await api.post('/login', { email, password })

    setCookie(COOKIE_TOKEN, JSON.stringify(data))
    Router.pushRoute('/path')
  }
}

Typings for typescript and issues with code

Hi

I've used your library in a Typescript project.

I have created a Pull Request for you library to DefinitelyTyped where Typescript typings can be created:
DefinitelyTyped/DefinitelyTyped#29857 (review)

When doing this I noticed a few things with the code:

  1. The default value for ctx seems unnecessary in set cookie?
    export function setCookie(ctx = {}, name, value, options = {}) {

  2. Set cookie should not return anything?
    Just remove return {}

I can fix in a Pull Request if you want me?

has no exported member 'NextContext'

Hey there,

Seems Next 9, NextContext became NextPageContext.

We find this type in

export declare function parseCookies(ctx?: next.NextContext | null | undefined, options?: cookie.CookieParseOptions)

export declare function setCookie(ctx: next.NextContext | null | undefined, name: string, value: string, options: cookie.CookieSerializeOptions)

export declare function destroyCookie(ctx: next.NextContext | null | undefined, name: string, options?: cookie.CookieSerializeOptions)

any idea to bypass it ?

Thanks

Setting multiple cookies in SSR should not re-encode with encodeURIComponent

Problem

During SSR, if we've called setCookie before with a custom encode function, setting another cookie re-encodes the value of the previous cookie using encodeURIComponent.

Here's the relevant snippet.

nookies/src/index.ts

Lines 132 to 140 in 2829f49

parsedCookies.forEach((parsedCookie: Cookie) => {
if (!areCookiesEqual(parsedCookie, createCookie(name, value, options))) {
cookiesToSet.push(
cookie.serialize(parsedCookie.name, parsedCookie.value, {
...(parsedCookie as cookie.CookieSerializeOptions),
}),
)
}
})

Looking at Line 136, we can see that we do not pass an encode function. This results in the previously-set cookies being encoded using the default encodeURIComponent. I believe we should pass an encode function like: (val) => val so it retains its current encoding. It is the responsibility of developers to ensure they use proper encoding should they pass a custom encode function.

Reproduction

  1. Call setCookie(ctx, 'key1', '|', { encode: (val) => val }) in SSR.
  2. Call setCookie(ctx, 'key2', '|', { encode: (val) => val }) in SSR.
  3. Value of key1 becomes %7C.

Solution

    parsedCookies.forEach((parsedCookie: Cookie) => {
      if (!areCookiesEqual(parsedCookie, createCookie(name, value, options))) {
        cookiesToSet.push(
          cookie.serialize(parsedCookie.name, parsedCookie.value, {
            encode: (val: string) => val, // Use a pass-through function for encode
            ...(parsedCookie as cookie.CookieSerializeOptions),
          }),
        )
      }
    })

PR demonstrating proposed fix: #357

Lemme know if there are concerns with the suggested changes.

Authentication Example

Hello. Really nice job. This is going to grow big! Do you have a post or an example application on using this for authentication?

cookie.CookieParseOptions;

hi matic!

it would be beneficial to have the options interface CookieSerializeOptions from 'cookies' available in nookies - perhaps you can add it one day :)

kind regards!

Set cookie in request headers too

If some further middlewares are going to read the request cookies too, you might want them to have up to date cookies. For instance, when refreshing a token client-side, I want both to set Set-Cookie headers, but also req.headers so that my server-side queries are triggered with the fresh token. This avoid going back to client to trigger a new request.
Do you think setCookie could be improved to do so?

Current alternative would be to add appContext.ctx.req.headers.cookie = appContext.ctx.res.headers['Set-Cookie'] or something like that after calling setCookie.

parseCookies is not working on Cookies on the client

Hi, I try to load cookie in componentDidMount but when I refresh the page I get cookie inside getInitialProps function I don't know how to fix this.

const cookies = parseCookies();
 console.log({ cookies })

It was return empty data, Please help

Can't set multiple cookies on server side

Hi there!

Description
I'm trying to set multiple different cookies on the server side using setCookie but it's not working as expected.
In the example below it's just simply throwing errors.
I have another application where I use setCookie multiple times in another helper class and even though it works in as it sets a value, the options that get passed to the cookie dependency of nookies get applied to only one of the calls. For the other calls the value does not get encoded using encodeURIComponent for instance.

Am I doing something wrong here?
How is it possible to set multiple cookies during one request?

To Reproduce

  1. Create a new app: npx create-next-app nookies-issue
  2. Install nookies npm install --save nookies
  3. Copy following code into pages/index.js:
import { Component } from 'react'
import Head from 'next/head'
import { setCookie } from 'nookies'

const foo =
  'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) Ap…ML, like Gecko) Chrome/87.0.4280.88 Safari/537.36'
const bar =
  'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) Ap…ML, like Gecko) Chrome/87.0.4280.88 Safari/537.36'

export default class MyClass extends Component {
  static getInitialProps(ctx) {
    setCookie(ctx, 'foo', foo, {})
    setCookie(ctx, 'bar', bar, {})

    return {}
  }

  render() {
    return <h1>Home</h1>
  }
}
  1. Start server and visit localhost:3000

how to get cookie on server

Hi guys, i need read cookie and do some action from redux, i try this one for set cookie when undifined and success create cookie, and how if the cookie already on browser and value true ?

static async getInitialProps({ Component, ctx }) {
    // Parse cookies
    const cookies = nookies.get(ctx);

    if (cookies.theme === undefined || cookies.theme === false) {
      ctx.store.dispatch(changeTheme(false));
      nookies.set(ctx, 'theme', false);
    }

    else if (cookies.theme === true ) {
      ctx.store.dispatch(changeTheme(true));
      nookies.set(ctx, 'theme', true);
    }

    return {
      pageProps: {
        // Call page-level getInitialProps
        ...(Component.getInitialProps ? await Component.getInitialProps(ctx) : {})
      },
      cookies
    };
  }

Cookie Not Being Destroyed

Hi,

I have a function that on success destroys the cookies, the first cookie is being destroyed but not the second, I'm not sure what the issue could be?

if (status === "succeeded") {
				nookies.destroy(null, 'fabCart')
				nookies.destroy(null, 'paymentIntentId')
				setStripeCheckoutSuccess(true);
			}

This is on the client side.

Clear a single cookie from a client-side

I have a next.js project where I have user authentication and I want to make a log out feature which would clear a single token cookie on a server. So far I have not found any approach to solve this, since i cannot pass a ctx object through getInitialProps static method, so i can use destroyCookie method. Anyone knows a workaround here how can I solve this?

setCookie only works sometimes in getServerSideProps

Hello,

Am using nookies with setCookie (also tried nookies.set) in getServerSideProps to set a cookie using values that I've checked are ok and I know that the code block is running. However, only sometimes is the cookie actually getting set - it seems to go through phases of working and then not working. Thanks.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.