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

@ciromaciel/extension-publisher

v0.2.1

Published

Publishes a browser extension to the Chrome Web Store and Microsoft Edge Add-ons, and a VS Code extension to the VS Code Marketplace and Open VSX, from the terminal or CI: credentials, package, upload, publish, status.

Readme

@ciromaciel/extension-publisher

Publica uma extensão de navegador na Chrome Web Store e no Microsoft Edge Add-ons, e uma extensão de VS Code no VS Code Marketplace e no Open VSX, pelo terminal ou no CI: salva as credenciais, empacota, envia, publica e acompanha o status.

bun add -g @ciromaciel/extension-publisher    # o comando extension-publish fica no PATH

O caminho, do zero

1. A primeira publicação é pelo painel de cada loja. Nenhuma das duas APIs cria o item nem mexe na ficha (textos, imagens, formulário de privacidade). Publique a primeira versão à mão, com o zip de extension-publish package, e anote os IDs:

| Loja | ID | Onde está | |---|---|---| | Chrome | publisherId | no endereço do painel: chrome.google.com/webstore/devconsole/<publisherId> | | Chrome | itemId | o ID da extensão, na página dela no painel | | Edge | productId | Partner Center → a extensão → "Extension identity" |

Os IDs vão no extension-publish.json da extensão. Eles não são segredo, porque aparecem nas URLs públicas das lojas, então o arquivo entra no git:

{
    "name": "history-extension",
    "build": "bun run build",
    "dist": "dist",
    "release": "release",
    "forbidden": ["localhost", "127.0.0.1"],
    "chrome": { "publisherId": "…", "itemId": "…" },
    "edge": { "productId": "…" }
}

2. As credenciais, uma vez por máquina. Cada comando abre as páginas certas no navegador e guia o resto:

extension-publish credentials google       # conta de serviço do Google (Chrome Web Store API V2)
extension-publish credentials microsoft    # Client ID e API key do Partner Center (Publish API v1.1)
extension-publish credentials              # o que está salvo, sem mostrar os segredos

Elas ficam em ~/.ciromacielos/extension-publisher/credentials.json, que só o seu usuário lê (0600), e nunca num repositório. A chave do Google é testada com o Google antes de ser salva. A API key da Microsoft não aparece enquanto você digita e vence: o Partner Center mostra a data, e o comando a guarda para lembrar você.

3. Publicar uma versão: suba o version da extensão e, na pasta dela, rode:

extension-publish publish --dry-run            # o pacote e o que impediria o envio, sem falar com as lojas
extension-publish publish                      # as duas lojas
extension-publish publish chrome --percent 10  # Chrome para 10% dos usuários primeiro
extension-publish publish edge --notes "Corrige a busca"

O comando faz, nesta ordem:

  1. o build de produção;
  2. as verificações;
  3. o zip em release/;
  4. em cada loja, o envio, a espera até a loja aceitar o pacote e a publicação.

Uma loja que falhe não impede a outra, e o comando termina com erro dizendo em qual falhou.

4. Acompanhar:

extension-publish status          # as duas
extension-publish status chrome   # em revisão · publicada · recusada · versão · % dos usuários

O Edge só acompanha operações, não a extensão, então o status mostra os últimos envios feitos por esta máquina (~/.ciromacielos/extension-publisher/state.json).

Extensões de VS Code

Uma extensão de VS Code não precisa de IDs: o publisher e o name do package.json já dizem quem ela é nas duas lojas. O extension-publish.json só marca o tipo e, se houver, o que roda antes do vsce package (que já roda o vscode:prepublish da extensão):

{
    "kind": "vscode",
    "build": "bun run --cwd ../../packages/shared build"
}

Para o CI, um comando só configura tudo: abre cada página no lugar certo, confere cada valor com a loja e grava os secrets direto no repositório do GitHub (OVSX_PAT, AZURE_CLIENT_ID, AZURE_TENANT_ID), sem mostrar nenhum:

brew install gh azure-cli                   # se faltar
extension-publish setup vscode              # da raiz do repositório das extensões
extension-publish setup vscode --only openvsx

O Marketplace publica pelo Microsoft Entra ID, não por token: o Azure DevOps parou de emitir os tokens globais que ele aceitava em março de 2026, e os que restam vencem em 01/12/2026. Quem publica é uma managed identity numa assinatura do Azure (a gratuita serve; a identidade não tem custo). Um app registration entra no Azure, mas o Marketplace recusa. E uma conta Microsoft pessoal não entra no Azure CLI pelo login comum, só pelo diretório dela — por isso o setup pede o ID do locatário e entra com código.

