Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,13 @@ jobs:
steps:
- uses: actions/checkout@v3

- name: Install pnpm
uses: pnpm/action-setup@v3
with:
version: 9

- name: Install Vercel CLI
run: npm install --global vercel@latest
run: pnpm add --global vercel@latest

- name: Pull Vercel Environment Information
run: vercel pull --yes --environment=${{ env.VERCEL_ENV }} --token=${{ secrets.VERCEL_TOKEN }}
Expand Down
26 changes: 18 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,28 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4

- name: Install pnpm
uses: pnpm/action-setup@v3
with:
version: 9

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "22.x"
cache: "npm"
cache: "pnpm"

- name: Install dependencies
run: npm ci
run: pnpm install --frozen-lockfile

- name: Run ESLint
run: npm run lint
run: pnpm run lint

- name: Check Prettier formatting
run: npm run format:check
run: pnpm run format:check

- name: TypeScript type check
run: npm run typecheck
run: pnpm run typecheck

build:
name: Build
Expand All @@ -39,16 +44,21 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4

- name: Install pnpm
uses: pnpm/action-setup@v3
with:
version: 9

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "22.x"
cache: "npm"
cache: "pnpm"

- name: Install dependencies
run: npm ci
run: pnpm install --frozen-lockfile

- name: Build
run: npm run build
run: pnpm run build
env:
NODE_ENV: production
7 changes: 6 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,13 @@ jobs:
steps:
- uses: actions/checkout@v3

- name: Install pnpm
uses: pnpm/action-setup@v3
with:
version: 9

- name: Install Vercel CLI
run: npm install --global vercel@latest
run: pnpm add --global vercel@latest

- name: Pull Vercel Environment Information
run: vercel pull --yes --environment=${{ env.VERCEL_ENV }} --token=${{ secrets.VERCEL_TOKEN }}
Expand Down
2 changes: 1 addition & 1 deletion .husky/commit-msg
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
npx --no -- commitlint --edit ${1}
pnpm dlx commitlint --edit ${1}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

pnpm dlx vs npx --no behavior commitlint

💡 Result:

Short answer: they’re different.

  • npx --no (aka --no-install) prevents npx from downloading a package; it only runs an existing local/global binary and will fail instead of installing. This is what commitlint docs use in husky hooks to avoid prompting to install. [1][3]

  • pnpm dlx always fetches a package temporarily from the registry and runs it (does not add it to package.json). It’s the pnpm equivalent of npx for one‑off remote execution. It does not implement an npx‑style “no‑install” that refuses to download. [2]

Practical guidance for commitlint + Husky:

  • If commitlint is a devDependency in the repo: run the local binary via pnpm (pnpm exec commitlint or simply pnpm commitlint) in the hook. That mirrors npx --no behaviour (no remote install). [2][3]
  • If you want the one‑time download/execute behaviour (like npx when it installs), use pnpm dlx commitlint ... which will fetch commitlint temporarily. [2][3]

Sources:
[1] npx docs (npm) — npx options and --no/--no-install behavior.
[2] pnpm dlx docs — dlx fetches and runs packages temporarily.
[3] commitlint local setup (Husky example uses "npx --no -- commitlint --edit $1").


🌐 Web query:

pnpm dlx automatic install prompt behavior missing package

💡 Result:

Short answer: pnpm dlx does not "automatically install" a package into your project — it fetches the requested package temporarily from the registry and runs it. If the package cannot be resolved (not published, private/unreachable, or blocked by policy like minimumReleaseAge), dlx will fail with an error (or with the same resolution behavior as normal pnpm commands) rather than silently installing something different. There are related pnpm settings that control prompts and automatic installs for other commands (e.g., verify-deps-before-run), and there are known edge-case bugs (e.g., minimumReleaseAge interactions) discussed in the pnpm issue tracker. See pnpm dlx docs and related GitHub issues for details. [1][2][3]

Sources:

  • pnpm dlx documentation. [1]
  • pnpm CLI docs / release notes mentioning verify-deps-before-run and dlx behavior. [2]
  • GitHub issue discussing dlx / minimumReleaseAge behavior. [3]

🌐 Web query:

npx --no flag purpose prevent install prompt

💡 Result:

--no tells npx to answer the interactive "Ok to proceed?" prompt with "no" (i.e., refuse installing missing packages), so it prevents npx from prompting to download/install and causes the run to fail if the command isn’t already available. It’s the replacement for the older --no-install behavior. [1][2]


pnpm dlx에서 pnpm exec로 변경하세요.

