Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Show HN: cookies.js, making cookies a delight to work with on the front-end (github.com/franciscop)
122 points by franciscop on Sept 8, 2016 | hide | past | favorite | 46 comments


Congrats on shipping it!

This got me thinking about what the existing cookie libraries looked like in npm, since I figured it was a solved problem already, potentially even with the exact same API.

There are a lot of cookie libraries for the browser in npm! Here are the ones I found, grouped by what syntax they end up implementing, and showing their current downloads per month...

Using the .get() .set() .remove() syntax:

    js-cookie           (141,938)
    cookies-js          (36,319)
    cookie-cutter       (8,848)
    cookie-monster      (7,457)
    client-cookies      (216)
    cookie-browser      (198)
    cookie-handler      (118)
    juicy-cookie        (115)
    cookies-es5         (109)
    cookie.js           (84)
    mmm-cookies         (41)
    cookie-crisp        (60)
    easy-cookies        (13)
Using the Web Storage syntax:

    cookie-storage      (1,101)
    mozilla-doc-cookies (491)
    cookiestorage       (27)
Using the almost-Web-Storage syntax:

    oven                (111)
Using the `(get, set) syntax:

    component-cookie    (7,360)
    cookee              (1,568)
Using your syntax:

    cookiesjs           (49)
I think it's a good example of npm's problem as a search engine for packages. Realistically all of these libraries have the same goal, and probably achieve it equally well. A few have better browser support, a few have better docs, a few have better tests, etc.

No one should be prevented from creating and publishing whatever they want as a library.

But npm should be doing a much, much, much better job at pointing people towards the popular libraries. It takes a lot of work to figure out what cookie libraries to use. Or what snake-case library to use. When it really shouldn't. You could easily eliminate most of these libraries with a few simple metadata checks. And I think it's incredibly unfortunate that npm isn't pushing people in that direction.


I think you raise a good point, but when has this been the package manager's concern?

When I type in 'dnf search' or 'apt-get install' or 'pip search' or the equivalent, I don't get details, I just get a list of packages, one of whose title or description fields match what I pass on the command-line. A package's exported API is important (obviously, since without it you can't use it), but I'm not entirely sure the package manager is the best place to surface this information. Or maybe it should be, but no package manager so far does this well?


Yup, I don't think any package manager has ever really done this well.

But what makes the problem worse is that npm advocates using lots of small modules, and using them in an environment (the browser) where duplication weight has big negative consequences.

I think there's a real opportunity to unseat npm if someone applied to same kind of UX-first thinking to package management that has been applied to other areas.


I kind of agree.. the search on npm isn't very good, I get better from google with site: option. Beyond that, it would be nice if results could be sorted by downloads/month, freshness, frequency of updates, and github issues.

Even just downloads/month on the search results screen would be helpful, as well as repo link... I usually look at downloads and gh issues as the canary for health, which is usually a good indicator.


It's absolute garbage. More than once I've not been able to search for a package with the exact spelling. Google usually guides me to the page, or manually manipulating the URL.


Maybe that's an opportunity for someone or something, like The Wirecutter[1] for npm.

[1] http://thewirecutter.com/


Good work, but I prefer the syntax of cookies-js [1]

Side note, Bower is a dying package manager. You'd get better results if you promoted the npm link over bower.

[1] https://www.npmjs.com/package/cookies-js


Fair enough, I didn't like it and that's the main reason why I continued and published this package. Is it just a preference or do you have any reasoning for liking it?


Is preference not a valid reason? :)

Other reason: the syntax is more explicit, and already familiar to anybody who has used Maps [1]

I find your syntax a little confusing. It's not immediately obvious how I would set multiple cookies with different options, for instance.

[1] https://developer.mozilla.org/en/docs/Web/JavaScript/Referen...


It is totally a valid reason, that's what I wanted to say with fair enough (:

I see, you could just call the same function few times with different options (preferred) as cookies(cookie1, opt1); cookies(cookie2, opt2); or concatenate them: cookies(cookie1, opt1)(cookie2, opt2); but this is arguably really strange syntax.

I will add more examples to the readme.md to make it more clear :+1:


Unlike izolate, I prefer your API. Great Library!


Thank you


Bower is definitely not dying, and in fact Npm is totally unsuited for some communities

http://harry.garrood.me/blog/purescript-why-bower/


https://www.google.com/trends/explore?q=bower,npm

"Dying" is a bit strong, but there's no question that NPM is becoming the go-to choice for javascript development across the stack.


TL;DR: dependencies are a difficult problem.

When you use two distinct dependencies that subsequently have the same dependency but separate major releases, you may encounter breakage.

The author simply prefers Bower because of how it handles this problem differently than npm.


Is this something like putting it out of its mercy, removing your open support for bower because you hear it's dying?


To me it's silly that bower requires npm.. so just use npm. Although you may or may not agree with npm's dependency resolution, I find it more silly to use a tool that requires another tool that does the same job...

I prefer my screwdriver, that I have to open with another screwdriver.


To be honest I tend to avoid packages that have bower support. It just gives me the feeling of legacy. It's unfounded, I know, but that's me.


To an old man out of the loop, what gives you a supported, future-looking feeling?


Precisely that. To in-the-loop JS developers, Bower is old news. To see Bower/Less/jQuery in 2016 conjures up images of out of touch backend developers living in 2011.

There are better alternatives available (NPM/PostCSS/vanilla.js to the above)


But bower came after NPM...

Anyway, I didn't really intend this library to be in-the-loop. I just did it because I couldn't find one I liked in 2016. Which is just nuts on itself. so I went all old-school and tried to keep cross-browser support high and make it simple. It took an hour to be done and a couple of them to test and document it (plus another couple of them for small details such as CDN, bugs/patchs/small features).


jQuery to me has the same connotations but I was surprised by Bower. As an out-of-the-loop sometime JS developer what's respectable these days, npm/gulp/sass, vanilla.js/react/angular2?


Cool submission!

Per RFC 6265, which is the cookie spec you seem to use, the valid chars for cookie names is defined [1] by RFC 2616 (since obsoleted by the 723x series; but agreeing on this issue [2]).

The cookie name must be a 'token', which is incidentally the exact same rule as for HTTP header names. 'token' evaluates to one or more of the following ASCII visible characters:

    "!" / "#" / "$" / "%" / "&" / "'" / "*"
  / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~"
  / DIGIT (0-9) / ALPHA (A-Z, a-z)
Right now you allow any valid JSON object key to be set as a cookie name.

EDIT: To be more precise, your defaults are fine as they URLencode the key too, along with the value. But the defaults are overridable and affect both the cookie key and value simultaneously. Allowing the value encoding to be overridden would be useful, while allowing the name encoding to be overridden can cause the cookie to fall out of spec.

[1] https://tools.ietf.org/html/rfc2616#section-2.2

[2] https://tools.ietf.org/html/rfc7230#section-3.2.6


I URL-Encode it:

    var res = opt.encode(key) + '=' + encoded + ...
Where `opt.encode()` is defined as:

    function (val) {
      return encodeURIComponent(val);
    }
But from your comment I understand that this is not enough and I should dig deeper into this (though I find the RFC really dense/difficult to read).


I did more research and have a further follow-up. According to MDN [1], encodeURIComponent escapes all characters except the following:

  alphabetic, decimal digits, - _ . ! ~ * ' ( )
which means that out of the allowed ASCII characters in a cookie name:

   "!" / "#" / "$" / "%" / "&" / "'" / "*"
  / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~"
  / DIGIT (0-9) / ALPHA (A-Z, a-z)
the following matrix of behaviors results:

      Gets-Encoded? Is-Allowed?   Current-Behavior
  -----------------------------------------------------
  !   not-encoded   allowed       behavior-OK
  #   encoded       allowed       unnecessarily-encoded
  $   encoded       allowed       unnecessarily-encoded
  %   encoded       allowed       unnecessarily-encoded
  &   encoded       allowed       unnecessarily-encoded
  '   not-encoded   allowed       behavior-OK
  *   not-encoded   allowed       behavior-OK
  +   encoded       allowed       unnecessarily-encoded
  -   not-encoded   allowed       behavior-OK
  .   not-encoded   allowed       behavior-OK
  ^   encoded       allowed       unnecessarily-encoded
  _   not-encoded   allowed       behavior-OK
  `   encoded       allowed       unnecessarily-encoded
  |   encoded       allowed       unnecessarily-encoded
  ~   not-encoded   allowed       unnecessarily-encoded
  (   not-encoded   not-allowed   invalid-must-encode
  )   not-encoded   not-allowed   invalid-must-encode
