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

@cmarket/embed

v0.5.0

Published

CMARKET 파트너 임베드(iframe) SDK — launch code postMessage 핸드셰이크를 origin 고정으로 캡슐화

Readme

@cmarket/embed

CMARKET 파트너 임베드(iframe) SDK — 발주기관 ERP 페이지 안에 cmarket 화면(공고 등록 등)을 재로그인 없이 띄웁니다. iframe 생성과 launch code postMessage 핸드셰이크의 보안 로직 (origin 고정, code 를 URL 밖으로)을 SDK 가 대신 강제합니다.

  • 런타임 의존성 0 (zero dependencies)
  • npm(ESM/CJS) + CDN(UMD 전역 CMarketEmbed) 동시 제공

통합 개요 — 두 레이어

| 레이어 | 누가 | 도구 | | --------------------- | --------------------------------------------------- | ----------------------------------- | | ① launch code 발급 | ERP 백엔드 (client_secret 필요 — 브라우저 금지) | Partner API POST /v2/embed/launch | | ② iframe + 핸드셰이크 | ERP 프론트 | 이 SDK 의 mount() |

launch code 는 일회성·60초 TTL 입니다. 페이지 진입(또는 세션 만료) 시마다 ERP 백엔드에서 새로 발급해 프론트에 내려주세요. code 를 URL 쿼리/해시에 싣지 마세요 — SDK 도 postMessage 로만 전달합니다.

① ERP 백엔드 — launch code 발급

OAuth2 client_credentials 토큰(scope embed:launch)으로 호출합니다:

# 1. 토큰 발급 (scope 에 embed:launch 포함) — token endpoint 는 버전 프리픽스 없음(/oauth/token), JSON body
curl -X POST https://partner-api.c-market.net/oauth/token \
  -H "Content-Type: application/json" \
  -d "{\"grant_type\":\"client_credentials\",\"client_id\":\"$CMARKET_CLIENT_ID\",\"client_secret\":\"$CMARKET_CLIENT_SECRET\",\"scope\":\"embed:launch\"}"

# 2. launch code 발급 (memberId = cmarket 계정, screen = 임베드 화면 키)
curl -X POST https://partner-api.c-market.net/v2/embed/launch \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"memberId": "M123456", "screen": "bid-register"}'
# → { "launchCode": "...", "expiresIn": 60 }

발급된 launchCode 를 ERP 프론트로 내려주세요 (페이지 렌더 응답에 포함하거나 별도 XHR).

② ERP 프론트 — mount

npm

npm install @cmarket/embed
import { mount } from '@cmarket/embed';

const controller = mount('#cmarket-slot', {
  launchCode, // ERP 백엔드가 발급한 일회성 code
  screen: 'bid-register',
  onSuccess: ({ bidId }) => console.log('공고 등록 완료:', bidId),
  onCancel: () => console.log('사용자 취소'),
  onSessionExpired: async () => {
    controller.destroy();
    const fresh = await fetchNewLaunchCodeFromMyBackend(); // ①을 다시 호출
    mount('#cmarket-slot', { launchCode: fresh, screen: 'bid-register' });
  },
  onError: (err) => console.error('임베드 실패:', err.code, err.message),
});

CDN (script tag)

버전 핀 규율: 반드시 아래처럼 버전을 핀하세요. latest/무핀 URL 은 사용 금지 — 예고 없는 major 변경이 라이브 페이지를 깨뜨릴 수 있습니다. 1.0.0 GA 이후에는 major-pin(@1)을 권장합니다 (비파괴 개선 자동 수신): https://cdn.jsdelivr.net/npm/@cmarket/embed@1/dist/embed.umd.js 0.x 파일럿 기간에는 정확 버전 핀을 사용하세요:

<div id="cmarket-slot" style="width: 100%; height: 720px"></div>
<script src="https://cdn.jsdelivr.net/npm/@cmarket/[email protected]/dist/embed.umd.js"></script>
<script>
  var controller = CMarketEmbed.mount('#cmarket-slot', {
    launchCode: window.__CMARKET_LAUNCH_CODE__, // 서버 렌더 시 주입
    screen: 'bid-register',
    onSuccess: function (e) {
      console.log('공고 등록 완료:', e.bidId);
    },
    onCancel: function () {
      console.log('사용자 취소');
    },
    onError: function (err) {
      console.error(err.code, err.message);
    },
  });
</script>

API

CMarketEmbed.mount(container, options) => { destroy() }

| 옵션 | 타입 | 기본값 | 설명 | | ------------------ | ---------------------------------- | ---------------------- | ------------------------------------------- | | launchCode | string | (필수) | 일회성 launch code (60s TTL) | | screen | 'bid-register' | (필수) | 임베드 화면 키 (화이트리스트 검증) | | baseUrl | string | https://c-market.net | cmarket 프론트 origin (staging 은 명시) | | prefill | EmbedBidPrefillV1 | — | 폼 기본값 (비권위 — 제출 검증은 cmarket 측) | | onSuccess | (e: {screen, bidId}) => void | — | 등록 완료 | | onCancel | () => void | — | 사용자 취소 | | onSessionExpired | () => void | — | 세션(30분) 만료 — 새 code 로 재-mount | | onError | (err: CMarketEmbedError) => void | — | 비동기 실패 (err.code: 'READY_TIMEOUT') | | timeoutMs | number | 10000 | iframe ready 대기 한도 |

  • 잘못된 통합(미존재 container, 화이트리스트 외 screen, 빈 launchCode, 불량 baseUrl)은 mount()동기 throw 합니다 — 개발 중에 즉시 드러납니다.
  • destroy() 는 멱등이며 리스너·타임아웃·iframe 을 정리합니다.

보안 설계 (SDK 가 강제하는 것)

  • launch code 는 iframe URL 에 절대 실리지 않고 postMessage 로만 전달됩니다 (브라우저 히스토리/Referer/서버 로그 유출 차단).
  • 모든 발신 postMessage 의 targetOrigin 은 cmarket origin 으로 고정됩니다 ('*' 없음).
  • 수신 메시지는 event.origin(cmarket origin) + event.source(우리 iframe) 2중 검증.
  • iframe sandbox: allow-scripts allow-same-origin allow-forms allow-downloads 만 부여 (allow-downloads 는 assistant 화면의 리포트 엑셀 export 용 — 없으면 브라우저가 조용히 차단한다) — top-navigation/popup/download 불가.

버전 정책

SemVer. CDN 산출물이 파트너 라이브 페이지에서 로드되므로 breaking change 는 반드시 major 로만 나갑니다. 문서/통합 코드에는 항상 핀된 URL 만 사용하세요.