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

@arkanaio/connector-microsoft-365-licenses

v0.2.0

Published

Microsoft 365 license products, capacity and assignments for ALMA.

Readme

Microsoft 365 licenses

@arkanaio/connector-microsoft-365-licenses reads the Microsoft Graph v1.0 license catalogue and the accounts holding each user license. It declares only licenses. No employee directory connector, Microsoft login, or Google Workspace connection is required.

Set up the connection

  1. In Microsoft Entra admin center, create a dedicated, single-tenant app registration in the organization whose licenses you want to read.
  2. Under API permissions, add Microsoft Graph Application permissions:
    • LicenseAssignment.Read.All: read the subscribed SKU catalogue.
    • User.Read.All: find users holding each SKU and read their account ID, display name, mail and user principal name.
  3. Grant administrator consent for those permissions. No delegated user, redirect URI, Directory.Read.All, write permission, Reports permission or audit-log permission is needed. Reading user identities for license matching does not enable employee synchronization in ALMA.
  4. Create a client secret. Record its Value, not its secret ID, and expiry.
  5. In ALMA's license integration form enter the Directory (tenant) ID and Application (client) ID GUIDs, then the client secret value. The package must first have been published and incorporated in that ALMA deployment.
  6. Renew the secret and reconnect before it expires. Revoking admin consent or letting it expire makes the next read fail; it never becomes zero licenses.

Use a dedicated app with only these permissions: Microsoft's .default scope includes all Graph application permissions granted to that app.

What is returned

  • One plan per skuId, named with Microsoft's skuPartNumber. These are provider identifiers, not a hard-coded marketing-name catalogue.
  • Only SKUs whose appliesTo is User. Company-wide entitlements cannot be represented as user seats and are excluded. Products with no assignments remain in the catalogue.
  • purchasedQuantity.value is prepaidUnits.enabled, the units enabled for active subscriptions. Missing capacity is null; reported zero remains zero. Warning/grace-period, suspended and locked-out units are not added. This is active licensed capacity, not a price, proof of a paid purchase, invoice quantity, or the number of accounts. Trials and free entitlements may be present because Graph does not provide their billing terms here.
  • Each account returned by the SKU assignment filter becomes one seat, keyed by SKU GUID and user GUID. The filter includes direct and inherited license assignments. We do not filter out disabled accounts or guests: an account retaining a license still holds it.
  • Email uses mail, falling back to a valid userPrincipalName; synthetic guest #EXT# identifiers are not email addresses. With neither, email is null. ALMA determines employee matches and orphaned assignments.
  • Price, currency and billing cycle are always null. Last activity is not declared and is always null. Generic sign-ins are not license usage.

consumedQuantity.value independently preserves Graph's consumedUnits aggregate. Both readings use unit person, their exact Graph field as source, and the UTC date of context.now() as observedOn. Either reading can be unknown while the other is known; neither is reconstructed from the paginated account list. A consumed total never creates account assignments. It measures assignment, not activity or usage intensity.

Requests and limits

Only the global Microsoft cloud is supported. Sovereign cloud endpoints are not silently substituted.

Every page obtains a fresh app-only token at login.microsoftonline.com/{tenant}/oauth2/v2.0/token, reads graph.microsoft.com/v1.0/subscribedSkus, and makes at most five /users queries, with 100 accounts per query, filtered by SKU. Large tenants continue using an opaque cursor containing only a SKU GUID and a Graph position token. No token or secret is cached across contexts. Each call has a 15-second timeout.

Client authentication uses the documented RFC 6749 HTTP Basic form: the secret is only in the authorization header. The token request creates no provider business data; all Graph calls are GETs. Bearer tokens only go to Graph. Continuation links must use the exact Graph users endpoint and matching query; only their position token is retained. Redirects are rejected by the shared fetch boundary.

The catalogue is capped at the contract's 1,000 plans. Unexpected catalogue pagination, malformed data and repeated page positions fail explicitly. Microsoft may delay propagation of license changes; a scan is not an atomic snapshot. Throttling and server errors are retryable; invalid credentials and missing administrator consent require fixing the connection.

Validation and evidence

Tests use the real createConnectorFetch boundary and synthetic responses based on Microsoft's documented schema. They cover pagination, unknown and zero capacity, products without accounts, guest identifiers, credential placement, permission failures, service failures, schema drift, and malicious continuation links. No live Microsoft tenant was used; these fixtures are not a claim of production acceptance. Validate administrator consent, token issuance and license totals against a real test tenant before release acceptance.

Provider references