Skip to content

Commit

Permalink
Improve ESM compatibility
Browse files Browse the repository at this point in the history
This change follows the solution described in [1] to make the package
play nice with both CommonJS and ESM clients.

This includes:

* Changing imports to use the .js extension explicitly
* Modifying the dist/package.json file to refer to different directories
  depending on the context
* Providing two package.json files that override the package type
  depending on the context

Fixes: GH-37

[1] https://www.sensedeep.com/blog/posts/2021/how-to-create-single-source-npm-module.html
  • Loading branch information
jstasiak committed Mar 14, 2022
1 parent b051dd0 commit 3d70bf1
Show file tree
Hide file tree
Showing 20 changed files with 52 additions and 26 deletions.
4 changes: 4 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,8 @@ module.exports = {
statements: 100,
},
},
moduleNameMapper: {
"^(.*)\\.js$": "$1"
},

};
1 change: 1 addition & 0 deletions package-cjs.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"type": "commonjs"}
1 change: 1 addition & 0 deletions package-esm.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"type": "module"}
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
"private": true,
"scripts": {
"build": "npm run clean && npm run build:ts && npm run build:copy",
"build:ts": "tsc -p tsconfig.json && tsc -p tsconfig.json -m esnext --outDir dist/esm/ -d false -declarationMap false",
"build:copy": "copyfiles README.md LICENSE src/package.json dist --flat && copyfiles src/rxjs-operators/package.json dist --up 1",
"build:ts": "tsc -p tsconfig-cjs.json && tsc -p tsconfig-esm.json",
"build:copy": "copyfiles README.md LICENSE src/package.json dist --flat && copyfiles src/rxjs-operators/package.json dist/cjs --up 1 && cp package-cjs.json dist/cjs/package.json && cp package-esm.json dist/esm/package.json",
"clean": "rm -rf dist",
"test": "jest",
"format": "prettier . --write"
Expand Down
4 changes: 2 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export * from './result';
export * from './option';
export * from './result.js';
export * from './option.js';
4 changes: 2 additions & 2 deletions src/option.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { toString } from './utils';
import { Result, Ok, Err } from './result';
import { toString } from './utils.js';
import { Result, Ok, Err } from './result.js';

interface BaseOption<T> extends Iterable<T extends Iterable<infer U> ? U : never> {
/** `true` when the Option is Some */ readonly some: boolean;
Expand Down
12 changes: 9 additions & 3 deletions src/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@
"name": "ts-results",
"version": "3.3.0",
"description": "A typescript implementation of Rust's Result and Option objects.",
"main": "index.js",
"module": "./esm/index.js",
"types": "index.d.ts",
"main": "cjs/index.js",
"module": "esm/index.js",
"types": "esm/index.d.ts",
"exports": {
".": {
"import": "./esm/index.js",
"require": "./cjs/index.js"
}
},
"keywords": [
"Rust",
"Result",
Expand Down
4 changes: 2 additions & 2 deletions src/result.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { toString } from './utils';
import { Option, None, Some } from './option';
import { toString } from './utils.js';
import { Option, None, Some } from './option.js';

/*
* Missing Rust Result type methods:
Expand Down
2 changes: 1 addition & 1 deletion src/rxjs-operators/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { MonoTypeOperatorFunction, Observable, ObservableInput, of, OperatorFunction } from 'rxjs';
import { filter, map, mergeMap, switchMap, tap } from 'rxjs/operators';
import { Err, Ok, Result } from '../index';
import { Err, Ok, Result } from '../index.js';

export function resultMap<T, T2, E>(mapper: (val: T) => T2): OperatorFunction<Result<T, E>, Result<T2, E>> {
return (source) => {
Expand Down
2 changes: 1 addition & 1 deletion src/rxjs-operators/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
"name": "ts-results/rxjs-operators",
"types": "index.d.ts",
"main": "index.js",
"module": "../esm/rxjs-operators/index.js"
"module": "../../esm/rxjs-operators/index.js"
}
4 changes: 2 additions & 2 deletions test/err.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { assert } from 'conditional-type-checks';
import { Err, Ok } from '../src';
import { eq, expect_never } from './util';
import { Err, Ok } from '../src/index.js';
import { eq, expect_never } from './util.js';

test('Constructable & Callable', () => {
const a = new Err(3);
Expand Down
4 changes: 2 additions & 2 deletions test/ok.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { assert } from 'conditional-type-checks';
import { Err, Ok, Result } from '../src';
import { eq, expect_never, expect_string } from './util';
import { Err, Ok, Result } from '../src/index.js';
import { eq, expect_never, expect_string } from './util.js';

test('Constructable & Callable', () => {
const a = new Ok(3);
Expand Down
4 changes: 2 additions & 2 deletions test/option.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Err, None, Ok, Option, OptionSomeType, Result, Some } from '../src';
import { eq } from './util';
import { Err, None, Ok, Option, OptionSomeType, Result, Some } from '../src/index.js';
import { eq } from './util.js';

const someString = Some('foo');
const someNum = new Some(10);
Expand Down
4 changes: 2 additions & 2 deletions test/result.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import {
ResultOkType,
ResultOkTypes,
Some,
} from '../src';
import { eq } from './util';
} from '../src/index.js';
import { eq } from './util.js';

test('Err<E> | Ok<T> should be Result<T, E>', () => {
const r1 = Err(0);
Expand Down
6 changes: 3 additions & 3 deletions test/rxjs.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Err, Ok, Result } from '../src';
import { Err, Ok, Result } from '../src/index.js';
import { Observable, of } from 'rxjs';
import {
elseMap,
Expand All @@ -13,8 +13,8 @@ import {
resultSwitchMap,
tapResultErr,
tapResultOk,
} from '../src/rxjs-operators';
import { eq } from './util';
} from '../src/rxjs-operators/index.js';
import { eq } from './util.js';

const goodVal: Observable<Result<string, number>> = of(Ok('good'));
const badVal: Observable<Result<string, number>> = of(Err(0));
Expand Down
2 changes: 1 addition & 1 deletion test/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"extends": "../tsconfig.json",
"extends": "../tsconfig-cjs.json",
"compilerOptions": {
"baseUrl": "./",
"sourceMap": true,
Expand Down
2 changes: 1 addition & 1 deletion test/util.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { IsExact, IsNever } from 'conditional-type-checks';
import { Result } from '../src';
import { Result } from '../src/index.js';
import { Observable } from 'rxjs';

export function expect_string<T>(x: T, y: IsExact<T, string>) {}
Expand Down
File renamed without changes.
7 changes: 7 additions & 0 deletions tsconfig-cjs.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"extends": "./tsconfig-base.json",
"compilerOptions": {
"outDir": "./dist/cjs",
"module": "commonjs"
}
}
7 changes: 7 additions & 0 deletions tsconfig-esm.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"extends": "./tsconfig-base.json",
"compilerOptions": {
"outDir": "dist/esm",
"module": "esnext"
}
}

0 comments on commit 3d70bf1

Please sign in to comment.