Skip to content

feature: Better exports#126

Open
ejn wants to merge 2 commits intocamptocamp:mainfrom
ejn:feature/better-exports
Open

feature: Better exports#126
ejn wants to merge 2 commits intocamptocamp:mainfrom
ejn:feature/better-exports

Conversation

@ejn
Copy link
Copy Markdown
Contributor

@ejn ejn commented Oct 17, 2025

This has the aim of exposing the existing API without using a single barrel file, so that e.g. the http-utils functions can be sensibly used by other packages or so that a bundler-friendly import of individual modules can be used.

The existing exports as defined in the base index.js have been modularised into indidual files under api/. Everything is still re-exported in index.js ensuring the existing exported API is still available without change, but adding the new individual exports to be used for those who want them.

As a bonus the function setQueryParams() from http-utils is exposed as this could be helpful for users of this library. Actually this was the reason I started on this PR, the rest was just trying to do things better :)

ejn added 2 commits October 17, 2025 14:57
This has the aim of exposing the existing API without using a single
barrel file, so that e.g. the http-utils functions can be sensibly used
by other packages or so that a bundler-friendly import of individual
modules can be used.

The existing exports as defined in the base index.js have been
modularised into indidual files under api/. Everything is still
re-exported in index.js ensuring the existing exported API is still
available without change, but adding the new individual exports.
@ejn ejn force-pushed the feature/better-exports branch from 9c191ef to 790f6a4 Compare October 17, 2025 12:57
@ejn
Copy link
Copy Markdown
Contributor Author

ejn commented Oct 17, 2025

Sorry for the noise - now tidied up the lint problems and rebased for a clean history

@jahow
Copy link
Copy Markdown
Member

jahow commented Oct 17, 2025

Thank you! I'm on mobile currently so I'll give this a more complete review later.