[1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...


For the edit:

I see, so I could add a `cookies.encodevalue()` and default it to `cookies.encode`. However, I think that'd just add too much noise to it so I will just add a warning. Thank you.


This reminds me of jquery-cookie which was replaced by js-cookie. https://github.com/js-cookie/js-cookie


Yes, after the initial simple version, when I thought of expanding it, I looked into js-cookie and Cookies [1], but they all seem to require a `.set()` and `.get()` methods which I find too verbose for something so simple. A couple more of differences:

- I just added a CDN to cookies.js

- The default is a 100-day cookie, as cookies for me imply long-lived cookies, not sessions.

- The default is that if you visit `https`, it will require secure connection.

- [configurable] to remove a cookie you can just null-ify it.

[1] https://github.com/ScottHamper/Cookies


It would be interesting if you adapted this to use the WebStorage api. https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage...


Someone already mentioned js-cookie [0], but they didn't mention that it supports legacy browsers! If you're tied down supporting old IE, it's a great choice.

I've used both js-cookie and cookies-js, and ultimately ended up going with js-cookie. Unfortunately, I don't remember the reason why js-cookie won me over; I think I encountered some issue with cookies-js.

[0] https://github.com/js-cookie/js-cookie


Obligatory old man rant/question... why does software development need to be delightful? I just need it to work and not get in my way. I have other things I can do in my life that are delightful, like reading a good book or watching my kid's first steps.

Edit: I'm sorry, that came off with a lot extra snark and not nearly as much joking as I was intending. I'm happy that people find working with cookies delightful.


It could be argued that if it "just works" and is not in your way that it feels delightful to program with :)


