Skip to content

Releases: ReelVault/sdk

v1.3.0

Choose a tag to compare

@gaam24 gaam24 released this 12 Oct 22:12

Full Changelog: v1.2.2...v1.3.0

Features

  • Completed plays in admin analytics — AdminAnalyticsSchema (GET /admin/analytics) carries completedPlaysCount, the plays in totalPlaysCount that finished their title. totalPlaysCount now also counts interrupted playback sessions that reached the minimum play time (server setting system.analytics.minPlaySeconds).
  • Trickplay regeneration for several titles — admin.regenerateTrickplay({ scope: "titles", ids, force }) queues the previews of up to 50 titles as one operation. TrickplayRegenerateRequestSchema accepts that shape next to the single library, title and season scopes.
  • Live session log link — admin.getLiveSessionLogUrl(sessionId) returns the URL of a playback session's log archive (ZIP), served by GET /admin/live-activity/:sessionId/log.
  • Library scan progress — libraries.getScanProgress() for GET /libraries/scan-progress lists the queued and running library scans with progressPercent, which is null while a scan discovers files. LibraryScanProgressResponseSchema / LibraryScanProgressResponse describe the reply.
  • Scan findings can be ignored — libraries.getScanFindings(libraryId, status) lists the active or ignored findings and returns counts for both. libraries.setScanFindingIgnored(libraryId, { filePath, ignored }) ignores a finding until it is restored, and a rescan keeps it ignored. libraries.getScanFindingCandidates(libraryId, filePath) searches the providers for the title parsed from the file name; a scan never runs that search. The ScanFinding* schemas and types describe the replies.
  • Playback view limits — PlaybackViewResponse.effectivePreferences reports the bitrate cap that applies to the profile's streams (the lower of the profile and server caps, null when neither is set) and the HDR mode.
  • Overwrite locked fields on rematch — the rematch body accepts overwriteLocked (default false). Locked fields keep their values unless it is true.
  • Notify every administrator — host.notifications.createForAdmins({ type, title, message?, data?, link? }) sends one notification to each administrator. Each recipient counts against the plugin's daily notification limit.
  • Code block for plugin UI — a code schema node shows read-only, preformatted text that keeps its line breaks and scrolls. Plugin authors get the code() helper from @reelvault/sdk/ui/schema.
  • Profile bitrate cap — ProfilePreferences, UpdateProfilePreferences and ProfilePreferenceDefaults carry maxStreamingBitrateKbps (0 = no limit, up to 50 000 kbps).
  • Profile HDR mode — ProfilePreferences, UpdateProfilePreferences and ProfilePreferenceDefaults carry hdrMode (auto or toneMapToSdr). auto keeps passing HDR through where the device supports it; toneMapToSdr always converts HDR sources to SDR.
  • Backup code count — auth.getBackupCodesStatus() for GET /auth/two-factor/backup-codes, typed by TwoFactorBackupCodesStatusSchema / TwoFactorBackupCodesStatus ({ remaining: number | null }).
  • Rating badge preference — hideRatingOverlay in ProfilePreferencesSchema, UpdateProfilePreferencesSchema and ProfilePreferenceDefaultsSchema. It hides the rating badge on poster cards and defaults to off.
  • Catalog statuses — metadata.getStatuses() for GET /metadata/statuses, with MetadataStatusesResponseSchema / MetadataStatusesResponse ({ statuses: string[] }).
  • Dry runs for log cleanup and trickplay deletes — admin.cleanupLogs(retentionDays, { dryRun }) and admin.deleteTrickplayMany(ids, { dryRun }). TrickplayDeleteResult and the log cleanup result carry dryRun; a dry run reports what would be removed and removes nothing.
  • Worker history purge dry run — PurgeWorkerHistoryOptions.dryRun and PurgeWorkerHistoryResponse.dryRun; a dry run reports the counts a purge would delete and removes nothing.
  • Cancel an update — admin.cancelUpdate(target) for POST /admin/update/cancel. AdminUpdateCancelResponseSchema / AdminUpdateCancelResponse describe the reply, and an update history entry may now have status cancelled.
  • Forced server updates — admin.installUpdate(target, { force }) and admin.rollbackUpdate(target, { force }). A server install or rollback is refused with update.blocked_active_streams while streams play, unless force is set.
  • Plugin configuration reset, export and import — admin.resetPluginConfig(id, { keys? }), admin.exportPluginConfig(id) and admin.importPluginConfig(id, file) with ResetPluginConfigBodySchema and PluginConfigExportSchema. Exports never contain secret fields.
  • Catalog reports unavailable repositories — admin.getPluginCatalog() returns { plugins, unavailableRepositories }; each unavailable repository has its repositoryId, repositoryName and an errorCode. PluginCatalogResultSchema / PluginCatalogResult describe it.
  • Bulk plugin state and version pinning — admin.setPluginsEnabled({ enabled, pluginIds }) returns an outcome per plugin; admin.setPluginPinned(id, pinned); PluginAdminStatus.pinned.
  • Refuse a plugin's CSP sources — PluginAdminStatus.cspDisabled and admin.setPluginCsp(id, enabled) for PUT /admin/plugins/:id/csp.
  • Setting metadata — SystemSettingItemView reports the unit of a number setting and restartRequired for settings that take effect only after a restart.
  • Server capabilities — ServerCapabilitiesSchema / ServerCapabilities and reelvault.capabilities.get() for the public GET /capabilities endpoint (trickplay, downloads).
  • Profile PIN status — profiles.getPinStatus(id) returns { hasPin } for the owner's profile (ProfilePinStatusSchema / ProfilePinStatus), so settings can offer removing the PIN without ever receiving it.
  • Filtered marker list — media.getAllMarkers({ type, source, q, limit }) narrows the admin marker list on the server; MediaMarkerFiltersSchema / MediaMarkerFilters describe the filters. Calls without arguments behave as before.
  • Subtitle text search — SubtitleFiltersSchema takes q (up to 200 characters); subtitles.getAll({ q }) matches it against the label, the language and the media file id.
  • Safer database restore — admin.restoreDatabase(fileName, { force? }) sends the optional force, and AdminDatabaseRestoreResponse carries preRestoreBackup, the copy taken just before the swap.
  • Audit filter options — admin.getAuditOptions() returns the resource types in the audit log and the administrators who wrote entries (AdminAuditOptionsSchema / AdminAuditOptions), for the filter dropdowns. name is null when the account no longer exists.
  • User list filters — admin.getUsers({ role, status }) narrows the account list by role (admin or user) and by status (active or blocked), next to the search.
  • Download title link — DownloadJob.metadataId (nullable, also on AdminDownloadJobSchema) names the title the download's media file belongs to, so a download can link to its title.
  • Watchlist auto-removal preference — profile preferences gain watchlistAutoRemoveWatched (boolean, off by default). When it is on, a title leaves the watchlist once the profile has watched it. The field is part of ProfilePreferencesSchema, UpdateProfilePreferencesSchema and ProfilePreferenceDefaultsSchema.
  • Watch state controls — me.resetPlaybackProgress(mediaFileId, { scope }) takes scope: file resets only that file, title (the default) resets every file of its title. me.setWatchStateBulk({ mediaFileIds, watched }) marks up to 500 files watched or unwatched in one call (WatchStateBulkSchema / WatchStateBulk, WatchStateScopeSchema / WatchStateScope).
  • Update history and environment — admin.getUpdateHistory({ page, limit }) pages through the installs and rollbacks (AdminUpdateHistoryPageSchema / AdminUpdateHistoryPage). AdminUpdateStatus.environment reports the container engine (docker, podman or none), whether the server runs without root and whether systemd manages it as a user or system unit (AdminUpdateEnvironmentSchema).
  • Subtitle extractability — Subtitle.extractable is false for image-based embedded tracks (PGS, VobSub), which cannot be served as text.
  • Migration status — admin.getDatabaseMigrations() returns DatabaseMigrationStatus (total, applied, pending, latest, migrations).
  • Paginated marker list — media.getAllMarkers(query) takes page next to limit and returns PaginatedResponse<MediaMarker> (data, total, totalPages) instead of a bare array.
  • Mark all read by type — notifications.markAllRead(type?) marks only the notifications of the given type when one is passed.
  • Live activity capacity — AdminLiveActivityResponse gains capacity ({ limit, active }): the server-wide stream limit and the number of slots in use.
  • Remove notifications — notifications.delete(id) and notifications.deleteMany(ids) (up to 200) remove notifications from the caller's list and return { deleted }.
  • Trickplay regeneration by scope — admin.regenerateTrickplay({ scope, id, force? }) (scope is library, title or season) returns TrickplayRegenerationQueued ({ operationId?, matching, enqueued, remaining }); admin.getTrickplayRegenerationReport(operationId) returns TrickplayRegenerationReport with the generated, budget-skipped, other-skipped, failed, cancelled and unfinished counts.
  • Worker schedule pause, job retry and watchdog state — admin.setWorkerScheduleEnabled(workerId, enabled) returns WorkerScheduleState ({ workerId, enabled, nextRunAt }); admin.retryWorkerJob(jobId) returns WorkerRetryResponse ({ success, jobId } of the new job); admin.getWorkerWatchdog() returns WorkerWatchdogState ...
