- Startseite
- Documentation
- Nativ
- Nativer Binding-Vertrag (TypeScript-Seite)
Nativer Binding-Vertrag (TypeScript-Seite)
Dieses Dokument definiert den TypeScript-seitigen Vertrag, der zwischen den Aufrufern von @f5-sales-demo/pi-natives und dem geladenen N-API-Addon steht.
Es konzentriert sich auf drei Aspekte:
- Vertragsform (
NativeBindings+ Modul-Augmentierung), - Wrapper-Verhalten (
src/<module>/index.ts), - Öffentliche Exportoberfläche (
src/index.ts).
Implementierungsdateien
Abschnitt betitelt „Implementierungsdateien“packages/natives/src/bindings.tspackages/natives/src/native.tspackages/natives/src/index.tspackages/natives/src/clipboard/types.tspackages/natives/src/clipboard/index.tspackages/natives/src/glob/types.tspackages/natives/src/glob/index.tspackages/natives/src/grep/types.tspackages/natives/src/grep/index.tspackages/natives/src/highlight/types.tspackages/natives/src/highlight/index.tspackages/natives/src/html/types.tspackages/natives/src/html/index.tspackages/natives/src/image/types.tspackages/natives/src/image/index.tspackages/natives/src/keys/types.tspackages/natives/src/keys/index.tspackages/natives/src/ps/types.tspackages/natives/src/ps/index.tspackages/natives/src/pty/types.tspackages/natives/src/pty/index.tspackages/natives/src/shell/types.tspackages/natives/src/shell/index.tspackages/natives/src/system-info/types.tspackages/natives/src/system-info/index.tspackages/natives/src/text/types.tspackages/natives/src/text/index.tspackages/natives/src/work/types.tspackages/natives/src/work/index.ts
Vertragsmodell
Abschnitt betitelt „Vertragsmodell“packages/natives/src/bindings.ts definiert den Basisvertrag:
NativeBindings(Basisinterface, enthält derzeitcancelWork(id: number): void)Cancellable(timeoutMs?: number,signal?: AbortSignal)TsFunc<T>Callback-Signatur, die von N-API-threadsicheren Callbacks verwendet wird
Jedes Modul fügt seine eigenen Felder durch Deklarationszusammenführung hinzu:
// packages/natives/src/<module>/types.tsdeclare module "../bindings" { interface NativeBindings { grep(options: GrepOptions, onMatch?: TsFunc<GrepMatch>): Promise<GrepResult>; }}Dies ergibt ein aggregiertes Binding-Interface ohne eine monolithische zentrale Typdatei.
Lebenszyklus der Deklarationszusammenführung und Zustandsübergänge
Abschnitt betitelt „Lebenszyklus der Deklarationszusammenführung und Zustandsübergänge“1) Typzusammenstellung zur Kompilierzeit
Abschnitt betitelt „1) Typzusammenstellung zur Kompilierzeit“bindings.tsstellt das Basis-SymbolNativeBindingsbereit.- Jede
src/<module>/types.tsaugmentiertNativeBindings. src/native.tsimportiert alle./<module>/types-Dateien für Seiteneffekte, damit der zusammengeführte Vertrag im Geltungsbereich ist, woNativeBindingsverwendet wird.
Zustandsübergang: Basisvertrag → Zusammengeführter Vertrag.
2) Laufzeit-Addon-Laden und Validierungsschranke
Abschnitt betitelt „2) Laufzeit-Addon-Laden und Validierungsschranke“src/native.tslädt Kandidaten-.node-Binärdateien.- Das geladene Objekt wird als
NativeBindingsbehandelt und sofort durchvalidateNative(...)geleitet. validateNativeüberprüft erforderliche Exportschlüssel mittelstypeof bindings[name] === "function".
Zustandsübergang: Nicht vertrauenswürdiges Addon-Objekt → Validiertes natives Binding-Objekt (oder harter Fehler).
3) Wrapper-Aufruf
Abschnitt betitelt „3) Wrapper-Aufruf“- Modul-Wrapper in
src/<module>/index.tsrufennative.<export>auf. - Wrapper passen Standardwerte und Callback-Signaturen an (
(err, value)zu Nur-Wert-Callback-Mustern in JS-APIs). src/index.tsre-exportiert Modul-Wrapper/Typen als öffentliche Paket-API.
Zustandsübergang: Validierte Roh-Bindings → Ergonomische öffentliche API.
Verantwortlichkeiten der Wrapper
Abschnitt betitelt „Verantwortlichkeiten der Wrapper“Wrapper sind bewusst dünn gehalten; sie reimplementieren keine native Logik.
Hauptverantwortlichkeiten:
- Argument-Normalisierung/Standardwerte
glob()löstoptions.pathzu einem absoluten Pfad auf und setzt Standardwerte fürhidden,gitignore,recursive.hasMatch()füllt Standard-Flags (ignoreCase,multiline) vor dem nativen Aufruf.
- Callback-Anpassung
grep(),glob(),executeShell()konvertierenTsFunc<T>(error, value) in einen Benutzer-Callback, der nur erfolgreiche Werte empfängt.
- Umgebungs- oder Richtlinienverhalten um native Aufrufe
- Der Clipboard-Wrapper fügt OSC52/Termux/Headless-Behandlung hinzu und behandelt das Kopieren als Best-Effort.
- Öffentliche Benennung und Re-Export-Kuratierung
searchContent()wird auf den nativen Exportsearchabgebildet.
Organisation der öffentlichen Exportoberfläche
Abschnitt betitelt „Organisation der öffentlichen Exportoberfläche“packages/natives/src/index.ts ist das kanonische öffentliche Barrel. Es gruppiert Exporte nach Fähigkeitsdomäne:
- Suche/Text:
grep,glob,text,highlight - Ausführung/Prozess/Terminal:
shell,pty,ps,keys - System/Medien/Konvertierung:
image,html,clipboard,system-info,work
Regel für Maintainer: Wenn ein Wrapper nicht aus src/index.ts re-exportiert wird, gehört er nicht zur beabsichtigten öffentlichen Paketoberfläche.
JS-API ↔ Native-Export-Zuordnung (repräsentativ)
Abschnitt betitelt „JS-API ↔ Native-Export-Zuordnung (repräsentativ)“Die Rust-Seite verwendet N-API-Exportnamen (typischerweise durch #[napi] snake_case → camelCase-Konvertierung, gelegentlich mit expliziten Aliasen), die mit diesen Binding-Schlüsseln übereinstimmen müssen.
| Kategorie | Öffentliche JS-API (Wrapper) | Nativer Binding-Schlüssel | Rückgabetyp | Async? |
|---|---|---|---|---|
| Grep | grep(options, onMatch?) | grep | Promise<GrepResult> | Ja |
| Grep | searchContent(content, options) | search | SearchResult | Nein |
| Grep | hasMatch(content, pattern, opts?) | hasMatch | boolean | Nein |
| Grep | fuzzyFind(options) | fuzzyFind | Promise<FuzzyFindResult> | Ja |
| Glob | glob(options, onMatch?) | glob | Promise<GlobResult> | Ja |
| Glob | invalidateFsScanCache(path?) | invalidateFsScanCache | void | Nein |
| Shell | executeShell(options, onChunk?) | executeShell | Promise<ShellExecuteResult> | Ja |
| Shell | Shell | Shell | Klassenkonstruktor | N/A |
| PTY | PtySession | PtySession | Klassenkonstruktor | N/A |
| Text | truncateToWidth(...) | truncateToWidth | string | Nein |
| Text | sliceWithWidth(...) | sliceWithWidth | SliceWithWidthResult | Nein |
| Text | visibleWidth(text) | visibleWidth | number | Nein |
| Highlight | highlightCode(code, lang, colors) | highlightCode | string | Nein |
| HTML | htmlToMarkdown(html, options?) | htmlToMarkdown | Promise<string> | Ja |
| System | getSystemInfo() | getSystemInfo | SystemInfo | Nein |
| Work | getWorkProfile(lastSeconds) | getWorkProfile | WorkProfile | Nein |
| Prozess | killTree(pid, signal) | killTree | number | Nein |
| Prozess | listDescendants(pid) | listDescendants | number[] | Nein |
| Clipboard | copyToClipboard(text) | copyToClipboard | Promise<void> (Best-Effort-Wrapper-Verhalten) | Ja |
| Clipboard | readImageFromClipboard() | readImageFromClipboard | Promise<ClipboardImage | null> | Ja |
| Keys | parseKey(data, kittyProtocolActive) | parseKey | string | null | Nein |
Unterschiede zwischen synchronem und asynchronem Vertrag
Abschnitt betitelt „Unterschiede zwischen synchronem und asynchronem Vertrag“Der Vertrag mischt synchrone und asynchrone APIs; Wrapper bewahren den nativen Aufrufstil, anstatt ein einzelnes Modell zu erzwingen:
- Promise-basierte asynchrone Exporte für I/O oder langlebige Arbeit (
grep,glob,htmlToMarkdown,executeShell, Clipboard, Bildoperationen). - Synchrone Exporte für deterministische In-Memory-Transformationen/Parser (
search,hasMatch, Highlighting, Textbreite/-Slicing, Schlüssel-Parsing, Prozessabfragen). - Konstruktor-Exporte für zustandsbehaftete Laufzeitobjekte (
Shell,PtySession,PhotonImage).
Implikation für Maintainer: Das Ändern von synchron ↔ asynchron für einen bestehenden Export ist eine breaking API- und Vertragsänderung über Wrapper und Aufrufer hinweg.
Objekt- und Enum-Typisierungsmuster
Abschnitt betitelt „Objekt- und Enum-Typisierungsmuster“Objektmuster (JS-Objekte im #[napi(object)]-Stil)
Abschnitt betitelt „Objektmuster (JS-Objekte im #[napi(object)]-Stil)“TS modelliert objektförmige native Werte als Interfaces, zum Beispiel:
GrepResult,SearchResult,GlobResultSystemInfo,WorkProfileClipboardImage,ParsedKittyResult
Dies sind strukturelle Verträge zur Kompilierzeit; die Korrektheit der Laufzeitform liegt in der Verantwortung der nativen Implementierung.
Enum-Muster
Abschnitt betitelt „Enum-Muster“Numerische native Enums werden als const enum-Werte in TS dargestellt:
FileType(1=file,2=dir,3=symlink)ImageFormat(0=PNG,1=JPEG,2=WEBP,3=GIF)SamplingFilter,Ellipsis,KeyEventType
Aufrufer sehen benannte Enum-Mitglieder; an der Binding-Grenze werden Zahlen übergeben.
Wie Abweichungen erkannt werden
Abschnitt betitelt „Wie Abweichungen erkannt werden“Die Erkennung von Abweichungen erfolgt auf zwei Ebenen:
-
Vertragsprüfungen durch TypeScript zur Kompilierzeit
- Wrapper rufen
native.<name>gegen das zusammengeführteNativeBindingsauf. - Fehlende/umbenannte Binding-Schlüssel brechen die TS-Typprüfung in Wrappern.
- Wrapper rufen
-
Laufzeitvalidierung in
validateNative- Nach dem Laden prüft
native.tsdie erforderlichen Exporte und wirft einen Fehler, wenn welche fehlen. - Die Fehlermeldung enthält die fehlenden Schlüssel und eine Rebuild-Anweisung.
- Nach dem Laden prüft
Dies fängt den häufigen Fall veralteter Binärdateien ab: Wrapper/Typ existiert, aber das geladene .node besitzt den Export nicht.
Fehlerverhalten und Einschränkungen
Abschnitt betitelt „Fehlerverhalten und Einschränkungen“Lade-/Validierungsfehler (harte Fehler)
Abschnitt betitelt „Lade-/Validierungsfehler (harte Fehler)“- Addon-Ladefehler oder nicht unterstützte Plattform lösen während der Modulinitialisierung in
native.tseine Exception aus. - Fehlende erforderliche Exporte lösen eine Exception aus, bevor Wrapper nutzbar sind.
Effekt: Das Paket schlägt sofort fehl, anstatt den Fehler bis zum ersten Aufruf aufzuschieben.
Verhaltensunterschiede auf Wrapper-Ebene
Abschnitt betitelt „Verhaltensunterschiede auf Wrapper-Ebene“- Einige Wrapper mildern Fehler bewusst ab (
copyToClipboardarbeitet nach dem Best-Effort-Prinzip und schluckt native Fehler). - Streaming-Callbacks ignorieren Callback-Fehler-Payloads und leiten nur erfolgreiche Wert-Events weiter.
Einschränkungen auf Typebene (Laufzeit strenger als TS)
Abschnitt betitelt „Einschränkungen auf Typebene (Laufzeit strenger als TS)“- Optionale TS-Felder garantieren keine semantische Gültigkeit; die native Schicht kann trotzdem fehlerhafte Werte ablehnen.
const enum-Typisierung verhindert nicht, dass zur Laufzeit numerische Werte außerhalb des gültigen Bereichs von untypisierten Aufrufern übergeben werden.validateNativeprüft nur die Anwesenheit und den Funktionscharakter der erforderlichen Exporte, nicht die tiefe Argument-/Rückgabe-Form-Kompatibilität.bindings.tsenthältcancelWork(id)im Basisinterface, aber die aktuelle Laufzeit-Validierungsliste erzwingt diesen Schlüssel nicht.
Maintainer-Checkliste für Binding-Änderungen
Abschnitt betitelt „Maintainer-Checkliste für Binding-Änderungen“Beim Hinzufügen/Ändern eines Exports sind alle folgenden Stellen zu aktualisieren:
src/<module>/types.ts(Augmentierung + Vertragstypen)src/<module>/index.ts(Wrapper-Verhalten)src/native.ts-Importe für die Modultypen (bei neuem Modul)validateNativePrüfungen der erforderlichen Exportesrc/index.tsöffentliche Re-Exporte
Das Auslassen eines Schrittes erzeugt entweder Kompilierzeit-Abweichungen oder Laufzeit-Ladefehler.