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

Fix ESM/CJS compatibility #1

Merged
merged 3 commits into from
Feb 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 0 additions & 15 deletions .babelrc

This file was deleted.

8 changes: 7 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,14 @@
"node": true
},
"settings": {
"import/extensions": [".js", ".ts"]
"import/extensions": [".js", ".ts"],
"import/resolver": {
"typescript": {
"project": ["./tsconfig.json"]
}
}
},
"ignorePatterns": ["/dist/**"],
"rules": {
"@typescript-eslint/no-unused-vars": [
"error",
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14.x, 16.x, 18.x]
node-version: [16.x, 18.x]
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v2
Expand Down
39 changes: 24 additions & 15 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,21 @@
"license": "MIT",
"repository": "git://github.com/MetaMask/superstruct.git",
"type": "module",
"exports": {
".": {
"import": {
"default": "./dist/index.mjs",
"types": "./dist/index.d.mts"
},
"require": {
"default": "./dist/index.cjs",
"types": "./dist/index.d.cts"
}
}
},
"main": "./dist/index.cjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"types": "./dist/index.d.cts",
"sideEffects": false,
"files": [
"dist"
Expand All @@ -16,39 +28,36 @@
"registry": "https://registry.npmjs.org"
},
"engines": {
"node": ">=14.0.0"
"node": ">=16.0.0"
},
"devDependencies": {
"@babel/cli": "^7.6.3",
"@babel/core": "^7.6.3",
"@babel/plugin-transform-modules-commonjs": "^7.12.1",
"@babel/preset-env": "^7.20.2",
"@babel/preset-typescript": "^7.6.0",
"@babel/register": "^7.6.2",
"@rollup/plugin-typescript": "^9.0.2",
"@types/expect": "^24.3.0",
"@types/lodash": "^4.14.144",
"@types/lodash-es": "^4.17.12",
"@types/mocha": "^10.0.0",
"@types/node": "^18.7.14",
"@typescript-eslint/eslint-plugin": "^5.43.0",
"@typescript-eslint/parser": "^5.43.0",
"babel-eslint": "^10.0.3",
"eslint": "^7.14.0",
"eslint-config-prettier": "^7.2.0",
"eslint-plugin-import": "^2.22.1",
"eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-prettier": "^4.0.0",
"is-email": "^1.0.0",
"is-url": "^1.2.4",
"is-uuid": "^1.0.2",
"lodash": "^4.17.15",
"jest": "^29.7.0",
"lodash-es": "^4.17.21",
"mocha": "^10.0.0",
"np": "^7.6.2",
"prettier": "^2.0.5",
"rollup": "^3.3.0",
"typescript": "^4.8.3"
"typescript": "^4.8.3",
"vitest": "^1.2.2"
},
"scripts": {
"build": "rm -rf ./{dist} && rollup --config ./rollup.config.js",
"build": "rm -rf ./dist && rollup --config ./rollup.config.js && scripts/split-tsd-files.sh",
"clean": "rm -rf ./{dist,node_modules}",
"fix": "npm run fix:eslint && npm run fix:prettier",
"fix:eslint": "npm run lint:eslint --fix",
Expand All @@ -57,8 +66,8 @@
"lint:eslint": "eslint '{src,test}/*.{js,ts}'",
"lint:prettier": "prettier --list-different '**/*.{js,json,ts}'",
"release": "npm run build && npm run lint && np",
"test": "npm run build && npm run test:types && npm run test:mocha",
"test:mocha": "mocha --require ./test/register.cjs --require source-map-support/register ./test/index.ts",
"test": "npm run build && npm run test:types && npm run test:vitest",
"test:vitest": "vitest run",
"test:types": "tsc --noEmit && tsc --project ./test/tsconfig.json --noEmit",
"watch": "npm run build -- --watch"
},
Expand Down
25 changes: 25 additions & 0 deletions scripts/split-tsd-files.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/bin/bash

set -euo pipefail

find dist -name '*.d.ts' -print0 | while IFS= read -r -d $'\0' file; do
echo " $file -> ${file%.d.ts}.d.cts"
cp "$file" "${file%.d.ts}.d.cts"
echo " $file -> ${file%.d.ts}.d.mts"
cp "$file" "${file%.d.ts}.d.mts"
rm "$file"
done

find dist -name '*.d.cts' -print0 | while IFS= read -r -d $'\0' file; do
echo " $file"
sed -e 's/\.d\.ts/.d.cts/' -i.bak "$file"
sed -e 's/\.js/.cjs/' -i.bak "$file"
done

find dist -name '*.d.mts' -print0 | while IFS= read -r -d $'\0' file; do
echo " $file"
sed -e 's/\.d\.ts/.d.mts/' -i.bak "$file"
sed -e 's/\.js/.mjs/' -i.bak "$file"
done

find dist -name '*.bak' -print0 | xargs -0 rm
12 changes: 6 additions & 6 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export * from './error'
export * from './struct'
export * from './structs/coercions'
export * from './structs/refinements'
export * from './structs/types'
export * from './structs/utilities'
export * from './error.js'
export * from './struct.js'
export * from './structs/coercions.js'
export * from './structs/refinements.js'
export * from './structs/types.js'
export * from './structs/utilities.js'
4 changes: 2 additions & 2 deletions src/struct.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { toFailures, shiftIterator, StructSchema, run } from './utils'
import { StructError, Failure } from './error'
import { toFailures, shiftIterator, StructSchema, run } from './utils.js'
import { StructError, Failure } from './error.js'

/**
* `Struct` objects encapsulate the validation logic for a specific type of
Expand Down
6 changes: 3 additions & 3 deletions src/structs/coercions.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Struct, is, Coercer } from '../struct'
import { isPlainObject } from '../utils'
import { string, unknown } from './types'
import { Struct, is, Coercer } from '../struct.js'
import { isPlainObject } from '../utils.js'
import { string, unknown } from './types.js'

/**
* Augment a `Struct` to add an additional coercion step to its input.
Expand Down
4 changes: 2 additions & 2 deletions src/structs/refinements.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Struct, Refiner } from '../struct'
import { toFailures } from '../utils'
import { Struct, Refiner } from '../struct.js'
import { toFailures } from '../utils.js'

/**
* Ensure that a string, array, map, or set is empty.
Expand Down
6 changes: 3 additions & 3 deletions src/structs/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Infer, Struct } from '../struct'
import { define } from './utilities'
import { Infer, Struct } from '../struct.js'
import { define } from './utilities.js'
import {
ObjectSchema,
ObjectType,
Expand All @@ -9,7 +9,7 @@ import {
AnyStruct,
InferStructTuple,
UnionToIntersection,
} from '../utils'
} from '../utils.js'

/**
* Ensure that any value passes validation.
Expand Down
11 changes: 8 additions & 3 deletions src/structs/utilities.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { Context, Struct, Validator } from '../struct'
import { Assign, ObjectSchema, ObjectType, PartialObjectSchema } from '../utils'
import { object, optional, type } from './types'
import { Context, Struct, Validator } from '../struct.js'
import {
Assign,
ObjectSchema,
ObjectType,
PartialObjectSchema,
} from '../utils.js'
import { object, optional, type } from './types.js'

/**
* Create a new struct that combines the properties properties from multiple
Expand Down
4 changes: 2 additions & 2 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Struct, Infer, Result, Context, Describe } from './struct'
import { Failure } from './error'
import { Struct, Infer, Result, Context, Describe } from './struct.js'
import { Failure } from './error.js'

/**
* Check if a value is an iterator.
Expand Down
1 change: 1 addition & 0 deletions test/api/assert.ts → test/api/assert.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { throws, doesNotThrow } from 'assert'
import { assert, string, StructError } from '../../src'
import { describe, it } from 'vitest'

describe('assert', () => {
it('valid as helper', () => {
Expand Down
1 change: 1 addition & 0 deletions test/api/create.ts → test/api/create.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { describe, it } from 'vitest'
import { strictEqual, deepEqual, deepStrictEqual, throws } from 'assert'
import {
type,
Expand Down
1 change: 1 addition & 0 deletions test/api/is.ts → test/api/is.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { describe, it } from 'vitest'
import { strictEqual } from 'assert'
import { is, string } from '../../src'

Expand Down
1 change: 1 addition & 0 deletions test/api/mask.ts → test/api/mask.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { describe, it } from 'vitest'
import { deepStrictEqual, throws } from 'assert'
import {
mask,
Expand Down
1 change: 1 addition & 0 deletions test/api/validate.ts → test/api/validate.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { describe, it } from 'vitest'
import { deepStrictEqual, strictEqual } from 'assert'
import {
validate,
Expand Down
16 changes: 5 additions & 11 deletions test/index.ts → test/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import assert, { CallTracker } from 'assert'
import fs from 'fs'
import { pick } from 'lodash'
import { pick } from 'lodash-es'
import { basename, extname, resolve } from 'path'
import {
any,
Expand All @@ -12,15 +12,9 @@ import {
StructError,
} from '../src'

describe('superstruct', () => {
describe('api', () => {
require('./api/assert')
require('./api/create')
require('./api/is')
require('./api/mask')
require('./api/validate')
})
import { describe, it } from 'vitest'

describe('superstruct', () => {
describe('validation', () => {
const kindsDir = resolve(__dirname, 'validation')
const kinds = fs
Expand All @@ -29,15 +23,15 @@ describe('superstruct', () => {
.map((t) => basename(t, extname(t)))

for (const kind of kinds) {
describe(kind, () => {
describe(kind, async () => {
const testsDir = resolve(kindsDir, kind)
const tests = fs
.readdirSync(testsDir)
.filter((t) => t[0] !== '.')
.map((t) => basename(t, extname(t)))

for (const name of tests) {
const module = require(resolve(testsDir, name))
const module = await import(resolve(testsDir, name))
const { Struct, data, create, only, skip, output, failures } = module
const run = only ? it.only : skip ? it.skip : it
run(name, () => {
Expand Down
3 changes: 0 additions & 3 deletions test/register.cjs

This file was deleted.

6 changes: 5 additions & 1 deletion test/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
{
"extends": "../tsconfig.json",
"include": ["./**/*.ts"]
"include": ["./**/*.ts"],
"compilerOptions": {
"lib": ["esnext"],
"skipLibCheck": true
Copy link
Author

@mcmire mcmire Feb 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is unfortunate we have to do this. If we don't do this, then we get type errors from vitest. It seems that there are some requirements we may not be following here that vitest does, one of which is to use a moduleResolution of bundler (this can be observed in the vitest repo and in another project that uses vitest, such as this one). However, that would require using TypeScript 5. Upgrading that in this project causes all kinds of errors, and I didn't want to bother with that considering this is just a temporary solution.

}
}
2 changes: 1 addition & 1 deletion test/typings/any.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { assert, any } from '../../src'
import { test } from '..'
import { test } from '../index.test'

