Catalog npm
PACKAGE EXPLORERView in registry

9am-build

npm

CfxLua test runner and build pipeline for FiveM (Cfx.re) resources

cfxcfxluafivemgta5luatest
Versions collected3
Direct dependencies10From release 1.2.1
Last observed20 Oct, 21:35 UTC

README

Current package documentation

9am-build

Automated build & deploy pipeline for FiveM (Cfx.re) resources. Push to GitHub, get your script on the Cfx.re Portal — with AI-powered changelogs posted to Discord and versioned GitHub releases.

git push  -->  webhook  -->  build zip  -->  upload to portal  -->  GitHub release  -->  changelog to Discord

Plus a CfxLua test runner you can use in any resource folder, with no clone and no setup:

cd path/to/your-resource
npx 9am-build test        # or: bunx 9am-build test

Quick Start

git clone <repo-url> 9am-build && cd 9am-build
bun install
bunx playwright install chromium   # one-time browser download
cp .env.example .env               # edit with your values
bun run register-passkey            # one-time passkey setup
bun run deploy my-resource          # build + upload to portal
bun run release my-resource         # build + GitHub release only (no portal)

Requirements

  • Bun v1.0+ — runs the app (CLI, webhook server, portal API calls)
  • Node.js v20.11+ — runs the Playwright browser step (Bun cannot drive Playwright's pipe transport, so passkey login/registration runs under Node via a small subprocess). Must be on PATH, or set NODE_BIN.
  • Git
  • Playwright Chromium — after bun install, run bunx playwright install chromium once (the Docker image does this automatically)

Setup

1. Install Dependencies

bun install

2. Configure Environment

cp .env.example .env

Edit .env with your values:

WEBHOOK_SECRET=your-webhook-secret
PORT=9000
DISCORD_CHANGELOG_WEBHOOK=https://discord.com/api/webhooks/...
ANTHROPIC_API_KEY=sk-ant-...
GITHUB_TOKEN=ghp_...

Generating a strong WEBHOOK_SECRET:

openssl rand -hex 32

Use the same value in both .env and the GitHub webhook secret field.

3. Register a Passkey (One-Time)

The Cfx.re Portal login is automated via a WebAuthn passkey. You register it once, then all future logins are automatic.

Note: This step requires a GUI browser, so do it on your local machine first. Transfer the credential file to your server afterwards.

  1. Run bun run register-passkey
  2. A Chromium window opens — log into the Cfx.re Forum if prompted
  3. It navigates to your security preferences automatically
  4. Click "Add Passkey", confirm access with your password when prompted, name it (e.g. 9am-build), and confirm
  5. Go back to the terminal and press Enter
  6. Credentials are saved to passkey-credential.json

Deploying to a remote server? Copy the credential file:

scp passkey-credential.json user@your-server:/path/to/9am-build/

Session cookies are saved to auth-state.json and reused automatically. No GUI needed after initial registration.

4. Add Your Repos

Edit repos.json to register your FiveM resources:

{
  "repos": [
    {
      "name": "my-resource",
      "githubUrl": "git@github.com:username/my-resource.git",
      "branch": "main"
    }
  ]
}
FieldDescription
nameResource name — used for CLI commands and webhook matching
githubUrlGit clone URL (SSH or HTTPS)
branchBranch to track (pushes to other branches are ignored)

5. Add upload-config.json to Each Resource

Each FiveM resource needs an upload-config.json in its root. This tells 9am-build how to package and where to upload.

{
  "name": "my-resource",
  "exclude": [
    "upload-config.json",
    ".gitignore",
    ".git/**",
    ".vscode/**"
  ],
  "frontend": {
    "dir": "web",
    "buildCommand": "bun run build",
    "buildOutput": "build"
  },
  "versions": {
    "escrow": {
      "assetId": 123456,
      "escrowIgnore": ["config.lua", "fxmanifest.lua"]
    }
  }
}
All upload-config.json fields
FieldRequiredDescription
nameYesResource name
excludeYesGlob patterns to exclude from all zips
frontendNoFrontend build settings
frontend.dirYes*Frontend directory (e.g. web)
frontend.buildCommandNoBuild command (default: bun run build)
frontend.buildOutputNoOutput directory (default: build). Use dist for Vue/Svelte
versionsYesAt least one version must be defined
versions.escrow.assetIdYes*Cfx.re Portal asset ID
versions.escrow.escrowIgnoreYes*Files to add to fxmanifest.lua escrow_ignore block
versions.open.assetIdYes*Cfx.re Portal asset ID

*Required if parent field is defined.

Escrow vs Open versions
  • Escrow — Source files excluded, only build output included. escrowIgnore patterns are injected into fxmanifest.lua.
  • Open — All files included. escrow_ignore { "**/*.*", "*" } is added automatically so nothing is encrypted.

You can define one or both versions. Each gets its own zip and asset upload.

Finding your Asset ID
  1. Go to the Cfx.re Portal
  2. Find your resource in the asset list
  3. The number in the ID column is your assetId

Commands

CommandDescription
npx 9am-build testRun *.test.lua in a resource folder — the only published command, needs no clone
bun run build <name>Build zip(s) only — no upload
bun run deploy <name>Build + upload to Cfx.re Portal + GitHub release
bun run release <name>Build + GitHub release only — never touches the portal or opens a browser
bun run serverStart webhook server for automated deployments
bun run register-passkeyOne-time passkey registration
bun src/index.ts debug <name> <commit>Test changelog generation for a commit

Webhook Mode (CI/CD)

Automate deployments on every push. The server receives GitHub webhooks, builds, uploads, and posts a changelog to Discord.

Setup

  1. Start the server:

    bun run server
    
  2. Create a webhook on GitHub (Settings > Webhooks > Add webhook):

    FieldValue
    Payload URLhttps://your-server:9000/webhook
    Content typeapplication/json
    SecretSame as WEBHOOK_SECRET in .env
    Events"Just the push event"

How It Works

  1. You push to a tracked branch
  2. GitHub sends a webhook to your server
  3. Server verifies the HMAC-SHA256 signature
  4. Matches the repo/branch against repos.json
  5. Enqueues the build (one at a time, latest push wins)
  6. Builds zip(s) and uploads to the Cfx.re Portal
  7. Generates a changelog via Claude API and posts it to Discord

Endpoints

MethodPathDescription
GET/healthHealth check — returns { status: "ok" }
POST/webhookGitHub push webhook receiver

Running with PM2

To keep the server running in the background with auto-restart:

npm install -g pm2
pm2 start bun --name 9am-build -- run server
pm2 save && pm2 startup
pm2 logs 9am-build      # view logs
pm2 restart 9am-build    # restart
pm2 stop 9am-build       # stop
pm2 delete 9am-build     # remove

GitHub Releases

After a successful portal upload, the pipeline creates a GitHub release on the resource's repo, tagged with the version from fxmanifest.lua (e.g. v1.0.3), with auto-generated release notes and the built zips attached as assets (<name>-escrow.zip, <name>-open.zip).

  1. Create a personal access token with repo scope (classic) or Contents: Read and write permission (fine-grained) for your resource repos

  2. Add it to .env:

    GITHUB_TOKEN=ghp_...
    
  • The release targets the exact commit that was built
  • If a release for the tag already exists, the zips are attached to it (existing assets with the same name are kept)
  • If GITHUB_TOKEN is not set, this step is skipped silently
  • Failures are non-fatal — the deploy still succeeds if the release fails

Discord Changelog

Automatically posts AI-generated changelogs to Discord after each deployment.

  1. Create a webhook: Channel Settings > Integrations > Webhooks > New Webhook

  2. Add the URL to .env:

    DISCORD_CHANGELOG_WEBHOOK=https://discord.com/api/webhooks/...
    
  • Changelogs are generated from commit diffs using OpenRouter (priority) or Anthropic (fallback)
  • Written as 1-5 bullet points from the end-user's perspective
  • Posted as a gold/yellow embed with the resource name
  • Model is configurable via OPENROUTER_MODEL (default: anthropic/claude-sonnet-4.6)
  • If DISCORD_CHANGELOG_WEBHOOK is not set, this step is skipped silently

Environment Variables

VariableRequiredDescription
WEBHOOK_SECRETServer modeGitHub webhook HMAC secret
PORTServer modeHTTP server port (default: 9000)
ANTHROPIC_API_KEYChangelog*Anthropic API key
OPENROUTER_API_KEYChangelog*OpenRouter API key (takes priority over Anthropic)
OPENROUTER_MODELNoOpenRouter model (default: anthropic/claude-sonnet-4.6)
DISCORD_CHANGELOG_WEBHOOKNoDiscord webhook URL
GITHUB_TOKENNoGitHub token for creating releases with build zips
CHROMIUM_NO_SANDBOXNoSet to 1 to disable the Chromium sandbox (needed only when running as root in a container; the Docker image sets it automatically). Leave unset locally.

*At least one API key required for changelog generation.

CfxLua Unit Tests

Run FiveM resource tests without a live FXServer — powered by the CfxLua CLI runtime (LuaGLM 5.4 + mocked natives, Citizen, events, exports).

# From a resource directory — no clone, no setup
npx 9am-build test          # or: bunx 9am-build test
npx 9am-build test --json   # machine-readable results
npx 9am-build test --strict # exit 1 when no specs exist

# From a clone of this repo
bun run test:lua ./path/to/my-resource
bunx 9am-build test my-resource          # repos.json name

The published CLI is compiled to plain ESM and runs on Node ≥ 20.11, so npx works on machines without Bun.

Writing tests

Spec files are discovered at tests/**/*.spec.lua, test/**/*.spec.lua, or any co-located *.test.lua next to the code it covers (web/ and node_modules/ are skipped). Override the patterns with 9am-test.json:

my-resource/
├── fxmanifest.lua
├── server/
│   └── main.lua
├── tests/
│   └── pricing.spec.lua
└── 9am-test.json          # optional

Example spec (tests/pricing.spec.lua):

local pricing = require('server.main')

describe('pricing.withTax', function()
  it('adds tax to the base price', function()
    expect(pricing.withTax(100, 0.2)).to.equal(120)
  end)
end)

describe('events', function()
  it('can spy on TriggerEvent', function()
    local spy = TestHelpers.spy()
    local restore = TestHelpers.mockGlobal('TriggerEvent', spy)
    TriggerEvent('shop:open', 1)
    restore()
    expect(spy:call_count()).to.equal(1)
  end)
end)

Test API

GlobalDescription
describe(name, fn)Group tests
it(name, fn)Define a test case
beforeEach(fn) / afterEach(fn)Per-test hooks
expect(value).to.equal(x)Equality assert
expect(value).to.deep_equal(x)Deep table compare
expect(fn).to.throw('msg')Error assert
TestHelpers.spy(fn?)Callable spy with .calls, :call_count()
TestHelpers.mockGlobal(name, value)Temporarily replace a global

require('server.pricing') resolves against the resource root through a custom searcher that loads the module under a resource-relative chunk name, so tracebacks read server/pricing.lua:4 rather than an absolute path that Lua truncates into uselessness.

Framework batteries (ox_lib / QBCore / QBox / ESX)

Working fakes for the framework layer load before any resource or spec file, so a resource written against ox_lib, QBCore, QBox (qbx_core) or ESX (es_extended) loads with zero configuration: lib.*, QBCore / exports['qb-core']:GetCoreObject(), exports.qbx_core, and exports['es_extended']:getSharedObject() all exist and are backed by one shared player state — money removed through QBCore.Functions.RemoveMoney is visible through xPlayer.getMoney() and vice versa.

GetResourceState reports exactly one framework as started (default: qbx_core), so Bridge-style load-time detection behaves as on a real server, and can be switched per test:

describe('bridge', function()
  it('charges through the ESX path', function()
    TestHelpers.framework.use('esx')
    local Bridge = TestHelpers.reload('server.bridge')   -- re-runs detection
    TestHelpers.framework.addPlayer(1, { money = { bank = 1000 } })
    expect(Bridge.Charge(1, 'bank', 400)).to.be_truthy()
    expect(TestHelpers.framework.getState(1).money.bank).to.equal(600)
  end)
end)
HelperDescription
TestHelpers.framework.use(name)Activate 'qbox', 'qbcore', 'esx' or 'none'
TestHelpers.framework.active()Currently active framework name
TestHelpers.framework.addPlayer(src, opts?)Seed a player (citizenid, job, money, items all overridable)
TestHelpers.framework.removePlayer(src)Remove a seeded player
TestHelpers.framework.getState(src)Canonical record for assertions
TestHelpers.framework.notifications()Every lib.notify / Notify / showNotification, one log
TestHelpers.framework.useItem(src, item)Trigger a registered useable item
TestHelpers.framework.reset()Clear players + notifications (registries survive)
TestHelpers.callback(name, src, ...)Invoke any registered callback (ox_lib, QBCore or ESX style) and get its results
TestHelpers.reload(module)Drop the require cache and load again

Callbacks registered via lib.callback.register, QBCore.Functions.CreateCallback and ESX.RegisterServerCallback land in one registry; lib.callback.await(name, false, ...) — the client-side call shape — dispatches there with the default source (TestHelpers.framework.defaultSource()), so client-flow code exercises real server handlers. Jobs registered through exports['qb-core']:AddJob, exports.qbx_core:CreateJob or seeded directly are visible through QBCore.Shared.Jobs, exports.qbx_core:GetJobs() and ESX.GetJobs() alike.

Reading a failure

Output is plain, greppable, and every location is a path:line anchor — no box drawing, no status glyphs, and no colour when stdout is not a TTY:

FAIL server/pricing.test.lua:12  withTax > blows up inside resource code

  error      server/pricing.lua:4: attempt to perform arithmetic on a nil value (local 'price')

  traceback
    server/pricing.lua:4: in function 'server.pricing.withTax'
    server/pricing.test.lua:13: in field 'fn'

  source server/pricing.lua:4
      3 | function M.withTax(price, rate)
    > 4 |   return price + (price * rate)
      5 | end

24 tests  22 passed  2 failed  26ms

A failed matcher reports matcher / expected / actual as separate lines instead of a prose sentence. CfxLua's own bootstrap.lua and scheduler.lua frames are stripped, since they sit beneath every test and say nothing about the resource under test. --json emits the same data as one document.

Exit code is 0 when everything passes, 1 on any failure. "No specs found" exits 0 unless you pass --strict.

Add **/*.test.lua and tests/** to exclude in your upload-config.json so specs never ship inside the escrow or open zip.

Configuration (9am-test.json)

{
  "patterns": ["tests/**/*.spec.lua", "tests/**/*.test.lua"],
  "include": ["tests/manual.spec.lua"],
  "exclude": ["**/node_modules/**"],
  "framework": "qbcore",   // initial active framework: qbox (default) | qbcore | esx | none
  "batteries": true         // false disables the framework batteries; or a list, e.g. ["oxlib"]
}

