diff --git a/dist/either.js b/dist/either.js index e439aea..f467f2e 100644 --- a/dist/either.js +++ b/dist/either.js @@ -1,6 +1,4 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const exhaustive_1 = require("@freckle/exhaustive"); +import { exhaustive } from '@freckle/exhaustive'; const Either = { // Construct a value with the 'left' tag Left(left) { @@ -19,7 +17,7 @@ const Either = { case 'right': return branches.right(e.right); default: - return (0, exhaustive_1.exhaustive)(e, 'EitherT'); + return exhaustive(e, 'EitherT'); } }, // Wrap a pure value in EitherT by tagging it with 'right' @@ -63,4 +61,4 @@ const Either = { }); } }; -exports.default = Either; +export default Either; diff --git a/dist/formatting.d.ts b/dist/formatting.d.ts index de62480..005d26b 100644 --- a/dist/formatting.d.ts +++ b/dist/formatting.d.ts @@ -1,3 +1,3 @@ -import { type ErrorStackT } from './index'; +import { type ErrorStackT } from './index.js'; export declare function formatError(root: ErrorStackT): string; export declare function saferStringify(root: any): string; diff --git a/dist/formatting.js b/dist/formatting.js index 00a9ceb..dbcd2b1 100644 --- a/dist/formatting.js +++ b/dist/formatting.js @@ -1,14 +1,7 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.formatError = formatError; -exports.saferStringify = saferStringify; -const times_1 = __importDefault(require("lodash/times")); -const maybe_1 = require("@freckle/maybe"); -const exhaustive_1 = require("@freckle/exhaustive"); -const path_1 = __importDefault(require("./path")); +import { times } from 'lodash'; +import { mapMaybes } from '@freckle/maybe'; +import { exhaustive } from '@freckle/exhaustive'; +import Path from './path.js'; // Format an ErrorStackT into a human-readable message // // For example, the following ErrorStackT: @@ -50,7 +43,7 @@ const path_1 = __importDefault(require("./path")); // The top of the error message applies to the deepest part of the // data structure. Further down, we provide more context about where // the error occurred. -function formatError(root) { +export function formatError(root) { function walk(node, lines) { switch (node.tag) { case 'fail': { @@ -68,7 +61,7 @@ function formatError(root) { } case 'context': { const { expected, element, input, next } = node; - const path = path_1.default.join(element); + const path = Path.join(element); const where = path === null || path === undefined ? 'in' : `at key path ${path} of`; const example = input === null || input === undefined ? [] @@ -77,7 +70,7 @@ function formatError(root) { return walk(next, [...newLines, ...lines]); } default: - return (0, exhaustive_1.exhaustive)(node, 'ErrorStackT'); + return exhaustive(node, 'ErrorStackT'); } } return walk(root, []).join('\n'); @@ -128,7 +121,7 @@ function typeofDeep(root, maxDepth = 20) { } } } - const pairs = (0, maybe_1.mapMaybes)(Object.keys(node), key => + const pairs = mapMaybes(Object.keys(node), key => // eslint-disable-next-line no-prototype-builtins node.hasOwnProperty(key) ? `${key}: ${walk(node[key], depth + 1)}` : null); return `{${pairs.join(', ')}}`; @@ -136,7 +129,7 @@ function typeofDeep(root, maxDepth = 20) { return walk(root, 0); } // JSON.stringify ignores undefined and throws on circular objects -function saferStringify(root) { +export function saferStringify(root) { if (root === undefined) { return 'undefined'; } @@ -152,5 +145,5 @@ function saferStringify(root) { } // Indent string n spaces function indent(n, text) { - return `${(0, times_1.default)(n, () => ' ').join('')}${text}`; + return `${times(n, () => ' ').join('')}${text}`; } diff --git a/dist/index.d.ts b/dist/index.d.ts index e9ff65c..b005609 100644 --- a/dist/index.d.ts +++ b/dist/index.d.ts @@ -1,9 +1,9 @@ import { type Moment } from 'moment-timezone'; import { type NonEmptyArray } from '@freckle/non-empty'; -import { type PathT } from './path'; -import { type EitherT } from './either'; -export { saferStringify } from './formatting'; -export { parseExpect, parseSuccess, parseFailure } from './test-helper'; +import { type PathT } from './path.js'; +import { type EitherT } from './either.js'; +export { saferStringify } from './formatting.js'; +export { parseExpect, parseSuccess, parseFailure } from './test-helper.js'; type LevelT = 'recoverable' | 'fatal'; export type ErrorStackT = { tag: 'fail'; diff --git a/dist/index.js b/dist/index.js index c074757..aa67a27 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1,52 +1,11 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.Parser = exports.parseFailure = exports.parseSuccess = exports.parseExpect = exports.saferStringify = void 0; -exports.tag = tag; -exports.onSelf = onSelf; -exports.literal = literal; -exports.typeOf = typeOf; -exports.pure = pure; -exports.any = any; -exports.string = string; -exports.stringInt = stringInt; -exports.number = number; -exports.rounded = rounded; -exports.fixed = fixed; -exports.boolean = boolean; -exports.nullableDefault = nullableDefault; -exports.nullable = nullable; -exports.nullableDefined = nullableDefined; -exports.array = array; -exports.nonEmptyArray = nonEmptyArray; -exports.date = date; -exports.stringEnum = stringEnum; -exports.oneOf = oneOf; -exports.firstOf = firstOf; -exports.fields = fields; -exports.field = field; -exports.record = record; -exports.stringMap = stringMap; -exports.merge = merge; -exports.mapStatic = mapStatic; -exports.map = map; -exports.obfuscated = obfuscated; -const reduce_1 = __importDefault(require("lodash/reduce")); -const map_1 = __importDefault(require("lodash/map")); // Underscored to avoid name clash -const find_1 = __importDefault(require("lodash/find")); -const moment_timezone_1 = __importDefault(require("moment-timezone")); -const non_empty_1 = require("@freckle/non-empty"); -const path_1 = __importDefault(require("./path")); -const either_1 = __importDefault(require("./either")); -const formatting_1 = require("./formatting"); -var formatting_2 = require("./formatting"); -Object.defineProperty(exports, "saferStringify", { enumerable: true, get: function () { return formatting_2.saferStringify; } }); -var test_helper_1 = require("./test-helper"); -Object.defineProperty(exports, "parseExpect", { enumerable: true, get: function () { return test_helper_1.parseExpect; } }); -Object.defineProperty(exports, "parseSuccess", { enumerable: true, get: function () { return test_helper_1.parseSuccess; } }); -Object.defineProperty(exports, "parseFailure", { enumerable: true, get: function () { return test_helper_1.parseFailure; } }); +import { reduce, map as _map, find } from 'lodash'; +import moment from 'moment-timezone'; +import { mkNonEmpty, mkNonEmptyFromHead, unconsOnNonEmpty } from '@freckle/non-empty'; +import Path from './path.js'; +import Either from './either.js'; +import { formatError } from './formatting.js'; +export { saferStringify } from './formatting.js'; +export { parseExpect, parseSuccess, parseFailure } from './test-helper.js'; function propagate(level, next) { if (next.tag === 'context' && next.level === 'fatal') { return 'fatal'; @@ -56,17 +15,17 @@ function propagate(level, next) { function stringify(a) { return typeof a === 'string' ? JSON.stringify(a) : a.toString(); } -function tag(value) { +export function tag(value) { const expected = `tag(${stringify(value)})`; return { type: 'tag', expected, parse: x => { - return x === value ? exports.Parser.ok(x) : exports.Parser.fail({ expected, got: x }); + return x === value ? Parser.ok(x) : Parser.fail({ expected, got: x }); } }; } -function onSelf(parser) { +export function onSelf(parser) { const { parse } = parser; const expected = `onSelf(${parser.expected})`; return { @@ -78,74 +37,74 @@ function onSelf(parser) { // Parser that uses equality to decode a literal value // // Prefer using tag when the literal is used in a discriminated union -function literal(value) { +export function literal(value) { const expected = `literal(${stringify(value)})`; return { type: 'parser', expected, parse: x => { - return x === value ? exports.Parser.ok(x) : exports.Parser.fail({ expected, got: x }); + return x === value ? Parser.ok(x) : Parser.fail({ expected, got: x }); } }; } // Parser that uses `typeof` -function typeOf(ty) { +export function typeOf(ty) { const expected = `typeOf(${stringify(ty)})`; return { type: 'parser', expected, parse: x => { - return typeof x === ty ? exports.Parser.ok(x) : exports.Parser.fail({ expected, got: x }); + return typeof x === ty ? Parser.ok(x) : Parser.fail({ expected, got: x }); } }; } // Lift a pure value into a ParserT -function pure(a) { +export function pure(a) { const expected = `pure(${stringify(a)})`; return { type: 'parser', expected, - parse: _ => exports.Parser.ok(a) + parse: _ => Parser.ok(a) }; } // Parser for any -function any() { +export function any() { return { type: 'parser', expected: 'any()', - parse: exports.Parser.ok + parse: Parser.ok }; } // Parser for strings -function string() { +export function string() { return typeOf('string'); } // Parser for int as a string -function stringInt() { +export function stringInt() { const expected = 'stringInt()'; return { type: 'parser', expected, parse: x => { const mInt = parseInt(x, 10); - return isNaN(mInt) ? exports.Parser.fail({ expected, got: x }) : exports.Parser.ok(mInt); + return isNaN(mInt) ? Parser.fail({ expected, got: x }) : Parser.ok(mInt); } }; } // Parser for numbers -function number() { +export function number() { return typeOf('number'); } // Parser for rounded numbers -function rounded() { - return exports.Parser.map(number(), 'round', x => Math.round(x)); +export function rounded() { + return Parser.map(number(), 'round', x => Math.round(x)); } // Parser for fixed numbers -function fixed(digits) { - return exports.Parser.map(number(), 'fixed', x => parseFloat(x.toFixed(digits))); +export function fixed(digits) { + return Parser.map(number(), 'fixed', x => parseFloat(x.toFixed(digits))); } // Parser for booleans -function boolean() { +export function boolean() { return typeOf('boolean'); } // Build parser that returns a default when encountering null or undefined @@ -155,93 +114,93 @@ function withDefault(parser, def, expected) { expected, parse: (x, path) => { if (x === null || x === undefined) { - return exports.Parser.ok(def); + return Parser.ok(def); } - return exports.Parser.context({ expected }, parser.parse(x, path)); + return Parser.context({ expected }, parser.parse(x, path)); } }; } // Parser for nullable values with a default -function nullableDefault(parser, def) { +export function nullableDefault(parser, def) { const expected = `nullableDefault(${parser.expected}, ${stringify(def)})`; return withDefault(parser, def, expected); } // Parser for nullable values -function nullable(parser) { +export function nullable(parser) { const expected = `nullable(${parser.expected})`; return withDefault(parser, null, expected); } // Parser for nullable values that are never undefined after parsing -function nullableDefined(parser) { +export function nullableDefined(parser) { const expected = `nullableDefined(${parser.expected})`; return withDefault(parser, null, expected); } function collect(parser, xs, args) { const { path, expected } = args; // Intentionally using mutation below - return (0, reduce_1.default)(xs, (acc, x, i) => { - return either_1.default.liftA2((result, parsed) => { + return reduce(xs, (acc, x, i) => { + return Either.liftA2((result, parsed) => { result[i] = parsed; return result; }, () => acc, () => { - const element = path_1.default.index(path, i); + const element = Path.index(path, i); const parsed = parser.parse(x, element); - return exports.Parser.context({ element, expected, input: xs }, parsed); + return Parser.context({ element, expected, input: xs }, parsed); }); - }, exports.Parser.ok(new Array(xs.length))); + }, Parser.ok(new Array(xs.length))); } // Parser for arrays -function array(parser) { +export function array(parser) { const expected = `array(${parser.expected})`; return { type: 'parser', expected, parse: (xs, path) => { if (!Array.isArray(xs)) { - return exports.Parser.fail({ expected, got: xs }); + return Parser.fail({ expected, got: xs }); } return collect(parser, xs, { path, expected }); } }; } // Parser for non-empty arrays -function nonEmptyArray(parser) { +export function nonEmptyArray(parser) { const expected = `nonEmptyArray(${parser.expected})`; return { type: 'parser', expected, parse: (xs, path) => { if (!Array.isArray(xs) || xs.length === 0) { - return exports.Parser.fail({ expected, got: xs }); + return Parser.fail({ expected, got: xs }); } - const parsed = (0, non_empty_1.mkNonEmpty)(xs); + const parsed = mkNonEmpty(xs); if (parsed === null) { - return exports.Parser.fail({ expected, got: xs }); + return Parser.fail({ expected, got: xs }); } return collect(parser, parsed, { path, expected }); } }; } // Parser for dates represented as moments -function date() { +export function date() { const expected = 'date()'; return { type: 'parser', expected, parse: x => { if (typeof x !== 'string') { - return exports.Parser.fail({ expected, got: x }); + return Parser.fail({ expected, got: x }); } - const parsed = (0, moment_timezone_1.default)(x); + const parsed = moment(x); if (!parsed.isValid()) { - return exports.Parser.fail({ expected, got: x }); + return Parser.fail({ expected, got: x }); } - return exports.Parser.ok(parsed); + return Parser.ok(parsed); } }; } // Parser for enums given a parsing function -function stringEnum(name, parse) { +export function stringEnum(name, parse) { // Ignore parse function in expected since name should be enough to // identify Parser const expected = `stringEnum(${stringify(name)}, _)`; @@ -250,13 +209,13 @@ function stringEnum(name, parse) { expected, parse: x => { if (typeof x !== 'string') { - return exports.Parser.fail({ expected: name, got: x }); + return Parser.fail({ expected: name, got: x }); } const parsed = parse(x); if (parsed === null || parsed === undefined) { - return exports.Parser.fail({ expected: name, got: x }); + return Parser.fail({ expected: name, got: x }); } - return exports.Parser.ok(parsed); + return Parser.ok(parsed); } }; } @@ -266,25 +225,25 @@ function stringEnum(name, parse) { // > type MyType = 'foo' | 'bar' | 'baz' // > oneOf('MyType', ['foo', 'bar', 'baz']) // -function oneOf(name, all) { - return stringEnum(name, (text) => (0, find_1.default)(all, value => value === text)); +export function oneOf(name, all) { + return stringEnum(name, (text) => find(all, value => value === text)); } // Parser that succeeds if any of its arguments succeeds // // Fatal errors do short circuit. Currently, these are only produced by using the // special tag() parser which allows committing early inside record() -function firstOf(first, ...rest) { - const expecteds = (0, map_1.default)([first, ...rest], parser => parser.expected); +export function firstOf(first, ...rest) { + const expecteds = _map([first, ...rest], parser => parser.expected); const expected = `firstOf(${expecteds.join(', ')})`; return { type: 'parser', expected, parse: (x, path) => { - return (0, reduce_1.default)(rest, (lhs, parser) => { - if (exports.Parser.isFatal(lhs)) { + return reduce(rest, (lhs, parser) => { + if (Parser.isFatal(lhs)) { return lhs; } - return either_1.default.alt(() => lhs, () => parser.parse(x, path)); + return Either.alt(() => lhs, () => parser.parse(x, path)); }, first.parse(x, path)); } }; @@ -295,10 +254,10 @@ function firstOf(first, ...rest) { // // record({uuid: fields(string(), 'id', 'ID')}) // -function fields(parser, first, ...rest) { +export function fields(parser, first, ...rest) { const { expected, parse } = parser; - const fields = (0, non_empty_1.mkNonEmptyFromHead)(first, rest); - const expectedFields = (0, map_1.default)(fields, field => stringify(field)).join(', '); + const fields = mkNonEmptyFromHead(first, rest); + const expectedFields = _map(fields, field => stringify(field)).join(', '); const prefix = rest.length === 0 ? 'field' : 'fields'; return { type: 'renamer', @@ -313,7 +272,7 @@ function fields(parser, first, ...rest) { // // record({uuid: field('id', string())}) // -function field(parser, field) { +export function field(parser, field) { return fields(parser, field); } function extractTagParser(parsers) { @@ -329,9 +288,9 @@ function extractTagParser(parsers) { return result; } // Parser for records where each key has its own parser -function record(parsers) { +export function record(parsers) { const keys = Object.keys(parsers).sort(); - const pairs = (0, map_1.default)(keys, key => `${key}: ${parsers[key].expected}`); + const pairs = _map(keys, key => `${key}: ${parsers[key].expected}`); const expected = `record({${pairs.join(', ')}})`; const extracted = extractTagParser(parsers); return { @@ -339,7 +298,7 @@ function record(parsers) { expected, parse: (x, path) => { if (typeof x !== 'object' || x === null) { - return exports.Parser.fail({ expected, got: x }); + return Parser.fail({ expected, got: x }); } // If we have a tag, we can fail early. However, if we find the // tag, any further failures are fatal. Specifically, firstOf() @@ -349,72 +308,75 @@ function record(parsers) { const { key, parser } = extracted; const value = x[key]; if (value === undefined) { - return exports.Parser.fail({ expected: `object with tag at key "${key}"`, got: x }); + return Parser.fail({ expected: `object with tag at key "${key}"`, got: x }); } const result = parser.parse(value, path); if (result.tag === 'right') { shouldCommit = true; } else { - return exports.Parser.context({ element: path_1.default.key(path, key), expected, input: x }, result); + return Parser.context({ element: Path.key(path, key), expected, input: x }, result); } } const parseOne = (parser, key, field) => { if (parser.type === 'self') { const parsed = parser.parse(x, path); - return exports.Parser.context({ element: path, expected, input: x }, parsed); + return Parser.context({ element: path, expected, input: x }, parsed); } else { - const element = path_1.default.key(path, key); - const parsed = parser.parse(x[field], path_1.default.key(path, field)); - return exports.Parser.context({ element, expected, input: x }, parsed); + const element = Path.key(path, key); + const parsed = parser.parse(x[field], Path.key(path, field)); + return Parser.context({ element, expected, input: x }, parsed); } }; // Intentionally using mutation below - const result = (0, reduce_1.default)(keys, (acc, key) => { - return either_1.default.liftA2((result, parsed) => (Object.assign(Object.assign({}, result), { [key]: parsed })), () => acc, () => { + const result = reduce(keys, (acc, key) => { + return Either.liftA2((result, parsed) => ({ + ...result, + [key]: parsed + }), () => acc, () => { const parser = parsers[key]; - const [first, rest] = parser.type === 'renamer' ? (0, non_empty_1.unconsOnNonEmpty)(parser.fields) : [key, []]; - return (0, reduce_1.default)(rest, (parsed, field) => either_1.default.alt(() => parsed, () => parseOne(parser, key, field)), parseOne(parser, first, first)); + const [first, rest] = parser.type === 'renamer' ? unconsOnNonEmpty(parser.fields) : [key, []]; + return reduce(rest, (parsed, field) => Either.alt(() => parsed, () => parseOne(parser, key, field)), parseOne(parser, first, first)); }); - }, exports.Parser.ok({})); + }, Parser.ok({})); // Commit if we found a specific tag - return shouldCommit ? exports.Parser.commit(result) : result; + return shouldCommit ? Parser.commit(result) : result; } }; } // Parser for records with arbitrary string keys, but homogenous values -function stringMap(parser) { +export function stringMap(parser) { const expected = `stringMap(${parser.expected})`; return { type: 'parser', expected, parse: (x, path) => { if (typeof x !== 'object' || x === null) { - return exports.Parser.fail({ expected, got: x }); + return Parser.fail({ expected, got: x }); } // Intentionally using mutation below - return (0, reduce_1.default)(Object.keys(x), (acc, key) => { - return either_1.default.liftA2((result, value) => { + return reduce(Object.keys(x), (acc, key) => { + return Either.liftA2((result, value) => { result.set(key, value); return result; }, () => acc, () => { - const element = path_1.default.key(path, key); + const element = Path.key(path, key); const parsed = parser.parse(x[key], element); - return exports.Parser.context({ element, expected, input: x }, parsed); + return Parser.context({ element, expected, input: x }, parsed); }); - }, exports.Parser.ok(new Map())); + }, Parser.ok(new Map())); } }; } // Merge two record parsers to parse one object with the union of their keys -function merge(lhs, rhs) { +export function merge(lhs, rhs) { const expected = `merge(${lhs.expected}, ${rhs.expected})`; return { type: 'parser', expected, parse: (x, path) => { - return either_1.default.liftA2((lhs, rhs) => (Object.assign(Object.assign({}, lhs), rhs)), () => exports.Parser.context({ expected, input: x }, lhs.parse(x, path)), () => exports.Parser.context({ expected, input: x }, rhs.parse(x, path))); + return Either.liftA2((lhs, rhs) => ({ ...lhs, ...rhs }), () => Parser.context({ expected, input: x }, lhs.parse(x, path)), () => Parser.context({ expected, input: x }, rhs.parse(x, path))); } }; } @@ -424,7 +386,7 @@ function merge(lhs, rhs) { // this for functions that are known to have a non-empty name property. // Falls back to toString() which is sketchy as hell. // -function mapStatic(parser, f) { +export function mapStatic(parser, f) { const expected = `mapStatic(${parser.expected}, ${f.name || f.toString()})`; return mapInternal(parser, expected, f); } @@ -434,7 +396,7 @@ function mapStatic(parser, f) { // so it can be used in the expected value, which can then be used // to compare Parsers for rough equality. // -function map(parser, name, f) { +export function map(parser, name, f) { const expected = `map(${parser.expected}, ${name}, _)`; return mapInternal(parser, expected, f); } @@ -444,42 +406,42 @@ function mapInternal(parser, expected, f) { expected, parse: (x, path) => { const parsed = parser.parse(x, path); - return either_1.default.map(f, exports.Parser.context({ expected }, parsed)); + return Either.map(f, Parser.context({ expected }, parsed)); } }; } // Unobfuscate the response and make sure it follow the expected format -function obfuscated(parser) { +export function obfuscated(parser) { const expected = `obfuscated(${parser.expected})`; return { type: 'parser', expected, - parse: (x, path) => either_1.default.bind(string().parse(x, path), s => { + parse: (x, path) => Either.bind(string().parse(x, path), s => { let unObfuscated; try { unObfuscated = JSON.parse(b64DecodeUnicode(s)); } catch (e) { - return exports.Parser.fail({ expected, got: s }); + return Parser.fail({ expected, got: s }); } return parser.parse(unObfuscated, path); }) }; } -exports.Parser = { +export const Parser = { // Smart constructor for a successful parse ok(result) { - return either_1.default.pure(result); + return Either.pure(result); }, // Smart constructor for a failure at the leaf level fail(obj) { - return either_1.default.fail(Object.assign({ tag: 'fail' }, obj)); + return Either.fail({ tag: 'fail', ...obj }); }, // Mark failure fatal commit(parsed) { - return either_1.default.bimap(error => { + return Either.bimap(error => { if (error.tag === 'context') { - return Object.assign(Object.assign({}, error), { level: 'fatal' }); + return { ...error, level: 'fatal' }; } return error; }, x => x, parsed); @@ -497,10 +459,10 @@ exports.Parser = { // expected - representation of an input that would successfully parse context(args, parsed) { const { input, level, element, expected } = args; - return either_1.default.bimap(next => ({ + return Either.bimap(next => ({ tag: 'context', level: propagate(level, next), - element: element || path_1.default.skip(), + element: element || Path.skip(), expected, input, next @@ -533,21 +495,21 @@ exports.Parser = { mapStatic, // Exported for testing runInternal(value, parser, onSuccess, onError) { - return either_1.default.match(parser.parse(value, path_1.default.root()), { - left: err => onError((0, formatting_1.formatError)(err)), + return Either.match(parser.parse(value, Path.root()), { + left: err => onError(formatError(err)), right: result => onSuccess(result) }); }, // Run a parser on an input. Throws an exception if the parser fails run(value, parser) { - return exports.Parser.runInternal(value, parser, result => result, error => { + return Parser.runInternal(value, parser, result => result, error => { console.log(error); throw new Error(error); }); }, // Make a run function that partially applies `parser` mkRun(parser) { - return (value) => exports.Parser.run(value, parser); + return (value) => Parser.run(value, parser); } }; // Taken from https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#Solution_4_%E2%80%93_escaping_the_string_before_encoding_it diff --git a/dist/path.js b/dist/path.js index e0160d1..d436ced 100644 --- a/dist/path.js +++ b/dist/path.js @@ -1,10 +1,5 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const map_1 = __importDefault(require("lodash/map")); -const exhaustive_1 = require("@freckle/exhaustive"); +import { map } from 'lodash'; +import { exhaustive } from '@freckle/exhaustive'; const Path = { root() { return []; @@ -23,17 +18,17 @@ const Path = { }, // Convert a Path into a string representation join(path) { - const strings = (0, map_1.default)(path, component => { + const strings = map(path, component => { switch (component.tag) { case 'index': return component.index.toString(); case 'key': return component.key; default: - return (0, exhaustive_1.exhaustive)(component, 'PathComponentT'); + return exhaustive(component, 'PathComponentT'); } }); return strings.length === 0 ? null : strings.join('.'); } }; -exports.default = Path; +export default Path; diff --git a/dist/test-helper.d.ts b/dist/test-helper.d.ts index e746ba1..6933b97 100644 --- a/dist/test-helper.d.ts +++ b/dist/test-helper.d.ts @@ -1,4 +1,4 @@ -import { type ParserT } from '.'; +import { type ParserT } from './index.js'; export declare function parseExpect(expected: R, value: any, parser: ParserT): void; export declare function parseSuccess(value: any, parser: ParserT): void; export declare function parseFailure(value: any, parser: ParserT): void; diff --git a/dist/test-helper.js b/dist/test-helper.js index c46eb22..f2ee802 100644 --- a/dist/test-helper.js +++ b/dist/test-helper.js @@ -1,13 +1,5 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.parseExpect = parseExpect; -exports.parseSuccess = parseSuccess; -exports.parseFailure = parseFailure; -const identity_1 = __importDefault(require("lodash/identity")); -const _1 = require("."); +import { identity } from 'lodash'; +import { Parser } from './index.js'; // Set true to see parse results const verbose = false; function expectSuccess(expected) { @@ -29,7 +21,7 @@ function expectFailure(expected) { }; } // Expect parse to succeed and return specified value -function parseExpect(expected, value, parser) { +export function parseExpect(expected, value, parser) { function die(error) { if (verbose) { console.log(error); @@ -37,13 +29,13 @@ function parseExpect(expected, value, parser) { // Extra newline defeats jest's dumb error formatting throw new Error(`\n${error}`); } - expect(_1.Parser.runInternal(value, parser, identity_1.default, die)).toEqual(expected); + expect(Parser.runInternal(value, parser, identity, die)).toEqual(expected); } // Expect parse to succeed -function parseSuccess(value, parser) { - expect(_1.Parser.runInternal(value, parser, expectSuccess(true), expectFailure(false))).toEqual(true); +export function parseSuccess(value, parser) { + expect(Parser.runInternal(value, parser, expectSuccess(true), expectFailure(false))).toEqual(true); } // Expect parse to fail -function parseFailure(value, parser) { - expect(_1.Parser.runInternal(value, parser, expectSuccess(false), expectFailure(true))).toEqual(true); +export function parseFailure(value, parser) { + expect(Parser.runInternal(value, parser, expectSuccess(false), expectFailure(true))).toEqual(true); } diff --git a/package.json b/package.json index 00a3024..a9863ba 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,14 @@ { "name": "@freckle/parser", "version": "2.0.0", + "type": "module", "description": "One that parses", "main": "./dist/index.js", "repository": "https://github.com/freckle/parser-js.git", "author": "Freckle", "license": "MIT", "scripts": { - "build": "tsc -d", + "build": "tsc -p tsconfig.build.json -d", "test": "vitest run", "format": "prettier --write 'src/**/*.js'", "check-git-clean": "./check-git-clean.sh" diff --git a/src/formatting.ts b/src/formatting.ts index d9e2d10..47015de 100644 --- a/src/formatting.ts +++ b/src/formatting.ts @@ -1,11 +1,11 @@ -import times from 'lodash/times' +import {times} from 'lodash' import {mapMaybes} from '@freckle/maybe' import {exhaustive} from '@freckle/exhaustive' -import Path from './path' +import Path from './path.js' -import {type ErrorStackT} from './index' +import {type ErrorStackT} from './index.js' // Format an ErrorStackT into a human-readable message // diff --git a/src/index.test.ts b/src/index.test.ts index e6885a7..baa1227 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -1,4 +1,4 @@ -import forEach from 'lodash/forEach' +import {forEach} from 'lodash' import { type ParserT, @@ -26,9 +26,9 @@ import { tag, onSelf, stringMap -} from './index' +} from './index.js' -import {parseExpect, parseSuccess, parseFailure} from './test-helper' +import {parseExpect, parseSuccess, parseFailure} from './test-helper.js' describe('Parser', () => { describe('test', () => { diff --git a/src/index.ts b/src/index.ts index 001d0a6..13de90f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,4 @@ -import reduce from 'lodash/reduce' -import _map from 'lodash/map' // Underscored to avoid name clash -import find from 'lodash/find' +import {reduce, map as _map, find} from 'lodash' import moment, {type Moment} from 'moment-timezone' import { type NonEmptyArray, @@ -9,14 +7,14 @@ import { unconsOnNonEmpty } from '@freckle/non-empty' -import Path from './path' -import {type PathT} from './path' -import {type EitherT} from './either' -import Either from './either' -import {formatError} from './formatting' +import Path from './path.js' +import {type PathT} from './path.js' +import {type EitherT} from './either.js' +import Either from './either.js' +import {formatError} from './formatting.js' -export {saferStringify} from './formatting' -export {parseExpect, parseSuccess, parseFailure} from './test-helper' +export {saferStringify} from './formatting.js' +export {parseExpect, parseSuccess, parseFailure} from './test-helper.js' // Recoverable errors mean we can try another parser in // firstOf. Fatal errors short circuit any operation. diff --git a/src/path.ts b/src/path.ts index b3132fd..6f6d0eb 100644 --- a/src/path.ts +++ b/src/path.ts @@ -1,4 +1,4 @@ -import map from 'lodash/map' +import {map} from 'lodash' import {exhaustive} from '@freckle/exhaustive' diff --git a/src/test-helper.ts b/src/test-helper.ts index 0ffd0eb..aa12686 100644 --- a/src/test-helper.ts +++ b/src/test-helper.ts @@ -1,6 +1,6 @@ -import identity from 'lodash/identity' +import {identity} from 'lodash' -import {type ParserT, Parser} from '.' +import {type ParserT, Parser} from './index.js' // Set true to see parse results const verbose = false diff --git a/tsconfig.build.json b/tsconfig.build.json new file mode 100644 index 0000000..eeccde4 --- /dev/null +++ b/tsconfig.build.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "exclude": ["./src/**/*.test.ts"] +} diff --git a/tsconfig.json b/tsconfig.json index 7c58839..1a4442c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,9 @@ { + "$schema": "https://json.schemastore.org/tsconfig", "compilerOptions": { - "target": "ES2017", - "module": "commonjs", + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", "strict": true, "esModuleInterop": true, "skipLibCheck": true, @@ -9,8 +11,8 @@ "declaration": true, "rootDir": "src", "outDir": "dist", + "isolatedModules": true, "types": ["vitest/globals"] }, - "include": ["src/**/*.ts"], - "exclude": ["src/**/*.test.ts"] + "include": ["./src/**/*"] } diff --git a/vitest.config.ts b/vitest.config.ts index 3fefe01..df57230 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -4,5 +4,6 @@ export default defineConfig({ test: { globals: true, environment: 'jsdom', + mockReset: true, }, })