npx --no에서 pnpm dlx로의 전환은 기능적으로 다릅니다. 다음을 확인해주세요:

  1. npx --no의 역할: 원격 패키지 설치를 거부하고 로컬에 있는 패키지만 실행합니다. 패키지가 없으면 실행이 실패합니다.

  2. pnpm dlx의 동작: 항상 레지스트리에서 패키지를 임시로 다운로드하여 실행합니다. --no 같은 플래그로 다운로드를 거부할 수 없습니다.

  3. 올바른 대체 방법: commitlint가 devDependency로 설치되어 있다면 pnpm exec commitlint --edit ${1}을 사용하세요. 이것이 npx --no 동작과 동등합니다.

현재 코드는 의도하지 않은 동작 변경을 포함하고 있습니다.

🤖 Prompt for AI Agents
In @.husky/commit-msg at line 1, Replace the use of "pnpm dlx commitlint --edit
${1}" with the equivalent local-only execution "pnpm exec commitlint --edit
${1}" in the .husky/commit-msg hook (change the "pnpm dlx commitlint --edit
${1}" invocation), and ensure commitlint is installed as a devDependency so the
local exec will run the local package rather than downloading from the registry.


4 changes: 2 additions & 2 deletions .husky/pre-push
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
echo "🔍 Running lint check before push..."
npm run lint
pnpm run lint

echo "🔍 Running type check before push..."
npm run typecheck
pnpm run typecheck

echo "✅ All checks passed!"
9 changes: 9 additions & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Next.js 호환성을 위한 설정
shamefully-hoist=true
auto-install-peers=true
strict-peer-dependencies=false
Comment on lines +1 to +4
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Check if .npmrc exists and read its content
if [ -f .npmrc ]; then
  echo "=== .npmrc content ==="
  cat -n .npmrc
  echo ""
else
  echo ".npmrc not found"
fi

# Check for package.json to understand the project
if [ -f package.json ]; then
  echo "=== package.json (first 50 lines) ==="
  head -50 package.json
  echo ""
fi

Repository: solid-connection/solid-connect-web

Length of output: 2002


🏁 Script executed:

# Search for any related issues or comments about shamefully-hoist or pnpm settings
echo "=== Searching for pnpm config related comments ==="
rg -i "shamefully-hoist|auto-install-peers|strict-peer-dependencies|public-hoist" --type-list | head -20

Repository: solid-connection/solid-connect-web

Length of output: 535


🏁 Script executed:

# Check for any build configuration files
echo "=== Checking for build/config files ==="
fd -e "next.config" -e "tsconfig" -e "babel.config" -e ".npmrc" -e "pnpm-workspace"

Repository: solid-connection/solid-connect-web

Length of output: 117


🏁 Script executed:

# Check for pnpm-related files and search for any configuration comments
echo "=== Checking for pnpm workspace or related configs ==="
find . -maxdepth 2 -type f \( -name "pnpm-workspace.yaml" -o -name ".pnpmfile.cjs" -o -name "pnpm-lock.yaml" \) 2>/dev/null | head -10

echo ""
echo "=== Searching for peer dependency or pnpm-related issues in comments ==="
rg -i "peer.*depend|shamefully|hoist|pnpm.*config" --type ts --type tsx --type js --type json -B 1 -A 1 2>/dev/null | head -30

Repository: solid-connection/solid-connect-web

Length of output: 223


🏁 Script executed:

# Check if there are any build errors or warnings documented
echo "=== Looking for any related documentation or issues ==="
find . -maxdepth 2 -type f \( -name "README.md" -o -name "CONTRIBUTING.md" -o -name ".github" \) 2>/dev/null | head -10

# Search in README if it exists
if [ -f README.md ]; then
  echo ""
  echo "=== Checking README for pnpm/Next.js setup info ==="
  rg -i "pnpm|install|setup|next" README.md -A 2 | head -40
fi

Repository: solid-connection/solid-connect-web

Length of output: 606


🌐 Web query:

Next.js pnpm shamefully-hoist configuration best practices

💡 Result:

Short answer: avoid shamefully-hoist=true for Next.js workspaces unless you must — prefer targeted hoisting (publicHoistPattern / hoistPattern) or fixing dependency declarations. Use shamefully-hoist only as a last-resort compatibility fallback.

Why:

  • shamefully-hoist flattens/hoists everything to root node_modules (makes phantom deps globally available) which hides missing/incorrect dependency declarations and can cause subtle runtime/build differences and native-module resolution problems in Next.js. (pnpm.io)