Toolchain

On first run, 9am-build downloads CfxLua v1.1.0 to ~/.9am-build/cfxlua/. Override with:

VariableDescription
CFXLUA_VMPath to cfxlua-vm binary
CFXLUA_RUNTIMEPath to cfxlua runtime/ directory
CFXLUA_TIMEOUTScript timeout in ms (default: 30000)
NINEAM_CFXLUA_CACHECustom cache directory

On Windows, if the native VM fails to start, 9am-build automatically falls back to the Linux binary via WSL.

Testing the runner itself

bun test covers discovery, config parsing and WSL path translation. The end-to-end tests spawn the real CfxLua VM; they run automatically once the toolchain is cached and can be forced with NINEAM_CFXLUA_E2E=1 bun test.

Project Structure

9am-build/
├── src/
│   ├── cli.ts                 # Published npm entry — `9am-build test` only
│   ├── index.ts               # Repo-only CLI entry point & command router
│   ├── cfx/                   # Cfx portal layer (browser only for login)
│   │   ├── api.ts             # portal-api REST client + chunking/error helpers
│   │   ├── upload.ts          # Chunked asset upload + version-cap recovery
│   │   ├── requester.ts       # fetch-based Requester (Cookie header from session)
│   │   ├── session.ts         # 3-tier ensureSession (jwt → SSO → passkey)
│   │   ├── login.ts           # Passkey + SSO-only portal login flows
│   │   ├── passkey.ts         # WebAuthn virtual authenticator + credential store
│   │   ├── storage-state.ts   # Playwright storageState + legacy migration
│   │   ├── run-browser.ts     # Spawns the Node browser runner from Bun
│   │   └── browser-runner.ts  # Node entry for login/register (Playwright)
│   ├── core/                  # Build & repo primitives
│   │   ├── config.ts          # Load & validate upload-config.json
│   │   ├── build.ts           # Zip creation & frontend builds
│   │   ├── git.ts             # Git clone / pull / diff
│   │   └── manifest.ts        # Read version from fxmanifest.lua
│   ├── integrations/          # External services
│   │   ├── github.ts          # GitHub release creation & asset upload
│   │   ├── discord.ts         # Discord webhook notifications
│   │   └── changelog.ts       # AI changelog generation
│   ├── commands/              # One file per CLI command
│   │   ├── test.ts            # Run *.test.lua (published)
│   │   ├── build.ts           # Zip only
│   │   ├── deploy.ts          # Build + portal upload + GitHub release
│   │   ├── release.ts         # Build + GitHub release only (no portal)
│   │   ├── register.ts        # Passkey registration (headed)
│   │   ├── server.ts          # GitHub webhook HTTP server
│   │   ├── test.ts            # CfxLua unit test runner
│   │   └── shared.ts          # Shared post-release Discord announcement
│   ├── cfxlua/                # Offline FiveM Lua test runner (published)
│   │   ├── discover.ts        # Find *.spec.lua / *.test.lua files
│   │   ├── ensure-toolchain.ts # Download/cache CfxLua VM (+ WSL fallback)
│   │   ├── run.ts             # Orchestrate execution, parse the JSON payload
│   │   ├── report.ts          # Agent-first text and --json rendering
│   │   ├── spawn.ts           # node:child_process wrapper (Node-compatible)
│   │   ├── types.ts           # Result shapes
│   │   └── test/              # Lua side: framework, helpers, runner
│   │       └── batteries/     # ox_lib / QBCore / QBox / ESX fakes over one shared state
│   └── server-support/
│       ├── queue.ts           # Serial build queue (latest-wins)
│       └── repos.ts           # repos.json loader
├── repos.json                 # Managed repo list
├── fixtures/                  # Sample resource for CfxLua test demos
├── scripts/copy-lua.mjs       # Copy Lua assets into dist on build
├── .env.example               # Environment template
└── package.json

