import {z} from 'zod' export type GetApiSystemConfigurationOptions = {baseUrl?: string | undefined, CustomAuthentication?: string | undefined, fetch?: typeof fetch | undefined}; export const version = z.object({Major: z.number().int().optional(), Minor: z.number().int().optional(), Build: z.number().int().optional(), Revision: z.number().int().optional(), MajorRevision: z.number().int().optional(), MinorRevision: z.number().int().optional()}); export const imageSavingConvention = z.enum(["Legacy", "Compatible"]); export const metadataOptions = z.object({ItemType: z.string().nullable().optional(), DisabledMetadataSavers: z.array(z.string()).nullable().optional(), LocalMetadataReaderOrder: z.array(z.string()).nullable().optional(), DisabledMetadataFetchers: z.array(z.string()).nullable().optional(), MetadataFetcherOrder: z.array(z.string()).nullable().optional(), DisabledImageFetchers: z.array(z.string()).nullable().optional(), ImageFetcherOrder: z.array(z.string()).nullable().optional()}); export const nameValuePair = z.object({Name: z.string().nullable().optional(), Value: z.string().nullable().optional()}); export const repositoryInfo = z.object({Name: z.string().nullable().optional(), Url: z.string().nullable().optional(), Enabled: z.boolean().optional()}); export const pathSubstitution = z.object({From: z.string().nullable().optional(), To: z.string().nullable().optional()}); export const serverConfiguration = z.object({LogFileRetentionDays: z.number().int().optional(), IsStartupWizardCompleted: z.boolean().optional(), CachePath: z.string().nullable().optional(), PreviousVersion: version.optional(), PreviousVersionStr: z.string().nullable().optional(), EnableUPnP: z.boolean().optional(), EnableMetrics: z.boolean().optional(), PublicPort: z.number().int().optional(), UPnPCreateHttpPortMap: z.boolean().optional(), UDPPortRange: z.string().nullable().optional(), EnableIPV6: z.boolean().optional(), EnableIPV4: z.boolean().optional(), EnableSSDPTracing: z.boolean().optional(), SSDPTracingFilter: z.string().nullable().optional(), UDPSendCount: z.number().int().optional(), UDPSendDelay: z.number().int().optional(), IgnoreVirtualInterfaces: z.boolean().optional(), VirtualInterfaceNames: z.string().nullable().optional(), GatewayMonitorPeriod: z.number().int().optional(), EnableMultiSocketBinding: z.boolean().optional(), TrustAllIP6Interfaces: z.boolean().optional(), HDHomerunPortRange: z.string().nullable().optional(), PublishedServerUriBySubnet: z.array(z.string()).nullable().optional(), AutoDiscoveryTracing: z.boolean().optional(), AutoDiscovery: z.boolean().optional(), PublicHttpsPort: z.number().int().optional(), HttpServerPortNumber: z.number().int().optional(), HttpsPortNumber: z.number().int().optional(), EnableHttps: z.boolean().optional(), EnableNormalizedItemByNameIds: z.boolean().optional(), CertificatePath: z.string().nullable().optional(), CertificatePassword: z.string().nullable().optional(), IsPortAuthorized: z.boolean().optional(), QuickConnectAvailable: z.boolean().optional(), EnableRemoteAccess: z.boolean().optional(), EnableCaseSensitiveItemIds: z.boolean().optional(), DisableLiveTvChannelUserDataName: z.boolean().optional(), MetadataPath: z.string().nullable().optional(), MetadataNetworkPath: z.string().nullable().optional(), PreferredMetadataLanguage: z.string().nullable().optional(), MetadataCountryCode: z.string().nullable().optional(), SortReplaceCharacters: z.array(z.string()).nullable().optional(), SortRemoveCharacters: z.array(z.string()).nullable().optional(), SortRemoveWords: z.array(z.string()).nullable().optional(), MinResumePct: z.number().int().optional(), MaxResumePct: z.number().int().optional(), MinResumeDurationSeconds: z.number().int().optional(), MinAudiobookResume: z.number().int().optional(), MaxAudiobookResume: z.number().int().optional(), LibraryMonitorDelay: z.number().int().optional(), EnableDashboardResponseCaching: z.boolean().optional(), ImageSavingConvention: imageSavingConvention.optional(), MetadataOptions: z.array(metadataOptions).nullable().optional(), SkipDeserializationForBasicTypes: z.boolean().optional(), ServerName: z.string().nullable().optional(), BaseUrl: z.string().nullable().optional(), UICulture: z.string().nullable().optional(), SaveMetadataHidden: z.boolean().optional(), ContentTypes: z.array(nameValuePair).nullable().optional(), RemoteClientBitrateLimit: z.number().int().optional(), EnableFolderView: z.boolean().optional(), EnableGroupingIntoCollections: z.boolean().optional(), DisplaySpecialsWithinSeasons: z.boolean().optional(), LocalNetworkSubnets: z.array(z.string()).nullable().optional(), LocalNetworkAddresses: z.array(z.string()).nullable().optional(), CodecsUsed: z.array(z.string()).nullable().optional(), PluginRepositories: z.array(repositoryInfo).nullable().optional(), EnableExternalContentInSuggestions: z.boolean().optional(), RequireHttps: z.boolean().optional(), EnableNewOmdbSupport: z.boolean().optional(), RemoteIPFilter: z.array(z.string()).nullable().optional(), IsRemoteIPFilterBlacklist: z.boolean().optional(), ImageExtractionTimeoutMs: z.number().int().optional(), PathSubstitutions: z.array(pathSubstitution).nullable().optional(), EnableSimpleArtistDetection: z.boolean().optional(), UninstalledPlugins: z.array(z.string()).nullable().optional(), EnableSlowResponseWarning: z.boolean().optional(), SlowResponseThresholdMs: z.number().int().optional(), CorsHosts: z.array(z.string()).nullable().optional(), KnownProxies: z.array(z.string()).nullable().optional(), ActivityLogRetentionDays: z.number().int().nullable().optional(), LibraryScanFanoutConcurrency: z.number().int().optional(), LibraryMetadataRefreshConcurrency: z.number().int().optional(), RemoveOldPlugins: z.boolean().optional(), DisablePluginImages: z.boolean().optional()}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * Gets application configuration. * * GET /System/Configuration */ export const getApiSystemConfiguration = async (options?: GetApiSystemConfigurationOptions) => { const {baseUrl = "http://localhost", fetch: fetchFn = fetch, CustomAuthentication} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") if (CustomAuthentication !== undefined) headers.set("X-Emby-Authorization", CustomAuthentication) const url = `${baseUrl.replace(/\/+$/, '')}/System/Configuration${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "GET", headers}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(serverConfiguration, await res.json()) };