@delta-comic/plugin 2.1.0 → 3.0.0-next.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/global-B4SQiBzS.mjs +1446 -0
- package/dist/global-B4SQiBzS.mjs.map +1 -0
- package/dist/lib/index.d.mts +927 -0
- package/dist/lib/index.mjs +535 -0
- package/dist/lib/index.mjs.map +1 -0
- package/dist/native-CHH-Olpj.mjs +63 -0
- package/dist/native-CHH-Olpj.mjs.map +1 -0
- package/dist/rolldown-runtime-D7D4PA-g.mjs +13 -0
- package/dist/runtime-DQbAfFDr.mjs +663 -0
- package/dist/runtime-DQbAfFDr.mjs.map +1 -0
- package/dist/storage-DMKDlPzl.mjs +351 -0
- package/dist/storage-DMKDlPzl.mjs.map +1 -0
- package/dist/vite/index.d.mts +33 -0
- package/dist/vite/index.mjs +81 -0
- package/dist/vite/index.mjs.map +1 -0
- package/package.json +30 -37
- package/README.md +0 -42
- package/dist/core-BF7YwnuZ.js +0 -2
- package/dist/core-Czlf2w3A.js +0 -521
- package/dist/core-Czlf2w3A.js.map +0 -1
- package/dist/index.css +0 -3
- package/dist/index.js +0 -6764
- package/dist/index.js.map +0 -1
- package/dist/lib/config.d.ts +0 -71
- package/dist/lib/depends.d.ts +0 -7
- package/dist/lib/driver/booter.d.ts +0 -4
- package/dist/lib/driver/core.d.ts +0 -67
- package/dist/lib/driver/icon.d.ts +0 -3
- package/dist/lib/driver/index.d.ts +0 -4
- package/dist/lib/driver/init/booter/0_configSetter.d.ts +0 -8
- package/dist/lib/driver/init/booter/10_apiTest.d.ts +0 -9
- package/dist/lib/driver/init/booter/20_resourceTest.d.ts +0 -8
- package/dist/lib/driver/init/booter/30_boot.d.ts +0 -8
- package/dist/lib/driver/init/booter/40_auth.d.ts +0 -8
- package/dist/lib/driver/init/booter/50_otherProcess.d.ts +0 -8
- package/dist/lib/driver/init/booter/utils.d.ts +0 -3
- package/dist/lib/driver/init/installer/10_normalUrl.d.ts +0 -12
- package/dist/lib/driver/init/installer/20_local.d.ts +0 -12
- package/dist/lib/driver/init/installer/30_dev.d.ts +0 -12
- package/dist/lib/driver/init/installer/40_github.d.ts +0 -12
- package/dist/lib/driver/init/installer/9999_awesome.d.ts +0 -12
- package/dist/lib/driver/init/loader/1_userscript.d.ts +0 -11
- package/dist/lib/driver/init/loader/2_zip.d.ts +0 -11
- package/dist/lib/driver/init/utils.d.ts +0 -29
- package/dist/lib/driver/install.d.ts +0 -14
- package/dist/lib/driver/loader.d.ts +0 -5
- package/dist/lib/driver/store.d.ts +0 -37
- package/dist/lib/env/Inject.vue.d.ts +0 -18
- package/dist/lib/env/index.d.ts +0 -12
- package/dist/lib/global.d.ts +0 -26
- package/dist/lib/index.d.ts +0 -6
- package/dist/lib/plugin/api.d.ts +0 -8
- package/dist/lib/plugin/auth.d.ts +0 -15
- package/dist/lib/plugin/content.d.ts +0 -8
- package/dist/lib/plugin/index.d.ts +0 -58
- package/dist/lib/plugin/otherProgress.d.ts +0 -4
- package/dist/lib/plugin/resource.d.ts +0 -5
- package/dist/lib/plugin/search.d.ts +0 -75
- package/dist/lib/plugin/share.d.ts +0 -26
- package/dist/lib/plugin/subscribe.d.ts +0 -15
- package/dist/lib/plugin/user.d.ts +0 -47
- package/dist/pack.tgz +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-DQbAfFDr.mjs","names":["_TestPluginResource","pkg.version","configSetter","i18n","apiTest","resourceTest","boot","auth","otherProgress","zipLoader","devLoader","fallbackUrlInstaller","localInstaller","devInstaller","githubInstaller","awesomeInstaller"],"sources":["../lib/features/core/booters/0_configSetter.ts","../lib/features/core/booters/5_i18n.ts","../lib/features/core/booters/utils.ts","../lib/features/core/booters/10_apiTest.ts","../lib/features/core/booters/20_resourceTest.ts","../lib/features/core/booters/30_boot.ts","../lib/features/core/booters/40_auth.ts","../lib/plugin/otherProgress.ts","../lib/features/core/booters/50_otherProcess.ts","../lib/features/core/installers/downloadAsset.ts","../lib/features/core/installers/10_normalUrl.ts","../lib/features/core/installers/20_local.ts","../lib/features/core/installers/30_dev.ts","../package.json","../lib/features/core/installers/40_github.ts","../lib/features/core/installers/9999_awesome.ts","../lib/features/core/loaders/1_zip.ts","../lib/features/core/loaders/2_dev.ts","../lib/features/core/runtime.ts"],"sourcesContent":["import { logger } from '@delta-comic/logger'\nimport { uni } from '@delta-comic/model'\n\nimport { useConfig } from '@/config'\nimport { Global } from '@/global'\nimport { pluginMessageKey } from '@/i18n'\nimport type { PluginConfig } from '@/plugin'\n\nimport { PluginBooter, type PluginBooterSetMeta } from '../../../driver/extensionTypes'\n\nconst configSetterLogger = logger.scoped('plugin:config-setter')\n\nclass _ConfigSetter extends PluginBooter {\n public override name = pluginMessageKey('plugin.runtime.steps.presets.title')\n public override async call(cfg: PluginConfig, setMeta: PluginBooterSetMeta): Promise<any> {\n configSetterLogger.debug('registering plugin capabilities', { plugin: cfg.name })\n setMeta(pluginMessageKey('plugin.runtime.steps.presets.applying'))\n const { name: plugin, content, resource, search, user, subscribe, share } = cfg\n if (content)\n for (const [\n ct,\n { commentRow, contentPage, downloadProvider, itemCard, layout, itemTranslator },\n ] of Object.entries(content)) {\n if (layout) uni.content.ContentPage.layouts.set(ct, layout)\n if (itemCard) uni.item.Item.itemCards.set(ct, itemCard)\n if (contentPage) uni.content.ContentPage.contentPages.set(ct, contentPage)\n if (downloadProvider) uni.content.ContentPage.downloadProviders.set(ct, downloadProvider)\n if (commentRow) uni.comment.Comment.commentRow.set(ct, commentRow)\n if (itemTranslator) uni.item.Item.itemTranslator.set(ct, itemTranslator)\n }\n\n if (resource) {\n if (resource.types)\n for (const type of resource.types) uni.resource.Resource.fork.set([plugin, type.type], type)\n if (resource.process)\n for (const [name, fn] of Object.entries(resource.process))\n uni.resource.Resource.processInstances.set([plugin, name], fn)\n }\n if (search) {\n if (search.categories) for (const c of search.categories) Global.addCategories(plugin, c)\n if (search.tabbar) for (const c of search.tabbar) Global.addTabbar(plugin, c)\n if (search.hotPage) {\n for (const mlc of search.hotPage.mainListCard ?? []) Global.addMainList(plugin, mlc)\n for (const lb of search.hotPage.levelBoard ?? []) Global.addLevelboard(plugin, lb)\n for (const tb of search.hotPage.topButton ?? []) Global.addTopButton(plugin, tb)\n }\n if (search.barcode) {\n for (const barcode of search.barcode ?? []) Global.addBarcode(plugin, barcode)\n }\n if (search.hotSearch) {\n for (const provider of search.hotSearch) Global.addHotSearch(plugin, provider)\n }\n }\n if (user) {\n if (user.card) uni.user.User.userCards.set(plugin, user.card)\n if (user.edit) uni.user.User.userEditorBase.set(plugin, user.edit as any)\n if (user.userActions)\n for (const [type, value] of Object.entries(user.userActions))\n Global.userActions.set([plugin, type], value)\n if (user.authorIcon)\n for (const [key, value] of Object.entries(user.authorIcon))\n uni.item.Item.authorIcon.set([plugin, key], value as any)\n }\n if (subscribe) {\n for (const [key, value] of Object.entries(subscribe))\n Global.subscribes.set([plugin, key], value)\n }\n if (cfg.config) {\n for (const config of cfg.config) useConfig().$registerConfig(config)\n }\n if (share) {\n for (const v of share.initiative ?? []) Global.share.set([plugin, v.key], v)\n for (const v of share.tokenListen ?? []) Global.shareToken.set([plugin, v.key], v)\n }\n }\n}\nexport default new _ConfigSetter()","import { pluginI18n, pluginMessageKey } from '@/i18n'\nimport type { PluginConfig } from '@/plugin'\n\nimport { PluginBooter } from '../../../driver/extensionTypes'\n\nclass PluginI18nBooter extends PluginBooter {\n public override name = pluginMessageKey('plugin.runtime.steps.language.title')\n\n public override async call(cfg: PluginConfig): Promise<void> {\n if (cfg.i18n) pluginI18n.register(cfg.name, cfg.i18n)\n }\n}\n\nexport default new PluginI18nBooter()","import { logger } from '@delta-comic/logger'\nimport { isEmpty, sortBy } from 'es-toolkit/compat'\n\nimport type { PluginConfig } from '@/plugin'\n\nconst pluginProbeLogger = logger.scoped('plugin:probe')\n\nexport const testApi = async (cfg: NonNullable<PluginConfig['api']>[string]) => {\n const forks = await cfg.forks()\n return await test(forks, cfg.test)\n}\n\nexport const testResourceApi = (\n cfg: NonNullable<NonNullable<PluginConfig['resource']>['types']>[number],\n) => {\n const forks = cfg.urls\n return test(forks, cfg.test)\n}\n\nconst test = async (\n forks: string[],\n test: (url: string, signal: AbortSignal) => PromiseLike<any>,\n) => {\n if (isEmpty(forks)) throw new Error('[plugin test] no fork found')\n const record: [url: string, result: false | number][] = []\n const abortController = new AbortController()\n try {\n await Promise.all(\n forks.map(async (_fork, index) => {\n try {\n const begin = Date.now()\n const stopTimeout = setTimeout(() => {\n abortController.abort()\n }, 10000)\n await test(_fork, abortController.signal)\n clearTimeout(stopTimeout)\n const end = Date.now()\n const time = end - begin\n record.push([_fork, time])\n pluginProbeLogger.debug('plugin endpoint probe succeeded', { index, latencyMs: time })\n abortController.abort()\n } catch {\n record.push([_fork, false])\n pluginProbeLogger.debug('plugin endpoint probe failed', { index })\n }\n }),\n )\n } catch (err) {\n pluginProbeLogger.debug('plugin endpoint probe aborted', err)\n }\n const result = sortBy(\n record.filter(v => v[1] != false),\n v => v[1],\n )[0]\n pluginProbeLogger.debug('plugin endpoint probe completed', { found: Boolean(result) })\n if (!result) {\n return ['', false] as [string, false]\n }\n return result\n}","import { pluginI18n, pluginMessageKey } from '@/i18n'\nimport type { PluginConfig } from '@/plugin'\n\nimport { PluginBooter, type PluginBooterSetMeta } from '../../../driver/extensionTypes'\n\nimport { testApi } from './utils'\n\nexport type _TestPluginApiResult = Record<string, string | false | undefined>\n\nclass _TestPluginApi extends PluginBooter {\n public override name = pluginMessageKey('plugin.runtime.steps.apiTest.title')\n public override async call(\n cfg: PluginConfig,\n setMeta: PluginBooterSetMeta,\n env: Record<any, any>,\n ): Promise<any> {\n if (!cfg.api) return\n setMeta(pluginMessageKey('plugin.runtime.steps.tests.starting'))\n\n const namespaces = Object.keys(cfg.api)\n const results = await Promise.all(namespaces.map(namespace => testApi(cfg.api![namespace])))\n const displayResult = new Array<[namespace: string, time: number | false]>()\n const api: _TestPluginApiResult = {}\n namespaces.forEach((namespace, i) => {\n api[namespace] = results[i][0]\n displayResult.push([namespace, results[i][1]])\n })\n\n env.api = api\n\n if (Object.values(api).some(v => v == false)) {\n setMeta(pluginMessageKey('plugin.runtime.steps.tests.unreachable'))\n throw new Error('can not connect to server')\n }\n setMeta(\n pluginI18n.translate('plugin.runtime.steps.tests.complete', {\n results: displayResult.map(ent => `${ent[0]} -> ${ent[1]} ms`).join('\\n'),\n }),\n )\n }\n}\nexport default new _TestPluginApi()","import { uni } from '@delta-comic/model'\n\nimport { pluginI18n, pluginMessageKey } from '@/i18n'\nimport type { PluginConfig } from '@/plugin'\n\nimport { PluginBooter, type PluginBooterSetMeta } from '../../../driver/extensionTypes'\n\nimport { testResourceApi } from './utils'\n\nclass _TestPluginResource extends PluginBooter {\n public override name = pluginMessageKey('plugin.runtime.steps.resourceTest.title')\n public override async call(cfg: PluginConfig, setMeta: PluginBooterSetMeta): Promise<any> {\n if (!cfg.resource?.types?.length) return\n setMeta(pluginMessageKey('plugin.runtime.steps.tests.starting'))\n\n const types = cfg.resource.types.map(v => ({ type: v.type, val: v }))\n const results = await Promise.all(types.map(type => testResourceApi(type.val)))\n const displayResult = new Array<[type: (typeof types)[number], time: number | false]>()\n types.forEach((type, i) => {\n if (results[i][1])\n uni.resource.Resource.precedenceFork.set([cfg.name, type.type], results[i][0])\n displayResult.push([type, results[i][1]])\n })\n if (results.some(v => v[1] == false)) {\n setMeta(pluginMessageKey('plugin.runtime.steps.tests.unreachable'))\n throw new Error('[plugin test] can not connect to server')\n }\n setMeta(\n pluginI18n.translate('plugin.runtime.steps.tests.complete', {\n results: displayResult.map(ent => `${ent[0].type} -> ${ent[1]} ms`).join('\\n'),\n }),\n )\n }\n}\nexport default new _TestPluginResource()","import { declareDepType, provide } from '@/depends'\nimport { pluginMessageKey } from '@/i18n'\nimport type { PluginConfig } from '@/plugin'\n\nimport { PluginBooter } from '../../../driver/extensionTypes'\n\nclass _ExposeBootPlugin extends PluginBooter {\n public override name = pluginMessageKey('plugin.runtime.steps.customBoot.title')\n public override async call(cfg: PluginConfig, _: any, env: Record<any, any>): Promise<any> {\n if (!cfg.onBooted) return\n const expose = await cfg.onBooted({ api: env.api })\n if (expose) provide(declareDepType(cfg.name), expose)\n }\n}\nexport default new _ExposeBootPlugin()","import { logger } from '@delta-comic/logger'\nimport { createForm } from '@delta-comic/ui'\nimport { PageWebviewAuth } from '@delta-comic/utils'\nimport { Mutex } from 'es-toolkit'\nimport { NModal, useDialog } from 'naive-ui'\nimport { defineComponent, h, markRaw, ref } from 'vue'\n\nimport { usePluginStore } from '@/driver/store'\nimport { Global } from '@/global'\nimport { pluginI18n, pluginMessageKey } from '@/i18n'\nimport type { Auth, PluginConfig } from '@/plugin'\n\nimport { PluginBooter, type PluginBooterSetMeta } from '../../../driver/extensionTypes'\n\nconst pluginAuthLogger = logger.scoped('plugin:auth')\n\nconst authPopupMutex = new Mutex()\n\nclass _PluginAuth extends PluginBooter {\n public override name = pluginMessageKey('plugin.runtime.steps.auth.title')\n public override async call(cfg: PluginConfig, setMeta: PluginBooterSetMeta): Promise<any> {\n if (!cfg.auth) return\n const pluginStore = usePluginStore()\n let mutexAcquired = false\n try {\n const pluginName = pluginStore.$getI18nName(cfg.name)\n setMeta(pluginMessageKey('plugin.runtime.steps.auth.checking'))\n const isPass = await cfg.auth.passSelect()\n const waitMethod = Promise.withResolvers<'logIn' | 'signUp'>()\n pluginAuthLogger.info('plugin authentication state checked', {\n authenticated: Boolean(isPass),\n plugin: cfg.name,\n })\n await authPopupMutex.acquire()\n mutexAcquired = true\n setMeta(pluginMessageKey('plugin.runtime.steps.auth.waiting'))\n if (!isPass) {\n setMeta(pluginMessageKey('plugin.runtime.steps.auth.selecting'))\n void useDialog().create({\n type: 'default',\n positiveText: pluginI18n.translate('plugin.runtime.steps.auth.logIn'),\n negativeText: pluginI18n.translate('plugin.runtime.steps.auth.signUp'),\n closable: false,\n maskClosable: false,\n content: pluginI18n.translate('plugin.runtime.steps.auth.selectMethod'),\n title: pluginName,\n onNegativeClick() {\n waitMethod.resolve('signUp')\n },\n onPositiveClick() {\n waitMethod.resolve('logIn')\n },\n })\n } else {\n setMeta(pluginMessageKey('plugin.runtime.steps.auth.skipping'))\n waitMethod.resolve(isPass)\n }\n const method = await waitMethod.promise\n setMeta(pluginMessageKey('plugin.runtime.steps.auth.authenticating'))\n const by: Auth.Method = {\n async form(form) {\n const formInstance = createForm(form)\n Global.addGlobalNode(\n markRaw(\n defineComponent(() => {\n const show = ref(true)\n void formInstance.data.then(() => (show.value = false))\n return () =>\n h(\n NModal,\n { show: show.value, position: 'center', preset: 'dialog', title: pluginName },\n formInstance.comp,\n )\n }),\n ),\n cfg.name,\n )\n const data = await formInstance.data\n return data\n },\n async website<T>(\n url: string,\n injectCode: Auth.InjectCode,\n ): Promise<Auth.CallbackResult<T>> {\n const auth = new PageWebviewAuth<T>(url, injectCode, { title: pluginName })\n return auth.mount()\n },\n }\n if (method == 'logIn') {\n await cfg.auth.logIn(by)\n } else if (method == 'signUp') {\n await cfg.auth.signUp(by)\n }\n authPopupMutex.release()\n mutexAcquired = false\n setMeta(pluginMessageKey('plugin.runtime.steps.auth.success'))\n pluginAuthLogger.info('plugin authentication completed', { plugin: cfg.name })\n } catch (error: any) {\n if (mutexAcquired) authPopupMutex.release()\n setMeta(pluginI18n.translate('plugin.runtime.steps.auth.failure', { error: String(error) }))\n pluginAuthLogger.error('plugin authentication failed', { plugin: cfg.name }, error)\n throw error\n }\n }\n}\nexport default new _PluginAuth()","export interface Config {\n /** Run immediately with adjacent async steps; a trailing async group does not block loading. */\n async?: boolean\n call: (setDescription: (description: string) => void) => PromiseLike<any>\n name: string\n}\n\nexport interface OtherProgressRunnerOptions {\n onBackgroundError?: (error: AggregateError) => void\n setMeta: (meta: { description: string; name: string }) => void\n}\n\nconst runProgress = async (progress: Config, setMeta: OtherProgressRunnerOptions['setMeta']) => {\n setMeta({ name: progress.name, description: '' })\n await progress.call(description => setMeta({ name: progress.name, description }))\n}\n\nexport const runOtherProgress = async (\n progresses: readonly Config[],\n {\n setMeta,\n onBackgroundError = error => otherProgressLogger.error('background plugin steps failed', error),\n }: OtherProgressRunnerOptions,\n) => {\n let parallelGroup: Promise<void>[] = []\n\n for (const progress of progresses) {\n if (progress.async) {\n otherProgressLogger.debug('background plugin step started', { name: progress.name })\n parallelGroup.push(runProgress(progress, setMeta))\n continue\n }\n\n if (parallelGroup.length > 0) {\n await Promise.all(parallelGroup)\n parallelGroup = []\n }\n await runProgress(progress, setMeta)\n otherProgressLogger.debug('plugin step completed', { name: progress.name })\n }\n\n if (parallelGroup.length === 0) return\n void Promise.allSettled(parallelGroup).then(results => {\n const errors = results.flatMap(result => (result.status === 'rejected' ? [result.reason] : []))\n if (errors.length > 0) onBackgroundError(new AggregateError(errors, '后台插件步骤执行失败'))\n })\n}\nimport { logger } from '@delta-comic/logger'\n\nconst otherProgressLogger = logger.scoped('plugin:background-progress')","import { pluginMessageKey } from '@/i18n'\nimport type { PluginConfig } from '@/plugin'\nimport { runOtherProgress } from '@/plugin/otherProgress'\n\nimport { PluginBooter, type PluginBooterSetMeta } from '../../../driver/extensionTypes'\n\nclass _TestPluginResource extends PluginBooter {\n public override name = pluginMessageKey('plugin.runtime.steps.other.title')\n public override async call(cfg: PluginConfig, setMeta: PluginBooterSetMeta): Promise<any> {\n if (!cfg.otherProgress?.length) return\n\n await runOtherProgress(cfg.otherProgress, { setMeta })\n }\n}\nexport default new _TestPluginResource()","import { Downloader } from '@delta-comic/downloader'\nimport { logger } from '@delta-comic/logger'\nimport ky from 'ky'\n\nimport { isTauriRuntime } from '../../../driver/init/storage'\n\nexport const MAX_PLUGIN_ASSET_BYTES = 128 * 1024 * 1024\nexport const PLUGIN_DOWNLOAD_TIMEOUT_MS = 5 * 60 * 1000\n\nconst downloader = Downloader.get()\nconst assetLogger = logger.scoped('plugin:install:asset')\n\nexport interface DownloadInstallerAssetOptions {\n retry: number\n maxBytes?: number\n}\n\n/**\n * Managed downloads are intentionally bypassed here: installer assets are temporary and must\n * never appear in the user's download queue or leave a task record behind.\n */\nexport const downloadInstallerAsset = async (\n url: string,\n options: DownloadInstallerAssetOptions,\n): Promise<Blob> => {\n assetLogger.info('installer asset download started', {\n maxBytes: options.maxBytes ?? MAX_PLUGIN_ASSET_BYTES,\n runtime: isTauriRuntime() ? 'tauri' : 'web',\n })\n if (isTauriRuntime()) {\n const bytes = await downloader.downloadEphemeral(url, {\n maxBytes: options.maxBytes ?? MAX_PLUGIN_ASSET_BYTES,\n })\n assetLogger.info('installer asset download completed', { bytes: bytes.byteLength })\n return new Blob([bytes])\n }\n\n const blob = await ky\n .get(url, { retry: options.retry, timeout: PLUGIN_DOWNLOAD_TIMEOUT_MS })\n .blob()\n assetLogger.info('installer asset download completed', { bytes: blob.size })\n return blob\n}","import type { PluginArchiveDB } from '@delta-comic/db'\n\nimport { PluginInstaller, type PluginInstallerDescription } from '../../../driver/extensionTypes'\nimport { pluginMessageKey } from '../../../i18n'\n\nimport { downloadInstallerAsset } from './downloadAsset'\n\nconst getFileName = (input: string): string => {\n const url = new URL(input)\n const encoded = url.pathname.split('/').filter(Boolean).at(-1) ?? url.hostname\n let decoded = encoded\n try {\n decoded = decodeURIComponent(encoded)\n } catch {\n // Keep malformed percent escapes verbatim; URL parsing has already validated the input.\n }\n const withoutControlCharacters = [...decoded]\n .map(character => {\n const code = character.charCodeAt(0)\n return code < 32 || code === 127 ? '_' : character\n })\n .join('')\n return withoutControlCharacters.replace(/[<>:\"/\\\\|?*]/g, '_').trim() || 'us.js'\n}\n\nexport class _PluginInstallByFallbackUrl extends PluginInstaller {\n public override description: PluginInstallerDescription = {\n title: pluginMessageKey('plugin.install.methods.url.title'),\n description: pluginMessageKey('plugin.install.methods.url.description'),\n }\n public override name = 'fallbackUrl'\n private async installer(input: string): Promise<File> {\n const data = await downloadInstallerAsset(input, { retry: 3 })\n return new File([data], getFileName(input))\n }\n\n public override async download(input: string): Promise<File> {\n const file = await this.installer(input)\n return file\n }\n public override async update(pluginMeta: PluginArchiveDB.Archive): Promise<File> {\n const file = await this.installer(pluginMeta.installInput)\n return file\n }\n public override async fetchPluginMetaFile(input: string): Promise<File | string> {\n const file = await this.installer(input)\n return file\n }\n\n public override isMatched(input: string): boolean {\n return URL.canParse(input)\n }\n}\n\nexport default new _PluginInstallByFallbackUrl()","import type { PluginArchiveDB } from '@delta-comic/db'\n\nimport { PluginInstaller, type PluginInstallerDescription } from '../../../driver/extensionTypes'\nimport { readLocalFile } from '../../../driver/init/native'\nimport { isTauriRuntime } from '../../../driver/init/storage'\nimport { pluginMessageKey } from '../../../i18n'\n\nexport class _PluginInstallByLocal extends PluginInstaller {\n public override description: PluginInstallerDescription = {\n title: pluginMessageKey('plugin.install.methods.local.title'),\n description: pluginMessageKey('plugin.install.methods.local.description'),\n }\n public override name = 'local'\n private async installer(input: string): Promise<File> {\n const path = decodeURIComponent(input.replace(/^local:/, ''))\n return await readLocalFile(path)\n }\n public override async download(input: string): Promise<File> {\n const file = await this.installer(input)\n return file\n }\n public override async update(pluginMeta: PluginArchiveDB.Archive): Promise<File> {\n const file = await this.installer(pluginMeta.installInput)\n return file\n }\n public override async fetchPluginMetaFile(input: string): Promise<File | string> {\n const file = await this.installer(input)\n return file\n }\n public override isMatched(input: string): boolean {\n return isTauriRuntime() && input.startsWith('local:')\n }\n}\n\nexport default new _PluginInstallByLocal()","import type { PluginArchiveDB } from '@delta-comic/db'\nimport ky from 'ky'\n\nimport { PluginInstaller, type PluginInstallerDescription } from '../../../driver/extensionTypes'\nimport { prepareDevScript } from '../../../driver/init/native'\nimport { pluginMessageKey } from '../../../i18n'\n\nexport class _PluginInstallByDev extends PluginInstaller {\n public override description: PluginInstallerDescription = {\n title: pluginMessageKey('plugin.install.methods.development.title'),\n description: pluginMessageKey('plugin.install.methods.development.description'),\n }\n public override name = 'devUrl'\n private async installer(input: string): Promise<File> {\n const res = await ky\n .get(\n `http://${/:\\d+$/.test(input) ? input : input + ':6173'}/__vite-plugin-monkey.install.user.js?origin=http%3A%2F%2F${input}%3A6173`,\n )\n .text()\n const processed = await prepareDevScript(input, res)\n return new File([processed], 'us.js')\n }\n public override async download(input: string): Promise<File> {\n const file = await this.installer(input)\n return file\n }\n public override async update(pluginMeta: PluginArchiveDB.Archive): Promise<File> {\n const file = await this.installer(pluginMeta.installInput)\n return file\n }\n public override async fetchPluginMetaFile(input: string): Promise<File | string> {\n const file = await this.installer(input)\n return file\n }\n public override isMatched(input: string): boolean {\n return /^(((\\d+\\.?)+)|(localhost))(:\\d+)?$/.test(input)\n }\n}\n\nexport default new _PluginInstallByDev()","","import type { PluginArchiveDB } from '@delta-comic/db'\nimport { Octokit } from '@octokit/rest'\n\nimport pkg from '../../../../package.json'\nimport { useConfig } from '../../../config'\nimport { PluginInstaller, type PluginInstallerDescription } from '../../../driver/extensionTypes'\nimport { pluginI18n, pluginMessageKey } from '../../../i18n'\nimport { isPluginManifestCompatible, parsePluginManifest } from '../../../manifest'\n\nimport { downloadInstallerAsset } from './downloadAsset'\n\ntype GitHubRelease = Awaited<ReturnType<Octokit['rest']['repos']['listReleases']>>['data'][number]\n\ninterface GitHubInstallerConfig {\n githubToken: string\n receivePerReleaseUpdate: boolean\n}\n\nexport interface GitHubInstallerDependencies {\n coreVersion: string\n downloadAsset: (url: string) => Promise<Blob>\n getConfig: () => GitHubInstallerConfig\n listReleasePages: (\n owner: string,\n repo: string,\n token?: string,\n ) => AsyncIterable<readonly GitHubRelease[]>\n}\n\nexport const defaultGitHubInstallerDependencies: GitHubInstallerDependencies = {\n coreVersion: pkg.version,\n downloadAsset: async url => await downloadInstallerAsset(url, { retry: 2 }),\n getConfig: () => useConfig().$loadApp().data.value,\n async *listReleasePages(owner, repo, token) {\n const octokit = new Octokit({ auth: token })\n const pages = octokit.paginate.iterator(octokit.rest.repos.listReleases, {\n owner,\n per_page: 100,\n repo,\n })\n for await (const page of pages) yield page.data\n },\n}\n\nconst parseRepository = (input: string) => {\n const [owner, repo, ...rest] = input.replace(/^gh:/, '').split('/')\n if (!owner || !repo || rest.length > 0) {\n throw new Error(pluginI18n.translate('plugin.install.errors.invalidGitHub', { input }))\n }\n return { owner, repo }\n}\n\nconst decodeManifest = async (blob: Blob): Promise<PluginArchiveDB.Meta | undefined> => {\n try {\n return parsePluginManifest(JSON.parse(await blob.text()))\n } catch {\n return undefined\n }\n}\n\ninterface CompatibleRelease {\n manifest: Blob\n plugin: GitHubRelease['assets'][number]\n}\n\nexport class _PluginInstallByNormalUrl extends PluginInstaller {\n public override description: PluginInstallerDescription = {\n title: pluginMessageKey('plugin.install.methods.github.title'),\n description: pluginMessageKey('plugin.install.methods.github.description'),\n }\n public override name = 'github'\n\n public constructor(private readonly dependencies = defaultGitHubInstallerDependencies) {\n super()\n }\n\n private async findCompatibleRelease(input: string): Promise<CompatibleRelease> {\n const { githubToken, receivePerReleaseUpdate } = this.dependencies.getConfig()\n const { owner, repo } = parseRepository(input)\n const pages = this.dependencies.listReleasePages(owner, repo, githubToken || undefined)\n\n for await (const releases of pages) {\n for (const release of releases) {\n if (release.draft || (!receivePerReleaseUpdate && release.prerelease)) continue\n\n const manifestAsset = release.assets.find(asset => asset.name === 'manifest.json')\n const plugin = release.assets.find(asset => asset.name === 'plugin.zip')\n if (!manifestAsset || !plugin) continue\n\n const manifest = await this.dependencies.downloadAsset(manifestAsset.browser_download_url)\n const meta = await decodeManifest(manifest)\n if (!meta || !isPluginManifestCompatible(meta, this.dependencies.coreVersion)) {\n continue\n }\n return { manifest, plugin }\n }\n }\n\n throw new Error(\n pluginI18n.translate('plugin.install.errors.noCompatibleRelease', {\n version: this.dependencies.coreVersion,\n }),\n )\n }\n\n private async installer(input: string): Promise<File> {\n const { plugin } = await this.findCompatibleRelease(input)\n const data = await this.dependencies.downloadAsset(plugin.browser_download_url)\n return new File([data], plugin.name)\n }\n\n public override async download(input: string): Promise<File> {\n return await this.installer(input)\n }\n\n public override async update(pluginMeta: PluginArchiveDB.Archive): Promise<File> {\n return await this.installer(pluginMeta.installInput)\n }\n\n public override async fetchPluginMetaFile(input: string): Promise<File> {\n const { manifest } = await this.findCompatibleRelease(input)\n return new File([manifest], 'manifest.json')\n }\n\n public override isMatched(input: string): boolean {\n return input.startsWith('gh:') && input.split('/').length === 2\n }\n}\n\nexport default new _PluginInstallByNormalUrl()","import type { PluginArchiveDB } from '@delta-comic/db'\n\nimport { PluginInstaller, type PluginInstallerDescription } from '../../../driver/extensionTypes'\nimport { pluginI18n, pluginMessageKey } from '../../../i18n'\nimport {\n AwesomeRegistryClient,\n marketplaceDownloadToInstallInput,\n type AwesomePluginListing,\n} from '../../../marketplace'\n\nexport interface AwesomeInstallerRegistry {\n findListing(id: string): Promise<AwesomePluginListing>\n loadManifest(listing: AwesomePluginListing): Promise<PluginArchiveDB.Meta | undefined>\n}\n\nexport class _PluginInstallByAwesome extends PluginInstaller {\n public override description: PluginInstallerDescription = {\n title: pluginMessageKey('plugin.install.methods.marketplace.title'),\n description: pluginMessageKey('plugin.install.methods.marketplace.description'),\n }\n public override name = 'awesome'\n public constructor(\n private readonly registry: AwesomeInstallerRegistry = new AwesomeRegistryClient(),\n ) {\n super()\n }\n\n private async listing(input: string) {\n const match = /^ap:([A-Za-z0-9][A-Za-z0-9_-]{0,63})$/.exec(input)\n if (!match) {\n throw new Error(pluginI18n.translate('plugin.install.errors.invalidMarketplaceId', { input }))\n }\n return await this.registry.findListing(match[1])\n }\n\n private async installer(input: string): Promise<File | string> {\n const listing = await this.listing(input)\n return marketplaceDownloadToInstallInput(listing.download)\n }\n public override async download(input: string): Promise<File | string> {\n const file = await this.installer(input)\n return file\n }\n public override async update(pluginMeta: PluginArchiveDB.Archive): Promise<File | string> {\n const file = await this.installer(pluginMeta.installInput)\n return file\n }\n public override async fetchPluginMetaFile(input: string): Promise<File | string> {\n const listing = await this.listing(input)\n const manifest = await this.registry.loadManifest(listing)\n if (!manifest) return marketplaceDownloadToInstallInput(listing.download)\n return new File([JSON.stringify(manifest)], 'manifest.json', { type: 'application/json' })\n }\n public override isMatched(input: string): boolean {\n return /^ap:[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/.test(input)\n }\n}\n\nexport default new _PluginInstallByAwesome()","import type { PluginArchiveDB } from '@delta-comic/db'\nimport { logger } from '@delta-comic/logger'\nimport JSZip from 'jszip'\n\nimport { pluginI18n } from '@/i18n'\nimport type { PluginConfigFactory } from '@/plugin'\n\nimport { PluginLoader, type PluginLoaderInstallContext } from '../../../driver/extensionTypes'\nimport {\n createPluginAssetUrl,\n createPluginModuleUrl,\n installZipFile,\n isTauriRuntime,\n listPluginFiles,\n readPluginText,\n} from '../../../driver/init/storage'\n\nconst zipLoaderLogger = logger.scoped('plugin:loader:zip')\n\nexport const rewriteCssAssetUrls = async (\n cssPath: string,\n css: string,\n createAssetUrl: (path: string) => Promise<string>,\n) => {\n const pattern = /url\\(\\s*(?:([\"'])(.*?)\\1|([^)'\"\\s][^)]*?))\\s*\\)/g\n let output = ''\n let cursor = 0\n for (const match of css.matchAll(pattern)) {\n const index = match.index\n const rawUrl = (match[2] ?? match[3] ?? '').trim()\n if (!rawUrl || /^(?:#|blob:|data:|https?:|\\/\\/)/i.test(rawUrl)) continue\n const resolved = new URL(rawUrl, `https://plugin.local/${cssPath}`)\n const assetUrl = await createAssetUrl(resolved.pathname.slice(1))\n output += css.slice(cursor, index) + `url(\"${assetUrl}${resolved.search}${resolved.hash}\")`\n cursor = index + match[0].length\n }\n return output + css.slice(cursor)\n}\n\nexport default new (class extends PluginLoader {\n public override name = 'zip'\n public override async install(\n file: File,\n context?: PluginLoaderInstallContext,\n ): Promise<PluginArchiveDB.Meta> {\n zipLoaderLogger.info('zip plugin installation started', { bytes: file.size })\n return await installZipFile(file, progress => {\n const percent = progress.total > 0 ? (progress.current / progress.total) * 90 : 0\n context?.report({\n description: progress.path\n ? pluginI18n.translate('plugin.progress.extractingPath', { path: progress.path })\n : pluginI18n.translate('plugin.progress.extracting'),\n progress: percent,\n })\n })\n }\n public override canInstall(file: File): boolean {\n return file.name.endsWith('.zip')\n }\n\n public override async load(\n pluginMeta: PluginArchiveDB.Archive,\n ): Promise<PluginConfigFactory | undefined> {\n zipLoaderLogger.debug('zip plugin module load started', { plugin: pluginMeta.pluginName })\n if (!pluginMeta.meta.entry) throw new Error('not found entry')\n const files = await listPluginFiles(pluginMeta.pluginName)\n const javascriptFiles = files.filter(path => /\\.(?:js|mjs)$/i.test(path))\n if (!isTauriRuntime() && javascriptFiles.length > 1) {\n throw new Error(\n pluginI18n.translate('plugin.install.errors.webSingleFile', {\n files: javascriptFiles.join(', '),\n }),\n )\n }\n const src = await createPluginModuleUrl(pluginMeta.pluginName, pluginMeta.meta.entry.jsPath)\n const config = await import(/* @vite-ignore */ src).finally(() => {\n if (src.startsWith('blob:')) URL.revokeObjectURL(src)\n })\n const result = config.default as PluginConfigFactory | undefined\n\n if (!pluginMeta.meta.entry?.cssPath) return result\n const cssPath = pluginMeta.meta.entry.cssPath\n\n if (cssPath == 'auto') {\n const discovered = files.find(path => path.endsWith('.css'))\n if (!discovered) return result\n var filePath = discovered\n } else var filePath = cssPath\n\n const style = document.createElement('style')\n style.dataset.plugin = pluginMeta.pluginName\n style.textContent = await rewriteCssAssetUrls(\n filePath,\n await readPluginText(pluginMeta.pluginName, filePath),\n path => createPluginAssetUrl(pluginMeta.pluginName, path),\n )\n document.head.appendChild(style)\n zipLoaderLogger.debug('zip plugin stylesheet attached', { plugin: pluginMeta.pluginName })\n\n return result\n }\n public override async decodeMeta(file: File): Promise<PluginArchiveDB.Meta> {\n const zip = await JSZip.loadAsync(file)\n const manifest = zip.file('manifest.json')\n if (!manifest) throw new Error('plugin archive does not contain manifest.json')\n return JSON.parse(await manifest.async('text')) as PluginArchiveDB.Meta\n }\n\n public override isMetaFile(file: File): boolean {\n return file.name.endsWith('.zip') || file.name == 'manifest.json'\n }\n public override async decodeMetaFile(file: File): Promise<PluginArchiveDB.Meta | string> {\n if (file.name == 'manifest.json') return JSON.parse(await file.text())\n const jszip = new JSZip()\n const zip = await jszip.loadAsync(file)\n const mFile = await zip.filter(p => p == 'manifest.json')[0].async('text')\n return JSON.parse(mFile)\n }\n})()","import type { PluginArchiveDB } from '@delta-comic/db'\n\nimport type { PluginConfigFactory } from '@/plugin'\n\nimport { PluginLoader } from '../../../driver/extensionTypes'\nimport { decodeDevMeta } from '../../../driver/init/native'\nimport { installDevCode, readPluginText } from '../../../driver/init/storage'\n\nexport default new (class extends PluginLoader {\n public override name = 'dev'\n\n public override async install(file: File): Promise<PluginArchiveDB.Meta> {\n const code = await file.text()\n return await installDevCode(code)\n }\n public override canInstall(file: File): boolean {\n return file.name.endsWith('.js')\n }\n\n public override async load(\n pluginMeta: PluginArchiveDB.Archive,\n ): Promise<PluginConfigFactory | undefined> {\n const code = await readPluginText(pluginMeta.pluginName, 'us.js')\n const lastIndex = code.lastIndexOf(';') + 1\n\n const blob = new Blob([code.slice(0, lastIndex)], { type: 'text/javascript' })\n\n const url = URL.createObjectURL(blob)\n try {\n const mod: { default: any } = await import(/* @vite-ignore */ url)\n return mod.default as PluginConfigFactory | undefined\n } finally {\n URL.revokeObjectURL(url)\n }\n }\n public override async decodeMeta(file: File): Promise<PluginArchiveDB.Meta> {\n const code = await file.text()\n return await decodeDevMeta(code)\n }\n\n public override isMetaFile(file: File): boolean {\n return file.name.endsWith('.js')\n }\n public override async decodeMetaFile(file: File): Promise<PluginArchiveDB.Meta | string> {\n return this.decodeMeta(file)\n }\n})()","import { registerBooter, registerInstaller, registerLoader } from '../../driver/extensions'\n\nimport configSetter from './booters/0_configSetter'\nimport i18n from './booters/5_i18n'\nimport apiTest from './booters/10_apiTest'\nimport resourceTest from './booters/20_resourceTest'\nimport boot from './booters/30_boot'\nimport auth from './booters/40_auth'\nimport otherProgress from './booters/50_otherProcess'\nimport fallbackUrlInstaller from './installers/10_normalUrl'\nimport localInstaller from './installers/20_local'\nimport devInstaller from './installers/30_dev'\nimport githubInstaller from './installers/40_github'\nimport awesomeInstaller from './installers/9999_awesome'\nimport zipLoader from './loaders/1_zip'\nimport devLoader from './loaders/2_dev'\n\nlet registered = false\n\nexport const registerCoreRuntimeExtensions = () => {\n if (registered) return\n registered = true\n\n registerBooter(configSetter, { order: 0 })\n registerBooter(i18n, { order: 5 })\n registerBooter(apiTest, { order: 10 })\n registerBooter(resourceTest, { order: 20 })\n registerBooter(boot, { order: 30 })\n registerBooter(auth, { order: 40 })\n registerBooter(otherProgress, { order: 50 })\n\n registerLoader(zipLoader, { order: 1 })\n registerLoader(devLoader, { order: 2 })\n\n registerInstaller(fallbackUrlInstaller, { order: 10 })\n registerInstaller(localInstaller, { order: 20 })\n registerInstaller(devInstaller, { order: 30 })\n registerInstaller(githubInstaller, { order: 40 })\n registerInstaller(awesomeInstaller, { order: 9999 })\n}"],"mappings":"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"}
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
import { logger } from "@delta-comic/logger";
|
|
2
|
+
import { isTauri } from "@tauri-apps/api/core";
|
|
3
|
+
import JSZip from "jszip";
|
|
4
|
+
//#region lib/driver/init/storage.ts
|
|
5
|
+
const pluginStorageLogger = logger.scoped("plugin:storage");
|
|
6
|
+
const databaseName = "delta-comic-plugin-files";
|
|
7
|
+
const storeName = "files";
|
|
8
|
+
const memoryFiles = /* @__PURE__ */ new Map();
|
|
9
|
+
const pluginObjectUrls = /* @__PURE__ */ new Map();
|
|
10
|
+
const isTauriRuntime = isTauri;
|
|
11
|
+
const fileKey = (pluginId, path) => `${pluginId}/${path.replace(/^\/+/, "")}`;
|
|
12
|
+
const openFileDatabase = async () => {
|
|
13
|
+
if (!globalThis.indexedDB) return null;
|
|
14
|
+
return await new Promise((resolve, reject) => {
|
|
15
|
+
const request = indexedDB.open(databaseName, 1);
|
|
16
|
+
let settled = false;
|
|
17
|
+
request.onupgradeneeded = () => {
|
|
18
|
+
if (!request.result.objectStoreNames.contains(storeName)) request.result.createObjectStore(storeName);
|
|
19
|
+
};
|
|
20
|
+
request.onsuccess = () => {
|
|
21
|
+
if (settled) {
|
|
22
|
+
request.result.close();
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
settled = true;
|
|
26
|
+
resolve(request.result);
|
|
27
|
+
};
|
|
28
|
+
request.onerror = () => {
|
|
29
|
+
settled = true;
|
|
30
|
+
reject(request.error ?? /* @__PURE__ */ new Error("failed to open plugin file database"));
|
|
31
|
+
};
|
|
32
|
+
request.onblocked = () => {
|
|
33
|
+
settled = true;
|
|
34
|
+
reject(/* @__PURE__ */ new Error("opening plugin file database was blocked"));
|
|
35
|
+
};
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
const getTransactionError = (transaction, fallback) => transaction.error ?? new Error(fallback);
|
|
39
|
+
const withStore = async (mode, run) => {
|
|
40
|
+
let database = null;
|
|
41
|
+
try {
|
|
42
|
+
database = await openFileDatabase();
|
|
43
|
+
if (!database) return void 0;
|
|
44
|
+
return await new Promise((resolve, reject) => {
|
|
45
|
+
let transaction;
|
|
46
|
+
let request;
|
|
47
|
+
let requestCompleted = false;
|
|
48
|
+
let requestResult;
|
|
49
|
+
let requestError = null;
|
|
50
|
+
let settled = false;
|
|
51
|
+
const close = () => {
|
|
52
|
+
database?.close();
|
|
53
|
+
database = null;
|
|
54
|
+
};
|
|
55
|
+
const fail = (error) => {
|
|
56
|
+
if (settled) return;
|
|
57
|
+
settled = true;
|
|
58
|
+
close();
|
|
59
|
+
reject(error);
|
|
60
|
+
};
|
|
61
|
+
try {
|
|
62
|
+
transaction = database.transaction(storeName, mode);
|
|
63
|
+
request = run(transaction.objectStore(storeName));
|
|
64
|
+
} catch (error) {
|
|
65
|
+
fail(error);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
request.onsuccess = () => {
|
|
69
|
+
requestCompleted = true;
|
|
70
|
+
requestResult = request.result;
|
|
71
|
+
};
|
|
72
|
+
request.onerror = () => {
|
|
73
|
+
requestError = request.error;
|
|
74
|
+
};
|
|
75
|
+
transaction.oncomplete = () => {
|
|
76
|
+
if (settled) return;
|
|
77
|
+
settled = true;
|
|
78
|
+
close();
|
|
79
|
+
if (!requestCompleted) {
|
|
80
|
+
reject(requestError ?? /* @__PURE__ */ new Error("IndexedDB request did not complete"));
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
resolve(requestResult);
|
|
84
|
+
};
|
|
85
|
+
transaction.onerror = () => {
|
|
86
|
+
fail(requestError ?? getTransactionError(transaction, "IndexedDB transaction failed"));
|
|
87
|
+
};
|
|
88
|
+
transaction.onabort = () => {
|
|
89
|
+
fail(requestError ?? getTransactionError(transaction, "IndexedDB transaction aborted"));
|
|
90
|
+
};
|
|
91
|
+
});
|
|
92
|
+
} catch (error) {
|
|
93
|
+
database?.close();
|
|
94
|
+
pluginStorageLogger.warn("IndexedDB operation failed; using memory fallback", error);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
const replaceMemoryPlugin = (pluginId, files) => {
|
|
99
|
+
const prefix = `${pluginId}/`;
|
|
100
|
+
for (const key of memoryFiles.keys()) if (key.startsWith(prefix)) memoryFiles.delete(key);
|
|
101
|
+
for (const [path, bytes] of files) memoryFiles.set(fileKey(pluginId, path), bytes);
|
|
102
|
+
};
|
|
103
|
+
const replacePersistentPlugin = async (pluginId, files) => {
|
|
104
|
+
const database = await openFileDatabase();
|
|
105
|
+
if (!database) return false;
|
|
106
|
+
return await new Promise((resolve, reject) => {
|
|
107
|
+
let transaction;
|
|
108
|
+
let settled = false;
|
|
109
|
+
let operationError;
|
|
110
|
+
const close = () => database.close();
|
|
111
|
+
const fail = (error) => {
|
|
112
|
+
if (settled) return;
|
|
113
|
+
settled = true;
|
|
114
|
+
close();
|
|
115
|
+
reject(error);
|
|
116
|
+
};
|
|
117
|
+
try {
|
|
118
|
+
transaction = database.transaction(storeName, "readwrite");
|
|
119
|
+
} catch (error) {
|
|
120
|
+
close();
|
|
121
|
+
reject(error);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
transaction.oncomplete = () => {
|
|
125
|
+
if (settled) return;
|
|
126
|
+
settled = true;
|
|
127
|
+
close();
|
|
128
|
+
resolve(true);
|
|
129
|
+
};
|
|
130
|
+
transaction.onerror = () => {
|
|
131
|
+
fail(operationError ?? getTransactionError(transaction, "plugin update transaction failed"));
|
|
132
|
+
};
|
|
133
|
+
transaction.onabort = () => {
|
|
134
|
+
fail(operationError ?? getTransactionError(transaction, "plugin update transaction aborted"));
|
|
135
|
+
};
|
|
136
|
+
try {
|
|
137
|
+
const store = transaction.objectStore(storeName);
|
|
138
|
+
const prefix = `${pluginId}/`;
|
|
139
|
+
const cursorRequest = store.openKeyCursor();
|
|
140
|
+
cursorRequest.onsuccess = () => {
|
|
141
|
+
try {
|
|
142
|
+
const cursor = cursorRequest.result;
|
|
143
|
+
if (cursor) {
|
|
144
|
+
if (String(cursor.key).startsWith(prefix)) store.delete(cursor.key);
|
|
145
|
+
cursor.continue();
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
for (const [path, bytes] of files) store.put(bytes, fileKey(pluginId, path));
|
|
149
|
+
} catch (error) {
|
|
150
|
+
operationError = error;
|
|
151
|
+
transaction.abort();
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
cursorRequest.onerror = () => {
|
|
155
|
+
operationError = cursorRequest.error;
|
|
156
|
+
};
|
|
157
|
+
} catch (error) {
|
|
158
|
+
operationError = error;
|
|
159
|
+
try {
|
|
160
|
+
transaction.abort();
|
|
161
|
+
} catch {
|
|
162
|
+
fail(error);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
};
|
|
167
|
+
const replaceWebPlugin = async (pluginId, files) => {
|
|
168
|
+
const persisted = await replacePersistentPlugin(pluginId, files);
|
|
169
|
+
replaceMemoryPlugin(pluginId, files);
|
|
170
|
+
return persisted;
|
|
171
|
+
};
|
|
172
|
+
const readWebFile = async (pluginId, path) => {
|
|
173
|
+
const key = fileKey(pluginId, path);
|
|
174
|
+
const stored = await withStore("readonly", (store) => store.get(key));
|
|
175
|
+
if (stored) return stored instanceof Uint8Array ? stored : new Uint8Array(stored);
|
|
176
|
+
const memory = memoryFiles.get(key);
|
|
177
|
+
if (memory) return memory;
|
|
178
|
+
throw new Error(`plugin file not found: ${pluginId}/${path}`);
|
|
179
|
+
};
|
|
180
|
+
const getTauriPluginPath = async (pluginId, path) => {
|
|
181
|
+
const { appLocalDataDir, join } = await import("@tauri-apps/api/path");
|
|
182
|
+
return await join(await appLocalDataDir(), "plugin", pluginId, path);
|
|
183
|
+
};
|
|
184
|
+
const readPluginFile = async (pluginId, path) => {
|
|
185
|
+
if (!isTauriRuntime()) return await readWebFile(pluginId, path);
|
|
186
|
+
return await (await import("@tauri-apps/plugin-fs")).readFile(await getTauriPluginPath(pluginId, path));
|
|
187
|
+
};
|
|
188
|
+
const readPluginText = async (pluginId, path) => new TextDecoder().decode(await readPluginFile(pluginId, path));
|
|
189
|
+
const mimeTypeFor = (path) => {
|
|
190
|
+
return {
|
|
191
|
+
avif: "image/avif",
|
|
192
|
+
gif: "image/gif",
|
|
193
|
+
jpeg: "image/jpeg",
|
|
194
|
+
jpg: "image/jpeg",
|
|
195
|
+
png: "image/png",
|
|
196
|
+
svg: "image/svg+xml",
|
|
197
|
+
webp: "image/webp",
|
|
198
|
+
woff: "font/woff",
|
|
199
|
+
woff2: "font/woff2"
|
|
200
|
+
}[path.split(".").at(-1)?.toLowerCase() ?? ""] ?? "application/octet-stream";
|
|
201
|
+
};
|
|
202
|
+
const listPluginFiles = async (pluginId) => {
|
|
203
|
+
if (isTauriRuntime()) return (await (await import("@tauri-apps/plugin-fs")).readDir(await getTauriPluginPath(pluginId, ""))).filter((entry) => entry.isFile).map((entry) => entry.name);
|
|
204
|
+
const prefix = `${pluginId}/`;
|
|
205
|
+
const keys = new Set([...memoryFiles.keys()].filter((key) => key.startsWith(prefix)).map((key) => key.slice(prefix.length)));
|
|
206
|
+
const storedKeys = await withStore("readonly", (store) => store.getAllKeys());
|
|
207
|
+
for (const key of storedKeys ?? []) {
|
|
208
|
+
const value = String(key);
|
|
209
|
+
if (value.startsWith(prefix)) keys.add(value.slice(prefix.length));
|
|
210
|
+
}
|
|
211
|
+
return [...keys];
|
|
212
|
+
};
|
|
213
|
+
const createPluginModuleUrl = async (pluginId, path) => {
|
|
214
|
+
if (isTauriRuntime()) {
|
|
215
|
+
const { convertFileSrc } = await import("@tauri-apps/api/core");
|
|
216
|
+
return convertFileSrc(await getTauriPluginPath(pluginId, path));
|
|
217
|
+
}
|
|
218
|
+
const bytes = await readPluginFile(pluginId, path);
|
|
219
|
+
const buffer = bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
|
|
220
|
+
return URL.createObjectURL(new Blob([buffer], { type: "text/javascript" }));
|
|
221
|
+
};
|
|
222
|
+
const createPluginAssetUrl = async (pluginId, path) => {
|
|
223
|
+
if (isTauriRuntime()) {
|
|
224
|
+
const { convertFileSrc } = await import("@tauri-apps/api/core");
|
|
225
|
+
return convertFileSrc(await getTauriPluginPath(pluginId, path));
|
|
226
|
+
}
|
|
227
|
+
const bytes = await readPluginFile(pluginId, path);
|
|
228
|
+
const buffer = bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
|
|
229
|
+
const url = URL.createObjectURL(new Blob([buffer], { type: mimeTypeFor(path) }));
|
|
230
|
+
const urls = pluginObjectUrls.get(pluginId) ?? /* @__PURE__ */ new Set();
|
|
231
|
+
urls.add(url);
|
|
232
|
+
pluginObjectUrls.set(pluginId, urls);
|
|
233
|
+
return url;
|
|
234
|
+
};
|
|
235
|
+
const releasePluginObjectUrls = (pluginId) => {
|
|
236
|
+
const urls = pluginObjectUrls.get(pluginId);
|
|
237
|
+
if (!urls) return;
|
|
238
|
+
for (const url of urls) URL.revokeObjectURL(url);
|
|
239
|
+
pluginObjectUrls.delete(pluginId);
|
|
240
|
+
};
|
|
241
|
+
const removePluginFiles = async (pluginId) => {
|
|
242
|
+
pluginStorageLogger.info("removing plugin files", { plugin: pluginId });
|
|
243
|
+
releasePluginObjectUrls(pluginId);
|
|
244
|
+
if (!isTauriRuntime()) {
|
|
245
|
+
await replaceWebPlugin(pluginId, /* @__PURE__ */ new Map());
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
const fs = await import("@tauri-apps/plugin-fs");
|
|
249
|
+
const root = await getTauriPluginPath(pluginId, "");
|
|
250
|
+
if (await fs.exists(root)) await fs.remove(root, { recursive: true });
|
|
251
|
+
pluginStorageLogger.info("plugin files removed", { plugin: pluginId });
|
|
252
|
+
};
|
|
253
|
+
const decodeDevMetaFromCode = (code) => {
|
|
254
|
+
const markerIndex = code.indexOf("@description");
|
|
255
|
+
if (markerIndex < 0) throw new Error("not found @description metadata");
|
|
256
|
+
const [json] = code.slice(markerIndex + 12).trimStart().split(/\r?\n/, 1);
|
|
257
|
+
return JSON.parse(json.trim());
|
|
258
|
+
};
|
|
259
|
+
const assertPluginId = (meta) => {
|
|
260
|
+
const id = meta.name?.id;
|
|
261
|
+
if (!id || id === "." || id === ".." || /[\\/]/.test(id)) throw new Error(`invalid plugin id: ${id}`);
|
|
262
|
+
return id;
|
|
263
|
+
};
|
|
264
|
+
const hex = (bytes) => [...bytes].map((value) => value.toString(16).padStart(2, "0")).join("");
|
|
265
|
+
const digestPluginBytes = async (bytes) => {
|
|
266
|
+
try {
|
|
267
|
+
const [{ default: loadBlake3 }, { default: wasmUrl }] = await Promise.all([import("blake3-wasm/browser-async.js"), import("blake3-wasm/dist/wasm/web/blake3_js_bg.wasm?url")]);
|
|
268
|
+
const { hash } = await loadBlake3(wasmUrl);
|
|
269
|
+
return {
|
|
270
|
+
algorithm: "blake3",
|
|
271
|
+
digest: hash(bytes).toString("hex")
|
|
272
|
+
};
|
|
273
|
+
} catch (error) {
|
|
274
|
+
pluginStorageLogger.warn("BLAKE3 unavailable; using SHA-256 fallback", error);
|
|
275
|
+
const digest = await globalThis.crypto.subtle.digest("SHA-256", Uint8Array.from(bytes).buffer);
|
|
276
|
+
return {
|
|
277
|
+
algorithm: "sha256",
|
|
278
|
+
digest: hex(new Uint8Array(digest))
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
const withIntegrity = async (meta, bytes) => ({
|
|
283
|
+
...meta,
|
|
284
|
+
integrity: await digestPluginBytes(bytes)
|
|
285
|
+
});
|
|
286
|
+
const installDevCode = async (code) => {
|
|
287
|
+
pluginStorageLogger.info("development plugin installation started");
|
|
288
|
+
const bytes = new TextEncoder().encode(code);
|
|
289
|
+
const meta = await withIntegrity(decodeDevMetaFromCode(code), bytes);
|
|
290
|
+
if (isTauriRuntime()) {
|
|
291
|
+
const { invoke } = await import("@tauri-apps/api/core");
|
|
292
|
+
return {
|
|
293
|
+
...await invoke("plugin:plugin|install_dev", { code }),
|
|
294
|
+
integrity: meta.integrity
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
const pluginId = assertPluginId(meta);
|
|
298
|
+
await replaceWebPlugin(pluginId, /* @__PURE__ */ new Map([["us.js", bytes]]));
|
|
299
|
+
pluginStorageLogger.info("development plugin installation completed", { plugin: pluginId });
|
|
300
|
+
return meta;
|
|
301
|
+
};
|
|
302
|
+
const installZipFile = async (file, onProgress) => {
|
|
303
|
+
pluginStorageLogger.info("plugin archive extraction started", { bytes: file.size });
|
|
304
|
+
const archiveBytes = new Uint8Array(await file.arrayBuffer());
|
|
305
|
+
if (isTauriRuntime()) {
|
|
306
|
+
const { createNativeOperationId, installZip, writeNativeTempFile } = await import("./native-CHH-Olpj.mjs").then((n) => n.n);
|
|
307
|
+
const nativeMeta = await installZip(await writeNativeTempFile(file), createNativeOperationId(), onProgress);
|
|
308
|
+
return await withIntegrity(nativeMeta, archiveBytes);
|
|
309
|
+
}
|
|
310
|
+
const zip = await JSZip.loadAsync(archiveBytes);
|
|
311
|
+
const manifest = zip.file("manifest.json");
|
|
312
|
+
if (!manifest) throw new Error("plugin archive does not contain manifest.json");
|
|
313
|
+
const meta = await withIntegrity(JSON.parse(await manifest.async("text")), archiveBytes);
|
|
314
|
+
const pluginId = assertPluginId(meta);
|
|
315
|
+
const entries = Object.values(zip.files).filter((entry) => !entry.dir);
|
|
316
|
+
const stagedFiles = /* @__PURE__ */ new Map();
|
|
317
|
+
onProgress?.({
|
|
318
|
+
current: 0,
|
|
319
|
+
opId: "",
|
|
320
|
+
phase: "start",
|
|
321
|
+
total: entries.length
|
|
322
|
+
});
|
|
323
|
+
for (const [index, entry] of entries.entries()) {
|
|
324
|
+
const normalized = entry.name.replaceAll("\\", "/");
|
|
325
|
+
if (normalized.startsWith("/") || normalized.split("/").includes("..")) continue;
|
|
326
|
+
stagedFiles.set(normalized, await entry.async("uint8array"));
|
|
327
|
+
onProgress?.({
|
|
328
|
+
current: index + 1,
|
|
329
|
+
opId: "",
|
|
330
|
+
path: normalized,
|
|
331
|
+
phase: "extract",
|
|
332
|
+
total: entries.length
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
await replaceWebPlugin(pluginId, stagedFiles);
|
|
336
|
+
onProgress?.({
|
|
337
|
+
current: entries.length,
|
|
338
|
+
opId: "",
|
|
339
|
+
phase: "done",
|
|
340
|
+
total: entries.length
|
|
341
|
+
});
|
|
342
|
+
pluginStorageLogger.info("plugin archive extraction completed", {
|
|
343
|
+
fileCount: stagedFiles.size,
|
|
344
|
+
plugin: pluginId
|
|
345
|
+
});
|
|
346
|
+
return meta;
|
|
347
|
+
};
|
|
348
|
+
//#endregion
|
|
349
|
+
export { installZipFile as a, readPluginText as c, installDevCode as i, releasePluginObjectUrls as l, createPluginModuleUrl as n, isTauriRuntime as o, decodeDevMetaFromCode as r, listPluginFiles as s, createPluginAssetUrl as t, removePluginFiles as u };
|
|
350
|
+
|
|
351
|
+
//# sourceMappingURL=storage-DMKDlPzl.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-DMKDlPzl.mjs","names":[],"sources":["../lib/driver/init/storage.ts"],"sourcesContent":["import type { PluginArchiveDB } from '@delta-comic/db'\nimport { logger } from '@delta-comic/logger'\nimport { isTauri } from '@tauri-apps/api/core'\nimport JSZip from 'jszip'\n\nimport type { NativeInstallProgress } from './native'\n\nconst pluginStorageLogger = logger.scoped('plugin:storage')\n\nconst databaseName = 'delta-comic-plugin-files'\nconst storeName = 'files'\nconst memoryFiles = new Map<string, Uint8Array>()\nconst pluginObjectUrls = new Map<string, Set<string>>()\n\nexport const isTauriRuntime = isTauri\n\nconst fileKey = (pluginId: string, path: string) => `${pluginId}/${path.replace(/^\\/+/, '')}`\n\nconst openFileDatabase = async (): Promise<IDBDatabase | null> => {\n if (!globalThis.indexedDB) return null\n return await new Promise((resolve, reject) => {\n const request = indexedDB.open(databaseName, 1)\n let settled = false\n request.onupgradeneeded = () => {\n if (!request.result.objectStoreNames.contains(storeName)) {\n request.result.createObjectStore(storeName)\n }\n }\n request.onsuccess = () => {\n if (settled) {\n request.result.close()\n return\n }\n settled = true\n resolve(request.result)\n }\n request.onerror = () => {\n settled = true\n reject(request.error ?? new Error('failed to open plugin file database'))\n }\n request.onblocked = () => {\n settled = true\n reject(new Error('opening plugin file database was blocked'))\n }\n })\n}\n\nconst getTransactionError = (transaction: IDBTransaction, fallback: string) =>\n transaction.error ?? new Error(fallback)\n\nconst withStore = async <T>(\n mode: IDBTransactionMode,\n run: (store: IDBObjectStore) => IDBRequest<T>,\n): Promise<T | undefined> => {\n let database: IDBDatabase | null = null\n try {\n database = await openFileDatabase()\n if (!database) return undefined\n return await new Promise<T>((resolve, reject) => {\n let transaction: IDBTransaction\n let request: IDBRequest<T>\n let requestCompleted = false\n let requestResult: T\n let requestError: DOMException | null = null\n let settled = false\n\n const close = () => {\n database?.close()\n database = null\n }\n const fail = (error: unknown) => {\n if (settled) return\n settled = true\n close()\n reject(error)\n }\n\n try {\n transaction = database!.transaction(storeName, mode)\n request = run(transaction.objectStore(storeName))\n } catch (error) {\n fail(error)\n return\n }\n\n request.onsuccess = () => {\n requestCompleted = true\n requestResult = request.result\n }\n request.onerror = () => {\n requestError = request.error\n }\n transaction.oncomplete = () => {\n if (settled) return\n settled = true\n close()\n if (!requestCompleted) {\n reject(requestError ?? new Error('IndexedDB request did not complete'))\n return\n }\n resolve(requestResult)\n }\n transaction.onerror = () => {\n fail(requestError ?? getTransactionError(transaction, 'IndexedDB transaction failed'))\n }\n transaction.onabort = () => {\n fail(requestError ?? getTransactionError(transaction, 'IndexedDB transaction aborted'))\n }\n })\n } catch (error) {\n database?.close()\n pluginStorageLogger.warn('IndexedDB operation failed; using memory fallback', error)\n return undefined\n }\n}\n\nconst replaceMemoryPlugin = (pluginId: string, files: ReadonlyMap<string, Uint8Array>) => {\n const prefix = `${pluginId}/`\n for (const key of memoryFiles.keys()) {\n if (key.startsWith(prefix)) memoryFiles.delete(key)\n }\n for (const [path, bytes] of files) {\n memoryFiles.set(fileKey(pluginId, path), bytes)\n }\n}\n\nconst replacePersistentPlugin = async (\n pluginId: string,\n files: ReadonlyMap<string, Uint8Array>,\n): Promise<boolean> => {\n const database = await openFileDatabase()\n if (!database) return false\n\n return await new Promise<boolean>((resolve, reject) => {\n let transaction: IDBTransaction\n let settled = false\n let operationError: unknown\n\n const close = () => database.close()\n const fail = (error: unknown) => {\n if (settled) return\n settled = true\n close()\n reject(error)\n }\n\n try {\n transaction = database.transaction(storeName, 'readwrite')\n } catch (error) {\n close()\n reject(error)\n return\n }\n\n transaction.oncomplete = () => {\n if (settled) return\n settled = true\n close()\n resolve(true)\n }\n transaction.onerror = () => {\n fail(operationError ?? getTransactionError(transaction, 'plugin update transaction failed'))\n }\n transaction.onabort = () => {\n fail(operationError ?? getTransactionError(transaction, 'plugin update transaction aborted'))\n }\n\n try {\n const store = transaction.objectStore(storeName)\n const prefix = `${pluginId}/`\n const cursorRequest = store.openKeyCursor()\n cursorRequest.onsuccess = () => {\n try {\n const cursor = cursorRequest.result\n if (cursor) {\n if (String(cursor.key).startsWith(prefix)) store.delete(cursor.key)\n cursor.continue()\n return\n }\n for (const [path, bytes] of files) {\n store.put(bytes, fileKey(pluginId, path))\n }\n } catch (error) {\n operationError = error\n transaction.abort()\n }\n }\n cursorRequest.onerror = () => {\n operationError = cursorRequest.error\n }\n } catch (error) {\n operationError = error\n try {\n transaction.abort()\n } catch {\n fail(error)\n }\n }\n })\n}\n\nconst replaceWebPlugin = async (pluginId: string, files: ReadonlyMap<string, Uint8Array>) => {\n const persisted = await replacePersistentPlugin(pluginId, files)\n // Every byte is prepared before this synchronous switch. If IndexedDB is available,\n // its transaction has committed at this point; otherwise memory is the storage backend.\n replaceMemoryPlugin(pluginId, files)\n return persisted\n}\n\nconst readWebFile = async (pluginId: string, path: string): Promise<Uint8Array> => {\n const key = fileKey(pluginId, path)\n const stored = await withStore<ArrayBuffer | Uint8Array>('readonly', store => store.get(key))\n if (stored) return stored instanceof Uint8Array ? stored : new Uint8Array(stored)\n const memory = memoryFiles.get(key)\n if (memory) return memory\n throw new Error(`plugin file not found: ${pluginId}/${path}`)\n}\n\nconst getTauriPluginPath = async (pluginId: string, path: string) => {\n const { appLocalDataDir, join } = await import('@tauri-apps/api/path')\n return await join(await appLocalDataDir(), 'plugin', pluginId, path)\n}\n\nexport const readPluginFile = async (pluginId: string, path: string): Promise<Uint8Array> => {\n if (!isTauriRuntime()) return await readWebFile(pluginId, path)\n const fs = await import('@tauri-apps/plugin-fs')\n return await fs.readFile(await getTauriPluginPath(pluginId, path))\n}\n\nexport const readPluginText = async (pluginId: string, path: string) =>\n new TextDecoder().decode(await readPluginFile(pluginId, path))\n\nconst mimeTypeFor = (path: string) => {\n const extension = path.split('.').at(-1)?.toLowerCase()\n return (\n {\n avif: 'image/avif',\n gif: 'image/gif',\n jpeg: 'image/jpeg',\n jpg: 'image/jpeg',\n png: 'image/png',\n svg: 'image/svg+xml',\n webp: 'image/webp',\n woff: 'font/woff',\n woff2: 'font/woff2',\n }[extension ?? ''] ?? 'application/octet-stream'\n )\n}\n\nexport const listPluginFiles = async (pluginId: string): Promise<string[]> => {\n if (isTauriRuntime()) {\n const fs = await import('@tauri-apps/plugin-fs')\n const entries = await fs.readDir(await getTauriPluginPath(pluginId, ''))\n return entries.filter(entry => entry.isFile).map(entry => entry.name)\n }\n const prefix = `${pluginId}/`\n const keys = new Set(\n [...memoryFiles.keys()]\n .filter(key => key.startsWith(prefix))\n .map(key => key.slice(prefix.length)),\n )\n const storedKeys = await withStore<IDBValidKey[]>('readonly', store => store.getAllKeys())\n for (const key of storedKeys ?? []) {\n const value = String(key)\n if (value.startsWith(prefix)) keys.add(value.slice(prefix.length))\n }\n return [...keys]\n}\n\nexport const createPluginModuleUrl = async (pluginId: string, path: string) => {\n if (isTauriRuntime()) {\n const { convertFileSrc } = await import('@tauri-apps/api/core')\n return convertFileSrc(await getTauriPluginPath(pluginId, path))\n }\n const bytes = await readPluginFile(pluginId, path)\n const buffer = bytes.buffer.slice(\n bytes.byteOffset,\n bytes.byteOffset + bytes.byteLength,\n ) as ArrayBuffer\n return URL.createObjectURL(new Blob([buffer], { type: 'text/javascript' }))\n}\n\nexport const createPluginAssetUrl = async (pluginId: string, path: string) => {\n if (isTauriRuntime()) {\n const { convertFileSrc } = await import('@tauri-apps/api/core')\n return convertFileSrc(await getTauriPluginPath(pluginId, path))\n }\n const bytes = await readPluginFile(pluginId, path)\n const buffer = bytes.buffer.slice(\n bytes.byteOffset,\n bytes.byteOffset + bytes.byteLength,\n ) as ArrayBuffer\n const url = URL.createObjectURL(new Blob([buffer], { type: mimeTypeFor(path) }))\n const urls = pluginObjectUrls.get(pluginId) ?? new Set<string>()\n urls.add(url)\n pluginObjectUrls.set(pluginId, urls)\n return url\n}\n\nexport const releasePluginObjectUrls = (pluginId: string) => {\n const urls = pluginObjectUrls.get(pluginId)\n if (!urls) return\n for (const url of urls) URL.revokeObjectURL(url)\n pluginObjectUrls.delete(pluginId)\n}\n\nexport const removePluginFiles = async (pluginId: string) => {\n pluginStorageLogger.info('removing plugin files', { plugin: pluginId })\n releasePluginObjectUrls(pluginId)\n if (!isTauriRuntime()) {\n await replaceWebPlugin(pluginId, new Map())\n return\n }\n const fs = await import('@tauri-apps/plugin-fs')\n const root = await getTauriPluginPath(pluginId, '')\n if (await fs.exists(root)) await fs.remove(root, { recursive: true })\n pluginStorageLogger.info('plugin files removed', { plugin: pluginId })\n}\n\nexport const decodeDevMetaFromCode = (code: string): PluginArchiveDB.Meta => {\n const marker = '@description'\n const markerIndex = code.indexOf(marker)\n if (markerIndex < 0) throw new Error('not found @description metadata')\n const rest = code.slice(markerIndex + marker.length).trimStart()\n const [json] = rest.split(/\\r?\\n/, 1)\n return JSON.parse(json.trim()) as PluginArchiveDB.Meta\n}\n\nconst assertPluginId = (meta: PluginArchiveDB.Meta) => {\n const id = meta.name?.id\n if (!id || id === '.' || id === '..' || /[\\\\/]/.test(id)) {\n throw new Error(`invalid plugin id: ${id}`)\n }\n return id\n}\n\nconst hex = (bytes: Uint8Array) =>\n [...bytes].map(value => value.toString(16).padStart(2, '0')).join('')\n\nexport const digestPluginBytes = async (\n bytes: Uint8Array,\n): Promise<NonNullable<PluginArchiveDB.Meta['integrity']>> => {\n try {\n const [{ default: loadBlake3 }, { default: wasmUrl }] = await Promise.all([\n import('blake3-wasm/browser-async'),\n import('blake3-wasm/dist/wasm/web/blake3_js_bg.wasm?url'),\n ])\n const { hash } = await loadBlake3(wasmUrl)\n return { algorithm: 'blake3', digest: hash(bytes).toString('hex') }\n } catch (error) {\n pluginStorageLogger.warn('BLAKE3 unavailable; using SHA-256 fallback', error)\n const digest = await globalThis.crypto.subtle.digest('SHA-256', Uint8Array.from(bytes).buffer)\n return { algorithm: 'sha256', digest: hex(new Uint8Array(digest)) }\n }\n}\n\nconst withIntegrity = async (meta: PluginArchiveDB.Meta, bytes: Uint8Array) => ({\n ...meta,\n integrity: await digestPluginBytes(bytes),\n})\n\nexport const installDevCode = async (code: string): Promise<PluginArchiveDB.Meta> => {\n pluginStorageLogger.info('development plugin installation started')\n const bytes = new TextEncoder().encode(code)\n const meta = await withIntegrity(decodeDevMetaFromCode(code), bytes)\n if (isTauriRuntime()) {\n const { invoke } = await import('@tauri-apps/api/core')\n const nativeMeta = await invoke<PluginArchiveDB.Meta>('plugin:plugin|install_dev', { code })\n return { ...nativeMeta, integrity: meta.integrity }\n }\n const pluginId = assertPluginId(meta)\n await replaceWebPlugin(pluginId, new Map([['us.js', bytes]]))\n pluginStorageLogger.info('development plugin installation completed', { plugin: pluginId })\n return meta\n}\n\nexport const installZipFile = async (\n file: File,\n onProgress?: (progress: NativeInstallProgress) => void,\n): Promise<PluginArchiveDB.Meta> => {\n pluginStorageLogger.info('plugin archive extraction started', { bytes: file.size })\n const archiveBytes = new Uint8Array(await file.arrayBuffer())\n if (isTauriRuntime()) {\n const { createNativeOperationId, installZip, writeNativeTempFile } = await import('./native')\n const nativeMeta = await installZip(\n await writeNativeTempFile(file),\n createNativeOperationId(),\n onProgress,\n )\n return await withIntegrity(nativeMeta, archiveBytes)\n }\n\n const zip = await JSZip.loadAsync(archiveBytes)\n const manifest = zip.file('manifest.json')\n if (!manifest) throw new Error('plugin archive does not contain manifest.json')\n const meta = await withIntegrity(\n JSON.parse(await manifest.async('text')) as PluginArchiveDB.Meta,\n archiveBytes,\n )\n const pluginId = assertPluginId(meta)\n const entries = Object.values(zip.files).filter(entry => !entry.dir)\n const stagedFiles = new Map<string, Uint8Array>()\n onProgress?.({ current: 0, opId: '', phase: 'start', total: entries.length })\n for (const [index, entry] of entries.entries()) {\n const normalized = entry.name.replaceAll('\\\\', '/')\n if (normalized.startsWith('/') || normalized.split('/').includes('..')) continue\n stagedFiles.set(normalized, await entry.async('uint8array'))\n onProgress?.({\n current: index + 1,\n opId: '',\n path: normalized,\n phase: 'extract',\n total: entries.length,\n })\n }\n await replaceWebPlugin(pluginId, stagedFiles)\n onProgress?.({ current: entries.length, opId: '', phase: 'done', total: entries.length })\n pluginStorageLogger.info('plugin archive extraction completed', {\n fileCount: stagedFiles.size,\n plugin: pluginId,\n })\n return meta\n}"],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { PluginArchiveDB } from "@delta-comic/db";
|
|
2
|
+
|
|
3
|
+
//#region vite/index.d.ts
|
|
4
|
+
type DeltaComicBundleAssetSource = string | Uint8Array;
|
|
5
|
+
type DeltaComicPluginContext = {
|
|
6
|
+
emitFile(file: {
|
|
7
|
+
type: 'asset';
|
|
8
|
+
fileName: string;
|
|
9
|
+
source: DeltaComicBundleAssetSource;
|
|
10
|
+
}): unknown;
|
|
11
|
+
};
|
|
12
|
+
type DeltaComicBundleItem = {
|
|
13
|
+
type: 'asset';
|
|
14
|
+
fileName: string;
|
|
15
|
+
source: DeltaComicBundleAssetSource;
|
|
16
|
+
} | {
|
|
17
|
+
type: 'chunk';
|
|
18
|
+
fileName: string;
|
|
19
|
+
code: string;
|
|
20
|
+
};
|
|
21
|
+
type DeltaComicOutputBundle = Record<string, DeltaComicBundleItem>;
|
|
22
|
+
type DeltaComicPlugin = {
|
|
23
|
+
name: string;
|
|
24
|
+
enforce?: 'post' | 'pre';
|
|
25
|
+
config?(config: unknown): unknown;
|
|
26
|
+
resolveId?(source: string): void;
|
|
27
|
+
generateBundle?(this: DeltaComicPluginContext, options: unknown, bundle: DeltaComicOutputBundle): void | Promise<void>;
|
|
28
|
+
};
|
|
29
|
+
type DeltaComicPluginOption = DeltaComicPlugin | DeltaComicPluginOption[] | false | null | undefined;
|
|
30
|
+
declare const deltaComic: (meta: PluginArchiveDB.Meta, command: 'build' | 'serve') => DeltaComicPluginOption[];
|
|
31
|
+
//#endregion
|
|
32
|
+
export { deltaComic };
|
|
33
|
+
//# sourceMappingURL=index.d.mts.map
|