fix: make module import-safe in Node/SSR environments#35
Open
dmchaledev wants to merge 1 commit into
Open
Conversation
Importing the package in any non-browser context (Node, SSR, build-time prerender) threw 'ReferenceError: document is not defined' because the <template>, the HTMLElement base class, and customElements.define() were all evaluated unconditionally at module load. This contradicted the README/index.d.ts, which advertise a pure DOM-free calculate() and list Next.js (SSR) as a supported environment. The existing smoke test masked the bug by installing global DOM shims before importing. - Build the <template> lazily (only when a component is instantiated) - Fall back to a plain base class when HTMLElement is undefined - Guard customElements.define() on browser availability + double-define Browser behavior is unchanged. Adds test/ssr-import.test.mjs, which imports the module with no DOM globals to lock in SSR/Node import safety. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TYLi1vdETg67Kc1DHNAwTk
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Problem
Importing the package in any non-browser context — Node, SSR, or build-time prerender — throws immediately at module load:
(and
HTMLElement is not definedoncedocumentis shimmed).This directly contradicts what the package advertises:
import { calculate } from '@hailbytes/vulnerability-calculator') and lists Next.js among supported frameworks.index.d.tsdocumentscalculate()as "Pure infrastructure-sizing calculation — no DOM required."But the module evaluated three things unconditionally at the top level, all of which require a browser:
class HailbytesVulnCalculator extends HTMLElement—HTMLElementis undefined in Node/SSRconst TMPL = document.createElement('template')—documentis undefinedcustomElements.define(...)—customElementsis undefinedThe existing
test/smoke.test.mjsmasked the bug because it installs global DOM shims before importing the module, which is not how Next.js SSR or a server-sidecalculate()call behaves.Reproduction
Fix
Make the three browser-only operations defer/guard on environment availability. Browser behavior is unchanged; the element still registers and renders identically when a DOM is present.
<template>lazily — only when a component is actually instantiated.HTMLElementis undefined, so the class declaration evaluates in Node/SSR.customElements.define()on browser availability, and skip it if the element is already defined (avoids double-registration errors).Tests
Adds
test/ssr-import.test.mjs, which imports the module in a plain Node process with no DOM globals (the Node test runner isolates each test file in its own process) and asserts both import-safety and thatcalculate()works server-side.🤖 Generated with Claude Code
Generated by Claude Code