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

Add support for Node ESM #4038

Merged
merged 20 commits into from
Feb 14, 2023
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
8 changes: 7 additions & 1 deletion .circleci/api-comment.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,13 @@ async function run() {

if (pr != null) {
let commentId = await findDifferComment(pr);
let diffs = fs.readFileSync('/tmp/dist/ts-diff.txt');
let diffs;
try {
diffs = fs.readFileSync('/tmp/dist/ts-diff.txt');
} catch (e) {
console.log('No TS Diff output to run on.')
return;
}
if (diffs.length > 0) {
if (commentId != null) {
// delete existing comment
Expand Down
26 changes: 26 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ executors:
CACHE_VERSION: v1
working_directory: ~/react-spectrum

rsp-xlarge-nodeupdate:
docker:
- image: cimg/node:16.18.0
resource_class: xlarge
environment:
CACHE_VERSION: v1
working_directory: ~/react-spectrum

jobs:
install:
executor: rsp-large
Expand Down Expand Up @@ -206,6 +214,20 @@ jobs:
- store_artifacts:
path: ~/junit


test-esm:
executor: rsp-xlarge-nodeupdate
steps:
- restore_cache:
key: react-spectrum-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }}

- run:
name: test
command: |
make build
yarn lerna run prepublishOnly
node --loader ./scripts/esm-support/loader.mjs ./scripts/esm-support/testESM.mjs

lint:
executor: rsp
steps:
Expand Down Expand Up @@ -451,6 +473,9 @@ workflows:
- test-17:
requires:
- install-17
- test-esm:
requires:
- install
- lint:
requires:
- install
Expand Down Expand Up @@ -506,6 +531,7 @@ workflows:
- test-16
- test-ssr-17
- test-17
- test-esm
- storybook
- storybook-16
- storybook-17
Expand Down
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ publish-nightly: build

build:
parcel build packages/@react-{spectrum,aria,stately}/*/ packages/@internationalized/{message,string,date,number}/ --no-optimize
yarn lerna run prepublishOnly
for pkg in packages/@react-{spectrum,aria,stately}/*/ packages/@internationalized/{message,string,date,number}/ packages/@adobe/react-spectrum/ packages/react-aria/ packages/react-stately/; \
do cp $$pkg/dist/module.js $$pkg/dist/import.mjs; \
done
sed -i.bak s/\.js/\.mjs/ packages/@react-aria/i18n/dist/import.mjs
rm packages/@react-aria/i18n/dist/import.mjs.bak

website:
yarn build:docs --public-url /reactspectrum/$$(git rev-parse HEAD)/docs --dist-dir dist/$$(git rev-parse HEAD)/docs
Expand Down
61 changes: 61 additions & 0 deletions babel-esm.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
{
"presets": [
"@babel/preset-typescript",
"@babel/preset-react",
["@babel/preset-env",
{
"loose": true,
"modules": false
}
]
],
"env": {
"storybook": {
"presets": [
[
"@babel/preset-env",
{
"loose": true,
"targets": {
"esmodules": true
}
}
]
]
},
"cover": {
"plugins": [
"istanbul"
]
},
"production": {
"plugins": [
[
"react-remove-properties",
{
"properties": [
"data-testid"
]
}
]
]
}
},
"plugins": [
[
"@babel/plugin-transform-runtime",
{
"version": "^7.6.2"
}
],
[
"@babel/plugin-proposal-decorators",
{
"legacy": true
}
],
"transform-glob-import",
"babel-plugin-macros"
],
"sourceType": "unambiguous"
}
137 changes: 71 additions & 66 deletions bin/imports.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,73 +16,78 @@ const fs = require('fs');
const Module = require('module');
const substrings = ['-', '+'];

module.exports = function (context) {
let processNode = (node) => {
if (!node.source || node.importKind === 'type') {
return;
}

let source = node.source.value.replace(/^[a-z]+:/, '');
if (source.startsWith('.') || Module.builtinModules.includes(source)) {
return;
}

// Split the import specifier on slashes. If it starts with an @ then it's
// a scoped package, otherwise just take the first part.
let parts = source.split('/');
let pkgName = source.startsWith('@') ? parts.slice(0, 2).join('/') : parts[0];

// Search for a package.json starting from the current filename
let pkgPath = findUp.sync('package.json', {cwd: path.dirname(context.getFilename())});
if (!pkgPath) {
return;
}

let pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));

// The only dev dependency should be spectrum-css.
if (exists(pkg.devDependencies, pkgName) && pkgName === '@adobe/spectrum-css-temp') {
return;
}

if (!exists(pkg.dependencies, pkgName) && !exists(pkg.peerDependencies, pkgName)) {
context.report({
node,
message: `Missing dependency on ${pkgName}.`,
fix(fixer) {
// Attempt to find a package in the monorepo. If the dep is for an external library,
// then we cannot auto fix it because we don't know the version to add.
let depPath = __dirname + '/../packages/' + pkgName + '/package.json';
if (!fs.existsSync(depPath)) {
return;
module.exports = {
meta: {
fixable: 'code'
},
create: function (context) {
let processNode = (node) => {
if (!node.source || node.importKind === 'type') {
return;
}

let source = node.source.value.replace(/^[a-z]+:/, '');
if (source.startsWith('.') || Module.builtinModules.includes(source)) {
return;
}

// Split the import specifier on slashes. If it starts with an @ then it's
// a scoped package, otherwise just take the first part.
let parts = source.split('/');
let pkgName = source.startsWith('@') ? parts.slice(0, 2).join('/') : parts[0];

// Search for a package.json starting from the current filename
let pkgPath = findUp.sync('package.json', {cwd: path.dirname(context.getFilename())});
if (!pkgPath) {
return;
}

let pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));

// The only dev dependency should be spectrum-css.
if (exists(pkg.devDependencies, pkgName) && pkgName === '@adobe/spectrum-css-temp') {
return;
}

if (!exists(pkg.dependencies, pkgName) && !exists(pkg.peerDependencies, pkgName) && pkgName !== pkg.name) {
context.report({
node,
message: `Missing dependency on ${pkgName}.`,
fix(fixer) {
// Attempt to find a package in the monorepo. If the dep is for an external library,
// then we cannot auto fix it because we don't know the version to add.
let depPath = __dirname + '/../packages/' + pkgName + '/package.json';
if (!fs.existsSync(depPath)) {
return;
}

let depPkg = JSON.parse(fs.readFileSync(depPath, 'utf8'));
let pkgVersion = substrings.some(v => depPkg.version.includes(v)) ? depPkg.version : `^${depPkg.version}`;

if (pkgName === '@react-spectrum/provider') {
pkg.peerDependencies = insertObject(pkg.peerDependencies, pkgName, pkgVersion);
} else {
pkg.dependencies = insertObject(pkg.dependencies, pkgName, pkgVersion);
}

fs.writeFileSync(pkgPath, JSON.stringify(pkg, false, 2) + '\n');

// Fake fix so eslint doesn't show the error.
return {
range: [0, 0],
text: ''
};
}

let depPkg = JSON.parse(fs.readFileSync(depPath, 'utf8'));
let pkgVersion = substrings.some(v => depPkg.version.includes(v)) ? depPkg.version : `^${depPkg.version}`;

if (pkgName === '@react-spectrum/provider') {
pkg.peerDependencies = insertObject(pkg.peerDependencies, pkgName, pkgVersion);
} else {
pkg.dependencies = insertObject(pkg.dependencies, pkgName, pkgVersion);
}

fs.writeFileSync(pkgPath, JSON.stringify(pkg, false, 2) + '\n');

// Fake fix so eslint doesn't show the error.
return {
range: [0, 0],
text: ''
};
}
});
}
};

return {
ImportDeclaration: processNode,
ExportNamedDeclaration: processNode,
ExportAllDeclaration: processNode
};
});
}
};

return {
ImportDeclaration: processNode,
ExportNamedDeclaration: processNode,
ExportAllDeclaration: processNode
};
}
};

