forked from
npmx.dev/npmx.dev
[READ-ONLY]
a fast, modern browser for the npm registry
1/**
2 * npm Registry API Types
3 * Custom types for search and download APIs (not covered by @npm/types).
4 *
5 * @see https://github.com/npm/types
6 * @see https://github.com/npm/registry/blob/main/docs/REGISTRY-API.md
7 */
8
9import type {
10 Packument as PackumentWithoutLicenseObjects,
11 PackumentVersion as PackumentVersionWithoutAttestations,
12 Contact,
13} from '@npm/types'
14import type { ReadmeResponse } from './readme'
15
16// Re-export official npm types for packument/manifest
17export type { Manifest, ManifestVersion, PackageJSON } from '@npm/types'
18
19type NpmTrustedPublisherEvidence = NpmSearchTrustedPublisher | NpmTrustedPublisher | true
20
21export interface PackumentVersion extends PackumentVersionWithoutAttestations {
22 _npmUser?: Contact & { trustedPublisher?: NpmTrustedPublisherEvidence }
23 dist: PackumentVersionWithoutAttestations['dist'] & { attestations?: NpmVersionAttestations }
24}
25
26export type Packument = Omit<PackumentWithoutLicenseObjects, 'license' | 'versions'> & {
27 // Fix for license field being incorrectly typed in @npm/types
28 // TODO: Remove this type override when @npm/types fixes the license field typing
29 license?: string | { type: string; url?: string }
30 versions: Record<string, PackumentVersion>
31}
32
33/** Install scripts info (preinstall, install, postinstall) */
34export interface InstallScriptsInfo {
35 scripts: ('preinstall' | 'install' | 'postinstall')[]
36 content: Record<string, string>
37 npxDependencies: Record<string, string>
38}
39
40/** PackumentVersion with additional install scripts info */
41export type SlimPackumentVersion = PackumentVersion & {
42 installScripts?: InstallScriptsInfo
43}
44
45export type PublishTrustLevel = 'none' | 'trustedPublisher' | 'provenance'
46
47export type SlimVersion = Pick<SlimPackumentVersion, 'version' | 'deprecated' | 'tags'> & {
48 hasProvenance?: boolean
49 trustLevel?: PublishTrustLevel
50}
51
52/**
53 * Slimmed down Packument for client-side use.
54 * Strips unnecessary fields to reduce payload size.
55 * - readme removed (fetched separately)
56 * - versions limited to dist-tag versions only
57 * - time limited to dist-tag versions
58 */
59export interface SlimPackument {
60 '_id': string
61 '_rev'?: string
62 'name': string
63 'description'?: string
64 'dist-tags': { latest?: string } & Record<string, string>
65 /**
66 * Timestamps for package versions.
67 *
68 * **IMPORTANT**: Use `time[version]` to get the publish date of a specific version.
69 *
70 * **DO NOT use `time.modified`** - it can be updated by metadata changes (e.g., maintainer
71 * additions/removals) without any code being published, making it misleading for users
72 * trying to assess package maintenance activity.
73 *
74 * - `time[version]` - When that specific version was published (use this!)
75 * - `time.created` - When the package was first created
76 * - `time.modified` - Last metadata change (misleading - avoid using)
77 */
78 'time': { modified?: string; created?: string } & Record<string, string>
79 'maintainers'?: NpmPerson[]
80 'author'?: NpmPerson
81 'license'?: string
82 'homepage'?: string
83 'keywords'?: string[]
84 'repository'?: { type?: string; url?: string; directory?: string }
85 'bugs'?: { url?: string; email?: string }
86 /** current version */
87 'requestedVersion': SlimPackumentVersion | null
88 /** Only includes dist-tag versions (with installScripts info added per version) */
89 'versions': Record<string, SlimVersion>
90 /** Lightweight security metadata for all versions */
91 'securityVersions'?: PackageVersionInfo[]
92}
93
94/**
95 * Lightweight version info for the version list
96 */
97export interface PackageVersionInfo {
98 version: string
99 time?: string
100 hasProvenance: boolean
101 trustLevel?: PublishTrustLevel
102 deprecated?: string
103}
104
105/**
106 * Person/contact type extracted from @npm/types Contact interface
107 * Used for maintainers, authors, publishers
108 */
109export interface NpmPerson {
110 name?: string
111 email?: string
112 url?: string
113 username?: string
114}
115
116/**
117 * Search API response
118 * Returned by GET /-/v1/search
119 * Note: Not covered by @npm/types (see https://github.com/npm/types/issues/28)
120 */
121export interface NpmSearchResponse {
122 isStale: boolean
123 objects: NpmSearchResult[]
124 total: number
125 time: string
126}
127
128export interface NpmSearchResult {
129 package: NpmSearchPackage
130 score: NpmSearchScore
131 searchScore: number
132 /** Download counts (weekly/monthly) */
133 downloads?: {
134 weekly?: number
135 monthly?: number
136 }
137 /** Number of dependents */
138 dependents?: string
139 /** Last updated timestamp (ISO 8601) */
140 updated?: string
141 flags?: {
142 unstable?: boolean
143 insecure?: number
144 }
145}
146
147/**
148 * Trusted publisher info from search API
149 * Present when package was published via OIDC (e.g., GitHub Actions)
150 */
151export interface NpmSearchTrustedPublisher {
152 /** OIDC provider identifier (e.g., "github", "gitlab") */
153 id: string
154 /** OIDC config ID */
155 oidcConfigId?: string
156}
157
158/**
159 * Publisher info with optional trusted publisher and actor details
160 */
161export interface NpmSearchPublisher extends NpmPerson {
162 /** Trusted publisher info (present if published via OIDC) */
163 trustedPublisher?: NpmSearchTrustedPublisher
164 /** Actor who triggered the publish (for trusted publishing) */
165 actor?: {
166 name: string
167 type: 'user' | 'team'
168 email?: string
169 }
170}
171
172export interface NpmSearchPackage {
173 name: string
174 scope?: string
175 version: string
176 description?: string
177 keywords?: string[]
178 date: string
179 links: {
180 npm?: string
181 homepage?: string
182 repository?: string
183 bugs?: string
184 }
185 author?: NpmPerson
186 publisher?: NpmSearchPublisher
187 maintainers?: NpmPerson[]
188 license?: string
189}
190
191export interface NpmSearchScore {
192 final: number
193 detail: {
194 quality: number
195 popularity: number
196 maintenance: number
197 }
198}
199
200/**
201 * Attestations/provenance info on package version dist
202 * Present when package was published with provenance
203 * Note: Not covered by @npm/types
204 */
205export interface NpmVersionAttestations {
206 /** URL to fetch full attestation details */
207 url: string
208 /** Provenance info */
209 provenance: {
210 /** SLSA predicate type URL */
211 predicateType: string
212 }
213}
214
215/**
216 * Extended dist info that may include attestations
217 * The base PackumentVersion.dist doesn't include attestations
218 */
219export interface NpmVersionDist {
220 shasum: string
221 tarball: string
222 integrity?: string
223 fileCount?: number
224 unpackedSize?: number
225 signatures?: Array<{
226 keyid: string
227 sig: string
228 }>
229 /** Attestations/provenance (present if published with provenance) */
230 attestations?: NpmVersionAttestations
231}
232
233/**
234 * Parsed provenance details for display (from attestation bundle SLSA predicate).
235 * Used by the provenance API and PackageProvenanceSection.
236 * @public
237 */
238export interface ProvenanceDetails {
239 /** Provider ID (e.g. "github", "gitlab") */
240 provider: string
241 /** Human-readable provider label (e.g. "GitHub Actions") */
242 providerLabel: string
243 /** Link to build run summary (e.g. GitHub Actions run URL) */
244 buildSummaryUrl?: string
245 /** Link to source commit in repository */
246 sourceCommitUrl?: string
247 /** Source commit SHA (short or full) */
248 sourceCommitSha?: string
249 /** Link to workflow/build config file in repo */
250 buildFileUrl?: string
251 /** Workflow path (e.g. ".github/workflows/release.yml") */
252 buildFilePath?: string
253 /** Link to transparency log entry (e.g. Sigstore search) */
254 publicLedgerUrl?: string
255}
256
257/**
258 * Download counts API response
259 * From https://api.npmjs.org/downloads/
260 * Note: Not covered by @npm/types
261 */
262export interface NpmDownloadCount {
263 downloads: number
264 start: string
265 end: string
266 package: string
267}
268
269export interface NpmDownloadRange {
270 downloads: Array<{
271 downloads: number
272 day: string
273 }>
274 start: string
275 end: string
276 package: string
277}
278
279/**
280 * Organization API types
281 * These require authentication
282 * Note: Not covered by @npm/types
283 */
284export interface NpmOrgMember {
285 user: string
286 role: 'developer' | 'admin' | 'owner'
287}
288
289export interface NpmTeam {
290 name: string
291 description?: string
292 members?: string[]
293}
294
295export interface NpmPackageAccess {
296 permissions: 'read-only' | 'read-write'
297}
298
299/**
300 * Trusted Publishing types
301 * Note: Not covered by @npm/types
302 */
303export interface NpmTrustedPublisher {
304 type: 'github-actions' | 'gitlab-ci'
305 // GitHub Actions specific
306 repository?: string
307 workflow?: string
308 environment?: string
309 // GitLab CI specific
310 namespace?: string
311 project?: string
312 ciConfigPath?: string
313}
314
315/**
316 * jsDelivr API Types
317 * Used for package file browsing
318 */
319
320/**
321 * Response from jsDelivr package API (nested structure)
322 * GET https://data.jsdelivr.com/v1/packages/npm/{package}@{version}
323 */
324export interface JsDelivrPackageResponse {
325 type: 'npm'
326 name: string
327 version: string
328 /** Default entry point file */
329 default: string | null
330 /** Nested file tree */
331 files: JsDelivrFileNode[]
332}
333
334/**
335 * A file or directory node from jsDelivr API
336 */
337export interface JsDelivrFileNode {
338 type: 'file' | 'directory'
339 name: string
340 /** File hash (only for files) */
341 hash?: string
342 /** File size in bytes (only for files) */
343 size?: number
344 /** Child nodes (only for directories) */
345 files?: JsDelivrFileNode[]
346}
347
348/**
349 * Tree node for package file browser
350 */
351export interface PackageFileTree {
352 /** File or directory name */
353 name: string
354 /** Full path from package root */
355 path: string
356 /** Node type */
357 type: 'file' | 'directory'
358 /** File size in bytes (only for files) */
359 size?: number
360 /** Child nodes (only for directories) */
361 children?: PackageFileTree[]
362}
363
364/**
365 * Response from file tree API
366 */
367export interface PackageFileTreeResponse {
368 package: string
369 version: string
370 default?: string
371 tree: PackageFileTree[]
372}
373
374/**
375 * Response from file content API
376 */
377export interface PackageFileContentResponse {
378 package: string
379 version: string
380 path: string
381 language: string
382 content: string
383 html: string
384 lines: number
385 markdownHtml?: ReadmeResponse
386}
387
388/**
389 * Minimal packument data needed for package cards
390 */
391export interface MinimalPackument {
392 'name': string
393 'description'?: string
394 'keywords'?: string[]
395 // `dist-tags` can be missing in some later unpublished packages
396 'dist-tags'?: Record<string, string>
397 'time': Record<string, string>
398 'maintainers'?: NpmPerson[]
399}
400
401/**
402 * Lightweight package metadata returned by /api/registry/package-meta/.
403 * Contains only the fields needed for search result cards, extracted
404 * server-side from the full packument + downloads API.
405 */
406export interface PackageMetaResponse {
407 name: string
408 version: string
409 description?: string
410 keywords?: string[]
411 license?: string
412 date: string
413 links: {
414 npm: string
415 homepage?: string
416 repository?: string
417 bugs?: string
418 }
419 author?: NpmPerson
420 maintainers?: NpmPerson[]
421 weeklyDownloads?: number
422}