-
Notifications
You must be signed in to change notification settings - Fork 9
npm publishing interfaces #388
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
base: main
Are you sure you want to change the base?
Conversation
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.
Pull request overview
This PR sets up npm publishing infrastructure for the @janhq/interfaces package, making it available as a standalone npm package. The changes prepare the package for distribution by configuring build settings, publishing workflow, and adjusting internal import paths.
Key changes:
- Added TypeScript build configuration and npm publishing workflow
- Configured package.json with metadata, exports, and build scripts for npm distribution
- Fixed import path in sonner.tsx to use relative path instead of alias, and added ThemeProvider implementation
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
packages/interfaces/tsconfig.build.json |
New TypeScript build configuration for compiling the package with declaration files |
packages/interfaces/package.json |
Updated with publishing metadata, version 0.1.0, exports configuration, and build scripts |
packages/interfaces/src/ui/sonner.tsx |
Fixed import path from alias to relative path for theme provider |
packages/interfaces/src/providers/theme-provider.tsx |
Added ThemeProvider component for theme management |
package.json |
Added build script shortcut for building interfaces package |
.github/workflows/publish-interfaces.yml |
New GitHub Actions workflow for automated npm publishing on tagged releases |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| on: | ||
| push: | ||
| tags: ['v[0-9]+.[0-9]+.[0-9]+-interfaces'] | ||
| paths: ['packages/interfaces/**', '.github/workflows/publish-interfaces.yml'] |
Copilot
AI
Jan 2, 2026
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.
The paths filter in the workflow trigger will not work correctly with tags. The paths filter is only valid for push and pull_request events on branches, not on tag pushes. This means the paths filter will be ignored when a tag is pushed.
| paths: ['packages/interfaces/**', '.github/workflows/publish-interfaces.yml'] |
|
|
||
| - name: Extract tag name without v prefix | ||
| id: get_version | ||
| run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV && echo "::set-output name=version::${GITHUB_REF#refs/tags/v}" |
Copilot
AI
Jan 2, 2026
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.
The set-output command is deprecated and will be disabled in the future. Use environment files instead by writing to $GITHUB_OUTPUT. Additionally, the VERSION environment variable is already being set, making the set-output redundant.
| run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV && echo "::set-output name=version::${GITHUB_REF#refs/tags/v}" | |
| run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV |
| "main": "./dist/index.js", | ||
| "types": "./dist/index.d.ts", |
Copilot
AI
Jan 2, 2026
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.
The package specifies main as ./dist/index.js and types as ./dist/index.d.ts, but there appears to be no src/index.ts file in the source directory. When the package is built, TypeScript will not generate these files. Either create an src/index.ts entry point file, or remove the main and types fields if this package is intended to be used exclusively through the subpath exports.
| "main": "./dist/index.js", | |
| "types": "./dist/index.d.ts", |
| () => (localStorage.getItem(storageKey) as Theme) || defaultTheme, | ||
| ); | ||
|
|
||
| useEffect(() => { | ||
| const root = window.document.documentElement; | ||
|
|
||
| root.classList.remove("light", "dark"); | ||
|
|
||
| if (theme === "system") { | ||
| const systemTheme = window.matchMedia("(prefers-color-scheme: dark)") | ||
| .matches | ||
| ? "dark" | ||
| : "light"; | ||
|
|
||
| root.classList.add(systemTheme); | ||
| return; | ||
| } | ||
|
|
||
| root.classList.add(theme); | ||
| }, [theme]); | ||
|
|
||
| const value = { | ||
| theme, | ||
| setTheme: (theme: Theme) => { | ||
| localStorage.setItem(storageKey, theme); |
Copilot
AI
Jan 2, 2026
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.
The ThemeProvider directly accesses localStorage and window without checking if they exist. This will cause the component to fail in server-side rendering (SSR) environments like Next.js. Consider adding checks like typeof window !== 'undefined' before accessing browser APIs, or wrap these calls in a way that's safe for SSR.
| new_version=$(echo $tag | sed -n 's/-interfaces//p') | ||
| echo $new_version |
Copilot
AI
Jan 2, 2026
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.
The sed command with -n flag and s///p will only print lines that match and substitute. If the tag doesn't contain "-interfaces", this will result in an empty new_version. This could cause the package.json to have an empty version field. Consider using a simpler approach like sed 's/-interfaces//' without the -n and p flags, or add validation to ensure the version is not empty before updating package.json.
| new_version=$(echo $tag | sed -n 's/-interfaces//p') | |
| echo $new_version | |
| new_version=$(echo "$tag" | sed 's/-interfaces$//') | |
| if [ -z "$new_version" ]; then | |
| echo "Error: Derived version is empty. Original tag: '$tag'" >&2 | |
| exit 1 | |
| fi | |
| echo "$new_version" |
| "allowImportingTsExtensions": false, | ||
| "moduleResolution": "node" |
Copilot
AI
Jan 2, 2026
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.
The tsconfig.build.json sets moduleResolution to "node", but the base tsconfig.json uses "bundler". For a published npm package, "node" or "node16"/"nodenext" is more appropriate. However, the base config also has allowImportingTsExtensions: true which conflicts with emitting files (building). The build config correctly sets this to false, but consider aligning the module resolution strategy between configs or ensuring the build output is compatible with Node.js module resolution.
| "allowImportingTsExtensions": false, | |
| "moduleResolution": "node" | |
| "allowImportingTsExtensions": false |
| run: npm install | ||
| working-directory: packages/interfaces |
Copilot
AI
Jan 2, 2026
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.
Installing dependencies only in the packages/interfaces directory may fail if the package has workspace dependencies or if the monorepo uses workspace features. Consider running npm install from the root directory first to ensure all workspace dependencies are properly linked, or use npm ci for a clean install based on the lockfile.
| run: npm install | |
| working-directory: packages/interfaces | |
| run: npm ci |
| useEffect(() => { | ||
| const root = window.document.documentElement; | ||
|
|
||
| root.classList.remove("light", "dark"); | ||
|
|
||
| if (theme === "system") { | ||
| const systemTheme = window.matchMedia("(prefers-color-scheme: dark)") | ||
| .matches | ||
| ? "dark" | ||
| : "light"; | ||
|
|
||
| root.classList.add(systemTheme); | ||
| return; | ||
| } | ||
|
|
||
| root.classList.add(theme); | ||
| }, [theme]); |
Copilot
AI
Jan 2, 2026
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.
The useEffect accesses window.document and window.matchMedia without checking if window is defined. This will cause errors in SSR environments. Wrap the useEffect content in a check like if (typeof window === 'undefined') return; or ensure this component only runs on the client side.
packages/interfaces/package.json
Outdated
| "./providers/*": { | ||
| "types": "./src/providers/*.tsx", | ||
| "default": "./src/providers/*.tsx" | ||
| }, | ||
| "./providers/theme-provider": { | ||
| "types": "./src/providers/theme-provider.tsx", | ||
| "default": "./src/providers/theme-provider.tsx" | ||
| }, |
Copilot
AI
Jan 2, 2026
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.
The wildcard export pattern ./providers/* with source file paths won't work correctly when the package is published with compiled files. Additionally, having both a wildcard pattern (./providers/*) and a specific export (./providers/theme-provider) is redundant - the wildcard should already cover the specific case. Consider removing the redundant specific export or restructuring the exports to point to compiled files in the dist directory.
c63b2dd to
3de4277
Compare
3de4277 to
62a7f1c
Compare
62a7f1c to
e71d47a
Compare
Describe Your Changes
Fixes Issues
Self Checklist