That was totally my original meaning; sensible defaults, easy options and just a simple function to work with makes me want to keep using a library all day. So I try to follow that when writing a new library when I'm not comfortable with the status quo.


Maybe you just defined delightfulness? Things that just work and not get in my way are few enough and far enough between that when it happens, I'm always delighted! ;)


Put an edit at the end of my post. My sense of humor hasn't woken up yet this morning and my tone of voice didn't come across in my post.


That is great that you have a work life balance you are comfortable with but why not enjoy working? Given the choice of getting paid to do something delightful vs doing something that just works but not super enjoyable, I pick delightful. I don't know that anyone ever said it needed to be delightful but there are enough people who would prefer it that way.


It was intended more as a playful[1] comment on the overuse of the word "delightful", "beautiful", etc. Hence the sarcastic lead in with the ellipses on the end. I'm happy that some people can get that from coding.

[1] well that was the intention, obviously it didn't come off that way.


This feels so wrong....

    cookies({ token: '42' }, {
      expires: 100 * 24 * 3600,     // The time to expire in seconds
      domain: false,                // The domain for the cookie
      path: '/',                    // The path for the cookie
      secure: https ? true : false  // Require the use of https
    });


Why? It looks pretty standard to me. It uses named variables for options, instead of argument position, and has reasonable defaults, so you don't have to specify every option.

This is the standard, modern way of added options to a function.


Can you elaborate? Is it the DSL-like syntax for setting cookies that's strange? Or?

I actually quite like it because you can manipulate each portion of the string separetely, vs.

  token: 42; expires: 8640000; path=/; secure


No one should ever use cookies! You should use local storage, and only send what you need to the server and only when you need it


There are situations where cookies make more sense. Local storage gives you less control on the origin where that data can be accessed. Local storage doesn't let you set things such has HttpOnly so that JavaScript can not access the data (this is important to limit the risk of XSS when dealing with session ids). Local storage also doesn't give you as much control over when data should expire.


Sure but here we're talking about javascript cookies that aren't htttpOnly or secure. The expiration date and broad compatibility are the only arguments for the use of js cookies.


and the `path` attribute which allows you to control where a cookie should be used within the same origin.


How does this compare to Express's cookie parser (https://github.com/expressjs/cookie-parser) which relies on cookie (https://github.com/jshttp/cookie) for parsing?


> "Interactive and easy cookies from your browser in javascript"

It is a front-end package, not a Node.js package. I am totally happy with the state-of-the-art Node.js cookie parsing




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: