Compare commits

17 Commits

Author SHA1 Message Date
b3db73c8c7 chore(deps): update dependency @vitest/eslint-plugin to v1.3.10
All checks were successful
renovate/stability-days Updates have met minimum release age requirement
/ playwright (push) Successful in 2m8s
CI/CD Pipeline / build-and-deploy (push) Successful in 3m17s
2025-09-18 22:07:33 +08:00
严浩
70688a626b refactor(eslint.config.ts): 在ESLint配置中添加对worker-configuration.d.ts的忽略
All checks were successful
CI/CD Pipeline / build-and-deploy (push) Successful in 3m44s
/ playwright (push) Successful in 4m38s
2025-09-18 15:20:52 +08:00
严浩
7255675c9b ci(.github/workflows/ci-cd.yaml): 添加条件判断以限制部署到Cloudflare
Some checks failed
CI/CD Pipeline / build-and-deploy (push) Has been cancelled
/ playwright (push) Has been cancelled
2025-09-18 15:19:47 +08:00
严浩
f92ef0f870 feat: 添加 UnoCSS 样式到主要组件
All checks were successful
CI/CD Pipeline / build-and-deploy (push) Successful in 3m34s
/ playwright (push) Successful in 3m51s
- AppLayout.vue: 添加渐变背景和响应式布局
- App.vue: 美化主页面,包含卡片布局和绿色主题按钮
- index.page.vue: 创建彩色渐变的英雄区块,包含动画效果和交互卡片

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-18 13:16:22 +08:00
严浩
c928aa72bc chore(ci-cd): 重构工作流,合并构建和部署步骤
All checks were successful
/ playwright (push) Successful in 2m57s
CI/CD Pipeline / build-and-deploy (push) Successful in 4m3s
2025-09-18 12:57:00 +08:00
严浩
077e7b5c90 chore(deps): 更新依赖和配置
Some checks failed
CI/CD Pipeline / lint-build-and-typecheck (push) Successful in 2m0s
CI/CD Pipeline / deploy (push) Has been cancelled
/ playwright (push) Has been cancelled
2025-09-18 12:54:13 +08:00
df0109205f chore(deps): update dependency @types/node to v22.18.5
All checks were successful
renovate/stability-days Updates have met minimum release age requirement
CI/CD Pipeline / lint-build-and-typecheck (push) Successful in 2m43s
/ playwright (push) Successful in 3m15s
CI/CD Pipeline / deploy (push) Successful in 1m23s
2025-09-18 05:58:24 +08:00
266192ffff chore(deps): update dependency @types/node to v22.18.4 2025-09-17 12:15:35 +08:00
74b608a2da chore(deps): update dependency unplugin-icons to v22.3.0 2025-09-15 09:38:54 +08:00
0dddb07909 chore(deps): update dependency eslint-plugin-oxlint to ~1.15.0 2025-09-15 06:28:18 +08:00
7305a7a4c0 chore(deps): update dependency vite-plugin-vue-devtools to v8.0.2 2025-09-15 03:30:02 +08:00
6fcc87b4dd chore(deps): update dependency oxlint to ~1.15.0 2025-09-14 18:44:09 +08:00
e7d701dfc6 chore(deps): update dependency @types/node to v22.18.3 2025-09-14 09:01:29 +08:00
671cea101b chore(deps): update dependency @intlify/unplugin-vue-i18n to v11.0.1 2025-09-14 02:06:31 +08:00
严浩
eb600d0b6b chore(package): 更新依赖包版本 2025-09-11 16:18:05 +08:00
严浩
87e701042f ci: 优化 GitHub Actions 工作流并添加单元测试 2025-09-09 23:22:35 +08:00
严浩
306ed9a527 ci: 更新 Playwright 配置以使用预览服务器
- 将 baseURL 固定为 http://localhost:4173,不再根据环境变量区分 CI 和本地环境
- 修改启动命令为先构建再启动预览服务器
- 设置 reuseExistingServer 为 true,优化服务器重用逻辑

