Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This project currently uses a combination of CJS
require
/module.exports
and ESMimport
/export
. As part of my efforts to help finish porting to TypeScript, I keep running into issues where one module is exported usingmodule.exports = …
and another is usingexport function …
, which means sometimes it can be loaded withimport
, and sometimes it has to userequire
.I thought it might be
easier(haha) better to first standardized on ESM by converting everything toimport
/export
, so this branch is an attempt to remedy that. It has turned out to be way more work than I expected, and it's not done yet.Summary of changes:
"type": "module"
in all thepackage.json
files, which tells node to treat all files as ESM modules, which among other things, blocks the use of CJS features likemodule.exports
,require()
, and__dirname
.require
statements withimport
.import
statements to use full file paths instead of directories or extension-less imports, for example:module.exports = …
withexport const …
/export function …
/export default …
__dirname
withimport.meta.dirname
There are a few things that I'm still working through:
import
is called dynamically inside a function–and not statically at the top of a file–it is asynchronous. There is no way to make it synchronous likerequire()
is. That means any dynamic loading (like json config files, or the configured security strategy), it is asynchronous. A lot of this setup currently happens in theconstructor
function of theServer
class, and constructors cannot be async. The json files are easy to fix by callingJSON.parse(fs.readFileSync(…))
, but there's not an immediately obviously solution to dynamically loading functionality like the security strategy. My current plan is to let this PR sit while I work on a new branch to refactor server initialization to allow asynchronous loading, and then rebase this.import.meta.dirname
was added in NodeJS 20.11, so I need to add a helper function to make work with node 20.0-20.10. It's only a couple lines of code to useimport.meta.url
.tsc -b
and passeseslint
, but the server fails to start and most of the tests are failing due to the first issue with asynchronous initialization.@signalk/server-admin-ui-dependencies
is still a CJS module. All it does is verify dependencies on load, so I'm not sure there is any value in converting it to ESM, but I can look closer at it@signalk/server-api
probably needs to be published as both ESM and CJS for CJS plugins that depend on it. It's easy to add support for both in the same package, it just requires anothertsconfig
and build step.