npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@god-beom/fsot-vite

v0.1.2

Published

Overlay collaboration tool for React frontends — per-page kanban & real-time chat

Readme

fsot - Frontend Source Overlay Tool


fwagger — 화면 데이터 명세 (VM Swagger)

프론트엔드 라우트별로 사용하는 데이터 타입과 훅을 자동으로 수집해서 Swagger처럼 보여주는 기능입니다.

🚀 빠른 시작

라우트에 매핑된 컴포넌트 옆에 *.VM.ts 파일을 만들면 끝입니다.

src/pages/cost/
  CostDashboardPage.tsx       ← 라우터에 등록된 컴포넌트
  CostDashboardPage.VM.ts     ← 이 파일만 만들면 fsot가 알아서 수집
# 스펙 생성
cd apps/your-app
npx fsot swagger
# → fsot.swagger.json 생성됨

개발 서버를 켜면 오버레이에서 실시간으로 확인할 수 있습니다.


VM 파일 작성 규칙

서버와 주고받는 데이터 타입과 React Query 훅만 작성합니다. UI 전용 타입(탭 구조, 정렬 상태 등)은 포함하지 않습니다.

// CostDashboardPage.VM.ts

import { useQuery } from '@tanstack/react-query';
import { fetchMonthlyCost, type MonthlyCostResponse } from '../../api/costApi';

// ─── Types ───────────────────────────────────
export interface CloudCostVM {
  cloud: 'aws' | 'azure' | 'gcp';
  amount: number;
  currency: string;
}

export interface MonthlyCostVM {
  periodLabel: string;
  total: number;
  clouds: CloudCostVM[];
}

// ─── Mapper ──────────────────────────────────
function toMonthlyCostVM(dto: MonthlyCostResponse): MonthlyCostVM {
  return dto;
}

// ─── Hook ────────────────────────────────────
export function useMonthlyCost() {
  return useQuery({
    queryKey: ['cost', 'monthly'],
    queryFn: fetchMonthlyCost,
    select: toMonthlyCostVM,
  });
}

파일명 태그 자동 추론:

| 파일명 패턴 | 태그 | |-------------|------| | *Page.VM.ts | PAGE | | *Tab.VM.ts | TAB | | *Modal.VM.ts | MODAL | | 그 외 | COMPONENT |


fsot가 VM을 수집하는 방법

1단계 — 라우터 파일 파싱

vite.config.ts에 지정한 라우터 파일(src/routes/index.tsx)을 읽어서 경로-컴포넌트 매핑을 추출합니다.

// 이런 라우터 정의에서
{ path: '/cost/dashboard', element: <CostDashboardPage /> }

// 이 매핑을 만듭니다
'/cost/dashboard' → CostDashboardPage.tsx

2단계 — import 트리 재귀 추적

각 페이지 컴포넌트에서 시작해 import된 파일들을 따라가며 *.VM.ts 파일을 찾습니다.

CostDashboardPage.tsx
  └─ import CostSummaryCard        → CostSummaryCard.VM.ts ✅ 수집
  └─ import BudgetSettingsModal    → BudgetSettingsModal.VM.ts ✅ 수집
  └─ import SomeChart              → VM 없음 → skip

단, 다른 라우트 컴포넌트를 만나면 탐색을 멈춥니다. 탭 레이아웃처럼 자식 라우트 컴포넌트를 import하는 경우 VM이 중복 수집되는 것을 방지합니다.

3단계 — VM 파일 AST 파싱

수집된 *.VM.ts 파일에서 interfaceexport function useXxx() 를 파싱해 스펙을 생성합니다.

4단계 — LayoutPage 자동 제외

자식 라우트가 있는 LayoutPage는 항상 첫 번째 탭으로 리다이렉트되므로 manifest에서 자동으로 제외됩니다.

/asset/scheduler          ← LayoutPage → 자동 제외
/asset/scheduler/schedule ← TabPage   → 수집 ✅
/asset/scheduler/history  ← TabPage   → 수집 ✅

따라서 LayoutPage에는 VM 파일이 필요 없습니다. 탭 전환 로직은 LayoutPage 컴포넌트 안에 직접 작성합니다.


탭 구조 권장 패턴

