crocks icon indicating copy to clipboard operation
crocks copied to clipboard

Distribute src as ES Modules

Open semmel opened this issue 2 years ago • 2 comments

Shipping src as ES modules has obvious benefits: E.g.

  • loading only the parts of crocks what you need (i.e. treeshaking),
  • bundler-free development in browsers and
  • supporting projects using another JS loader.

With #264 an attempt to migrate crocks to ES modules has been started.

Idea:

In the meantime I suggest generating ES modules files from every CommonJS file in /src in the build step. This achieves almost the same as the conversion of all source files – some code will be duplicated though.

Dead ends

CJS → ESM Conversion tools are either abandoned like nolanlawson/cjs-to-es6, or wessberg/cjstoesm produces errors converting the crocks codebase.

Solution:

I've employed rollup with a quite standard config file of about 40 lines code in my tests. It generates a dist/esm folder, which can be mapped via

  • exports section in package.json for bundlers and Node, or
  • importmap in browsers

to bare ES module import specifiers.

Quite similar to the ReadMe instructions, for example:

import { logic } from 'crocks';
import Maybe from 'crocks/Maybe';
import pointfree from 'crocks/pointfree';
// not quite sure about this one yet:
// no problem in Node, in browser depends on importmap capabilities
import either from 'crocks/pointfree/either';
// or
import either from '../node_modules/crocks/dist/esm/pointfree/either.js';
const
	{and, not} = logic,
	{ option } = pointfree,
	mFoo = Maybe.of("bar"),
	mNothing = Maybe.Nothing(),
// …

My contribution would involve adding rollup as dev depondency, adding the export section in package.json and a rollup.config.js file.

Should I attempt a PR?

semmel avatar Oct 05 '22 20:10 semmel

The generated dist/Maybe/find.js file is like what cdn.sykpack.dev generates for crocks.

import { c as curry_1, t as types, i as isFunction_1, a as isSameType_1 } from './types-79e513c1.js';
import { p as predOrFunc_1 } from './predOrFunc-a430cf4e.js';
import { h as hasAlg_1 } from './Maybe-f40e27d5.js';
import { M as Maybe } from './index-e9cd2952.js';

/** @license ISC License (c) copyright 2017 original and current authors */

/** @author Ian Hofmann-Hicks (evil) */

const hasAlg = hasAlg_1;

/** isFoldable :: a -> Boolean */
function isFoldable$1(m) {
  return !!m
    && hasAlg('reduce', m)
}

var isFoldable_1 = isFoldable$1;

/** @license ISC License (c) copyright 2018 original and current authors */

/** @author Dale Francis (dalefrancis88) */

const Pred = types.proxy('Pred');

const curry = curry_1;
const predOrFunc = predOrFunc_1;
const isFunction = isFunction_1;
const isFoldable = isFoldable_1;
const isSameType = isSameType_1;

const { Just, Nothing } = Maybe.exports;

const accumulator = fn => (acc, cur) =>
  !acc.found && predOrFunc(fn, cur) ? { found: true, value: cur } : acc;

/** find :: Foldable f => ((a -> Boolean) | Pred) -> f a -> Maybe a */
function find(fn, foldable) {
  if(!isFunction(fn) && !isSameType(Pred, fn)) {
    throw new TypeError('find: First argument must be a Pred or predicate')
  }

  if(!isFoldable(foldable)) {
    throw new TypeError('find: Second argument must be a Foldable')
  }

  const result = foldable.reduce(accumulator(fn), { found: false });

  return result.found ? Just(result.value) : Nothing()
}

var find_1 = curry(find);

export { find_1 as default };

semmel avatar Oct 15 '22 19:10 semmel

Export conditions are widely supported now. Good time to pull the trigger on this

bennypowers avatar Feb 01 '23 06:02 bennypowers