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

@gaonjs/adapter-mongo

v0.5.6

Published

Gaon 선택형 문서형(MongoDB) 어댑터 — collection()·mongoSchema() (Mongoose 기반 · SQL model() 과 나란한 문서형 축). mongoose 는 optional peer 로 opt-in.

Readme

@gaonjs/adapter-mongo

Gaon 선택형 문서형(MongoDB) 어댑터 — SQL model()(Kysely) 옆에 문서형 동사 collection() 을 Mongoose 위에 둔다 (v1.1 · 결정 278~282).

로그·이벤트·감사·분석 이벤트처럼 문서·유연 스키마·대량 append 용도에 쓴다. 운영 데이터(관계형·트랜잭션)는 그대로 SQL model() 을 쓴다.

설치 (opt-in)

문서형은 선택 기능이라 SQL 전용 프로젝트는 mongoose 를 받지 않는다(optional peer). 켜려면 mongoose 하나만 받으면 된다:

npm i mongoose

@gaonjs/adapter-mongo 자체는 gaonjs·@gaonjs/config 의 정규 dependency 라 이미 설치돼 있다 — 따로 받지 않는다(결정 422 · createDb 의 수리 안내와 같은 문구).

사용

import { collection, mongoSchema } from 'gaonjs/data'   // 파사드 재수출
import type { Model } from 'mongoose'

// 정본 패턴(결정 288·332): Doc + Methods + Model 인터페이스 3-제네릭 —
// AuditLog.recent(50)·doc.summary() 가 캐스트 없이 컴파일된다.
interface AuditDoc {
  actorId: string
  action: string
  ip?: string
  createdAt?: Date
  updatedAt?: Date
}
interface AuditMethods {
  summary(): string
}
interface AuditModel extends Model<AuditDoc, {}, AuditMethods> {
  recent(limit: number): Promise<AuditDoc[]>
}

const auditLogSchema = mongoSchema<AuditDoc, AuditModel, AuditMethods>({
  actorId: { type: String, required: true, index: true },
  action:  { type: String, required: true },
  ip:      { type: String, hidden: true },   // 직렬화 경계에서 제외 (SQL .hidden() 과 동일 의미)
}, {
  timestamps: true,
  statics: {
    async recent(limit: number) {
      return (await this.find().sort({ createdAt: -1 }).limit(limit).lean()) as AuditDoc[]
    },
  },
  methods: {
    summary() { return `${this.actorId}:${this.action}` },
  },
})

// db: 'logs' — 몽고 커넥션 바인딩 (SQL 의 { db: 'legacy' } 와 대칭)
export const AuditLog = collection('audit_logs', auditLogSchema, { db: 'logs' })
gaon.config.ts:
export default defineConfig({
  db: {
    main: { adapter: 'postgres', url: env('DATABASE_URL') },
    logs: { adapter: 'mongodb', url: env('MONGO_URL') },   // 문서형 커넥션
  },
})

v1 스코프

  • ✅ 순수 CRUD + Mongoose 미들웨어(pre/post) 통과, statics/methods(순수 Mongoose)
  • { db } 커넥션 바인딩 · per-connection 격리(전역 mongoose.model() 금지)
  • hidden 필드 직렬화 비노출(SQL 과 동일 — 서버는 읽고 직렬화만 제외 · .lean()/create() 반환/toObject() 전부 방어 · 결정 289 · 중첩 dot-path 지원 (profile.ssn·서브도큐먼트 배열 요소 필드 · 결정 336 — 지원 밖 위치는 fail-loud))
  • ✅ statics/methods 타입 통로 — Doc+Methods+Model 인터페이스 3-제네릭 정본(결정 332 · 캐스트 0)
  • ✅ ObjectId(_id 포함) → string 정규화(응답 경계)
  • ✅ 인덱스 = Mongoose 스키마 선언 — dev·test 는 autoIndex 기본값이 첫 사용 시 보장 · 운영(NODE_ENV=production)은 autoIndex 기본 false(결정 333) — 배포 절차에서 syncMongoIndexes() 로 명시 동기화(커넥션 설정 autoIndex 명시가 우선)
  • ❌ 몽고 마이그레이션 없음(gaon db 순회는 mongodb 를 건너뛰고 skipped 보고 · 결정 292) · 몽고 트랜잭션 없음 · change stream 없음

⚠️ adapter: 'mongodb' 커넥션에는 url(경로에 DB 명 포함) 또는 database필수다 — 둘 다 없으면 부팅이 수리 안내로 throw 한다(결정 335 · 드라이버 기본 test DB 무신호 접속 봉합).

⚠️ 같은 커넥션·같은 컬렉션명에 다른 스키마를 선언하면 첫 접근에서 throw 한다(결정 334) — 같은 컬렉션이면 mongoSchema 산출 하나를 export 해 재사용하라.

크로스커넥션 안전

몽고는 v1 에서 트랜잭션이 없다. SQL service() 트랜잭션 안에서 몽고에 쓰면 MongoCrossConnectionWriteError막힌다(조용한 부분 커밋 방지 · 결정 281·331). "커밋 후 로그" 는 afterCommit 으로:

service(async () => {
  const user = await Users.create(input)          // SQL tx
  afterCommit(() => AuditLog.create({ actorId: String(user.id), action: 'signup' }))  // 커밋 뒤 몽고 쓰기
})

⚠️ aggregate 결과는 임의 projection 이라 hidden 마커를 심지 않는다(raw 탈출구). 문서를 렌더에 흘릴 땐 .lean() 을 권장한다(정본 경로 · 경량).

⚠️ 가드는 allowlist 반전이다(결정 331) — SQL tx 안에서는 읽기 전용 내장 (find/findOne/countDocuments/aggregate 읽기 등)만 통과하고, 그 밖의 static 호출 (쓰기·커스텀 static·미지의 신규 메서드)은 fail-closed 로 막힌다. Query 체이닝 쓰기 (find(f).updateMany(u) 등)와 aggregate$out/$merge 도 실행 지점 pre 훅이 막는다. 유일한 예외 = 인스턴스 doc.save()(정본 예외 · 미가드).

자세한 설계는 docs/design/mongo-collection-adapter.mdagents/data.md 참조.