diff --git a/packages/vite-plugin-warpdrive/src/index.ts b/packages/vite-plugin-warpdrive/src/index.ts index 12c6388ae..13b6093b2 100644 --- a/packages/vite-plugin-warpdrive/src/index.ts +++ b/packages/vite-plugin-warpdrive/src/index.ts @@ -138,7 +138,7 @@ export function WarpDrivePlugin(options: WarpDrivePluginOptions): Plugin { return } if (!options.provider) { - resolvedConfig.logger?.warn?.(`[${pluginName}] no upload provider configured, skipping upload step`) + resolvedConfig.logger.warn(`[${pluginName}] no upload provider configured, skipping upload step`) return } @@ -186,13 +186,13 @@ export function WarpDrivePlugin(options: WarpDrivePluginOptions): Plugin { return } if (!options.provider) { - resolvedConfig.logger?.warn?.(`[${pluginName}] no upload provider configured, skipping upload step`) + resolvedConfig.logger.warn(`[${pluginName}] no upload provider configured, skipping upload step`) return } if (!pendingUploads.length) return if (isDryRun) { - resolvedConfig.logger.info?.( + resolvedConfig.logger.info( `[${pluginName}] dry run enabled; skipping clean/upload for ${pendingUploads.length} assets`, ) return @@ -200,16 +200,16 @@ export function WarpDrivePlugin(options: WarpDrivePluginOptions): Plugin { if (shouldCleanRemote && !cleanedRemote) { if (!prefix) { - resolvedConfig.logger?.warn?.(`[${pluginName}] skipping clean step because no prefix provided`) + 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}`) + resolvedConfig.logger.info(`[${pluginName}] cleaning remote prefix: ${prefix}`) await options.provider.cleanPrefix(prefix) - resolvedConfig.logger.info?.(`[${pluginName}] cleaned remote prefix: ${prefix}`) + resolvedConfig.logger.info(`[${pluginName}] cleaned remote prefix: ${prefix}`) cleanedRemote = true } else { - resolvedConfig.logger?.warn?.( + resolvedConfig.logger.warn( `[${pluginName}] clean is enabled but provider does not support prefix cleaning; skipping`, ) } @@ -224,7 +224,7 @@ export function WarpDrivePlugin(options: WarpDrivePluginOptions): Plugin { try { const skip = await options.provider.shouldSkipUpload(localPath, key) if (skip) { - resolvedConfig.logger.info?.( + resolvedConfig.logger.info( `[${pluginName}] skipped upload (not modified): ${fileName} -> ${key}`, ) if (shouldDeleteLocalAsset) { @@ -233,14 +233,14 @@ export function WarpDrivePlugin(options: WarpDrivePluginOptions): Plugin { resolvedConfig.logger.info(`[${pluginName}] deleted local asset: ${fileName}`) } catch (error) { - resolvedConfig.logger.warn?.(`[${pluginName}] failed to delete local asset ${fileName}: ${error}`) + resolvedConfig.logger.warn(`[${pluginName}] failed to delete local asset ${fileName}: ${error}`) } } return } } catch (error) { - resolvedConfig.logger.warn?.( + resolvedConfig.logger.warn( `[${pluginName}] could not determine if upload should be skipped for ${fileName}: ${error}`, ) } @@ -259,7 +259,7 @@ export function WarpDrivePlugin(options: WarpDrivePluginOptions): Plugin { resolvedConfig.logger.info(`[${pluginName}] deleted local asset: ${fileName}`) } catch (error) { - resolvedConfig.logger.warn?.(`[${pluginName}] failed to delete local asset ${fileName}: ${error}`) + resolvedConfig.logger.warn(`[${pluginName}] failed to delete local asset ${fileName}: ${error}`) } } })()) @@ -278,5 +278,6 @@ function normalizePrefix(prefix: string) { 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 new file mode 100644 index 000000000..8ea143ee8 --- /dev/null +++ b/packages/vite-plugin-warpdrive/src/providers/s3.test.ts @@ -0,0 +1,28 @@ +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 index 5ea173f79..23056d81e 100644 --- a/packages/vite-plugin-warpdrive/src/providers/s3.ts +++ b/packages/vite-plugin-warpdrive/src/providers/s3.ts @@ -1,11 +1,12 @@ -import { createHash } from 'node:crypto' -import { readFile } from 'node:fs/promises' -import { join } from 'node:path' - -import { S3mini } from 's3mini' +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 @@ -45,6 +46,7 @@ export function createS3Provider(options: S3ProviderOptions): UploadProvider { const normalizedPrefix = normalizePrefix(prefix) if (!normalizedPrefix) return + const objects = await client.listObjects('/', `${normalizedPrefix}/`) if (!objects?.length) return diff --git a/packages/vite-plugin-warpdrive/vitest.config.ts b/packages/vite-plugin-warpdrive/vitest.config.ts new file mode 100644 index 000000000..a3ee64355 --- /dev/null +++ b/packages/vite-plugin-warpdrive/vitest.config.ts @@ -0,0 +1,14 @@ +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/services/telegram-bot/vitest.config.ts b/services/telegram-bot/vitest.config.ts index 44f5922a2..2b2f9f3ab 100644 --- a/services/telegram-bot/vitest.config.ts +++ b/services/telegram-bot/vitest.config.ts @@ -10,7 +10,7 @@ export default defineConfig(({ mode }) => { test: { // mode defines what ".env.{mode}" file to choose if exists env: loadEnv(mode, cwd(), ''), - workspace: [ + projects: [ { extends: true, test: { diff --git a/vitest.config.ts b/vitest.config.ts index da11910bc..7404ad00a 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -3,8 +3,8 @@ import { defineConfig } from 'vitest/config' export default defineConfig({ test: { projects: [ - 'packages/injecta', 'packages/stage-ui', + 'packages/vite-plugin-warpdrive', ], }, })