(cherry picked from commit df6ffb99c8)
2025-09-09 23:11:00 +08:00
13 changed files with 626 additions and 610 deletions

2
.env
View File

@@ -1,2 +1,4 @@
VITE_BASE=/
VITE_BUILD_SOURCE_MAP=true
VITE_BUILD_COMMIT= VITE_BUILD_COMMIT=
VITE_BUILD_TIME= VITE_BUILD_TIME=

View File

@@ -12,7 +12,7 @@ on:
workflow_dispatch: workflow_dispatch:
jobs: jobs:
lint-build-and-typecheck: build-and-deploy:
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: gitea/runner-images:ubuntu-latest-slim # https://github.com/cloudflare/wrangler-action/issues/329#issuecomment-3046747722 container: gitea/runner-images:ubuntu-latest-slim # https://github.com/cloudflare/wrangler-action/issues/329#issuecomment-3046747722
@@ -28,6 +28,9 @@ jobs:
env: env:
VITE_BUILD_COMMIT: ${{ github.sha }} VITE_BUILD_COMMIT: ${{ github.sha }}
- name: 🧪 单元测试
run: pnpm run test:unit
- name: 📊 计算构建大小 - name: 📊 计算构建大小
run: | run: |
echo "📊 构建大小统计:" echo "📊 构建大小统计:"
@@ -41,33 +44,8 @@ jobs:
- name: ✅ 类型检查 - name: ✅ 类型检查
run: pnpm run type-check # 要先 build保证 components.d.ts 存在 run: pnpm run type-check # 要先 build保证 components.d.ts 存在
deploy:
runs-on: ubuntu-latest
needs: lint-build-and-typecheck
if: github.ref == 'refs/heads/main'
# https://github.com/cloudflare/wrangler-action/issues/329#issuecomment-3046747722
container:
image: gitea/runner-images:ubuntu-latest-slim
steps:
- name: 🛠️ 设置Node环境
uses: yanhao98/composite-actions/setup-node-environment@25eb4dc0c134cc9df2b7c569aa54140a366b45a8
- name: 📦 构建项目
run: pnpm run build-only
env:
VITE_BUILD_COMMIT: ${{ github.sha }}
# - name: 🚀 上传版本到 Cloudflare
# uses: cloudflare/wrangler-action@v3
# id: upload
# with:
# apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
# accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
# command: versions upload --tag "${{ github.sha }}" --message "Deploy commit ${{ github.sha }} from ${{ github.ref_name }}"
- name: 🚀 部署到 Cloudflare - name: 🚀 部署到 Cloudflare
if: github.ref == 'refs/heads/main'
uses: cloudflare/wrangler-action@v3 uses: cloudflare/wrangler-action@v3
with: with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}

2
.npmrc
View File

@@ -1,4 +1,4 @@
registry=https://registry.npmmirror.com/ # registry=https://registry.npmmirror.com/
# https://pnpm.io/zh/npmrc#node-mirrorltreleasedir # https://pnpm.io/zh/npmrc#node-mirrorltreleasedir
use-node-version=24.7.0 use-node-version=24.7.0

View File

@@ -55,6 +55,5 @@ test.describe('Vue App', () => {
await page.goto('/') await page.goto('/')
const appLayout = page.locator('.app-layout') const appLayout = page.locator('.app-layout')
await expect(appLayout).toBeVisible() await expect(appLayout).toBeVisible()
await expect(appLayout).toContainText('AppLayout')
}) })
}) })

View File

@@ -17,7 +17,7 @@ export default defineConfigWithVueTs(
files: ['**/*.{ts,mts,tsx,vue}'], files: ['**/*.{ts,mts,tsx,vue}'],
}, },
globalIgnores(['**/dist/**', '**/dist-ssr/**', '**/coverage/**']), globalIgnores(['worker-configuration.d.ts', '**/dist/**', '**/dist-ssr/**', '**/coverage/**']),
pluginVue.configs['flat/essential'], pluginVue.configs['flat/essential'],
vueTsConfigs.recommended, vueTsConfigs.recommended,

