Files
WRNexusJS/packages/native/src/manifest.ts
T
Clintchiz 586a6db8ff
Quality / quality (ubuntu-latest) (push) Failing after 21s
Quality / quality (windows-latest) (push) Canceled after 0s
release: WRNexusJS 0.8.0
2026-08-02 23:18:51 +05:30

61 lines
2.2 KiB
TypeScript

import { registered, supports } from "./registry.ts";
import type { NativeTarget } from "./types.ts";
export type NativePermission =
"camera" | "geolocation" | "microphone" | "notifications" | "photos" | "storage" | (string & {});
export interface NativeCapabilityManifestEntry {
name: string;
description?: string;
permissions?: NativePermission[];
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: NativePermission): Promise<"granted" | "denied" | "prompt" | "unavailable">;
request?(name: NativePermission): Promise<"granted" | "denied">;
}
export class PermissionManager {
constructor(private readonly adapter: PermissionAdapter) {}
query(name: NativePermission) {
return this.adapter.query(name);
}
async ensure(name: NativePermission): 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;
}
}