I have some questions/remarks already:

  • Don't you think it could make sense to group APIs into more logical paths instead of simply following the inner code structure? I.e. ogc-client/utils, ogc-client/wfs, ogc-client/ogcapi etc
  • I have the impression that this PR exposes things that were not part of the API before; this is risky as it means we'll be stuck with these symbols unless we do a breaking change which is annoying for everyone
  • Have you checked the output of the API doc website with your changes? It might be broken (or not, I'm not sure)
  • Lastly, I feel like bundlers are already able to leave out pieces of code that are not used, even though they are under the same import path; have you confirmed that your PR does indeed change a typical bundle size?

Thank you!

@ejn
Copy link
Copy Markdown
Contributor Author

ejn commented Oct 17, 2025

  1. That's pretty much what this PR does - the files under /api do the grouping, and are then exported using logical(ish) names
  2. The aim was for the API surface to remain exactly the same as previously, just exported (1) as a bundle and (2) as individual modules
  3. I haven't checked the doc output - obviously that should be done!
  4. Yes and no - doing the tree shaking takes time for the bundler so that the build is slower, and may or may not be perfect. Additionally there are files included which have side effects (e.g. the installation of the worker) which may not be strictly necessary for any particular use case. In my case I was wanting to include the one function (which has no side-effects) "statically" but the rest of the library should be dynamically loaded on demand: Separating the exports means that the bundler can sort that out elegantly. Otherwise I'm not so sure. Other libraries (e.g. OpenLayers) are moving away from barrel files: This PR is a bit of a halfway house with small files for each API module to keep the same API surface as beforehand but removing the need to always import from the one big barrel.

@ejn
Copy link
Copy Markdown
Contributor Author

ejn commented Oct 17, 2025

(and thanks for the quick reply - I've tried to answer quickly as I won't be able to for the next few days: but I understand that this PR is in some way a fairly big change so I was expecting some discussion!)

Copy link
Copy Markdown
Member

@jahow jahow left a comment

Choose a reason for hiding this comment

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

Ok so I think this approach is good and it'd be great to have it in the next release.

As for entrypoints I think it'd be great to just have these:

  • ogc-client/shared[.js] (containing everything under /shared including http-utils, cache, etc. for the sake of simplicity)
  • ogc-client/ogc-api[.js]
  • ogc-client/wms[.js]
  • ogc-client/wmts[.js]
  • ogc-client/wfs[.js]
  • ogc-client/tms[.js]
  • ...and ogc-client/stac[.js] when #129 is merged

Importing things from ogc-client[/index.js] should obviously still work!

Note the ability to point to actual JS files which is important when working without a bundler.

If you don't have the capacity to update this PR I can also do it, and anyway we'll rebase this once #129 is merged so that we can add the new path accordingly.

Comment thread src/api/shared/errors.ts
@@ -0,0 +1,5 @@
export {
check,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

we can probably drop this to be honest, I can't remember why it's part of the API in the first place; to be investigated more

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I guess officially that would be an API break and a new major version since this function is already exposed?

Maybe in the first instance keep the export but mark it as @deprecated?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

it would be a major version yes, but I think we're heading that way because we dropped support for older versions of node

export {
sharedFetch,
setFetchOptions,
setQueryParams,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I would not put this in the API, even though it's useful it's also specific to what we do inside the library and we need toe flexibility to change its behavior without notice

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The other functions already exposed from http-utils should stay though?

Since re-using this function was my original motivation for this then it's a shame, but I understand your reasons for not wanting it to be part of the API: I guess I'll just have to copy and paste it into my local library instead.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

well we might also leave it exported but mark it as not part of the official API; then we still have the freedom of changing it in the future!

Could you describe a bit more your use case? maybe we can expose something a bit more high level in the API too.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I had to look what I'm actually doing with it! Looks like building up custom WFS queries in a scenario where I'm not wanting to first retrieve the capabilities (capabilities are retrieved once when the layer is added and the configuration saved - when the map is re-opened then no new capabilities request is made).

I think I actually replaced a local function I had with this function since it is a nice implementation of all the special cases needed for dealing with OWS GET requests, particularly case-sensitive parameter names, and was better than what I previously had.

For such nice general-purpose functions I always find it a shame when libraries don't expose them for re-use, although I can understand the argument of wanting to keep the API surface higher-level.

@ejn
Copy link
Copy Markdown
Contributor Author

ejn commented Nov 3, 2025

As for entrypoints I think it'd be great to just have these:

* `ogc-client/shared[.js]` (containing everything under /shared including http-utils, cache, etc. for the sake of simplicity)

I assume, regarding your comment below, now not including http-utils?

Importing things from ogc-client[/index.js] should obviously still work!

Agreed.

Note the ability to point to actual JS files which is important when working without a bundler.

Is this really necessary when those working without a bundler can import directly from ogc-client, which also exposes the same complete API? If you think yes then would it be sensible to make the entrypoints all ogc-client/*.js so that the import paths are the same in all cases?

If you don't have the capacity to update this PR I can also do it, and anyway we'll rebase this once #129 is merged so that we can add the new path accordingly.

I'm happy to keep working on this - from your feedback we're only really talking about minor changes here.

@jahow
Copy link
Copy Markdown
Member

jahow commented Nov 4, 2025

Is this really necessary when those working without a bundler can import directly from ogc-client, which also exposes the same complete API? If you think yes then would it be sensible to make the entrypoints all ogc-client/*.js so that the import paths are the same in all cases?

If the code contains imports like import { WfsEndpoint } from 'ogc-client/wfs.js then it just needs an import map like so to run without a bundler:

{
  'ogc-client/': 'https://path-to-libs/ogc-client/'
}

Whereas if the import is import { WfsEndpoint } from 'ogc-client/wfs or even import { WfsEndpoint } from 'ogc-client then the import map must look like this:

{
  'ogc-client': 'https://path-to-libs/ogc-client/index.js',
  'ogc-client/wfs': 'https://path-to-libs/ogc-client/wfs.js',
  // etc... all other internals of ogc-client must be added here
}

So I think it makes sense to allow the first kind of imports? I'm not 100% sure though.

@ejn
Copy link
Copy Markdown
Contributor Author

ejn commented Nov 7, 2025

So I think it makes sense to allow the first kind of imports? I'm not 100% sure though.

I've no idea really either since my use-case is always with a bundler, but I can't see any real disadvantages to having the exports all as [path].js and if it makes some use-cases easier then why not...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants