Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ESM build script #154

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
277 changes: 277 additions & 0 deletions index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,277 @@
const exports = {}
export {
parse,
serialize,
exports as default
}

/*!
* cookie
* Copyright(c) 2012-2014 Roman Shtylman
* Copyright(c) 2015 Douglas Christopher Wilson
* MIT Licensed
*/

'use strict';

/**
* Module exports.
* @public
*/

exports.parse = parse;
exports.serialize = serialize;

/**
* Module variables.
* @private
*/

var __toString = Object.prototype.toString

/**
* RegExp to match field-content in RFC 7230 sec 3.2
*
* field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
* field-vchar = VCHAR / obs-text
* obs-text = %x80-FF
*/

var fieldContentRegExp = /^[\u0009\u0020-\u007e\u0080-\u00ff]+$/;

/**
* Parse a cookie header.
*
* Parse the given cookie header string into an object
* The object has the various cookies as keys(names) => values
*
* @param {string} str
* @param {object} [options]
* @return {object}
* @public
*/

function parse(str, options) {
if (typeof str !== 'string') {
throw new TypeError('argument str must be a string');
}

var obj = {}
var opt = options || {};
var dec = opt.decode || decode;

var index = 0
while (index < str.length) {
var eqIdx = str.indexOf('=', index)

// no more cookie pairs
if (eqIdx === -1) {
break
}

var endIdx = str.indexOf(';', index)

if (endIdx === -1) {
endIdx = str.length
} else if (endIdx < eqIdx) {
// backtrack on prior semicolon
index = str.lastIndexOf(';', eqIdx - 1) + 1
continue
}

var key = str.slice(index, eqIdx).trim()

// only assign once
if (undefined === obj[key]) {
var val = str.slice(eqIdx + 1, endIdx).trim()

// quoted values
if (val.charCodeAt(0) === 0x22) {
val = val.slice(1, -1)
}

obj[key] = tryDecode(val, dec);
}

index = endIdx + 1
}

return obj;
}

/**
* Serialize data into a cookie header.
*
* Serialize the a name value pair into a cookie string suitable for
* http headers. An optional options object specified cookie parameters.
*
* serialize('foo', 'bar', { httpOnly: true })
* => "foo=bar; httpOnly"
*
* @param {string} name
* @param {string} val
* @param {object} [options]
* @return {string}
* @public
*/

function serialize(name, val, options) {
var opt = options || {};
var enc = opt.encode || encode;

if (typeof enc !== 'function') {
throw new TypeError('option encode is invalid');
}

if (!fieldContentRegExp.test(name)) {
throw new TypeError('argument name is invalid');
}

var value = enc(val);

if (value && !fieldContentRegExp.test(value)) {
throw new TypeError('argument val is invalid');
}

var str = name + '=' + value;

if (null != opt.maxAge) {
var maxAge = opt.maxAge - 0;

if (isNaN(maxAge) || !isFinite(maxAge)) {
throw new TypeError('option maxAge is invalid')
}

str += '; Max-Age=' + Math.floor(maxAge);
}

if (opt.domain) {
if (!fieldContentRegExp.test(opt.domain)) {
throw new TypeError('option domain is invalid');
}

str += '; Domain=' + opt.domain;
}

if (opt.path) {
if (!fieldContentRegExp.test(opt.path)) {
throw new TypeError('option path is invalid');
}

str += '; Path=' + opt.path;
}

if (opt.expires) {
var expires = opt.expires

if (!isDate(expires) || isNaN(expires.valueOf())) {
throw new TypeError('option expires is invalid');
}

str += '; Expires=' + expires.toUTCString()
}

if (opt.httpOnly) {
str += '; HttpOnly';
}

if (opt.secure) {
str += '; Secure';
}

if (opt.priority) {
var priority = typeof opt.priority === 'string'
? opt.priority.toLowerCase()
: opt.priority

switch (priority) {
case 'low':
str += '; Priority=Low'
break
case 'medium':
str += '; Priority=Medium'
break
case 'high':
str += '; Priority=High'
break
default:
throw new TypeError('option priority is invalid')
}
}

if (opt.sameSite) {
var sameSite = typeof opt.sameSite === 'string'
? opt.sameSite.toLowerCase() : opt.sameSite;

switch (sameSite) {
case true:
str += '; SameSite=Strict';
break;
case 'lax':
str += '; SameSite=Lax';
break;
case 'strict':
str += '; SameSite=Strict';
break;
case 'none':
str += '; SameSite=None';
break;
default:
throw new TypeError('option sameSite is invalid');
}
}

return str;
}

/**
* URL-decode string value. Optimized to skip native call when no %.
*
* @param {string} str
* @returns {string}
*/

function decode (str) {
return str.indexOf('%') !== -1
? decodeURIComponent(str)
: str
}

/**
* URL-encode value.
*
* @param {string} str
* @returns {string}
*/

function encode (val) {
return encodeURIComponent(val)
}

/**
* Determine if value is a Date.
*
* @param {*} val
* @private
*/

function isDate (val) {
return __toString.call(val) === '[object Date]' ||
val instanceof Date
}

/**
* Try decoding a string using a decoding function.
*
* @param {string} str
* @param {function} decode
* @private
*/

function tryDecode(str, decode) {
try {
return decode(str);
} catch (e) {
return str;
}
}
9 changes: 8 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,25 @@
"LICENSE",
"README.md",
"SECURITY.md",
"index.js"
"index.js",
"index.mjs"
],
"engines": {
"node": ">= 0.6"
},
"scripts": {
"bench": "node benchmark/index.js",
"build-esm": "node scripts/build-esm.js",
"lint": "eslint .",
"prepare": "npm run build-esm",
"test": "mocha --reporter spec --bail --check-leaks test/",
"test-ci": "nyc --reporter=lcov --reporter=text npm test",
"test-cov": "nyc --reporter=html --reporter=text npm test",
"update-bench": "node scripts/update-benchmark.js",
"version": "node scripts/version-history.js && git add HISTORY.md"
},
"exports": {
"import": "./index.mjs",
"require": "./index.js"
}
}
27 changes: 27 additions & 0 deletions scripts/build-esm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
'use strict'

/* Generate the ESM version of the library by prepending an export statement
* Makes the following assumptions about index.js:
* - that `parse` and `serialize` are functions that get hoisted
* - the CJS file references `exports`, not `module.exports`
*
* Although modules use strict mode by default,
* this script does not remove the 'use strict' pragma.
*/

var fs = require('fs')
var path = require('path')

var srcFile = path.join(__dirname, '../index.js')
var destFile = path.join(__dirname, '../index.mjs')

var cjsCode = fs.readFileSync(srcFile, 'utf-8')
var esmCode = "const exports = {}\
export {\
parse,\
serialize,\
exports as default\
}\
" + cjsCode;

fs.writeFileSync(destFile, esmCode);