* Begin external projects moderator database frontend * add copy link button * begin project page permissions settings * MEL database backend routes * include filename in external files * wip: when uploading a version file, fetch its overrides as a list * wip: override license checks * improve FileHost ref counting * file host read capability * scan files when inserting version file * add dependency sha1 field * clean up version files * wip: attributions * update s3 file host * attribution scanning basic works * works * insert attribution info after resolving * add routes * remove dep sha1 stuff * prepr * wip: override file sources * add files_missing_attributions to versions * return extended version info + attributed at/by * hook up frontend to backend (mostly) * expose version date published * withholding version visibility * frontend work * prepr * use api-client for img upload * moar frontend * prepr * Add schema to attribution resolution and Flame project results * sqlx prepare * changes * remove feature flag, fix optional proof images * fix schema * fmt * fix deletion and file fetch * prepare * fix admonition * update frontend stuff to new schema * prepr * attribution on dependencies * fixes * sqlx prepare * fixes * routes * fix routes * Version grandfathering * prepare * wip: bulk routes * pushing what i've got rn * include link in NoPermission * change hash insert to bulk route * query flame even if entry in MEL * delete file with weird name * Prioritise putting override files in existing groups even with ExternalLicense * fix how hex bytes are handled in route * feat: coolbot moderation changes (#6215) * Update moderator checklist * move permissions stage order * Updated nagContext.versions to v3, added nag for permissions * Update permissions.vue default messages * prepr --------- Co-authored-by: coolbot100s <76798835+coolbot100s@users.noreply.github.com> * QA * prepr * should group by project * return attribution resolution correctly * updated by moderator info * Track what moderator reviewed an attribution moderation status * default deser FMA field * new version page * clean up fetching + add a couple missing features * qa items * prepr * provide moderation package stuff with DI * format? * don't redact moderated_at * move supplementary resources * Reorganize moderation messages. * Quick replies for external content permissions. * prepare * QA * allow exempting projects * Ignore Flame projects which 404 * fix ci * fix cross project attribution stuff * Fix permission error * change what files get cscanned * add more logging * QA Jun 22 * fix * idempotency * Expose route for rescanning * update blog link --------- Co-authored-by: aecsocket <aecsocket@tutanota.com> Co-authored-by: coolbot100s <76798835+coolbot100s@users.noreply.github.com> Co-authored-by: aecsocket <43144841+aecsocket@users.noreply.github.com>
@modrinth/api-client
Platform-agnostic TypeScript client for Modrinth's API across Node.js, browsers, Nuxt, and Tauri.
⚠️ We use this internally to power modrinth.com, Modrinth App, and Modrinth Hosting frontends. It may break without any notice, but you are welcome to use it.
Installation
pnpm add @modrinth/api-client
Tauri apps also need the optional peer dependency:
pnpm add @modrinth/api-client @tauri-apps/plugin-http
Usage
Generic Node.js or Browser Client
import { AuthFeature, GenericModrinthClient, type Labrinth } from '@modrinth/api-client'
const client = new GenericModrinthClient({
userAgent: 'my-app/1.0.0',
features: [new AuthFeature({ token: process.env.MODRINTH_TOKEN })],
})
const project: Labrinth.Projects.v2.Project = await client.labrinth.projects_v2.get('sodium')
const members = await client.labrinth.projects_v3.getMembers(project.id)
You can still make direct requests through the same platform layer:
const project = await client.request<Labrinth.Projects.v2.Project>('/project/sodium', {
api: 'labrinth',
version: 2,
})
Nuxt
import { AuthFeature, CircuitBreakerFeature, NuxtCircuitBreakerStorage, NuxtModrinthClient } from '@modrinth/api-client'
export const useModrinthClient = async () => {
const config = useRuntimeConfig()
return new NuxtModrinthClient({
userAgent: 'my-nuxt-app/1.0.0',
rateLimitKey: import.meta.server ? config.rateLimitKey : undefined,
features: [
new AuthFeature({
token: process.env.MODRINTH_TOKEN,
}),
new CircuitBreakerFeature({
storage: new NuxtCircuitBreakerStorage(),
}),
],
})
}
Tauri
import { getVersion } from '@tauri-apps/api/app'
import { AuthFeature, TauriModrinthClient } from '@modrinth/api-client'
const client = new TauriModrinthClient({
userAgent: async () => `modrinth/theseus/${await getVersion()} (support@modrinth.com)`,
features: [new AuthFeature({ token: process.env.MODRINTH_TOKEN })],
})
const project = await client.labrinth.projects_v2.get('sodium')
API Modules
Modules are available as nested properties on the client:
client.labrinth.projects_v2
client.labrinth.projects_v3
client.labrinth.versions_v3
Types are exported from the package root:
import type { Labrinth } from '@modrinth/api-client'
const project: Labrinth.Projects.v3.Project = await client.labrinth.projects_v3.get('sodium')
Modrinth Hosting API Modules
- These modules are internal to Modrinth and are only supported inside the Modrinth Hosting panel in Modrinth App and on modrinth.com. They should not be expected to work in third-party clients today. We are discussing how to safely expose access to your own server through these APIs in the future.
Base URLs
By default, the client uses Modrinth production services:
labrinthBaseUrl:https://api.modrinth.com
Override them for staging or custom deployments:
const client = new GenericModrinthClient({
userAgent: 'my-app/1.0.0',
labrinthBaseUrl: 'https://staging-api.modrinth.com',
})
External APIs can be targeted per request by passing a full URL as api and disabling auth:
await client.request('/endpoint', {
api: 'https://example.com',
version: 1,
skipAuth: true,
})
Features
Features wrap requests before they reach the platform implementation:
import { AuthFeature, CircuitBreakerFeature, RetryFeature } from '@modrinth/api-client'
const client = new GenericModrinthClient({
features: [new AuthFeature({ token: async () => process.env.MODRINTH_TOKEN }), new RetryFeature({ maxAttempts: 3, backoffStrategy: 'exponential' }), new CircuitBreakerFeature({ maxFailures: 3, resetTimeout: 30_000 })],
})
Built-in features include authentication, node auth, retries, circuit breaking, panel version headers, and verbose logging.
Uploads
Upload endpoints return an UploadHandle<T> with progress and cancellation support:
const upload = client.kyros.files_v0.uploadFile(path, file)
upload.onProgress(({ progress }) => {
console.log(Math.round(progress * 100))
})
await upload.promise
Uploads use XMLHttpRequest for progress tracking and are only available in browser-capable contexts. NuxtModrinthClient.upload() throws during SSR.
Third-Party API Typings
- This package also includes some third-party API modules and typings used by Modrinth internals. They are not part of the stable public API surface and should be used at your own risk.
Development
pnpm --filter @modrinth/api-client build
pnpm --filter @modrinth/api-client lint
# or pnpm prepr:frontend:lib in turborepo root.
When adding a module, add it to src/modules/index.ts so it is included in the typed client structure.
License
Licensed under LGPL-3.0. See LICENSE.