Read more

v1.2.2

Choose a tag to compare

@gaam24 gaam24 released this 08 Oct 13:44

Full Changelog: v1.2.1...v1.2.2

Features

  • Plugin-declared CSP sources — PluginManifest.csp (typed via PluginCspDirectives, allowlisted by PLUGIN_CSP_DIRECTIVES) lets a plugin declare extra img-src / media-src / connect-src / font-src / frame-src sources for host UI content. The server validates them and appends them to the web UI Content-Security-Policy, so provider artwork and embedded players load without widening script or style execution.

v1.2.1

Choose a tag to compare

@gaam24 gaam24 released this 08 Oct 00:58

Full Changelog: v1.2.0...v1.2.1

Features

  • Trickplay storage stats — getTrickplayStats() and TrickplayStatsSchema now carry storageBytes and storageBudgetBytes, so clients can show how much of the core artifact budget (system.artifacts.coreMaxStorageGb) is used.

Fixes

  • Dashboard view library contract — AdminDashboardViewResponseSchema.libraries now uses LibraryWithRelationsSchema (paths + file/size stats). The previous base LibrarySchema stripped relations during response validation, which crashed the admin libraries page that reads the dashboard-seeded cache.

v1.2.0

Choose a tag to compare

@gaam24 gaam24 released this 06 Oct 17:29

