diff --git a/.agents/skills/release-note-writer/SKILL.md b/.agents/skills/release-note-writer/SKILL.md index 213135f03..0a940b680 100644 --- a/.agents/skills/release-note-writer/SKILL.md +++ b/.agents/skills/release-note-writer/SKILL.md @@ -56,7 +56,7 @@ Use `To developers` for external developer impact: Use `To contributors` for internal project work: -- `vishot`, `vite-plugin-warpdrive`, `cap-vite`, CI, dev scripts, repo build/test/lint workflow, docs generation, internal-only packages, release automation, test harnesses, screenshots, evaluation tools. +- `vishot`, `cap-vite`, CI, dev scripts, repo build/test/lint workflow, docs generation, internal-only packages, release automation, test harnesses, screenshots, evaluation tools. - Include relevant `chore` commits even when changelogithub does not surface them prominently. ## End-User Writing diff --git a/AGENTS.md b/AGENTS.md index a0f42b77e..e1a6a261c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -34,7 +34,6 @@ Concise but detailed reference for contributors working across the `moeru-ai/air - **IPC/Eventa**: Always use `@moeru/eventa` for type-safe, framework/runtime-agnostic IPC/RPC. Define contracts centrally (e.g., `apps/stage-tamagotchi/src/shared`) and follow usage patterns in `apps/stage-tamagotchi/src/main/services/electron` for main/renderer integration. - **Dependency Injection**: Use `injeca` for services/electron modules/plugins/frontend; see `apps/stage-tamagotchi/src/main/index.ts` for composition patterns. - **Build/CI/Lint**: `.github/workflows` for pipelines; `eslint.config.js` for lint rules. -- **Bundling libs**: Use `tsdown` for new modules (see `packages/vite-plugin-warpdrive`). - **Styles**: UnoCSS config at `uno.config.ts`; check `apps/stage-web/src/styles` for existing animations; prefer UnoCSS over Tailwind. ## Key Path Index (what lives where) @@ -60,7 +59,6 @@ Concise but detailed reference for contributors working across the `moeru-ai/air - Styles: `uno.config.ts` (UnoCSS), `apps/stage-web/src/styles` (animations/reference). - Build pipeline refs: `.github/workflows`; lint rules in `eslint.config.js`. - Tailwind/UnoCSS: prefer UnoCSS; if standardizing styles, add shortcuts/rules/plugins in `uno.config.ts`. -- Bundling pattern: `packages/vite-plugin-warpdrive` (tsdown example). ## Commands (pnpm with filters) diff --git a/apps/stage-pocket/package.json b/apps/stage-pocket/package.json index 326293ef2..da2ed1ae8 100644 --- a/apps/stage-pocket/package.json +++ b/apps/stage-pocket/package.json @@ -124,7 +124,6 @@ "@proj-airi/lobe-icons": "^1.0.19", "@proj-airi/unplugin-fetch": "catalog:", "@proj-airi/unplugin-live2d-sdk": "^0.1.7", - "@proj-airi/vite-plugin-warpdrive": "workspace:*", "@shikijs/markdown-it": "^4.0.2", "@types/audioworklet": "catalog:", "@types/culori": "^4.0.1", diff --git a/apps/stage-web/package.json b/apps/stage-web/package.json index 22c110f34..b65d0c024 100644 --- a/apps/stage-web/package.json +++ b/apps/stage-web/package.json @@ -120,7 +120,6 @@ "@proj-airi/lobe-icons": "^1.0.19", "@proj-airi/unplugin-fetch": "catalog:", "@proj-airi/unplugin-live2d-sdk": "^0.1.7", - "@proj-airi/vite-plugin-warpdrive": "workspace:*", "@shikijs/markdown-it": "^4.0.2", "@types/audioworklet": "catalog:", "@types/culori": "^4.0.1", @@ -136,6 +135,7 @@ "csstype": "^3.2.3", "hfup": "^1.0.4", "less": "^4.6.4", + "unplugin-basemove": "0.0.1", "unplugin-info": "^1.3.2", "unplugin-yaml": "^4.1.0", "vite": "catalog:", diff --git a/apps/stage-web/vite.config.ts b/apps/stage-web/vite.config.ts index b2a1a5b5d..ba5c4b35d 100644 --- a/apps/stage-web/vite.config.ts +++ b/apps/stage-web/vite.config.ts @@ -7,6 +7,7 @@ import VueI18n from '@intlify/unplugin-vue-i18n/vite' import templateCompilerOptions from '@tresjs/core/template-compiler-options' import Vue from '@vitejs/plugin-vue' import Unocss from 'unocss/vite' +import Basemove, { createS3Provider } from 'unplugin-basemove/vite' import Info from 'unplugin-info/vite' import Yaml from 'unplugin-yaml/vite' import Mkcert from 'vite-plugin-mkcert' @@ -18,7 +19,6 @@ import VueRouter from 'vue-router/vite' import { tryCatch } from '@moeru/std' import { Download } from '@proj-airi/unplugin-fetch/vite' import { DownloadLive2DSDK } from '@proj-airi/unplugin-live2d-sdk/vite' -import { createS3Provider, WarpDrivePlugin } from '@proj-airi/vite-plugin-warpdrive' import { LFS, SpaceCard } from 'hfup/vite' import { defineConfig } from 'vite' import { VitePWA } from 'vite-plugin-pwa' @@ -275,7 +275,7 @@ export default defineConfig({ ...((!env.S3_ENDPOINT || !env.S3_ACCESS_KEY_ID || !env.S3_SECRET_ACCESS_KEY) ? [] : [ - WarpDrivePlugin({ + Basemove({ prefix: env.STAGE_WEB_WARP_DRIVE_PREFIX || 'proj-airi/stage-web/main/', include: [/\.wasm$/i, /\.ttf$/i, /\.vrm$/i, /\.zip$/i], // in existing assets, wasm, ttf, vrm files are the largest ones manifest: true, diff --git a/cspell.config.yaml b/cspell.config.yaml index 09fc8ef3b..5c77c815b 100644 --- a/cspell.config.yaml +++ b/cspell.config.yaml @@ -32,6 +32,7 @@ words: - baichuan - baiducloud - bailian + - Basemove - bestmove - bigserial - bilibili @@ -345,7 +346,6 @@ words: - vueuse - waapi - Waifu - - warpdrive - Warudo - wavefile - webgpu diff --git a/packages/stage-ui/package.json b/packages/stage-ui/package.json index 35d0a4de7..e17b3c7ff 100644 --- a/packages/stage-ui/package.json +++ b/packages/stage-ui/package.json @@ -182,7 +182,6 @@ "@pinia/testing": "catalog:", "@proj-airi/lobe-icons": "^1.0.19", "@proj-airi/stream-kit": "workspace:*", - "@proj-airi/vite-plugin-warpdrive": "workspace:*", "@types/audioworklet": "catalog:", "@types/culori": "^4.0.1", "@types/d3": "catalog:", @@ -197,6 +196,7 @@ "histoire": "catalog:", "is-network-error": "catalog:", "unocss": "^66.6.8", + "unplugin-basemove": "0.0.1", "unplugin-info": "catalog:", "unplugin-yaml": "^4.1.0", "vite": "^6.4.2", diff --git a/packages/stage-ui/vite.config.ts b/packages/stage-ui/vite.config.ts index 8d4825dbf..1b1db9cc8 100644 --- a/packages/stage-ui/vite.config.ts +++ b/packages/stage-ui/vite.config.ts @@ -5,10 +5,10 @@ import { env } from 'node:process' import Vue from '@vitejs/plugin-vue' import Unocss from 'unocss/vite' +import Basemove, { createS3Provider } from 'unplugin-basemove/vite' import Yaml from 'unplugin-yaml/vite' import Inspect from 'vite-plugin-inspect' -import { createS3Provider, WarpDrivePlugin } from '@proj-airi/vite-plugin-warpdrive' import { defineConfig } from 'vite' // For Histoire @@ -61,7 +61,7 @@ export default defineConfig({ ...((!env.S3_ENDPOINT || !env.S3_ACCESS_KEY_ID || !env.S3_SECRET_ACCESS_KEY) ? [] : [ - WarpDrivePlugin({ + Basemove({ prefix: env.STAGE_UI_WARP_DRIVE_PREFIX || 'proj-airi/stage-ui/main/', include: [/\.wasm$/i, /\.ttf$/i, /\.vrm$/i, /\.zip$/i], // in existing assets, wasm, ttf, vrm files are the largest ones manifest: true, diff --git a/packages/vite-plugin-warpdrive/README.md b/packages/vite-plugin-warpdrive/README.md deleted file mode 100644 index 5e9cb5a9f..000000000 --- a/packages/vite-plugin-warpdrive/README.md +++ /dev/null @@ -1,84 +0,0 @@ -# @proj-airi/vite-plugin-warpdrive - -Vite plugin that rewrites selected build assets (large WASM/TTF/VRM, etc.) to remote object storage and uploads them after build. It uses Vite's `renderBuiltUrl` hook so the generated bundles reference the remote URL while keeping the local file for upload. - -## Why - -- Keep HTML/JS bundles lean while serving heavy assets (WASM, fonts, models) from object storage/CDN. -- Simple provider abstraction; ships with an S3-compatible implementation via [`s3mini`](https://github.com/good-lly/s3mini). -- Emits an optional manifest (`remote-assets.manifest.json`) that maps built filenames to remote URLs plus hostId/hostType for debugging. - -## Install - -```bash -pnpm add -D @proj-airi/vite-plugin-warpdrive -``` - -## Usage - -```ts -import { createS3Provider, WarpDrivePlugin } from '@proj-airi/vite-plugin-warpdrive' -// vite.config.ts -import { defineConfig } from 'vite' - -export default defineConfig({ - plugins: [ - WarpDrivePlugin({ - prefix: 'remote-assets', // path prefix in the bucket (default: remote-assets) - include: [/\.wasm$/i, /\.ttf$/i, /\.vrm$/i], // which assets to rewrite/upload (required) - // includeBy: (file, ctx) => ctx.hostId?.includes('duckdb'), // extra predicate with host info - // contentTypeBy: (file) => file.endsWith('.wasm') ? 'application/wasm' : undefined, - manifest: true, // emit remote-assets.manifest.json in dist - delete: true, // delete local uploaded assets (default: true) - clean: true, // clean remote prefix before upload (default: true if provider supports it) - skipNotModified: true, // skip uploads if provider supports it (default: true) - // dryRun: true, // rewrite URLs/manifest only; skip cleaning/uploading - provider: createS3Provider({ - endpoint: process.env.S3_ENDPOINT!, - accessKeyId: process.env.S3_ACCESS_KEY_ID!, - secretAccessKey: process.env.S3_SECRET_ACCESS_KEY!, - region: process.env.S3_REGION, - publicBaseUrl: process.env.WARP_DRIVE_PUBLIC_BASE, // defaults to endpoint - }), - }), - ], -}) -``` - -### Options - -- `provider` (required): object implementing `UploadProvider` (see below). -- `prefix`: string path prefix for uploaded keys and URLs (default: `remote-assets`; e.g. `remote-assets/assets/foo.wasm`). -- `include`: array of regex or predicate functions to decide which assets to rewrite/upload (empty array means nothing is rewritten). -- `includeBy`: optional `(filename, ctx) => boolean` for finer control (`ctx` has `hostId`, `hostType`). -- `contentTypeBy`: optional `(filename) => string | Promise | undefined` resolver passed to `provider.upload`. -- `manifest`: when true, emits `remote-assets.manifest.json` describing fileName/key/url/hostId/hostType/size. -- `delete`: when true (default), delete uploaded local assets from disk after upload. -- `clean`: when true (default), call `provider.cleanPrefix(prefix)` before uploading; skipped if no prefix or provider lacks `cleanPrefix`. -- `skipNotModified`: when true (default), skip uploads if `provider.shouldSkipUpload` returns true. -- `dryRun`: when true, rewrite URLs/emit manifest without cleaning or uploading. - -#### UploadProvider interface - -```ts -interface UploadProvider { - getPublicUrl: (key: string) => string - upload: (localPath: string, key: string, contentType?: string) => Promise - cleanPrefix?: (prefix: string) => Promise - shouldSkipUpload?: (localPath: string, key: string) => Promise -} -``` - -### createS3Provider - -Light wrapper around `s3mini`. Required fields: - -- `endpoint`: full bucket URL (e.g. `https://s3.example.com/my-bucket`). -- `accessKeyId`, `secretAccessKey`: credentials. -- Optional: `region`, `requestSizeInBytes`, `requestAbortTimeout`, `publicBaseUrl` (override public URL base), `skipNotModified` (default: true; uses ETag/MD5 to skip uploads). - -## How it works - -1. `renderBuiltUrl` returns the remote URL for matching assets while remembering the key/hostId/hostType. -2. `generateBundle` records assets to upload, emits the optional manifest, and leaves the local files in `dist/`. -3. `closeBundle` optionally cleans the prefix, skips unmodified uploads when supported, uploads assets, and deletes local copies (unless `delete` is false). diff --git a/packages/vite-plugin-warpdrive/package.json b/packages/vite-plugin-warpdrive/package.json deleted file mode 100644 index a93a92bed..000000000 --- a/packages/vite-plugin-warpdrive/package.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "name": "@proj-airi/vite-plugin-warpdrive", - "type": "module", - "version": "0.10.2", - "private": true, - "description": "Vite plugin to rewrite and upload heavy build assets to remote object storage", - "author": { - "name": "Moeru AI Project AIRI Team", - "email": "airi@moeru.ai", - "url": "https://github.com/moeru-ai" - }, - "license": "MIT", - "exports": { - ".": { - "types": "./dist/index.d.mts", - "default": "./dist/index.mjs" - } - }, - "main": "./dist/index.mjs", - "types": "./dist/index.d.mts", - "files": [ - "README.md", - "dist", - "package.json" - ], - "scripts": { - "build": "tsdown", - "typecheck": "tsc --noEmit" - }, - "peerDependencies": { - "vite": "^5.0.0 || ^6.0.0" - }, - "dependencies": { - "rolldown": "1.0.0-beta.51", - "s3mini": "^0.9.4" - }, - "devDependencies": { - "@moeru/std": "catalog:" - } -} diff --git a/packages/vite-plugin-warpdrive/src/index.ts b/packages/vite-plugin-warpdrive/src/index.ts deleted file mode 100644 index 07b2cbb44..000000000 --- a/packages/vite-plugin-warpdrive/src/index.ts +++ /dev/null @@ -1,293 +0,0 @@ -import type { OutputAsset } from 'rollup' -import type { Plugin, RenderBuiltAssetUrl, ResolvedConfig } from 'vite' - -import type { UploadProvider } from './providers/types' - -import { Buffer } from 'node:buffer' -import { rm } from 'node:fs/promises' -import { join, resolve } from 'node:path' -import { cwd } from 'node:process' - -import { errorCauseFrom, errorMessageFrom, errorNameFrom, errorStackFrom } from '@moeru/std' - -export { createS3Provider } from './providers/s3' -export type { S3ProviderOptions } from './providers/s3' -export type { UploadProvider } from './providers/types' - -type IncludeMatcher = RegExp | ((filename: string) => boolean) - -export interface WarpDrivePluginOptions { - provider: UploadProvider - /** - * Prefix to prepend before the asset filename when uploading and when rewriting URLs. - * e.g. `remote-assets` will produce `remote-assets/assets/duckdb-eh-123.wasm`. - */ - prefix?: string - /** - * Restrict which assets are rewritten/uploaded. - */ - include?: IncludeMatcher[] - /** - * Optional extra predicate that receives filename + host info to decide inclusion. - */ - includeBy?: (filename: string, ctx: { hostId?: string, hostType?: string }) => boolean - /** - * Optional content-type resolver. If omitted, uploads use the provider default. - */ - contentTypeBy?: (filename: string) => Promise | string | undefined - /** - * Emit a manifest with module id + URL for debugging. - */ - manifest?: boolean - /** - * Delete the uploaded local asset from disk after upload completes. Enabled by default. - */ - delete?: boolean - /** - * Clean the remote prefix before uploading (delete existing objects). Enabled by default. - */ - clean?: boolean - /** - * When enabled, skip cleaning and uploading; emit manifest/rewrite URLs only. - */ - dryRun?: boolean - /** - * Skip uploading assets that are already present and not modified. Enabled by default when supported. - */ - skipNotModified?: boolean -} - -export function WarpDrivePlugin(options: WarpDrivePluginOptions): Plugin { - const include = options.include ?? [] - const prefix = normalizePrefix(options.prefix ?? 'remote-assets') - const pluginName = 'proj-airi-warpdrive' - const shouldDeleteLocalAsset = options.delete !== false - const shouldCleanRemote = options.clean !== false - const shouldSkipNotModified = options.skipNotModified !== false - const isDryRun = options.dryRun === true - - const tracked = new Map() - const manifest: Array<{ - fileName: string - url: string - key: string - hostId?: string - hostType?: string - size: number - }> = [] - - let resolvedConfig: ResolvedConfig | undefined - let cleanedRemote = false - const pendingUploads: Array<{ - fileName: string - key: string - localPath: string - contentType?: string - }> = [] - - const shouldHandle = (filename: string, ctx: { hostId?: string, hostType?: string }) => { - const includeMatch = include.some((matcher) => { - if (matcher instanceof RegExp) - return matcher.test(filename) - - return matcher(filename) - }) - - if (!includeMatch) - return false - if (options.includeBy) - return options.includeBy(filename, ctx) - - return true - } - - const renderBuiltUrl: RenderBuiltAssetUrl = (filename, ctx) => { - if (!shouldHandle(filename, ctx)) - return - if (!options.provider) - return - - const key = prefix ? `${prefix}/${filename}` : filename - const url = options.provider.getPublicUrl(key) - - tracked.set(filename, { - key, - url, - hostId: ctx.hostId, - hostType: ctx.hostType, - }) - - return url - } - - return { - name: pluginName, - apply: 'build', - enforce: 'post', - config: () => { - return { - experimental: { - renderBuiltUrl, - }, - } - }, - configResolved(config) { - resolvedConfig = config - }, - async generateBundle(_, bundle) { - if (!resolvedConfig) { - console.warn?.(`[${pluginName}] Vite config not resolved, skipping upload step`) - return - } - if (!options.provider) { - resolvedConfig.logger.warn(`[${pluginName}] no upload provider configured, skipping upload step`) - return - } - - const root = resolvedConfig.root || cwd() - const outDir = resolve(root, resolvedConfig.build.outDir) - - for (const [fileName, output] of Object.entries(bundle)) { - if (output.type !== 'asset') - continue - - const trackedMeta = tracked.get(fileName) - if (!trackedMeta) - continue - - const key = trackedMeta.key - const url = trackedMeta.url - const localPath = join(outDir, fileName) - const size = getAssetSize(output) - const contentType = await options.contentTypeBy?.(fileName) - - manifest.push({ - fileName, - url, - key, - hostId: trackedMeta.hostId, - hostType: trackedMeta.hostType, - size, - }) - - pendingUploads.push({ fileName, key, localPath, contentType }) - resolvedConfig.logger.info(`[${pluginName}] scheduled uploading: ${fileName} -> ${key} (${size} bytes)`) - } - - if (options.manifest && manifest.length) { - this.emitFile({ - type: 'asset', - fileName: 'remote-assets.manifest.json', - source: JSON.stringify({ assets: manifest }, null, 2), - }) - } - }, - async closeBundle() { - if (!resolvedConfig) { - console.warn?.(`[${pluginName}] Vite config not resolved, skipping upload step`) - return - } - if (!options.provider) { - resolvedConfig.logger.warn(`[${pluginName}] no upload provider configured, skipping upload step`) - return - } - if (!pendingUploads.length) - return - if (isDryRun) { - resolvedConfig.logger.info( - `[${pluginName}] dry run enabled; skipping clean/upload for ${pendingUploads.length} assets`, - ) - return - } - - if (shouldCleanRemote && !cleanedRemote) { - if (!prefix) { - resolvedConfig.logger.warn(`[${pluginName}] skipping clean step because no prefix provided`) - } - else if (typeof options.provider.cleanPrefix === 'function') { - resolvedConfig.logger.info(`[${pluginName}] cleaning remote prefix: ${prefix}`) - await options.provider.cleanPrefix(prefix) - resolvedConfig.logger.info(`[${pluginName}] cleaned remote prefix: ${prefix}`) - cleanedRemote = true - } - else { - resolvedConfig.logger.warn( - `[${pluginName}] clean is enabled but provider does not support prefix cleaning; skipping`, - ) - } - } - - resolvedConfig.logger.info(`[${pluginName}] uploading ${pendingUploads.length} assets to remote storage...`) - const uploads: Array> = [] - - for (const { fileName, key, localPath, contentType } of pendingUploads) { - uploads.push((async () => { - if (shouldSkipNotModified && typeof options.provider.shouldSkipUpload === 'function') { - try { - const skip = await options.provider.shouldSkipUpload(localPath, key) - if (skip) { - resolvedConfig.logger.info( - `[${pluginName}] skipped upload (not modified): ${fileName} -> ${key}`, - ) - if (shouldDeleteLocalAsset) { - try { - await rm(localPath, { force: true }) - resolvedConfig.logger.info(`[${pluginName}] deleted local asset: ${fileName}`) - } - catch (error) { - resolvedConfig.logger.warn(`[${pluginName}] failed to delete local asset ${fileName}: ${error}`) - } - } - return - } - } - catch (error) { - resolvedConfig.logger.warn( - `[${pluginName}] could not determine if upload should be skipped for ${fileName}: ${error}`, - ) - } - } - try { - await options.provider.upload(localPath, key, contentType) - } - catch (err) { - const error = new Error(errorMessageFrom(err)) - error.name = errorNameFrom(err) || 'UploadError' - const stack = errorStackFrom(err) - if (stack) - error.stack = stack - - error.cause = errorCauseFrom(err) - - resolvedConfig.logger.error(`[${pluginName}] upload failed, file: ${fileName} -> ${key}: ${err}`, { error }) - throw err - } - - if (shouldDeleteLocalAsset) { - try { - await rm(localPath, { force: true }) - resolvedConfig.logger.info(`[${pluginName}] deleted local asset: ${fileName}`) - } - catch (error) { - resolvedConfig.logger.warn(`[${pluginName}] failed to delete local asset ${fileName}: ${error}`) - } - } - })()) - } - - await Promise.all(uploads) - resolvedConfig.logger.info(`[${pluginName}] upload complete`) - }, - } -} - -function normalizePrefix(prefix: string) { - return prefix.replace(/^\/*/, '').replace(/\/*$/, '') -} - -function getAssetSize(asset: OutputAsset) { - if (typeof asset.source === 'string') - return Buffer.byteLength(asset.source) - - return asset.source?.byteLength ?? 0 -} diff --git a/packages/vite-plugin-warpdrive/src/providers/s3.test.ts b/packages/vite-plugin-warpdrive/src/providers/s3.test.ts deleted file mode 100644 index a03efe50d..000000000 --- a/packages/vite-plugin-warpdrive/src/providers/s3.test.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { join } from 'node:path' -import { cwd, env } from 'node:process' - -import { describe, expect, it } from 'vitest' - -import { createS3Provider } from './s3' - -describe('s3', (test) => { - if (!env.S3_ENDPOINT || !env.S3_REGION || !env.S3_ACCESS_KEY_ID || !env.S3_SECRET_ACCESS_KEY) { - test.skip('S3_ENDPOINT, S3_REGION, S3_ACCESS_KEY_ID and S3_SECRET_ACCESS_KEY must be set in environment to run this test', () => {}) - return - } - - // eslint-disable-next-line test/prefer-lowercase-title - describe('S3Provider', () => { - it('should skip upload', async () => { - const s3 = createS3Provider({ - endpoint: env.S3_ENDPOINT!, - accessKeyId: env.S3_ACCESS_KEY_ID!, - secretAccessKey: env.S3_SECRET_ACCESS_KEY!, - region: env.S3_REGION, - publicBaseUrl: env.WARP_DRIVE_PUBLIC_BASE ?? env.S3_ENDPOINT, - }) - - expect(await s3.shouldSkipUpload?.(join(cwd(), 'packages', 'stage-ui', 'src', 'assets', 'live2d', 'models', 'hiyori_free_zh.zip'), '/proj-airi/stage-web/assets/hiyori_free_zh-D9UJNK98.zip')).toBe(true) - }) - }) -}) diff --git a/packages/vite-plugin-warpdrive/src/providers/s3.ts b/packages/vite-plugin-warpdrive/src/providers/s3.ts deleted file mode 100644 index 23056d81e..000000000 --- a/packages/vite-plugin-warpdrive/src/providers/s3.ts +++ /dev/null @@ -1,102 +0,0 @@ -import type { Buffer } from 'node:buffer' - -import type { UploadProvider } from './types' - -import { createHash } from 'node:crypto' -import { readFile } from 'node:fs/promises' - -import { S3mini } from 's3mini' - -export interface S3ProviderOptions { - endpoint: string - accessKeyId: string - secretAccessKey: string - region?: string - requestSizeInBytes?: number - requestAbortTimeout?: number - /** - * Skip uploading when the remote object ETag matches the local content hash (MD5). Enabled by default. - */ - skipNotModified?: boolean - /** - * Public base URL used in rewritten assets. Defaults to endpoint. - */ - publicBaseUrl?: string -} - -export function createS3Provider(options: S3ProviderOptions): UploadProvider { - const client = new S3mini({ - accessKeyId: options.accessKeyId, - secretAccessKey: options.secretAccessKey, - endpoint: options.endpoint, - region: options.region ?? 'auto', - requestAbortTimeout: options.requestAbortTimeout, - requestSizeInBytes: options.requestSizeInBytes, - }) - - const publicBaseUrl = options.publicBaseUrl ?? options.endpoint - const skipNotModified = options.skipNotModified !== false - - return { - async upload(localPath: string, key: string, contentType?: string) { - const data = await readFile(localPath) - await client.putObject(normalizeKey(key), data, contentType ?? 'application/octet-stream') - }, - async cleanPrefix(prefix: string) { - const normalizedPrefix = normalizePrefix(prefix) - if (!normalizedPrefix) - return - - const objects = await client.listObjects('/', `${normalizedPrefix}/`) - if (!objects?.length) - return - - const keys = objects.map(obj => obj.Key) - await client.deleteObjects(keys) - }, - async shouldSkipUpload(localPath: string, key: string) { - if (!skipNotModified) - return false - - const data = await readFile(localPath) - return isMd5HashMatched(client, key, data) - }, - getPublicUrl(key: string) { - return joinUrl(publicBaseUrl, key) - }, - } -} - -async function isMd5HashMatched(client: S3mini, key: string, data: Buffer) { - try { - const etag = await client.getEtag(normalizeKey(key)) - if (!etag) - return false - - const normalizedEtag = sanitizeEtag(etag) - if (!normalizedEtag || normalizedEtag.includes('-')) - return false - - const localHash = createHash('md5').update(data).digest('hex') - return normalizedEtag.toLowerCase() === localHash.toLowerCase() - } - catch { - return false - } -} - -function normalizePrefix(prefix: string) { - return prefix.replace(/^\/*/, '').replace(/\/*$/, '') -} - -function normalizeKey(key: string) { - return key.replace(/^\/*/, '') -} - -function joinUrl(base: string, path: string) { - return `${base.replace(/\/+$/, '')}/${path.replace(/^\/+/, '')}` -} - -function sanitizeEtag(etag: string) { - return etag.replace(/^"+|"+$/g, '') -} diff --git a/packages/vite-plugin-warpdrive/src/providers/types.ts b/packages/vite-plugin-warpdrive/src/providers/types.ts deleted file mode 100644 index 3fd43b01a..000000000 --- a/packages/vite-plugin-warpdrive/src/providers/types.ts +++ /dev/null @@ -1,12 +0,0 @@ -export interface UploadProvider { - getPublicUrl: (key: string) => string - upload: (localPath: string, key: string, contentType?: string) => Promise - /** - * Optionally clean a remote prefix before uploading new assets. - */ - cleanPrefix?: (prefix: string) => Promise - /** - * Optionally determine if an upload can be skipped (e.g., hash/etag match). - */ - shouldSkipUpload?: (localPath: string, key: string) => Promise -} diff --git a/packages/vite-plugin-warpdrive/tsconfig.json b/packages/vite-plugin-warpdrive/tsconfig.json deleted file mode 100644 index 00dcfd807..000000000 --- a/packages/vite-plugin-warpdrive/tsconfig.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "compilerOptions": { - "target": "ESNext", - "lib": [ - "ESNext" - ], - "module": "ESNext", - "moduleResolution": "bundler", - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "isolatedModules": true, - "verbatimModuleSyntax": true, - "skipLibCheck": true - }, - "include": [ - "src/**/*.ts" - ] -} diff --git a/packages/vite-plugin-warpdrive/tsdown.config.ts b/packages/vite-plugin-warpdrive/tsdown.config.ts deleted file mode 100644 index ef150f707..000000000 --- a/packages/vite-plugin-warpdrive/tsdown.config.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { defineConfig } from 'tsdown' - -export default defineConfig({ - entry: [ - './src/index.ts', - ], - dts: true, - sourcemap: true, -}) diff --git a/packages/vite-plugin-warpdrive/vitest.config.ts b/packages/vite-plugin-warpdrive/vitest.config.ts deleted file mode 100644 index a3ee64355..000000000 --- a/packages/vite-plugin-warpdrive/vitest.config.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { join } from 'node:path' -import { cwd } from 'node:process' - -import { loadEnv } from 'vite' -import { defineConfig } from 'vitest/config' - -export default defineConfig(({ mode }) => { - return ({ - test: { - include: ['src/**/*.test.ts'], - env: loadEnv(mode, join(cwd(), 'packages', 'vite-plugin-warpdrive'), ''), - }, - }) -}) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d9926a439..a3c800e0e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1063,9 +1063,6 @@ importers: '@proj-airi/unplugin-live2d-sdk': specifier: ^0.1.7 version: 0.1.7(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3) - '@proj-airi/vite-plugin-warpdrive': - specifier: workspace:* - version: link:../../packages/vite-plugin-warpdrive '@shikijs/markdown-it': specifier: ^4.0.2 version: 4.0.2 @@ -1950,9 +1947,6 @@ importers: '@proj-airi/unplugin-live2d-sdk': specifier: ^0.1.7 version: 0.1.7(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3) - '@proj-airi/vite-plugin-warpdrive': - specifier: workspace:* - version: link:../../packages/vite-plugin-warpdrive '@shikijs/markdown-it': specifier: ^4.0.2 version: 4.0.2 @@ -1998,6 +1992,9 @@ importers: less: specifier: ^4.6.4 version: 4.6.4 + unplugin-basemove: + specifier: 0.0.1 + version: 0.0.1(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)) unplugin-info: specifier: ^1.3.2 version: 1.3.2(esbuild@0.27.2)(rollup@4.60.1)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)) @@ -3486,9 +3483,6 @@ importers: '@proj-airi/stream-kit': specifier: workspace:* version: link:../stream-kit - '@proj-airi/vite-plugin-warpdrive': - specifier: workspace:* - version: link:../vite-plugin-warpdrive '@types/audioworklet': specifier: 'catalog:' version: 0.0.97 @@ -3531,6 +3525,9 @@ importers: unocss: specifier: ^66.6.8 version: 66.6.8(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(vite@6.4.2(@types/node@25.6.0)(jiti@2.6.1)(less@4.6.4)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)) + unplugin-basemove: + specifier: 0.0.1 + version: 0.0.1(vite@6.4.2(@types/node@25.6.0)(jiti@2.6.1)(less@4.6.4)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)) unplugin-info: specifier: 'catalog:' version: 1.3.2(esbuild@0.27.2)(rollup@4.60.1)(vite@6.4.2(@types/node@25.6.0)(jiti@2.6.1)(less@4.6.4)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)) @@ -3876,22 +3873,6 @@ importers: specifier: ^3.2.6 version: 3.2.6(typescript@5.9.3) - packages/vite-plugin-warpdrive: - dependencies: - rolldown: - specifier: 1.0.0-beta.51 - version: 1.0.0-beta.51(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) - s3mini: - specifier: ^0.9.4 - version: 0.9.4 - vite: - specifier: ^5.0.0 || ^6.0.0 - version: 6.4.2(@types/node@25.6.0)(jiti@2.6.1)(less@4.6.4)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3) - devDependencies: - '@moeru/std': - specifier: 'catalog:' - version: 0.1.0-beta.17 - plugins/airi-plugin-bilibili-laplace: dependencies: '@guiiai/logg': @@ -7944,9 +7925,6 @@ packages: '@oxc-project/types@0.126.0': resolution: {integrity: sha512-oGfVtjAgwQVVpfBrbtk4e1XDyWHRFta6BS3GWVzrF8xYBT2VGQAk39yJS/wFSMrZqoiCU4oghT3Ch0HaHGIHcQ==} - '@oxc-project/types@0.98.0': - resolution: {integrity: sha512-Vzmd6FsqVuz5HQVcRC/hrx7Ujo3WEVeQP7C2UNP5uy1hUY4SQvMB+93jxkI1KRHz9a/6cni3glPOtvteN+zpsw==} - '@oxc-resolver/binding-android-arm-eabi@11.19.1': resolution: {integrity: sha512-aUs47y+xyXHUKlbhqHUjBABjvycq6YSD7bpxSW7vplUmdzAlJ93yXY6ZR0c1o1x5A/QKbENCvs3+NlY8IpIVzg==} cpu: [arm] @@ -8703,12 +8681,6 @@ packages: '@rive-app/canvas-lite@2.37.2': resolution: {integrity: sha512-Pp8R/ZpZliwkPm684HFIKZ4N6UurcfbfFQXV74+HV2bxAutpQYsDCr0sOjEgJC/brG5aeSCVyJY3Iq7nNAkmeQ==} - '@rolldown/binding-android-arm64@1.0.0-beta.51': - resolution: {integrity: sha512-Ctn8FUXKWWQI9pWC61P1yumS9WjQtelNS9riHwV7oCkknPGaAry4o7eFx2KgoLMnI2BgFJYpW7Im8/zX3BuONg==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [android] - '@rolldown/binding-android-arm64@1.0.0-rc.15': resolution: {integrity: sha512-YYe6aWruPZDtHNpwu7+qAHEMbQ/yRl6atqb/AhznLTnD3UY99Q1jE7ihLSahNWkF4EqRPVC4SiR4O0UkLK02tA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -8721,12 +8693,6 @@ packages: cpu: [arm64] os: [android] - '@rolldown/binding-darwin-arm64@1.0.0-beta.51': - resolution: {integrity: sha512-EL1aRW2Oq15ShUEkBPsDtLMO8GTqfb/ktM/dFaVzXKQiEE96Ss6nexMgfgQrg8dGnNpndFyffVDb5IdSibsu1g==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [darwin] - '@rolldown/binding-darwin-arm64@1.0.0-rc.15': resolution: {integrity: sha512-oArR/ig8wNTPYsXL+Mzhs0oxhxfuHRfG7Ikw7jXsw8mYOtk71W0OkF2VEVh699pdmzjPQsTjlD1JIOoHkLP1Fg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -8739,12 +8705,6 @@ packages: cpu: [arm64] os: [darwin] - '@rolldown/binding-darwin-x64@1.0.0-beta.51': - resolution: {integrity: sha512-uGtYKlFen9pMIPvkHPWZVDtmYhMQi5g5Ddsndg1gf3atScKYKYgs5aDP4DhHeTwGXQglhfBG7lEaOIZ4UAIWww==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [darwin] - '@rolldown/binding-darwin-x64@1.0.0-rc.15': resolution: {integrity: sha512-YzeVqOqjPYvUbJSWJ4EDL8ahbmsIXQpgL3JVipmN+MX0XnXMeWomLN3Fb+nwCmP/jfyqte5I3XRSm7OfQrbyxw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -8757,12 +8717,6 @@ packages: cpu: [x64] os: [darwin] - '@rolldown/binding-freebsd-x64@1.0.0-beta.51': - resolution: {integrity: sha512-JRoVTQtHYbZj1P07JLiuTuXjiBtIa7ag7/qgKA6CIIXnAcdl4LrOf7nfDuHPJcuRKaP5dzecMgY99itvWfmUFQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [freebsd] - '@rolldown/binding-freebsd-x64@1.0.0-rc.15': resolution: {integrity: sha512-9Erhx956jeQ0nNTyif1+QWAXDRD38ZNjr//bSHrt6wDwB+QkAfl2q6Mn1k6OBPerznjRmbM10lgRb1Pli4xZPw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -8775,12 +8729,6 @@ packages: cpu: [x64] os: [freebsd] - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.51': - resolution: {integrity: sha512-BKATVnpPZ0TYBW9XfDwyd4kPGgvf964HiotIwUgpMrFOFYWqpZ+9ONNzMV4UFAYC7Hb5C2qgYQk/qj2OnAd4RQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm] - os: [linux] - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.15': resolution: {integrity: sha512-cVwk0w8QbZJGTnP/AHQBs5yNwmpgGYStL88t4UIaqcvYJWBfS0s3oqVLZPwsPU6M0zlW4GqjP0Zq5MnAGwFeGA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -8793,13 +8741,6 @@ packages: cpu: [arm] os: [linux] - '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.51': - resolution: {integrity: sha512-xLd7da5jkfbVsBCm1buIRdWtuXY8+hU3+6ESXY/Tk5X5DPHaifrUblhYDgmA34dQt6WyNC2kfXGgrduPEvDI6Q==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [linux] - libc: [glibc] - '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.15': resolution: {integrity: sha512-eBZ/u8iAK9SoHGanqe/jrPnY0JvBN6iXbVOsbO38mbz+ZJsaobExAm1Iu+rxa4S1l2FjG0qEZn4Rc6X8n+9M+w==} engines: {node: ^20.19.0 || >=22.12.0} @@ -8814,13 +8755,6 @@ packages: os: [linux] libc: [glibc] - '@rolldown/binding-linux-arm64-musl@1.0.0-beta.51': - resolution: {integrity: sha512-EQFXTgHxxTzv3t5EmjUP/DfxzFYx9sMndfLsYaAY4DWF6KsK1fXGYsiupif6qPTViPC9eVmRm78q0pZU/kuIPg==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [linux] - libc: [musl] - '@rolldown/binding-linux-arm64-musl@1.0.0-rc.15': resolution: {integrity: sha512-ZvRYMGrAklV9PEkgt4LQM6MjQX2P58HPAuecwYObY2DhS2t35R0I810bKi0wmaYORt6m/2Sm+Z+nFgb0WhXNcQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -8863,13 +8797,6 @@ packages: os: [linux] libc: [glibc] - '@rolldown/binding-linux-x64-gnu@1.0.0-beta.51': - resolution: {integrity: sha512-p5P6Xpa68w3yFaAdSzIZJbj+AfuDnMDqNSeglBXM7UlJT14Q4zwK+rV+8Mhp9MiUb4XFISZtbI/seBprhkQbiQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [linux] - libc: [glibc] - '@rolldown/binding-linux-x64-gnu@1.0.0-rc.15': resolution: {integrity: sha512-023bTPBod7J3Y/4fzAN6QtpkSABR0rigtrwaP+qSEabUh5zf6ELr9Nc7GujaROuPY3uwdSIXWrvhn1KxOvurWA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -8884,13 +8811,6 @@ packages: os: [linux] libc: [glibc] - '@rolldown/binding-linux-x64-musl@1.0.0-beta.51': - resolution: {integrity: sha512-sNVVyLa8HB8wkFipdfz1s6i0YWinwpbMWk5hO5S+XAYH2UH67YzUT13gs6wZTKg2x/3gtgXzYnHyF5wMIqoDAw==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [linux] - libc: [musl] - '@rolldown/binding-linux-x64-musl@1.0.0-rc.15': resolution: {integrity: sha512-witB2O0/hU4CgfOOKUoeFgQ4GktPi1eEbAhaLAIpgD6+ZnhcPkUtPsoKKHRzmOoWPZue46IThdSgdo4XneOLYw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -8905,12 +8825,6 @@ packages: os: [linux] libc: [musl] - '@rolldown/binding-openharmony-arm64@1.0.0-beta.51': - resolution: {integrity: sha512-e/JMTz9Q8+T3g/deEi8DK44sFWZWGKr9AOCW5e8C8SCVWzAXqYXAG7FXBWBNzWEZK0Rcwo9TQHTQ9Q0gXgdCaA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [openharmony] - '@rolldown/binding-openharmony-arm64@1.0.0-rc.15': resolution: {integrity: sha512-UCL68NJ0Ud5zRipXZE9dF5PmirzJE4E4BCIOOssEnM7wLDsxjc6Qb0sGDxTNRTP53I6MZpygyCpY8Aa8sPfKPg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -8923,11 +8837,6 @@ packages: cpu: [arm64] os: [openharmony] - '@rolldown/binding-wasm32-wasi@1.0.0-beta.51': - resolution: {integrity: sha512-We3LWqSu6J9s5Y0MK+N7fUiiu37aBGPG3Pc347EoaROuAwkCS2u9xJ5dpIyLW4B49CIbS3KaPmn4kTgPb3EyPw==} - engines: {node: '>=14.0.0'} - cpu: [wasm32] - '@rolldown/binding-wasm32-wasi@1.0.0-rc.15': resolution: {integrity: sha512-ApLruZq/ig+nhaE7OJm4lDjayUnOHVUa77zGeqnqZ9pn0ovdVbbNPerVibLXDmWeUZXjIYIT8V3xkT58Rm9u5Q==} engines: {node: '>=14.0.0'} @@ -8938,12 +8847,6 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} cpu: [wasm32] - '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.51': - resolution: {integrity: sha512-fj56buHRuMM+r/cb6ZYfNjNvO/0xeFybI6cTkTROJatdP4fvmQ1NS8D/Lm10FCSDEOkqIz8hK3TGpbAThbPHsA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [win32] - '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.15': resolution: {integrity: sha512-KmoUoU7HnN+Si5YWJigfTws1jz1bKBYDQKdbLspz0UaqjjFkddHsqorgiW1mxcAj88lYUE6NC/zJNwT+SloqtA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -8956,18 +8859,6 @@ packages: cpu: [arm64] os: [win32] - '@rolldown/binding-win32-ia32-msvc@1.0.0-beta.51': - resolution: {integrity: sha512-fkqEqaeEx8AySXiDm54b/RdINb3C0VovzJA3osMhZsbn6FoD73H0AOIiaVAtGr6x63hefruVKTX8irAm4Jkt2w==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [ia32] - os: [win32] - - '@rolldown/binding-win32-x64-msvc@1.0.0-beta.51': - resolution: {integrity: sha512-CWuLG/HMtrVcjKGa0C4GnuxONrku89g0+CsH8nT0SNhOtREXuzwgjIXNJImpE/A/DMf9JF+1Xkrq/YRr+F/rCg==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [win32] - '@rolldown/binding-win32-x64-msvc@1.0.0-rc.15': resolution: {integrity: sha512-3P2A8L+x75qavWLe/Dll3EYBJLQmtkJN8rfh+U/eR3MqMgL/h98PhYI+JFfXuDPgPeCB7iZAKiqii5vqOvnA0g==} engines: {node: ^20.19.0 || >=22.12.0} @@ -8980,9 +8871,6 @@ packages: cpu: [x64] os: [win32] - '@rolldown/pluginutils@1.0.0-beta.51': - resolution: {integrity: sha512-51/8cNXMrqWqX3o8DZidhwz1uYq0BhHDDSfVygAND1Skx5s1TDw3APSSxCMcFFedwgqGcx34gRouwY+m404BBQ==} - '@rolldown/pluginutils@1.0.0-rc.13': resolution: {integrity: sha512-3ngTAv6F/Py35BsYbeeLeecvhMKdsKm4AoOETVhAA+Qc8nrA2I0kF7oa93mE9qnIurngOSpMnQ0x2nQY2FPviA==} @@ -16245,11 +16133,6 @@ packages: vue-tsc: optional: true - rolldown@1.0.0-beta.51: - resolution: {integrity: sha512-ZRLgPlS91l4JztLYEZnmMcd3Umcla1hkXJgiEiR4HloRJBBoeaX8qogTu5Jfu36rRMVLndzqYv0h+M5gJAkUfg==} - engines: {node: ^20.19.0 || >=22.12.0} - hasBin: true - rolldown@1.0.0-rc.15: resolution: {integrity: sha512-Ff31guA5zT6WjnGp0SXw76X6hzGRk/OQq2hE+1lcDe+lJdHSgnSX6nK3erbONHyCbpSj9a9E+uX/OvytZoWp2g==} engines: {node: ^20.19.0 || >=22.12.0} @@ -17328,6 +17211,11 @@ packages: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} + unplugin-basemove@0.0.1: + resolution: {integrity: sha512-U1XlGlzhmppJwNbCLMHZCr9srhRclpCTa70vcOoe8B9CGcmQ5ykqqsNc4p3twHLifsmorWL0mXgjWd71y89VSA==} + peerDependencies: + vite: ^5.0.0 || ^6.0.0 + unplugin-combine@2.3.0: resolution: {integrity: sha512-0aZjv0JqOCPY+yujTatSwlCbsK6bMcBUZDlpMHTlc7KDc2gq8XL5cPgEOeS2GZ767BHAonkEqhC+NlOvzzm5FA==} engines: {node: '>=20.19.0'} @@ -22251,8 +22139,6 @@ snapshots: '@oxc-project/types@0.126.0': {} - '@oxc-project/types@0.98.0': {} - '@oxc-resolver/binding-android-arm-eabi@11.19.1': optional: true @@ -22900,63 +22786,42 @@ snapshots: '@rive-app/canvas-lite@2.37.2': {} - '@rolldown/binding-android-arm64@1.0.0-beta.51': - optional: true - '@rolldown/binding-android-arm64@1.0.0-rc.15': optional: true '@rolldown/binding-android-arm64@1.0.0-rc.16': optional: true - '@rolldown/binding-darwin-arm64@1.0.0-beta.51': - optional: true - '@rolldown/binding-darwin-arm64@1.0.0-rc.15': optional: true '@rolldown/binding-darwin-arm64@1.0.0-rc.16': optional: true - '@rolldown/binding-darwin-x64@1.0.0-beta.51': - optional: true - '@rolldown/binding-darwin-x64@1.0.0-rc.15': optional: true '@rolldown/binding-darwin-x64@1.0.0-rc.16': optional: true - '@rolldown/binding-freebsd-x64@1.0.0-beta.51': - optional: true - '@rolldown/binding-freebsd-x64@1.0.0-rc.15': optional: true '@rolldown/binding-freebsd-x64@1.0.0-rc.16': optional: true - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.51': - optional: true - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.15': optional: true '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.16': optional: true - '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.51': - optional: true - '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.15': optional: true '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.16': optional: true - '@rolldown/binding-linux-arm64-musl@1.0.0-beta.51': - optional: true - '@rolldown/binding-linux-arm64-musl@1.0.0-rc.15': optional: true @@ -22975,41 +22840,24 @@ snapshots: '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.16': optional: true - '@rolldown/binding-linux-x64-gnu@1.0.0-beta.51': - optional: true - '@rolldown/binding-linux-x64-gnu@1.0.0-rc.15': optional: true '@rolldown/binding-linux-x64-gnu@1.0.0-rc.16': optional: true - '@rolldown/binding-linux-x64-musl@1.0.0-beta.51': - optional: true - '@rolldown/binding-linux-x64-musl@1.0.0-rc.15': optional: true '@rolldown/binding-linux-x64-musl@1.0.0-rc.16': optional: true - '@rolldown/binding-openharmony-arm64@1.0.0-beta.51': - optional: true - '@rolldown/binding-openharmony-arm64@1.0.0-rc.15': optional: true '@rolldown/binding-openharmony-arm64@1.0.0-rc.16': optional: true - '@rolldown/binding-wasm32-wasi@1.0.0-beta.51(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)': - dependencies: - '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) - transitivePeerDependencies: - - '@emnapi/core' - - '@emnapi/runtime' - optional: true - '@rolldown/binding-wasm32-wasi@1.0.0-rc.15': dependencies: '@emnapi/core': 1.9.2 @@ -23024,29 +22872,18 @@ snapshots: '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) optional: true - '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.51': - optional: true - '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.15': optional: true '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.16': optional: true - '@rolldown/binding-win32-ia32-msvc@1.0.0-beta.51': - optional: true - - '@rolldown/binding-win32-x64-msvc@1.0.0-beta.51': - optional: true - '@rolldown/binding-win32-x64-msvc@1.0.0-rc.15': optional: true '@rolldown/binding-win32-x64-msvc@1.0.0-rc.16': optional: true - '@rolldown/pluginutils@1.0.0-beta.51': {} - '@rolldown/pluginutils@1.0.0-rc.13': {} '@rolldown/pluginutils@1.0.0-rc.15': {} @@ -31687,29 +31524,6 @@ snapshots: transitivePeerDependencies: - oxc-resolver - rolldown@1.0.0-beta.51(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2): - dependencies: - '@oxc-project/types': 0.98.0 - '@rolldown/pluginutils': 1.0.0-beta.51 - optionalDependencies: - '@rolldown/binding-android-arm64': 1.0.0-beta.51 - '@rolldown/binding-darwin-arm64': 1.0.0-beta.51 - '@rolldown/binding-darwin-x64': 1.0.0-beta.51 - '@rolldown/binding-freebsd-x64': 1.0.0-beta.51 - '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-beta.51 - '@rolldown/binding-linux-arm64-gnu': 1.0.0-beta.51 - '@rolldown/binding-linux-arm64-musl': 1.0.0-beta.51 - '@rolldown/binding-linux-x64-gnu': 1.0.0-beta.51 - '@rolldown/binding-linux-x64-musl': 1.0.0-beta.51 - '@rolldown/binding-openharmony-arm64': 1.0.0-beta.51 - '@rolldown/binding-wasm32-wasi': 1.0.0-beta.51(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) - '@rolldown/binding-win32-arm64-msvc': 1.0.0-beta.51 - '@rolldown/binding-win32-ia32-msvc': 1.0.0-beta.51 - '@rolldown/binding-win32-x64-msvc': 1.0.0-beta.51 - transitivePeerDependencies: - - '@emnapi/core' - - '@emnapi/runtime' - rolldown@1.0.0-rc.15: dependencies: '@oxc-project/types': 0.124.0 @@ -33041,6 +32855,18 @@ snapshots: unpipe@1.0.0: {} + unplugin-basemove@0.0.1(vite@6.4.2(@types/node@25.6.0)(jiti@2.6.1)(less@4.6.4)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)): + dependencies: + s3mini: 0.9.4 + unplugin: 3.0.0 + vite: 6.4.2(@types/node@25.6.0)(jiti@2.6.1)(less@4.6.4)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3) + + unplugin-basemove@0.0.1(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)): + dependencies: + s3mini: 0.9.4 + unplugin: 3.0.0 + vite: 8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3) + unplugin-combine@2.3.0(esbuild@0.27.2)(rolldown@1.0.0-rc.16)(rollup@2.80.0)(unplugin@2.3.11)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)): optionalDependencies: esbuild: 0.27.2 diff --git a/vitest.config.ts b/vitest.config.ts index e4198c552..23d011e44 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -15,7 +15,6 @@ export default defineConfig({ 'packages/server-runtime', 'packages/server-sdk', 'packages/stage-shared', - 'packages/vite-plugin-warpdrive', ], }, })