AOSSIE-Org / AOSSIE-Org/SocialShareButton

[BUG]: npm package cannot be imported from ESM or CJS, the documented README snippet throws

Abierto
#234 1 comentario 0 reacciones 0 asignados Ver en GitHub
bug documentation enhancement
Lenguaje dominante
TypeScript
Estrellas
25
Forks
64
Merge medio
2 d 11 h
PR fusionados (30 d)
1

Descripción

### Bug Description

I was working through the README to try the library in a small React app, and I got stuck on the very first line of the **Advanced Usage > Using npm Package** section. That snippet is:

```javascript
import SocialShareButton from "@aossie-org/social-share-button";
```

Running exactly that against the published `@aossie-org/social-share-button@1.0.4` throws:

```
SyntaxError: The requested module '@aossie-org/social-share-button' does not provide an export named 'default'
```

I assumed I had made a mistake, so I checked the other entry points too. As far as I can tell the published package cannot be consumed from either module system, and only the CDN script tag path works. I wanted to write up what I measured rather than guess, so here is the whole picture.

**What I measured against the published tarball (not a local build):**

| Entry point | Result |
|---|---|
| `import S from '@aossie-org/social-share-button'` | `SyntaxError`, no `default` export |
| `import * as ns from '...'` | resolves, but the namespace is empty (`[]`) |
| `require('@aossie-org/social-share-button')` | returns an empty module namespace, no class |
| `` | works, sets `window.SocialShareButton` |

**Why I think it happens**

`package.json` sets `"type": "module"`, so every `.js` file in the package is an ES module. The only export machinery in `src/social-share-button.js` is at the bottom of the file:

```javascript
if (typeof module !== "undefined" && module.exports) {
module.exports = SocialShareButton;
}

if (typeof window !== "undefined") {
window.SocialShareButton = SocialShareButton;
}
```

In an ES module `module` is not defined, so that first block never runs. There is no `export` statement anywhere in the file, which is why the module genuinely has zero exports rather than just a missing default. The `window` assignment still works, which is why the CDN path is fine and the npm path is not.

Two smaller things I noticed while looking:

1. The `files` array lists the React wrapper but not `src/social-share-button-preact.jsx` or `src/social-share-button-qwik.tsx`, so those two are not in the published tarball. I confirmed this with `tar -tzf` on both my own `npm pack` output and the tarball npm actually serves: 7 files, neither wrapper present.
2. There is no `exports` map, no `module` field, and no `types` field.

### Steps to Reproduce

```bash
mkdir repro && cd repro
printf '{"name":"repro","version":"1.0.0","type":"module","private":true}\n' > package.json
npm install @aossie-org/social-share-button@1.0.4

# ESM, the exact snippet from the README
printf "import S from '@aossie-org/social-share-button';\nconsole.log(S);\n" > esm.mjs
node esm.mjs

# CJS
printf "const m = require('@aossie-org/social-share-button');\nconsole.log(typeof m, Object.keys(m));\n" > cjs.cjs
node cjs.cjs

# what actually shipped
tar -tzf "$(npm pack @aossie-org/social-share-button@1.0.4 2>/dev/null | tail -1)"
```

### Logs and Screenshots

```
### STATIC import, published 1.0.4 ###
SyntaxError: The requested module '@aossie-org/social-share-button' does not provide an export named 'default'

### namespace import ###
namespace keys: []

### CJS require ###
typeof: object keys: [] value: [Module: null prototype] { }

### files shipped ###
social-share-analytics.js
social-share-button-react.jsx
social-share-button.css
social-share-button.js
```

### Environment Details

- OS: macOS (Darwin 25.6.0)
- Node.js: v22.21.0
- npm package: `@aossie-org/social-share-button@1.0.4` installed from the npm registry
- No bundler involved, plain Node, so nothing in my toolchain is papering over or causing the failure

One caveat on the `require` row: Node 22.21 supports `require()` of an ES module, which is why it returns an empty namespace instead of erroring. I did not test on a Node version without that support, so I would not want to claim what happens there.

### Impact

High - Major feature is broken

The CDN and script tag path is unaffected, so this is not a total outage. It is the npm install path and the README snippet documenting it that do not work.

### Proposed fix

I put together a patched build locally and verified it, mostly to be sure I was not proposing something that would not work. Three parts:

1. Add real ESM exports to `src/social-share-button.js`:
```javascript
export default SocialShareButton;
export { SocialShareButton };
```
2. Add an `exports` map with `import` and `require` conditions, plus named subpaths for the CSS and the framework wrappers.
3. Add the Preact and Qwik wrappers to `files` so they actually ship.

With those applied, all three entry points return the real class:

```
### ESM static default import ###
typeof: function | name: SocialShareButton
### ESM named import ###
typeof: function | name: SocialShareButton
### CJS require ###
typeof default: function | name: SocialShareButton
```

### A few things I would rather ask than decide

These felt like calls that belong to the maintainers, so I did not want to assume:

1. **How should CJS be served?** The repo has no build step today. I got `require()` working with a two line `.cjs` file that re-exports the ESM one, which keeps things build free. The alternative is a real bundler step producing a proper CJS build. The first is much smaller, the second is more conventional. Do you have a preference, or would you rather the package go ESM only and just document that clearly? Going ESM only would also mean deleting the dead `module.exports` block, which might be the most honest option.
2. **Should the old deep paths keep working?** Adding an `exports` map is technically a breaking change, because it stops consumers from reaching into `src/...` directly. The README currently documents `import "@aossie-org/social-share-button/src/social-share-button.css"`. I can keep that path working alongside a nicer `/css` subpath so nothing breaks, or make the clean break. Happy either way, just did not want to silently break someone.
3. **Is the Qwik wrapper meant to ship as `.tsx` source?** Node cannot load `.jsx` or `.tsx` directly, so those subpaths only work for consumers with a bundler. That is completely normal for source shipped components, but it does mean the wrappers are bundler only, and I did not know whether that was the intent.

### Relationship to #233

This overlaps with #233 (adding TypeScript definitions) but does not duplicate it, and I am explicitly not asking for that issue. It is @Mansi2007275's and they said in the body that they intend to write the `.d.ts` files themselves.

The connection is just that the two need each other to be useful. Type definitions are surfaced to consumers through a `types` field or a `types` condition in the `exports` map, and this package currently has neither. So once the `.d.ts` files from #233 land, they still will not be picked up until the packaging side is sorted out. If it helps, I would be glad to make sure whatever `exports` map comes out of this leaves a clean `types` slot for #233 to drop into, so the two pieces meet without either of us having to redo work. Entirely happy to sequence it whichever way suits, including waiting for #233 to land first.

### Offer

If this is something you would like fixed, I would be happy to send a PR. I have the change working locally already. I would just want a steer on question 1 and 2 above first, since the answers change the shape of the diff quite a bit. And if you would rather someone else pick this up, or if I have misread the intent and the package is meant to be CDN only, please do say, no problem at all.

### AI disclosure

I used Claude to help investigate this and to draft this write up. The reproduction, the measurements in the table, the tarball contents and the patched build were all run and verified by me locally against the published package.

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.