test<any>((x) => {
assert(x, any())
Expand Down
2 changes: 1 addition & 1 deletion test/typings/array.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { assert, array, number } from '../../src'
import { test } from '..'
import { test } from '../index.test'

test<Array<unknown>>((x) => {
assert(x, array())
Expand Down
2 changes: 1 addition & 1 deletion test/typings/assign.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { assert, assign, object, number, string } from '../../src'
import { test } from '..'
import { test } from '../index.test'

test<{
a: number
Expand Down
2 changes: 1 addition & 1 deletion test/typings/bigint.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { assert, bigint } from '../../src'
import { test } from '..'
import { test } from '../index.test'

test<bigint>((x) => {
assert(x, bigint())
Expand Down
2 changes: 1 addition & 1 deletion test/typings/boolean.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { assert, boolean } from '../../src'
import { test } from '..'
import { test } from '../index.test'

test<boolean>((x) => {
assert(x, boolean())
Expand Down
2 changes: 1 addition & 1 deletion test/typings/coerce.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { assert, coerce, string, number } from '../../src'
import { test } from '..'
import { test } from '../index.test'

test<number>((x) => {
assert(
Expand Down
2 changes: 1 addition & 1 deletion test/typings/date.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { assert, date } from '../../src'
import { test } from '..'
import { test } from '../index.test'

test<Date>((x) => {
assert(x, date())
Expand Down
2 changes: 1 addition & 1 deletion test/typings/defaulted.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { assert, defaulted, string } from '../../src'
import { test } from '..'
import { test } from '../index.test'

test<string>((x) => {
assert(x, defaulted(string(), 'Untitled'))
Expand Down
2 changes: 1 addition & 1 deletion test/typings/deprecated.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { assert, object, deprecated, any, Context } from '../../src'
import { test } from '..'
import { test } from '../index.test'

test<unknown>((x) => {
const log = (value: unknown, ctx: Context) => {}
Expand Down
2 changes: 1 addition & 1 deletion test/typings/describe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import {
min,
pattern,
} from '../../src'
import { test } from '..'
import { test } from '../index.test'

test<Describe<any>>((x) => {
return any()
Expand Down
2 changes: 1 addition & 1 deletion test/typings/dynamic.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { assert, dynamic, string } from '../../src'
import { test } from '..'
import { test } from '../index.test'

test<string>((x) => {
assert(
Expand Down
2 changes: 1 addition & 1 deletion test/typings/empty.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { assert, empty, string, array, map, set } from '../../src'
import { test } from '..'
import { test } from '../index.test'

test<string>((x) => {
assert(x, empty(string()))
Expand Down
Loading
Loading