function exists(deps, name) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module.exports = {
export default {
transpilePackages: [
"@adobe/react-spectrum",
"@react-spectrum/actiongroup",
Expand Down
1 change: 1 addition & 0 deletions examples/rsp-next-ts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"start": "next start",
"lint": "next lint"
},
"type": "module",
"dependencies": {
"@adobe/react-spectrum": "^3.22.0",
"@react-spectrum/color": "^3.0.0-beta.16",
Expand Down
3 changes: 3 additions & 0 deletions examples/rsp-webpack-4/.babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"presets": ["@babel/env", "@babel/preset-react"]
}
5 changes: 5 additions & 0 deletions examples/rsp-webpack-4/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = {
moduleNameMapper: {
'\\.(css|styl)$': 'identity-obj-proxy'
}
};
34 changes: 34 additions & 0 deletions examples/rsp-webpack-4/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"name": "rsp-cra-18-webpack-4",
"version": "1.0.0",
"description": "test esm with webpack 4",
"main": "src/index.jsx",
"scripts": {
"build": "webpack --mode production",
"start": "webpack-dev-server --mode development --open",
"test": "test"
},
"private": true,
"workspaces": [
"../../packages/*/*"
],
"dependencies": {
"@adobe/react-spectrum": "^3.24.1",
"@spectrum-icons/workflow": "^4.0.6",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@babel/core": "^7.1.0",
"@babel/cli": "^7.1.0",
"@babel/preset-env": "^7.1.0",
"@babel/preset-react": "^7.0.0",
"webpack": "4.19.1",
"webpack-cli": "3.1.1",
"webpack-dev-server": "3.1.8",
"style-loader": "0.23.0",
"css-loader": "1.0.0",
"babel-loader": "8.0.2",
"jest": "^26"
}
}
22 changes: 22 additions & 0 deletions examples/rsp-webpack-4/src/App.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
body{
height: 100%;
}

.no-bullets{
list-style-type: none;
padding: 0px;
}

#root{
padding: 0;
margin: 0;
height: 100%;
}

html {
height: 100%;
}

.content-padding{
padding: 50px;
}
22 changes: 22 additions & 0 deletions examples/rsp-webpack-4/src/App.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import './App.css';
import {Provider, defaultTheme} from '@adobe/react-spectrum'
import Lighting from './Lighting';
import {useState} from 'react'
import BodyContent from './BodyContent';

function App() {
let [selected, setSelection] = useState(false);

return (
<Provider theme={defaultTheme}
colorScheme={selected ? "light" : "dark"}
height="100%">
<div className="content-padding">
<Lighting selected={selected} switch={setSelection} />
<BodyContent />
</div>
</Provider>
);
}

export default App;
Loading