Skip to content

Commit

Permalink
feat: full Node.js ESM runtime support (#54)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: umd builds are removed and all middleware imports are moved to `get-it/middleware`. Imports such as `import promise from 'get-it/lib-node/middleware/promise'` are no longer supported. The default import is replaced with a named one: change `import getIt from 'get-it'` to `import {getIt} from 'get-it'`

Other changes
- Migrated codebase to TypeScript, moving away from using `any` is out of scope for this PR but linter rules are setup to make it easier to do this refactor in a later PR.
- The required Node.js version is moved from 12 to 14, as 12 does not support `pkg.exports`.
- Tooling have moved to `@sanity/pkg-utils`, gone is `@babel/cli`, `browserify`, `esbuild`, `uglifyjs`, and more.
- Replaced `mocha` testing suite with `vitest` to ensure the new ESM codebase runs the same way it'll run in production with codebases such as `sanity`.
- The `pkg.exports` are refactored to follow our updated ESM best practices, spearheaded by `@sanity/pkg-utils`. It implements the Node.js `dual package hazard` technique to steer the Node.js ESM runtime back into CJS mode as half our `dependencies` aren't shipping ESM-runtime code yet.
- The `pkg.exports` and build setup is also configured to generate browser code that is picked up by modern and legacy bundlers alike. It no longer uses `pkg.browser` to redirect package imports, instead there's `index.ts` and `index.browser.ts` entrypoints, and `middleware.ts` and `middleware.browser.ts`. These entrypoints use different imports on things that diverge depending on wether it's a `node` or `browser` runtime environment. The generated bundles are then self-contained and have much wider support than today's [super-complex `pkg.exports`](https://github.com/sanity-io/get-it/blob/8fecf9ff77e8805bb9ae1aac74b74d4d786a11ca/package.json#L42-L154) and [`pkg.browser`](https://github.com/sanity-io/get-it/blob/8fecf9ff77e8805bb9ae1aac74b74d4d786a11ca/package.json#L18-L41).
- `pkg.type` is changed from `commonjs` to `module`.
- Added `pkg.sideEffects: false` to enable much better tree-shaking in bundlers such as `webpack`.
- Now shipping TypeScript types.
- The `Deno`  testing suite is updated to follow current best practice for deno's node.js interop.
- Generated JS is now using the same `browserslist` setup as we do in the rest of our modern ecosystem as well as `sanity`.
- All dependencies have been updated, to their latest version that still ships code that can run in both Node.js CJS and ESM runtimes.
- Some packages have been inlined as they proved too problematic to use with TypeScript, such as `@sanity/timed-out` and `simple-concat`
- Adds a `Lock thread` workflow that locks closed issues and PRs to avoid people commenting on them as we don't get notified by that, and it's best to help nudge people towards making new issues instead.
- Also adds a prettier workflow that runs prettier if a push to `main` forgot to apply it.
  • Loading branch information
stipsan committed Jan 4, 2023
1 parent 7f72956 commit ab8a4fd
Show file tree
Hide file tree
Showing 141 changed files with 8,365 additions and 18,812 deletions.
44 changes: 0 additions & 44 deletions .babelrc

This file was deleted.

3 changes: 0 additions & 3 deletions .eslintignore
@@ -1,7 +1,4 @@
/coverage
/dist
/lib
/lib-node
/umd
# ESLint isn't configured to deal with ESM yet
/test-esm
10 changes: 0 additions & 10 deletions .eslintrc

This file was deleted.

37 changes: 37 additions & 0 deletions .eslintrc.cjs
@@ -0,0 +1,37 @@
module.exports = {
env: {
browser: true,
es6: true,
node: true,
},
extends: [
'eslint:recommended',
'plugin:prettier/recommended',
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 2018,
},
plugins: ['@typescript-eslint', 'simple-import-sort', 'prettier'],
rules: {
'@typescript-eslint/interface-name-prefix': 'off',
'@typescript-eslint/member-delimiter-style': 'off',
'@typescript-eslint/no-empty-interface': 'off',
'simple-import-sort/imports': 'warn',
'simple-import-sort/exports': 'warn',
'no-console': 'error',
'no-shadow': 'error',
'no-warning-comments': ['warn', {location: 'start', terms: ['todo', '@todo', 'fixme']}],
},

overrides: [
{
files: ['**/*.js'],
rules: {
'@typescript-eslint/explicit-module-boundary-types': 'off',
},
},
],
}
63 changes: 30 additions & 33 deletions .github/workflows/ci.yml
Expand Up @@ -33,7 +33,7 @@ jobs:
cache: npm
- run: npm ci
- run: npm run build
- run: npm run lint
- run: npm run lint -- --quiet
- run: npm run coverage

test:
Expand All @@ -43,24 +43,26 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest]
# Test the oldest Node.js version we support, and the latest in development
node: [12, current]
# Run the testing suite on each major OS with the latest LTS release of Node.js
os: [macos-latest, ubuntu-latest, windows-latest]
node: [lts/*]
# It makes sense to also test the oldest, and latest, versions of Node.js, on ubuntu-only since it's the fastest CI runner
include:
# ubuntu and lts already runs tests in the `build` job, so we only need to add windows and mac here
- os: macos-latest
node: lts/*
- os: windows-latest
node: lts/*
- os: ubuntu-latest
# Test the oldest LTS release of Node that's still receiving bugfixes and security patches, versions older than that have reached End-of-Life
node: lts/-2
- os: ubuntu-latest
# Test the actively developed version that will become the latest LTS release next October
node: current
steps:
- uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3
- uses: actions/setup-node@8c91899e586c5b171469028077307d293428b516 # v3
with:
node-version: ${{ matrix.node }}
cache: npm
- run: npm ci
- run: npm i
- run: npm run build
- run: npm run coverage
- run: npm test
env:
SKIP_MTLS_TEST: "${{ matrix.os == 'ubuntu-latest' && 'true' || 'false' }}"

Expand All @@ -74,11 +76,10 @@ jobs:
with:
# The testing suite uses the native test runner introduced in Node.js v18
# https://nodejs.org/api/test.html
node-version: 18
node-version: lts/*
cache: npm
- run: npm ci
- run: npm run build
- run: npm run build:esm
- run: npm run test:esm
# This test will run both in a CJS and an ESM mode in Node.js to ensure backwards compatibility
name: Ensure pkg.exports don't break anything in modern Node.js envs
Expand All @@ -88,26 +89,22 @@ jobs:
name: Test the 'browser' conditional using Node.js

test-deno:
name: Test Deno in Node compatibility mode
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3
- uses: actions/setup-node@8c91899e586c5b171469028077307d293428b516 # v3
with:
node-version: lts/*
cache: npm
- run: npm ci
- run: npm run build
- run: npm run build:esm
- uses: denoland/setup-deno@v1
with:
# @todo: stop overriding the version after migrating from `--compat` (https://github.com/sanity-io/get-it/issues/33)
deno-version: v1.24.x
- run: npm run test:esm:deno
# When not in Node Compat mode it's likely using something like https://esm.sh/get-it, which supports the same `deno` conditional
# and thus it's not necessary to run a test outside compat mode here
name: Test that pkg.exports supports Deno running in Node Compatibility mode
name: Test Deno in Node compatibility mode
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3
- uses: actions/setup-node@8c91899e586c5b171469028077307d293428b516 # v3
with:
node-version: lts/*
cache: npm
- run: npm ci
- run: npm run build
- uses: denoland/setup-deno@v1
with:
deno-version: vx.x.x
- run: npm run test:esm:deno
name: Test that pkg.exports supports Deno running in Node Compatibility mode

release:
name: Semantic release
Expand Down
24 changes: 24 additions & 0 deletions .github/workflows/lock.yml
@@ -0,0 +1,24 @@
---
name: 'Lock Threads'

on:
schedule:
- cron: '0 0 * * *'
workflow_dispatch:

permissions:
issues: write
pull-requests: write

concurrency:
group: ${{ github.workflow }}
cancel-in-progress: true

jobs:
action:
runs-on: ubuntu-latest
steps:
- uses: dessant/lock-threads@c1b35aecc5cdb1a34539d14196df55838bb2f836 # v4
with:
issue-inactive-days: 0
pr-inactive-days: 0
35 changes: 35 additions & 0 deletions .github/workflows/prettier.yml
@@ -0,0 +1,35 @@
---
name: Prettier

on:
push:
branches: [main]
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

jobs:
run:
name: 🤔
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3
- uses: actions/setup-node@8c91899e586c5b171469028077307d293428b516 # tag=v3
with:
cache: npm
node-version: lts/*
- run: npm ci --ignore-scripts --only-dev
- uses: actions/cache@4723a57e26efda3a62cbde1812113b730952852d # v3
with:
path: node_modules/.cache/prettier/.prettier-cache
key: prettier-${{ hashFiles('package-lock.json') }}-${{ hashFiles('.gitignore') }}
- name: check if workflows needs prettier
run: npx prettier --cache --check ".github/workflows/**/*.yml" || (echo "An action can't make changes to actions, you'll have to run prettier manually" && exit 1)
- run: npx prettier --ignore-path .gitignore --cache --write .
- uses: EndBug/add-and-commit@61a88be553afe4206585b31aa72387c64295d08b # tag=v9
with:
default_author: github_actions
commit: --no-verify
message: 'chore(prettier): 🤖 ✨'
9 changes: 1 addition & 8 deletions .gitignore
Expand Up @@ -9,15 +9,8 @@ pids

# Built sources
/dist
/lib
/lib-node
/umd

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
.nyc_output
# Coverage directory used by tools like c8
coverage

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
Expand Down
1 change: 1 addition & 0 deletions .npmrc
@@ -0,0 +1 @@
legacy-peer-deps=true
3 changes: 0 additions & 3 deletions .nycrc

This file was deleted.

File renamed without changes.
5 changes: 0 additions & 5 deletions .travis.yml

This file was deleted.

0 comments on commit ab8a4fd

Please sign in to comment.