View File

@@ -1,4 +1,5 @@
{ {
"packageManager": "pnpm@10.15.1",
"name": "vue-ts-example-2025", "name": "vue-ts-example-2025",
"version": "0.0.0", "version": "0.0.0",
"private": true, "private": true,
@@ -32,6 +33,7 @@
"wrangler:deploy": "pnpm run build && wrangler deploy", "wrangler:deploy": "pnpm run build && wrangler deploy",
"wrangler:versions:upload": "pnpm run build && wrangler versions upload", "wrangler:versions:upload": "pnpm run build && wrangler versions upload",
"cf-typegen": "wrangler types", "cf-typegen": "wrangler types",
"postinstall": "wrangler types",
"_dep:dedupe": "pnpm dedupe", "_dep:dedupe": "pnpm dedupe",
"_dep:update": "pnpm dlx taze major --interactive", "_dep:update": "pnpm dlx taze major --interactive",
"_sizecheck:Treemap": "pnpm dlx vite-bundle-visualizer -t treemap", "_sizecheck:Treemap": "pnpm dlx vite-bundle-visualizer -t treemap",
@@ -48,15 +50,13 @@
] ]
}, },
"pnpm": { "pnpm": {
"overrides": { "overrides": {}
"vite": "$vite"
}
}, },
"dependencies": { "dependencies": {
"@commitlint/cli": "^19.8.1", "@commitlint/cli": "^19.8.1",
"@commitlint/config-conventional": "^19.8.1", "@commitlint/config-conventional": "^19.8.1",
"@formkit/auto-animate": "^0.9.0", "@formkit/auto-animate": "^0.9.0",
"@pinia/colada": "^0.17.3", "@pinia/colada": "^0.17.4",
"@primeuix/themes": "^1.2.3", "@primeuix/themes": "^1.2.3",
"@unhead/vue": "^2.0.14", "@unhead/vue": "^2.0.14",
"@vueuse/core": "^13.9.0", "@vueuse/core": "^13.9.0",
@@ -70,7 +70,7 @@
"vue-router": "^4.5.1" "vue-router": "^4.5.1"
}, },
"devDependencies": { "devDependencies": {
"@cloudflare/vite-plugin": "^1.12.4", "@cloudflare/vite-plugin": "^1.13.2",
"@commitlint/types": "^19.8.1", "@commitlint/types": "^19.8.1",
"@intlify/unplugin-vue-i18n": "^11.0.0", "@intlify/unplugin-vue-i18n": "^11.0.0",
"@playwright/test": "^1.55.0", "@playwright/test": "^1.55.0",
@@ -89,7 +89,7 @@
"@vue/test-utils": "^2.4.6", "@vue/test-utils": "^2.4.6",
"@vue/tsconfig": "^0.8.1", "@vue/tsconfig": "^0.8.1",
"eslint": "^9.35.0", "eslint": "^9.35.0",
"eslint-plugin-oxlint": "~1.14.0", "eslint-plugin-oxlint": "~1.15.0",
"eslint-plugin-playwright": "^2.2.2", "eslint-plugin-playwright": "^2.2.2",
"eslint-plugin-vue": "~10.4.0", "eslint-plugin-vue": "~10.4.0",
"husky": "^9.1.7", "husky": "^9.1.7",
@@ -98,9 +98,8 @@
"lint-staged": "^16.1.6", "lint-staged": "^16.1.6",
"npm-run-all2": "^8.0.4", "npm-run-all2": "^8.0.4",
"nprogress": "^0.2.0", "nprogress": "^0.2.0",
"oxlint": "~1.14.0", "oxlint": "~1.15.0",
"prettier": "3.6.2", "prettier": "3.6.2",
"rolldown": "1.0.0-beta.36",
"typescript": "~5.9.2", "typescript": "~5.9.2",
"unocss": "^66.5.1", "unocss": "^66.5.1",
"unocss-preset-animations": "^1.2.1", "unocss-preset-animations": "^1.2.1",
@@ -109,7 +108,7 @@
"unplugin-vue-components": "^29.0.0", "unplugin-vue-components": "^29.0.0",
"unplugin-vue-markdown": "^29.1.0", "unplugin-vue-markdown": "^29.1.0",
"unplugin-vue-router": "^0.15.0", "unplugin-vue-router": "^0.15.0",
"vite": "npm:rolldown-vite@^7.1.8", "vite": "^7.1.5",
"vite-plugin-checker": "^0.10.3", "vite-plugin-checker": "^0.10.3",
"vite-plugin-fake-server": "^2.2.0", "vite-plugin-fake-server": "^2.2.0",
"vite-plugin-image-optimizer": "^2.0.2", "vite-plugin-image-optimizer": "^2.0.2",
@@ -119,6 +118,6 @@
"vitest": "^3.2.4", "vitest": "^3.2.4",
"vue-macros": "3.0.0-beta.23", "vue-macros": "3.0.0-beta.23",
"vue-tsc": "^3.0.6", "vue-tsc": "^3.0.6",
"wrangler": "^4.35.0" "wrangler": "^4.37.1"
} }
} }