Auto-generated files (gitignored):

FilePurpose
auth-state.jsonCached Cfx.re session cookies
passkey-credential.jsonWebAuthn passkey credentials
repos/Cloned repository working copies

License

MIT

Downloads & popularity

0downloads
1-day window · source-reported counts19 Oct 2026
337168.50
2026-07-22: 0 · observed 2026-10-20T23:10:26.5079225Z · period 2026-07-22–2026-07-222026-07-23: 337 · observed 2026-10-20T23:10:26.5079225Z · period 2026-07-23–2026-07-232026-07-24: 33 · observed 2026-10-20T23:10:26.5079225Z · period 2026-07-24–2026-07-242026-07-25: 16 · observed 2026-10-20T23:10:26.5079225Z · period 2026-07-25–2026-07-252026-07-26: 23 · observed 2026-10-20T23:10:26.5079225Z · period 2026-07-26–2026-07-262026-07-27: 2 · observed 2026-10-20T23:10:26.5079225Z · period 2026-07-27–2026-07-272026-07-28: 7 · observed 2026-10-20T23:10:26.5079225Z · period 2026-07-28–2026-07-282026-07-29: 8 · observed 2026-10-20T23:10:26.5079225Z · period 2026-07-29–2026-07-292026-07-30: 17 · observed 2026-10-20T23:10:26.5079225Z · period 2026-07-30–2026-07-302026-07-31: 0 · observed 2026-10-20T23:10:26.5079225Z · period 2026-07-31–2026-07-312026-08-01: 1 · observed 2026-10-20T23:10:26.5079225Z · period 2026-08-01–2026-08-012026-08-02: 3 · observed 2026-10-20T23:10:26.5079225Z · period 2026-08-02–2026-08-022026-08-03: 4 · observed 2026-10-20T23:10:26.5079225Z · period 2026-08-03–2026-08-032026-08-04: 3 · observed 2026-10-20T23:10:26.5079225Z · period 2026-08-04–2026-08-042026-08-05: 0 · observed 2026-10-20T23:10:26.5079225Z · period 2026-08-05–2026-08-052026-08-06: 37 · observed 2026-10-20T23:10:26.5079225Z · period 2026-08-06–2026-08-062026-08-07: 36 · observed 2026-10-20T23:10:26.5079225Z · period 2026-08-07–2026-08-072026-08-08: 89 · observed 2026-10-20T23:10:26.5079225Z · period 2026-08-08–2026-08-082026-08-09: 86 · observed 2026-10-20T23:10:26.5079225Z · period 2026-08-09–2026-08-092026-08-10: 83 · observed 2026-10-20T23:10:26.5079225Z · period 2026-08-10–2026-08-102026-08-11: 90 · observed 2026-10-20T23:10:26.5079225Z · period 2026-08-11–2026-08-112026-08-12: 52 · observed 2026-10-20T23:10:26.5079225Z · period 2026-08-12–2026-08-122026-08-13: 86 · observed 2026-10-20T23:10:26.5079225Z · period 2026-08-13–2026-08-132026-08-14: 0 · observed 2026-10-20T23:10:26.5079225Z · period 2026-08-14–2026-08-142026-08-15: 164 · observed 2026-10-20T23:10:26.5079225Z · period 2026-08-15–2026-08-152026-08-16: 130 · observed 2026-10-20T23:10:26.5079225Z · period 2026-08-16–2026-08-162026-08-17: 167 · observed 2026-10-20T23:10:26.5079225Z · period 2026-08-17–2026-08-172026-08-18: 163 · observed 2026-10-20T23:10:26.5079225Z · period 2026-08-18–2026-08-182026-08-19: 118 · observed 2026-10-20T23:10:26.5079225Z · period 2026-08-19–2026-08-192026-08-20: 166 · observed 2026-10-20T23:10:26.5079225Z · period 2026-08-20–2026-08-202026-08-21: 130 · observed 2026-10-20T23:10:26.5079225Z · period 2026-08-21–2026-08-212026-08-22: 1 · observed 2026-10-20T23:10:26.5079225Z · period 2026-08-22–2026-08-222026-08-23: 0 · observed 2026-10-20T23:10:26.5079225Z · period 2026-08-23–2026-08-232026-08-24: 2 · observed 2026-10-20T23:10:26.5079225Z · period 2026-08-24–2026-08-242026-08-25: 4 · observed 2026-10-20T23:10:26.5079225Z · period 2026-08-25–2026-08-252026-08-26: 4 · observed 2026-10-20T23:10:26.5079225Z · period 2026-08-26–2026-08-262026-08-27: 3 · observed 2026-10-20T23:10:26.5079225Z · period 2026-08-27–2026-08-272026-08-28: 2 · observed 2026-10-20T23:10:26.5079225Z · period 2026-08-28–2026-08-282026-08-29: 1 · observed 2026-10-20T23:10:26.5079225Z · period 2026-08-29–2026-08-292026-08-30: 8 · observed 2026-10-20T23:10:26.5079225Z · period 2026-08-30–2026-08-302026-08-31: 1 · observed 2026-10-20T23:10:26.5079225Z · period 2026-08-31–2026-08-312026-09-01: 2 · observed 2026-10-20T23:10:26.5079225Z · period 2026-09-01–2026-09-012026-09-02: 0 · observed 2026-10-20T23:10:26.5079225Z · period 2026-09-02–2026-09-022026-09-03: 0 · observed 2026-10-20T23:10:26.5079225Z · period 2026-09-03–2026-09-032026-09-04: 19 · observed 2026-10-20T23:10:26.5079225Z · period 2026-09-04–2026-09-042026-09-05: 1 · observed 2026-10-20T23:10:26.5079225Z · period 2026-09-05–2026-09-052026-09-06: 3 · observed 2026-10-20T23:10:26.5079225Z · period 2026-09-06–2026-09-062026-09-07: 0 · observed 2026-10-20T23:10:26.5079225Z · period 2026-09-07–2026-09-072026-09-08: 0 · observed 2026-10-20T23:10:26.5079225Z · period 2026-09-08–2026-09-082026-09-09: 3 · observed 2026-10-20T23:10:26.5079225Z · period 2026-09-09–2026-09-092026-09-10: 1 · observed 2026-10-20T23:10:26.5079225Z · period 2026-09-10–2026-09-102026-09-11: 0 · observed 2026-10-20T23:10:26.5079225Z · period 2026-09-11–2026-09-112026-09-12: 6 · observed 2026-10-20T23:10:26.5079225Z · period 2026-09-12–2026-09-122026-09-13: 2 · observed 2026-10-20T23:10:26.5079225Z · period 2026-09-13–2026-09-132026-09-14: 6 · observed 2026-10-20T23:10:26.5079225Z · period 2026-09-14–2026-09-142026-09-15: 0 · observed 2026-10-20T23:10:26.5079225Z · period 2026-09-15–2026-09-152026-09-16: 1 · observed 2026-10-20T23:10:26.5079225Z · period 2026-09-16–2026-09-162026-09-17: 40 · observed 2026-10-20T23:10:26.5079225Z · period 2026-09-17–2026-09-172026-09-18: 0 · observed 2026-10-20T23:10:26.5079225Z · period 2026-09-18–2026-09-182026-09-19: 0 · observed 2026-10-20T23:10:26.5079225Z · period 2026-09-19–2026-09-192026-09-20: 0 · observed 2026-10-20T23:10:26.5079225Z · period 2026-09-20–2026-09-202026-09-21: 3 · observed 2026-10-20T23:10:26.5079225Z · period 2026-09-21–2026-09-212026-09-22: 2 · observed 2026-10-20T23:10:26.5079225Z · period 2026-09-22–2026-09-222026-09-23: 3 · observed 2026-10-20T23:10:26.5079225Z · period 2026-09-23–2026-09-232026-09-24: 6 · observed 2026-10-20T23:10:26.5079225Z · period 2026-09-24–2026-09-242026-09-25: 0 · observed 2026-10-20T23:10:26.5079225Z · period 2026-09-25–2026-09-252026-09-26: 0 · observed 2026-10-20T23:10:26.5079225Z · period 2026-09-26–2026-09-262026-09-27: 0 · observed 2026-10-20T23:10:26.5079225Z · period 2026-09-27–2026-09-272026-09-28: 0 · observed 2026-10-20T23:10:26.5079225Z · period 2026-09-28–2026-09-282026-09-29: 0 · observed 2026-10-20T23:10:26.5079225Z · period 2026-09-29–2026-09-292026-09-30: 0 · observed 2026-10-20T23:10:26.5079225Z · period 2026-09-30–2026-09-302026-10-01: 0 · observed 2026-10-20T23:10:26.5079225Z · period 2026-10-01–2026-10-012026-10-02: 2 · observed 2026-10-20T23:10:26.5079225Z · period 2026-10-02–2026-10-022026-10-03: 2 · observed 2026-10-20T23:10:26.5079225Z · period 2026-10-03–2026-10-032026-10-04: 0 · observed 2026-10-20T23:10:26.5079225Z · period 2026-10-04–2026-10-042026-10-05: 4 · observed 2026-10-20T23:10:26.5079225Z · period 2026-10-05–2026-10-052026-10-06: 0 · observed 2026-10-20T23:10:26.5079225Z · period 2026-10-06–2026-10-062026-10-07: 0 · observed 2026-10-20T23:10:26.5079225Z · period 2026-10-07–2026-10-072026-10-08: 0 · observed 2026-10-20T23:10:26.5079225Z · period 2026-10-08–2026-10-082026-10-09: 0 · observed 2026-10-20T23:10:26.5079225Z · period 2026-10-09–2026-10-092026-10-10: 2 · observed 2026-10-20T23:10:26.5079225Z · period 2026-10-10–2026-10-102026-10-11: 1 · observed 2026-10-20T23:10:26.5079225Z · period 2026-10-11–2026-10-112026-10-12: 2 · observed 2026-10-20T23:10:26.5079225Z · period 2026-10-12–2026-10-122026-10-13: 0 · observed 2026-10-20T23:10:26.5079225Z · period 2026-10-13–2026-10-132026-10-14: 0 · observed 2026-10-20T23:10:26.5079225Z · period 2026-10-14–2026-10-142026-10-15: 0 · observed 2026-10-20T23:10:26.5079225Z · period 2026-10-15–2026-10-152026-10-16: 0 · observed 2026-10-20T23:10:26.5079225Z · period 2026-10-16–2026-10-162026-10-17: 2 · observed 2026-10-20T23:10:26.5079225Z · period 2026-10-17–2026-10-172026-10-18: 3 · observed 2026-10-20T23:10:26.5079225Z · period 2026-10-18–2026-10-182026-10-19: 0 · observed 2026-10-20T23:10:26.5079225Z · period 2026-10-19–2026-10-19
22 Jul19 Oct

