Skip to main content

JavaScript API Reference

Egern scripts use export default to export an async function. The ctx object is injected at runtime.

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

Five script types are supported: Request, Response, Schedule, Generic, and Network.


ctx

ctx.script

Script information.

PropertyTypeDescription
ctx.script.namestringScript name

ctx.env

Object<string, string> — Environment variable key-value pairs. See Environment Variables for details.

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

ctx.app

Application information.

PropertyTypeDescription
ctx.app.versionstringApp version
ctx.app.languagestringSystem language

ctx.device

Device network environment information.

PropertyTypeDescription
ctx.device.cellular.carrierstring | nullCellular carrier
ctx.device.cellular.radiostring | nullCellular radio technology
ctx.device.wifi.ssidstring | nullWi-Fi name
ctx.device.wifi.bssidstring | nullWi-Fi BSSID
ctx.device.ipv4.addressstring | nullIPv4 address
ctx.device.ipv4.gatewaystring | nullIPv4 gateway
ctx.device.ipv4.interfacestring | nullNetwork interface
ctx.device.ipv6.addressstring | nullIPv6 address
ctx.device.ipv6.interfacestring | nullNetwork interface
ctx.device.dnsServersstring[]DNS server list

ctx.cron

string | undefined — Only available in schedule scripts. The cron expression.

ctx.widgetFamily

string | undefined — Only available in generic scripts. The widget size family.

Possible values: systemSmall, systemMedium, systemLarge, systemExtraLarge, accessoryCircular, accessoryRectangular, accessoryInline.

ctx.request

Object | undefined — Only available in request/response scripts.

Property/MethodTypeDescription
methodstringHTTP method
urlstringRequest URL
headersHeadersRequest headers
bodyReadableStream | nullRequest body stream
json()Promise<any>Parse as JSON
text()Promise<string>Parse as text
arrayBuffer()Promise<ArrayBuffer>Parse as ArrayBuffer
blob()Promise<Blob>Parse as Blob
formData()Promise<FormData>Parse as FormData

Note: The body can only be consumed once (consistent with Fetch API behavior).

ctx.response

Object | undefined — Only available in response scripts.

Property/MethodTypeDescription
statusnumberStatus code
headersHeadersResponse headers
bodyReadableStream | nullResponse body stream
json()Promise<any>Parse as JSON
text()Promise<string>Parse as text
arrayBuffer()Promise<ArrayBuffer>Parse as ArrayBuffer
blob()Promise<Blob>Parse as Blob
formData()Promise<FormData>Parse as FormData

Note: The body can only be consumed once (consistent with Fetch API behavior).

Headers Object

ctx.request.headers, ctx.response.headers, and ctx.http response headers are all Headers objects. They support case-insensitive property access and the following methods:

MethodReturnDescription
headers.get(name)string | nullGet value (multiple values joined with , )
headers.getAll(name)string[]Get all values (always returns array)
headers.has(name)booleanCheck existence
headers.set(name, value)voidSet (replaces existing)
headers.append(name, value)voidAppend value
headers.delete(name)voidDelete

All method name parameters are case-insensitive. Direct property access is also case-insensitive, returning string for single values and string[] for multiple values:

// These are equivalent
headers['Content-Type'] // 'application/json'
headers['content-type'] // 'application/json'

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

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

ctx.http

Send HTTP requests. All methods return Promise<Response>.

Methods

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?)

Parameters

  • urlstring, the request URL.
  • options — Optional object:
FieldTypeDescription
headersHeaders | Object<string, string | string[]>Request headers (multi-value headers as arrays)
bodystring | Uint8Array | Object | ReadableStreamRequest body (Object is auto-serialized to JSON)
timeoutnumberTimeout in milliseconds
policystringProxy policy
policyDescriptorstringPolicy descriptor
redirect'follow' | 'manual' | 'error'Redirect policy (default 'follow'); manual returns 3xx response, error throws on redirect
credentials'omit' | 'include'Whether to include cookies (default 'include')
insecureTlsbooleanAllow insecure TLS (default false)

Response Object

Property/MethodTypeDescription
statusnumberStatus code
headersHeadersResponse headers
bodyReadableStreamResponse body stream
json()Promise<any>Parse as JSON
text()Promise<string>Parse as text
blob()Promise<Blob>Parse as Blob
arrayBuffer()Promise<ArrayBuffer>Parse as ArrayBuffer
formData()Promise<FormData>Parse as FormData

Note: The body can only be consumed once (consistent with Fetch API behavior).

Example

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

ctx.storage

Persistent key-value storage.

MethodReturnDescription
ctx.storage.get(key)string | nullRead value
ctx.storage.set(key, value)voidWrite value (value is string)
ctx.storage.getJSON(key)any | nullRead and JSON parse
ctx.storage.setJSON(key, value)voidJSON serialize and write
ctx.storage.delete(key)voidDelete key