O setup cria o grupo e a identidade, deixa a branch main do repositório entrar como ela (OIDC, sem segredo guardado), grava os secrets e roda o workflow uma vez para ler o ID da identidade no Azure DevOps (só ela consegue). O ID vai para a área de transferência, e a tela de membros do publisher abre para você colar. No CI, VSCE_AZURE_CREDENTIAL=1 faz o vsce publicar como ela.

Na sua máquina, também dá para usar tokens:

extension-publish credentials marketplace   # token do Azure DevOps (Marketplace → Manage)
extension-publish credentials openvsx       # token do Open VSX (assine antes o Publisher Agreement)

extension-publish status                    # a versão do package.json e a de cada loja
extension-publish publish --dry-run         # o .vsix e o que impediria o envio
extension-publish publish                   # as duas lojas
extension-publish publish openvsx           # só uma

O publish pergunta a cada loja qual versão ela tem e só envia para a que não tem a do package.json. Sem subir a versão, ele não faz nada e termina bem, e por isso pode rodar em todo push: é assim que o CI publica. Uma loja que falhou é tentada de novo no próximo push, e só ela.

O .vsix é feito e enviado pelas ferramentas das próprias lojas (vsce e ovsx, via bunx), que acompanham as regras e a autenticação de cada uma. O mesmo arquivo vai para as duas. Os tokens chegam a elas por variável de ambiente, nunca na linha de comando. No Open VSX, o namespace (o publisher) é criado na primeira publicação.

Antes de publicar, confere:

  • o package.json tem publisher, name, engines.vscode e uma versão x.y.z;
  • o main (e o browser, se houver) está dentro do .vsix.

CI: as credenciais num comando só

setup cria o que dá para criar, confere cada credencial com a loja e grava os secrets direto no repositório do GitHub (via gh, pela entrada padrão, sem mostrar nenhum). Rode da pasta da extensão; sem nome de loja, ele faz as do extension-publish.json dali. Pode rodar de novo: o que existe é reaproveitado.

brew install gh                               # sempre
brew install --cask google-cloud-sdk          # para o Chrome
brew install azure-cli                        # para o VS Code Marketplace

extension-publish setup            # as lojas da extensão daqui
extension-publish setup chrome     # → CHROME_SERVICE_ACCOUNT
extension-publish setup edge       # → EDGE_CLIENT_ID, EDGE_API_KEY
extension-publish setup vscode     # → OVSX_PAT, AZURE_CLIENT_ID, AZURE_TENANT_ID

| Loja | O que o setup faz sozinho | O que fica com você | |---|---|---| | Chrome | projeto no Google Cloud, API ligada, conta de serviço, chave testada com o Google | colar o e-mail da conta (já copiado) em Conta, no painel | | Edge | testa o Client ID e a API key contra a extensão | criar as credenciais na página da Publish API, que ele abre | | Open VSX | confere o token, cria o namespace | assinar o acordo da Eclipse e gerar o token | | Marketplace | grupo e managed identity, entrada da main por OIDC, o ID da identidade (já copiado) | ter uma assinatura do Azure (gratuita); colar o ID em Members, no publisher |

Com as credenciais no CI, publish pula a loja que já tem a versão: no Chrome, publicada ou em revisão; no VS Code, publicada. O Edge não tem como perguntar a versão pela API, então, sem subir a versão, o envio para ele falha.

O que é verificado antes de enviar

Um pacote com algum destes problemas nunca sai daqui:

  • Manifesto: não há manifest.json na raiz, o manifesto não é Manifest V3, ou a versão é inválida.
  • Endereços: aparece qualquer palavra da lista forbidden, por padrão localhost e 127.0.0.1. Isso pega um build que falaria com a máquina de quem desenvolve.
  • eval ou new Function: código gerado em tempo de execução, que a revisão das lojas recusa.
  • Mapas de código (.map).

Em CI

As variáveis de ambiente valem mais que o arquivo de credenciais:

| Variável | O quê | |---|---| | CHROME_SERVICE_ACCOUNT | o JSON da chave da conta de serviço, como texto | | EDGE_CLIENT_ID | Client ID do Partner Center | | EDGE_API_KEY | API key do Partner Center | | VSCE_PAT | token do Azure DevOps para o VS Code Marketplace | | OVSX_PAT | token do Open VSX |

Testes

bun test tests/

Os testes simulam as quatro lojas e as ferramentas vsce e ovsx, e cobrem:

  • os endereços e cabeçalhos de cada API;
  • a assinatura da conta de serviço, conferida com a chave pública;
  • a espera até cada envio terminar;
  • as verificações do pacote;
  • as credenciais com permissão 0600 e sem o segredo no terminal;
  • no VS Code, pular a loja que já tem a versão, e o token só no ambiente.