asset/scheduler/
  SchedulerLayoutPage.tsx          ← 탭 UI + 전환 로직 (VM 없음)
  SchedulePageTab.tsx              ← 라우트: /asset/scheduler/schedule
  SchedulePageTab.VM.ts            ← Types + Mapper + Hook ✅
  ScheduleHistoryPageTab.tsx       ← 라우트: /asset/scheduler/history
  ScheduleHistoryPageTab.VM.ts     ← Types + Mapper + Hook ✅

한 파일에 모두: TabPage.VM.ts = Types + Mapper + Hook (완결)


vite.config.ts 설정

import { fsot } from '@prime/fsot/vite';

export default defineConfig({
  plugins: [
    fsot({
      projectId: 'my-project',
      serverUrl: 'https://...',
      vm: {
        router: 'react-router',
        routerFile: 'src/routes/index.tsx',
        include: 'src/**/*.VM.ts',
      },
    }),
  ],
});

인증 구조

Supabase Auth를 사용하지 않고, fsot_users 테이블 + bcrypt + JWT로 직접 인증합니다.

클라이언트 → POST /api/auth/setup, /api/auth/login → 서버(bcrypt 검증) → JWT 반환
클라이언트 → Authorization: Bearer <JWT> → 서버(JWT 검증 + fsot_users 조회)
  • 비밀번호 해싱: 서버에서만 (bcrypt)
  • 세션: JWT (localStorage fsot_token), 유효기간 7일
  • DB: fsot_users 테이블 (RLS OFF)
  • Supabase Auth 완전 미사용 → bit/hito와 충돌 없음

서버 API

| 엔드포인트 | 설명 | |---|---| | GET /api/auth/setup-status | 초기 설정 여부 확인 | | POST /api/auth/setup | 관리자 계정 생성 (첫 사용 시) | | POST /api/auth/login | 로그인 → JWT 반환 | | GET /api/auth/me | 현재 사용자 정보 (JWT 필요) | | GET /api/admin/users | 사용자 목록 (admin+) | | POST /api/admin/users | 사용자 생성 (admin+) | | PUT /api/admin/users | 사용자 수정 (admin+) | | DELETE /api/admin/users | 사용자 삭제 (admin+) |

역할 (role)

| role | 설명 | |---|---| | god | 최고 관리자, 프로젝트 간 로그인 가능 | | hostAdmin | 호스트앱 관리자 | | admin | 일반 관리자 | | user | 일반 사용자 |

보안 TODO (미해결)

fsot 전용 테이블 RLS OFF 상태 — 보안 취약

현재 아래 테이블들의 RLS가 OFF되어 있습니다:

  • kanban_cards
  • kanban_columns
  • chat_messages
  • page_completions

원인: Supabase Auth 제거 후 기존 RLS 정책(auth.uid() 기반)이 동작하지 않아 임시로 RLS를 비활성화.

위험: 클라이언트(useKanban.ts, useChat.ts)가 Supabase anon key로 직접 DB에 접근하고 있어, anon key를 아는 누구나 데이터를 조작할 수 있음.

해결 방법: 클라이언트의 Supabase 직접 접근을 제거하고, 모든 CRUD를 fsot 서버 API를 경유하도록 변경.

현재 (위험): 클라이언트 → (anon key) → Supabase (RLS OFF)
목표 (안전): 클라이언트 → (JWT) → fsot 서버 → (service_role) → Supabase

수정 대상 파일:

  • src/hooks/useKanban.ts — 칸반 CRUD
  • src/hooks/useChat.ts — 채팅 메시지 CRUD
  • src/overlay/KanbanPanel.tsx — page_completions 직접 접근
  • 서버에 대응하는 API 라우트 추가 필요

실행

# 서버 (포트 4000)
cd apps/fsot/server && npx tsx src/index.ts

# 환경변수: server/.env
SUPABASE_URL=https://kgejfsxantavmzwdukmq.supabase.co
SUPABASE_SECRET_KEY=<service_role_key>
JWT_SECRET=<optional, 기본값 있음>
PORT=4000

Supabase 프로젝트

sotfront (kgejfsxantavmzwdukmq) — bit, hito와 공유. fsot 전용 테이블만 사용.