Example

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

// JSON convenience methods
ctx.storage.setJSON('config', { theme: 'dark', lang: 'zh' });
const config = ctx.storage.getJSON('config'); // { theme: 'dark', lang: 'zh' }

ctx.notify(options)

Send a notification.

FieldTypeDescription
titlestringTitle
subtitlestringSubtitle (optional)
bodystringContent (optional)
soundbooleanPlay alert sound (default true)
durationnumberDisplay duration in seconds (optional)
attachmentObjectNotification attachment (optional)
attachment.urlstringMedia URL, auto-downloaded as attachment (mutually exclusive with base64)
attachment.base64stringBase64-encoded media data (mutually exclusive with url)
attachment.mimeTypestringMIME type (optional, gif/png/jpg/pdf auto-detected)
actionObjectTap action (optional)
action.typestring"openUrl" or "clipboard"
action.urlstringURL to open when type is "openUrl"
action.textstringText to copy when type is "clipboard"

Example

// Basic notification
ctx.notify({ title: 'Done', body: 'Task completed' });

// With attachment and tap action
ctx.notify({
title: 'Screenshot saved',
body: 'Tap for details',
sound: true,
duration: 5,
attachment: {
url: 'https://example.com/image.png',
mimeType: 'image/png',
},
action: {
type: 'openUrl',
url: 'https://example.com/details',
},
});

// Base64 attachment + copy to clipboard
ctx.notify({
title: 'Verification code',
body: '1234',
attachment: {
base64: 'iVBORw0KGgo...',
mimeType: 'image/png',
},
action: {
type: 'clipboard',
text: '1234',
},
});

ctx.lookupIP(ip)

Look up IP address information.

  • ipstring, the IP address.
  • Returns Object | null:
PropertyTypeDescription
countrystringCountry/region code
asnnumberAS number
organizationstringOrganization name

Example

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

ctx.compress

Compression/decompression. Input and output are Uint8Array. All methods return Promise<Uint8Array | null>.

MethodDescription
ctx.compress.gzip(data)Gzip compress
ctx.compress.gunzip(data)Gzip decompress
ctx.compress.deflate(data)Deflate compress
ctx.compress.inflate(data)Deflate decompress
ctx.compress.brotli(data)Brotli compress
ctx.compress.unbrotli(data)Brotli decompress

ctx.respond(response)

In request scripts, return a response directly without sending the request to the upstream server.

  • response — Object:
FieldTypeDescription
statusnumberStatus code
headersHeaders | Object<string, string | string[]>Response headers (optional, multi-value as arrays)
bodystring | Uint8Array | Object | ReadableStreamResponse body (optional, Object is auto-serialized to JSON)
return ctx.respond({ status: 200, headers: { 'Content-Type': 'text/plain' }, body: 'blocked' });

ctx.abort()

Abort the current request or response. Used in request/response scripts.

return ctx.abort();

Return Values

The function's return value determines script behavior. Different script types return different structures.

Request Script

Executes before an HTTP request is sent. Can modify the request, return a response directly, or abort.

Return an object to modify the request. All fields are optional; omitted fields remain unchanged.

FieldTypeDescription
methodstringHTTP method
urlstringRequest URL
headersHeaders | Object<string, string | string[]>Request headers (multi-value as arrays)
bodystring | Uint8Array | Object | ReadableStreamRequest body (Object is auto-serialized to JSON)

You can also use ctx.respond() to return a response directly, ctx.abort() to abort, or return nothing to pass through.

// Modify request
return { url: 'https://...', headers: { ... }, body: '...' };

// Pass through body stream
return { url: 'https://...', body: ctx.request.body };

// Return response directly
return ctx.respond({ status: 200, headers: {}, body: 'blocked' });

// Abort request
return ctx.abort();

Response Script

Executes before an HTTP response is returned to the client. Can modify the response or abort.

Return an object to modify the response. All fields are optional; omitted fields remain unchanged.

FieldTypeDescription
statusnumberStatus code
headersHeaders | Object<string, string | string[]>Response headers (multi-value as arrays)
bodystring | Uint8Array | Object | ReadableStreamResponse body (Object is auto-serialized to JSON)

You can also use ctx.abort() to abort, or return nothing to pass through.

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

Generic Script

Return a Widget DSL JSON object. Egern renders it as an iOS widget. The root node must have type: "widget".

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

Schedule / Network Script

No return value needed.


Full Examples

Request — URL Rewrite

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

Response — Modify JSON Body

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

Request — Block Ads

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

Schedule — Scheduled Task

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 — Widget

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,
};
}