Full Changelog: v1.1.1...v1.2.0

Highlights

  • Richer playback contracts — hydrated watchlist items, batch playback suggestions, and a full-row playback view.
  • One-call admin dashboard — getDashboardView() returns stats, libraries, worker operations, audit feed, error logs and update status together.
  • Explicit pagination contracts — one flat envelope everywhere (admin pages included) and a clear split between offset and cursor endpoints.
  • Codes, not text — remote-access checks now return stable machine codes with params; clients own all translated text.
  • Typed request/response schemas for playback progress, stream prefs, heartbeat, watchlist statuses and the worker status filter.

Breaking changes

  1. Admin page envelopes are flat
    • Before: { data, pagination: { total, page, limit, totalPages } }
    • After: { page, limit, total, totalPages, data }
    • Affects AdminUsersPage, AdminLogsPage, AdminAuditPage and the audit/logs fields inside AdminDashboardViewResponse.
    • Empty pages now report totalPages: 0.
  2. Cursor contracts split from offset contracts
    • PaginationQuery is offset-only (page, limit); cursor endpoints use the new CursorPaginationQuery (cursor).
    • PaginatedResponse<T> no longer carries nextCursor; cursor endpoints return the new CursorPaginatedResponse<T>.
    • me.getWatchedHistory now accepts CursorPaginationQuery; the dead perPage parameter is gone.
    • Cursor mode applies to GET /v1/metadata and GET /v1/me/watched-history only.
  3. Remote-access checks return codes
    • RemoteAccessCheck changed from { id, ok, title, detail } to { id, ok, code, params? }.
    • Translate remote_access.* codes on the client (website already does).

New in 1.2.0

  • BatchSmartPlayResponseSchema + me.getPlaybackSuggestionsBatch(metadataIds) (up to 50 ids) — suggestion + watchlist flag per card in one request.
  • HydratedWatchlistItemSchema + me.getWatchlist({ hydrate: true }) overload — each item carries its full metadata card.
  • PlaybackViewResponseSchema.mediaFile is now the complete row (no projection) so the player UI works on the strict shape.
  • worker:progress realtime event (throttled to at most one message per second per running job).
  • AdminDashboardViewResponseSchema + admin.getDashboardView() — replaces six parallel dashboard requests.
  • New typed schemas: UpdatePlaybackProgressSchema, StreamPrefsSchema, HeartbeatBodySchema, WatchlistStatusSchema, WatchlistStatusesResponseSchema, WorkerStatusFilterSchema.
  • PaginationMetaSchema is now the single source for every page envelope.

Upgrade notes

  • Bump @reelvault/sdk to ^1.2.0.
  • Update consumers that read .pagination on admin endpoints (see breaking change 1) and translate remote-access codes (breaking change 3).
  • Everything else is wire-compatible; the remaining changes are schema deduplication and type exports.

v1.1.1

Choose a tag to compare

@gaam24 gaam24 released this 30 Sep 21:44

Full Changelog: v1.1.0...v1.1.1

v1.1.0

Choose a tag to compare

@gaam24 gaam24 released this 30 Sep 16:35

Full Changelog: v1.0.3...v1.1.0

v1.0.3

Choose a tag to compare

@gaam24 gaam24 released this 28 Sep 01:02

Full Changelog: v1.0.2...v1.0.3

v1.0.2

Choose a tag to compare

@gaam24 gaam24 released this 28 Sep 00:12

Full Changelog: v1.0.1...v1.0.2

v1.0.1

Choose a tag to compare

@gaam24 gaam24 released this 23 Sep 18:18

Full Changelog: v1.0.0...v1.0.1

v1.0.0

Choose a tag to compare

@gaam24 gaam24 released this 23 Sep 18:03

Initial SDK release