npm · 90 observations shown. Missing days are unknown.

View observed values
Date / source periodValueObserved at
2026-10-19 – 2026-10-1902026-10-20T23:10:26.5079225Z
2026-10-18 – 2026-10-1832026-10-20T23:10:26.5079225Z
2026-10-17 – 2026-10-1722026-10-20T23:10:26.5079225Z
2026-10-16 – 2026-10-1602026-10-20T23:10:26.5079225Z
2026-10-15 – 2026-10-1502026-10-20T23:10:26.5079225Z
2026-10-14 – 2026-10-1402026-10-20T23:10:26.5079225Z
2026-10-13 – 2026-10-1302026-10-20T23:10:26.5079225Z
2026-10-12 – 2026-10-1222026-10-20T23:10:26.5079225Z
2026-10-11 – 2026-10-1112026-10-20T23:10:26.5079225Z
2026-10-10 – 2026-10-1022026-10-20T23:10:26.5079225Z
2026-10-09 – 2026-10-0902026-10-20T23:10:26.5079225Z
2026-10-08 – 2026-10-0802026-10-20T23:10:26.5079225Z
2026-10-07 – 2026-10-0702026-10-20T23:10:26.5079225Z
2026-10-06 – 2026-10-0602026-10-20T23:10:26.5079225Z
2026-10-05 – 2026-10-0542026-10-20T23:10:26.5079225Z
2026-10-04 – 2026-10-0402026-10-20T23:10:26.5079225Z
2026-10-03 – 2026-10-0322026-10-20T23:10:26.5079225Z
2026-10-02 – 2026-10-0222026-10-20T23:10:26.5079225Z
2026-10-01 – 2026-10-0102026-10-20T23:10:26.5079225Z
2026-09-30 – 2026-09-3002026-10-20T23:10:26.5079225Z
2026-09-29 – 2026-09-2902026-10-20T23:10:26.5079225Z
2026-09-28 – 2026-09-2802026-10-20T23:10:26.5079225Z
2026-09-27 – 2026-09-2702026-10-20T23:10:26.5079225Z
2026-09-26 – 2026-09-2602026-10-20T23:10:26.5079225Z
2026-09-25 – 2026-09-2502026-10-20T23:10:26.5079225Z
2026-09-24 – 2026-09-2462026-10-20T23:10:26.5079225Z
2026-09-23 – 2026-09-2332026-10-20T23:10:26.5079225Z
2026-09-22 – 2026-09-2222026-10-20T23:10:26.5079225Z
2026-09-21 – 2026-09-2132026-10-20T23:10:26.5079225Z
2026-09-20 – 2026-09-2002026-10-20T23:10:26.5079225Z
2026-09-19 – 2026-09-1902026-10-20T23:10:26.5079225Z
2026-09-18 – 2026-09-1802026-10-20T23:10:26.5079225Z
2026-09-17 – 2026-09-17402026-10-20T23:10:26.5079225Z
2026-09-16 – 2026-09-1612026-10-20T23:10:26.5079225Z
2026-09-15 – 2026-09-1502026-10-20T23:10:26.5079225Z
2026-09-14 – 2026-09-1462026-10-20T23:10:26.5079225Z
2026-09-13 – 2026-09-1322026-10-20T23:10:26.5079225Z
2026-09-12 – 2026-09-1262026-10-20T23:10:26.5079225Z
2026-09-11 – 2026-09-1102026-10-20T23:10:26.5079225Z
2026-09-10 – 2026-09-1012026-10-20T23:10:26.5079225Z
2026-09-09 – 2026-09-0932026-10-20T23:10:26.5079225Z
2026-09-08 – 2026-09-0802026-10-20T23:10:26.5079225Z
2026-09-07 – 2026-09-0702026-10-20T23:10:26.5079225Z
2026-09-06 – 2026-09-0632026-10-20T23:10:26.5079225Z
2026-09-05 – 2026-09-0512026-10-20T23:10:26.5079225Z
2026-09-04 – 2026-09-04192026-10-20T23:10:26.5079225Z
2026-09-03 – 2026-09-0302026-10-20T23:10:26.5079225Z
2026-09-02 – 2026-09-0202026-10-20T23:10:26.5079225Z
2026-09-01 – 2026-09-0122026-10-20T23:10:26.5079225Z
2026-08-31 – 2026-08-3112026-10-20T23:10:26.5079225Z
2026-08-30 – 2026-08-3082026-10-20T23:10:26.5079225Z
2026-08-29 – 2026-08-2912026-10-20T23:10:26.5079225Z
2026-08-28 – 2026-08-2822026-10-20T23:10:26.5079225Z
2026-08-27 – 2026-08-2732026-10-20T23:10:26.5079225Z
2026-08-26 – 2026-08-2642026-10-20T23:10:26.5079225Z
2026-08-25 – 2026-08-2542026-10-20T23:10:26.5079225Z
2026-08-24 – 2026-08-2422026-10-20T23:10:26.5079225Z
2026-08-23 – 2026-08-2302026-10-20T23:10:26.5079225Z
2026-08-22 – 2026-08-2212026-10-20T23:10:26.5079225Z
2026-08-21 – 2026-08-211302026-10-20T23:10:26.5079225Z
2026-08-20 – 2026-08-201662026-10-20T23:10:26.5079225Z
2026-08-19 – 2026-08-191182026-10-20T23:10:26.5079225Z
2026-08-18 – 2026-08-181632026-10-20T23:10:26.5079225Z
2026-08-17 – 2026-08-171672026-10-20T23:10:26.5079225Z
2026-08-16 – 2026-08-161302026-10-20T23:10:26.5079225Z
2026-08-15 – 2026-08-151642026-10-20T23:10:26.5079225Z
2026-08-14 – 2026-08-1402026-10-20T23:10:26.5079225Z
2026-08-13 – 2026-08-13862026-10-20T23:10:26.5079225Z
2026-08-12 – 2026-08-12522026-10-20T23:10:26.5079225Z
2026-08-11 – 2026-08-11902026-10-20T23:10:26.5079225Z
2026-08-10 – 2026-08-10832026-10-20T23:10:26.5079225Z
2026-08-09 – 2026-08-09862026-10-20T23:10:26.5079225Z
2026-08-08 – 2026-08-08892026-10-20T23:10:26.5079225Z
2026-08-07 – 2026-08-07362026-10-20T23:10:26.5079225Z
2026-08-06 – 2026-08-06372026-10-20T23:10:26.5079225Z
2026-08-05 – 2026-08-0502026-10-20T23:10:26.5079225Z
2026-08-04 – 2026-08-0432026-10-20T23:10:26.5079225Z
2026-08-03 – 2026-08-0342026-10-20T23:10:26.5079225Z
2026-08-02 – 2026-08-0232026-10-20T23:10:26.5079225Z
2026-08-01 – 2026-08-0112026-10-20T23:10:26.5079225Z
2026-07-31 – 2026-07-3102026-10-20T23:10:26.5079225Z
2026-07-30 – 2026-07-30172026-10-20T23:10:26.5079225Z
2026-07-29 – 2026-07-2982026-10-20T23:10:26.5079225Z
2026-07-28 – 2026-07-2872026-10-20T23:10:26.5079225Z
2026-07-27 – 2026-07-2722026-10-20T23:10:26.5079225Z
2026-07-26 – 2026-07-26232026-10-20T23:10:26.5079225Z
2026-07-25 – 2026-07-25162026-10-20T23:10:26.5079225Z
2026-07-24 – 2026-07-24332026-10-20T23:10:26.5079225Z
2026-07-23 – 2026-07-233372026-10-20T23:10:26.5079225Z
2026-07-22 – 2026-07-2202026-10-20T23:10:26.5079225Z

Versions 3

Collected releases
VersionPublishedDirect dependenciesOpen version
1.2.1Registry latest23 Jul 202610
1.2.023 Jul 202610
1.0.023 Jul 202610

Package advisories

0
No matching advisories collected

This describes our collected data; it is not a security assessment.

Repository

PENDING
ilovehugetits/9am-build

Shared repository data · GitHub

License detected in repository
Not collected

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 21:35 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package:bc7aed6fbeba5bf3f9e400ab5f16423c0c6d62a34f819fece42b7ff0b81d6800