chore: update version to 1.6.2

This commit is contained in:
Linus Rath
2026-05-06 20:07:36 +02:00
parent 91cf125a5d
commit 178922323d
30 changed files with 89 additions and 43 deletions
+1 -1
View File
@@ -103,7 +103,7 @@ describe('JMAPClient.sendEmail threading headers', () => {
const create = setCall[1].create as Record<string, Record<string, unknown>>;
const draft = Object.values(create)[0];
// Bare msg-ids per RFC 8621 angle brackets stripped.
// Bare msg-ids per RFC 8621 - angle brackets stripped.
expect(draft.inReplyTo).toEqual(['parent@example.com']);
expect(draft.references).toEqual(['root@example.com', 'parent@example.com']);
});
+1 -1
View File
@@ -162,7 +162,7 @@ export function resolveTrustedJmapUrl(
}
const matched = servers.find((s) => normalizeUrl(s.url) === target);
if (matched) return matched.url;
// No match caller decides whether to honor the request anyway (e.g. when
// No match - caller decides whether to honor the request anyway (e.g. when
// allowCustomJmapEndpoint is enabled).
return null;
}
+3 -3
View File
@@ -80,7 +80,7 @@ function resolveBundlePath(pluginDir: string, entrypoint: string): ResolvedBundl
/**
* Load and bundle a dev plugin's code. For `src/` sources this runs esbuild
* on every call so saves are reflected immediately. Errors are surfaced as
* a JS module that throws at activation time that way the dev sees the
* a JS module that throws at activation time - that way the dev sees the
* failure in the browser console instead of a silent 404.
*/
export async function readDevBundle(entry: DevPluginEntry): Promise<string> {
@@ -98,7 +98,7 @@ export async function readDevBundle(entry: DevPluginEntry): Promise<string> {
sourcemap: 'inline',
target: ['es2020'],
// React/ReactDOM are exposed on globalThis.__PLUGIN_EXTERNALS__ by the
// host, so we mark them external the bundle won't try to ship them.
// host, so we mark them external - the bundle won't try to ship them.
external: ['react', 'react-dom', 'react/jsx-runtime'],
});
const out = result.outputFiles?.[0]?.text;
@@ -143,7 +143,7 @@ async function loadDevPlugin(pluginDir: string): Promise<DevPluginEntry | null>
}
// Hash from the on-disk source so any edit propagates. For src/ sources
// we hash the source close enough for dev-time change detection (we
// we hash the source - close enough for dev-time change detection (we
// don't need to re-hash transitive imports).
let bundleHash: string;
try {
+1 -1
View File
@@ -7,7 +7,7 @@
* In-Reply-To = parent.Message-ID
* References = parent.References (if any) + parent.Message-ID
*
* Bare msg-ids only angle brackets are stripped because JMAP RFC 8621
* Bare msg-ids only - angle brackets are stripped because JMAP RFC 8621
* §4.1.2.3 stores Message-IDs without them.
*/
+1 -1
View File
@@ -304,7 +304,7 @@ function stripMessageIdBrackets(id: string): string {
// form: `Display Name <addr@example.com>`. Re-emitting that as the JMAP
// from.name field produces a doubled From header (`"Name <addr>" <addr>`)
// whose display-name is invalid per RFC 5322 §3.4 and gets rejected by the
// submission validator the email then sits forever in Drafts.
// submission validator - the email then sits forever in Drafts.
function sanitizeIdentityDisplayName(name: string | undefined | null): string {
if (!name) return '';
return name.replace(/\s*<[^>]*>\s*$/, '').trim();
+3 -3
View File
@@ -115,7 +115,7 @@ function createPluginLogger(pluginId: string) {
* declared `httpOrigins` patterns. Patterns are either a literal origin
* (`https://host[:port]`) or a wildcard subdomain form (`https://*.host`).
*
* Wildcards match exactly one subdomain layer above `host` e.g.
* Wildcards match exactly one subdomain layer above `host` - e.g.
* `https://*.example.com` matches `https://a.example.com` but NOT
* `https://example.com` and NOT `https://a.b.example.com`. This mirrors how
* the CSP frame-src handles wildcards and avoids accidentally widening
@@ -153,7 +153,7 @@ function originMatchesAllowlist(url: URL, allowlist: string[]): boolean {
export interface PluginFetchInit {
/** HTTP method. Defaults to GET. */
method?: string;
/** Request headers. Plain object only no Headers / cookies forwarded. */
/** Request headers. Plain object only - no Headers / cookies forwarded. */
headers?: Record<string, string>;
/** Body. Plain string, ArrayBuffer, Uint8Array, Blob, or FormData. */
body?: string | ArrayBuffer | ArrayBufferView | Blob | FormData | null;
@@ -210,7 +210,7 @@ export interface PluginAPI {
* Cross-origin fetch against an origin declared in the manifest's
* `httpOrigins` allowlist. Requires `http:fetch` permission.
*
* No webmail credentials are forwarded the plugin must supply its own
* No webmail credentials are forwarded - the plugin must supply its own
* `Authorization` (or other auth) header. Each call is gated on origin
* even when the URL came from plugin settings, so a user-pasted URL
* outside the allowlist is rejected at the boundary.
+1 -1
View File
@@ -1,4 +1,4 @@
// Projection helpers convert host-internal types into the read-only views
// Projection helpers - convert host-internal types into the read-only views
// that plugins consume. Keeping this in one place ensures every slot/hook
// hands plugins the same shape declared in plugin-types.ts.
+1 -1
View File
@@ -678,7 +678,7 @@ export interface SelectionContext {
export interface ConflictWarning {
/** Stable unique key per warning, used as React key */
key: string;
/** Short message e.g. "Conflicts with: Team Standup" */
/** Short message - e.g. "Conflicts with: Team Standup" */
message: string;
severity?: 'info' | 'warning' | 'error';
}
+1 -1
View File
@@ -19,7 +19,7 @@ export function isSupportedSubAddressDelimiter(value: string): value is SubAddre
}
// RFC 5321 atext "special" characters, minus alphanumerics and "@". A custom
// delimiter must be exactly one of these they're safe to embed in a local
// delimiter must be exactly one of these - they're safe to embed in a local
// part and unambiguously separate the user from the tag.
const VALID_DELIMITER_REGEX = /^[!#$%&'*+\-./=?^_`{|}~]$/;
+1 -1
View File
@@ -51,7 +51,7 @@ export async function fetchStatus(
if (!endpoint) return { ok: false, error: 'endpoint blank' };
if (!currentVersion) return { ok: false, error: 'current version blank' };
// Build the URL safely never inject the version as a raw path component.
// Build the URL safely - never inject the version as a raw path component.
let url: URL;
try {
url = new URL(endpoint);
+1 -1
View File
@@ -71,7 +71,7 @@ async function tick(): Promise<void> {
await scheduleNext(delay);
}
// Idempotent safe to call from instrumentation hot-reload in dev.
// Idempotent - safe to call from instrumentation hot-reload in dev.
export async function startScheduler(): Promise<void> {
if (disabledByEnv()) {
logger.info('version-check: scheduler not started (disabled by env)');
+1 -1
View File
@@ -25,7 +25,7 @@ const SUBSCRIPTION_REFRESH_THRESHOLD_DAYS = 7;
// Only `EmailDelivery` state-changes when new mail is actually delivered.
// `Email` fires for any mutation (sending, drafting, moving, marking read,
// deleting) and `Mailbox` fires for mailbox edits both produced spurious
// deleting) and `Mailbox` fires for mailbox edits - both produced spurious
// system notifications, so we keep them out of the push subscription.
// In-app sync uses a separate StateChange channel and is unaffected.
const PUSH_TYPES = ['EmailDelivery'] as const;