跳到主要内容

JavaScript API 参考

Egern 脚本使用 export default 导出一个 async 函数,运行时会将 ctx 对象注入该函数。

export default async function(ctx) {
// ...
}

支持五种脚本类型:RequestResponseScheduleGenericNetwork


ctx

ctx.script

脚本信息。

属性类型说明
ctx.script.namestring脚本名称

ctx.env

Object<string, string> — 环境变量键值对。详见 环境变量

export default async function(ctx) {
const apiKey = ctx.env.API_KEY;
const apiUrl = ctx.env.API_URL;
}

ctx.app

应用信息。

属性类型说明
ctx.app.versionstring应用版本
ctx.app.languagestring系统语言

ctx.device

设备网络环境信息。

属性类型说明
ctx.device.cellular.carrierstring | null蜂窝运营商
ctx.device.cellular.radiostring | null蜂窝网络制式
ctx.device.wifi.ssidstring | nullWi-Fi 名称
ctx.device.wifi.bssidstring | nullWi-Fi BSSID
ctx.device.ipv4.addressstring | nullIPv4 地址
ctx.device.ipv4.gatewaystring | nullIPv4 网关
ctx.device.ipv4.interfacestring | null网络接口
ctx.device.ipv6.addressstring | nullIPv6 地址
ctx.device.ipv6.interfacestring | null网络接口
ctx.device.dnsServersstring[]DNS 服务器列表

ctx.cron

string | undefined — 仅在 schedule 类型脚本中可用,值为 cron 表达式。

ctx.widgetFamily

string | undefined — 仅在 generic 类型脚本中可用,表示小组件尺寸系列。

可能的值:systemSmallsystemMediumsystemLargesystemExtraLargeaccessoryCircularaccessoryRectangularaccessoryInline

ctx.request

Object | undefined — 仅在 request/response 脚本中可用。

属性/方法类型说明
methodstringHTTP 方法
urlstring请求 URL
headersHeaders请求头
bodyReadableStream | null请求体流
json()Promise<any>解析为 JSON
text()Promise<string>解析为文本
arrayBuffer()Promise<ArrayBuffer>解析为 ArrayBuffer
blob()Promise<Blob>解析为 Blob
formData()Promise<FormData>解析为 FormData

注意:body 只能消费一次(与 Fetch API 行为一致)。

ctx.response

Object | undefined — 仅在 response 脚本中可用。

属性/方法类型说明
statusnumber状态码
headersHeaders响应头
bodyReadableStream | null响应体流
json()Promise<any>解析为 JSON
text()Promise<string>解析为文本
arrayBuffer()Promise<ArrayBuffer>解析为 ArrayBuffer
blob()Promise<Blob>解析为 Blob
formData()Promise<FormData>解析为 FormData

注意:body 只能消费一次(与 Fetch API 行为一致)。

Headers 对象

ctx.request.headersctx.response.headersctx.http 响应的 headers 均为 Headers 对象,支持大小写无关的属性访问和以下方法:

方法返回值说明
headers.get(name)string | null获取值(多值用 , 合并)
headers.getAll(name)string[]获取所有值(始终返回数组)
headers.has(name)boolean是否存在
headers.set(name, value)void设置(替换已有值)
headers.append(name, value)void追加值
headers.delete(name)void删除

所有方法的 name 参数均大小写无关。直接属性访问同样大小写无关,单值返回 string,多值返回 string[]

// 以下访问等价
headers['Content-Type'] // 'application/json'
headers['content-type'] // 'application/json'

// 多值 header
headers['set-cookie'] // ['session=abc', 'token=xyz']
headers.get('set-cookie') // 'session=abc, token=xyz'
headers.getAll('set-cookie') // ['session=abc', 'token=xyz']

// 修改
headers.set('X-Custom', 'value');
headers.append('X-Custom', 'value2');
headers.delete('X-Custom');
headers['X-New'] = 'value';
delete headers['X-New'];

ctx.http

发送 HTTP 请求。所有方法返回 Promise<Response>

方法

