release: WRNexusJS 0.4.0

This commit is contained in:
2026-07-27 12:42:18 +05:30
parent 8b728a3e5d
commit 30e5721e84
250 changed files with 10065 additions and 3923 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/native",
"version": "0.3.6",
"version": "0.4.0",
"type": "module",
"main": "src/index.ts",
"exports": {
+11
View File
@@ -22,3 +22,14 @@ export { browserCapabilities } from "./browser.ts";
export { mobileCapabilities } from "./mobile.ts";
export const native = { isMobile, platform, register, registered, run, supports };
export {
defineNativeManifest,
inspectNativeCapabilities,
missingNativeCapabilities,
PermissionManager,
} from "./manifest.ts";
export type {
NativeCapabilityManifestEntry,
NativeCapabilityManifest,
PermissionAdapter,
} from "./manifest.ts";
+58
View File
@@ -0,0 +1,58 @@
import { registered, supports } from "./registry.ts";
import type { NativeTarget } from "./types.ts";
export interface NativeCapabilityManifestEntry {
name: string;
description?: string;
permissions?: string[];
targets?: NativeTarget[];
optional?: boolean;
}
export interface NativeCapabilityManifest {
name: string;
version?: string;
capabilities: NativeCapabilityManifestEntry[];
}
export function defineNativeManifest<T extends NativeCapabilityManifest>(manifest: T): T {
const names = new Set<string>();
for (const capability of manifest.capabilities) {
if (!/^[A-Za-z][A-Za-z0-9.-]*$/.test(capability.name))
throw new TypeError(`Invalid native capability: ${capability.name}`);
if (names.has(capability.name))
throw new Error(`Duplicate native capability: ${capability.name}`);
names.add(capability.name);
}
return manifest;
}
export function inspectNativeCapabilities(
target?: NativeTarget,
): Array<{ name: string; supported: boolean }> {
return registered().map((name) => ({ name, supported: supports(name, target) }));
}
export function missingNativeCapabilities(
manifest: NativeCapabilityManifest,
target?: NativeTarget,
): NativeCapabilityManifestEntry[] {
return manifest.capabilities.filter(
(capability) =>
!capability.optional &&
(!capability.targets || !target || capability.targets.includes(target)) &&
!supports(capability.name, target),
);
}
export interface PermissionAdapter {
query(name: string): Promise<"granted" | "denied" | "prompt" | "unavailable">;
request?(name: string): Promise<"granted" | "denied">;
}
export class PermissionManager {
constructor(private readonly adapter: PermissionAdapter) {}
query(name: string) {
return this.adapter.query(name);
}
async ensure(name: string): Promise<boolean> {
const state = await this.adapter.query(name);
if (state === "granted") return true;
if (state === "prompt" && this.adapter.request)
return (await this.adapter.request(name)) === "granted";
return false;
}
}