revenge-bundle-next/src/plugins/preinit/api.json-storage/index.ts

83 lines
2.7 KiB
TypeScript
Raw Normal View History

import * as jsonStorage from '@revenge-mod/json-storage'
import { getJsonStorage } from '@revenge-mod/json-storage'
import { exists, rm } from '@revenge-mod/modules/native/fs'
import {
InternalPluginFlags,
PluginFlags,
feat!: new repo system + versioning system support + bug fixes BREAKING CHANGES: - New versioning system: Allowing any amount of number segments, with prerelease support. - Any number of segments is supported: 1, 1.0, 1.0.0, 1.0.0.0, ... - Prerelease labels are compared "digit-run", similar to Debian. - Plugins must specify a version. - User-facing plugins should use CalVer. API plugins should use SemVer. Revenge APIs use SemVer while the new `discord` dependency parses the Discord version string directly. - Dependency is now a Map, with support for version ranges and optional. Suggested URL is removed. (See new repo system) - Plugins will now have to declare a dependency on `revenge.api` (Revenge API version) and `discord` (Discord version). - Manifest now requires a format version (currently `1`) New APIs: - lib/plugins/utils: Utilities to format versioning Features: - New repo system: Repository design is inspired by Linux package repositories. - Repos host manifest, versions, channels, download URL/size, and hash for multiple plugins. - New dependency system: Plugins are versioned, and shouldn't break when updates come. Plugins can now declare dependency on supported Discord/Revenge API versions, so they won't break with auto-updates. Dependencies can be optional, but dependency on `revenge.api` and `discord` must be required. Dependents are soft-disabled when dependencies don't satisfy. Once satisfied, the plugin can start again. - All updates for running plugins REQUIRE a reload to prevent stale linking issues. Both native and JS-side. - Update checking is handled entirely by JS. But the native-side still handles installation, indexing, and verification. - Local indexes are updated against remote indexes. Dependency checking always uses local indexes. - Users can add custom repositories and custom their priority order. URL is the identity. - Plugins can now have custom data URI icons instead of being restricted to React Native app assets. - External plugin installs require UI confirmation before installing. - Pending Update and Pending Reload filters in Plugins page. - Ability to browse external plugins in repositories. Official repository will be added soon. Fixes/Refactor: - Refactored Plugin-related settings to a separate "Plugin Settings" plugin. - Masonry layout fixes in landscape. - Updated plugins now show "reload to apply" toast instead. - Removed dead code.
2026-07-25 23:35:23 +07:00
registerInternalPlugin,
} from '@revenge-mod/plugins/_'
import { pluginStorageDirFor } from '@revenge-mod/plugins/constants'
import { defineLazyProperty } from '@revenge-mod/utils/object'
import type { JsonStorage, JsonStorageOptions } from '@revenge-mod/json-storage'
import type { InitPluginApi, Plugin } from '@revenge-mod/plugins/types'
import type { AnyObject } from '@revenge-mod/utils/types'
type PluginJsonStorageOptions = JsonStorageOptions & {
file?: string
}
const storageOptions = new WeakMap<Plugin<any, any>, PluginJsonStorageOptions>()
feat!: new repo system + versioning system support + bug fixes BREAKING CHANGES: - New versioning system: Allowing any amount of number segments, with prerelease support. - Any number of segments is supported: 1, 1.0, 1.0.0, 1.0.0.0, ... - Prerelease labels are compared "digit-run", similar to Debian. - Plugins must specify a version. - User-facing plugins should use CalVer. API plugins should use SemVer. Revenge APIs use SemVer while the new `discord` dependency parses the Discord version string directly. - Dependency is now a Map, with support for version ranges and optional. Suggested URL is removed. (See new repo system) - Plugins will now have to declare a dependency on `revenge.api` (Revenge API version) and `discord` (Discord version). - Manifest now requires a format version (currently `1`) New APIs: - lib/plugins/utils: Utilities to format versioning Features: - New repo system: Repository design is inspired by Linux package repositories. - Repos host manifest, versions, channels, download URL/size, and hash for multiple plugins. - New dependency system: Plugins are versioned, and shouldn't break when updates come. Plugins can now declare dependency on supported Discord/Revenge API versions, so they won't break with auto-updates. Dependencies can be optional, but dependency on `revenge.api` and `discord` must be required. Dependents are soft-disabled when dependencies don't satisfy. Once satisfied, the plugin can start again. - All updates for running plugins REQUIRE a reload to prevent stale linking issues. Both native and JS-side. - Update checking is handled entirely by JS. But the native-side still handles installation, indexing, and verification. - Local indexes are updated against remote indexes. Dependency checking always uses local indexes. - Users can add custom repositories and custom their priority order. URL is the identity. - Plugins can now have custom data URI icons instead of being restricted to React Native app assets. - External plugin installs require UI confirmation before installing. - Pending Update and Pending Reload filters in Plugins page. - Ability to browse external plugins in repositories. Official repository will be added soon. Fixes/Refactor: - Refactored Plugin-related settings to a separate "Plugin Settings" plugin. - Masonry layout fixes in landscape. - Updated plugins now show "reload to apply" toast instead. - Removed dead code.
2026-07-25 23:35:23 +07:00
registerInternalPlugin(
{
id: 'revenge.api.json-storage',
name: 'JSON Storage API',
description: '@revenge-mod/json-storage API for plugins.',
author: 'Revenge',
icon: 'PollsIcon',
},
{
preInit({ decorate, unscoped }) {
unscoped.jsonStorage = jsonStorage
decorate((plugin, { jsonStorage }) => {
if (jsonStorage) storageOptions.set(plugin, jsonStorage)
})
},
init({ decorate }) {
const makePluginStorage = (
plugin: Plugin,
opts?: PluginJsonStorageOptions,
) =>
getJsonStorage(
jsonStorage.pluginStoragePathFor(
plugin.manifest.id,
opts?.file,
),
opts,
)
decorate(plugin => {
const opts = storageOptions.get(plugin)
if (opts?.load)
plugin.api.jsonStorage = makePluginStorage(plugin, opts)
else
defineLazyProperty(plugin.api, 'jsonStorage', () =>
makePluginStorage(plugin, opts),
)
})
},
},
PluginFlags.Enabled,
// biome-ignore format: Don't format this
InternalPluginFlags.Internal |
InternalPluginFlags.Essential |
InternalPluginFlags.API,
)
export async function deleteJsonStorageForPlugin(plugin: Plugin<any, any>) {
const path = pluginStorageDirFor(plugin.manifest.id)
if (await exists(path)) await rm(path)
const api = plugin.api as
| InitPluginApi<{ jsonStorage: AnyObject }>
| undefined
// Only update already initialized storages
const storage = Object.getOwnPropertyDescriptor(api, 'jsonStorage')
?.value as JsonStorage<AnyObject> | undefined
await storage?.get()
}