ctx.http.get(url, options?)
ctx.http.post(url, options?)
ctx.http.put(url, options?)
ctx.http.delete(url, options?)
ctx.http.head(url, options?)
ctx.http.options(url, options?)
ctx.http.patch(url, options?)

参数

  • urlstring,请求 URL。
  • options — 可选对象:
字段类型说明
headersHeaders | Object<string, string | string[]>请求头(多值 header 为数组)
bodystring | Uint8Array | Object | ReadableStream请求体(Object 会自动 JSON 序列化)
timeoutnumber超时时间(毫秒)
policystring代理策略
policyDescriptorstring策略描述符
redirect'follow' | 'manual' | 'error'重定向策略(默认 'follow');manual 返回 3xx 响应,error 遇到重定向时抛异常
credentials'omit' | 'include'是否携带 Cookie(默认 'include'
insecureTlsboolean是否允许不安全的 TLS(默认 false

Response 对象

属性/方法类型说明
statusnumber状态码
headersHeaders响应头
bodyReadableStream响应体流
json()Promise<any>解析为 JSON
text()Promise<string>解析为文本
blob()Promise<Blob>解析为 Blob
arrayBuffer()Promise<ArrayBuffer>解析为 ArrayBuffer
formData()Promise<FormData>解析为 FormData

注意:body 只能消费一次(与 Fetch API 行为一致)。

示例

const resp = await ctx.http.get('https://api.example.com/data');
const data = await resp.json();

ctx.storage

持久化键值存储。

方法返回值说明
ctx.storage.get(key)string | null读取值
ctx.storage.set(key, value)void写入值(value 为 string)
ctx.storage.getJSON(key)any | null读取值并 JSON 解析
ctx.storage.setJSON(key, value)voidJSON 序列化后写入
ctx.storage.delete(key)void删除键

示例

ctx.storage.set('token', 'abc123');
const token = ctx.storage.get('token'); // 'abc123'
ctx.storage.delete('token');

// JSON 便捷方法
ctx.storage.setJSON('config', { theme: 'dark', lang: 'zh' });
const config = ctx.storage.getJSON('config'); // { theme: 'dark', lang: 'zh' }

ctx.notify(options)

发送通知。

字段类型说明
titlestring标题
subtitlestring副标题(可选)
bodystring内容(可选)
soundboolean是否播放提示音(默认 true
durationnumber通知展示时长,单位为秒(可选)
attachmentObject通知附件(可选)
attachment.urlstring媒体 URL,自动下载作为附件(与 base64 二选一)
attachment.base64stringBase64 编码的媒体数据(与 url 二选一)
attachment.mimeTypestringMIME 类型(可选,gif/png/jpg/pdf 可自动检测)
actionObject点击通知时的行为(可选)
action.typestring"openUrl""clipboard"
action.urlstringtype 为 "openUrl" 时打开的 URL
action.textstringtype 为 "clipboard" 时复制的文本

示例

// 基本通知
ctx.notify({ title: 'Done', body: 'Task completed' });

// 带附件和点击行为
ctx.notify({
title: '截图已保存',
body: '点击查看详情',
sound: true,
duration: 5,
attachment: {
url: 'https://example.com/image.png',
mimeType: 'image/png',
},
action: {
type: 'openUrl',
url: 'https://example.com/details',
},
});

// 使用 base64 附件 + 复制到剪贴板
ctx.notify({
title: '验证码',
body: '1234',
attachment: {
base64: 'iVBORw0KGgo...',
mimeType: 'image/png',
},
action: {
type: 'clipboard',
text: '1234',
},
});

ctx.lookupIP(ip)

查询 IP 地址信息。

  • ipstring,IP 地址。
  • 返回 Object | null
属性类型说明
countrystring国家/地区代码
asnnumberAS 号
organizationstring组织名称

示例

const info = ctx.lookupIP('8.8.8.8');
// { country: 'US', asn: 15169, organization: 'GOOGLE' }

ctx.compress

压缩/解压缩,输入输出均为 Uint8Array。所有方法返回 Promise<Uint8Array | null>

方法说明
ctx.compress.gzip(data)Gzip 压缩
ctx.compress.gunzip(data)Gzip 解压
ctx.compress.deflate(data)Deflate 压缩
ctx.compress.inflate(data)Deflate 解压
ctx.compress.brotli(data)Brotli 压缩
ctx.compress.unbrotli(data)Brotli 解压

ctx.respond(response)

在 request 脚本中直接返回响应,不将请求发送到上游服务器。

  • response — 对象:
字段类型说明
statusnumber状态码
headersHeaders | Object<string, string | string[]>响应头(可选,多值 header 为数组)
bodystring | Uint8Array | Object | ReadableStream响应体(可选,Object 会自动 JSON 序列化)
return ctx.respond({ status: 200, headers: { 'Content-Type': 'text/plain' }, body: 'blocked' });

ctx.abort()

中止当前请求或响应,用于 request/response 脚本。

return ctx.abort();

返回值

函数的返回值决定脚本行为,不同脚本类型返回不同结构。

Request 脚本

执行于 HTTP 请求发送之前,可修改请求、直接返回响应或中止请求。

返回对象修改请求,所有字段均可选,省略的字段保持原值不变。

字段类型说明
methodstringHTTP 方法
urlstring请求 URL
headersHeaders | Object<string, string | string[]>请求头(多值 header 为数组)
bodystring | Uint8Array | Object | ReadableStream请求体(Object 会自动 JSON 序列化)

也可使用 ctx.respond() 直接返回响应、ctx.abort() 中止请求,或不返回以透传。

// 修改请求
return { url: 'https://...', headers: { ... }, body: '...' };

// 透传 body 流
return { url: 'https://...', body: ctx.request.body };

// 直接返回响应
return ctx.respond({ status: 200, headers: {}, body: 'blocked' });

// 中止请求
return ctx.abort();

Response 脚本

执行于 HTTP 响应返回给客户端之前,可修改响应或中止连接。

返回对象修改响应,所有字段均可选,省略的字段保持原值不变。

字段类型说明
statusnumber状态码
headersHeaders | Object<string, string | string[]>响应头(多值 header 为数组)
bodystring | Uint8Array | Object | ReadableStream响应体(Object 会自动 JSON 序列化)

也可使用 ctx.abort() 中止,或不返回以透传。

return { status: 200, headers: { ... }, body: '...' };
return ctx.abort();

Generic 脚本

返回 Widget DSL JSON 对象,Egern 将其渲染为 iOS 小组件。根节点必须为 type: "widget"

return {
type: 'widget',
children: [
{ type: 'text', text: 'Status: OK', font: { size: 'headline', weight: 'semibold' }, textColor: '#FFFFFF' }
],
backgroundColor: '#2D6A4F',
padding: 16,
};

Schedule / Network 脚本

无需返回值。


完整示例

Request — 重写 URL

export default async function(ctx) {
return { url: ctx.request.url.replace('http://', 'https://') };
}

Response — 修改 JSON 响应体

export default async function(ctx) {
const data = await ctx.response.json();
data.ads = [];
return { body: data };
}

Request — 拦截广告

export default async function(ctx) {
if (ctx.request.url.includes('/ads')) return ctx.abort();
}

Schedule — 定时任务

export default async function(ctx) {
const resp = await ctx.http.get('https://api.example.com/data');
const data = await resp.json();
ctx.storage.set('latest', JSON.stringify(data));
ctx.notify({ title: 'Updated', body: `${data.length} items` });
}

Generic — 小组件

export default async function(ctx) {
const resp = await ctx.http.get('https://api.example.com/status');
const status = await resp.text();
return {
type: 'widget',
children: [
{ type: 'text', text: 'Server Status', font: { size: 'headline', weight: 'bold' }, textColor: '#FFFFFF' },
{ type: 'text', text: status, font: { size: 'body' }, textColor: '#FFFFFFCC' },
],
backgroundColor: '#1A1A2E',
padding: 16,
gap: 8,
};
}