Best practices

  1. Prefer correctness over global hoisting

    • Ensure each package declares the deps/devDeps it actually uses (fix phantom/missing deps). This avoids needing global hoisting. (pnpm.io)
  2. Use targeted hoisting instead of shamefully-hoist

    • publicHoistPattern (or public-hoist-pattern in .npmrc) exposes only matching packages at the root; hoistPattern controls what goes into the virtual store. Use patterns for specific tooling (e.g., eslint, babel, legacy plugins) rather than * for everything. Example: publicHoistPattern[]=plugin or hoistPattern[]=eslint. (pnpm.io)
  3. Only enable shamefully-hoist as last resort

    • If a third‑party tool absolutely requires classic flattened node_modules and you cannot fix it, set shamefully-hoist=true temporarily and document why. Prefer limited publicHoistPattern over a global shameful hoist. (pnpm.io)
  4. Common Next.js-specific gotchas and fixes

    • Native modules / compiled artifacts inside workspace packages: Next’s resolver/build may not find .node/.native builds if not hoisted; instead either (a) export/build artifacts into package’s published dist and require from that path, (b) add a narrow publicHoistPattern for that native package, or (c) fix import paths/packaging. See Next.js issues where native modules in pnpm workspaces failed to load unless hoisted. (github.com)
    • SWC/webpack/loaders and plugin tooling that assume root node_modules: prefer publicHoistPattern for those specific plugins (e.g., babel, eslint, webpack plugins) rather than global hoist. (pnpm.io)
  5. Recommended minimal config examples

    • .npmrc (root) — targeted public hoist:
      • public-hoist-pattern[]=eslint
      • public-hoist-pattern[]=babel-
        (avoid shamefully-hoist=true)
        (pnpm.io)
    • pnpm-workspace.yaml — hoistPattern example:
      • hoistPattern:
  6. Debugging checklist before enabling shamefully-hoist

    • pnpm why to see where a package is installed.
    • Confirm each package.json lists required deps.
    • Try hoistPattern/publicHoistPattern for the offending package.
    • Reproduce build locally after each change; if unresolved, enable shamefully-hoist temporarily and open an issue with the tool/maintainer. (newreleases.io)
  7. Operational notes

    • Pin pnpm versions across CI/dev machines because hoisting behavior and defaults have changed across pnpm releases. Test CI builds after any hoist config change. (newreleases.io)

If you want, I can:

  • review your repo’s pnpm/Next.js layout and suggest a minimal hoistPattern/publicHoistPattern, or
  • produce the exact .npmrc / pnpm-workspace.yaml snippets tailored to your packages.

Citations:


pnpm 설정의 엄격함을 약화시키는 옵션들을 검토하고 개선해주세요.

현재 .npmrc의 설정들이 pnpm의 핵심 강점인 의존성 격리를 완화하고 있습니다. 다음 단계를 통해 더 나은 구성으로 개선할 수 있습니다:

  1. 현재 설정의 영향 파악하기

    • shamefully-hoist=true: 모든 패키지를 root node_modules에 호이스팅하여 누락된 의존성 선언을 숨길 수 있음
    • auto-install-peers=truestrict-peer-dependencies=false: pnpm의 엄격한 의존성 검사를 우회
  2. 설정 없이 프로젝트가 정상 작동하는지 테스트

    • .npmrc에서 shamefully-hoist=true 주석 처리
    • node_modules 제거 후 pnpm install 실행
    • pnpm run buildpnpm run dev 실행하여 에러 확인
  3. 특정 패키지만 호이스팅 필요한 경우 대안 사용

    • 특정 도구나 플러그인(예: eslint, babel)만 호이스팅이 필요하다면, 전역 shamefully-hoist 대신 public-hoist-pattern을 사용하는 것이 권장됨
    • 예시: public-hoist-pattern[]=*eslint* 또는 public-hoist-pattern[]=*babel-*
  4. 의존성 누락 확인

    • pnpm why <패키지명> 명령으로 각 패키지의 설치 위치 확인
    • 필요한 경우 package.json의 의존성 선언을 정정
🤖 Prompt for AI Agents
In @.npmrc around lines 1 - 4, The .npmrc currently weakens pnpm isolation via
shamefully-hoist=true, auto-install-peers=true, and
strict-peer-dependencies=false; remove or comment out those three lines, run rm
-rf node_modules && pnpm install then validate with pnpm run build and pnpm run
dev, and if a specific tool truly needs hoisting replace shamefully-hoist with
targeted public-hoist-pattern entries (e.g., public-hoist-pattern[]=*eslint* or
public-hoist-pattern[]=*babel-*) and fix any missing declarations discovered via
pnpm why <package> by adding them to package.json.


# 기본 설정
registry=https://registry.npmjs.org/
enable-pre-post-scripts=true
lockfile=true
41 changes: 39 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,47 @@
- Prettier
- Vercel

## Prerequisites

- Node.js 22.x
- pnpm 9.x or later

## Installation

This project uses pnpm as the package manager.

```bash
# Install pnpm globally
npm install -g pnpm

# Install dependencies
pnpm install
```

## Commands

```bash
npm run dev
# Development server
pnpm run dev

npm run lint
# Build for production
pnpm run build

# Linting
pnpm run lint

# Type checking
pnpm run typecheck

# Format code
pnpm run format
```

## Migration from npm

If you have an existing clone:

```bash
rm -rf node_modules package-lock.json
pnpm install
```
Loading