View File

@@ -2,7 +2,7 @@ import { defineConfig, devices } from '@playwright/test'
import process from 'node:process' import process from 'node:process'
// const runningInVSCode = process.env.TERM_PROGRAM === 'vscode' // const runningInVSCode = process.env.TERM_PROGRAM === 'vscode'
const baseURL = process.env.CI ? 'http://localhost:4173' : 'http://localhost:4730' const baseURL = 'http://localhost:4173'
/** /**
* Read environment variables from file. * Read environment variables from file.
@@ -106,8 +106,8 @@ export default defineConfig({
* Use the preview server on CI for more realistic testing. * Use the preview server on CI for more realistic testing.
* Playwright will re-use the local server if there is already a dev-server running. * Playwright will re-use the local server if there is already a dev-server running.
*/ */
command: process.env.CI ? 'pnpm run preview' : 'pnpm run dev', command: 'pnpm run build-only; pnpm run preview',
port: Number(new URL(baseURL).port), port: Number(new URL(baseURL).port),
reuseExistingServer: !process.env.CI, reuseExistingServer: true /* !process.env.CI */,
}, },
}) })

914
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -11,19 +11,37 @@ const getName = async () => {
</script> </script>
<template> <template>
<div> <div class="app-container bg-slate-50 min-h-screen">
<h1>You did it!</h1> <div class="container mx-auto px-6 py-8">
<p> <h1 class="text-4xl font-extrabold text-emerald-600 mb-6 text-center">You did it!</h1>
Visit <a href="https://vuejs.org/" target="_blank" rel="noopener">vuejs.org</a> to read the <div class="bg-white rounded-lg shadow-lg p-8 mb-8">
documentation <p class="text-lg text-gray-700 mb-6 text-center">
</p> Visit
<button class="green" @click="getName" aria-label="get name"> <a
Name from API is: {{ name }} href="https://vuejs.org/"
</button> target="_blank"
rel="noopener"
class="text-emerald-500 hover:text-emerald-700 underline font-semibold"
>
vuejs.org
</a>
to read the documentation
</p>
<div class="flex justify-center">
<button
class="bg-emerald-500 hover:bg-emerald-600 text-white font-bold py-3 px-6 rounded-lg transition-colors duration-200 shadow-md hover:shadow-lg"
@click="getName"
aria-label="get name"
>
Name from API is: {{ name }}
</button>
</div>
</div>
</div>
<DynamicDialog />
<ConfirmDialog />
<Toast />
<RouterView />
</div> </div>
<DynamicDialog /> <ConfirmDialog /> <Toast />
<RouterView />
</template> </template>
<style scoped></style>

View File

@@ -1,9 +1,10 @@
<script setup lang="ts"></script> <script setup lang="ts"></script>
<template> <template>
<div class="app-layout"> <div class="app-layout min-h-screen bg-gradient-to-br from-blue-50 to-indigo-100">
<div>AppLayout</div> <main class="max-w-7xl mx-auto px-4 py-8">
<router-view /> <router-view />
</main>
</div> </div>
</template> </template>

View File

@@ -1,7 +1,31 @@
<script setup lang="ts"></script> <script setup lang="ts"></script>
<template> <template>
<div></div> <div
class="hero-section bg-gradient-to-r from-purple-400 via-pink-500 to-red-500 rounded-xl p-8 shadow-2xl"
>
<div class="text-center">
<h2 class="text-3xl font-bold text-white mb-4 animate-bounce">🎉 This is the index page</h2>
<p class="text-white/90 text-lg mb-6">Welcome to your awesome Vue.js application!</p>
<div class="flex justify-center space-x-4">
<div
class="bg-white/20 backdrop-blur-sm rounded-lg p-4 hover:bg-white/30 transition-all duration-300"
>
<span class="text-white font-semibold">Feature 1</span>
</div>
<div
class="bg-white/20 backdrop-blur-sm rounded-lg p-4 hover:bg-white/30 transition-all duration-300"
>
<span class="text-white font-semibold">Feature 2</span>
</div>
<div
class="bg-white/20 backdrop-blur-sm rounded-lg p-4 hover:bg-white/30 transition-all duration-300"
>
<span class="text-white font-semibold">Feature 3</span>
</div>
</div>
</div>
</div>
</template> </template>
<style scoped></style> <style scoped></style>

View File

@@ -1,18 +1,19 @@
import { fileURLToPath, URL } from 'node:url' import { fileURLToPath, URL } from 'node:url'
import { createViteProxy } from 'utils4u/vite' import { createViteProxy } from 'utils4u/vite'
import { defineConfig, type DepOptimizationOptions } from 'vite' import { defineConfig, loadEnv, type DepOptimizationOptions } from 'vite'
import { Plugins } from './vite.config.plugins' import { Plugins } from './vite.config.plugins'
// import { createRolldownSplitChunks } from './vite.config.rolldown.split-chunks'
// https://vite.dev/config/ // https://vite.dev/config/
export default defineConfig(({ command /* mode */ }) => { export default defineConfig(({ command, mode }) => {
const isBuild = command === 'build' const isBuild = command === 'build'
// const env = loadEnv(mode, process.cwd()) const env = loadEnv(mode, process.cwd())
return { return {
// build: createRolldownSplitChunks(), base: env.VITE_BASE,
// base: env.VITE_BASE, build: {
sourcemap: env.VITE_BUILD_SOURCE_MAP === 'true',
},
plugins: Plugins(), plugins: Plugins(),
resolve: { resolve: {
alias: { alias: {

View File

@@ -1,6 +1,6 @@
/* eslint-disable */ /* eslint-disable */
// Generated by Wrangler by running `wrangler types` (hash: a5d3a0d06638640f4072385a766cb44d) // Generated by Wrangler by running `wrangler types` (hash: a5d3a0d06638640f4072385a766cb44d)
// Runtime types generated with workerd@1.20250902.0 2025-09-09 // Runtime types generated with workerd@1.20250906.0 2025-09-09
declare namespace Cloudflare { declare namespace Cloudflare {
interface Env { interface Env {
KV: KVNamespace; KV: KVNamespace;
@@ -414,7 +414,7 @@ interface DurableObjectId {
equals(other: DurableObjectId): boolean; equals(other: DurableObjectId): boolean;
readonly name?: string; readonly name?: string;
} }
interface DurableObjectNamespace<T extends Rpc.DurableObjectBranded | undefined = undefined> { declare abstract class DurableObjectNamespace<T extends Rpc.DurableObjectBranded | undefined = undefined> {
newUniqueId(options?: DurableObjectNamespaceNewUniqueIdOptions): DurableObjectId; newUniqueId(options?: DurableObjectNamespaceNewUniqueIdOptions): DurableObjectId;
idFromName(name: string): DurableObjectId; idFromName(name: string): DurableObjectId;
idFromString(id: string): DurableObjectId; idFromString(id: string): DurableObjectId;
@@ -432,6 +432,7 @@ interface DurableObjectNamespaceGetDurableObjectOptions {
} }
interface DurableObjectState { interface DurableObjectState {
waitUntil(promise: Promise<any>): void; waitUntil(promise: Promise<any>): void;
props: any;
readonly id: DurableObjectId; readonly id: DurableObjectId;
readonly storage: DurableObjectStorage; readonly storage: DurableObjectStorage;
container?: Container; container?: Container;
@@ -474,6 +475,7 @@ interface DurableObjectStorage {
deleteAlarm(options?: DurableObjectSetAlarmOptions): Promise<void>; deleteAlarm(options?: DurableObjectSetAlarmOptions): Promise<void>;
sync(): Promise<void>; sync(): Promise<void>;
sql: SqlStorage; sql: SqlStorage;
kv: SyncKvStorage;
transactionSync<T>(closure: () => T): T; transactionSync<T>(closure: () => T): T;
getCurrentBookmark(): Promise<string>; getCurrentBookmark(): Promise<string>;
getBookmarkForTime(timestamp: number | Date): Promise<string>; getBookmarkForTime(timestamp: number | Date): Promise<string>;
@@ -2045,6 +2047,7 @@ interface TraceItem {
readonly scriptVersion?: ScriptVersion; readonly scriptVersion?: ScriptVersion;
readonly dispatchNamespace?: string; readonly dispatchNamespace?: string;
readonly scriptTags?: string[]; readonly scriptTags?: string[];
readonly durableObjectId?: string;
readonly outcome: string; readonly outcome: string;
readonly executionModel: string; readonly executionModel: string;
readonly truncated: boolean; readonly truncated: boolean;
@@ -2566,6 +2569,23 @@ declare class MessageChannel {
interface MessagePortPostMessageOptions { interface MessagePortPostMessageOptions {
transfer?: any[]; transfer?: any[];
} }
interface SyncKvStorage {
get<T = unknown>(key: string): T | undefined;
list<T = unknown>(options?: SyncKvListOptions): Iterable<[
string,
T
]>;
put<T>(key: string, value: T): void;
delete(key: string): boolean;
}
interface SyncKvListOptions {
start?: string;
startAfter?: string;
end?: string;
prefix?: string;
reverse?: boolean;
limit?: number;
}
type AiImageClassificationInput = { type AiImageClassificationInput = {
image: number[]; image: number[];
}; };
@@ -5440,7 +5460,7 @@ type AIGatewayHeaders = {
[key: string]: string | number | boolean | object; [key: string]: string | number | boolean | object;
}; };
type AIGatewayUniversalRequest = { type AIGatewayUniversalRequest = {
provider: AIGatewayProviders | string; provider: AIGatewayProviders | string; // eslint-disable-line
endpoint: string; endpoint: string;
headers: Partial<AIGatewayHeaders>; headers: Partial<AIGatewayHeaders>;
query: unknown; query: unknown;
@@ -5456,7 +5476,7 @@ declare abstract class AiGateway {
gateway?: UniversalGatewayOptions; gateway?: UniversalGatewayOptions;
extraHeaders?: object; extraHeaders?: object;
}): Promise<Response>; }): Promise<Response>;
getUrl(provider?: AIGatewayProviders | string): Promise<string>; getUrl(provider?: AIGatewayProviders | string): Promise<string>; // eslint-disable-line
} }
interface AutoRAGInternalError extends Error { interface AutoRAGInternalError extends Error {
} }
@@ -6555,6 +6575,7 @@ type ImageOutputOptions = {
format: 'image/jpeg' | 'image/png' | 'image/gif' | 'image/webp' | 'image/avif' | 'rgb' | 'rgba'; format: 'image/jpeg' | 'image/png' | 'image/gif' | 'image/webp' | 'image/avif' | 'rgb' | 'rgba';
quality?: number; quality?: number;
background?: string; background?: string;
anim?: boolean;
}; };
interface ImagesBinding { interface ImagesBinding {
/** /**
@@ -6613,6 +6634,108 @@ interface ImagesError extends Error {
readonly message: string; readonly message: string;
readonly stack?: string; readonly stack?: string;
} }
/**
* Media binding for transforming media streams.
* Provides the entry point for media transformation operations.
*/
interface MediaBinding {
/**
* Creates a media transformer from an input stream.
* @param media - The input media bytes
* @returns A MediaTransformer instance for applying transformations
*/
input(media: ReadableStream<Uint8Array>): MediaTransformer;
}
/**
* Media transformer for applying transformation operations to media content.
* Handles sizing, fitting, and other input transformation parameters.
*/
interface MediaTransformer {
/**
* Applies transformation options to the media content.
* @param transform - Configuration for how the media should be transformed
* @returns A generator for producing the transformed media output
*/
transform(transform: MediaTransformationInputOptions): MediaTransformationGenerator;
}
/**
* Generator for producing media transformation results.
* Configures the output format and parameters for the transformed media.
*/
interface MediaTransformationGenerator {
/**
* Generates the final media output with specified options.
* @param output - Configuration for the output format and parameters
* @returns The final transformation result containing the transformed media
*/
output(output: MediaTransformationOutputOptions): MediaTransformationResult;
}
/**
* Result of a media transformation operation.
* Provides multiple ways to access the transformed media content.
*/
interface MediaTransformationResult {
/**
* Returns the transformed media as a readable stream of bytes.
* @returns A stream containing the transformed media data
*/
media(): ReadableStream<Uint8Array>;
/**
* Returns the transformed media as an HTTP response object.
* @returns The transformed media as a Response, ready to store in cache or return to users
*/
response(): Response;
/**
* Returns the MIME type of the transformed media.
* @returns The content type string (e.g., 'image/jpeg', 'video/mp4')
*/
contentType(): string;
}
/**
* Configuration options for transforming media input.
* Controls how the media should be resized and fitted.
*/
type MediaTransformationInputOptions = {
/** How the media should be resized to fit the specified dimensions */
fit?: 'contain' | 'cover' | 'scale-down';
/** Target width in pixels */
width?: number;
/** Target height in pixels */
height?: number;
};
/**
* Configuration options for Media Transformations output.
* Controls the format, timing, and type of the generated output.
*/
type MediaTransformationOutputOptions = {
/**
* Output mode determining the type of media to generate
*/
mode?: 'video' | 'spritesheet' | 'frame' | 'audio';
/** Whether to include audio in the output */
audio?: boolean;
/**
* Starting timestamp for frame extraction or start time for clips. (e.g. '2s').
*/
time?: string;
/**
* Duration for video clips, audio extraction, and spritesheet generation (e.g. '5s').
*/
duration?: string;
/**
* Output format for the generated media.
*/
format?: 'jpg' | 'png' | 'm4a';
};
/**
* Error object for media transformation operations.
* Extends the standard Error interface with additional media-specific information.
*/
interface MediaError extends Error {
readonly code: number;
readonly message: string;
readonly stack?: string;
}
type Params<P extends string = any> = Record<P, string | string[]>; type Params<P extends string = any> = Record<P, string | string[]>;
type EventContext<Env, P extends string, Data> = { type EventContext<Env, P extends string, Data> = {
request: Request<unknown, IncomingRequestCfProperties<unknown>>; request: Request<unknown, IncomingRequestCfProperties<unknown>>;
@@ -6999,21 +7122,17 @@ declare namespace TailStream {
readonly tag?: string; readonly tag?: string;
readonly message?: string; readonly message?: string;
} }
interface Trigger {
readonly traceId: string;
readonly invocationId: string;
readonly spanId: string;
}
interface Onset { interface Onset {
readonly type: "onset"; readonly type: "onset";
readonly attributes: Attribute[]; readonly attributes: Attribute[];
// id for the span being opened by this Onset event.
readonly spanId: string;
readonly dispatchNamespace?: string; readonly dispatchNamespace?: string;
readonly entrypoint?: string; readonly entrypoint?: string;
readonly executionModel: string; readonly executionModel: string;
readonly scriptName?: string; readonly scriptName?: string;
readonly scriptTags?: string[]; readonly scriptTags?: string[];
readonly scriptVersion?: ScriptVersion; readonly scriptVersion?: ScriptVersion;
readonly trigger?: Trigger;
readonly info: FetchEventInfo | JsRpcEventInfo | ScheduledEventInfo | AlarmEventInfo | QueueEventInfo | EmailEventInfo | TraceEventInfo | HibernatableWebSocketEventInfo | CustomEventInfo; readonly info: FetchEventInfo | JsRpcEventInfo | ScheduledEventInfo | AlarmEventInfo | QueueEventInfo | EmailEventInfo | TraceEventInfo | HibernatableWebSocketEventInfo | CustomEventInfo;
} }
interface Outcome { interface Outcome {
@@ -7025,6 +7144,8 @@ declare namespace TailStream {
interface SpanOpen { interface SpanOpen {
readonly type: "spanOpen"; readonly type: "spanOpen";
readonly name: string; readonly name: string;
// id for the span being opened by this SpanOpen event.
readonly spanId: string;
readonly info?: FetchEventInfo | JsRpcEventInfo | Attributes; readonly info?: FetchEventInfo | JsRpcEventInfo | Attributes;
} }
interface SpanClose { interface SpanClose {
@@ -7047,6 +7168,10 @@ declare namespace TailStream {
readonly level: "debug" | "error" | "info" | "log" | "warn"; readonly level: "debug" | "error" | "info" | "log" | "warn";
readonly message: object; readonly message: object;
} }
// This marks the worker handler return information.
// This is separate from Outcome because the worker invocation can live for a long time after
// returning. For example - Websockets that return an http upgrade response but then continue
// streaming information or SSE http connections.
interface Return { interface Return {
readonly type: "return"; readonly type: "return";
readonly info?: FetchResponseInfo; readonly info?: FetchResponseInfo;
@@ -7060,9 +7185,28 @@ declare namespace TailStream {
readonly info: Attribute[]; readonly info: Attribute[];
} }
type EventType = Onset | Outcome | SpanOpen | SpanClose | DiagnosticChannelEvent | Exception | Log | Return | Attributes; type EventType = Onset | Outcome | SpanOpen | SpanClose | DiagnosticChannelEvent | Exception | Log | Return | Attributes;
// Context in which this trace event lives.
interface SpanContext {
// Single id for the entire top-level invocation
// This should be a new traceId for the first worker stage invoked in the eyeball request and then
// same-account service-bindings should reuse the same traceId but cross-account service-bindings
// should use a new traceId.
readonly traceId: string;
// spanId in which this event is handled
// for Onset and SpanOpen events this would be the parent span id
// for Outcome and SpanClose these this would be the span id of the opening Onset and SpanOpen events
// For Hibernate and Mark this would be the span under which they were emitted.
// spanId is not set ONLY if:
// 1. This is an Onset event
// 2. We are not inherting any SpanContext. (e.g. this is a cross-account service binding or a new top-level invocation)
readonly spanId?: string;
}
interface TailEvent<Event extends EventType> { interface TailEvent<Event extends EventType> {
// invocation id of the currently invoked worker stage.
// invocation id will always be unique to every Onset event and will be the same until the Outcome event.
readonly invocationId: string; readonly invocationId: string;
readonly spanId: string; // Inherited spanContext for this event.
readonly spanContext: SpanContext;
readonly timestamp: Date; readonly timestamp: Date;
readonly sequence: number; readonly sequence: number;
readonly event: Event; readonly event: Event;