-
Notifications
You must be signed in to change notification settings - Fork 26
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
feat: migrate api
and core
to ESM
#733
Conversation
i hate this song
@@ -2,11 +2,13 @@ | |||
"name": "api", | |||
"version": "7.0.0-alpha.3", | |||
"description": "Magical SDK generation from an OpenAPI definition 🪄", | |||
"type": "module", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
api
is now ESM-only. Codegen'd SDKs will support ESM and CJS but because api
is a CLI-only tool we don't need to accommodate both module flows.
@@ -197,8 +196,8 @@ describe('typescript', () => { | |||
}); | |||
}); | |||
|
|||
it('should be able to make an API request (JS + CommonJS)', async () => { | |||
const sdk = await import('../../__fixtures__/sdk/simple-js-cjs').then(r => r.default); | |||
it.skip('should be able to make an API request (JS + CommonJS)', async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These tests that are testing CJS built SDKs no longer work because of the way that these modules are handled now. These tests will get reworked in #734 when we refactor the codegen process to properly build CJS SDKs.
// eslint-disable-next-line import/extensions | ||
import '@api/test-utils/vitest.matchers.ts'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks funky but because the way the test-utils
package is setup if we don't have this .ts
extension here then the import for these Vitest matchers don't get properly loaded. @kanadgupta and I went through a whole pairing on session on this and settled on a method of getting it working with a very complicated exports
object in the package.json
for that package but that ultimately broke a lot of things downstream where we're loading definitions out of @api/test-utils/definitions
.
Just adding this .ts
extension, and the very minor change to the Vitest config to use ../test-utils
instead of @api/test-utils
is a cleaner option than a flaky package config.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so weird my goodness
"require": "./dist/index.cjs", | ||
"import": "./dist/index.js" | ||
}, | ||
"./errors/fetchError": { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the only other export because it might be nice for folks to be able to do instanceof FetchError
in their implementations.
@@ -35,8 +31,6 @@ type Enumerate<N extends number, Acc extends number[] = []> = Acc['length'] exte | |||
|
|||
export type HTTPMethodRange<F extends number, T extends number> = Exclude<Enumerate<T>, Enumerate<F>>; | |||
|
|||
export { getJSONSchemaDefaults, parseResponse, prepareAuth, prepareParams, prepareServer }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not only are these utilities causing issues with the CJS export of this library but also these utilities are never used outside of core internals so they don't need to be exported.
@@ -35,8 +31,6 @@ type Enumerate<N extends number, Acc extends number[] = []> = Acc['length'] exte | |||
|
|||
export type HTTPMethodRange<F extends number, T extends number> = Exclude<Enumerate<T>, Enumerate<F>>; | |||
|
|||
export { getJSONSchemaDefaults, parseResponse, prepareAuth, prepareParams, prepareServer }; | |||
|
|||
export default class APICore { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This default export alongside the named TS type exports is still causing issues with attw
:
> @readme/api-core@7.0.0-alpha.3 attw
> attw --pack --format table-flipped
@readme/api-core v7.0.0-alpha.3
Build tools:
- typescript@^5.2.2
❓ The JavaScript appears to set both module.exports and module.exports.default for improved compatibility, but the types only reflect the latter (by using export default). This will cause TypeScript under the node16 module mode to think an extra .default property access is required, which will work at runtime but is not necessary. These types export = an object with a default property instead of using export default. https://github.com/arethetypeswrong/arethetypeswrong.github.io/blob/main/docs/problems/MissingExportEquals.md
💀 Import failed to resolve to type declarations or JavaScript files. https://github.com/arethetypeswrong/arethetypeswrong.github.io/blob/main/docs/problems/NoResolution.md
┌──────────────────────────────────────┬───────────────────────┬───────────────────────┬───────────────────┬───────────┐
│ │ node10 │ node16 (from CJS) │ node16 (from ESM) │ bundler │
├──────────────────────────────────────┼───────────────────────┼───────────────────────┼───────────────────┼───────────┤
│ "@readme/api-core" │ ❓ Missing `export =` │ ❓ Missing `export =` │ 🟢 (ESM) │ 🟢 │
├──────────────────────────────────────┼───────────────────────┼───────────────────────┼───────────────────┼───────────┤
│ "@readme/api-core/errors/fetchError" │ 💀 Resolution failed │ 🟢 (CJS) │ 🟢 (ESM) │ 🟢 │
├──────────────────────────────────────┼───────────────────────┼───────────────────────┼───────────────────┼───────────┤
│ "@readme/api-core/package.json" │ 🟢 (JSON) │ 🟢 (JSON) │ 🟢 (JSON) │ 🟢 (JSON) │
└──────────────────────────────────────┴───────────────────────┴───────────────────────┴───────────────────┴───────────┘
Everything seems to work with the dist but it still worries me. I attempted to refactor the TS type exports out into a types.ts
file, which satisfies attw
but using that types file is another story:
diff --git a/packages/core/package.json b/packages/core/package.json
index 5d16e2b..4e95761 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -13,6 +13,10 @@
"require": "./dist/errors/fetchError.cjs",
"import": "./dist/errors/fetchError.js"
},
+ "./types": {
+ "require": "./dist/types.d.cts",
+ "import": "./dist/types.d.ts"
+ },
"./package.json": "./package.json"
},
"main": "dist/index.cjs",
@@ -74,7 +74,7 @@ function getAuthSources(operation: Operation) { | |||
return matchers; | |||
} | |||
|
|||
export interface APIOptions { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This interface is never used outside of the library so it doesn't need to be exported.
@@ -87,6 +87,7 @@ const client: Client<APIOptions> = { | |||
title: 'API', | |||
link: 'https://npm.im/api', | |||
description: 'Automatic SDK generation from an OpenAPI definition.', | |||
extname: '.js', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a new requirement I added in @readme/httpsnippet
when I upgraded it to support ESM.
@@ -111,7 +110,7 @@ describe('httpsnippet-client-api', () => { | |||
it('should generate the expected snippet', async () => { | |||
const expected = await fs.readFile(path.join(DATASETS_DIR, snippet, 'output.js'), 'utf-8'); | |||
|
|||
const code = new HTTPSnippet(mock.har).convert('node', 'api', { | |||
const code = await new HTTPSnippet(mock.har).convert('node', 'api', { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks to some native fetch
improvements I did in @readme/httpsnippet
, completely dropping support for funky FormData
objects that node-fetch@2
supports, the convert
function there is now async.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changes look good but I don't think we need tsup
for the api
and core
packages, more on this below!
packages/core/tsup.config.ts
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay i also don't think we need to build this subpackage with tsup
either and I think we can just rely on tsc
— I was able to get pretty far in #734 with just the ESM build of this subpackage! i say this for several reasons:
-
to eliminate the confusing accommodations we have to make here (see this comment)
-
we're using
tsup
at the code-gen level in feat: esm +tsup
#734, which will take care of bundling the ESM code and spitting out proper CJS/ESM SDKs. this pretty much eliminates the need for us to do any dual-export mess for downstream packages (with the exception of packages that we need for cjs repos like our main app, of course)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think? that if we dont offer cjs exports of this library then cjs codegend sdks wont be able to use it because itll be esm only and tsup wont touch it because its loaded in code as a dependency
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ill change this and see how it shakes out
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
slept on it for a few days and i'm a bit nervous about making core
ESM-only with tsc
so im going to wait until the tsup
codegen work is done before making any refactors to the core
build process.
🧰 Changes
This very much (in-progress) PR migrates the
api
andcore
subpackages over to ESM. Since we're theoretically going to be using a build tool like Rollup ortsup
to generate the ESM- and CJS-flavored SDKs, we theoretically should be able to move everything here to pure ESM (but could be wrong about that, will report back 😮💨)Known Issues
.json
files here:api/packages/httpsnippet-client-api/test/__datasets__/application-form-encoded/index.ts
Line 4 in 61bf2de
fetch-har
(hopefully should be addressed by feat: esm and cjs exports fetch-har#427):api/packages/core/src/index.ts
Lines 125 to 126 in ec9754c
tsup
#734🧬 QA & Testing
Provide as much information as you can on how to test what you've done.